From 3da8f2eda156d9371be9caea2b83932683caaabf Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Mon, 29 Jan 2018 15:40:21 +0800 Subject: [PATCH 001/187] bugfix(touch): change the default value for sar_touch_enable register. Reported from github: https://github.com/espressif/esp-idf/issues/1236 All the touch channels are enabled by default in hardware. This would interfere other RTC function on Touch IOs. Disable touch function in touch_pad_init(). --- components/driver/rtc_module.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/driver/rtc_module.c b/components/driver/rtc_module.c index a04282b808..e7725f2793 100644 --- a/components/driver/rtc_module.c +++ b/components/driver/rtc_module.c @@ -783,6 +783,7 @@ esp_err_t touch_pad_init() return ESP_FAIL; } touch_pad_intr_disable(); + touch_pad_clear_group_mask(TOUCH_PAD_BIT_MASK_MAX, TOUCH_PAD_BIT_MASK_MAX, TOUCH_PAD_BIT_MASK_MAX); touch_pad_set_fsm_mode(TOUCH_FSM_MODE_DEFAULT); touch_pad_set_trigger_mode(TOUCH_TRIGGER_MODE_DEFAULT); touch_pad_set_trigger_source(TOUCH_TRIGGER_SOURCE_DEFAULT); From a239e1359a7d47fb0d4a08b91be7a5cd0a806c44 Mon Sep 17 00:00:00 2001 From: panfeng Date: Wed, 31 Jan 2018 19:32:53 +0800 Subject: [PATCH 002/187] bugfix(rmt): tx cmd without negative coding --- examples/peripherals/rmt_nec_tx_rx/main/infrared_nec_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/peripherals/rmt_nec_tx_rx/main/infrared_nec_main.c b/examples/peripherals/rmt_nec_tx_rx/main/infrared_nec_main.c index 6f58966878..ae20b070f2 100644 --- a/examples/peripherals/rmt_nec_tx_rx/main/infrared_nec_main.c +++ b/examples/peripherals/rmt_nec_tx_rx/main/infrared_nec_main.c @@ -338,7 +338,7 @@ static void rmt_example_nec_tx_task() int i, offset = 0; while(1) { //To build a series of waveforms. - i = nec_build_items(channel, item + offset, item_num - offset, ((~addr) << 8) | addr, cmd); + i = nec_build_items(channel, item + offset, item_num - offset, ((~addr) << 8) | addr, ((~cmd) << 8) | cmd); if(i < 0) { break; } From 973913b151fb91e823f82fbc66399c512aba9277 Mon Sep 17 00:00:00 2001 From: Xu Chun Guang Date: Tue, 13 Mar 2018 15:57:33 +0800 Subject: [PATCH 003/187] feat: Adjust log level about UART There are too many log when UART baud is around 2Mbps if not use hard flow control. --- components/driver/uart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/driver/uart.c b/components/driver/uart.c index 0b5638a90f..a2412067a7 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -837,7 +837,7 @@ static void uart_rx_intr_handler_default(void *param) p_uart->rx_buffered_len + pat_idx); } if ((p_uart->xQueueUart != NULL) && (pdFALSE == xQueueSendFromISR(p_uart->xQueueUart, (void * )&uart_event, &HPTaskAwoken))) { - ESP_EARLY_LOGW(UART_TAG, "UART event queue full"); + ESP_EARLY_LOGV(UART_TAG, "UART event queue full"); } } uart_event.type = UART_BUFFER_FULL; @@ -923,7 +923,7 @@ static void uart_rx_intr_handler_default(void *param) if(uart_event.type != UART_EVENT_MAX && p_uart->xQueueUart) { if (pdFALSE == xQueueSendFromISR(p_uart->xQueueUart, (void * )&uart_event, &HPTaskAwoken)) { - ESP_EARLY_LOGW(UART_TAG, "UART event queue full"); + ESP_EARLY_LOGV(UART_TAG, "UART event queue full"); } if(HPTaskAwoken == pdTRUE) { portYIELD_FROM_ISR() ; From 8fb9bfef7940cf10d37f0c5f3c19ba4796ce32fd Mon Sep 17 00:00:00 2001 From: kooho <2229179028@qq.com> Date: Tue, 20 Mar 2018 21:28:34 +0800 Subject: [PATCH 004/187] example(ble): Update ble a2d_sink example --- examples/bluetooth/a2dp_sink/main/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/bluetooth/a2dp_sink/main/main.c b/examples/bluetooth/a2dp_sink/main/main.c index 787dd45f97..6fc554fa43 100644 --- a/examples/bluetooth/a2dp_sink/main/main.c +++ b/examples/bluetooth/a2dp_sink/main/main.c @@ -54,14 +54,14 @@ void app_main() i2s_config_t i2s_config = { #ifdef CONFIG_A2DP_SINK_OUTPUT_INTERNAL_DAC - .mode = I2S_MODE_DAC_BUILT_IN, + .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN, #else .mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX #endif .sample_rate = 44100, .bits_per_sample = 16, .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels - .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB, + .communication_format = I2S_COMM_FORMAT_I2S_MSB, .dma_buf_count = 6, .dma_buf_len = 60, // .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 //Interrupt level 1 @@ -70,6 +70,7 @@ void app_main() i2s_driver_install(0, &i2s_config, 0, NULL); #ifdef CONFIG_A2DP_SINK_OUTPUT_INTERNAL_DAC + i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN); i2s_set_pin(0, NULL); #else i2s_pin_config_t pin_config = { From b1dcb52fec4d427cc831240d675e6804d9aebc6f Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Fri, 20 Apr 2018 16:59:25 +0800 Subject: [PATCH 005/187] feature(psram): configure flash and psram speed during runtime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Bootloader reads SPI configuration from bin header, so that the burning configuration can be different with compiling configuration. 2. Psram mode init will overwrite original flash speed mode, so that users can change psram and flash speed after OTA.
3. Flash read mode(QIO/DIO…) will not be changed in app bin. It is decided by bootloader, OTA can not change this mode. 4. Add read flash ID function, and save flash ID in g_rom_flashchip 5. Set drive ability for all related GPIOs 6. Check raise VDDSDIO voltage in 80Mhz mode 7. Add check flash ID and update settings in bootloader 8. Read flash ID once and keep in global variable 9. Read flash image header once and reuse the result Tested cases: 1. Test new and old version of bootloader boot Flash 20M —> app Flash 80M + Psram 80M boot Flash 40M —> app Flash 80M + Psram 80M boot Flash 80M —> app Flash 80M + Psram 80M boot Flash 20M —> app Flash 80M + Psram 40M boot Flash 40M —> app Flash 80M + Psram 40M boot Flash 80M —> app Flash 80M + Psram 40M boot Flash 20M —> app Flash 40M + Psram 40M boot Flash 40M —> app Flash 40M + Psram 40M boot Flash 80M —> app Flash 40M + Psram 40M
2. Working after esp_restart reboot. --- .../include_priv/flash_qio_mode.h | 8 ++ .../bootloader_support/src/bootloader_init.c | 89 +++++++++++++------ .../bootloader_support/src/flash_qio_mode.c | 24 +++-- components/esp32/include/rom/spi_flash.h | 2 + components/esp32/spiram_psram.c | 79 ++++++++++++---- 5 files changed, 148 insertions(+), 54 deletions(-) diff --git a/components/bootloader_support/include_priv/flash_qio_mode.h b/components/bootloader_support/include_priv/flash_qio_mode.h index 9efa1313e2..98e2fd22a1 100644 --- a/components/bootloader_support/include_priv/flash_qio_mode.h +++ b/components/bootloader_support/include_priv/flash_qio_mode.h @@ -24,6 +24,14 @@ extern "C" { */ void bootloader_enable_qio_mode(void); +/** + * @brief Read flash ID by sending 0x9F command + * @return flash raw ID + * mfg_id = (ID >> 16) & 0xFF; + flash_id = ID & 0xffff; + */ +uint32_t bootloader_read_flash_id(); + #ifdef __cplusplus } #endif diff --git a/components/bootloader_support/src/bootloader_init.c b/components/bootloader_support/src/bootloader_init.c index bed0223971..5a1ecd6ab9 100644 --- a/components/bootloader_support/src/bootloader_init.c +++ b/components/bootloader_support/src/bootloader_init.c @@ -63,7 +63,7 @@ static esp_err_t bootloader_main(); static void print_flash_info(const esp_image_header_t* pfhdr); static void update_flash_config(const esp_image_header_t* pfhdr); static void vddsdio_configure(); -static void flash_gpio_configure(); +static void flash_gpio_configure(const esp_image_header_t* pfhdr); static void uart_console_configure(void); static void wdt_reset_check(void); @@ -118,7 +118,14 @@ esp_err_t bootloader_init() static esp_err_t bootloader_main() { vddsdio_configure(); - flash_gpio_configure(); + /* Read and keep flash ID, for further use. */ + g_rom_flashchip.device_id = bootloader_read_flash_id(); + esp_image_header_t fhdr; + if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &fhdr, sizeof(esp_image_header_t), true) != ESP_OK) { + ESP_LOGE(TAG, "failed to load bootloader header!"); + return ESP_FAIL; + } + flash_gpio_configure(&fhdr); #if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ == 240) //Check if ESP32 is rated for a CPU frequency of 160MHz only if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_RATED) && @@ -132,8 +139,6 @@ static esp_err_t bootloader_main() wdt_reset_check(); ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER); - esp_image_header_t fhdr; - ESP_LOGI(TAG, "compile time " __TIME__ ); ets_set_appcpu_boot_addr(0); @@ -158,11 +163,6 @@ static esp_err_t bootloader_main() bootloader_enable_qio_mode(); #endif - if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &fhdr, sizeof(esp_image_header_t), true) != ESP_OK) { - ESP_LOGE(TAG, "failed to load bootloader header!"); - return ESP_FAIL; - } - print_flash_info(&fhdr); update_flash_config(&fhdr); @@ -295,31 +295,49 @@ static void vddsdio_configure() #define FLASH_SPIHD_IO 9 #define FLASH_IO_MATRIX_DUMMY_40M 1 #define FLASH_IO_MATRIX_DUMMY_80M 2 -static void IRAM_ATTR flash_gpio_configure() +#define FLASH_IO_DRIVE_GD_WITH_1V8PSRAM 3 + +/* + * Bootloader reads SPI configuration from bin header, so that + * the burning configuration can be different with compiling configuration. + */ +static void IRAM_ATTR flash_gpio_configure(const esp_image_header_t* pfhdr) { int spi_cache_dummy = 0; int drv = 2; -#if CONFIG_FLASHMODE_QIO - spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN; //qio 3 -#elif CONFIG_FLASHMODE_QOUT - spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; //qout 7 -#elif CONFIG_FLASHMODE_DIO - spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //dio 3 -#elif CONFIG_FLASHMODE_DOUT - spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; //dout 7 -#endif + switch (pfhdr->spi_mode) { + case ESP_IMAGE_SPI_MODE_QIO: + spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; + break; + case ESP_IMAGE_SPI_MODE_DIO: + spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //qio 3 + break; + case ESP_IMAGE_SPI_MODE_QOUT: + case ESP_IMAGE_SPI_MODE_DOUT: + default: + spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; + break; + } + /* dummy_len_plus values defined in ROM for SPI flash configuration */ extern uint8_t g_rom_spiflash_dummy_len_plus[]; -#if CONFIG_ESPTOOLPY_FLASHFREQ_40M - g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M; - g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M; - SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY -#elif CONFIG_ESPTOOLPY_FLASHFREQ_80M - g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M; - g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M; - SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY - drv = 3; -#endif + switch (pfhdr->spi_speed) { + case ESP_IMAGE_SPI_SPEED_80M: + g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M; + g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M; + SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M, + SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + drv = 3; + break; + case ESP_IMAGE_SPI_SPEED_40M: + g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M; + g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M; + SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M, + SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + break; + default: + break; + } uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG); uint32_t pkg_ver = chip_ver & 0x7; @@ -361,6 +379,19 @@ static void IRAM_ATTR flash_gpio_configure() // set drive ability for clock PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK); SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S); + + #if CONFIG_SPIRAM_TYPE_ESPPSRAM32 + uint32_t flash_id = g_rom_flashchip.device_id; + if (flash_id == FLASH_ID_GD25LQ32C) { + // Set drive ability for 1.8v flash in 80Mhz. + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA0_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA1_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA2_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA3_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CMD_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S); + } + #endif } } } diff --git a/components/bootloader_support/src/flash_qio_mode.c b/components/bootloader_support/src/flash_qio_mode.c index 001b76f41d..e01ad6a1ed 100644 --- a/components/bootloader_support/src/flash_qio_mode.c +++ b/components/bootloader_support/src/flash_qio_mode.c @@ -114,6 +114,19 @@ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8 /* dummy_len_plus values defined in ROM for SPI flash configuration */ extern uint8_t g_rom_spiflash_dummy_len_plus[]; +uint32_t bootloader_read_flash_id() +{ + uint32_t old_ctrl_reg = SPIFLASH.ctrl.val; + SPIFLASH.ctrl.val = SPI_WP_REG; // keep WP high while idle, otherwise leave DIO mode + SPIFLASH.user.usr_dummy = 0; + SPIFLASH.user.usr_addr = 0; + SPIFLASH.user.usr_command = 1; + SPIFLASH.user2.usr_command_bitlen = 7; + uint32_t id = execute_flash_command(CMD_RDID, 0, 0, 24); + SPIFLASH.ctrl.val = old_ctrl_reg; + id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00); + return id; +} void bootloader_enable_qio_mode(void) { @@ -129,17 +142,12 @@ void bootloader_enable_qio_mode(void) /* Set up some of the SPIFLASH user/ctrl variables which don't change while we're probing using execute_flash_command() */ old_ctrl_reg = SPIFLASH.ctrl.val; - SPIFLASH.ctrl.val = SPI_WP_REG; // keep WP high while idle, otherwise leave DIO mode - SPIFLASH.user.usr_dummy = 0; - SPIFLASH.user.usr_addr = 0; - SPIFLASH.user.usr_command = 1; - SPIFLASH.user2.usr_command_bitlen = 7; - raw_flash_id = execute_flash_command(CMD_RDID, 0, 0, 24); + raw_flash_id = g_rom_flashchip.device_id; ESP_LOGD(TAG, "Raw SPI flash chip id 0x%x", raw_flash_id); - mfg_id = raw_flash_id & 0xFF; - flash_id = (raw_flash_id >> 16) | (raw_flash_id & 0xFF00); + mfg_id = (raw_flash_id >> 16) & 0xFF; + flash_id = raw_flash_id & 0xFFFF; ESP_LOGD(TAG, "Manufacturer ID 0x%02x chip ID 0x%04x", mfg_id, flash_id); for (i = 0; i < NUM_CHIPS-1; i++) { diff --git a/components/esp32/include/rom/spi_flash.h b/components/esp32/include/rom/spi_flash.h index 35d010d797..cc9856f455 100644 --- a/components/esp32/include/rom/spi_flash.h +++ b/components/esp32/include/rom/spi_flash.h @@ -117,6 +117,8 @@ extern "C" { #define ESP_ROM_SPIFLASH_WR_PROTECT (ESP_ROM_SPIFLASH_BP0|ESP_ROM_SPIFLASH_BP1|ESP_ROM_SPIFLASH_BP2) #define ESP_ROM_SPIFLASH_QE BIT9 +#define FLASH_ID_GD25LQ32C 0xC86016 + typedef enum { ESP_ROM_SPIFLASH_QIO_MODE = 0, ESP_ROM_SPIFLASH_QOUT_MODE, diff --git a/components/esp32/spiram_psram.c b/components/esp32/spiram_psram.c index 39bb0a3881..279de8d2f7 100644 --- a/components/esp32/spiram_psram.c +++ b/components/esp32/spiram_psram.c @@ -37,6 +37,7 @@ #include "driver/periph_ctrl.h" #if CONFIG_SPIRAM_SUPPORT +#include "soc/rtc.h" //Commands for PSRAM chip #define PSRAM_READ 0x03 @@ -79,15 +80,10 @@ #define PSRAM_IO_MATRIX_DUMMY_40M 1 #define PSRAM_IO_MATRIX_DUMMY_80M 2 -#if CONFIG_FLASHMODE_QIO -#define SPI_CACHE_DUMMY SPI0_R_QIO_DUMMY_CYCLELEN //qio 3 -#elif CONFIG_FLASHMODE_QOUT -#define SPI_CACHE_DUMMY SPI0_R_FAST_DUMMY_CYCLELEN //qout 7 -#elif CONFIG_FLASHMODE_DIO -#define SPI_CACHE_DUMMY SPI0_R_DIO_DUMMY_CYCLELEN //dio 3 -#elif CONFIG_FLASHMODE_DOUT -#define SPI_CACHE_DUMMY SPI0_R_FAST_DUMMY_CYCLELEN //dout 7 -#endif +#define _SPI_CACHE_PORT 0 +#define _SPI_FLASH_PORT 1 +#define _SPI_80M_CLK_DIV 1 +#define _SPI_40M_CLK_DIV 2 static const char* TAG = "psram"; typedef enum { @@ -101,9 +97,7 @@ static psram_cache_mode_t s_psram_mode = PSRAM_CACHE_MAX; /* dummy_len_plus values defined in ROM for SPI flash configuration */ extern uint8_t g_rom_spiflash_dummy_len_plus[]; - static int extra_dummy = 0; - typedef enum { PSRAM_CMD_QPI, PSRAM_CMD_SPI, @@ -421,8 +415,23 @@ void IRAM_ATTR psram_spi_init(psram_spi_num_t spi_num, psram_cache_mode_t mode) memset((void*)SPI_W0_REG(spi_num), 0, 16 * 4); } +/* + * Psram mode init will overwrite original flash speed mode, so that it is possible to change psram and flash speed after OTA. + * Flash read mode(QIO/QOUT/DIO/DOUT) will not be changed in app bin. It is decided by bootloader, OTA can not change this mode. + */ static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode) { + int spi_cache_dummy = 0; + uint32_t rd_mode_reg = READ_PERI_REG(SPI_CTRL_REG(0)); + if (rd_mode_reg & (SPI_FREAD_QIO_M | SPI_FREAD_DIO_M)) { + spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN; + } else if (rd_mode_reg & (SPI_FREAD_QUAD_M | SPI_FREAD_DUAL_M)) { + spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; + } else { + spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; + } + // In bootloader, all the signals are already configured, + // We keep the following code in case the bootloader is some older version. gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0); gpio_matrix_out(PSRAM_SPIQ_IO, SPIQ_OUT_IDX, 0, 0); gpio_matrix_in(PSRAM_SPIQ_IO, SPIQ_IN_IDX, 0); @@ -436,24 +445,33 @@ static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode) switch (mode) { case PSRAM_CACHE_F80M_S40M: extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M; - g_rom_spiflash_dummy_len_plus[1] = PSRAM_IO_MATRIX_DUMMY_40M; - SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, SPI_CACHE_DUMMY + PSRAM_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + g_rom_spiflash_dummy_len_plus[_SPI_CACHE_PORT] = PSRAM_IO_MATRIX_DUMMY_80M; + g_rom_spiflash_dummy_len_plus[_SPI_FLASH_PORT] = PSRAM_IO_MATRIX_DUMMY_40M; + SET_PERI_REG_BITS(SPI_USER1_REG(_SPI_CACHE_PORT), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + PSRAM_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_CACHE_PORT); + esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_FLASH_PORT); //set drive ability for clock SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S); SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV, 2, FUN_DRV_S); break; case PSRAM_CACHE_F80M_S80M: extra_dummy = PSRAM_IO_MATRIX_DUMMY_80M; - g_rom_spiflash_dummy_len_plus[1] = PSRAM_IO_MATRIX_DUMMY_80M; - SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, SPI_CACHE_DUMMY + PSRAM_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + g_rom_spiflash_dummy_len_plus[_SPI_CACHE_PORT] = PSRAM_IO_MATRIX_DUMMY_80M; + g_rom_spiflash_dummy_len_plus[_SPI_FLASH_PORT] = PSRAM_IO_MATRIX_DUMMY_80M; + SET_PERI_REG_BITS(SPI_USER1_REG(_SPI_CACHE_PORT), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + PSRAM_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_CACHE_PORT); + esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_FLASH_PORT); //set drive ability for clock SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S); SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV, 3, FUN_DRV_S); break; case PSRAM_CACHE_F40M_S40M: extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M; - g_rom_spiflash_dummy_len_plus[1] = PSRAM_IO_MATRIX_DUMMY_40M; - SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, SPI_CACHE_DUMMY + PSRAM_IO_MATRIX_DUMMY_40M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + g_rom_spiflash_dummy_len_plus[_SPI_CACHE_PORT] = PSRAM_IO_MATRIX_DUMMY_40M; + g_rom_spiflash_dummy_len_plus[_SPI_FLASH_PORT] = PSRAM_IO_MATRIX_DUMMY_40M; + SET_PERI_REG_BITS(SPI_USER1_REG(_SPI_CACHE_PORT), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + PSRAM_IO_MATRIX_DUMMY_40M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_CACHE_PORT); + esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_FLASH_PORT); //set drive ability for clock SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 2, FUN_DRV_S); SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV, 2, FUN_DRV_S); @@ -549,11 +567,38 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad gpio_matrix_out(PSRAM_CLK_IO, SIG_IN_FUNC225_IDX, 0, 0); break; } + #if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V + // For flash 80Mhz, we must update ldo voltage in case older version of bootloader didn't do this. + rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config(); + if (cfg.enable == 1 && cfg.tieh == 0) { // VDDSDIO regulator is enabled @ 1.8V + cfg.drefh = 3; + cfg.drefm = 3; + cfg.drefl = 3; + cfg.force = 1; + rtc_vddsdio_set_config(cfg); + ets_delay_us(10); // wait for regulator to become stable + } + #endif CLEAR_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_CS_SETUP_M); psram_gpio_config(mode); WRITE_PERI_REG(GPIO_ENABLE_W1TS_REG, BIT(PSRAM_CS_IO)| BIT(PSRAM_CLK_IO)); PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CS_IO], PIN_FUNC_GPIO); PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], PIN_FUNC_GPIO); + + uint32_t flash_id = g_rom_flashchip.device_id; + if (flash_id == FLASH_ID_GD25LQ32C) { + #if CONFIG_SPIRAM_TYPE_ESPPSRAM32 + // Set drive ability for 1.8v flash in 80Mhz. + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA0_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA1_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA2_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA3_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CMD_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CS_IO], FUN_DRV, 3, FUN_DRV_S); + SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV, 3, FUN_DRV_S); + #endif + } uint32_t id; psram_read_id(&id); if (((id >> PSRAM_MFG_ID_S) & PSRAM_MFG_ID_M) != PSRAM_MFG_ID_V) { From aa357a32bc4aba4eb77d3d1c7ea3108b1f618731 Mon Sep 17 00:00:00 2001 From: Amit Sheth Date: Thu, 19 Apr 2018 05:48:05 +0530 Subject: [PATCH 006/187] nvs_flash: Add binary creation support for NVS partition. Ideally suited for generating a binary externally, containing key-value pairs specific to device manufacturers. Utility allows creation of a binary, compatible with NVS structure, which can be separately flashed onto a new partition. This helps device manufacturers set different values for different devices, e.g. serial numbers, but using a single firmaware image. --- .../nvs_partition_generator/README.rst | 60 +++ .../nvs_partition_gen.py | 361 ++++++++++++++++++ .../nvs_partition_generator/sample.csv | 12 + .../testdata/sample.bin | 1 + .../testdata/sample.hex | 1 + .../testdata/sample.txt | 1 + .../test_nvs_host/spi_flash_emulation.h | 8 + .../nvs_flash/test_nvs_host/test_nvs.cpp | 49 +++ docs/en/api-reference/storage/index.rst | 1 + docs/en/api-reference/storage/nvs_flash.rst | 5 + .../storage/nvs_partition_gen.rst | 1 + .../storage/nvs_partition_gen.rst | 1 + 12 files changed, 501 insertions(+) create mode 100644 components/nvs_flash/nvs_partition_generator/README.rst create mode 100644 components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py create mode 100644 components/nvs_flash/nvs_partition_generator/sample.csv create mode 100644 components/nvs_flash/nvs_partition_generator/testdata/sample.bin create mode 100644 components/nvs_flash/nvs_partition_generator/testdata/sample.hex create mode 100644 components/nvs_flash/nvs_partition_generator/testdata/sample.txt create mode 100644 docs/en/api-reference/storage/nvs_partition_gen.rst create mode 100644 docs/zh_CN/api-reference/storage/nvs_partition_gen.rst diff --git a/components/nvs_flash/nvs_partition_generator/README.rst b/components/nvs_flash/nvs_partition_generator/README.rst new file mode 100644 index 0000000000..5b62ebc394 --- /dev/null +++ b/components/nvs_flash/nvs_partition_generator/README.rst @@ -0,0 +1,60 @@ +NVS Partition Generator Utility +=============================== + +Introduction +------------ + +:component_file:`nvs_flash/nvs_partition_generator/nvs_partition_gen.py` utility is designed to help create a binary file, compatible with NVS architecture defined in :doc:`Non-Volatile Storage `, based on user provided key-value pairs in a CSV file. +Utility is ideally suited for generating a binary blob, containing data specific to ODM/OEM, which can be flashed externally at the time of device manufacturing. This helps manufacturers set unique value for various parameters for each device, e.g. serial number, while using same application firmaware for all devices. + +CSV file format +--------------- + +Each row of the .csv file should have 4 parameters, separated by comma. Below is the description of each of these parameters: + +Key + Key of the data. Data can later be accessed from an application via this key. + +Type + Supported values are ``file``, ``data`` and ``namespace``. + +Encoding + Supported values are: ``u8``, ``i8``, ``u16``, ``u32``, ``i32``, ``string``, ``hex2bin`` and ``binary``. This specifies how actual data values are encoded in the resultant binary file. Difference between ``string`` and ``binary`` encoding is that ``string`` data is terminated with a NULL character, whereas ``binary`` data is not. + + .. note:: For ``file`` type, only ``hex2bin``, ``string`` and ``binary`` is supported as of now. + +Value + Data value. + +.. note:: Encoding and Value cells for ``namespace`` field type should be empty. Encoding and Value of ``namespace`` is fixed and isn't configurable. Any value in these cells are ignored. + +.. note:: First row of the CSV file should always be column header and isn't configurable. + +Below is an example dump of such CSV file:: + + key,type,encoding,value <-- column header + namespace_name,namespace,, <-- First entry should be of type "namespace" + key1,data,u8,1 + key2,file,string,/path/to/file + +.. note:: Make sure there are no spaces before and after ',' in CSV file. + +NVS Entry and Namespace association +----------------------------------- + +When a new namespace entry is encountered in the CSV file, each follow-up entries will be part of that namespace, until next namespace entry is found, in which case all the follow-up entries will be part of the new namespace. + +.. note:: First entry in a CSV file should always be ``namespace`` entry. + +Running the utility +------------------- + +A sample CSV file provided with the utility. You can run the utility using below command:: + + python nvs_partition_generator.py sample.csv sample.bin + +Caveats +------- +- Utility doesn't check for duplicate keys and will write data pertaining to both keys. User needs to make sure keys are distinct. +- Once a new page is created, no data will be written in the space left in previous page. Fields in the CSV file need to be ordered in such a way so as to optimize memory. +- 64-bit datatype is not yet supported. diff --git a/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py b/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py new file mode 100644 index 0000000000..ecbe9b5db0 --- /dev/null +++ b/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py @@ -0,0 +1,361 @@ +#!/usr/bin/env python +# +# esp-idf NVS partition generation tool. Tool helps in generating NVS-compatible +# partition binary, with key-value pair entries provided via a CSV file. +# +# Copyright 2018 Espressif Systems (Shanghai) PTE LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import sys +import argparse +import binascii +import getopt +import struct +import os +import array +import csv +import zlib +from os import path + +""" Class for standard NVS page structure """ +class Page(object): + PAGE_PARAMS = { + "max_size": 4096, + "max_blob_size": 1984, + "max_entries": 126 + } + + # Item type codes + U8 = 0x01 + I8 = 0x11 + U16 = 0x02 + I16 = 0x12 + U32 = 0x04 + I32 = 0x14 + SZ = 0x21 + BLOB = 0x41 + + # Few Page constants + HEADER_SIZE = 32 + BITMAPARRAY_OFFSET = 32 + BITMAPARRAY_SIZE_IN_BYTES = 32 + FIRST_ENTRY_OFFSET = 64 + SINGLE_ENTRY_SIZE = 32 + + def __init__(self, page_num): + self.entry_num = 0 + self.bitmap_array = array.array('B') + self.page_buf = bytearray(b'\xff')*Page.PAGE_PARAMS["max_size"] + self.bitmap_array = self.create_bitmap_array() + self.set_header(page_num) + + def set_header(self, page_num): + # set page state to active + page_header= bytearray(b'\xff')*32 + page_state_active_seq = 0xFFFFFFFE + page_header[0:4] = struct.pack(' Page.PAGE_PARAMS["max_blob_size"]: + raise InputError("%s: Size exceeds max allowed length." % key) + + # Calculate no. of entries data will require + rounded_size = (datalen + 31) & ~31 + data_entry_count = rounded_size / 32 + total_entry_count = data_entry_count + 1 # +1 for the entry header + + # Check if page is already full and new page is needed to be created right away + if (self.entry_num + total_entry_count) >= Page.PAGE_PARAMS["max_entries"]: + raise PageFullError() + + # Entry header + entry_struct = bytearray('\xff')*32 + entry_struct[0] = ns_index # namespace index + entry_struct[2] = data_entry_count + 1 # Span + + # set key + key_array = bytearray('\x00')*16 + entry_struct[8:24] = key_array + entry_struct[8:8 + len(key)] = key + + # set Type + if encoding == "string": + entry_struct[1] = Page.SZ + elif encoding == "hex2bin" or encoding == "binary": + entry_struct[1] = Page.BLOB + + # compute CRC of data + entry_struct[24:26] = struct.pack('= Page.PAGE_PARAMS["max_entries"]: + raise PageFullError() + + entry_struct = bytearray('\xff')*32 + entry_struct[0] = ns_index # namespace index + entry_struct[2] = 0x01 # Span + + # write key + key_array = bytearray('\x00')*16 + entry_struct[8:24] = key_array + entry_struct[8:8 + len(key)] = key + + if encoding == "u8": + entry_struct[1] = Page.U8 + entry_struct[24] = struct.pack(' #include +#include +#include #define TEST_ESP_ERR(rc, res) CHECK((rc) == (res)) #define TEST_ESP_OK(rc) CHECK((rc) == ESP_OK) @@ -1452,6 +1454,53 @@ TEST_CASE("Recovery from power-off when the entry being erased is not on active /* Add new tests above */ /* This test has to be the final one */ +TEST_CASE("check partition generation utility", "[nvs_part_gen]") +{ + int childpid = fork(); + if (childpid == 0) { + exit(execlp("python", "python", + "../nvs_partition_generator/nvs_partition_gen.py", + "../nvs_partition_generator/sample.csv", + "../nvs_partition_generator/partition.bin", NULL)); + } else { + CHECK(childpid > 0); + int status; + waitpid(childpid, &status, 0); + CHECK(WEXITSTATUS(status) != -1); + } +} + +TEST_CASE("read data from partition generated via partition generation utility", "[nvs_part_gen]") +{ + SpiFlashEmulator emu("../nvs_partition_generator/partition.bin"); + nvs_handle handle; + TEST_ESP_OK( nvs_flash_init_custom("test", 0, 2) ); + TEST_ESP_OK( nvs_open_from_partition("test", "dummyNamespace", NVS_READONLY, &handle)); + uint8_t u8v; + TEST_ESP_OK( nvs_get_u8(handle, "dummyU8Key", &u8v)); + CHECK(u8v == 127); + int8_t i8v; + TEST_ESP_OK( nvs_get_i8(handle, "dummyI8Key", &i8v)); + CHECK(i8v == -128); + uint16_t u16v; + TEST_ESP_OK( nvs_get_u16(handle, "dummyU16Key", &u16v)); + CHECK(u16v == 32768); + uint32_t u32v; + TEST_ESP_OK( nvs_get_u32(handle, "dummyU32Key", &u32v)); + CHECK(u32v == 4294967295); + int32_t i32v; + TEST_ESP_OK( nvs_get_i32(handle, "dummyI32Key", &i32v)); + CHECK(i32v == -2147483648); + char buf[64] = {0}; + size_t buflen = 64; + TEST_ESP_OK( nvs_get_str(handle, "dummyStringKey", buf, &buflen)); + CHECK(strncmp(buf, "0A:0B:0C:0D:0E:0F", buflen) == 0); + buflen = 64; + uint8_t hexdata[] = {0x01, 0x02, 0x03, 0xab, 0xcd, 0xef}; + TEST_ESP_OK( nvs_get_blob(handle, "dummyHex2BinKey", buf, &buflen)); + CHECK(memcmp(buf, hexdata, buflen) == 0); +} + TEST_CASE("dump all performance data", "[nvs]") { std::cout << "====================" << std::endl << "Dumping benchmarks" << std::endl; diff --git a/docs/en/api-reference/storage/index.rst b/docs/en/api-reference/storage/index.rst index a8cefae6f4..2a8074478c 100644 --- a/docs/en/api-reference/storage/index.rst +++ b/docs/en/api-reference/storage/index.rst @@ -7,6 +7,7 @@ Storage API SPI Flash and Partition APIs SD/SDIO/MMC Driver Non-Volatile Storage + NVS Partition Generation Utility Virtual Filesystem FAT Filesystem Wear Levelling diff --git a/docs/en/api-reference/storage/nvs_flash.rst b/docs/en/api-reference/storage/nvs_flash.rst index 184daff12a..4daa17ea21 100644 --- a/docs/en/api-reference/storage/nvs_flash.rst +++ b/docs/en/api-reference/storage/nvs_flash.rst @@ -1,5 +1,10 @@ .. include:: ../../../../components/nvs_flash/README.rst +NVS Partition Generator Utility +------------------------------- + +This utility helps in generating NVS-esque partition binary file which can be flashed separately on a dedicated partition via a flashing utility. Key-value pairs to be flashed onto the partition can be provided via a CSV file. Refer to :doc:`NVS Partition Generator Utility ` for more details. + Application Example ------------------- diff --git a/docs/en/api-reference/storage/nvs_partition_gen.rst b/docs/en/api-reference/storage/nvs_partition_gen.rst new file mode 100644 index 0000000000..c94a708c86 --- /dev/null +++ b/docs/en/api-reference/storage/nvs_partition_gen.rst @@ -0,0 +1 @@ +.. include:: /../../components/nvs_flash/nvs_partition_generator/README.rst diff --git a/docs/zh_CN/api-reference/storage/nvs_partition_gen.rst b/docs/zh_CN/api-reference/storage/nvs_partition_gen.rst new file mode 100644 index 0000000000..c94a708c86 --- /dev/null +++ b/docs/zh_CN/api-reference/storage/nvs_partition_gen.rst @@ -0,0 +1 @@ +.. include:: /../../components/nvs_flash/nvs_partition_generator/README.rst From 7b50ed70a34ea93c9b86b62afdc6595ffbfa484a Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Fri, 20 Apr 2018 19:45:50 +0530 Subject: [PATCH 007/187] aws_iot: add support for MQTT TLS over port 443 Signed-off-by: Mahavir Jain --- components/aws_iot/port/network_mbedtls_wrapper.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/components/aws_iot/port/network_mbedtls_wrapper.c b/components/aws_iot/port/network_mbedtls_wrapper.c index 07e2ed4138..6da6d5dad0 100644 --- a/components/aws_iot/port/network_mbedtls_wrapper.c +++ b/components/aws_iot/port/network_mbedtls_wrapper.c @@ -236,6 +236,15 @@ IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) { mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms); + /* Use the AWS IoT ALPN extension for MQTT, if port 443 is requested */ + if (pNetwork->tlsConnectParams.DestinationPort == 443) { + const char *alpnProtocols[] = { "x-amzn-mqtt-ca", NULL }; + if ((ret = mbedtls_ssl_conf_alpn_protocols(&(tlsDataParams->conf), alpnProtocols)) != 0) { + ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_alpn_protocols returned -0x%x", -ret); + return SSL_CONNECTION_ERROR; + } + } + if((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) { ESP_LOGE(TAG, "failed! mbedtls_ssl_setup returned -0x%x", -ret); return SSL_CONNECTION_ERROR; From 21584827b35676da4a93973e70284338b987b185 Mon Sep 17 00:00:00 2001 From: Sagar Bijwe Date: Tue, 24 Apr 2018 17:21:52 +0530 Subject: [PATCH 008/187] dhcp/dhcpserver Fix max station limit check in dhcp server Currently when MAX_STATION limit in DHCP config is set to N, dhcp server issues only N-1 IP addresses. This is problematic from customer perspective if both SoftAP MAX_STATION and DHCP MAX_STATION limit is set to same value. With this change DHCP server can issue N addresses that is inline with the set limit. Closes TW<20556> --- components/lwip/apps/dhcpserver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/lwip/apps/dhcpserver.c b/components/lwip/apps/dhcpserver.c index d4c48862ca..f43932d4df 100644 --- a/components/lwip/apps/dhcpserver.c +++ b/components/lwip/apps/dhcpserver.c @@ -1247,7 +1247,7 @@ void dhcps_coarse_tmr(void) } } - if (num_dhcps_pool >= MAX_STATION_NUM) { + if (num_dhcps_pool > MAX_STATION_NUM) { kill_oldest_dhcps_pool(); } } From 5fc130f2c062266fdfdebd4b84b97442091330c3 Mon Sep 17 00:00:00 2001 From: shangke Date: Wed, 14 Mar 2018 16:18:07 +0800 Subject: [PATCH 009/187] update emac_reg_v2.h --- components/ethernet/emac_dev.c | 50 +- components/ethernet/emac_dev.h | 10 +- components/ethernet/emac_main.c | 33 +- .../soc/esp32/include/soc/emac_reg_v2.h | 2608 +++++++++-------- 4 files changed, 1434 insertions(+), 1267 deletions(-) diff --git a/components/ethernet/emac_dev.c b/components/ethernet/emac_dev.c index 5a8b61cba0..cceea4f1b5 100644 --- a/components/ethernet/emac_dev.c +++ b/components/ethernet/emac_dev.c @@ -36,20 +36,20 @@ static const char *TAG = "emac"; void emac_enable_flowctrl(void) { - REG_SET_BIT(EMAC_GMACFLOWCONTROL_REG, EMAC_TRANSMIT_FLOW_CONTROL_ENABLE); - REG_SET_BIT(EMAC_GMACFLOWCONTROL_REG, EMAC_RECEIVE_FLOW_CONTROL_ENABLE); - REG_CLR_BIT(EMAC_GMACFLOWCONTROL_REG, EMAC_DISABLE_ZERO_QUANTA_PAUSE); - REG_SET_FIELD(EMAC_GMACFLOWCONTROL_REG, EMAC_PAUSE_TIME, 0x1648); - REG_SET_FIELD(EMAC_GMACFLOWCONTROL_REG, EMAC_PAUSE_LOW_THRESHOLD, 0x1); + REG_SET_BIT(EMAC_GMACFC_REG, EMAC_TFCE); + REG_SET_BIT(EMAC_GMACFC_REG, EMAC_RFCE); + REG_CLR_BIT(EMAC_GMACFC_REG, EMAC_DZPQ); + REG_SET_FIELD(EMAC_GMACFC_REG, EMAC_PAUSE_TIME, 0x1648); + REG_SET_FIELD(EMAC_GMACFC_REG, EMAC_PLT, 0x1); } void emac_disable_flowctrl(void) { - REG_CLR_BIT(EMAC_GMACFLOWCONTROL_REG, EMAC_TRANSMIT_FLOW_CONTROL_ENABLE); - REG_CLR_BIT(EMAC_GMACFLOWCONTROL_REG, EMAC_RECEIVE_FLOW_CONTROL_ENABLE); - REG_CLR_BIT(EMAC_GMACFLOWCONTROL_REG, EMAC_DISABLE_ZERO_QUANTA_PAUSE); - REG_SET_FIELD(EMAC_GMACFLOWCONTROL_REG, EMAC_PAUSE_TIME, 0); - REG_SET_FIELD(EMAC_GMACFLOWCONTROL_REG, EMAC_PAUSE_LOW_THRESHOLD, 0); + REG_CLR_BIT(EMAC_GMACFC_REG, EMAC_TFCE); + REG_CLR_BIT(EMAC_GMACFC_REG, EMAC_RFCE); + REG_CLR_BIT(EMAC_GMACFC_REG, EMAC_DZPQ); + REG_SET_FIELD(EMAC_GMACFC_REG, EMAC_PAUSE_TIME, 0); + REG_SET_FIELD(EMAC_GMACFC_REG, EMAC_PLT, 0); } void emac_enable_dma_tx(void) @@ -59,25 +59,17 @@ void emac_enable_dma_tx(void) void emac_enable_dma_rx(void) { - REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_RECEIVE); + REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_RX); } void emac_disable_dma_tx(void) { - REG_CLR_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_OPERATE_SECOND_FRAME); + REG_CLR_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_TRANSMISSION_COMMAND); } void emac_disable_dma_rx(void) { - REG_CLR_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_RECEIVE); -} - - -uint32_t emac_read_mac_version(void) -{ - uint32_t data = 0; - data = REG_READ(EMAC_GMACVERSION_REG); - return data; + REG_CLR_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_RX); } void emac_reset(void) @@ -103,22 +95,22 @@ void emac_enable_clk(bool enable) void emac_dma_init(void) { - REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_FORWARD_UNDERSIZED_GOOD_FRAMES); - REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_OPERATE_SECOND_FRAME); + REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_FWD_UNDER_GF); + REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_OPT_SECOND_FRAME); REG_SET_FIELD(EMAC_DMABUSMODE_REG, EMAC_PROG_BURST_LEN, 4); REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_DMAOPERATION_MODE_REG); } void emac_mac_enable_txrx(void) { - REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACRX); - REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACTX); + REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACRX); + REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACTX); } void emac_mac_init(void) { - REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX); - REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACMIIGMII); - REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACFESPEED); - REG_SET_BIT(EMAC_GMACFRAMEFILTER_REG, EMAC_PROMISCUOUS_MODE); + REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACDUPLEX); + REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACMII); + REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACFESPEED); + REG_SET_BIT(EMAC_GMACFF_REG, EMAC_PMODE); } diff --git a/components/ethernet/emac_dev.h b/components/ethernet/emac_dev.h index d29ab07534..0a49f94cc8 100644 --- a/components/ethernet/emac_dev.h +++ b/components/ethernet/emac_dev.h @@ -22,7 +22,7 @@ extern "C" { #endif -#define EMAC_INTR_ENABLE_BIT (EMAC_TRANSMIT_INTERRUPT_ENABLE | EMAC_RECEIVE_INTERRUPT_ENABLE | EMAC_RECEIVE_BUFFER_UNAVAILABLE_ENABLE | EMAC_NORMAL_INTERRUPT_SUMMARY_ENABLE) +#define EMAC_INTR_ENABLE_BIT (EMAC_DMAIN_TIE | EMAC_DMAIN_RIE | EMAC_DMAIN_RBUE | EMAC_DMAIN_NISE) struct dma_desc { uint32_t desc0; @@ -78,22 +78,22 @@ void inline emac_poll_rx_cmd(void) void inline emac_disable_rx_intr(void) { - REG_CLR_BIT(EMAC_DMAINTERRUPT_EN_REG, EMAC_RECEIVE_INTERRUPT_ENABLE); + REG_CLR_BIT(EMAC_DMAIN_EN_REG, EMAC_DMAIN_RIE); } void inline emac_enable_rx_intr(void) { - REG_SET_BIT(EMAC_DMAINTERRUPT_EN_REG, EMAC_RECEIVE_INTERRUPT_ENABLE); + REG_SET_BIT(EMAC_DMAIN_EN_REG, EMAC_DMAIN_RIE); } void inline emac_disable_rx_unavail_intr(void) { - REG_CLR_BIT(EMAC_DMAINTERRUPT_EN_REG, EMAC_RECEIVE_BUFFER_UNAVAILABLE_ENABLE); + REG_CLR_BIT(EMAC_DMAIN_EN_REG, EMAC_DMAIN_RBUE); } void inline emac_enable_rx_unavail_intr(void) { - REG_SET_BIT(EMAC_DMAINTERRUPT_EN_REG, EMAC_RECEIVE_BUFFER_UNAVAILABLE_ENABLE); + REG_SET_BIT(EMAC_DMAIN_EN_REG, EMAC_DMAIN_RBUE); } void IRAM_ATTR inline emac_send_pause_frame_enable(void) diff --git a/components/ethernet/emac_main.c b/components/ethernet/emac_main.c index b8c94b0fad..abdd50bef5 100644 --- a/components/ethernet/emac_main.c +++ b/components/ethernet/emac_main.c @@ -214,13 +214,13 @@ void esp_eth_smi_write(uint32_t reg_num, uint16_t value) { uint32_t phy_num = emac_config.phy_addr; - while (REG_GET_BIT(EMAC_GMACGMIIADDR_REG, EMAC_GMIIBUSY) == 1 ) { + while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1 ) { } - REG_WRITE(EMAC_GMACGMIIDATA_REG, value); - REG_WRITE(EMAC_GMACGMIIADDR_REG, 0x3 | ((reg_num & 0x1f) << 6) | ((phy_num & 0x1f) << 11) | ((0x3) << 2)); + REG_WRITE(EMAC_MIIDATA_REG, value); + REG_WRITE(EMAC_GMIIADDR_REG, 0x3 | ((reg_num & 0x1f) << 6) | ((phy_num & 0x1f) << 11) | ((0x3) << 2)); - while (REG_GET_BIT(EMAC_GMACGMIIADDR_REG, EMAC_GMIIBUSY) == 1 ) { + while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1 ) { } } @@ -229,13 +229,13 @@ uint16_t esp_eth_smi_read(uint32_t reg_num) uint32_t phy_num = emac_config.phy_addr; uint16_t value = 0; - while (REG_GET_BIT(EMAC_GMACGMIIADDR_REG, EMAC_GMIIBUSY) == 1 ) { + while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1 ) { } - REG_WRITE(EMAC_GMACGMIIADDR_REG, 0x1 | ((reg_num & 0x1f) << 6) | ((phy_num & 0x1f) << 11) | (0x3 << 2)); - while (REG_GET_BIT(EMAC_GMACGMIIADDR_REG, EMAC_GMIIBUSY) == 1 ) { + REG_WRITE(EMAC_GMIIADDR_REG, 0x1 | ((reg_num & 0x1f) << 6) | ((phy_num & 0x1f) << 11) | (0x3 << 2)); + while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1 ) { } - value = (REG_READ(EMAC_GMACGMIIDATA_REG) & 0xffff); + value = (REG_READ(EMAC_MIIDATA_REG) & 0xffff); return value; } @@ -285,12 +285,12 @@ static void emac_set_user_config_data(eth_config_t *config ) static void emac_enable_intr() { - REG_WRITE(EMAC_DMAINTERRUPT_EN_REG, EMAC_INTR_ENABLE_BIT); + REG_WRITE(EMAC_DMAIN_EN_REG, EMAC_INTR_ENABLE_BIT); } static void emac_disable_intr() { - REG_WRITE(EMAC_DMAINTERRUPT_EN_REG, 0); + REG_WRITE(EMAC_DMAIN_EN_REG, 0); } static esp_err_t emac_verify_args(void) @@ -590,22 +590,22 @@ static void IRAM_ATTR emac_process_intr(void *arg) static void emac_set_macaddr_reg(void) { - REG_SET_FIELD(EMAC_GMACADDR0HIGH_REG, EMAC_MAC_ADDRESS0_HI, (emac_config.macaddr[0] << 8) | (emac_config.macaddr[1])); - REG_WRITE(EMAC_GMACADDR0LOW_REG, (emac_config.macaddr[2] << 24) | (emac_config.macaddr[3] << 16) | (emac_config.macaddr[4] << 8) | (emac_config.macaddr[5])); + REG_SET_FIELD(EMAC_ADDR0HIGH_REG, EMAC_ADDRESS0_HI, (emac_config.macaddr[0] << 8) | (emac_config.macaddr[1])); + REG_WRITE(EMAC_ADDR0LOW_REG, (emac_config.macaddr[2] << 24) | (emac_config.macaddr[3] << 16) | (emac_config.macaddr[4] << 8) | (emac_config.macaddr[5])); } static void emac_check_phy_init(void) { emac_config.emac_phy_check_init(); if (emac_config.emac_phy_get_duplex_mode() == ETH_MODE_FULLDUPLEX) { - REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX); + REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACDUPLEX); } else { - REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACDUPLEX); + REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACDUPLEX); } if (emac_config.emac_phy_get_speed_mode() == ETH_SPEED_MODE_100M) { - REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACFESPEED); + REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACFESPEED); } else { - REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_GMACFESPEED); + REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACFESPEED); } #if CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE emac_disable_flowctrl(); @@ -1091,7 +1091,6 @@ esp_err_t esp_eth_init_internal(eth_config_t *config) emac_config.emac_gpio_config(); - ESP_LOGI(TAG, "mac version %04xa", emac_read_mac_version()); emac_hw_init(); emac_macaddr_init(); diff --git a/components/soc/esp32/include/soc/emac_reg_v2.h b/components/soc/esp32/include/soc/emac_reg_v2.h index a33ce44ade..72af5bfe36 100644 --- a/components/soc/esp32/include/soc/emac_reg_v2.h +++ b/components/soc/esp32/include/soc/emac_reg_v2.h @@ -11,1274 +11,1450 @@ // 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 _SOC_EMAC_REG_H_ +#define _SOC_EMAC_REG_H_ -#ifndef _EMAC_H_ -#define _EMAC_H_ #ifdef __cplusplus extern "C" { #endif - #include "soc.h" -#define REG_EMAC_BASE DR_REG_EMAC_BASE +#define EMAC_DMABUSMODE_REG (DR_REG_EMAC_BASE + 0x0000) +/* EMAC_DMAMIXEDBURST : R/W ;bitpos:[26] ;default: 1'h0 ; */ +/*description: When this bit is set high and the FIXED_BURST bit is low the + AHB master interface starts all bursts of a length more than 16 with INCR (undefined burst) whereas it reverts to fixed burst transfers (INCRx and SINGLE) for burst length of 16 and less.*/ +#define EMAC_DMAMIXEDBURST (BIT(26)) +#define EMAC_DMAMIXEDBURST_M (BIT(26)) +#define EMAC_DMAMIXEDBURST_V 0x1 +#define EMAC_DMAMIXEDBURST_S 26 +/* EMAC_DMAADDRALIBEA : R/W ;bitpos:[25] ;default: 1'h0 ; */ +/*description: When this bit is set high and the FIXED_BURST bit is 1 the AHB + interface generates all bursts aligned to the start address LS bits. If the FIXED_BURST bit is 0 the first burst (accessing the start address of data buffer) is not aligned but subsequent bursts are aligned to the address.*/ +#define EMAC_DMAADDRALIBEA (BIT(25)) +#define EMAC_DMAADDRALIBEA_M (BIT(25)) +#define EMAC_DMAADDRALIBEA_V 0x1 +#define EMAC_DMAADDRALIBEA_S 25 +/* EMAC_PBLX8_MODE : R/W ;bitpos:[24] ;default: 1'h0 ; */ +/*description: When set high this bit multiplies the programmed PBL value (Bits[22:17] + and Bits[13:8]) eight times. Therefore the DMA transfers the data in 8 16 32 64 128 and 256 beats depending on the PBL value.*/ +#define EMAC_PBLX8_MODE (BIT(24)) +#define EMAC_PBLX8_MODE_M (BIT(24)) +#define EMAC_PBLX8_MODE_V 0x1 +#define EMAC_PBLX8_MODE_S 24 +/* EMAC_USE_SEP_PBL : R/W ;bitpos:[23] ;default: 1'h0 ; */ +/*description: When set high this bit configures the Rx DMA to use the value + configured in Bits[22:17] as PBL. The PBL value in Bits[13:8] is applicable only to the Tx DMA operations. When reset to low the PBL value in Bits[13:8] is applicable for both DMA engines.*/ +#define EMAC_USE_SEP_PBL (BIT(23)) +#define EMAC_USE_SEP_PBL_M (BIT(23)) +#define EMAC_USE_SEP_PBL_V 0x1 +#define EMAC_USE_SEP_PBL_S 23 +/* EMAC_RX_DMA_PBL : R/W ;bitpos:[22:17] ;default: 6'h1 ; */ +/*description: This field indicates the maximum number of beats to be transferred + in one Rx DMA transaction. This is the maximum value that is used in a single block Read or Write.The Rx DMA always attempts to burst as specified in the RPBL(RX_DMA_PBL) bit each time it starts a burst transfer on the host bus. You can program RPBL with values of 1 2 4 8 16 and 32. Any other value results in undefined behavior. This field is valid and applicable only when USP(USE_SEP_PBL) is set high.*/ +#define EMAC_RX_DMA_PBL 0x0000003F +#define EMAC_RX_DMA_PBL_M ((EMAC_RX_DMA_PBL_V)<<(EMAC_RX_DMA_PBL_S)) +#define EMAC_RX_DMA_PBL_V 0x3F +#define EMAC_RX_DMA_PBL_S 17 +/* EMAC_FIXED_BURST : R/W ;bitpos:[16] ;default: 1'h0 ; */ +/*description: This bit controls whether the AHB master interface performs fixed + burst transfers or not. When set the AHB interface uses only SINGLE INCR4 INCR8 or INCR16 during start of the normal burst transfers. When reset the AHB interface uses SINGLE and INCR burst transfer Operations.*/ +#define EMAC_FIXED_BURST (BIT(16)) +#define EMAC_FIXED_BURST_M (BIT(16)) +#define EMAC_FIXED_BURST_V 0x1 +#define EMAC_FIXED_BURST_S 16 +/* EMAC_PRI_RATIO : R/W ;bitpos:[15:14] ;default: 2'h0 ; */ +/*description: These bits control the priority ratio in the weighted round-robin + arbitration between the Rx DMA and Tx DMA. These bits are valid only when Bit 1 (DA) is reset. The priority ratio Rx:Tx represented by each bit: 2'b00 -- 1: 1 2'b01 -- 2: 0 2'b10 -- 3: 1 2'b11 -- 4: 1*/ +#define EMAC_PRI_RATIO 0x00000003 +#define EMAC_PRI_RATIO_M ((EMAC_PRI_RATIO_V)<<(EMAC_PRI_RATIO_S)) +#define EMAC_PRI_RATIO_V 0x3 +#define EMAC_PRI_RATIO_S 14 +/* EMAC_PROG_BURST_LEN : R/W ;bitpos:[13:8] ;default: 6'h1 ; */ +/*description: These bits indicate the maximum number of beats to be transferred + in one DMA transaction. If the number of beats to be transferred is more than 32 then perform the following steps: 1. Set the PBLx8 mode 2. Set the PBL(PROG_BURST_LEN).*/ +#define EMAC_PROG_BURST_LEN 0x0000003F +#define EMAC_PROG_BURST_LEN_M ((EMAC_PROG_BURST_LEN_V)<<(EMAC_PROG_BURST_LEN_S)) +#define EMAC_PROG_BURST_LEN_V 0x3F +#define EMAC_PROG_BURST_LEN_S 8 +/* EMAC_ALT_DESC_SIZE : R/W ;bitpos:[7] ;default: 1'h0 ; */ +/*description: When set the size of the alternate descriptor increases to 32 bytes.*/ +#define EMAC_ALT_DESC_SIZE (BIT(7)) +#define EMAC_ALT_DESC_SIZE_M (BIT(7)) +#define EMAC_ALT_DESC_SIZE_V 0x1 +#define EMAC_ALT_DESC_SIZE_S 7 +/* EMAC_DESC_SKIP_LEN : R/W ;bitpos:[6:2] ;default: 5'h0 ; */ +/*description: This bit specifies the number of Word to skip between two unchained + descriptors.The address skipping starts from the end of current descriptor to the start of next descriptor. When the DSL(DESC_SKIP_LEN) value is equal to zero the descriptor table is taken as contiguous by the DMA in Ring mode.*/ +#define EMAC_DESC_SKIP_LEN 0x0000001F +#define EMAC_DESC_SKIP_LEN_M ((EMAC_DESC_SKIP_LEN_V)<<(EMAC_DESC_SKIP_LEN_S)) +#define EMAC_DESC_SKIP_LEN_V 0x1F +#define EMAC_DESC_SKIP_LEN_S 2 +/* EMAC_DMA_ARB_SCH : R/W ;bitpos:[1] ;default: 1'h0 ; */ +/*description: This bit specifies the arbitration scheme between the transmit + and receive paths.1'b0: weighted round-robin with RX:TX or TX:RX priority specified in PR (bit[15:14]). 1'b1 Fixed priority (Rx priority to Tx).*/ +#define EMAC_DMA_ARB_SCH (BIT(1)) +#define EMAC_DMA_ARB_SCH_M (BIT(1)) +#define EMAC_DMA_ARB_SCH_V 0x1 +#define EMAC_DMA_ARB_SCH_S 1 +/* EMAC_SW_RST : R_WS_SC ;bitpos:[0] ;default: 1'h1 ; */ +/*description: When this bit is set the MAC DMA Controller resets the logic + and all internal registers of the MAC. It is cleared automatically after the reset operation is complete in all of the ETH_MAC clock domains. Before reprogramming any register of the ETH_MAC you should read a zero (0) value in this bit.*/ +#define EMAC_SW_RST (BIT(0)) +#define EMAC_SW_RST_M (BIT(0)) +#define EMAC_SW_RST_V 0x1 +#define EMAC_SW_RST_S 0 -#define EMAC_DMABUSMODE_REG (REG_EMAC_BASE + 0x0000) -#define EMAC_DMAREBINCRBURST (BIT(31)) -#define EMAC_DMAREBINCRBURST_M (BIT(31)) -#define EMAC_DMAREBINCRBURST_V 1 -#define EMAC_DMAREBINCRBURST_S 31 -#define EMAC_DMACHANNELPRIOWT 0x00000003 -#define EMAC_DMACHANNELPRIOWT_M (EMAC_DMACHANNELPRIOWT_V << EMAC_DMACHANNELPRIOWT_S) -#define EMAC_DMACHANNELPRIOWT_V 0x00000003 -#define EMAC_DMACHANNELPRIOWT_S 28 -#define EMAC_DMATXRXPRIO (BIT(27)) -#define EMAC_DMATXRXPRIO_M (BIT(27)) -#define EMAC_DMATXRXPRIO_V 1 -#define EMAC_DMATXRXPRIO_S 27 -#define EMAC_DMAMIXEDBURST (BIT(26)) -#define EMAC_DMAMIXEDBURST_M (BIT(26)) -#define EMAC_DMAMIXEDBURST_V 1 -#define EMAC_DMAMIXEDBURST_S 26 -#define EMAC_DMAADDRALIBEA (BIT(25)) -#define EMAC_DMAADDRALIBEA_M (BIT(25)) -#define EMAC_DMAADDRALIBEA_V 1 -#define EMAC_DMAADDRALIBEA_S 25 -#define EMAC_PBLX8_MODE (BIT(24)) -#define EMAC_PBLX8_MODE_M (BIT(24)) -#define EMAC_PBLX8_MODE_V 1 -#define EMAC_PBLX8_MODE_S 24 -#define EMAC_USE_SEP_PBL (BIT(23)) -#define EMAC_USE_SEP_PBL_M (BIT(23)) -#define EMAC_USE_SEP_PBL_V 1 -#define EMAC_USE_SEP_PBL_S 23 -#define EMAC_RX_DMA_PBL 0x0000003F -#define EMAC_RX_DMA_PBL_M (EMAC_RX_DMA_PBL_V << EMAC_RX_DMA_PBL_S) -#define EMAC_RX_DMA_PBL_V 0x0000003F -#define EMAC_RX_DMA_PBL_S 17 -#define EMAC_FIXED_BURST (BIT(16)) -#define EMAC_FIXED_BURST_M (BIT(16)) -#define EMAC_FIXED_BURST_V 1 -#define EMAC_FIXED_BURST_S 16 -#define EMAC_PRI_RATIO 0x00000003 -#define EMAC_PRI_RATIO_M (EMAC_PRI_RATIO_V << EMAC_PRI_RATIO_S) -#define EMAC_PRI_RATIO_V 0x00000003 -#define EMAC_PRI_RATIO_S 14 -#define EMAC_PROG_BURST_LEN 0x0000003F -#define EMAC_PROG_BURST_LEN_M (EMAC_PROG_BURST_LEN_V << EMAC_PROG_BURST_LEN_S) -#define EMAC_PROG_BURST_LEN_V 0x0000003F -#define EMAC_PROG_BURST_LEN_S 8 -#define EMAC_ALT_DESC_SIZE (BIT(7)) -#define EMAC_ALT_DESC_SIZE_M (BIT(7)) -#define EMAC_ALT_DESC_SIZE_V 1 -#define EMAC_ALT_DESC_SIZE_S 7 -#define EMAC_DESC_SKIP_LEN 0x0000001F -#define EMAC_DESC_SKIP_LEN_M (EMAC_DESC_SKIP_LEN_V << EMAC_DESC_SKIP_LEN_S) -#define EMAC_DESC_SKIP_LEN_V 0x0000001F -#define EMAC_DESC_SKIP_LEN_S 2 -#define EMAC_DMA_ARB_SCH (BIT(1)) -#define EMAC_DMA_ARB_SCH_M (BIT(1)) -#define EMAC_DMA_ARB_SCH_V 1 -#define EMAC_DMA_ARB_SCH_S 1 -#define EMAC_SW_RST (BIT(0)) -#define EMAC_SW_RST_M (BIT(0)) -#define EMAC_SW_RST_V 1 -#define EMAC_SW_RST_S 0 +#define EMAC_DMATXPOLLDEMAND_REG (DR_REG_EMAC_BASE + 0x0004) +/* EMAC_TRANS_POLL_DEMAND : RO_WT ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: When these bits are written with any value the DMA reads the + current descriptor to which the Register (Current Host Transmit Descriptor Register) is pointing. If that descriptor is not available (owned by the Host) the transmission returns to the suspend state and Bit[2] (TU) of Status Register is asserted. If the descriptor is available the transmission resumes.*/ +#define EMAC_TRANS_POLL_DEMAND 0xFFFFFFFF +#define EMAC_TRANS_POLL_DEMAND_M ((EMAC_TRANS_POLL_DEMAND_V)<<(EMAC_TRANS_POLL_DEMAND_S)) +#define EMAC_TRANS_POLL_DEMAND_V 0xFFFFFFFF +#define EMAC_TRANS_POLL_DEMAND_S 0 -#define EMAC_DMATXPOLLDEMAND_REG (REG_EMAC_BASE + 0x0004) -#define EMAC_TRANS_POLL_DEMAND 0xFFFFFFFF -#define EMAC_TRANS_POLL_DEMAND_M (EMAC_TRANS_POLL_DEMAND_V << EMAC_TRANS_POLL_DEMAND_S) -#define EMAC_TRANS_POLL_DEMAND_V 0xFFFFFFFF -#define EMAC_TRANS_POLL_DEMAND_S 0 +#define EMAC_DMARXPOLLDEMAND_REG (DR_REG_EMAC_BASE + 0x0008) +/* EMAC_RECV_POLL_DEMAND : RO_WT ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: When these bits are written with any value the DMA reads the + current descriptor to which the Current Host Receive Descriptor Register is pointing. If that descriptor is not available (owned by the Host) the reception returns to the Suspended state and Bit[7] (RU) of Status Register is asserted. If the descriptor is available the Rx DMA returns to the active state.*/ +#define EMAC_RECV_POLL_DEMAND 0xFFFFFFFF +#define EMAC_RECV_POLL_DEMAND_M ((EMAC_RECV_POLL_DEMAND_V)<<(EMAC_RECV_POLL_DEMAND_S)) +#define EMAC_RECV_POLL_DEMAND_V 0xFFFFFFFF +#define EMAC_RECV_POLL_DEMAND_S 0 -#define EMAC_DMARXPOLLDEMAND_REG (REG_EMAC_BASE + 0x0008) -#define EMAC_RECV_POLL_DEMAND 0xFFFFFFFF -#define EMAC_RECV_POLL_DEMAND_M (EMAC_RECV_POLL_DEMAND_V << EMAC_RECV_POLL_DEMAND_S) -#define EMAC_RECV_POLL_DEMAND_V 0xFFFFFFFF -#define EMAC_RECV_POLL_DEMAND_S 0 +#define EMAC_DMARXBASEADDR_REG (DR_REG_EMAC_BASE + 0x000C) +/* EMAC_START_RECV_LIST : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: This field contains the base address of the first descriptor + in the Receive Descriptor list. The LSB Bits[1:0] are ignored and internally taken as all-zero by the DMA. Therefore these LSB bits are read-only.*/ +#define EMAC_START_RECV_LIST 0xFFFFFFFF +#define EMAC_START_RECV_LIST_M ((EMAC_START_RECV_LIST_V)<<(EMAC_START_RECV_LIST_S)) +#define EMAC_START_RECV_LIST_V 0xFFFFFFFF +#define EMAC_START_RECV_LIST_S 0 -#define EMAC_DMARXBASEADDR_REG (REG_EMAC_BASE + 0x000C) -#define EMAC_START_RECV_LIST 0xFFFFFFFF -#define EMAC_START_RECV_LIST_M (EMAC_START_RECV_LIST_V << EMAC_START_RECV_LIST_S) -#define EMAC_START_RECV_LIST_V 0xFFFFFFFF -#define EMAC_START_RECV_LIST_S 0 +#define EMAC_DMATXBASEADDR_REG (DR_REG_EMAC_BASE + 0x0010) +/* EMAC_START_TRANS_LIST : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: This field contains the base address of the first descriptor + in the Transmit Descriptor list. The LSB Bits[1:0] are ignored and are internally taken as all-zero by the DMA.Therefore these LSB bits are read-only.*/ +#define EMAC_START_TRANS_LIST 0xFFFFFFFF +#define EMAC_START_TRANS_LIST_M ((EMAC_START_TRANS_LIST_V)<<(EMAC_START_TRANS_LIST_S)) +#define EMAC_START_TRANS_LIST_V 0xFFFFFFFF +#define EMAC_START_TRANS_LIST_S 0 -#define EMAC_DMATXBASEADDR_REG (REG_EMAC_BASE + 0x0010) -#define EMAC_START_TRANS_LIST 0xFFFFFFFF -#define EMAC_START_TRANS_LIST_M (EMAC_START_TRANS_LIST_V << EMAC_START_TRANS_LIST_S) -#define EMAC_START_TRANS_LIST_V 0xFFFFFFFF -#define EMAC_START_TRANS_LIST_S 0 +#define EMAC_DMASTATUS_REG (DR_REG_EMAC_BASE + 0x0014) +/* EMAC_TS_TRI_INT : RO ;bitpos:[29] ;default: 1'h0 ; */ +/*description: This bit indicates an interrupt event in the Timestamp Generator + block of the ETH_MAC.The software must read the corresponding registers in the ETH_MAC to get the exact cause of the interrupt and clear its source to reset this bit to 1'b0.*/ +#define EMAC_TS_TRI_INT (BIT(29)) +#define EMAC_TS_TRI_INT_M (BIT(29)) +#define EMAC_TS_TRI_INT_V 0x1 +#define EMAC_TS_TRI_INT_S 29 +/* EMAC_PMT_INT : RO ;bitpos:[28] ;default: 1'h0 ; */ +/*description: This bit indicates an interrupt event in the PMT module of the + ETH_MAC. The software must read the PMT Control and Status Register in the MAC to get the exact cause of interrupt and clear its source to reset this bit to 1'b0.*/ +#define EMAC_PMT_INT (BIT(28)) +#define EMAC_PMT_INT_M (BIT(28)) +#define EMAC_PMT_INT_V 0x1 +#define EMAC_PMT_INT_S 28 +/* EMAC_ERROR_BITS : RO ;bitpos:[25:23] ;default: 3'h0 ; */ +/*description: This field indicates the type of error that caused a Bus Error + for example error response on the AHB interface. This field is valid only when Bit[13] (FBI) is set. This field does not generate an interrupt. 3'b000: Error during Rx DMA Write Data Transfer. 3'b011: Error during Tx DMA Read Data Transfer. 3'b100: Error during Rx DMA Descriptor Write Access. 3'b101: Error during Tx DMA Descriptor Write Access. 3'b110: Error during Rx DMA Descriptor Read Access. 3'b111: Error during Tx DMA Descriptor Read Access.*/ +#define EMAC_ERROR_BITS 0x00000007 +#define EMAC_ERROR_BITS_M ((EMAC_ERROR_BITS_V)<<(EMAC_ERROR_BITS_S)) +#define EMAC_ERROR_BITS_V 0x7 +#define EMAC_ERROR_BITS_S 23 +/* EMAC_TRANS_PROC_STATE : RO ;bitpos:[22:20] ;default: 3'h0 ; */ +/*description: This field indicates the Transmit DMA FSM state. This field does + not generate an interrupt. 3'b000: Stopped. Reset or Stop Transmit Command issued. 3'b001: Running. Fetching Transmit Transfer Descriptor. 3'b010: Reserved for future use. 3'b011: Running. Waiting for TX packets. 3'b100: Suspended. Receive Descriptor Unavailable. 3'b101: Running. Closing Transmit Descriptor. 3'b110: TIME_STAMP write state. 3'b111: Running. Transferring the TX packets data from transmit buffer to host memory.*/ +#define EMAC_TRANS_PROC_STATE 0x00000007 +#define EMAC_TRANS_PROC_STATE_M ((EMAC_TRANS_PROC_STATE_V)<<(EMAC_TRANS_PROC_STATE_S)) +#define EMAC_TRANS_PROC_STATE_V 0x7 +#define EMAC_TRANS_PROC_STATE_S 20 +/* EMAC_RECV_PROC_STATE : RO ;bitpos:[19:17] ;default: 3'h0 ; */ +/*description: This field indicates the Receive DMA FSM state. This field does + not generate an interrupt. 3'b000: Stopped. Reset or Stop Receive Command issued. 3'b001: Running. Fetching Receive Transfer Descriptor. 3'b010: Reserved for future use. 3'b011: Running. Waiting for RX packets. 3'b100: Suspended. Receive Descriptor Unavailable. 3'b101: Running. Closing Receive Descriptor. 3'b110: TIME_STAMP write state. 3'b111: Running. Transferring the TX packets data from receive buffer to host memory.*/ +#define EMAC_RECV_PROC_STATE 0x00000007 +#define EMAC_RECV_PROC_STATE_M ((EMAC_RECV_PROC_STATE_V)<<(EMAC_RECV_PROC_STATE_S)) +#define EMAC_RECV_PROC_STATE_V 0x7 +#define EMAC_RECV_PROC_STATE_S 17 +/* EMAC_NORM_INT_SUMM : R_SS_WC ;bitpos:[16] ;default: 1'h0 ; */ +/*description: Normal Interrupt Summary bit value is the logical OR of the following + bits when the corresponding interrupt bits are enabled in Interrupt Enable Register: Bit[0]: Transmit Interrupt. Bit[2]: Transmit Buffer Unavailable. Bit[6]: Receive Interrupt. Bit[14]: Early Receive Interrupt. Only unmasked bits affect the Normal Interrupt Summary bit.This is a sticky bit and must be cleared (by writing 1 to this bit) each time a corresponding bit which causes NIS to be set is cleared.*/ +#define EMAC_NORM_INT_SUMM (BIT(16)) +#define EMAC_NORM_INT_SUMM_M (BIT(16)) +#define EMAC_NORM_INT_SUMM_V 0x1 +#define EMAC_NORM_INT_SUMM_S 16 +/* EMAC_ABN_INT_SUMM : R_SS_WC ;bitpos:[15] ;default: 1'h0 ; */ +/*description: Abnormal Interrupt Summary bit value is the logical OR of the + following when the corresponding interrupt bits are enabled in Interrupt Enable Register: Bit[1]: Transmit Process Stopped. Bit[3]: Transmit Jabber Timeout. Bit[4]: Receive FIFO Overflow. Bit[5]: Transmit Underflow. Bit[7]: Receive Buffer Unavailable. Bit[8]: Receive Process Stopped. Bit[9]: Receive Watchdog Timeout. Bit[10]: Early Transmit Interrupt. Bit[13]: Fatal Bus Error. Only unmasked bits affect the Abnormal Interrupt Summary bit. This is a sticky bit and must be cleared (by writing 1 to this bit) each time a corresponding bit which causes AIS to be set is cleared.*/ +#define EMAC_ABN_INT_SUMM (BIT(15)) +#define EMAC_ABN_INT_SUMM_M (BIT(15)) +#define EMAC_ABN_INT_SUMM_V 0x1 +#define EMAC_ABN_INT_SUMM_S 15 +/* EMAC_EARLY_RECV_INT : R_SS_WC ;bitpos:[14] ;default: 1'h0 ; */ +/*description: This bit indicates that the DMA filled the first data buffer + of the packet. This bit is cleared when the software writes 1 to this bit or when Bit[6] (RI) of this register is set (whichever occurs earlier).*/ +#define EMAC_EARLY_RECV_INT (BIT(14)) +#define EMAC_EARLY_RECV_INT_M (BIT(14)) +#define EMAC_EARLY_RECV_INT_V 0x1 +#define EMAC_EARLY_RECV_INT_S 14 +/* EMAC_FATAL_BUS_ERR_INT : R_SS_WC ;bitpos:[13] ;default: 1'h0 ; */ +/*description: This bit indicates that a bus error occurred as described in + Bits [25:23]. When this bit is set the corresponding DMA engine disables all of its bus accesses.*/ +#define EMAC_FATAL_BUS_ERR_INT (BIT(13)) +#define EMAC_FATAL_BUS_ERR_INT_M (BIT(13)) +#define EMAC_FATAL_BUS_ERR_INT_V 0x1 +#define EMAC_FATAL_BUS_ERR_INT_S 13 +/* EMAC_EARLY_TRANS_INT : R_SS_WC ;bitpos:[10] ;default: 1'h0 ; */ +/*description: This bit indicates that the frame to be transmitted is fully + transferred to the MTL Transmit FIFO.*/ +#define EMAC_EARLY_TRANS_INT (BIT(10)) +#define EMAC_EARLY_TRANS_INT_M (BIT(10)) +#define EMAC_EARLY_TRANS_INT_V 0x1 +#define EMAC_EARLY_TRANS_INT_S 10 +/* EMAC_RECV_WDT_TO : R_SS_WC ;bitpos:[9] ;default: 1'h0 ; */ +/*description: When set this bit indicates that the Receive Watchdog Timer + expired while receiving the current frame and the current frame is truncated after the watchdog timeout.*/ +#define EMAC_RECV_WDT_TO (BIT(9)) +#define EMAC_RECV_WDT_TO_M (BIT(9)) +#define EMAC_RECV_WDT_TO_V 0x1 +#define EMAC_RECV_WDT_TO_S 9 +/* EMAC_RECV_PROC_STOP : R_SS_WC ;bitpos:[8] ;default: 1'h0 ; */ +/*description: This bit is asserted when the Receive Process enters the Stopped state.*/ +#define EMAC_RECV_PROC_STOP (BIT(8)) +#define EMAC_RECV_PROC_STOP_M (BIT(8)) +#define EMAC_RECV_PROC_STOP_V 0x1 +#define EMAC_RECV_PROC_STOP_S 8 +/* EMAC_RECV_BUF_UNAVAIL : R_SS_WC ;bitpos:[7] ;default: 1'h0 ; */ +/*description: This bit indicates that the host owns the Next Descriptor in + the Receive List and the DMA cannot acquire it. The Receive Process is suspended. To resume processing Receive descriptors the host should change the ownership of the descriptor and issue a Receive Poll Demand command. If no Receive Poll Demand is issued the Receive Process resumes when the next recognized incoming frame is received. This bit is set only when the previous Receive Descriptor is owned by the DMA.*/ +#define EMAC_RECV_BUF_UNAVAIL (BIT(7)) +#define EMAC_RECV_BUF_UNAVAIL_M (BIT(7)) +#define EMAC_RECV_BUF_UNAVAIL_V 0x1 +#define EMAC_RECV_BUF_UNAVAIL_S 7 +/* EMAC_RECV_INT : R_SS_WC ;bitpos:[6] ;default: 1'h0 ; */ +/*description: This bit indicates that the frame reception is complete. When + reception is complete the Bit[31] of RDES1 (Disable Interrupt on Completion) is reset in the last Descriptor and the specific frame status information is updated in the descriptor. The reception remains in the Running state.*/ +#define EMAC_RECV_INT (BIT(6)) +#define EMAC_RECV_INT_M (BIT(6)) +#define EMAC_RECV_INT_V 0x1 +#define EMAC_RECV_INT_S 6 +/* EMAC_TRANS_UNDFLOW : R_SS_WC ;bitpos:[5] ;default: 1'h0 ; */ +/*description: This bit indicates that the Transmit Buffer had an Underflow + during frame transmission. Transmission is suspended and an Underflow Error TDES0[1] is set.*/ +#define EMAC_TRANS_UNDFLOW (BIT(5)) +#define EMAC_TRANS_UNDFLOW_M (BIT(5)) +#define EMAC_TRANS_UNDFLOW_V 0x1 +#define EMAC_TRANS_UNDFLOW_S 5 +/* EMAC_RECV_OVFLOW : R_SS_WC ;bitpos:[4] ;default: 1'h0 ; */ +/*description: This bit indicates that the Receive Buffer had an Overflow during + frame reception. If the partial frame is transferred to the application the overflow status is set in RDES0[11].*/ +#define EMAC_RECV_OVFLOW (BIT(4)) +#define EMAC_RECV_OVFLOW_M (BIT(4)) +#define EMAC_RECV_OVFLOW_V 0x1 +#define EMAC_RECV_OVFLOW_S 4 +/* EMAC_TRANS_JABBER_TO : R_SS_WC ;bitpos:[3] ;default: 1'h0 ; */ +/*description: This bit indicates that the Transmit Jabber Timer expired which + happens when the frame size exceeds 2 048 (10 240 bytes when the Jumbo frame is enabled). When the Jabber Timeout occurs the transmission process is aborted and placed in the Stopped state. This causes the Transmit Jabber Timeout TDES0[14] flag to assert.*/ +#define EMAC_TRANS_JABBER_TO (BIT(3)) +#define EMAC_TRANS_JABBER_TO_M (BIT(3)) +#define EMAC_TRANS_JABBER_TO_V 0x1 +#define EMAC_TRANS_JABBER_TO_S 3 +/* EMAC_TRANS_BUF_UNAVAIL : R_SS_WC ;bitpos:[2] ;default: 1'h0 ; */ +/*description: This bit indicates that the host owns the Next Descriptor in + the Transmit List and the DMA cannot acquire it. Transmission is suspended. Bits[22:20] explain the Transmit Process state transitions. To resume processing Transmit descriptors the host should change the ownership of the descriptor by setting TDES0[31] and then issue a Transmit Poll Demand Command.*/ +#define EMAC_TRANS_BUF_UNAVAIL (BIT(2)) +#define EMAC_TRANS_BUF_UNAVAIL_M (BIT(2)) +#define EMAC_TRANS_BUF_UNAVAIL_V 0x1 +#define EMAC_TRANS_BUF_UNAVAIL_S 2 +/* EMAC_TRANS_PROC_STOP : R_SS_WC ;bitpos:[1] ;default: 1'h0 ; */ +/*description: This bit is set when the transmission is stopped.*/ +#define EMAC_TRANS_PROC_STOP (BIT(1)) +#define EMAC_TRANS_PROC_STOP_M (BIT(1)) +#define EMAC_TRANS_PROC_STOP_V 0x1 +#define EMAC_TRANS_PROC_STOP_S 1 +/* EMAC_TRANS_INT : R_SS_WC ;bitpos:[0] ;default: 1'h0 ; */ +/*description: This bit indicates that the frame transmission is complete. When + transmission is complete Bit[31] (OWN) of TDES0 is reset and the specific frame status information is updated in the Descriptor.*/ +#define EMAC_TRANS_INT (BIT(0)) +#define EMAC_TRANS_INT_M (BIT(0)) +#define EMAC_TRANS_INT_V 0x1 +#define EMAC_TRANS_INT_S 0 -#define EMAC_DMASTATUS_REG (REG_EMAC_BASE + 0x0014) -#define EMAC_GMAC_LPI_INT (BIT(30)) -#define EMAC_GMAC_LPI_INT_M (BIT(30)) -#define EMAC_GMAC_LPI_INT_V 1 -#define EMAC_GMAC_LPI_INT_S 30 -#define EMAC_TS_TRI_INT (BIT(29)) -#define EMAC_TS_TRI_INT_M (BIT(29)) -#define EMAC_TS_TRI_INT_V 1 -#define EMAC_TS_TRI_INT_S 29 -#define EMAC_GMAC_PMT_INT (BIT(28)) -#define EMAC_GMAC_PMT_INT_M (BIT(28)) -#define EMAC_GMAC_PMT_INT_V 1 -#define EMAC_GMAC_PMT_INT_S 28 -#define EMAC_GMAC_MMC_INT (BIT(27)) -#define EMAC_GMAC_MMC_INT_M (BIT(27)) -#define EMAC_GMAC_MMC_INT_V 1 -#define EMAC_GMAC_MMC_INT_S 27 -#define EMAC_GMAC_LINE_INF_INT (BIT(26)) -#define EMAC_GMAC_LINE_INF_INT_M (BIT(26)) -#define EMAC_GMAC_LINE_INF_INT_V 1 -#define EMAC_GMAC_LINE_INF_INT_S 26 -#define EMAC_ERROR_BITS 0x00000007 -#define EMAC_ERROR_BITS_M (EMAC_ERROR_BITS_V << EMAC_ERROR_BITS_S) -#define EMAC_ERROR_BITS_V 0x00000007 -#define EMAC_ERROR_BITS_S 23 -#define EMAC_TRANS_PROC_STATE 0x00000007 -#define EMAC_TRANS_PROC_STATE_M (EMAC_TRANS_PROC_STATE_V << EMAC_TRANS_PROC_STATE_S) -#define EMAC_TRANS_PROC_STATE_V 0x00000007 -#define EMAC_TRANS_PROC_STATE_S 20 -#define EMAC_RECV_PROC_STATE 0x00000007 -#define EMAC_RECV_PROC_STATE_M (EMAC_RECV_PROC_STATE_V << EMAC_RECV_PROC_STATE_S) -#define EMAC_RECV_PROC_STATE_V 0x00000007 -#define EMAC_RECV_PROC_STATE_S 17 -#define EMAC_NORM_INT_SUMM (BIT(16)) -#define EMAC_NORM_INT_SUMM_M (BIT(16)) -#define EMAC_NORM_INT_SUMM_V 1 -#define EMAC_NORM_INT_SUMM_S 16 -#define EMAC_ABN_INT_SUMM (BIT(15)) -#define EMAC_ABN_INT_SUMM_M (BIT(15)) -#define EMAC_ABN_INT_SUMM_V 1 -#define EMAC_ABN_INT_SUMM_S 15 -#define EMAC_EARLY_RECV_INT (BIT(14)) -#define EMAC_EARLY_RECV_INT_M (BIT(14)) -#define EMAC_EARLY_RECV_INT_V 1 -#define EMAC_EARLY_RECV_INT_S 14 -#define EMAC_FATAL_BUS_ERR_INT (BIT(13)) -#define EMAC_FATAL_BUS_ERR_INT_M (BIT(13)) -#define EMAC_FATAL_BUS_ERR_INT_V 1 -#define EMAC_FATAL_BUS_ERR_INT_S 13 -#define EMAC_EARLY_TRANS_INT (BIT(10)) -#define EMAC_EARLY_TRANS_INT_M (BIT(10)) -#define EMAC_EARLY_TRANS_INT_V 1 -#define EMAC_EARLY_TRANS_INT_S 10 -#define EMAC_RECV_WDT_TO (BIT(9)) -#define EMAC_RECV_WDT_TO_M (BIT(9)) -#define EMAC_RECV_WDT_TO_V 1 -#define EMAC_RECV_WDT_TO_S 9 -#define EMAC_RECV_PROC_STOP (BIT(8)) -#define EMAC_RECV_PROC_STOP_M (BIT(8)) -#define EMAC_RECV_PROC_STOP_V 1 -#define EMAC_RECV_PROC_STOP_S 8 -#define EMAC_RECV_BUF_UNAVAIL (BIT(7)) -#define EMAC_RECV_BUF_UNAVAIL_M (BIT(7)) -#define EMAC_RECV_BUF_UNAVAIL_V 1 -#define EMAC_RECV_BUF_UNAVAIL_S 7 -#define EMAC_RECV_INT (BIT(6)) -#define EMAC_RECV_INT_M (BIT(6)) -#define EMAC_RECV_INT_V 1 -#define EMAC_RECV_INT_S 6 -#define EMAC_TRANS_UNDFLOW (BIT(5)) -#define EMAC_TRANS_UNDFLOW_M (BIT(5)) -#define EMAC_TRANS_UNDFLOW_V 1 -#define EMAC_TRANS_UNDFLOW_S 5 -#define EMAC_RECV_OVFLOW (BIT(4)) -#define EMAC_RECV_OVFLOW_M (BIT(4)) -#define EMAC_RECV_OVFLOW_V 1 -#define EMAC_RECV_OVFLOW_S 4 -#define EMAC_TRANS_JABBER_TO (BIT(3)) -#define EMAC_TRANS_JABBER_TO_M (BIT(3)) -#define EMAC_TRANS_JABBER_TO_V 1 -#define EMAC_TRANS_JABBER_TO_S 3 -#define EMAC_TRANS_BUF_UNAVAIL (BIT(2)) -#define EMAC_TRANS_BUF_UNAVAIL_M (BIT(2)) -#define EMAC_TRANS_BUF_UNAVAIL_V 1 -#define EMAC_TRANS_BUF_UNAVAIL_S 2 -#define EMAC_TRANS_PROC_STOP (BIT(1)) -#define EMAC_TRANS_PROC_STOP_M (BIT(1)) -#define EMAC_TRANS_PROC_STOP_V 1 -#define EMAC_TRANS_PROC_STOP_S 1 -#define EMAC_TRANS_INT (BIT(0)) -#define EMAC_TRANS_INT_M (BIT(0)) -#define EMAC_TRANS_INT_V 1 -#define EMAC_TRANS_INT_S 0 +#define EMAC_DMAOPERATION_MODE_REG (DR_REG_EMAC_BASE + 0x0018) +/* EMAC_DIS_DROP_TCPIP_ERR_FRAM : R/W ;bitpos:[26] ;default: 1'h0 ; */ +/*description: When this bit is set the MAC does not drop the frames which + only have errors detected by the Receive Checksum engine.When this bit is reset all error frames are dropped if the Fwd_Err_Frame bit is reset.*/ +#define EMAC_DIS_DROP_TCPIP_ERR_FRAM (BIT(26)) +#define EMAC_DIS_DROP_TCPIP_ERR_FRAM_M (BIT(26)) +#define EMAC_DIS_DROP_TCPIP_ERR_FRAM_V 0x1 +#define EMAC_DIS_DROP_TCPIP_ERR_FRAM_S 26 +/* EMAC_RX_STORE_FORWARD : R/W ;bitpos:[25] ;default: 1'h0 ; */ +/*description: When this bit is set the MTL reads a frame from the Rx FIFO + only after the complete frame has been written to it.*/ +#define EMAC_RX_STORE_FORWARD (BIT(25)) +#define EMAC_RX_STORE_FORWARD_M (BIT(25)) +#define EMAC_RX_STORE_FORWARD_V 0x1 +#define EMAC_RX_STORE_FORWARD_S 25 +/* EMAC_DIS_FLUSH_RECV_FRAMES : R/W ;bitpos:[24] ;default: 1'h0 ; */ +/*description: When this bit is set the Rx DMA does not flush any frames because + of the unavailability of receive descriptors or buffers.*/ +#define EMAC_DIS_FLUSH_RECV_FRAMES (BIT(24)) +#define EMAC_DIS_FLUSH_RECV_FRAMES_M (BIT(24)) +#define EMAC_DIS_FLUSH_RECV_FRAMES_V 0x1 +#define EMAC_DIS_FLUSH_RECV_FRAMES_S 24 +/* EMAC_TX_STR_FWD : R/W ;bitpos:[21] ;default: 1'h0 ; */ +/*description: When this bit is set transmission starts when a full frame resides + in the MTL Transmit FIFO. When this bit is set the Tx_Thresh_Ctrl values specified in Tx_Thresh_Ctrl are ignored.*/ +#define EMAC_TX_STR_FWD (BIT(21)) +#define EMAC_TX_STR_FWD_M (BIT(21)) +#define EMAC_TX_STR_FWD_V 0x1 +#define EMAC_TX_STR_FWD_S 21 +/* EMAC_FLUSH_TX_FIFO : R_WS_SC ;bitpos:[20] ;default: 1'h0 ; */ +/*description: When this bit is set the transmit FIFO controller logic is reset + to its default values and thus all data in the Tx FIFO is lost or flushed. This bit is cleared internally when the flushing operation is complete.*/ +#define EMAC_FLUSH_TX_FIFO (BIT(20)) +#define EMAC_FLUSH_TX_FIFO_M (BIT(20)) +#define EMAC_FLUSH_TX_FIFO_V 0x1 +#define EMAC_FLUSH_TX_FIFO_S 20 +/* EMAC_TX_THRESH_CTRL : R/W ;bitpos:[16:14] ;default: 3'h0 ; */ +/*description: These bits control the threshold level of the MTL Transmit FIFO. + Transmission starts when the frame size within the MTL Transmit FIFO is larger than the threshold. In addition full frames with a length less than the threshold are also transmitted. These bits are used only when Tx_Str_fwd is reset. 3'b000: 64 3'b001: 128 3'b010: 192 3'b011: 256 3'b100: 40 3'b101: 32 3'b110: 24 3'b111: 16 .*/ +#define EMAC_TX_THRESH_CTRL 0x00000007 +#define EMAC_TX_THRESH_CTRL_M ((EMAC_TX_THRESH_CTRL_V)<<(EMAC_TX_THRESH_CTRL_S)) +#define EMAC_TX_THRESH_CTRL_V 0x7 +#define EMAC_TX_THRESH_CTRL_S 14 +/* EMAC_START_STOP_TRANSMISSION_COMMAND : R/W ;bitpos:[13] ;default: 1'h0 ; */ +/*description: When this bit is set transmission is placed in the Running state + and the DMA checks the Transmit List at the current position for a frame to be transmitted.When this bit is reset the transmission process is placed in the Stopped state after completing the transmission of the current frame.*/ +#define EMAC_START_STOP_TRANSMISSION_COMMAND (BIT(13)) +#define EMAC_START_STOP_TRANSMISSION_COMMAND_M (BIT(13)) +#define EMAC_START_STOP_TRANSMISSION_COMMAND_V 0x1 +#define EMAC_START_STOP_TRANSMISSION_COMMAND_S 13 +/* EMAC_FWD_ERR_FRAME : R/W ;bitpos:[7] ;default: 1'h0 ; */ +/*description: When this bit is reset the Rx FIFO drops frames with error status + (CRC error collision error giant frame watchdog timeout or overflow).*/ +#define EMAC_FWD_ERR_FRAME (BIT(7)) +#define EMAC_FWD_ERR_FRAME_M (BIT(7)) +#define EMAC_FWD_ERR_FRAME_V 0x1 +#define EMAC_FWD_ERR_FRAME_S 7 +/* EMAC_FWD_UNDER_GF : R/W ;bitpos:[6] ;default: 1'h0 ; */ +/*description: When set the Rx FIFO forwards Undersized frames (that is frames + with no Error and length less than 64 bytes) including pad-bytes and CRC.*/ +#define EMAC_FWD_UNDER_GF (BIT(6)) +#define EMAC_FWD_UNDER_GF_M (BIT(6)) +#define EMAC_FWD_UNDER_GF_V 0x1 +#define EMAC_FWD_UNDER_GF_S 6 +/* EMAC_DROP_GFRM : R/W ;bitpos:[5] ;default: 1'h0 ; */ +/*description: When set the MAC drops the received giant frames in the Rx FIFO + that is frames that are larger than the computed giant frame limit.*/ +#define EMAC_DROP_GFRM (BIT(5)) +#define EMAC_DROP_GFRM_M (BIT(5)) +#define EMAC_DROP_GFRM_V 0x1 +#define EMAC_DROP_GFRM_S 5 +/* EMAC_RX_THRESH_CTRL : R/W ;bitpos:[4:3] ;default: 2'h0 ; */ +/*description: These two bits control the threshold level of the MTL Receive + FIFO. Transfer (request) to DMA starts when the frame size within the MTL Receive FIFO is larger than the threshold. 2'b00: 64, 2'b01: 32, 2'b10: 96, 2'b11: 128 .*/ +#define EMAC_RX_THRESH_CTRL 0x00000003 +#define EMAC_RX_THRESH_CTRL_M ((EMAC_RX_THRESH_CTRL_V)<<(EMAC_RX_THRESH_CTRL_S)) +#define EMAC_RX_THRESH_CTRL_V 0x3 +#define EMAC_RX_THRESH_CTRL_S 3 +/* EMAC_OPT_SECOND_FRAME : R/W ;bitpos:[2] ;default: 1'h0 ; */ +/*description: When this bit is set it instructs the DMA to process the second + frame of the Transmit data even before the status for the first frame is obtained.*/ +#define EMAC_OPT_SECOND_FRAME (BIT(2)) +#define EMAC_OPT_SECOND_FRAME_M (BIT(2)) +#define EMAC_OPT_SECOND_FRAME_V 0x1 +#define EMAC_OPT_SECOND_FRAME_S 2 +/* EMAC_START_STOP_RX : R/W ;bitpos:[1] ;default: 1'h0 ; */ +/*description: When this bit is set the Receive process is placed in the Running + state. The DMA attempts to acquire the descriptor from the Receive list and processes the incoming frames.When this bit is cleared the Rx DMA operation is stopped after the transfer of the current frame.*/ +#define EMAC_START_STOP_RX (BIT(1)) +#define EMAC_START_STOP_RX_M (BIT(1)) +#define EMAC_START_STOP_RX_V 0x1 +#define EMAC_START_STOP_RX_S 1 -#define EMAC_DMAOPERATION_MODE_REG (REG_EMAC_BASE + 0x0018) -#define EMAC_DIS_DROP_TCPIP_CHKSUM_ERR_FRAM (BIT(26)) -#define EMAC_DIS_DROP_TCPIP_CHKSUM_ERR_FRAM_M (BIT(26)) -#define EMAC_DIS_DROP_TCPIP_CHKSUM_ERR_FRAM_V 1 -#define EMAC_DIS_DROP_TCPIP_CHKSUM_ERR_FRAM_S 26 -#define EMAC_RECV_STORE_FORWARD (BIT(25)) -#define EMAC_RECV_STORE_FORWARD_M (BIT(25)) -#define EMAC_RECV_STORE_FORWARD_V 1 -#define EMAC_RECV_STORE_FORWARD_S 25 -#define EMAC_DIS_FLUSH_RECV_FRAMES (BIT(24)) -#define EMAC_DIS_FLUSH_RECV_FRAMES_M (BIT(24)) -#define EMAC_DIS_FLUSH_RECV_FRAMES_V 1 -#define EMAC_DIS_FLUSH_RECV_FRAMES_S 24 -#define EMAC_MSB_THRESHOLD_ACTIVATING_FLOW_CONTROL (BIT(23)) -#define EMAC_MSB_THRESHOLD_ACTIVATING_FLOW_CONTROL_M (BIT(23)) -#define EMAC_MSB_THRESHOLD_ACTIVATING_FLOW_CONTROL_V 1 -#define EMAC_MSB_THRESHOLD_ACTIVATING_FLOW_CONTROL_S 23 -#define EMAC_MSB_THRESHOLD_DEACTIVATING_FLOW_CONTROL (BIT(22)) -#define EMAC_MSB_THRESHOLD_DEACTIVATING_FLOW_CONTROL_M (BIT(22)) -#define EMAC_MSB_THRESHOLD_DEACTIVATING_FLOW_CONTROL_V 1 -#define EMAC_MSB_THRESHOLD_DEACTIVATING_FLOW_CONTROL_S 22 -#define EMAC_TRANSMIT_STORE_FORWARD (BIT(21)) -#define EMAC_TRANSMIT_STORE_FORWARD_M (BIT(21)) -#define EMAC_TRANSMIT_STORE_FORWARD_V 1 -#define EMAC_TRANSMIT_STORE_FORWARD_S 21 -#define EMAC_FLUSH_TRANSMIT_FIFO (BIT(20)) -#define EMAC_FLUSH_TRANSMIT_FIFO_M (BIT(20)) -#define EMAC_FLUSH_TRANSMIT_FIFO_V 1 -#define EMAC_FLUSH_TRANSMIT_FIFO_S 20 -#define EMAC_TRANSMIT_THRESHOLD_CONTROL 0x00000007 -#define EMAC_TRANSMIT_THRESHOLD_CONTROL_M (EMAC_TRANSMIT_THRESHOLD_CONTROL_V << EMAC_TRANSMIT_THRESHOLD_CONTROL_S) -#define EMAC_TRANSMIT_THRESHOLD_CONTROL_V 0x00000007 -#define EMAC_TRANSMIT_THRESHOLD_CONTROL_S 14 -#define EMAC_START_STOP_TRANSMISSION_COMMAND (BIT(13)) -#define EMAC_START_STOP_TRANSMISSION_COMMAND_M (BIT(13)) -#define EMAC_START_STOP_TRANSMISSION_COMMAND_V 1 -#define EMAC_START_STOP_TRANSMISSION_COMMAND_S 13 -#define EMAC_THRESHOLD_DEACTIVATING_FLOW_CONTROL 0x00000003 -#define EMAC_THRESHOLD_DEACTIVATING_FLOW_CONTROL_M (EMAC_THRESHOLD_DEACTIVATING_FLOW_CONTROL_V << EMAC_THRESHOLD_DEACTIVATING_FLOW_CONTROL_S) -#define EMAC_THRESHOLD_DEACTIVATING_FLOW_CONTROL_V 0x00000003 -#define EMAC_THRESHOLD_DEACTIVATING_FLOW_CONTROL_S 11 -#define EMAC_THRESHOLD_ACTIVATING_FLOW_CONTROL 0x00000003 -#define EMAC_THRESHOLD_ACTIVATING_FLOW_CONTROL_M (EMAC_THRESHOLD_ACTIVATING_FLOW_CONTROL_V << EMAC_THRESHOLD_ACTIVATING_FLOW_CONTROL_S) -#define EMAC_THRESHOLD_ACTIVATING_FLOW_CONTROL_V 0x00000003 -#define EMAC_THRESHOLD_ACTIVATING_FLOW_CONTROL_S 9 -#define EMAC_ENABLE_HW_FLOW_CONTROL (BIT(8)) -#define EMAC_ENABLE_HW_FLOW_CONTROL_M (BIT(8)) -#define EMAC_ENABLE_HW_FLOW_CONTROL_V 1 -#define EMAC_ENABLE_HW_FLOW_CONTROL_S 8 -#define EMAC_FORWARD_ERROR_FRAMES (BIT(7)) -#define EMAC_FORWARD_ERROR_FRAMES_M (BIT(7)) -#define EMAC_FORWARD_ERROR_FRAMES_V 1 -#define EMAC_FORWARD_ERROR_FRAMES_S 7 -#define EMAC_FORWARD_UNDERSIZED_GOOD_FRAMES (BIT(6)) -#define EMAC_FORWARD_UNDERSIZED_GOOD_FRAMES_M (BIT(6)) -#define EMAC_FORWARD_UNDERSIZED_GOOD_FRAMES_V 1 -#define EMAC_FORWARD_UNDERSIZED_GOOD_FRAMES_S 6 -#define EMAC_DROP_GIANT_FRAMES (BIT(5)) -#define EMAC_DROP_GIANT_FRAMES_M (BIT(5)) -#define EMAC_DROP_GIANT_FRAMES_V 1 -#define EMAC_DROP_GIANT_FRAMES_S 5 -#define EMAC_RECEIVE_THRESHOLD_CONTROL 0x00000003 -#define EMAC_RECEIVE_THRESHOLD_CONTROL_M (EMAC_RECEIVE_THRESHOLD_CONTROL_V << EMAC_RECEIVE_THRESHOLD_CONTROL_S) -#define EMAC_RECEIVE_THRESHOLD_CONTROL_V 0x00000003 -#define EMAC_RECEIVE_THRESHOLD_CONTROL_S 3 -#define EMAC_OPERATE_SECOND_FRAME (BIT(2)) -#define EMAC_OPERATE_SECOND_FRAME_M (BIT(2)) -#define EMAC_OPERATE_SECOND_FRAME_V 1 -#define EMAC_OPERATE_SECOND_FRAME_S 2 -#define EMAC_START_STOP_RECEIVE (BIT(1)) -#define EMAC_START_STOP_RECEIVE_M (BIT(1)) -#define EMAC_START_STOP_RECEIVE_V 1 -#define EMAC_START_STOP_RECEIVE_S 1 +#define EMAC_DMAIN_EN_REG (DR_REG_EMAC_BASE + 0x001C) +/* EMAC_DMAIN_NISE : R/W ;bitpos:[16] ;default: 1'h0 ; */ +/*description: When this bit is set normal interrupt summary is enabled. When + this bit is reset normal interrupt summary is disabled. This bit enables the following interrupts in Status Register: Bit[0]: Transmit Interrupt. Bit[2]: Transmit Buffer Unavailable. Bit[6]: Receive Interrupt. Bit[14]: Early Receive Interrupt.*/ +#define EMAC_DMAIN_NISE (BIT(16)) +#define EMAC_DMAIN_NISE_M (BIT(16)) +#define EMAC_DMAIN_NISE_V 0x1 +#define EMAC_DMAIN_NISE_S 16 +/* EMAC_DMAIN_AISE : R/W ;bitpos:[15] ;default: 1'h0 ; */ +/*description: When this bit is set abnormal interrupt summary is enabled. + When this bit is reset the abnormal interrupt summary is disabled. This bit enables the following interrupts in Status Register: Bit[1]: Transmit Process Stopped. Bit[3]: Transmit Jabber Timeout. Bit[4]: Receive Overflow. Bit[5]: Transmit Underflow. Bit[7]: Receive Buffer Unavailable. Bit[8]: Receive Process Stopped. Bit[9]: Receive Watchdog Timeout. Bit[10]: Early Transmit Interrupt. Bit[13]: Fatal Bus Error.*/ +#define EMAC_DMAIN_AISE (BIT(15)) +#define EMAC_DMAIN_AISE_M (BIT(15)) +#define EMAC_DMAIN_AISE_V 0x1 +#define EMAC_DMAIN_AISE_S 15 +/* EMAC_DMAIN_ERIE : R/W ;bitpos:[14] ;default: 1'h0 ; */ +/*description: When this bit is set with Normal Interrupt Summary Enable (Bit[16]) + the Early Receive Interrupt is enabled. When this bit is reset the Early Receive Interrupt is disabled.*/ +#define EMAC_DMAIN_ERIE (BIT(14)) +#define EMAC_DMAIN_ERIE_M (BIT(14)) +#define EMAC_DMAIN_ERIE_V 0x1 +#define EMAC_DMAIN_ERIE_S 14 +/* EMAC_DMAIN_FBEE : R/W ;bitpos:[13] ;default: 1'h0 ; */ +/*description: When this bit is set with Abnormal Interrupt Summary Enable (Bit[15]) + the Fatal Bus Error Interrupt is enabled. When this bit is reset the Fatal Bus Error Enable Interrupt is disabled.*/ +#define EMAC_DMAIN_FBEE (BIT(13)) +#define EMAC_DMAIN_FBEE_M (BIT(13)) +#define EMAC_DMAIN_FBEE_V 0x1 +#define EMAC_DMAIN_FBEE_S 13 +/* EMAC_DMAIN_ETIE : R/W ;bitpos:[10] ;default: 1'h0 ; */ +/*description: When this bit is set with an Abnormal Interrupt Summary Enable + (Bit[15]) the Early Transmit Interrupt is enabled. When this bit is reset the Early Transmit Interrupt is disabled.*/ +#define EMAC_DMAIN_ETIE (BIT(10)) +#define EMAC_DMAIN_ETIE_M (BIT(10)) +#define EMAC_DMAIN_ETIE_V 0x1 +#define EMAC_DMAIN_ETIE_S 10 +/* EMAC_DMAIN_RWTE : R/W ;bitpos:[9] ;default: 1'h0 ; */ +/*description: When this bit is set with Abnormal Interrupt Summary Enable (Bit[15]) + the Receive Watchdog Timeout Interrupt is enabled. When this bit is reset the Receive Watchdog Timeout Interrupt is disabled.*/ +#define EMAC_DMAIN_RWTE (BIT(9)) +#define EMAC_DMAIN_RWTE_M (BIT(9)) +#define EMAC_DMAIN_RWTE_V 0x1 +#define EMAC_DMAIN_RWTE_S 9 +/* EMAC_DMAIN_RSE : R/W ;bitpos:[8] ;default: 1'h0 ; */ +/*description: When this bit is set with Abnormal Interrupt Summary Enable (Bit[15]) + the Receive Stopped Interrupt is enabled. When this bit is reset the Receive Stopped Interrupt is disabled.*/ +#define EMAC_DMAIN_RSE (BIT(8)) +#define EMAC_DMAIN_RSE_M (BIT(8)) +#define EMAC_DMAIN_RSE_V 0x1 +#define EMAC_DMAIN_RSE_S 8 +/* EMAC_DMAIN_RBUE : R/W ;bitpos:[7] ;default: 1'h0 ; */ +/*description: When this bit is set with Abnormal Interrupt Summary Enable (Bit[15]) + the Receive Buffer Unavailable Interrupt is enabled. When this bit is reset the Receive Buffer Unavailable Interrupt is disabled.*/ +#define EMAC_DMAIN_RBUE (BIT(7)) +#define EMAC_DMAIN_RBUE_M (BIT(7)) +#define EMAC_DMAIN_RBUE_V 0x1 +#define EMAC_DMAIN_RBUE_S 7 +/* EMAC_DMAIN_RIE : R/W ;bitpos:[6] ;default: 1'h0 ; */ +/*description: When this bit is set with Normal Interrupt Summary Enable (Bit[16]) + the Receive Interrupt is enabled. When this bit is reset the Receive Interrupt is disabled.*/ +#define EMAC_DMAIN_RIE (BIT(6)) +#define EMAC_DMAIN_RIE_M (BIT(6)) +#define EMAC_DMAIN_RIE_V 0x1 +#define EMAC_DMAIN_RIE_S 6 +/* EMAC_DMAIN_UIE : R/W ;bitpos:[5] ;default: 1'h0 ; */ +/*description: When this bit is set with Abnormal Interrupt Summary Enable (Bit[15]) + the Transmit Underflow Interrupt is enabled. When this bit is reset the Underflow Interrupt is disabled.*/ +#define EMAC_DMAIN_UIE (BIT(5)) +#define EMAC_DMAIN_UIE_M (BIT(5)) +#define EMAC_DMAIN_UIE_V 0x1 +#define EMAC_DMAIN_UIE_S 5 +/* EMAC_DMAIN_OIE : R/W ;bitpos:[4] ;default: 1'h0 ; */ +/*description: When this bit is set with Abnormal Interrupt Summary Enable (Bit[15]) + the Receive Overflow Interrupt is enabled. When this bit is reset the Overflow Interrupt is disabled.*/ +#define EMAC_DMAIN_OIE (BIT(4)) +#define EMAC_DMAIN_OIE_M (BIT(4)) +#define EMAC_DMAIN_OIE_V 0x1 +#define EMAC_DMAIN_OIE_S 4 +/* EMAC_DMAIN_TJTE : R/W ;bitpos:[3] ;default: 1'h0 ; */ +/*description: When this bit is set with Abnormal Interrupt Summary Enable (Bit[15]) + the Transmit Jabber Timeout Interrupt is enabled. When this bit is reset the Transmit Jabber Timeout Interrupt is disabled.*/ +#define EMAC_DMAIN_TJTE (BIT(3)) +#define EMAC_DMAIN_TJTE_M (BIT(3)) +#define EMAC_DMAIN_TJTE_V 0x1 +#define EMAC_DMAIN_TJTE_S 3 +/* EMAC_DMAIN_TBUE : R/W ;bitpos:[2] ;default: 1'h0 ; */ +/*description: When this bit is set with Normal Interrupt Summary Enable (Bit + 16) the Transmit Buffer Unavailable Interrupt is enabled. When this bit is reset the Transmit Buffer Unavailable Interrupt is Disabled.*/ +#define EMAC_DMAIN_TBUE (BIT(2)) +#define EMAC_DMAIN_TBUE_M (BIT(2)) +#define EMAC_DMAIN_TBUE_V 0x1 +#define EMAC_DMAIN_TBUE_S 2 +/* EMAC_DMAIN_TSE : R/W ;bitpos:[1] ;default: 1'h0 ; */ +/*description: When this bit is set with Abnormal Interrupt Summary Enable (Bit[15]) + the Transmission Stopped Interrupt is enabled. When this bit is reset the Transmission Stopped Interrupt is disabled.*/ +#define EMAC_DMAIN_TSE (BIT(1)) +#define EMAC_DMAIN_TSE_M (BIT(1)) +#define EMAC_DMAIN_TSE_V 0x1 +#define EMAC_DMAIN_TSE_S 1 +/* EMAC_DMAIN_TIE : R/W ;bitpos:[0] ;default: 1'h0 ; */ +/*description: When this bit is set with Normal Interrupt Summary Enable (Bit[16]) + the Transmit Interrupt is enabled. When this bit is reset the Transmit Interrupt is disabled.*/ +#define EMAC_DMAIN_TIE (BIT(0)) +#define EMAC_DMAIN_TIE_M (BIT(0)) +#define EMAC_DMAIN_TIE_V 0x1 +#define EMAC_DMAIN_TIE_S 0 -#define EMAC_DMAINTERRUPT_EN_REG (REG_EMAC_BASE + 0x001C) -#define EMAC_NORMAL_INTERRUPT_SUMMARY_ENABLE (BIT(16)) -#define EMAC_NORMAL_INTERRUPT_SUMMARY_ENABLE_M (BIT(16)) -#define EMAC_NORMAL_INTERRUPT_SUMMARY_ENABLE_V 1 -#define EMAC_NORMAL_INTERRUPT_SUMMARY_ENABLE_S 16 -#define EMAC_ABNORMAL_INTERRUPT_SUMMARY_ENABLE (BIT(15)) -#define EMAC_ABNORMAL_INTERRUPT_SUMMARY_ENABLE_M (BIT(15)) -#define EMAC_ABNORMAL_INTERRUPT_SUMMARY_ENABLE_V 1 -#define EMAC_ABNORMAL_INTERRUPT_SUMMARY_ENABLE_S 15 -#define EMAC_EARLY_RECEIVE_INTERRUPT_ENABLE (BIT(14)) -#define EMAC_EARLY_RECEIVE_INTERRUPT_ENABLE_M (BIT(14)) -#define EMAC_EARLY_RECEIVE_INTERRUPT_ENABLE_V 1 -#define EMAC_EARLY_RECEIVE_INTERRUPT_ENABLE_S 14 -#define EMAC_FATAL_BUS_ERROR_ENABLE (BIT(13)) -#define EMAC_FATAL_BUS_ERROR_ENABLE_M (BIT(13)) -#define EMAC_FATAL_BUS_ERROR_ENABLE_V 1 -#define EMAC_FATAL_BUS_ERROR_ENABLE_S 13 -#define EMAC_EARLY_TRANSMIT_INTERRUPT_ENABLE (BIT(10)) -#define EMAC_EARLY_TRANSMIT_INTERRUPT_ENABLE_M (BIT(10)) -#define EMAC_EARLY_TRANSMIT_INTERRUPT_ENABLE_V 1 -#define EMAC_EARLY_TRANSMIT_INTERRUPT_ENABLE_S 10 -#define EMAC_RECEIVE_WATCHDOG_TIMEOUT_ENABLE (BIT(9)) -#define EMAC_RECEIVE_WATCHDOG_TIMEOUT_ENABLE_M (BIT(9)) -#define EMAC_RECEIVE_WATCHDOG_TIMEOUT_ENABLE_V 1 -#define EMAC_RECEIVE_WATCHDOG_TIMEOUT_ENABLE_S 9 -#define EMAC_RECEIVE_STOPPED_ENABLE (BIT(8)) -#define EMAC_RECEIVE_STOPPED_ENABLE_M (BIT(8)) -#define EMAC_RECEIVE_STOPPED_ENABLE_V 1 -#define EMAC_RECEIVE_STOPPED_ENABLE_S 8 -#define EMAC_RECEIVE_BUFFER_UNAVAILABLE_ENABLE (BIT(7)) -#define EMAC_RECEIVE_BUFFER_UNAVAILABLE_ENABLE_M (BIT(7)) -#define EMAC_RECEIVE_BUFFER_UNAVAILABLE_ENABLE_V 1 -#define EMAC_RECEIVE_BUFFER_UNAVAILABLE_ENABLE_S 7 -#define EMAC_RECEIVE_INTERRUPT_ENABLE (BIT(6)) -#define EMAC_RECEIVE_INTERRUPT_ENABLE_M (BIT(6)) -#define EMAC_RECEIVE_INTERRUPT_ENABLE_V 1 -#define EMAC_RECEIVE_INTERRUPT_ENABLE_S 6 -#define EMAC_UNDERFLOW_INTERRUPT_ENABLE (BIT(5)) -#define EMAC_UNDERFLOW_INTERRUPT_ENABLE_M (BIT(5)) -#define EMAC_UNDERFLOW_INTERRUPT_ENABLE_V 1 -#define EMAC_UNDERFLOW_INTERRUPT_ENABLE_S 5 -#define EMAC_OVERFLOW_INTERRUPT_ENABLE (BIT(4)) -#define EMAC_OVERFLOW_INTERRUPT_ENABLE_M (BIT(4)) -#define EMAC_OVERFLOW_INTERRUPT_ENABLE_V 1 -#define EMAC_OVERFLOW_INTERRUPT_ENABLE_S 4 -#define EMAC_TRANSMIT_JABBER_TIMEOUT_ENABLE (BIT(3)) -#define EMAC_TRANSMIT_JABBER_TIMEOUT_ENABLE_M (BIT(3)) -#define EMAC_TRANSMIT_JABBER_TIMEOUT_ENABLE_V 1 -#define EMAC_TRANSMIT_JABBER_TIMEOUT_ENABLE_S 3 -#define EMAC_TRANSMIT_BUFFER_UNAVAILABLE_ENABLE (BIT(2)) -#define EMAC_TRANSMIT_BUFFER_UNAVAILABLE_ENABLE_M (BIT(2)) -#define EMAC_TRANSMIT_BUFFER_UNAVAILABLE_ENABLE_V 1 -#define EMAC_TRANSMIT_BUFFER_UNAVAILABLE_ENABLE_S 2 -#define EMAC_TRANSMIT_STOPPED_ENABLE (BIT(1)) -#define EMAC_TRANSMIT_STOPPED_ENABLE_M (BIT(1)) -#define EMAC_TRANSMIT_STOPPED_ENABLE_V 1 -#define EMAC_TRANSMIT_STOPPED_ENABLE_S 1 -#define EMAC_TRANSMIT_INTERRUPT_ENABLE (BIT(0)) -#define EMAC_TRANSMIT_INTERRUPT_ENABLE_M (BIT(0)) -#define EMAC_TRANSMIT_INTERRUPT_ENABLE_V 1 -#define EMAC_TRANSMIT_INTERRUPT_ENABLE_S 0 +#define EMAC_DMAMISSEDFR_REG (DR_REG_EMAC_BASE + 0x0020) +/* EMAC_OVERFLOW_BFOC : R_SS_RC ;bitpos:[28] ;default: 1'h0 ; */ +/*description: This bit is set every time the Overflow Frame Counter (Bits[27:17]) + overflows that is the Rx FIFO overflows with the overflow frame counter at maximum value. In such a scenario the overflow frame counter is reset to all-zeros and this bit indicates that the rollover happened.*/ +#define EMAC_OVERFLOW_BFOC (BIT(28)) +#define EMAC_OVERFLOW_BFOC_M (BIT(28)) +#define EMAC_OVERFLOW_BFOC_V 0x1 +#define EMAC_OVERFLOW_BFOC_S 28 +/* EMAC_OVERFLOW_FC : R_SS_RC ;bitpos:[27:17] ;default: 11'h0 ; */ +/*description: This field indicates the number of frames missed by the application. + This counter is incremented each time the MTL FIFO overflows. The counter is cleared when this register is read.*/ +#define EMAC_OVERFLOW_FC 0x000007FF +#define EMAC_OVERFLOW_FC_M ((EMAC_OVERFLOW_FC_V)<<(EMAC_OVERFLOW_FC_S)) +#define EMAC_OVERFLOW_FC_V 0x7FF +#define EMAC_OVERFLOW_FC_S 17 +/* EMAC_OVERFLOW_BMFC : R_SS_RC ;bitpos:[16] ;default: 1'h0 ; */ +/*description: This bit is set every time Missed Frame Counter (Bits[15:0]) + overflows that is the DMA discards an incoming frame because of the Host Receive Buffer being unavailable with the missed frame counter at maximum value. In such a scenario the Missed frame counter is reset to all-zeros and this bit indicates that the rollover happened.*/ +#define EMAC_OVERFLOW_BMFC (BIT(16)) +#define EMAC_OVERFLOW_BMFC_M (BIT(16)) +#define EMAC_OVERFLOW_BMFC_V 0x1 +#define EMAC_OVERFLOW_BMFC_S 16 +/* EMAC_MISSED_FC : R_SS_RC ;bitpos:[15:0] ;default: 16'h0 ; */ +/*description: This field indicates the number of frames missed by the controller + because of the Host Receive Buffer being unavailable. This counter is incremented each time the DMA discards an incoming frame. The counter is cleared when this register is read.*/ +#define EMAC_MISSED_FC 0x0000FFFF +#define EMAC_MISSED_FC_M ((EMAC_MISSED_FC_V)<<(EMAC_MISSED_FC_S)) +#define EMAC_MISSED_FC_V 0xFFFF +#define EMAC_MISSED_FC_S 0 -#define EMAC_DMAMISSEDFR_REG (REG_EMAC_BASE + 0x0020) -#define EMAC_OVERFLOW_BIT_FIFO_OVERFLOW_COUNTER (BIT(28)) -#define EMAC_OVERFLOW_BIT_FIFO_OVERFLOW_COUNTER_M (BIT(28)) -#define EMAC_OVERFLOW_BIT_FIFO_OVERFLOW_COUNTER_V 1 -#define EMAC_OVERFLOW_BIT_FIFO_OVERFLOW_COUNTER_S 28 -#define EMAC_OVERFLOW_FRAME_COUNTER 0x000007FF -#define EMAC_OVERFLOW_FRAME_COUNTER_M (EMAC_OVERFLOW_FRAME_COUNTER_V << EMAC_OVERFLOW_FRAME_COUNTER_S) -#define EMAC_OVERFLOW_FRAME_COUNTER_V 0x000007FF -#define EMAC_OVERFLOW_FRAME_COUNTER_S 17 -#define EMAC_OVERFLOW_BIT_MISSED_FRAME_COUNTER (BIT(16)) -#define EMAC_OVERFLOW_BIT_MISSED_FRAME_COUNTER_M (BIT(16)) -#define EMAC_OVERFLOW_BIT_MISSED_FRAME_COUNTER_V 1 -#define EMAC_OVERFLOW_BIT_MISSED_FRAME_COUNTER_S 16 -#define EMAC_MISSED_FRAME_COUNTER 0x0000FFFF -#define EMAC_MISSED_FRAME_COUNTER_M (EMAC_MISSED_FRAME_COUNTER_V << EMAC_MISSED_FRAME_COUNTER_S) -#define EMAC_MISSED_FRAME_COUNTER_V 0x0000FFFF -#define EMAC_MISSED_FRAME_COUNTER_S 0 +#define EMAC_DMARINTWDTIMER_REG (DR_REG_EMAC_BASE + 0x0024) +/* EMAC_RIWTC : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: This bit indicates the number of system clock cycles multiplied + by 256 for which the watchdog timer is set. The watchdog timer gets triggered with the programmed value after the Rx DMA completes the transfer of a frame for which the RI(RECV_INT) status bit is not set because of the setting in the corresponding descriptor RDES1[31]. When the watchdog timer runs out the RI bit is set and the timer is stopped. The watchdog timer is reset when the RI bit is set high because of automatic setting of RI as per RDES1[31] of any received frame.*/ +#define EMAC_RIWTC 0x000000FF +#define EMAC_RIWTC_M ((EMAC_RIWTC_V)<<(EMAC_RIWTC_S)) +#define EMAC_RIWTC_V 0xFF +#define EMAC_RIWTC_S 0 -#define EMAC_DMARECEIVE_INTERRUPT_WATCHDOG_TIMER_REG (REG_EMAC_BASE + 0x0024) -#define EMAC_RI_WATCHDOG_TIMER_COUNT 0x000000FF -#define EMAC_RI_WATCHDOG_TIMER_COUNT_M (EMAC_RI_WATCHDOG_TIMER_COUNT_V << EMAC_RI_WATCHDOG_TIMER_COUNT_S) -#define EMAC_RI_WATCHDOG_TIMER_COUNT_V 0x000000FF -#define EMAC_RI_WATCHDOG_TIMER_COUNT_S 0 +#define EMAC_DMATXCURRDESC_REG (DR_REG_EMAC_BASE + 0x0048) +/* EMAC_TRANS_DSCR_ADDR_PTR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: The address of the current receive descriptor list. Cleared on + Reset.Pointer updated by the DMA during operation.*/ +#define EMAC_TRANS_DSCR_ADDR_PTR 0xFFFFFFFF +#define EMAC_TRANS_DSCR_ADDR_PTR_M ((EMAC_TRANS_DSCR_ADDR_PTR_V)<<(EMAC_TRANS_DSCR_ADDR_PTR_S)) +#define EMAC_TRANS_DSCR_ADDR_PTR_V 0xFFFFFFFF +#define EMAC_TRANS_DSCR_ADDR_PTR_S 0 -#define EMAC_DMATXCURRDESC_REG (REG_EMAC_BASE + 0x0048) -#define EMAC_HOST_TRANSMIT_DESCRIPTOR_ADDRESS_POINTER 0xFFFFFFFF -#define EMAC_HOST_TRANSMIT_DESCRIPTOR_ADDRESS_POINTER_M (EMAC_HOST_TRANSMIT_DESCRIPTOR_ADDRESS_POINTER_V << EMAC_HOST_TRANSMIT_DESCRIPTOR_ADDRESS_POINTER_S) -#define EMAC_HOST_TRANSMIT_DESCRIPTOR_ADDRESS_POINTER_V 0xFFFFFFFF -#define EMAC_HOST_TRANSMIT_DESCRIPTOR_ADDRESS_POINTER_S 0 +#define EMAC_DMARXCURRDESC_REG (DR_REG_EMAC_BASE + 0x004C) +/* EMAC_RECV_DSCR_ADDR_PTR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: The address of the current receive descriptor list. Cleared on + Reset.Pointer updated by the DMA during operation.*/ +#define EMAC_RECV_DSCR_ADDR_PTR 0xFFFFFFFF +#define EMAC_RECV_DSCR_ADDR_PTR_M ((EMAC_RECV_DSCR_ADDR_PTR_V)<<(EMAC_RECV_DSCR_ADDR_PTR_S)) +#define EMAC_RECV_DSCR_ADDR_PTR_V 0xFFFFFFFF +#define EMAC_RECV_DSCR_ADDR_PTR_S 0 -#define EMAC_DMARXCURRDESC_REG (REG_EMAC_BASE + 0x004C) -#define EMAC_HOST_RECEIVE_DESCRIPTOR_ADDRESS_POINTER 0xFFFFFFFF -#define EMAC_HOST_RECEIVE_DESCRIPTOR_ADDRESS_POINTER_M (EMAC_HOST_RECEIVE_DESCRIPTOR_ADDRESS_POINTER_V << EMAC_HOST_RECEIVE_DESCRIPTOR_ADDRESS_POINTER_S) -#define EMAC_HOST_RECEIVE_DESCRIPTOR_ADDRESS_POINTER_V 0xFFFFFFFF -#define EMAC_HOST_RECEIVE_DESCRIPTOR_ADDRESS_POINTER_S 0 +#define EMAC_DMATXCURRADDR_BUF_REG (DR_REG_EMAC_BASE + 0x0050) +/* EMAC_TRANS_BUFF_ADDR_PTR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: The address of the current receive descriptor list. Cleared on + Reset.Pointer updated by the DMA during operation.*/ +#define EMAC_TRANS_BUFF_ADDR_PTR 0xFFFFFFFF +#define EMAC_TRANS_BUFF_ADDR_PTR_M ((EMAC_TRANS_BUFF_ADDR_PTR_V)<<(EMAC_TRANS_BUFF_ADDR_PTR_S)) +#define EMAC_TRANS_BUFF_ADDR_PTR_V 0xFFFFFFFF +#define EMAC_TRANS_BUFF_ADDR_PTR_S 0 -#define EMAC_DMATXCURRADDR_BUF_REG (REG_EMAC_BASE + 0x0050) -#define EMAC_HOST_TRANSMIT_BUFFER_ADDRESS_POINTER 0xFFFFFFFF -#define EMAC_HOST_TRANSMIT_BUFFER_ADDRESS_POINTER_M (EMAC_HOST_TRANSMIT_BUFFER_ADDRESS_POINTER_V << EMAC_HOST_TRANSMIT_BUFFER_ADDRESS_POINTER_S) -#define EMAC_HOST_TRANSMIT_BUFFER_ADDRESS_POINTER_V 0xFFFFFFFF -#define EMAC_HOST_TRANSMIT_BUFFER_ADDRESS_POINTER_S 0 +#define EMAC_DMARXCURRADDR_BUF_REG (DR_REG_EMAC_BASE + 0x0054) +/* EMAC_RECV_BUFF_ADDR_PTR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: The address of the current receive descriptor list. Cleared on + Reset.Pointer updated by the DMA during operation.*/ +#define EMAC_RECV_BUFF_ADDR_PTR 0xFFFFFFFF +#define EMAC_RECV_BUFF_ADDR_PTR_M ((EMAC_RECV_BUFF_ADDR_PTR_V)<<(EMAC_RECV_BUFF_ADDR_PTR_S)) +#define EMAC_RECV_BUFF_ADDR_PTR_V 0xFFFFFFFF +#define EMAC_RECV_BUFF_ADDR_PTR_S 0 -#define EMAC_DMARXCURRADDR_BUF_REG (REG_EMAC_BASE + 0x0054) -#define EMAC_HOST_RECEIVE_BUFFER_ADDRESS_POINTER 0xFFFFFFFF -#define EMAC_HOST_RECEIVE_BUFFER_ADDRESS_POINTER_M (EMAC_HOST_RECEIVE_BUFFER_ADDRESS_POINTER_V << EMAC_HOST_RECEIVE_BUFFER_ADDRESS_POINTER_S) -#define EMAC_HOST_RECEIVE_BUFFER_ADDRESS_POINTER_V 0xFFFFFFFF -#define EMAC_HOST_RECEIVE_BUFFER_ADDRESS_POINTER_S 0 +#define EMAC_GMACCONFIG_REG (DR_REG_EMAC_BASE + 0x1000) +/* EMAC_SAIRC : R/W ;bitpos:[30:28] ;default: 3'h0 ; */ +/*description: This field controls the source address insertion or replacement + for all transmitted frames.Bit[30] specifies which MAC Address register (0 or 1) is used for source address insertion or replacement based on the values of Bits [29:28]: 2'b0x: The input signals mti_sa_ctrl_i and ati_sa_ctrl_i control the SA field generation. 2'b10: If Bit[30] is set to 0 the MAC inserts the content of the MAC Address 0 registers in the SA field of all transmitted frames. If Bit[30] is set to 1 the MAC inserts the content of the MAC Address 1 registers in the SA field of all transmitted frames. 2'b11: If Bit[30] is set to 0 the MAC replaces the content of the MAC Address 0 registers in the SA field of all transmitted frames. If Bit[30] is set to 1 the MAC replaces the content of the MAC Address 1 registers in the SA field of all transmitted frames.*/ +#define EMAC_SAIRC 0x00000007 +#define EMAC_SAIRC_M ((EMAC_SAIRC_V)<<(EMAC_SAIRC_S)) +#define EMAC_SAIRC_V 0x7 +#define EMAC_SAIRC_S 28 +/* EMAC_ASS2KP : R/W ;bitpos:[27] ;default: 1'h0 ; */ +/*description: When set the MAC considers all frames with up to 2 000 bytes + length as normal packets.When Bit[20] (JE) is not set the MAC considers all received frames of size more than 2K bytes as Giant frames. When this bit is reset and Bit[20] (JE) is not set the MAC considers all received frames of size more than 1 518 bytes (1 522 bytes for tagged) as Giant frames. When Bit[20] is set setting this bit has no effect on Giant Frame status.*/ +#define EMAC_ASS2KP (BIT(27)) +#define EMAC_ASS2KP_M (BIT(27)) +#define EMAC_ASS2KP_V 0x1 +#define EMAC_ASS2KP_S 27 +/* EMAC_EMACWATCHDOG : R/W ;bitpos:[23] ;default: 1'h0 ; */ +/*description: When this bit is set the MAC disables the watchdog timer on + the receiver. The MAC can receive frames of up to 16 383 bytes. When this bit is reset the MAC does not allow a receive frame which more than 2 048 bytes (10 240 if JE is set high) or the value programmed in Register (Watchdog Timeout Register). The MAC cuts off any bytes received after the watchdog limit number of bytes.*/ +#define EMAC_EMACWATCHDOG (BIT(23)) +#define EMAC_EMACWATCHDOG_M (BIT(23)) +#define EMAC_EMACWATCHDOG_V 0x1 +#define EMAC_EMACWATCHDOG_S 23 +/* EMAC_EMACJABBER : R/W ;bitpos:[22] ;default: 1'h0 ; */ +/*description: When this bit is set the MAC disables the jabber timer on the + transmitter. The MAC can transfer frames of up to 16 383 bytes. When this bit is reset the MAC cuts off the transmitter if the application sends out more than 2 048 bytes of data (10 240 if JE is set high) during Transmission.*/ +#define EMAC_EMACJABBER (BIT(22)) +#define EMAC_EMACJABBER_M (BIT(22)) +#define EMAC_EMACJABBER_V 0x1 +#define EMAC_EMACJABBER_S 22 +/* EMAC_EMACJUMBOFRAME : R/W ;bitpos:[20] ;default: 1'h0 ; */ +/*description: When this bit is set the MAC allows Jumbo frames of 9 018 bytes + (9 022 bytes for VLAN tagged frames) without reporting a giant frame error in the receive frame status.*/ +#define EMAC_EMACJUMBOFRAME (BIT(20)) +#define EMAC_EMACJUMBOFRAME_M (BIT(20)) +#define EMAC_EMACJUMBOFRAME_V 0x1 +#define EMAC_EMACJUMBOFRAME_S 20 +/* EMAC_EMACINTERFRAMEGAP : R/W ;bitpos:[19:17] ;default: 1'h0 ; */ +/*description: These bits control the minimum IFG between frames during transmission. + 3'b000: 96 bit times. 3'b001: 88 bit times. 3'b010: 80 bit times. 3'b111: 40 bit times. In the half-duplex mode the minimum IFG can be configured only for 64 bit times (IFG = 100). Lower values are not considered.*/ +#define EMAC_EMACINTERFRAMEGAP 0x00000007 +#define EMAC_EMACINTERFRAMEGAP_M ((EMAC_EMACINTERFRAMEGAP_V)<<(EMAC_EMACINTERFRAMEGAP_S)) +#define EMAC_EMACINTERFRAMEGAP_V 0x7 +#define EMAC_EMACINTERFRAMEGAP_S 17 +/* EMAC_EMACDISABLECRS : R/W ;bitpos:[16] ;default: 1'h0 ; */ +/*description: When set high this bit makes the MAC transmitter ignore the + MII CRS signal during frame transmission in the half-duplex mode. This request results in no errors generated because of Loss of Carrier or No Carrier during such transmission. When this bit is low the MAC transmitter generates such errors because of Carrier Sense and can even abort the transmissions.*/ +#define EMAC_EMACDISABLECRS (BIT(16)) +#define EMAC_EMACDISABLECRS_M (BIT(16)) +#define EMAC_EMACDISABLECRS_V 0x1 +#define EMAC_EMACDISABLECRS_S 16 +/* EMAC_EMACMII : R/W ;bitpos:[15] ;default: 1'h0 ; */ +/*description: This bit selects the Ethernet line speed. It should be set to + 1 for 10 or 100 Mbps operations.In 10 or 100 Mbps operations this bit along with FES(EMACFESPEED) bit it selects the exact linespeed. In the 10/100 Mbps-only operations the bit is always 1.*/ +#define EMAC_EMACMII (BIT(15)) +#define EMAC_EMACMII_M (BIT(15)) +#define EMAC_EMACMII_V 0x1 +#define EMAC_EMACMII_S 15 +/* EMAC_EMACFESPEED : R/W ;bitpos:[14] ;default: 1'h0 ; */ +/*description: This bit selects the speed in the MII RMII interface. 0: 10 Mbps. 1: 100 Mbps.*/ +#define EMAC_EMACFESPEED (BIT(14)) +#define EMAC_EMACFESPEED_M (BIT(14)) +#define EMAC_EMACFESPEED_V 0x1 +#define EMAC_EMACFESPEED_S 14 +/* EMAC_EMACRXOWN : R/W ;bitpos:[13] ;default: 1'h0 ; */ +/*description: When this bit is set the MAC disables the reception of frames + when the TX_EN is asserted in the half-duplex mode. When this bit is reset the MAC receives all packets that are given by the PHY while transmitting. This bit is not applicable if the MAC is operating in the full duplex mode.*/ +#define EMAC_EMACRXOWN (BIT(13)) +#define EMAC_EMACRXOWN_M (BIT(13)) +#define EMAC_EMACRXOWN_V 0x1 +#define EMAC_EMACRXOWN_S 13 +/* EMAC_EMACLOOPBACK : R/W ;bitpos:[12] ;default: 1'h0 ; */ +/*description: When this bit is set the MAC operates in the loopback mode MII. + The MII Receive clock input (CLK_RX) is required for the loopback to work properly because the transmit clock is not looped-back internally.*/ +#define EMAC_EMACLOOPBACK (BIT(12)) +#define EMAC_EMACLOOPBACK_M (BIT(12)) +#define EMAC_EMACLOOPBACK_V 0x1 +#define EMAC_EMACLOOPBACK_S 12 +/* EMAC_EMACDUPLEX : R/W ;bitpos:[11] ;default: 1'h0 ; */ +/*description: When this bit is set the MAC operates in the full-duplex mode + where it can transmit and receive simultaneously. This bit is read only with default value of 1'b1 in the full-duplex-mode.*/ +#define EMAC_EMACDUPLEX (BIT(11)) +#define EMAC_EMACDUPLEX_M (BIT(11)) +#define EMAC_EMACDUPLEX_V 0x1 +#define EMAC_EMACDUPLEX_S 11 +/* EMAC_EMACRXIPCOFFLOAD : R/W ;bitpos:[10] ;default: 1'h0 ; */ +/*description: When this bit is set the MAC calculates the 16-bit one's complement + of the one's complement sum of all received Ethernet frame payloads. It also checks whether the IPv4 Header checksum (assumed to be bytes 25/26 or 29/30 (VLAN-tagged) of the received Ethernet frame) is correct for the received frame and gives the status in the receive status word. The MAC also appends the 16-bit checksum calculated for the IP header datagram payload (bytes after the IPv4 header) and appends it to the Ethernet frame transferred to the application (when Type 2 COE is deselected). When this bit is reset this function is disabled.*/ +#define EMAC_EMACRXIPCOFFLOAD (BIT(10)) +#define EMAC_EMACRXIPCOFFLOAD_M (BIT(10)) +#define EMAC_EMACRXIPCOFFLOAD_V 0x1 +#define EMAC_EMACRXIPCOFFLOAD_S 10 +/* EMAC_EMACRETRY : R/W ;bitpos:[9] ;default: 1'h0 ; */ +/*description: When this bit is set the MAC attempts only one transmission. + When a collision occurs on the MII interface the MAC ignores the current frame transmission and reports a Frame Abort with excessive collision error in the transmit frame status. When this bit is reset the MAC attempts retries based on the settings of the BL field (Bits [6:5]). This bit is applicable only in the half-duplex Mode.*/ +#define EMAC_EMACRETRY (BIT(9)) +#define EMAC_EMACRETRY_M (BIT(9)) +#define EMAC_EMACRETRY_V 0x1 +#define EMAC_EMACRETRY_S 9 +/* EMAC_EMACPADCRCSTRIP : R/W ;bitpos:[7] ;default: 1'h0 ; */ +/*description: When this bit is set the MAC strips the Pad or FCS field on + the incoming frames only if the value of the length field is less than 1 536 bytes. All received frames with length field greater than or equal to 1 536 bytes are passed to the application without stripping the Pad or FCS field. When this bit is reset the MAC passes all incoming frames without modifying them to the Host.*/ +#define EMAC_EMACPADCRCSTRIP (BIT(7)) +#define EMAC_EMACPADCRCSTRIP_M (BIT(7)) +#define EMAC_EMACPADCRCSTRIP_V 0x1 +#define EMAC_EMACPADCRCSTRIP_S 7 +/* EMAC_EMACBACKOFFLIMIT : R/W ;bitpos:[6:5] ;default: 2'h0 ; */ +/*description: The Back-Off limit determines the random integer number (r) of + slot time delays (512 bit times for 10/100 Mbps) for which the MAC waits before rescheduling a transmission attempt during retries after a collision. This bit is applicable only in the half-duplex mode. 00: k= min (n 10). 01: k = min (n 8). 10: k = min (n 4). 11: k = min (n 1) n = retransmission attempt. The random integer r takes the value in the Range 0 ~ 2000.*/ +#define EMAC_EMACBACKOFFLIMIT 0x00000003 +#define EMAC_EMACBACKOFFLIMIT_M ((EMAC_EMACBACKOFFLIMIT_V)<<(EMAC_EMACBACKOFFLIMIT_S)) +#define EMAC_EMACBACKOFFLIMIT_V 0x3 +#define EMAC_EMACBACKOFFLIMIT_S 5 +/* EMAC_EMACDEFERRALCHECK : R/W ;bitpos:[4] ;default: 1'h0 ; */ +/*description: Deferral Check.*/ +#define EMAC_EMACDEFERRALCHECK (BIT(4)) +#define EMAC_EMACDEFERRALCHECK_M (BIT(4)) +#define EMAC_EMACDEFERRALCHECK_V 0x1 +#define EMAC_EMACDEFERRALCHECK_S 4 +/* EMAC_EMACTX : R/W ;bitpos:[3] ;default: 1'h0 ; */ +/*description: When this bit is set the transmit state machine of the MAC is + enabled for transmission on the MII. When this bit is reset the MAC transmit state machine is disabled after the completion of the transmission of the current frame and does not transmit any further frames.*/ +#define EMAC_EMACTX (BIT(3)) +#define EMAC_EMACTX_M (BIT(3)) +#define EMAC_EMACTX_V 0x1 +#define EMAC_EMACTX_S 3 +/* EMAC_EMACRX : R/W ;bitpos:[2] ;default: 1'h0 ; */ +/*description: When this bit is set the receiver state machine of the MAC is + enabled for receiving frames from the MII. When this bit is reset the MAC receive state machine is disabled after the completion of the reception of the current frame and does not receive any further frames from the MII.*/ +#define EMAC_EMACRX (BIT(2)) +#define EMAC_EMACRX_M (BIT(2)) +#define EMAC_EMACRX_V 0x1 +#define EMAC_EMACRX_S 2 +/* EMAC_PLTF : R/W ;bitpos:[1:0] ;default: 2'h0 ; */ +/*description: These bits control the number of preamble bytes that are added + to the beginning of every Transmit frame. The preamble reduction occurs only when the MAC is operating in the full-duplex mode.2'b00: 7 bytes of preamble. 2'b01: 5 bytes of preamble. 2'b10: 3 bytes of preamble.*/ +#define EMAC_PLTF 0x00000003 +#define EMAC_PLTF_M ((EMAC_PLTF_V)<<(EMAC_PLTF_S)) +#define EMAC_PLTF_V 0x3 +#define EMAC_PLTF_S 0 -#define EMAC_DMAHWFEATURE_REG (REG_EMAC_BASE + 0x0058) -#define EMAC_SELECTED_PHY_INTERFACE 0x00000007 -#define EMAC_SELECTED_PHY_INTERFACE_M (EMAC_SELECTED_PHY_INTERFACE_V << EMAC_SELECTED_PHY_INTERFACE_S) -#define EMAC_SELECTED_PHY_INTERFACE_V 0x00000007 -#define EMAC_SELECTED_PHY_INTERFACE_S 28 -#define EMAC_SOURCE_ADDRESS_VLAN_INSERTION (BIT(27)) -#define EMAC_SOURCE_ADDRESS_VLAN_INSERTION_M (BIT(27)) -#define EMAC_SOURCE_ADDRESS_VLAN_INSERTION_V 1 -#define EMAC_SOURCE_ADDRESS_VLAN_INSERTION_S 27 -#define EMAC_FLEXIBLE_PULSE_PER_SECOND_OUTPUT (BIT(26)) -#define EMAC_FLEXIBLE_PULSE_PER_SECOND_OUTPUT_M (BIT(26)) -#define EMAC_FLEXIBLE_PULSE_PER_SECOND_OUTPUT_V 1 -#define EMAC_FLEXIBLE_PULSE_PER_SECOND_OUTPUT_S 26 -#define EMAC_TIMESTAMPING_INTERNAL_SYSTEM_TIME (BIT(25)) -#define EMAC_TIMESTAMPING_INTERNAL_SYSTEM_TIME_M (BIT(25)) -#define EMAC_TIMESTAMPING_INTERNAL_SYSTEM_TIME_V 1 -#define EMAC_TIMESTAMPING_INTERNAL_SYSTEM_TIME_S 25 -#define EMAC_ENHANCED_DESCRIPTOR (BIT(24)) -#define EMAC_ENHANCED_DESCRIPTOR_M (BIT(24)) -#define EMAC_ENHANCED_DESCRIPTOR_V 1 -#define EMAC_ENHANCED_DESCRIPTOR_S 24 -#define EMAC_NUMBER_ADDITIONAL_TX_CHANNELS 0x00000003 -#define EMAC_NUMBER_ADDITIONAL_TX_CHANNELS_M (EMAC_NUMBER_ADDITIONAL_TX_CHANNELS_V << EMAC_NUMBER_ADDITIONAL_TX_CHANNELS_S) -#define EMAC_NUMBER_ADDITIONAL_TX_CHANNELS_V 0x00000003 -#define EMAC_NUMBER_ADDITIONAL_TX_CHANNELS_S 22 -#define EMAC_NUMBER_ADDITIONAL_RX_CHANNELS 0x00000003 -#define EMAC_NUMBER_ADDITIONAL_RX_CHANNELS_M (EMAC_NUMBER_ADDITIONAL_RX_CHANNELS_V << EMAC_NUMBER_ADDITIONAL_RX_CHANNELS_S) -#define EMAC_NUMBER_ADDITIONAL_RX_CHANNELS_V 0x00000003 -#define EMAC_NUMBER_ADDITIONAL_RX_CHANNELS_S 20 -#define EMAC_RXFIFOSIZE (BIT(19)) -#define EMAC_RXFIFOSIZE_M (BIT(19)) -#define EMAC_RXFIFOSIZE_V 1 -#define EMAC_RXFIFOSIZE_S 19 -#define EMAC_IP_CHECKSUM_OFFLOAD_TYPE2 (BIT(18)) -#define EMAC_IP_CHECKSUM_OFFLOAD_TYPE2_M (BIT(18)) -#define EMAC_IP_CHECKSUM_OFFLOAD_TYPE2_V 1 -#define EMAC_IP_CHECKSUM_OFFLOAD_TYPE2_S 18 -#define EMAC_IP_CHECKSUM_OFFLOAD_TYPE1 (BIT(17)) -#define EMAC_IP_CHECKSUM_OFFLOAD_TYPE1_M (BIT(17)) -#define EMAC_IP_CHECKSUM_OFFLOAD_TYPE1_V 1 -#define EMAC_IP_CHECKSUM_OFFLOAD_TYPE1_S 17 -#define EMAC_CHECKSUM_OFFLOAD_TX (BIT(16)) -#define EMAC_CHECKSUM_OFFLOAD_TX_M (BIT(16)) -#define EMAC_CHECKSUM_OFFLOAD_TX_V 1 -#define EMAC_CHECKSUM_OFFLOAD_TX_S 16 -#define EMAC_AV_FEATURE_SEL (BIT(15)) -#define EMAC_AV_FEATURE_SEL_M (BIT(15)) -#define EMAC_AV_FEATURE_SEL_V 1 -#define EMAC_AV_FEATURE_SEL_S 15 -#define EMAC_EEE_SEL (BIT(14)) -#define EMAC_EEE_SEL_M (BIT(14)) -#define EMAC_EEE_SEL_V 1 -#define EMAC_EEE_SEL_S 14 -#define EMAC_TSVER2_SEL (BIT(13)) -#define EMAC_TSVER2_SEL_M (BIT(13)) -#define EMAC_TSVER2_SEL_V 1 -#define EMAC_TSVER2_SEL_S 13 -#define EMAC_TSVER1_SEL (BIT(12)) -#define EMAC_TSVER1_SEL_M (BIT(12)) -#define EMAC_TSVER1_SEL_V 1 -#define EMAC_TSVER1_SEL_S 12 -#define EMAC_MMC_SEL (BIT(11)) -#define EMAC_MMC_SEL_M (BIT(11)) -#define EMAC_MMC_SEL_V 1 -#define EMAC_MMC_SEL_S 11 -#define EMAC_MGK_SEL (BIT(10)) -#define EMAC_MGK_SEL_M (BIT(10)) -#define EMAC_MGK_SEL_V 1 -#define EMAC_MGK_SEL_S 10 -#define EMAC_RWK_SEL (BIT(9)) -#define EMAC_RWK_SEL_M (BIT(9)) -#define EMAC_RWK_SEL_V 1 -#define EMAC_RWK_SEL_S 9 -#define EMAC_SMA_SEL (BIT(8)) -#define EMAC_SMA_SEL_M (BIT(8)) -#define EMAC_SMA_SEL_V 1 -#define EMAC_SMA_SEL_S 8 -#define EMAC_L3L4FLTR_EN (BIT(7)) -#define EMAC_L3L4FLTR_EN_M (BIT(7)) -#define EMAC_L3L4FLTR_EN_V 1 -#define EMAC_L3L4FLTR_EN_S 7 -#define EMAC_PCS_SEL (BIT(6)) -#define EMAC_PCS_SEL_M (BIT(6)) -#define EMAC_PCS_SEL_V 1 -#define EMAC_PCS_SEL_S 6 -#define EMAC_ADDMACADR_SEL (BIT(5)) -#define EMAC_ADDMACADR_SEL_M (BIT(5)) -#define EMAC_ADDMACADR_SEL_V 1 -#define EMAC_ADDMACADR_SEL_S 5 -#define EMAC_HASH_SEL (BIT(4)) -#define EMAC_HASH_SEL_M (BIT(4)) -#define EMAC_HASH_SEL_V 1 -#define EMAC_HASH_SEL_S 4 -#define EMAC_EXTHASH_EN (BIT(3)) -#define EMAC_EXTHASH_EN_M (BIT(3)) -#define EMAC_EXTHASH_EN_V 1 -#define EMAC_EXTHASH_EN_S 3 -#define EMAC_HD_SEL (BIT(2)) -#define EMAC_HD_SEL_M (BIT(2)) -#define EMAC_HD_SEL_V 1 -#define EMAC_HD_SEL_S 2 -#define EMAC_GMII_SEL (BIT(1)) -#define EMAC_GMII_SEL_M (BIT(1)) -#define EMAC_GMII_SEL_V 1 -#define EMAC_GMII_SEL_S 1 -#define EMAC_MII_SEL (BIT(0)) -#define EMAC_MII_SEL_M (BIT(0)) -#define EMAC_MII_SEL_V 1 -#define EMAC_MII_SEL_S 0 +#define EMAC_GMACFF_REG (DR_REG_EMAC_BASE + 0x1004) +/* EMAC_RECEIVE_ALL : R/W ;bitpos:[31] ;default: 1'h0 ; */ +/*description: When this bit is set the MAC Receiver module passes all received + frames irrespective of whether they pass the address filter or not to the Application. The result of the SA or DA filtering is updated (pass or fail) in the corresponding bits in the Receive Status Word. When this bit is reset the Receiver module passes only those frames to the Application that pass the SA or DA address Filter.*/ +#define EMAC_RECEIVE_ALL (BIT(31)) +#define EMAC_RECEIVE_ALL_M (BIT(31)) +#define EMAC_RECEIVE_ALL_V 0x1 +#define EMAC_RECEIVE_ALL_S 31 +/* EMAC_SAFE : R/W ;bitpos:[9] ;default: 1'h0 ; */ +/*description: When this bit is set the MAC compares the SA field of the received + frames with the values programmed in the enabled SA registers. If the comparison fails the MAC drops the frame. When this bit is reset the MAC forwards the received frame to the application with updated SAF bit of the Rx Status depending on the SA address comparison.*/ +#define EMAC_SAFE (BIT(9)) +#define EMAC_SAFE_M (BIT(9)) +#define EMAC_SAFE_V 0x1 +#define EMAC_SAFE_S 9 +/* EMAC_SAIF : R/W ;bitpos:[8] ;default: 1'h0 ; */ +/*description: When this bit is set the Address Check block operates in inverse + filtering mode for the SA address comparison. The frames whose SA matches the SA registers are marked as failing the SA Address filter. When this bit is reset frames whose SA does not match the SA registers are marked as failing the SA Address filter.*/ +#define EMAC_SAIF (BIT(8)) +#define EMAC_SAIF_M (BIT(8)) +#define EMAC_SAIF_V 0x1 +#define EMAC_SAIF_S 8 +/* EMAC_PCF : R/W ;bitpos:[7:6] ;default: 2'h0 ; */ +/*description: These bits control the forwarding of all control frames (including + unicast and multicast Pause frames). 2'b00: MAC filters all control frames from reaching the application. 2'b01: MAC forwards all control frames except Pause frames to application even if they fail the Address filter. 2'b10: MAC forwards all control frames to application even if they fail the Address Filter. 2'b11: MAC forwards control frames that pass the Address Filter.The following conditions should be true for the Pause frames processing: Condition 1: The MAC is in the full-duplex mode and flow control is enabled by setting Bit 2 (RFE) of Register (Flow Control Register) to 1. Condition 2: The destination address (DA) of the received frame matches the special multicast address or the MAC Address 0 when Bit 3 (UP) of the Register(Flow Control Register) is set. Condition 3: The Type field of the received frame is 0x8808 and the OPCODE field is 0x0001.*/ +#define EMAC_PCF 0x00000003 +#define EMAC_PCF_M ((EMAC_PCF_V)<<(EMAC_PCF_S)) +#define EMAC_PCF_V 0x3 +#define EMAC_PCF_S 6 +/* EMAC_DBF : R/W ;bitpos:[5] ;default: 1'h0 ; */ +/*description: When this bit is set the AFM(Address Filtering Module) module + blocks all incoming broadcast frames. In addition it overrides all other filter settings. When this bit is reset the AFM module passes all received broadcast Frames.*/ +#define EMAC_DBF (BIT(5)) +#define EMAC_DBF_M (BIT(5)) +#define EMAC_DBF_V 0x1 +#define EMAC_DBF_S 5 +/* EMAC_PAM : R/W ;bitpos:[4] ;default: 1'h0 ; */ +/*description: When set this bit indicates that all received frames with a + multicast destination address (first bit in the destination address field is '1') are passed.*/ +#define EMAC_PAM (BIT(4)) +#define EMAC_PAM_M (BIT(4)) +#define EMAC_PAM_V 0x1 +#define EMAC_PAM_S 4 +/* EMAC_DAIF : R/W ;bitpos:[3] ;default: 1'h0 ; */ +/*description: When this bit is set the Address Check block operates in inverse + filtering mode for the DA address comparison for both unicast and multicast frames. When reset normal filtering of frames is performed.*/ +#define EMAC_DAIF (BIT(3)) +#define EMAC_DAIF_M (BIT(3)) +#define EMAC_DAIF_V 0x1 +#define EMAC_DAIF_S 3 +/* EMAC_PMODE : R/W ;bitpos:[0] ;default: 1'h0 ; */ +/*description: When this bit is set the Address Filter module passes all incoming + frames irrespective of the destination or source address. The SA or DA Filter Fails status bits of the Receive Status Word are always cleared when PR(PRI_RATIO) is set.*/ +#define EMAC_PMODE (BIT(0)) +#define EMAC_PMODE_M (BIT(0)) +#define EMAC_PMODE_V 0x1 +#define EMAC_PMODE_S 0 -#define EMAC_DMASLOTFNCTRLSTS_REG (REG_EMAC_BASE + 0x0130) -#define EMAC_REFERENCE_SLOT_NUMBER 0x0000000F -#define EMAC_REFERENCE_SLOT_NUMBER_M (EMAC_REFERENCE_SLOT_NUMBER_V << EMAC_REFERENCE_SLOT_NUMBER_S) -#define EMAC_REFERENCE_SLOT_NUMBER_V 0x0000000F -#define EMAC_REFERENCE_SLOT_NUMBER_S 16 -#define EMAC_ADVANCE_SLOT_CHECK (BIT(1)) -#define EMAC_ADVANCE_SLOT_CHECK_M (BIT(1)) -#define EMAC_ADVANCE_SLOT_CHECK_V 1 -#define EMAC_ADVANCE_SLOT_CHECK_S 1 -#define EMAC_ENABLE_SLOT_COMPARISON (BIT(0)) -#define EMAC_ENABLE_SLOT_COMPARISON_M (BIT(0)) -#define EMAC_ENABLE_SLOT_COMPARISON_V 1 -#define EMAC_ENABLE_SLOT_COMPARISON_S 0 +#define EMAC_GMIIADDR_REG (DR_REG_EMAC_BASE + 0x1010) +/* EMAC_MIIDEV : R/W ;bitpos:[15:11] ;default: 6'h0 ; */ +/*description: This field indicates which of the 32 possible PHY devices are being accessed.*/ +#define EMAC_MIIDEV 0x0000001F +#define EMAC_MIIDEV_M ((EMAC_MIIDEV_V)<<(EMAC_MIIDEV_S)) +#define EMAC_MIIDEV_V 0x1F +#define EMAC_MIIDEV_S 11 +/* EMAC_MIIREG : R/W ;bitpos:[10:6] ;default: 5'h0 ; */ +/*description: These bits select the desired MII register in the selected PHY device.*/ +#define EMAC_MIIREG 0x0000001F +#define EMAC_MIIREG_M ((EMAC_MIIREG_V)<<(EMAC_MIIREG_S)) +#define EMAC_MIIREG_V 0x1F +#define EMAC_MIIREG_S 6 +/* EMAC_MIICSRCLK : R/W ;bitpos:[5:2] ;default: 5'h0 ; */ +/*description: CSR clock range: 1.0 MHz ~ 2.5 MHz. 4'b0000: When the APB clock + frequency is 80 MHz the MDC clock frequency is APB CLK/42 4'b0000: When the APB clock frequency is 40 MHz the MDC clock frequency is APB CLK/26.*/ +#define EMAC_MIICSRCLK 0x0000000F +#define EMAC_MIICSRCLK_M ((EMAC_MIICSRCLK_V)<<(EMAC_MIICSRCLK_S)) +#define EMAC_MIICSRCLK_V 0xF +#define EMAC_MIICSRCLK_S 2 +/* EMAC_MIIWRITE : R/W ;bitpos:[1] ;default: 1'h0 ; */ +/*description: When set this bit indicates to the PHY that this is a Write + operation using the MII Data register. If this bit is not set it indicates that this is a Read operation that is placing the data in the MII Data register.*/ +#define EMAC_MIIWRITE (BIT(1)) +#define EMAC_MIIWRITE_M (BIT(1)) +#define EMAC_MIIWRITE_V 0x1 +#define EMAC_MIIWRITE_S 1 +/* EMAC_MIIBUSY : R_WS_SC ;bitpos:[0] ;default: 1'h0 ; */ +/*description: This bit should read logic 0 before writing to PHY Addr Register + and PHY data Register.During a PHY register access the software sets this bit to 1'b1 to indicate that a Read or Write access is in progress. PHY data Register is invalid until this bit is cleared by the MAC. Therefore PHY data Register (MII Data) should be kept valid until the MAC clears this bit during a PHY Write operation. Similarly for a read operation the contents of Register 5 are not valid until this bit is cleared. The subsequent read or write operation should happen only after the previous operation is complete. Because there is no acknowledgment from the PHY to MAC after a read or write operation is completed there is no change in the functionality of this bit even when the PHY is not Present.*/ +#define EMAC_MIIBUSY (BIT(0)) +#define EMAC_MIIBUSY_M (BIT(0)) +#define EMAC_MIIBUSY_V 0x1 +#define EMAC_MIIBUSY_S 0 -#define EMAC_DMACHANNELCTRL_REG (REG_EMAC_BASE + 0x0160) -#define EMAC_AVERAGE_BITS_PER_SLOT_INTERRUPT_ENABLE (BIT(17)) -#define EMAC_AVERAGE_BITS_PER_SLOT_INTERRUPT_ENABLE_M (BIT(17)) -#define EMAC_AVERAGE_BITS_PER_SLOT_INTERRUPT_ENABLE_V 1 -#define EMAC_AVERAGE_BITS_PER_SLOT_INTERRUPT_ENABLE_S 17 -#define EMAC_SLOT_COUNT 0x00000007 -#define EMAC_SLOT_COUNT_M (EMAC_SLOT_COUNT_V << EMAC_SLOT_COUNT_S) -#define EMAC_SLOT_COUNT_V 0x00000007 -#define EMAC_SLOT_COUNT_S 4 -#define EMAC_CREDIT_CONTROL (BIT(1)) -#define EMAC_CREDIT_CONTROL_M (BIT(1)) -#define EMAC_CREDIT_CONTROL_V 1 -#define EMAC_CREDIT_CONTROL_S 1 -#define EMAC_CREDIT_BASED_SHAPER_DISABLE (BIT(0)) -#define EMAC_CREDIT_BASED_SHAPER_DISABLE_M (BIT(0)) -#define EMAC_CREDIT_BASED_SHAPER_DISABLE_V 1 -#define EMAC_CREDIT_BASED_SHAPER_DISABLE_S 0 +#define EMAC_MIIDATA_REG (DR_REG_EMAC_BASE + 0x1014) +/* EMAC_MII_DATA : R/W ;bitpos:[15:0] ;default: 16'h0 ; */ +/*description: This field contains the 16-bit data value read from the PHY after + a Management Read operation or the 16-bit data value to be written to the PHY before a Management Write operation.*/ +#define EMAC_MII_DATA 0x0000FFFF +#define EMAC_MII_DATA_M ((EMAC_MII_DATA_V)<<(EMAC_MII_DATA_S)) +#define EMAC_MII_DATA_V 0xFFFF +#define EMAC_MII_DATA_S 0 -#define EMAC_DMACHANNELAVSTS_REG (REG_EMAC_BASE + 0x0064) -#define EMAC_ABS_UPDATED (BIT(17)) -#define EMAC_ABS_UPDATED_M (BIT(17)) -#define EMAC_ABS_UPDATED_V 1 -#define EMAC_ABS_UPDATED_S 17 -#define EMAC_AVERAGE_BITS_PER_SLOT 0x0001FFFF -#define EMAC_AVERAGE_BITS_PER_SLOT_M (EMAC_AVERAGE_BITS_PER_SLOT_V << EMAC_AVERAGE_BITS_PER_SLOT_S) -#define EMAC_AVERAGE_BITS_PER_SLOT_V 0x0001FFFF -#define EMAC_AVERAGE_BITS_PER_SLOT_S 0 +#define EMAC_GMACFC_REG (DR_REG_EMAC_BASE + 0x1018) +/* EMAC_PAUSE_TIME : R/W ;bitpos:[31:16] ;default: 16'h0 ; */ +/*description: This field holds the value to be used in the Pause Time field + in the transmit control frame. If the Pause Time bits is configured to be double-synchronized to the MII clock domain then consecutive writes to this register should be performed only after at least four clock cycles in the destination clock domain.*/ +#define EMAC_PAUSE_TIME 0x0000FFFF +#define EMAC_PAUSE_TIME_M ((EMAC_PAUSE_TIME_V)<<(EMAC_PAUSE_TIME_S)) +#define EMAC_PAUSE_TIME_V 0xFFFF +#define EMAC_PAUSE_TIME_S 16 +/* EMAC_DZPQ : R/W ;bitpos:[7] ;default: 1'h0 ; */ +/*description: When this bit is set it disables the automatic generation of + the Zero-Quanta Pause frames on the de-assertion of the flow-control signal from the FIFO layer. When this bit is reset normal operation with automatic Zero-Quanta Pause frame generation is enabled.*/ +#define EMAC_DZPQ (BIT(7)) +#define EMAC_DZPQ_M (BIT(7)) +#define EMAC_DZPQ_V 0x1 +#define EMAC_DZPQ_S 7 +/* EMAC_PLT : R/W ;bitpos:[5:4] ;default: 2'h0 ; */ +/*description: This field configures the threshold of the Pause timer automatic + retransmission of the Pause frame.The threshold values should be always less than the Pause Time configured in Bits[31:16]. For example if PT = 100H (256 slot-times) and PLT = 01 then a second Pause frame is automatically transmitted at 228 (256-28) slot times after the first Pause frame is transmitted. The following list provides the threshold values for different values: 2'b00: The threshold is Pause time minus 4 slot times (PT-4 slot times). 2'b01: The threshold is Pause time minus 28 slot times (PT-28 slot times). 2'b10: The threshold is Pause time minus 144 slot times (PT-144 slot times). 2'b11: The threshold is Pause time minus 256 slot times (PT-256 slot times). The slot time is defined as the time taken to transmit 512 bits (64 bytes) on the MII interface.*/ +#define EMAC_PLT 0x00000003 +#define EMAC_PLT_M ((EMAC_PLT_V)<<(EMAC_PLT_S)) +#define EMAC_PLT_V 0x3 +#define EMAC_PLT_S 4 +/* EMAC_UPFD : R/W ;bitpos:[3] ;default: 1'h0 ; */ +/*description: A pause frame is processed when it has the unique multicast address + specified in the IEEE Std 802.3. When this bit is set the MAC can also detect Pause frames with unicast address of the station. This unicast address should be as specified in the EMACADDR0 High Register and EMACADDR0 Low Register. When this bit is reset the MAC only detects Pause frames with unique multicast address.*/ +#define EMAC_UPFD (BIT(3)) +#define EMAC_UPFD_M (BIT(3)) +#define EMAC_UPFD_V 0x1 +#define EMAC_UPFD_S 3 +/* EMAC_RFCE : R/W ;bitpos:[2] ;default: 1'h0 ; */ +/*description: When this bit is set the MAC decodes the received Pause frame + and disables its transmitter for a specified (Pause) time. When this bit is reset the decode function of the Pause frame is disabled.*/ +#define EMAC_RFCE (BIT(2)) +#define EMAC_RFCE_M (BIT(2)) +#define EMAC_RFCE_V 0x1 +#define EMAC_RFCE_S 2 +/* EMAC_TFCE : R/W ;bitpos:[1] ;default: 1'h0 ; */ +/*description: In the full-duplex mode when this bit is set the MAC enables + the flow control operation to transmit Pause frames. When this bit is reset the flow control operation in the MAC is disabled and the MAC does not transmit any Pause frames. In the half-duplex mode when this bit is set the MAC enables the backpressure operation. When this bit is reset the backpressure feature is Disabled.*/ +#define EMAC_TFCE (BIT(1)) +#define EMAC_TFCE_M (BIT(1)) +#define EMAC_TFCE_V 0x1 +#define EMAC_TFCE_S 1 +/* EMAC_FCBBA : R_WS_SC(FCB)/R_W(BPA) ;bitpos:[0] ;default: 1'h0 ; */ +/*description: This bit initiates a Pause frame in the full-duplex mode and + activates the backpressure function in the half-duplex mode if the TFCE bit is set. In the full-duplex mode this bit should be read as 1'b0 before writing to the Flow Control register. To initiate a Pause frame the Application must set this bit to 1'b1. During a transfer of the Control Frame this bit continues to be set to signify that a frame transmission is in progress. After the completion of Pause frame transmission the MAC resets this bit to 1'b0. The Flow Control register should not be written to until this bit is cleared. In the half-duplex mode when this bit is set (and TFCE is set) then backpressure is asserted by the MAC. During backpressure when the MAC receives a new frame the transmitter starts sending a JAM pattern resulting in a collision. When the MAC is configured for the full-duplex mode the BPA(backpressure activate) is automatically disabled.*/ +#define EMAC_FCBBA (BIT(0)) +#define EMAC_FCBBA_M (BIT(0)) +#define EMAC_FCBBA_V 0x1 +#define EMAC_FCBBA_S 0 -#define EMAC_DMAIDLESLOPECREDIT_REG (REG_EMAC_BASE + 0x0068) -#define EMAC_IDLESLOPECREDIT 0x00003FFF -#define EMAC_IDLESLOPECREDIT_M (EMAC_IDLESLOPECREDIT_V << EMAC_IDLESLOPECREDIT_S) -#define EMAC_IDLESLOPECREDIT_V 0x00003FFF -#define EMAC_IDLESLOPECREDIT_S 0 +#define EMAC_DEBUG_REG (DR_REG_EMAC_BASE + 0x1024) +/* EMAC_MTLTSFFS : RO ;bitpos:[25] ;default: 1'h0 ; */ +/*description: When high this bit indicates that the MTL TxStatus FIFO is full. + Therefore the MTL cannot accept any more frames for transmission.*/ +#define EMAC_MTLTSFFS (BIT(25)) +#define EMAC_MTLTSFFS_M (BIT(25)) +#define EMAC_MTLTSFFS_V 0x1 +#define EMAC_MTLTSFFS_S 25 +/* EMAC_MTLTFNES : RO ;bitpos:[24] ;default: 1'h0 ; */ +/*description: When high this bit indicates that the MTL Tx FIFO is not empty + and some data is left for Transmission.*/ +#define EMAC_MTLTFNES (BIT(24)) +#define EMAC_MTLTFNES_M (BIT(24)) +#define EMAC_MTLTFNES_V 0x1 +#define EMAC_MTLTFNES_S 24 +/* EMAC_MTLTFWCS : RO ;bitpos:[22] ;default: 1'h0 ; */ +/*description: When high this bit indicates that the MTL Tx FIFO Write Controller + is active and is transferring data to the Tx FIFO.*/ +#define EMAC_MTLTFWCS (BIT(22)) +#define EMAC_MTLTFWCS_M (BIT(22)) +#define EMAC_MTLTFWCS_V 0x1 +#define EMAC_MTLTFWCS_S 22 +/* EMAC_MTLTFRCS : RO ;bitpos:[21:20] ;default: 2'h0 ; */ +/*description: This field indicates the state of the Tx FIFO Read Controller: + 2'b00: IDLE state. 2'b01: READ state (transferring data to the MAC transmitter). 2'b10: Waiting for TxStatus from the MAC transmitter. 2'b11: Writing the received TxStatus or flushing the Tx FIFO.*/ +#define EMAC_MTLTFRCS 0x00000003 +#define EMAC_MTLTFRCS_M ((EMAC_MTLTFRCS_V)<<(EMAC_MTLTFRCS_S)) +#define EMAC_MTLTFRCS_V 0x3 +#define EMAC_MTLTFRCS_S 20 +/* EMAC_MACTP : RO ;bitpos:[19] ;default: 1'h0 ; */ +/*description: When high this bit indicates that the MAC transmitter is in + the Pause condition (in the full-duplex-mode) and hence does not schedule any frame for transmission.*/ +#define EMAC_MACTP (BIT(19)) +#define EMAC_MACTP_M (BIT(19)) +#define EMAC_MACTP_V 0x1 +#define EMAC_MACTP_S 19 +/* EMAC_MACTFCS : RO ;bitpos:[18:17] ;default: 2'h0 ; */ +/*description: This field indicates the state of the MAC Transmit Frame Controller + module: 2'b00: IDLE state. 2'b01: Waiting for status of previous frame or IFG or backoff period to be over. 2'b10: Generating and transmitting a Pause frame (in the full-duplex mode). 2'b11: Transferring input frame for transmission.*/ +#define EMAC_MACTFCS 0x00000003 +#define EMAC_MACTFCS_M ((EMAC_MACTFCS_V)<<(EMAC_MACTFCS_S)) +#define EMAC_MACTFCS_V 0x3 +#define EMAC_MACTFCS_S 17 +/* EMAC_MACTPES : RO ;bitpos:[16] ;default: 1'h0 ; */ +/*description: When high this bit indicates that the MAC MII transmit protocol + engine is actively transmitting data and is not in the IDLE state.*/ +#define EMAC_MACTPES (BIT(16)) +#define EMAC_MACTPES_M (BIT(16)) +#define EMAC_MACTPES_V 0x1 +#define EMAC_MACTPES_S 16 +/* EMAC_MTLRFFLS : RO ;bitpos:[9:8] ;default: 2'h0 ; */ +/*description: This field gives the status of the fill-level of the Rx FIFO: + 2'b00: Rx FIFO Empty. 2'b01: Rx FIFO fill-level below flow-control deactivate threshold. 2'b10: Rx FIFO fill-level above flow-control activate threshold. 2'b11: Rx FIFO Full.*/ +#define EMAC_MTLRFFLS 0x00000003 +#define EMAC_MTLRFFLS_M ((EMAC_MTLRFFLS_V)<<(EMAC_MTLRFFLS_S)) +#define EMAC_MTLRFFLS_V 0x3 +#define EMAC_MTLRFFLS_S 8 +/* EMAC_MTLRFRCS : RO ;bitpos:[6:5] ;default: 2'h0 ; */ +/*description: This field gives the state of the Rx FIFO read Controller: 2'b00: + IDLE state.2'b01: Reading frame data.2'b10: Reading frame status (or timestamp).2'b11: Flushing the frame data and status.*/ +#define EMAC_MTLRFRCS 0x00000003 +#define EMAC_MTLRFRCS_M ((EMAC_MTLRFRCS_V)<<(EMAC_MTLRFRCS_S)) +#define EMAC_MTLRFRCS_V 0x3 +#define EMAC_MTLRFRCS_S 5 +/* EMAC_MTLRFWCAS : RO ;bitpos:[4] ;default: 1'h0 ; */ +/*description: When high this bit indicates that the MTL Rx FIFO Write Controller + is active and is transferring a received frame to the FIFO.*/ +#define EMAC_MTLRFWCAS (BIT(4)) +#define EMAC_MTLRFWCAS_M (BIT(4)) +#define EMAC_MTLRFWCAS_V 0x1 +#define EMAC_MTLRFWCAS_S 4 +/* EMAC_MACRFFCS : RO ;bitpos:[2:1] ;default: 2'h0 ; */ +/*description: When high this field indicates the active state of the FIFO + Read and Write controllers of the MAC Receive Frame Controller Module. MACRFFCS[1] represents the status of FIFO Read controller. MACRFFCS[0] represents the status of small FIFO Write controller.*/ +#define EMAC_MACRFFCS 0x00000003 +#define EMAC_MACRFFCS_M ((EMAC_MACRFFCS_V)<<(EMAC_MACRFFCS_S)) +#define EMAC_MACRFFCS_V 0x3 +#define EMAC_MACRFFCS_S 1 +/* EMAC_MACRPES : RO ;bitpos:[0] ;default: 1'h0 ; */ +/*description: When high this bit indicates that the MAC MII receive protocol + engine is actively receiving data and not in IDLE state.*/ +#define EMAC_MACRPES (BIT(0)) +#define EMAC_MACRPES_M (BIT(0)) +#define EMAC_MACRPES_V 0x1 +#define EMAC_MACRPES_S 0 -#define EMAC_DMASENDSLOPECREDIT_REG (REG_EMAC_BASE + 0x006C) -#define EMAC_SENDSLOPECREDIT 0x00003FFF -#define EMAC_SENDSLOPECREDIT_M (EMAC_SENDSLOPECREDIT_V << EMAC_SENDSLOPECREDIT_S) -#define EMAC_SENDSLOPECREDIT_V 0x00003FFF -#define EMAC_SENDSLOPECREDIT_S 0 +#define EMAC_PMT_RWUFFR_REG (DR_REG_EMAC_BASE + 0x1028) +/* EMAC_WKUPPKTFILTER : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: The MSB (31st bit) must be zero.Bit j[30:0] is the byte mask. + If Bit 1/2/3/4 (byte number) of the byte mask is set the CRC block processes the Filter 0/1/2/3 Offset + j of the incoming packet(PWKPTR is 0/1/2/3).RWKPTR is 0:Filter 0 Byte Mask .RWKPTR is 1:Filter 1 Byte Mask RWKPTR is 2:Filter 2 Byte Mask RWKPTR is 3:Filter 3 Byte Mask RWKPTR is 4:Bit 3/11/19/27 specifies the address type defining the destination address type of the pattern.When the bit is set the pattern applies to only multicast packets*/ +#define EMAC_WKUPPKTFILTER 0xFFFFFFFF +#define EMAC_WKUPPKTFILTER_M ((EMAC_WKUPPKTFILTER_V)<<(EMAC_WKUPPKTFILTER_S)) +#define EMAC_WKUPPKTFILTER_V 0xFFFFFFFF +#define EMAC_WKUPPKTFILTER_S 0 -#define EMAC_DMAHIGHCREDIT_REG (REG_EMAC_BASE + 0x0070) -#define EMAC_HICREDIT 0x1FFFFFFF -#define EMAC_HICREDIT_M (EMAC_HICREDIT_V << EMAC_HICREDIT_S) -#define EMAC_HICREDIT_V 0x1FFFFFFF -#define EMAC_HICREDIT_S 0 +#define EMAC_PMT_CSR_REG (DR_REG_EMAC_BASE + 0x102C) +/* EMAC_RWKFILTRST : R_WS_SC ;bitpos:[31] ;default: 1'h0 ; */ +/*description: When this bit is set it resets the RWKPTR register to 3’b000.*/ +#define EMAC_RWKFILTRST (BIT(31)) +#define EMAC_RWKFILTRST_M (BIT(31)) +#define EMAC_RWKFILTRST_V 0x1 +#define EMAC_RWKFILTRST_S 31 +/* EMAC_RWKPTR : RO ;bitpos:[28:24] ;default: 6'h0 ; */ +/*description: The maximum value of the pointer is 7 the detail information + please refer to PMT_RWUFFR.*/ +#define EMAC_RWKPTR 0x0000001F +#define EMAC_RWKPTR_M ((EMAC_RWKPTR_V)<<(EMAC_RWKPTR_S)) +#define EMAC_RWKPTR_V 0x1F +#define EMAC_RWKPTR_S 24 +/* EMAC_GLBLUCAST : R/W ;bitpos:[9] ;default: 1'h0 ; */ +/*description: When set enables any unicast packet filtered by the MAC (DAFilter) + address recognition to be a remote wake-up frame.*/ +#define EMAC_GLBLUCAST (BIT(9)) +#define EMAC_GLBLUCAST_M (BIT(9)) +#define EMAC_GLBLUCAST_V 0x1 +#define EMAC_GLBLUCAST_S 9 +/* EMAC_RWKPRCVD : R_SS_RC ;bitpos:[6] ;default: 1'h0 ; */ +/*description: When set this bit indicates the power management event is generated + because of the reception of a remote wake-up frame. This bit is cleared by a Read into this register.*/ +#define EMAC_RWKPRCVD (BIT(6)) +#define EMAC_RWKPRCVD_M (BIT(6)) +#define EMAC_RWKPRCVD_V 0x1 +#define EMAC_RWKPRCVD_S 6 +/* EMAC_MGKPRCVD : R_SS_RC ;bitpos:[5] ;default: 1'h0 ; */ +/*description: When set this bit indicates that the power management event + is generated because of the reception of a magic packet. This bit is cleared by a Read into this register.*/ +#define EMAC_MGKPRCVD (BIT(5)) +#define EMAC_MGKPRCVD_M (BIT(5)) +#define EMAC_MGKPRCVD_V 0x1 +#define EMAC_MGKPRCVD_S 5 +/* EMAC_RWKPKTEN : R/W ;bitpos:[2] ;default: 1'h0 ; */ +/*description: When set enables generation of a power management event because + of remote wake-up frame reception*/ +#define EMAC_RWKPKTEN (BIT(2)) +#define EMAC_RWKPKTEN_M (BIT(2)) +#define EMAC_RWKPKTEN_V 0x1 +#define EMAC_RWKPKTEN_S 2 +/* EMAC_MGKPKTEN : R/W ;bitpos:[1] ;default: 1'h0 ; */ +/*description: When set enables generation of a power management event because + of magic packet reception.*/ +#define EMAC_MGKPKTEN (BIT(1)) +#define EMAC_MGKPKTEN_M (BIT(1)) +#define EMAC_MGKPKTEN_V 0x1 +#define EMAC_MGKPKTEN_S 1 +/* EMAC_PWRDWN : R_WS_SC ;bitpos:[0] ;default: 1'h0 ; */ +/*description: When set the MAC receiver drops all received frames until it + receives the expected magic packet or remote wake-up frame.This bit must only be set when MGKPKTEN GLBLUCAST or RWKPKTEN bit is set high.*/ +#define EMAC_PWRDWN (BIT(0)) +#define EMAC_PWRDWN_M (BIT(0)) +#define EMAC_PWRDWN_V 0x1 +#define EMAC_PWRDWN_S 0 -#define EMAC_DMALOCREDIT_REG (REG_EMAC_BASE + 0x0074) -#define EMAC_LOCREDIT 0x1FFFFFFF -#define EMAC_LOCREDIT_M (EMAC_LOCREDIT_V << EMAC_LOCREDIT_S) -#define EMAC_LOCREDIT_V 0x1FFFFFFF -#define EMAC_LOCREDIT_S 0 +#define EMAC_GMACLPI_CRS_REG (DR_REG_EMAC_BASE + 0x1030) +/* EMAC_LPITXA : R/W ;bitpos:[19] ;default: 1'h0 ; */ +/*description: This bit controls the behavior of the MAC when it is entering + or coming out of the LPI mode on the transmit side.If the LPITXA and LPIEN bits are set to 1 the MAC enters the LPI mode only after all outstanding frames and pending frames have been transmitted. The MAC comes out of the LPI mode when the application sends any frame.When this bit is 0 the LPIEN bit directly controls behavior of the MAC when it is entering or coming out of the LPI mode.*/ +#define EMAC_LPITXA (BIT(19)) +#define EMAC_LPITXA_M (BIT(19)) +#define EMAC_LPITXA_V 0x1 +#define EMAC_LPITXA_S 19 +/* EMAC_PLS : R/W ;bitpos:[17] ;default: 1'h0 ; */ +/*description: This bit indicates the link status of the PHY.When set the link + is considered to be okay (up) and when reset the link is considered to be down.*/ +#define EMAC_PLS (BIT(17)) +#define EMAC_PLS_M (BIT(17)) +#define EMAC_PLS_V 0x1 +#define EMAC_PLS_S 17 +/* EMAC_LPIEN : R_W_SC ;bitpos:[16] ;default: 1'h0 ; */ +/*description: When set this bit instructs the MAC Transmitter to enter the + LPI state. When reset this bit instructs the MAC to exit the LPI state and resume normal transmission.This bit is cleared when the LPITXA bit is set and the MAC exits the LPI state because of the arrival of a new packet for transmission.*/ +#define EMAC_LPIEN (BIT(16)) +#define EMAC_LPIEN_M (BIT(16)) +#define EMAC_LPIEN_V 0x1 +#define EMAC_LPIEN_S 16 +/* EMAC_RLPIST : R/W ;bitpos:[9] ;default: 1'h0 ; */ +/*description: When set this bit indicates that the MAC is receiving the LPI + pattern on the MII interface.*/ +#define EMAC_RLPIST (BIT(9)) +#define EMAC_RLPIST_M (BIT(9)) +#define EMAC_RLPIST_V 0x1 +#define EMAC_RLPIST_S 9 +/* EMAC_TLPIST : R/W ;bitpos:[8] ;default: 1'h0 ; */ +/*description: When set this bit indicates that the MAC is transmitting the + LPI pattern on the MII interface.*/ +#define EMAC_TLPIST (BIT(8)) +#define EMAC_TLPIST_M (BIT(8)) +#define EMAC_TLPIST_V 0x1 +#define EMAC_TLPIST_S 8 +/* EMAC_RLPIEX : R_SS_RC ;bitpos:[3] ;default: 1'h0 ; */ +/*description: When set this bit indicates that the MAC Receiver has stopped + receiving the LPI pattern on the MII interface exited the LPI state and resumed the normal reception. This bit is cleared by a read into this register.*/ +#define EMAC_RLPIEX (BIT(3)) +#define EMAC_RLPIEX_M (BIT(3)) +#define EMAC_RLPIEX_V 0x1 +#define EMAC_RLPIEX_S 3 +/* EMAC_RLPIEN : R_SS_RC ;bitpos:[2] ;default: 1'h0 ; */ +/*description: When set this bit indicates that the MAC Receiver has received + an LPI pattern and entered the LPI state. This bit is cleared by a read into this register.*/ +#define EMAC_RLPIEN (BIT(2)) +#define EMAC_RLPIEN_M (BIT(2)) +#define EMAC_RLPIEN_V 0x1 +#define EMAC_RLPIEN_S 2 +/* EMAC_TLPIEX : R_SS_RC ;bitpos:[1] ;default: 1'h0 ; */ +/*description: When set this bit indicates that the MAC transmitter has exited + the LPI state after the user has cleared the LPIEN bit and the LPI_TW_Timer has expired.This bit is cleared by a read into this register.*/ +#define EMAC_TLPIEX (BIT(1)) +#define EMAC_TLPIEX_M (BIT(1)) +#define EMAC_TLPIEX_V 0x1 +#define EMAC_TLPIEX_S 1 +/* EMAC_TLPIEN : R_SS_RC ;bitpos:[0] ;default: 1'h0 ; */ +/*description: When set this bit indicates that the MAC Transmitter has entered + the LPI state because of the setting of the LPIEN bit. This bit is cleared by a read into this register.*/ +#define EMAC_TLPIEN (BIT(0)) +#define EMAC_TLPIEN_M (BIT(0)) +#define EMAC_TLPIEN_V 0x1 +#define EMAC_TLPIEN_S 0 -#define EMAC_GMACCONFIG_REG (REG_EMAC_BASE + 0x1000) -#define EMAC_SOURCE_ADDRESS_INSERTION_REPLACEMENT_CONTROL 0x00000007 -#define EMAC_SOURCE_ADDRESS_INSERTION_REPLACEMENT_CONTROL_M (EMAC_SOURCE_ADDRESS_INSERTION_REPLACEMENT_CONTROL_V << EMAC_SOURCE_ADDRESS_INSERTION_REPLACEMENT_CONTROL_S) -#define EMAC_SOURCE_ADDRESS_INSERTION_REPLACEMENT_CONTROL_V 0x00000007 -#define EMAC_SOURCE_ADDRESS_INSERTION_REPLACEMENT_CONTROL_S 28 -#define EMAC_AS_SUPPORT_2K_PACKETS (BIT(27)) -#define EMAC_AS_SUPPORT_2K_PACKETS_M (BIT(27)) -#define EMAC_AS_SUPPORT_2K_PACKETS_V 1 -#define EMAC_AS_SUPPORT_2K_PACKETS_S 27 -#define EMAC_SMII_FORCE_TRANSMIT_ERROR (BIT(26)) -#define EMAC_SMII_FORCE_TRANSMIT_ERROR_M (BIT(26)) -#define EMAC_SMII_FORCE_TRANSMIT_ERROR_V 1 -#define EMAC_SMII_FORCE_TRANSMIT_ERROR_S 26 -#define EMAC_CRC_STRIPPING_TYPE_FRAMES (BIT(25)) -#define EMAC_CRC_STRIPPING_TYPE_FRAMES_M (BIT(25)) -#define EMAC_CRC_STRIPPING_TYPE_FRAMES_V 1 -#define EMAC_CRC_STRIPPING_TYPE_FRAMES_S 25 -#define EMAC_TRANSMIT_CONFIGURATION (BIT(24)) -#define EMAC_TRANSMIT_CONFIGURATION_M (BIT(24)) -#define EMAC_TRANSMIT_CONFIGURATION_V 1 -#define EMAC_TRANSMIT_CONFIGURATION_S 24 -#define EMAC_GMACWATCHDOG (BIT(23)) -#define EMAC_GMACWATCHDOG_M (BIT(23)) -#define EMAC_GMACWATCHDOG_V 1 -#define EMAC_GMACWATCHDOG_S 23 -#define EMAC_GMACJABBER (BIT(22)) -#define EMAC_GMACJABBER_M (BIT(22)) -#define EMAC_GMACJABBER_V 1 -#define EMAC_GMACJABBER_S 22 -#define EMAC_GMACFRAMEBURST (BIT(21)) -#define EMAC_GMACFRAMEBURST_M (BIT(21)) -#define EMAC_GMACFRAMEBURST_V 1 -#define EMAC_GMACFRAMEBURST_S 21 -#define EMAC_GMACJUMBOFRAME (BIT(20)) -#define EMAC_GMACJUMBOFRAME_M (BIT(20)) -#define EMAC_GMACJUMBOFRAME_V 1 -#define EMAC_GMACJUMBOFRAME_S 20 -#define EMAC_GMACINTERFRAMEGAP 0x00000007 -#define EMAC_GMACINTERFRAMEGAP_M (EMAC_GMACINTERFRAMEGAP_V << EMAC_GMACINTERFRAMEGAP_S) -#define EMAC_GMACINTERFRAMEGAP_V 0x00000007 -#define EMAC_GMACINTERFRAMEGAP_S 17 -#define EMAC_GMACDISABLECRS (BIT(16)) -#define EMAC_GMACDISABLECRS_M (BIT(16)) -#define EMAC_GMACDISABLECRS_V 1 -#define EMAC_GMACDISABLECRS_S 16 -#define EMAC_GMACMIIGMII (BIT(15)) -#define EMAC_GMACMIIGMII_M (BIT(15)) -#define EMAC_GMACMIIGMII_V 1 -#define EMAC_GMACMIIGMII_S 15 -#define EMAC_GMACFESPEED (BIT(14)) -#define EMAC_GMACFESPEED_M (BIT(14)) -#define EMAC_GMACFESPEED_V 1 -#define EMAC_GMACFESPEED_S 14 -#define EMAC_GMACRXOWN (BIT(13)) -#define EMAC_GMACRXOWN_M (BIT(13)) -#define EMAC_GMACRXOWN_V 1 -#define EMAC_GMACRXOWN_S 13 -#define EMAC_GMACLOOPBACK (BIT(12)) -#define EMAC_GMACLOOPBACK_M (BIT(12)) -#define EMAC_GMACLOOPBACK_V 1 -#define EMAC_GMACLOOPBACK_S 12 -#define EMAC_GMACDUPLEX (BIT(11)) -#define EMAC_GMACDUPLEX_M (BIT(11)) -#define EMAC_GMACDUPLEX_V 1 -#define EMAC_GMACDUPLEX_S 11 -#define EMAC_GMACRXIPCOFFLOAD (BIT(10)) -#define EMAC_GMACRXIPCOFFLOAD_M (BIT(10)) -#define EMAC_GMACRXIPCOFFLOAD_V 1 -#define EMAC_GMACRXIPCOFFLOAD_S 10 -#define EMAC_GMACRETRY (BIT(9)) -#define EMAC_GMACRETRY_M (BIT(9)) -#define EMAC_GMACRETRY_V 1 -#define EMAC_GMACRETRY_S 9 -#define EMAC_GMACLINK (BIT(8)) -#define EMAC_GMACLINK_M (BIT(8)) -#define EMAC_GMACLINK_V 1 -#define EMAC_GMACLINK_S 8 -#define EMAC_GMACPADCRCSTRIP (BIT(7)) -#define EMAC_GMACPADCRCSTRIP_M (BIT(7)) -#define EMAC_GMACPADCRCSTRIP_V 1 -#define EMAC_GMACPADCRCSTRIP_S 7 -#define EMAC_GMACBACKOFFLIMIT 0x00000003 -#define EMAC_GMACBACKOFFLIMIT_M (EMAC_GMACBACKOFFLIMIT_V << EMAC_GMACBACKOFFLIMIT_S) -#define EMAC_GMACBACKOFFLIMIT_V 0x00000003 -#define EMAC_GMACBACKOFFLIMIT_S 5 -#define EMAC_GMACDEFERRALCHECK (BIT(4)) -#define EMAC_GMACDEFERRALCHECK_M (BIT(4)) -#define EMAC_GMACDEFERRALCHECK_V 1 -#define EMAC_GMACDEFERRALCHECK_S 4 -#define EMAC_GMACTX (BIT(3)) -#define EMAC_GMACTX_M (BIT(3)) -#define EMAC_GMACTX_V 1 -#define EMAC_GMACTX_S 3 -#define EMAC_GMACRX (BIT(2)) -#define EMAC_GMACRX_M (BIT(2)) -#define EMAC_GMACRX_V 1 -#define EMAC_GMACRX_S 2 -#define EMAC_PREAMBLE_LENGTH_TRANSMIT_FRAMES 0x00000003 -#define EMAC_PREAMBLE_LENGTH_TRANSMIT_FRAMES_M (EMAC_PREAMBLE_LENGTH_TRANSMIT_FRAMES_V << EMAC_PREAMBLE_LENGTH_TRANSMIT_FRAMES_S) -#define EMAC_PREAMBLE_LENGTH_TRANSMIT_FRAMES_V 0x00000003 -#define EMAC_PREAMBLE_LENGTH_TRANSMIT_FRAMES_S 0 +#define EMAC_GMACLPITIMERSCONTROL_REG (DR_REG_EMAC_BASE + 0x1034) +/* EMAC_LPI_LS_TIMER : R/W ;bitpos:[25:16] ;default: 10'h3E8 ; */ +/*description: This field specifies the minimum time (in milliseconds) for which + the link status from the PHY should be up (OKAY) before the LPI pattern can be transmitted to the PHY. The MAC does not transmit the LPI pattern even when the LPIEN bit is set unless the LPI_LS_Timer reaches the programmed terminal count. The default value of the LPI_LS_Timer is 1000 (1 sec) as defined in the IEEE standard.*/ +#define EMAC_LPI_LS_TIMER 0x000003FF +#define EMAC_LPI_LS_TIMER_M ((EMAC_LPI_LS_TIMER_V)<<(EMAC_LPI_LS_TIMER_S)) +#define EMAC_LPI_LS_TIMER_V 0x3FF +#define EMAC_LPI_LS_TIMER_S 16 +/* EMAC_LPI_TW_TIMER : R/W ;bitpos:[15:0] ;default: 16'h0 ; */ +/*description: This field specifies the minimum time (in microseconds) for which + the MAC waits after it stops transmitting the LPI pattern to the PHY and before it resumes the normal transmission. The TLPIEX status bit is set after the expiry of this timer.*/ +#define EMAC_LPI_TW_TIMER 0x0000FFFF +#define EMAC_LPI_TW_TIMER_M ((EMAC_LPI_TW_TIMER_V)<<(EMAC_LPI_TW_TIMER_S)) +#define EMAC_LPI_TW_TIMER_V 0xFFFF +#define EMAC_LPI_TW_TIMER_S 0 -#define EMAC_GMACFRAMEFILTER_REG (REG_EMAC_BASE + 0x1004) -#define EMAC_RECEIVEALL (BIT(31)) -#define EMAC_RECEIVEALL_M (BIT(31)) -#define EMAC_RECEIVEALL_V 1 -#define EMAC_RECEIVEALL_S 31 -#define EMAC_DROP_NON_TCP_UDP_IP_FRAMES (BIT(21)) -#define EMAC_DROP_NON_TCP_UDP_IP_FRAMES_M (BIT(21)) -#define EMAC_DROP_NON_TCP_UDP_IP_FRAMES_V 1 -#define EMAC_DROP_NON_TCP_UDP_IP_FRAMES_S 21 -#define EMAC_LAYER_3_AND_LAYER_4_FILTER_ENABLE (BIT(20)) -#define EMAC_LAYER_3_AND_LAYER_4_FILTER_ENABLE_M (BIT(20)) -#define EMAC_LAYER_3_AND_LAYER_4_FILTER_ENABLE_V 1 -#define EMAC_LAYER_3_AND_LAYER_4_FILTER_ENABLE_S 20 -#define EMAC_VLAN_TAG_FILTER_ENABLE (BIT(16)) -#define EMAC_VLAN_TAG_FILTER_ENABLE_M (BIT(16)) -#define EMAC_VLAN_TAG_FILTER_ENABLE_V 1 -#define EMAC_VLAN_TAG_FILTER_ENABLE_S 16 -#define EMAC_HASH_OR_PERFECT_FILTE (BIT(10)) -#define EMAC_HASH_OR_PERFECT_FILTE_M (BIT(10)) -#define EMAC_HASH_OR_PERFECT_FILTE_V 1 -#define EMAC_HASH_OR_PERFECT_FILTE_S 10 -#define EMAC_SOURCE_ADDRESS_FILTER_ENABLE (BIT(9)) -#define EMAC_SOURCE_ADDRESS_FILTER_ENABLE_M (BIT(9)) -#define EMAC_SOURCE_ADDRESS_FILTER_ENABLE_V 1 -#define EMAC_SOURCE_ADDRESS_FILTER_ENABLE_S 9 -#define EMAC_SA_INVERSE_FILTERING (BIT(8)) -#define EMAC_SA_INVERSE_FILTERING_M (BIT(8)) -#define EMAC_SA_INVERSE_FILTERING_V 1 -#define EMAC_SA_INVERSE_FILTERING_S 8 -#define EMAC_PASS_CONTROL_FRAMES 0x00000003 -#define EMAC_PASS_CONTROL_FRAMES_M (EMAC_PASS_CONTROL_FRAMES_V << EMAC_PASS_CONTROL_FRAMES_S) -#define EMAC_PASS_CONTROL_FRAMES_V 0x00000003 -#define EMAC_PASS_CONTROL_FRAMES_S 6 -#define EMAC_DISABLE_BROADCAST_FRAMES (BIT(5)) -#define EMAC_DISABLE_BROADCAST_FRAMES_M (BIT(5)) -#define EMAC_DISABLE_BROADCAST_FRAMES_V 1 -#define EMAC_DISABLE_BROADCAST_FRAMES_S 5 -#define EMAC_PASS_ALL_MULTICAST (BIT(4)) -#define EMAC_PASS_ALL_MULTICAST_M (BIT(4)) -#define EMAC_PASS_ALL_MULTICAST_V 1 -#define EMAC_PASS_ALL_MULTICAST_S 4 -#define EMAC_DA_INVERSE_FILTERING (BIT(3)) -#define EMAC_DA_INVERSE_FILTERING_M (BIT(3)) -#define EMAC_DA_INVERSE_FILTERING_V 1 -#define EMAC_DA_INVERSE_FILTERING_S 3 -#define EMAC_HASH_MULTICAST (BIT(2)) -#define EMAC_HASH_MULTICAST_M (BIT(2)) -#define EMAC_HASH_MULTICAST_V 1 -#define EMAC_HASH_MULTICAST_S 2 -#define EMAC_HASH_UNICAST (BIT(1)) -#define EMAC_HASH_UNICAST_M (BIT(1)) -#define EMAC_HASH_UNICAST_V 1 -#define EMAC_HASH_UNICAST_S 1 -#define EMAC_PROMISCUOUS_MODE (BIT(0)) -#define EMAC_PROMISCUOUS_MODE_M (BIT(0)) -#define EMAC_PROMISCUOUS_MODE_V 1 -#define EMAC_PROMISCUOUS_MODE_S 0 +#define EMAC_INTS_REG (DR_REG_EMAC_BASE + 0x1038) +/* EMAC_LPIIS : RO ;bitpos:[10] ;default: 1'h0 ; */ +/*description: When the Energy Efficient Ethernet feature is enabled this bit + is set for any LPI state entry or exit in the MAC Transmitter or Receiver. This bit is cleared on reading Bit[0] of Register (LPI Control and Status Register).*/ +#define EMAC_LPIIS (BIT(10)) +#define EMAC_LPIIS_M (BIT(10)) +#define EMAC_LPIIS_V 0x1 +#define EMAC_LPIIS_S 10 +/* EMAC_PMTINTS : RO ;bitpos:[3] ;default: 1'h0 ; */ +/*description: This bit is set when a magic packet or remote wake-up frame is + received in the power-down mode (see Bit[5] and Bit[6] in the PMT Control and Status Register). This bit is cleared when both Bits[6:5] are cleared because of a read operation to the PMT Control and Status register. This bit is valid only when you select the optional PMT module during core configuration.*/ +#define EMAC_PMTINTS (BIT(3)) +#define EMAC_PMTINTS_M (BIT(3)) +#define EMAC_PMTINTS_V 0x1 +#define EMAC_PMTINTS_S 3 -#define EMAC_GMACHASHHIGH_REG (REG_EMAC_BASE + 0x1008) -#define EMAC_HASH_TABLE_HIGH 0xFFFFFFFF -#define EMAC_HASH_TABLE_HIGH_M (EMAC_HASH_TABLE_HIGH_V << EMAC_HASH_TABLE_HIGH_S) -#define EMAC_HASH_TABLE_HIGH_V 0xFFFFFFFF -#define EMAC_HASH_TABLE_HIGH_S 0 +#define EMAC_INTMASK_REG (DR_REG_EMAC_BASE + 0x103C) +/* EMAC_LPIINTMASK : R/W ;bitpos:[10] ;default: 1'h0 ; */ +/*description: When set this bit disables the assertion of the interrupt signal + because of the setting of the LPI Interrupt Status bit in Register (Interrupt Status Register).*/ +#define EMAC_LPIINTMASK (BIT(10)) +#define EMAC_LPIINTMASK_M (BIT(10)) +#define EMAC_LPIINTMASK_V 0x1 +#define EMAC_LPIINTMASK_S 10 +/* EMAC_PMTINTMASK : R/W ;bitpos:[3] ;default: 1'h0 ; */ +/*description: When set this bit disables the assertion of the interrupt signal + because of the setting of PMT Interrupt Status bit in Register (Interrupt Status Register).*/ +#define EMAC_PMTINTMASK (BIT(3)) +#define EMAC_PMTINTMASK_M (BIT(3)) +#define EMAC_PMTINTMASK_V 0x1 +#define EMAC_PMTINTMASK_S 3 -#define EMAC_GMACHASHLOW_REG (REG_EMAC_BASE + 0x100C) -#define EMAC_HASH_TABLE_LOW 0xFFFFFFFF -#define EMAC_HASH_TABLE_LOW_M (EMAC_HASH_TABLE_LOW_V << EMAC_HASH_TABLE_LOW_S) -#define EMAC_HASH_TABLE_LOW_V 0xFFFFFFFF -#define EMAC_HASH_TABLE_LOW_S 0 +#define EMAC_ADDR0HIGH_REG (DR_REG_EMAC_BASE + 0x1040) +/* EMAC_ADDRESS_ENABLE0 : RO ;bitpos:[31] ;default: 1'h0 ; */ +/*description: This bit is always set to 1.*/ +#define EMAC_ADDRESS_ENABLE0 (BIT(31)) +#define EMAC_ADDRESS_ENABLE0_M (BIT(31)) +#define EMAC_ADDRESS_ENABLE0_V 0x1 +#define EMAC_ADDRESS_ENABLE0_S 31 +/* EMAC_ADDRESS0_HI : R/W ;bitpos:[15:0] ;default: 16'hFFFF ; */ +/*description: This field contains the upper 16 bits (47:32) of the first 6-byte + MAC address.The MAC uses this field for filtering the received frames and inserting the MAC address in the Transmit Flow Control (Pause) Frames.*/ +#define EMAC_ADDRESS0_HI 0x0000FFFF +#define EMAC_ADDRESS0_HI_M ((EMAC_ADDRESS0_HI_V)<<(EMAC_ADDRESS0_HI_S)) +#define EMAC_ADDRESS0_HI_V 0xFFFF +#define EMAC_ADDRESS0_HI_S 0 -#define EMAC_GMACGMIIADDR_REG (REG_EMAC_BASE + 0x1010) -#define EMAC_GMIIDEV 0x0000001F -#define EMAC_GMIIDEV_M (EMAC_GMIIDEV_V << EMAC_GMIIDEV_S) -#define EMAC_GMIIDEV_V 0x0000001F -#define EMAC_GMIIDEV_S 11 -#define EMAC_GMIIREG 0x0000001F -#define EMAC_GMIIREG_M (EMAC_GMIIREG_V << EMAC_GMIIREG_S) -#define EMAC_GMIIREG_V 0x0000001F -#define EMAC_GMIIREG_S 6 -#define EMAC_GMIICSRCLK 0x0000000F -#define EMAC_GMIICSRCLK_M (EMAC_GMIICSRCLK_V << EMAC_GMIICSRCLK_S) -#define EMAC_GMIICSRCLK_V 0x0000000F -#define EMAC_GMIICSRCLK_S 2 -#define EMAC_GMIIWRITE (BIT(1)) -#define EMAC_GMIIWRITE_M (BIT(1)) -#define EMAC_GMIIWRITE_V 1 -#define EMAC_GMIIWRITE_S 1 -#define EMAC_GMIIBUSY (BIT(0)) -#define EMAC_GMIIBUSY_M (BIT(0)) -#define EMAC_GMIIBUSY_V 1 -#define EMAC_GMIIBUSY_S 0 +#define EMAC_ADDR0LOW_REG (DR_REG_EMAC_BASE + 0x1044) +/* EMAC_MAC_ADDRESS0_LOW : R/W ;bitpos:[31:0] ;default: 32'hFFFFFFFF ; */ +/*description: This field contains the lower 32 bits of the first 6-byte MAC + address. This is used by the MAC for filtering the received frames and inserting the MAC address in the Transmit Flow Control (Pause) Frames.*/ +#define EMAC_MAC_ADDRESS0_LOW 0xFFFFFFFF +#define EMAC_MAC_ADDRESS0_LOW_M ((EMAC_MAC_ADDRESS0_LOW_V)<<(EMAC_MAC_ADDRESS0_LOW_S)) +#define EMAC_MAC_ADDRESS0_LOW_V 0xFFFFFFFF +#define EMAC_MAC_ADDRESS0_LOW_S 0 -#define EMAC_GMACGMIIDATA_REG (REG_EMAC_BASE + 0x1014) -#define EMAC_GMII_DATA 0x0000FFFF -#define EMAC_GMII_DATA_M (EMAC_GMII_DATA_V << EMAC_GMII_DATA_S) -#define EMAC_GMII_DATA_V 0x0000FFFF -#define EMAC_GMII_DATA_S 0 +#define EMAC_ADDR1HIGH_REG (DR_REG_EMAC_BASE + 0x1048) +/* EMAC_ADDRESS_ENABLE1 : R/W ;bitpos:[31] ;default: 1'h0 ; */ +/*description: When this bit is set the address filter module uses the second + MAC address for perfect filtering. When this bit is reset the address filter module ignores the address for filtering.*/ +#define EMAC_ADDRESS_ENABLE1 (BIT(31)) +#define EMAC_ADDRESS_ENABLE1_M (BIT(31)) +#define EMAC_ADDRESS_ENABLE1_V 0x1 +#define EMAC_ADDRESS_ENABLE1_S 31 +/* EMAC_SOURCE_ADDRESS : R/W ;bitpos:[30] ;default: 1'h0 ; */ +/*description: When this bit is set the EMACADDR1[47:0] is used to compare + with the SA fields of the received frame. When this bit is reset the EMACADDR1[47:0] is used to compare with the DA fields of the received frame.*/ +#define EMAC_SOURCE_ADDRESS (BIT(30)) +#define EMAC_SOURCE_ADDRESS_M (BIT(30)) +#define EMAC_SOURCE_ADDRESS_V 0x1 +#define EMAC_SOURCE_ADDRESS_S 30 +/* EMAC_MASK_BYTE_CONTROL : R/W ;bitpos:[29:24] ;default: 6'h0 ; */ +/*description: These bits are mask control bits for comparison of each of the + EMACADDR1 bytes. When set high the MAC does not compare the corresponding byte of received DA or SA with the contents of EMACADDR1 registers. Each bit controls the masking of the bytes as follows: Bit[29]: EMACADDR1 High [15:8]. Bit[28]: EMACADDR1 High [7:0]. Bit[27]: EMACADDR1 Low [31:24]. Bit[24]: EMACADDR1 Low [7:0].You can filter a group of addresses (known as group address filtering) by masking one or more bytes of the address.*/ +#define EMAC_MASK_BYTE_CONTROL 0x0000003F +#define EMAC_MASK_BYTE_CONTROL_M ((EMAC_MASK_BYTE_CONTROL_V)<<(EMAC_MASK_BYTE_CONTROL_S)) +#define EMAC_MASK_BYTE_CONTROL_V 0x3F +#define EMAC_MASK_BYTE_CONTROL_S 24 +/* EMAC_MAC_ADDRESS1_HI : R/W ;bitpos:[15:0] ;default: 16'hFFFF ; */ +/*description: This field contains the upper 16 bits Bits[47:32] of the second + 6-byte MAC Address.*/ +#define EMAC_MAC_ADDRESS1_HI 0x0000FFFF +#define EMAC_MAC_ADDRESS1_HI_M ((EMAC_MAC_ADDRESS1_HI_V)<<(EMAC_MAC_ADDRESS1_HI_S)) +#define EMAC_MAC_ADDRESS1_HI_V 0xFFFF +#define EMAC_MAC_ADDRESS1_HI_S 0 -#define EMAC_GMACFLOWCONTROL_REG (REG_EMAC_BASE + 0x1018) -#define EMAC_PAUSE_TIME 0x0000FFFF -#define EMAC_PAUSE_TIME_M (EMAC_PAUSE_TIME_V << EMAC_PAUSE_TIME_S) -#define EMAC_PAUSE_TIME_V 0x0000FFFF -#define EMAC_PAUSE_TIME_S 16 -#define EMAC_DISABLE_ZERO_QUANTA_PAUSE (BIT(7)) -#define EMAC_DISABLE_ZERO_QUANTA_PAUSE_M (BIT(7)) -#define EMAC_DISABLE_ZERO_QUANTA_PAUSE_V 1 -#define EMAC_DISABLE_ZERO_QUANTA_PAUSE_S 7 -#define EMAC_PAUSE_LOW_THRESHOLD 0x00000003 -#define EMAC_PAUSE_LOW_THRESHOLD_M (EMAC_PAUSE_LOW_THRESHOLD_V << EMAC_PAUSE_LOW_THRESHOLD_S) -#define EMAC_PAUSE_LOW_THRESHOLD_V 0x00000003 -#define EMAC_PAUSE_LOW_THRESHOLD_S 4 -#define EMAC_UNICAST_PAUSE_FRAME_DETECT (BIT(3)) -#define EMAC_UNICAST_PAUSE_FRAME_DETECT_M (BIT(3)) -#define EMAC_UNICAST_PAUSE_FRAME_DETECT_V 1 -#define EMAC_UNICAST_PAUSE_FRAME_DETECT_S 3 -#define EMAC_RECEIVE_FLOW_CONTROL_ENABLE (BIT(2)) -#define EMAC_RECEIVE_FLOW_CONTROL_ENABLE_M (BIT(2)) -#define EMAC_RECEIVE_FLOW_CONTROL_ENABLE_V 1 -#define EMAC_RECEIVE_FLOW_CONTROL_ENABLE_S 2 -#define EMAC_TRANSMIT_FLOW_CONTROL_ENABLE (BIT(1)) -#define EMAC_TRANSMIT_FLOW_CONTROL_ENABLE_M (BIT(1)) -#define EMAC_TRANSMIT_FLOW_CONTROL_ENABLE_V 1 -#define EMAC_TRANSMIT_FLOW_CONTROL_ENABLE_S 1 -#define EMAC_FLOW_CONTROL_BUSY_BACKPRESSURE_ACTIVATE (BIT(0)) -#define EMAC_FLOW_CONTROL_BUSY_BACKPRESSURE_ACTIVATE_M (BIT(0)) -#define EMAC_FLOW_CONTROL_BUSY_BACKPRESSURE_ACTIVATE_V 1 -#define EMAC_FLOW_CONTROL_BUSY_BACKPRESSURE_ACTIVATE_S 0 +#define EMAC_ADDR1LOW_REG (DR_REG_EMAC_BASE + 0x104C) +/* EMAC_MAC_ADDRESS1_LOW : R/W ;bitpos:[31:0] ;default: 32'hFFFFFFFF ; */ +/*description: This field contains the lower 32 bits of the second 6-byte MAC + address.The content of this field is undefined so the register needs to be configured after the initialization Process.*/ +#define EMAC_MAC_ADDRESS1_LOW 0xFFFFFFFF +#define EMAC_MAC_ADDRESS1_LOW_M ((EMAC_MAC_ADDRESS1_LOW_V)<<(EMAC_MAC_ADDRESS1_LOW_S)) +#define EMAC_MAC_ADDRESS1_LOW_V 0xFFFFFFFF +#define EMAC_MAC_ADDRESS1_LOW_S 0 -#define EMAC_GMACVLAN_REG (REG_EMAC_BASE + 0x101C) -#define EMAC_VLAN_TAG_HASH_TABLE_MATCH_ENABLE (BIT(19)) -#define EMAC_VLAN_TAG_HASH_TABLE_MATCH_ENABLE_M (BIT(19)) -#define EMAC_VLAN_TAG_HASH_TABLE_MATCH_ENABLE_V 1 -#define EMAC_VLAN_TAG_HASH_TABLE_MATCH_ENABLE_S 19 -#define EMAC_ENABLE_S_VLAN (BIT(18)) -#define EMAC_ENABLE_S_VLAN_M (BIT(18)) -#define EMAC_ENABLE_S_VLAN_V 1 -#define EMAC_ENABLE_S_VLAN_S 18 -#define EMAC_VLAN_TAG_INVERSE_MATCH_ENABLE (BIT(17)) -#define EMAC_VLAN_TAG_INVERSE_MATCH_ENABLE_M (BIT(17)) -#define EMAC_VLAN_TAG_INVERSE_MATCH_ENABLE_V 1 -#define EMAC_VLAN_TAG_INVERSE_MATCH_ENABLE_S 17 -#define EMAC_ENABLE_VLAN_TAG_COMPARISON (BIT(16)) -#define EMAC_ENABLE_VLAN_TAG_COMPARISON_M (BIT(16)) -#define EMAC_ENABLE_VLAN_TAG_COMPARISON_V 1 -#define EMAC_ENABLE_VLAN_TAG_COMPARISON_S 16 -#define EMAC_VLAN_TAG_IDENTIFIER_RECEIVE_FRAMES 0x0000FFFF -#define EMAC_VLAN_TAG_IDENTIFIER_RECEIVE_FRAMES_M (EMAC_VLAN_TAG_IDENTIFIER_RECEIVE_FRAMES_V << EMAC_VLAN_TAG_IDENTIFIER_RECEIVE_FRAMES_S) -#define EMAC_VLAN_TAG_IDENTIFIER_RECEIVE_FRAMES_V 0x0000FFFF -#define EMAC_VLAN_TAG_IDENTIFIER_RECEIVE_FRAMES_S 0 +#define EMAC_ADDR2HIGH_REG (DR_REG_EMAC_BASE + 0x1050) +/* EMAC_ADDRESS_ENABLE2 : R/W ;bitpos:[31] ;default: 1'h0 ; */ +/*description: When this bit is set the address filter module uses the third + MAC address for perfect filtering. When this bit is reset the address filter module ignores the address for filtering.*/ +#define EMAC_ADDRESS_ENABLE2 (BIT(31)) +#define EMAC_ADDRESS_ENABLE2_M (BIT(31)) +#define EMAC_ADDRESS_ENABLE2_V 0x1 +#define EMAC_ADDRESS_ENABLE2_S 31 +/* EMAC_SOURCE_ADDRESS2 : R/W ;bitpos:[30] ;default: 1'h0 ; */ +/*description: When this bit is set the EMACADDR2[47:0] is used to compare + with the SA fields of the received frame. When this bit is reset the EMACADDR2[47:0] is used to compare with the DA fields of the received frame.*/ +#define EMAC_SOURCE_ADDRESS2 (BIT(30)) +#define EMAC_SOURCE_ADDRESS2_M (BIT(30)) +#define EMAC_SOURCE_ADDRESS2_V 0x1 +#define EMAC_SOURCE_ADDRESS2_S 30 +/* EMAC_MASK_BYTE_CONTROL2 : R/W ;bitpos:[29:24] ;default: 6'h0 ; */ +/*description: These bits are mask control bits for comparison of each of the + EMACADDR2 bytes. When set high the MAC does not compare the corresponding byte of received DA or SA with the contents of EMACADDR2 registers. Each bit controls the masking of the bytes as follows: Bit[29]: EMACADDR2 High [15:8]. Bit[28]: EMACADDR2 High [7:0]. Bit[27]: EMACADDR2 Low [31:24]. Bit[24]: EMACADDR2 Low [7:0].You can filter a group of addresses (known as group address filtering) by masking one or more bytes of the address.*/ +#define EMAC_MASK_BYTE_CONTROL2 0x0000003F +#define EMAC_MASK_BYTE_CONTROL2_M ((EMAC_MASK_BYTE_CONTROL2_V)<<(EMAC_MASK_BYTE_CONTROL2_S)) +#define EMAC_MASK_BYTE_CONTROL2_V 0x3F +#define EMAC_MASK_BYTE_CONTROL2_S 24 +/* EMAC_MAC_ADDRESS2_HI : R/W ;bitpos:[15:0] ;default: 16'hFFFF ; */ +/*description: This field contains the upper 16 bits Bits[47:32] of the third + 6-byte MAC address.*/ +#define EMAC_MAC_ADDRESS2_HI 0x0000FFFF +#define EMAC_MAC_ADDRESS2_HI_M ((EMAC_MAC_ADDRESS2_HI_V)<<(EMAC_MAC_ADDRESS2_HI_S)) +#define EMAC_MAC_ADDRESS2_HI_V 0xFFFF +#define EMAC_MAC_ADDRESS2_HI_S 0 -#define EMAC_GMACVERSION_REG (REG_EMAC_BASE + 0x1020) -#define EMAC_USERVER 0x000000FF -#define EMAC_USERVER_M (EMAC_USERVER_V << EMAC_USERVER_S) -#define EMAC_USERVER_V 0x000000FF -#define EMAC_USERVER_S 8 -#define EMAC_SNPSVER 0x000000FF -#define EMAC_SNPSVER_M (EMAC_SNPSVER_V << EMAC_SNPSVER_S) -#define EMAC_SNPSVER_V 0x000000FF -#define EMAC_SNPSVER_S 0 +#define EMAC_ADDR2LOW_REG (DR_REG_EMAC_BASE + 0x1054) +/* EMAC_MAC_ADDRESS2_LOW : R/W ;bitpos:[31:0] ;default: 32'hFFFFFFFF ; */ +/*description: This field contains the lower 32 bits of the third 6-byte MAC + address. The content of this field is undefined so the register needs to be configured after the initialization process.*/ +#define EMAC_MAC_ADDRESS2_LOW 0xFFFFFFFF +#define EMAC_MAC_ADDRESS2_LOW_M ((EMAC_MAC_ADDRESS2_LOW_V)<<(EMAC_MAC_ADDRESS2_LOW_S)) +#define EMAC_MAC_ADDRESS2_LOW_V 0xFFFFFFFF +#define EMAC_MAC_ADDRESS2_LOW_S 0 -#define EMAC_GMACDEBUG_REG (REG_EMAC_BASE + 0x1024) -#define EMAC_MTL_TXSTATUS_FIFO_FULL_STATUS (BIT(25)) -#define EMAC_MTL_TXSTATUS_FIFO_FULL_STATUS_M (BIT(25)) -#define EMAC_MTL_TXSTATUS_FIFO_FULL_STATUS_V 1 -#define EMAC_MTL_TXSTATUS_FIFO_FULL_STATUS_S 25 -#define EMAC_MTL_TX_FIFO_NOT_EMPTY_STATUS (BIT(24)) -#define EMAC_MTL_TX_FIFO_NOT_EMPTY_STATUS_M (BIT(24)) -#define EMAC_MTL_TX_FIFO_NOT_EMPTY_STATUS_V 1 -#define EMAC_MTL_TX_FIFO_NOT_EMPTY_STATUS_S 24 -#define EMAC_MTL_TX_FIFO_WRITE_CONTROLLER_STATUS (BIT(22)) -#define EMAC_MTL_TX_FIFO_WRITE_CONTROLLER_STATUS_M (BIT(22)) -#define EMAC_MTL_TX_FIFO_WRITE_CONTROLLER_STATUS_V 1 -#define EMAC_MTL_TX_FIFO_WRITE_CONTROLLER_STATUS_S 22 -#define EMAC_MTL_TX_FIFO_READ_CONTROLLER_STATUS 0x00000003 -#define EMAC_MTL_TX_FIFO_READ_CONTROLLER_STATUS_M (EMAC_MTL_TX_FIFO_READ_CONTROLLER_STATUS_V << EMAC_MTL_TX_FIFO_READ_CONTROLLER_STATUS_S) -#define EMAC_MTL_TX_FIFO_READ_CONTROLLER_STATUS_V 0x00000003 -#define EMAC_MTL_TX_FIFO_READ_CONTROLLER_STATUS_S 20 -#define EMAC_MAC_TRANSMITTER_PAUSE (BIT(19)) -#define EMAC_MAC_TRANSMITTER_PAUSE_M (BIT(19)) -#define EMAC_MAC_TRANSMITTER_PAUSE_V 1 -#define EMAC_MAC_TRANSMITTER_PAUSE_S 19 -#define EMAC_MAC_TRANSMIT_FRAME_CONTROLLER_STATUS 0x00000003 -#define EMAC_MAC_TRANSMIT_FRAME_CONTROLLER_STATUS_M (EMAC_MAC_TRANSMIT_FRAME_CONTROLLER_STATUS_V << EMAC_MAC_TRANSMIT_FRAME_CONTROLLER_STATUS_S) -#define EMAC_MAC_TRANSMIT_FRAME_CONTROLLER_STATUS_V 0x00000003 -#define EMAC_MAC_TRANSMIT_FRAME_CONTROLLER_STATUS_S 17 -#define EMAC_MAC_TRANSMIT_PROTOCOL_ENGINE_STATUS (BIT(16)) -#define EMAC_MAC_TRANSMIT_PROTOCOL_ENGINE_STATUS_M (BIT(16)) -#define EMAC_MAC_TRANSMIT_PROTOCOL_ENGINE_STATUS_V 1 -#define EMAC_MAC_TRANSMIT_PROTOCOL_ENGINE_STATUS_S 16 -#define EMAC_MTL_RXFIFO_FILL_LEVEL_STATUS 0x00000003 -#define EMAC_MTL_RXFIFO_FILL_LEVEL_STATUS_M (EMAC_MTL_RXFIFO_FILL_LEVEL_STATUS_V << EMAC_MTL_RXFIFO_FILL_LEVEL_STATUS_S) -#define EMAC_MTL_RXFIFO_FILL_LEVEL_STATUS_V 0x00000003 -#define EMAC_MTL_RXFIFO_FILL_LEVEL_STATUS_S 8 -#define EMAC_MTL_RXFIFO_READ_CONTROLLER_STATE 0x00000003 -#define EMAC_MTL_RXFIFO_READ_CONTROLLER_STATE_M (EMAC_MTL_RXFIFO_READ_CONTROLLER_STATE_V << EMAC_MTL_RXFIFO_READ_CONTROLLER_STATE_S) -#define EMAC_MTL_RXFIFO_READ_CONTROLLER_STATE_V 0x00000003 -#define EMAC_MTL_RXFIFO_READ_CONTROLLER_STATE_S 5 -#define EMAC_MTL_RX_FIFO_WRITE_CONTROLLER_ACTIVE_STATUS (BIT(4)) -#define EMAC_MTL_RX_FIFO_WRITE_CONTROLLER_ACTIVE_STATUS_M (BIT(4)) -#define EMAC_MTL_RX_FIFO_WRITE_CONTROLLER_ACTIVE_STATUS_V 1 -#define EMAC_MTL_RX_FIFO_WRITE_CONTROLLER_ACTIVE_STATUS_S 4 -#define EMAC_MAC_RECEIVE_FRAME_FIFO_CONTROLLER_STATUS 0x00000003 -#define EMAC_MAC_RECEIVE_FRAME_FIFO_CONTROLLER_STATUS_M (EMAC_MAC_RECEIVE_FRAME_FIFO_CONTROLLER_STATUS_V << EMAC_MAC_RECEIVE_FRAME_FIFO_CONTROLLER_STATUS_S) -#define EMAC_MAC_RECEIVE_FRAME_FIFO_CONTROLLER_STATUS_V 0x00000003 -#define EMAC_MAC_RECEIVE_FRAME_FIFO_CONTROLLER_STATUS_S 1 -#define EMAC_MAC_RECEIVE_PROTOCOL_ENGINE_STATUS (BIT(0)) -#define EMAC_MAC_RECEIVE_PROTOCOL_ENGINE_STATUS_M (BIT(0)) -#define EMAC_MAC_RECEIVE_PROTOCOL_ENGINE_STATUS_V 1 -#define EMAC_MAC_RECEIVE_PROTOCOL_ENGINE_STATUS_S 0 +#define EMAC_ADDR3HIGH_REG (DR_REG_EMAC_BASE + 0x1058) +/* EMAC_ADDRESS_ENABLE3 : R/W ;bitpos:[31] ;default: 1'h0 ; */ +/*description: When this bit is set the address filter module uses the fourth + MAC address for perfect filtering. When this bit is reset the address filter module ignores the address for filtering.*/ +#define EMAC_ADDRESS_ENABLE3 (BIT(31)) +#define EMAC_ADDRESS_ENABLE3_M (BIT(31)) +#define EMAC_ADDRESS_ENABLE3_V 0x1 +#define EMAC_ADDRESS_ENABLE3_S 31 +/* EMAC_SOURCE_ADDRESS3 : R/W ;bitpos:[30] ;default: 1'h0 ; */ +/*description: When this bit is set the EMACADDR3[47:0] is used to compare + with the SA fields of the received frame. When this bit is reset the EMACADDR3[47:0] is used to compare with the DA fields of the received frame.*/ +#define EMAC_SOURCE_ADDRESS3 (BIT(30)) +#define EMAC_SOURCE_ADDRESS3_M (BIT(30)) +#define EMAC_SOURCE_ADDRESS3_V 0x1 +#define EMAC_SOURCE_ADDRESS3_S 30 +/* EMAC_MASK_BYTE_CONTROL3 : R/W ;bitpos:[29:24] ;default: 6'h0 ; */ +/*description: These bits are mask control bits for comparison of each of the + EMACADDR3 bytes. When set high the MAC does not compare the corresponding byte of received DA or SA with the contents of EMACADDR3 registers. Each bit controls the masking of the bytes as follows: Bit[29]: EMACADDR3 High [15:8]. Bit[28]: EMACADDR3 High [7:0]. Bit[27]: EMACADDR3 Low [31:24]. Bit[24]: EMACADDR3 Low [7:0].You can filter a group of addresses (known as group address filtering) by masking one or more bytes of the address.*/ +#define EMAC_MASK_BYTE_CONTROL3 0x0000003F +#define EMAC_MASK_BYTE_CONTROL3_M ((EMAC_MASK_BYTE_CONTROL3_V)<<(EMAC_MASK_BYTE_CONTROL3_S)) +#define EMAC_MASK_BYTE_CONTROL3_V 0x3F +#define EMAC_MASK_BYTE_CONTROL3_S 24 +/* EMAC_MAC_ADDRESS3_HI : R/W ;bitpos:[15:0] ;default: 16'hFFFF ; */ +/*description: This field contains the upper 16 bits Bits[47:32] of the fourth + 6-byte MAC address.*/ +#define EMAC_MAC_ADDRESS3_HI 0x0000FFFF +#define EMAC_MAC_ADDRESS3_HI_M ((EMAC_MAC_ADDRESS3_HI_V)<<(EMAC_MAC_ADDRESS3_HI_S)) +#define EMAC_MAC_ADDRESS3_HI_V 0xFFFF +#define EMAC_MAC_ADDRESS3_HI_S 0 -#define EMAC_GMACLPITIMERSCONTROL_REG (REG_EMAC_BASE + 0x1034) -#define EMAC_LPI_LS_TIMER 0x000003FF -#define EMAC_LPI_LS_TIMER_M (EMAC_LPI_LS_TIMER_V << EMAC_LPI_LS_TIMER_S) -#define EMAC_LPI_LS_TIMER_V 0x000003FF -#define EMAC_LPI_LS_TIMER_S 16 -#define EMAC_LPI_TW_TIMER 0x0000FFFF -#define EMAC_LPI_TW_TIMER_M (EMAC_LPI_TW_TIMER_V << EMAC_LPI_TW_TIMER_S) -#define EMAC_LPI_TW_TIMER_V 0x0000FFFF -#define EMAC_LPI_TW_TIMER_S 0 +#define EMAC_ADDR3LOW_REG (DR_REG_EMAC_BASE + 0x105C) +/* EMAC_MAC_ADDRESS3_LOW : R/W ;bitpos:[31:0] ;default: 32'hFFFFFFFF ; */ +/*description: This field contains the lower 32 bits of the fourth 6-byte MAC + address.The content of this field is undefined so the register needs to be configured after the initialization Process.*/ +#define EMAC_MAC_ADDRESS3_LOW 0xFFFFFFFF +#define EMAC_MAC_ADDRESS3_LOW_M ((EMAC_MAC_ADDRESS3_LOW_V)<<(EMAC_MAC_ADDRESS3_LOW_S)) +#define EMAC_MAC_ADDRESS3_LOW_V 0xFFFFFFFF +#define EMAC_MAC_ADDRESS3_LOW_S 0 -#define EMAC_GMACINTERRUPTSTATUS_REG (REG_EMAC_BASE + 0x1038) -#define EMAC_GPI_INTERRUPT_STATUS (BIT(11)) -#define EMAC_GPI_INTERRUPT_STATUS_M (BIT(11)) -#define EMAC_GPI_INTERRUPT_STATUS_V 1 -#define EMAC_GPI_INTERRUPT_STATUS_S 11 -#define EMAC_LPI_INTERRUPT_STATUS (BIT(10)) -#define EMAC_LPI_INTERRUPT_STATUS_M (BIT(10)) -#define EMAC_LPI_INTERRUPT_STATUS_V 1 -#define EMAC_LPI_INTERRUPT_STATUS_S 10 -#define EMAC_TIMESTAMP_INTERRUP_STATUS (BIT(9)) -#define EMAC_TIMESTAMP_INTERRUP_STATUS_M (BIT(9)) -#define EMAC_TIMESTAMP_INTERRUP_STATUS_V 1 -#define EMAC_TIMESTAMP_INTERRUP_STATUS_S 9 -#define EMAC_MMC_RECEIVE_CHECKSUM_OFFLOAD_INTERRUPT_STATUS (BIT(7)) -#define EMAC_MMC_RECEIVE_CHECKSUM_OFFLOAD_INTERRUPT_STATUS_M (BIT(7)) -#define EMAC_MMC_RECEIVE_CHECKSUM_OFFLOAD_INTERRUPT_STATUS_V 1 -#define EMAC_MMC_RECEIVE_CHECKSUM_OFFLOAD_INTERRUPT_STATUS_S 7 -#define EMAC_MMC_TRANSMIT_INTERRUPT_STATUS (BIT(6)) -#define EMAC_MMC_TRANSMIT_INTERRUPT_STATUS_M (BIT(6)) -#define EMAC_MMC_TRANSMIT_INTERRUPT_STATUS_V 1 -#define EMAC_MMC_TRANSMIT_INTERRUPT_STATUS_S 6 -#define EMAC_MMC_RECEIVE_INTERRUPT_STATUS (BIT(5)) -#define EMAC_MMC_RECEIVE_INTERRUPT_STATUS_M (BIT(5)) -#define EMAC_MMC_RECEIVE_INTERRUPT_STATUS_V 1 -#define EMAC_MMC_RECEIVE_INTERRUPT_STATUS_S 5 -#define EMAC_MMC_INTERRUPT_STATUS (BIT(4)) -#define EMAC_MMC_INTERRUPT_STATUS_M (BIT(4)) -#define EMAC_MMC_INTERRUPT_STATUS_V 1 -#define EMAC_MMC_INTERRUPT_STATUS_S 4 -#define EMAC_PMT_INTERRUPT_STATUS (BIT(3)) -#define EMAC_PMT_INTERRUPT_STATUS_M (BIT(3)) -#define EMAC_PMT_INTERRUPT_STATUS_V 1 -#define EMAC_PMT_INTERRUPT_STATUS_S 3 -#define EMAC_PCS_AUTO_NEGOTIATION_COMPLETE (BIT(2)) -#define EMAC_PCS_AUTO_NEGOTIATION_COMPLETE_M (BIT(2)) -#define EMAC_PCS_AUTO_NEGOTIATION_COMPLETE_V 1 -#define EMAC_PCS_AUTO_NEGOTIATION_COMPLETE_S 2 -#define EMAC_PCS_LINK_STATUS_CHANGED (BIT(1)) -#define EMAC_PCS_LINK_STATUS_CHANGED_M (BIT(1)) -#define EMAC_PCS_LINK_STATUS_CHANGED_V 1 -#define EMAC_PCS_LINK_STATUS_CHANGED_S 1 -#define EMAC_INTERRUPT_STATUS (BIT(0)) -#define EMAC_INTERRUPT_STATUS_M (BIT(0)) -#define EMAC_INTERRUPT_STATUS_V 1 -#define EMAC_INTERRUPT_STATUS_S 0 +#define EMAC_ADDR4HIGH_REG (DR_REG_EMAC_BASE + 0x1060) +/* EMAC_ADDRESS_ENABLE4 : R/W ;bitpos:[31] ;default: 1'h0 ; */ +/*description: When this bit is set the address filter module uses the fifth + MAC address for perfect filtering. When this bit is reset the address filter module ignores the address for filtering.*/ +#define EMAC_ADDRESS_ENABLE4 (BIT(31)) +#define EMAC_ADDRESS_ENABLE4_M (BIT(31)) +#define EMAC_ADDRESS_ENABLE4_V 0x1 +#define EMAC_ADDRESS_ENABLE4_S 31 +/* EMAC_SOURCE_ADDRESS4 : R/W ;bitpos:[30] ;default: 1'h0 ; */ +/*description: When this bit is set the EMACADDR4[47:0] is used to compare + with the SA fields of the received frame. When this bit is reset the EMACADDR4[47:0] is used to compare with the DA fields of the received frame.*/ +#define EMAC_SOURCE_ADDRESS4 (BIT(30)) +#define EMAC_SOURCE_ADDRESS4_M (BIT(30)) +#define EMAC_SOURCE_ADDRESS4_V 0x1 +#define EMAC_SOURCE_ADDRESS4_S 30 +/* EMAC_MASK_BYTE_CONTROL4 : R/W ;bitpos:[29:24] ;default: 6'h0 ; */ +/*description: These bits are mask control bits for comparison of each of the + EMACADDR4 bytes. When set high the MAC does not compare the corresponding byte of received DA or SA with the contents of EMACADDR4 registers. Each bit controls the masking of the bytes as follows: Bit[29]: EMACADDR4 High [15:8]. Bit[28]: EMACADDR4 High [7:0]. Bit[27]: EMACADDR4 Low [31:24]. Bit[24]: EMACADDR4 Low [7:0].You can filter a group of addresses (known as group address filtering) by masking one or more bytes of the address.*/ +#define EMAC_MASK_BYTE_CONTROL4 0x0000003F +#define EMAC_MASK_BYTE_CONTROL4_M ((EMAC_MASK_BYTE_CONTROL4_V)<<(EMAC_MASK_BYTE_CONTROL4_S)) +#define EMAC_MASK_BYTE_CONTROL4_V 0x3F +#define EMAC_MASK_BYTE_CONTROL4_S 24 +/* EMAC_MAC_ADDRESS4_HI : R/W ;bitpos:[15:0] ;default: 16'hFFFF ; */ +/*description: This field contains the upper 16 bits Bits[47:32] of the fifth + 6-byte MAC address.*/ +#define EMAC_MAC_ADDRESS4_HI 0x0000FFFF +#define EMAC_MAC_ADDRESS4_HI_M ((EMAC_MAC_ADDRESS4_HI_V)<<(EMAC_MAC_ADDRESS4_HI_S)) +#define EMAC_MAC_ADDRESS4_HI_V 0xFFFF +#define EMAC_MAC_ADDRESS4_HI_S 0 -#define EMAC_GMACINTERRUPTMASK_REG (REG_EMAC_BASE + 0x103C) -#define EMAC_LPI_INTERRUPT_MASK (BIT(10)) -#define EMAC_LPI_INTERRUPT_MASK_M (BIT(10)) -#define EMAC_LPI_INTERRUPT_MASK_V 1 -#define EMAC_LPI_INTERRUPT_MASK_S 10 -#define EMAC_TIMESTAMP_INTERRUPT_MASK (BIT(9)) -#define EMAC_TIMESTAMP_INTERRUPT_MASK_M (BIT(9)) -#define EMAC_TIMESTAMP_INTERRUPT_MASK_V 1 -#define EMAC_TIMESTAMP_INTERRUPT_MASK_S 9 -#define EMAC_PMT_INTERRUPT_MASK (BIT(3)) -#define EMAC_PMT_INTERRUPT_MASK_M (BIT(3)) -#define EMAC_PMT_INTERRUPT_MASK_V 1 -#define EMAC_PMT_INTERRUPT_MASK_S 3 -#define EMAC_PCS_AN_COMPLETION_INTERRUPT_MASK (BIT(2)) -#define EMAC_PCS_AN_COMPLETION_INTERRUPT_MASK_M (BIT(2)) -#define EMAC_PCS_AN_COMPLETION_INTERRUPT_MASK_V 1 -#define EMAC_PCS_AN_COMPLETION_INTERRUPT_MASK_S 2 -#define EMAC_PCS_LINK_STATUS_INTERRUPT_MASK (BIT(1)) -#define EMAC_PCS_LINK_STATUS_INTERRUPT_MASK_M (BIT(1)) -#define EMAC_PCS_LINK_STATUS_INTERRUPT_MASK_V 1 -#define EMAC_PCS_LINK_STATUS_INTERRUPT_MASK_S 1 -#define EMAC_INTERRUPT_MASK (BIT(0)) -#define EMAC_INTERRUPT_MASK_M (BIT(0)) -#define EMAC_INTERRUPT_MASK_V 1 -#define EMAC_INTERRUPT_MASK_S 0 +#define EMAC_ADDR4LOW_REG (DR_REG_EMAC_BASE + 0x1064) +/* EMAC_MAC_ADDRESS4_LOW : R/W ;bitpos:[31:0] ;default: 32'hFFFFFFFF ; */ +/*description: This field contains the lower 32 bits of the fifth 6-byte MAC + address. The content of this field is undefined so the register needs to be configured after the initialization process.*/ +#define EMAC_MAC_ADDRESS4_LOW 0xFFFFFFFF +#define EMAC_MAC_ADDRESS4_LOW_M ((EMAC_MAC_ADDRESS4_LOW_V)<<(EMAC_MAC_ADDRESS4_LOW_S)) +#define EMAC_MAC_ADDRESS4_LOW_V 0xFFFFFFFF +#define EMAC_MAC_ADDRESS4_LOW_S 0 -#define EMAC_GMACADDR0HIGH_REG (REG_EMAC_BASE + 0x1040) -#define EMAC_ADDRESS_ENABLE0 (BIT(31)) -#define EMAC_ADDRESS_ENABLE0_M (BIT(31)) -#define EMAC_ADDRESS_ENABLE0_V 1 -#define EMAC_ADDRESS_ENABLE0_S 31 -#define EMAC_MAC_ADDRESS0_HI 0x0000FFFF -#define EMAC_MAC_ADDRESS0_HI_M (EMAC_MAC_ADDRESS0_HI_V << EMAC_MAC_ADDRESS0_HI_S) -#define EMAC_MAC_ADDRESS0_HI_V 0x0000FFFF -#define EMAC_MAC_ADDRESS0_HI_S 0 +#define EMAC_ADDR5HIGH_REG (DR_REG_EMAC_BASE + 0x1068) +/* EMAC_ADDRESS_ENABLE5 : R/W ;bitpos:[31] ;default: 1'h0 ; */ +/*description: When this bit is set the address filter module uses the sixth + MAC address for perfect filtering. When this bit is reset the address filter module ignores the address for filtering.*/ +#define EMAC_ADDRESS_ENABLE5 (BIT(31)) +#define EMAC_ADDRESS_ENABLE5_M (BIT(31)) +#define EMAC_ADDRESS_ENABLE5_V 0x1 +#define EMAC_ADDRESS_ENABLE5_S 31 +/* EMAC_SOURCE_ADDRESS5 : R/W ;bitpos:[30] ;default: 1'h0 ; */ +/*description: When this bit is set the EMACADDR5[47:0] is used to compare + with the SA fields of the received frame. When this bit is reset the EMACADDR5[47:0] is used to compare with the DA fields of the received frame.*/ +#define EMAC_SOURCE_ADDRESS5 (BIT(30)) +#define EMAC_SOURCE_ADDRESS5_M (BIT(30)) +#define EMAC_SOURCE_ADDRESS5_V 0x1 +#define EMAC_SOURCE_ADDRESS5_S 30 +/* EMAC_MASK_BYTE_CONTROL5 : R/W ;bitpos:[29:24] ;default: 6'h0 ; */ +/*description: These bits are mask control bits for comparison of each of the + EMACADDR5 bytes. When set high the MAC does not compare the corresponding byte of received DA or SA with the contents of EMACADDR5 registers. Each bit controls the masking of the bytes as follows: Bit[29]: EMACADDR5 High [15:8]. Bit[28]: EMACADDR5 High [7:0]. Bit[27]: EMACADDR5 Low [31:24]. Bit[24]: EMACADDR5 Low [7:0].You can filter a group of addresses (known as group address filtering) by masking one or more bytes of the address.*/ +#define EMAC_MASK_BYTE_CONTROL5 0x0000003F +#define EMAC_MASK_BYTE_CONTROL5_M ((EMAC_MASK_BYTE_CONTROL5_V)<<(EMAC_MASK_BYTE_CONTROL5_S)) +#define EMAC_MASK_BYTE_CONTROL5_V 0x3F +#define EMAC_MASK_BYTE_CONTROL5_S 24 +/* EMAC_MAC_ADDRESS5_HI : R/W ;bitpos:[15:0] ;default: 16'hFFFF ; */ +/*description: This field contains the upper 16 bits Bits[47:32] of the sixth + 6-byte MAC address.*/ +#define EMAC_MAC_ADDRESS5_HI 0x0000FFFF +#define EMAC_MAC_ADDRESS5_HI_M ((EMAC_MAC_ADDRESS5_HI_V)<<(EMAC_MAC_ADDRESS5_HI_S)) +#define EMAC_MAC_ADDRESS5_HI_V 0xFFFF +#define EMAC_MAC_ADDRESS5_HI_S 0 -#define EMAC_GMACADDR0LOW_REG (REG_EMAC_BASE + 0x1044) -#define EMAC_MAC_ADDRESS0_LOW 0xFFFFFFFF -#define EMAC_MAC_ADDRESS0_LOW_M (EMAC_MAC_ADDRESS0_LOW_V << EMAC_MAC_ADDRESS0_LOW_S) -#define EMAC_MAC_ADDRESS0_LOW_V 0xFFFFFFFF -#define EMAC_MAC_ADDRESS0_LOW_S 0 +#define EMAC_ADDR5LOW_REG (DR_REG_EMAC_BASE + 0x106C) +/* EMAC_MAC_ADDRESS5_LOW : R/W ;bitpos:[31:0] ;default: 32'hFFFFFFFF ; */ +/*description: This field contains the lower 32 bits of the sixth 6-byte MAC + address. The content of this field is undefined so the register needs to be configured after the initialization process.*/ +#define EMAC_MAC_ADDRESS5_LOW 0xFFFFFFFF +#define EMAC_MAC_ADDRESS5_LOW_M ((EMAC_MAC_ADDRESS5_LOW_V)<<(EMAC_MAC_ADDRESS5_LOW_S)) +#define EMAC_MAC_ADDRESS5_LOW_V 0xFFFFFFFF +#define EMAC_MAC_ADDRESS5_LOW_S 0 -#define EMAC_GMACADDR1HIGH_REG (REG_EMAC_BASE + 0x1048) -#define EMAC_ADDRESS_ENABLE1 (BIT(31)) -#define EMAC_ADDRESS_ENABLE1_M (BIT(31)) -#define EMAC_ADDRESS_ENABLE1_V 1 -#define EMAC_ADDRESS_ENABLE1_S 31 -#define EMAC_SOURCE_ADDRESS (BIT(30)) -#define EMAC_SOURCE_ADDRESS_M (BIT(30)) -#define EMAC_SOURCE_ADDRESS_V 1 -#define EMAC_SOURCE_ADDRESS_S 30 -#define EMAC_MASK_BYTE_CONTROL 0x0000003F -#define EMAC_MASK_BYTE_CONTROL_M (EMAC_MASK_BYTE_CONTROL_V << EMAC_MASK_BYTE_CONTROL_S) -#define EMAC_MASK_BYTE_CONTROL_V 0x0000003F -#define EMAC_MASK_BYTE_CONTROL_S 24 -#define EMAC_MAC_ADDRESS1_HI 0x0000FFFF -#define EMAC_MAC_ADDRESS1_HI_M (EMAC_MAC_ADDRESS1_HI_V << EMAC_MAC_ADDRESS1_HI_S) -#define EMAC_MAC_ADDRESS1_HI_V 0x0000FFFF -#define EMAC_MAC_ADDRESS1_HI_S 0 +#define EMAC_ADDR6HIGH_REG (DR_REG_EMAC_BASE + 0x1070) +/* EMAC_ADDRESS_ENABLE6 : R/W ;bitpos:[31] ;default: 1'h0 ; */ +/*description: When this bit is set the address filter module uses the seventh + MAC address for perfect filtering. When this bit is reset the address filter module ignores the address for filtering.*/ +#define EMAC_ADDRESS_ENABLE6 (BIT(31)) +#define EMAC_ADDRESS_ENABLE6_M (BIT(31)) +#define EMAC_ADDRESS_ENABLE6_V 0x1 +#define EMAC_ADDRESS_ENABLE6_S 31 +/* EMAC_SOURCE_ADDRESS6 : R/W ;bitpos:[30] ;default: 1'h0 ; */ +/*description: When this bit is set the EMACADDR6[47:0] is used to compare + with the SA fields of the received frame. When this bit is reset the EMACADDR6[47:0] is used to compare with the DA fields of the received frame.*/ +#define EMAC_SOURCE_ADDRESS6 (BIT(30)) +#define EMAC_SOURCE_ADDRESS6_M (BIT(30)) +#define EMAC_SOURCE_ADDRESS6_V 0x1 +#define EMAC_SOURCE_ADDRESS6_S 30 +/* EMAC_MASK_BYTE_CONTROL6 : R/W ;bitpos:[29:24] ;default: 6'h0 ; */ +/*description: These bits are mask control bits for comparison of each of the + EMACADDR6 bytes. When set high the MAC does not compare the corresponding byte of received DA or SA with the contents of EMACADDR6 registers. Each bit controls the masking of the bytes as follows: Bit[29]: EMACADDR6 High [15:8]. Bit[28]: EMACADDR6 High [7:0]. Bit[27]: EMACADDR6 Low [31:24]. Bit[24]: EMACADDR6 Low [7:0].You can filter a group of addresses (known as group address filtering) by masking one or more bytes of the address.*/ +#define EMAC_MASK_BYTE_CONTROL6 0x0000003F +#define EMAC_MASK_BYTE_CONTROL6_M ((EMAC_MASK_BYTE_CONTROL6_V)<<(EMAC_MASK_BYTE_CONTROL6_S)) +#define EMAC_MASK_BYTE_CONTROL6_V 0x3F +#define EMAC_MASK_BYTE_CONTROL6_S 24 +/* EMAC_MAC_ADDRESS6_HI : R/W ;bitpos:[15:0] ;default: 16'hFFFF ; */ +/*description: This field contains the upper 16 bits Bits[47:32] of the seventh + 6-byte MAC Address.*/ +#define EMAC_MAC_ADDRESS6_HI 0x0000FFFF +#define EMAC_MAC_ADDRESS6_HI_M ((EMAC_MAC_ADDRESS6_HI_V)<<(EMAC_MAC_ADDRESS6_HI_S)) +#define EMAC_MAC_ADDRESS6_HI_V 0xFFFF +#define EMAC_MAC_ADDRESS6_HI_S 0 -#define EMAC_GMACADDR1LOW_REG (REG_EMAC_BASE + 0x104C) -#define EMAC_MAC_ADDRESS1_LOW 0xFFFFFFFF -#define EMAC_MAC_ADDRESS1_LOW_M (EMAC_MAC_ADDRESS1_LOW_V << EMAC_MAC_ADDRESS1_LOW_S) -#define EMAC_MAC_ADDRESS1_LOW_V 0xFFFFFFFF -#define EMAC_MAC_ADDRESS1_LOW_S 0 +#define EMAC_ADDR6LOW_REG (DR_REG_EMAC_BASE + 0x1074) +/* EMAC_MAC_ADDRESS6_LOW : R/W ;bitpos:[31:0] ;default: 32'hFFFFFFFF ; */ +/*description: This field contains the lower 32 bits of the seventh 6-byte MAC + address.The content of this field is undefined so the register needs to be configured after the initialization Process.*/ +#define EMAC_MAC_ADDRESS6_LOW 0xFFFFFFFF +#define EMAC_MAC_ADDRESS6_LOW_M ((EMAC_MAC_ADDRESS6_LOW_V)<<(EMAC_MAC_ADDRESS6_LOW_S)) +#define EMAC_MAC_ADDRESS6_LOW_V 0xFFFFFFFF +#define EMAC_MAC_ADDRESS6_LOW_S 0 -#define EMAC_GMAC_AN_CONTROL_REG (REG_EMAC_BASE + 0x10C0) -#define EMAC_SGMII_RAL_CONTROL (BIT(18)) -#define EMAC_SGMII_RAL_CONTROL_M (BIT(18)) -#define EMAC_SGMII_RAL_CONTROL_V 1 -#define EMAC_SGMII_RAL_CONTROL_S 18 -#define EMAC_LOCK_REFERENCE (BIT(17)) -#define EMAC_LOCK_REFERENCE_M (BIT(17)) -#define EMAC_LOCK_REFERENCE_V 1 -#define EMAC_LOCK_REFERENCE_S 17 -#define EMAC_ENABLE_COMMA_DETECT (BIT(16)) -#define EMAC_ENABLE_COMMA_DETECT_M (BIT(16)) -#define EMAC_ENABLE_COMMA_DETECT_V 1 -#define EMAC_ENABLE_COMMA_DETECT_S 16 -#define EMAC_EXTERNAL_LOOPBACK_ENABLE (BIT(14)) -#define EMAC_EXTERNAL_LOOPBACK_ENABLE_M (BIT(14)) -#define EMAC_EXTERNAL_LOOPBACK_ENABLE_V 1 -#define EMAC_EXTERNAL_LOOPBACK_ENABLE_S 14 -#define EMAC_AUTO_NEGOTIATION_ENABLE (BIT(12)) -#define EMAC_AUTO_NEGOTIATION_ENABLE_M (BIT(12)) -#define EMAC_AUTO_NEGOTIATION_ENABLE_V 1 -#define EMAC_AUTO_NEGOTIATION_ENABLE_S 12 -#define EMAC_RESTART_AUTO_NEGOTIATION (BIT(9)) -#define EMAC_RESTART_AUTO_NEGOTIATION_M (BIT(9)) -#define EMAC_RESTART_AUTO_NEGOTIATION_V 1 -#define EMAC_RESTART_AUTO_NEGOTIATION_S 9 +#define EMAC_ADDR7HIGH_REG (DR_REG_EMAC_BASE + 0x1078) +/* EMAC_ADDRESS_ENABLE7 : R/W ;bitpos:[31] ;default: 1'h0 ; */ +/*description: When this bit is set the address filter module uses the eighth + MAC address for perfect filtering. When this bit is reset the address filter module ignores the address for filtering.*/ +#define EMAC_ADDRESS_ENABLE7 (BIT(31)) +#define EMAC_ADDRESS_ENABLE7_M (BIT(31)) +#define EMAC_ADDRESS_ENABLE7_V 0x1 +#define EMAC_ADDRESS_ENABLE7_S 31 +/* EMAC_SOURCE_ADDRESS7 : R/W ;bitpos:[30] ;default: 1'h0 ; */ +/*description: When this bit is set the EMACADDR7[47:0] is used to compare + with the SA fields of the received frame. When this bit is reset the EMACADDR7[47:0] is used to compare with the DA fields of the received frame.*/ +#define EMAC_SOURCE_ADDRESS7 (BIT(30)) +#define EMAC_SOURCE_ADDRESS7_M (BIT(30)) +#define EMAC_SOURCE_ADDRESS7_V 0x1 +#define EMAC_SOURCE_ADDRESS7_S 30 +/* EMAC_MASK_BYTE_CONTROL7 : R/W ;bitpos:[29:24] ;default: 6'h0 ; */ +/*description: These bits are mask control bits for comparison of each of the + EMACADDR7 bytes. When set high the MAC does not compare the corresponding byte of received DA or SA with the contents of EMACADDR7 registers. Each bit controls the masking of the bytes as follows: Bit[29]: EMACADDR7 High [15:8]. Bit[28]: EMACADDR7 High [7:0]. Bit[27]: EMACADDR7 Low [31:24]. Bit[24]: EMACADDR7 Low [7:0].You can filter a group of addresses (known as group address filtering) by masking one or more bytes of the address.*/ +#define EMAC_MASK_BYTE_CONTROL7 0x0000003F +#define EMAC_MASK_BYTE_CONTROL7_M ((EMAC_MASK_BYTE_CONTROL7_V)<<(EMAC_MASK_BYTE_CONTROL7_S)) +#define EMAC_MASK_BYTE_CONTROL7_V 0x3F +#define EMAC_MASK_BYTE_CONTROL7_S 24 +/* EMAC_MAC_ADDRESS7_HI : R/W ;bitpos:[15:0] ;default: 16'hFFFF ; */ +/*description: This field contains the upper 16 bits Bits[47:32] of the eighth + 6-byte MAC Address.*/ +#define EMAC_MAC_ADDRESS7_HI 0x0000FFFF +#define EMAC_MAC_ADDRESS7_HI_M ((EMAC_MAC_ADDRESS7_HI_V)<<(EMAC_MAC_ADDRESS7_HI_S)) +#define EMAC_MAC_ADDRESS7_HI_V 0xFFFF +#define EMAC_MAC_ADDRESS7_HI_S 0 -#define EMAC_GMAC_AN_STATUS_REG (REG_EMAC_BASE + 0x10C4) -#define EMAC_EXTENDED_STATUS (BIT(8)) -#define EMAC_EXTENDED_STATUS_M (BIT(8)) -#define EMAC_EXTENDED_STATUS_V 1 -#define EMAC_EXTENDED_STATUS_S 8 -#define EMAC_AUTO_NEGOTIATION_COMPLETE (BIT(5)) -#define EMAC_AUTO_NEGOTIATION_COMPLETE_M (BIT(5)) -#define EMAC_AUTO_NEGOTIATION_COMPLETE_V 1 -#define EMAC_AUTO_NEGOTIATION_COMPLETE_S 5 -#define EMAC_AUTO_NEGOTIATION_ABILITY (BIT(3)) -#define EMAC_AUTO_NEGOTIATION_ABILITY_M (BIT(3)) -#define EMAC_AUTO_NEGOTIATION_ABILITY_V 1 -#define EMAC_AUTO_NEGOTIATION_ABILITY_S 3 -#define EMAC_LINK_AN_STATUS (BIT(2)) -#define EMAC_LINK_AN_STATUS_M (BIT(2)) -#define EMAC_LINK_AN_STATUS_V 1 -#define EMAC_LINK_AN_STATUS_S 2 +#define EMAC_ADDR7LOW_REG (DR_REG_EMAC_BASE + 0x107C) +/* EMAC_MAC_ADDRESS7_LOW : R/W ;bitpos:[31:0] ;default: 32'hFFFFFFFF ; */ +/*description: This field contains the lower 32 bits of the eighth 6-byte MAC + address.The content of this field is undefined so the register needs to be configured after the initialization Process.*/ +#define EMAC_MAC_ADDRESS7_LOW 0xFFFFFFFF +#define EMAC_MAC_ADDRESS7_LOW_M ((EMAC_MAC_ADDRESS7_LOW_V)<<(EMAC_MAC_ADDRESS7_LOW_S)) +#define EMAC_MAC_ADDRESS7_LOW_V 0xFFFFFFFF +#define EMAC_MAC_ADDRESS7_LOW_S 0 -#define EMAC_GMAC_AUTO_NEGOTIATION_ADVERTISEMENT_REG (REG_EMAC_BASE + 0x10C8) -#define EMAC_ADV_NEXT_PAGE_SUPPORT (BIT(15)) -#define EMAC_ADV_NEXT_PAGE_SUPPORT_M (BIT(15)) -#define EMAC_ADV_NEXT_PAGE_SUPPORT_V 1 -#define EMAC_ADV_NEXT_PAGE_SUPPORT_S 15 -#define EMAC_ADV_REMOTE_FAULT_ENCODING 0x00000003 -#define EMAC_ADV_REMOTE_FAULT_ENCODING_M (EMAC_ADV_REMOTE_FAULT_ENCODING_V << EMAC_ADV_REMOTE_FAULT_ENCODING_S) -#define EMAC_ADV_REMOTE_FAULT_ENCODING_V 0x00000003 -#define EMAC_ADV_REMOTE_FAULT_ENCODING_S 12 -#define EMAC_ADV_PAUSE_ENCODING 0x00000003 -#define EMAC_ADV_PAUSE_ENCODING_M (EMAC_ADV_PAUSE_ENCODING_V << EMAC_ADV_PAUSE_ENCODING_S) -#define EMAC_ADV_PAUSE_ENCODING_V 0x00000003 -#define EMAC_ADV_PAUSE_ENCODING_S 7 -#define EMAC_ADV_HALF_DUPLEX (BIT(6)) -#define EMAC_ADV_HALF_DUPLEX_M (BIT(6)) -#define EMAC_ADV_HALF_DUPLEX_V 1 -#define EMAC_ADV_HALF_DUPLEX_S 6 -#define EMAC_ADV_FULL_DUPLEX (BIT(5)) -#define EMAC_ADV_FULL_DUPLEX_M (BIT(5)) -#define EMAC_ADV_FULL_DUPLEX_V 1 -#define EMAC_ADV_FULL_DUPLEX_S 5 +#define EMAC_CSTATUS_REG (DR_REG_EMAC_BASE + 0x10D8) +/* EMAC_JABBER_TIMEOUT : RO ;bitpos:[4] ;default: 1'h0 ; */ +/*description: This bit indicates whether there is jabber timeout error (1'b1) + in the received Frame.*/ +#define EMAC_JABBER_TIMEOUT (BIT(4)) +#define EMAC_JABBER_TIMEOUT_M (BIT(4)) +#define EMAC_JABBER_TIMEOUT_V 0x1 +#define EMAC_JABBER_TIMEOUT_S 4 +/* EMAC_LINK_SPEED : RO ;bitpos:[2:1] ;default: 1'h0 ; */ +/*description: This bit indicates the current speed of the link: 2'b00: 2.5 + MHz. 2'b01: 25 MHz. 2'b10: 125 MHz.*/ +#define EMAC_LINK_SPEED 0x00000003 +#define EMAC_LINK_SPEED_M ((EMAC_LINK_SPEED_V)<<(EMAC_LINK_SPEED_S)) +#define EMAC_LINK_SPEED_V 0x3 +#define EMAC_LINK_SPEED_S 1 +/* EMAC_LINK_MODE : RO ;bitpos:[0] ;default: 1'h0 ; */ +/*description: This bit indicates the current mode of operation of the link: + 1'b0: Half-duplex mode. 1'b1: Full-duplex mode.*/ +#define EMAC_LINK_MODE (BIT(0)) +#define EMAC_LINK_MODE_M (BIT(0)) +#define EMAC_LINK_MODE_V 0x1 +#define EMAC_LINK_MODE_S 0 -#define EMAC_GMAC_AUTO_NEGOTIATION_LINK_PARTNER_ABILITY_REG (REG_EMAC_BASE + 0x10CC) -#define EMAC_LINK_NEXT_PAGE_SUPPORT (BIT(15)) -#define EMAC_LINK_NEXT_PAGE_SUPPORT_M (BIT(15)) -#define EMAC_LINK_NEXT_PAGE_SUPPORT_V 1 -#define EMAC_LINK_NEXT_PAGE_SUPPORT_S 15 -#define EMAC_LINK_ACKNOWLEDGE (BIT(14)) -#define EMAC_LINK_ACKNOWLEDGE_M (BIT(14)) -#define EMAC_LINK_ACKNOWLEDGE_V 1 -#define EMAC_LINK_ACKNOWLEDGE_S 14 -#define EMAC_LINK_REMOTE_FAULT_ENCODING 0x00000003 -#define EMAC_LINK_REMOTE_FAULT_ENCODING_M (EMAC_LINK_REMOTE_FAULT_ENCODING_V << EMAC_LINK_REMOTE_FAULT_ENCODING_S) -#define EMAC_LINK_REMOTE_FAULT_ENCODING_V 0x00000003 -#define EMAC_LINK_REMOTE_FAULT_ENCODING_S 12 -#define EMAC_LINK_PAUSE_ENCODING 0x00000003 -#define EMAC_LINK_PAUSE_ENCODING_M (EMAC_LINK_PAUSE_ENCODING_V << EMAC_LINK_PAUSE_ENCODING_S) -#define EMAC_LINK_PAUSE_ENCODING_V 0x00000003 -#define EMAC_LINK_PAUSE_ENCODING_S 7 -#define EMAC_LINK_HALF_DUPLEX (BIT(6)) -#define EMAC_LINK_HALF_DUPLEX_M (BIT(6)) -#define EMAC_LINK_HALF_DUPLEX_V 1 -#define EMAC_LINK_HALF_DUPLEX_S 6 -#define EMAC_LINK_FULL_DUPLEX (BIT(5)) -#define EMAC_LINK_FULL_DUPLEX_M (BIT(5)) -#define EMAC_LINK_FULL_DUPLEX_V 1 -#define EMAC_LINK_FULL_DUPLEX_S 5 - -#define EMAC_GMAC_AUTO_NEGOTIATION_EXPANSION_REG (REG_EMAC_BASE + 0x10D0) -#define EMAC_NEXT_PAGE_ABILITY (BIT(2)) -#define EMAC_NEXT_PAGE_ABILITY_M (BIT(2)) -#define EMAC_NEXT_PAGE_ABILITY_V 1 -#define EMAC_NEXT_PAGE_ABILITY_S 2 -#define EMAC_NEW_PAGE_RECEIVED (BIT(1)) -#define EMAC_NEW_PAGE_RECEIVED_M (BIT(1)) -#define EMAC_NEW_PAGE_RECEIVED_V 1 -#define EMAC_NEW_PAGE_RECEIVED_S 1 - -#define EMAC_GMAC_TBI_EXTENDED_STATUS_REG (REG_EMAC_BASE + 0x10D4) -#define EMAC_1000BASE_X_FULL_DUPLEX_CAPABLE (BIT(15)) -#define EMAC_1000BASE_X_FULL_DUPLEX_CAPABLE_M (BIT(15)) -#define EMAC_1000BASE_X_FULL_DUPLEX_CAPABLE_V 1 -#define EMAC_1000BASE_X_FULL_DUPLEX_CAPABLE_S 15 -#define EMAC_1000BASE_X_HALF_DUPLEX_CAPABLE (BIT(14)) -#define EMAC_1000BASE_X_HALF_DUPLEX_CAPABLE_M (BIT(14)) -#define EMAC_1000BASE_X_HALF_DUPLEX_CAPABLE_V 1 -#define EMAC_1000BASE_X_HALF_DUPLEX_CAPABLE_S 14 - -#define EMAC_GMAC_CONTROL_STATUS_REG (REG_EMAC_BASE + 0x10D8) -#define EMAC_SMIDRXS (BIT(16)) -#define EMAC_SMIDRXS_M (BIT(16)) -#define EMAC_SMIDRXS_V 1 -#define EMAC_SMIDRXS_S 16 -#define EMAC_FALSE_CARRIER_DETECTED (BIT(5)) -#define EMAC_FALSE_CARRIER_DETECTED_M (BIT(5)) -#define EMAC_FALSE_CARRIER_DETECTED_V 1 -#define EMAC_FALSE_CARRIER_DETECTED_S 5 -#define EMAC_JABBER_TIMEOUT (BIT(4)) -#define EMAC_JABBER_TIMEOUT_M (BIT(4)) -#define EMAC_JABBER_TIMEOUT_V 1 -#define EMAC_JABBER_TIMEOUT_S 4 -#define EMAC_LINK_STATUS (BIT(3)) -#define EMAC_LINK_STATUS_M (BIT(3)) -#define EMAC_LINK_STATUS_V 1 -#define EMAC_LINK_STATUS_S 3 -#define EMAC_LINK_SPEED 0x00000003 -#define EMAC_LINK_SPEED_M (EMAC_LINK_SPEED_V << EMAC_LINK_SPEED_S) -#define EMAC_LINK_SPEED_V 0x00000003 -#define EMAC_LINK_SPEED_S 1 -#define EMAC_LINK_MODE (BIT(0)) -#define EMAC_LINK_MODE_M (BIT(0)) -#define EMAC_LINK_MODE_V 1 -#define EMAC_LINK_MODE_S 0 - -#define EMAC_GMAC_WATCHDOG_TIMEOUT_REG (REG_EMAC_BASE + 0x10DC) -#define EMAC_PROGRAMMABLE_WATCHDOG_ENABLE (BIT(16)) -#define EMAC_PROGRAMMABLE_WATCHDOG_ENABLE_M (BIT(16)) -#define EMAC_PROGRAMMABLE_WATCHDOG_ENABLE_V 1 -#define EMAC_PROGRAMMABLE_WATCHDOG_ENABLE_S 16 -#define EMAC_WATCHDOG_TIMEOUT 0x00003FFF -#define EMAC_WATCHDOG_TIMEOUT_M (EMAC_WATCHDOG_TIMEOUT_V << EMAC_WATCHDOG_TIMEOUT_S) -#define EMAC_WATCHDOG_TIMEOUT_V 0x00003FFF -#define EMAC_WATCHDOG_TIMEOUT_S 0 - -#define EMAC_GMAC_GENERAL_PURPOSE_IO_REG (REG_EMAC_BASE + 0x10E0) -#define EMAC_GPI_TYPE 0x0000000F -#define EMAC_GPI_TYPE_M (EMAC_GPI_TYPE_V << EMAC_GPI_TYPE_S) -#define EMAC_GPI_TYPE_V 0x0000000F -#define EMAC_GPI_TYPE_S 24 -#define EMAC_GPI_INTERRUPT_ENABLE 0x0000000F -#define EMAC_GPI_INTERRUPT_ENABLE_M (EMAC_GPI_INTERRUPT_ENABLE_V << EMAC_GPI_INTERRUPT_ENABLE_S) -#define EMAC_GPI_INTERRUPT_ENABLE_V 0x0000000F -#define EMAC_GPI_INTERRUPT_ENABLE_S 16 -#define EMAC_GENERAL_PURPOSE_OUTPUT 0x0000000F -#define EMAC_GENERAL_PURPOSE_OUTPUT_M (EMAC_GENERAL_PURPOSE_OUTPUT_V << EMAC_GENERAL_PURPOSE_OUTPUT_S) -#define EMAC_GENERAL_PURPOSE_OUTPUT_V 0x0000000F -#define EMAC_GENERAL_PURPOSE_OUTPUT_S 8 -#define EMAC_GENERAL_PURPOSE_INPUT_STATUS 0x0000000F -#define EMAC_GENERAL_PURPOSE_INPUT_STATUS_M (EMAC_GENERAL_PURPOSE_INPUT_STATUS_V << EMAC_GENERAL_PURPOSE_INPUT_STATUS_S) -#define EMAC_GENERAL_PURPOSE_INPUT_STATUS_V 0x0000000F -#define EMAC_GENERAL_PURPOSE_INPUT_STATUS_S 0 - -#define EMAC_GMAC_LAYER3_LAYER4_CONTROL0_REG (REG_EMAC_BASE + 0x1400) -#define EMAC_LAYER4_DESTINATION_PORT_INVERSE_MATCH_ENABLE (BIT(21)) -#define EMAC_LAYER4_DESTINATION_PORT_INVERSE_MATCH_ENABLE_M (BIT(21)) -#define EMAC_LAYER4_DESTINATION_PORT_INVERSE_MATCH_ENABLE_V 1 -#define EMAC_LAYER4_DESTINATION_PORT_INVERSE_MATCH_ENABLE_S 21 -#define EMAC_LAYER4_DESTINATION_PORT_MATCH_ENABLE (BIT(20)) -#define EMAC_LAYER4_DESTINATION_PORT_MATCH_ENABLE_M (BIT(20)) -#define EMAC_LAYER4_DESTINATION_PORT_MATCH_ENABLE_V 1 -#define EMAC_LAYER4_DESTINATION_PORT_MATCH_ENABLE_S 20 -#define EMAC_LAYER4_SOURCE_PORT_INVERSE_MATCH_ENABLE (BIT(19)) -#define EMAC_LAYER4_SOURCE_PORT_INVERSE_MATCH_ENABLE_M (BIT(19)) -#define EMAC_LAYER4_SOURCE_PORT_INVERSE_MATCH_ENABLE_V 1 -#define EMAC_LAYER4_SOURCE_PORT_INVERSE_MATCH_ENABLE_S 19 -#define EMAC_LAYER4_SOURCE_PORT_MATCH_ENABLE (BIT(18)) -#define EMAC_LAYER4_SOURCE_PORT_MATCH_ENABLE_M (BIT(18)) -#define EMAC_LAYER4_SOURCE_PORT_MATCH_ENABLE_V 1 -#define EMAC_LAYER4_SOURCE_PORT_MATCH_ENABLE_S 18 -#define EMAC_LAYER4_PROTOCOL_ENABLE (BIT(16)) -#define EMAC_LAYER4_PROTOCOL_ENABLE_M (BIT(16)) -#define EMAC_LAYER4_PROTOCOL_ENABLE_V 1 -#define EMAC_LAYER4_PROTOCOL_ENABLE_S 16 -#define EMAC_LAYER3_IP_DA_HIGHER_BITS_MATCH 0x0000001F -#define EMAC_LAYER3_IP_DA_HIGHER_BITS_MATCH_M (EMAC_LAYER3_IP_DA_HIGHER_BITS_MATCH_V << EMAC_LAYER3_IP_DA_HIGHER_BITS_MATCH_S) -#define EMAC_LAYER3_IP_DA_HIGHER_BITS_MATCH_V 0x0000001F -#define EMAC_LAYER3_IP_DA_HIGHER_BITS_MATCH_S 11 -#define EMAC_LAYER3_IP_SA_HIGHER_BITS_MATCH 0x0000001F -#define EMAC_LAYER3_IP_SA_HIGHER_BITS_MATCH_M (EMAC_LAYER3_IP_SA_HIGHER_BITS_MATCH_V << EMAC_LAYER3_IP_SA_HIGHER_BITS_MATCH_S) -#define EMAC_LAYER3_IP_SA_HIGHER_BITS_MATCH_V 0x0000001F -#define EMAC_LAYER3_IP_SA_HIGHER_BITS_MATCH_S 6 -#define EMAC_LAYER3_IP_DA_INVERSE_MATCH_ENABLE (BIT(5)) -#define EMAC_LAYER3_IP_DA_INVERSE_MATCH_ENABLE_M (BIT(5)) -#define EMAC_LAYER3_IP_DA_INVERSE_MATCH_ENABLE_V 1 -#define EMAC_LAYER3_IP_DA_INVERSE_MATCH_ENABLE_S 5 -#define EMAC_LAYER3_IP_DA_MATCH_ENABLE (BIT(4)) -#define EMAC_LAYER3_IP_DA_MATCH_ENABLE_M (BIT(4)) -#define EMAC_LAYER3_IP_DA_MATCH_ENABLE_V 1 -#define EMAC_LAYER3_IP_DA_MATCH_ENABLE_S 4 -#define EMAC_LAYER3_IP_SA_INVERSE_MATCH_ENABLE (BIT(3)) -#define EMAC_LAYER3_IP_SA_INVERSE_MATCH_ENABLE_M (BIT(3)) -#define EMAC_LAYER3_IP_SA_INVERSE_MATCH_ENABLE_V 1 -#define EMAC_LAYER3_IP_SA_INVERSE_MATCH_ENABLE_S 3 -#define EMAC_LAYER3_IP_SA_MATCH_ENABLE (BIT(2)) -#define EMAC_LAYER3_IP_SA_MATCH_ENABLE_M (BIT(2)) -#define EMAC_LAYER3_IP_SA_MATCH_ENABLE_V 1 -#define EMAC_LAYER3_IP_SA_MATCH_ENABLE_S 2 -#define EMAC_LAYER3_PROTOCOL_ENABLE (BIT(0)) -#define EMAC_LAYER3_PROTOCOL_ENABLE_M (BIT(0)) -#define EMAC_LAYER3_PROTOCOL_ENABLE_V 1 -#define EMAC_LAYER3_PROTOCOL_ENABLE_S 0 - -#define EMAC_GMAC_LAYER4_ADDRESS0_REG (REG_EMAC_BASE + 0x1404) -#define EMAC_LAYER4_DESTINATION_PORT_NUMBER_FIELD 0x0000FFFF -#define EMAC_LAYER4_DESTINATION_PORT_NUMBER_FIELD_M (EMAC_LAYER4_DESTINATION_PORT_NUMBER_FIELD_V << EMAC_LAYER4_DESTINATION_PORT_NUMBER_FIELD_S) -#define EMAC_LAYER4_DESTINATION_PORT_NUMBER_FIELD_V 0x0000FFFF -#define EMAC_LAYER4_DESTINATION_PORT_NUMBER_FIELD_S 16 -#define EMAC_LAYER4_SOURCE_PORT_NUMBER_FIELD 0x0000FFFF -#define EMAC_LAYER4_SOURCE_PORT_NUMBER_FIELD_M (EMAC_LAYER4_SOURCE_PORT_NUMBER_FIELD_V << EMAC_LAYER4_SOURCE_PORT_NUMBER_FIELD_S) -#define EMAC_LAYER4_SOURCE_PORT_NUMBER_FIELD_V 0x0000FFFF -#define EMAC_LAYER4_SOURCE_PORT_NUMBER_FIELD_S 0 - -#define EMAC_GMAC_LAYER3_ADDRESS0_REG (REG_EMAC_BASE + 0x1410) -#define EMAC_LAYER3_ADDRESS0_FIELD 0xFFFFFFFF -#define EMAC_LAYER3_ADDRESS0_FIELD_M (EMAC_LAYER3_ADDRESS0_FIELD_V << EMAC_LAYER3_ADDRESS0_FIELD_S) -#define EMAC_LAYER3_ADDRESS0_FIELD_V 0xFFFFFFFF -#define EMAC_LAYER3_ADDRESS0_FIELD_S 0 - -#define EMAC_GMAC_LAYER3_ADDRESS1_REG (REG_EMAC_BASE + 0x1414) -#define EMAC_LAYER3_ADDRESS1_FIELD 0xFFFFFFFF -#define EMAC_LAYER3_ADDRESS1_FIELD_M (EMAC_LAYER3_ADDRESS1_FIELD_V << EMAC_LAYER3_ADDRESS1_FIELD_S) -#define EMAC_LAYER3_ADDRESS1_FIELD_V 0xFFFFFFFF -#define EMAC_LAYER3_ADDRESS1_FIELD_S 0 - -#define EMAC_GMAC_LAYER3_ADDRESS2_REG (REG_EMAC_BASE + 0x1418) -#define EMAC_LAYER3_ADDRESS2_FIELD 0xFFFFFFFF -#define EMAC_LAYER3_ADDRESS2_FIELD_M (EMAC_LAYER3_ADDRESS2_FIELD_V << EMAC_LAYER3_ADDRESS2_FIELD_S) -#define EMAC_LAYER3_ADDRESS2_FIELD_V 0xFFFFFFFF -#define EMAC_LAYER3_ADDRESS2_FIELD_S 0 - -#define EMAC_GMAC_LAYER3_ADDRESS3_REG (REG_EMAC_BASE + 0x141C) -#define EMAC_LAYER3_ADDRESS3_FIELD 0xFFFFFFFF -#define EMAC_LAYER3_ADDRESS3_FIELD_M (EMAC_LAYER3_ADDRESS3_FIELD_V << EMAC_LAYER3_ADDRESS3_FIELD_S) -#define EMAC_LAYER3_ADDRESS3_FIELD_V 0xFFFFFFFF -#define EMAC_LAYER3_ADDRESS3_FIELD_S 0 - -#define EMAC_GMAC_HASH_TABLE0_REG (REG_EMAC_BASE + 0x1500) -#define EMAC_FIRST32_BITS_HASH_TABLE 0xFFFFFFFF -#define EMAC_FIRST32_BITS_HASH_TABLE_M (EMAC_FIRST32_BITS_HASH_TABLE_V << EMAC_FIRST32_BITS_HASH_TABLE_S) -#define EMAC_FIRST32_BITS_HASH_TABLE_V 0xFFFFFFFF -#define EMAC_FIRST32_BITS_HASH_TABLE_S 0 - -#define EMAC_GMAC_VLAN_TAG_INCLUSION_REPLACEMENT_REG (REG_EMAC_BASE + 0x1584) -#define EMAC_VLAN_C_VLAN_S_VLAN (BIT(19)) -#define EMAC_VLAN_C_VLAN_S_VLAN_M (BIT(19)) -#define EMAC_VLAN_C_VLAN_S_VLAN_V 1 -#define EMAC_VLAN_C_VLAN_S_VLAN_S 19 -#define EMAC_VLAN_PRIORITY_CONTROL (BIT(18)) -#define EMAC_VLAN_PRIORITY_CONTROL_M (BIT(18)) -#define EMAC_VLAN_PRIORITY_CONTROL_V 1 -#define EMAC_VLAN_PRIORITY_CONTROL_S 18 -#define EMAC_VLAN_TAG_CONTROL_TRANSMIT_FRAMES 0x00000003 -#define EMAC_VLAN_TAG_CONTROL_TRANSMIT_FRAMES_M (EMAC_VLAN_TAG_CONTROL_TRANSMIT_FRAMES_V << EMAC_VLAN_TAG_CONTROL_TRANSMIT_FRAMES_S) -#define EMAC_VLAN_TAG_CONTROL_TRANSMIT_FRAMES_V 0x00000003 -#define EMAC_VLAN_TAG_CONTROL_TRANSMIT_FRAMES_S 16 -#define EMAC_VLAN_TAG_TRANSMIT_FRAMES 0x0000FFFF -#define EMAC_VLAN_TAG_TRANSMIT_FRAMES_M (EMAC_VLAN_TAG_TRANSMIT_FRAMES_V << EMAC_VLAN_TAG_TRANSMIT_FRAMES_S) -#define EMAC_VLAN_TAG_TRANSMIT_FRAMES_V 0x0000FFFF -#define EMAC_VLAN_TAG_TRANSMIT_FRAMES_S 0 - -#define EMAC_GMAC_VLAN_HASH_TABLE_REG (REG_EMAC_BASE + 0x1588) -#define EMAC_VLAN_HASH_TABLE 0x0000FFFF -#define EMAC_VLAN_HASH_TABLE_M (EMAC_VLAN_HASH_TABLE_V << EMAC_VLAN_HASH_TABLE_S) -#define EMAC_VLAN_HASH_TABLE_V 0x0000FFFF -#define EMAC_VLAN_HASH_TABLE_S 0 +#define EMAC_WDOGTO_REG (DR_REG_EMAC_BASE + 0x10DC) +/* EMAC_PWDOGEN : R/W ;bitpos:[16] ;default: 1'h0 ; */ +/*description: When this bit is set and Bit[23] (WD) of EMACCONFIG_REG is reset + the WTO field (Bits[13:0]) is used as watchdog timeout for a received frame. When this bit is cleared the watchdog timeout for a received frame is controlled by the setting of Bit[23] (WD) and Bit[20] (JE) in EMACCONFIG_REG.*/ +#define EMAC_PWDOGEN (BIT(16)) +#define EMAC_PWDOGEN_M (BIT(16)) +#define EMAC_PWDOGEN_V 0x1 +#define EMAC_PWDOGEN_S 16 +/* EMAC_WDOGTO : R/W ;bitpos:[13:0] ;default: 14'h0 ; */ +/*description: When Bit[16] (PWE) is set and Bit[23] (WD) of EMACCONFIG_REG + is reset this field is used as watchdog timeout for a received frame. If the length of a received frame exceeds the value of this field such frame is terminated and declared as an error frame.*/ +#define EMAC_WDOGTO 0x00003FFF +#define EMAC_WDOGTO_M ((EMAC_WDOGTO_V)<<(EMAC_WDOGTO_S)) +#define EMAC_WDOGTO_V 0x3FFF +#define EMAC_WDOGTO_S 0 #ifdef __cplusplus } #endif -#endif + + +#endif /*_SOC_EMAC_REG_H_ */ + From 2699bb49aea59f2145a426db69f901f117cf2ef0 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 23 Apr 2018 20:10:38 +0800 Subject: [PATCH 010/187] sdspi: handle delayed responses for data write commands Command response tokens can be delayed from the original command by 1 to 8 bytes. In 4a2489b9, handling for delayed tokens was added for normal (no data) commands, and data read commands. This adds handling for delayed commands for data write commands. --- components/driver/sdspi_host.c | 73 +++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/components/driver/sdspi_host.c b/components/driver/sdspi_host.c index e0faa73a68..ab9420eb12 100644 --- a/components/driver/sdspi_host.c +++ b/components/driver/sdspi_host.c @@ -67,6 +67,8 @@ static esp_err_t start_command_write_blocks(int slot, sdspi_hw_cmd_t *cmd, static esp_err_t start_command_default(int slot, int flags, sdspi_hw_cmd_t *cmd); +static esp_err_t poll_cmd_response(int slot, sdspi_hw_cmd_t *cmd); + /// A few helper functions /// Set CS high for given slot @@ -429,32 +431,21 @@ static esp_err_t start_command_default(int slot, int flags, sdspi_hw_cmd_t *cmd) /* response is a stuff byte from previous transfer, ignore it */ cmd->r1 = 0xff; } + if (ret != ESP_OK) { + ESP_LOGD(TAG, "%s: spi_device_transmit returned 0x%x", __func__, ret); + return ret; + } if (flags & SDSPI_CMD_FLAG_NORSP) { /* no (correct) response expected from the card, so skip polling loop */ ESP_LOGV(TAG, "%s: ignoring response byte", __func__); cmd->r1 = 0x00; } - int response_delay_bytes = SDSPI_RESPONSE_MAX_DELAY; - while ((cmd->r1 & SD_SPI_R1_NO_RESPONSE) != 0 && response_delay_bytes-- > 0) { - spi_transaction_t* t = get_transaction(slot); - *t = (spi_transaction_t) { - .flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA, - .length = 8, - }; - t->tx_data[0] = 0xff; - ret = spi_device_transmit(spi_handle(slot), t); - uint8_t r1 = t->rx_data[0]; - release_transaction(slot); - if (ret != ESP_OK) { - return ret; - } - cmd->r1 = r1; + ret = poll_cmd_response(slot, cmd); + if (ret != ESP_OK) { + ESP_LOGD(TAG, "%s: poll_cmd_response returned 0x%x", __func__, ret); + return ret; } - if (cmd->r1 & SD_SPI_R1_NO_RESPONSE) { - ESP_LOGD(TAG, "%s: no response token found", __func__); - return ESP_ERR_TIMEOUT; - } - return ret; + return ESP_OK; } // Wait until MISO goes high @@ -563,6 +554,30 @@ static esp_err_t poll_data_token(int slot, spi_transaction_t* t, return ESP_ERR_TIMEOUT; } +static esp_err_t poll_cmd_response(int slot, sdspi_hw_cmd_t *cmd) +{ + int response_delay_bytes = SDSPI_RESPONSE_MAX_DELAY; + while ((cmd->r1 & SD_SPI_R1_NO_RESPONSE) != 0 && response_delay_bytes-- > 0) { + spi_transaction_t* t = get_transaction(slot); + *t = (spi_transaction_t) { + .flags = SPI_TRANS_USE_RXDATA | SPI_TRANS_USE_TXDATA, + .length = 8, + }; + t->tx_data[0] = 0xff; + esp_err_t ret = spi_device_transmit(spi_handle(slot), t); + uint8_t r1 = t->rx_data[0]; + release_transaction(slot); + if (ret != ESP_OK) { + return ret; + } + cmd->r1 = r1; + } + if (cmd->r1 & SD_SPI_R1_NO_RESPONSE) { + return ESP_ERR_TIMEOUT; + } + return ESP_OK; +} + /** * Receiving one or more blocks of data happens as follows: @@ -759,9 +774,17 @@ static esp_err_t start_command_write_blocks(int slot, sdspi_hw_cmd_t *cmd, if (ret != ESP_OK) { return ret; } + wait_for_transactions(slot); + + // Poll for command response which may be delayed up to 8 bytes + ret = poll_cmd_response(slot, cmd); + if (ret != ESP_OK) { + ESP_LOGD(TAG, "%s: poll_cmd_response returned 0x%x", __func__, ret); + return ret; + } + uint8_t start_token = tx_length <= SDSPI_MAX_DATA_LEN ? TOKEN_BLOCK_START : TOKEN_BLOCK_START_WRITE_MULTI; - wait_for_transactions(slot); while (tx_length > 0) { @@ -771,7 +794,7 @@ static esp_err_t start_command_write_blocks(int slot, sdspi_hw_cmd_t *cmd, .length = sizeof(start_token) * 8, .tx_buffer = &start_token }; - esp_err_t ret = spi_device_queue_trans(spi_handle(slot), t_start_token, 0); + ret = spi_device_queue_trans(spi_handle(slot), t_start_token, 0); if (ret != ESP_OK) { return ret; } @@ -816,12 +839,6 @@ static esp_err_t start_command_write_blocks(int slot, sdspi_hw_cmd_t *cmd, // Wait for data to be sent wait_for_transactions(slot); - // Check if R1 response for the command was correct - if (cmd->r1 != 0) { - ESP_LOGD(TAG, "%s: invalid R1 response: 0x%02x", __func__, cmd->r1); - return ESP_ERR_INVALID_RESPONSE; - } - // Poll for response spi_transaction_t* t_poll = get_transaction(slot); ret = poll_response_token(slot, t_poll, cmd->timeout_ms); From 5a63faa516a4ef169c4652667e801771a03e770d Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 23 Apr 2018 20:14:23 +0800 Subject: [PATCH 011/187] sdmmc: enable more test cases Some test cases did not run automatically in CI, this change enables them. --- components/sdmmc/test/test_sd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/sdmmc/test/test_sd.c b/components/sdmmc/test/test_sd.c index 33b3890ccd..1808a0cdd0 100644 --- a/components/sdmmc/test/test_sd.c +++ b/components/sdmmc/test/test_sd.c @@ -177,7 +177,7 @@ static void read_write_test(sdmmc_card_t* card) do_single_write_read_test(card, card->csd.capacity/2, 128, 1); } -TEST_CASE("can write and read back blocks", "[sd][test_env=UT_T1_SDMODE][ignore]") +TEST_CASE("can write and read back blocks", "[sd][test_env=UT_T1_SDMODE]") { sdmmc_host_t config = SDMMC_HOST_DEFAULT(); config.max_freq_khz = SDMMC_FREQ_HIGHSPEED; @@ -192,7 +192,7 @@ TEST_CASE("can write and read back blocks", "[sd][test_env=UT_T1_SDMODE][ignore] TEST_ESP_OK(sdmmc_host_deinit()); } -TEST_CASE("can write and read back blocks(using SPI)", "[sdspi][test_env=UT_T1_SPIMODE][ignore]") +TEST_CASE("can write and read back blocks(using SPI)", "[sdspi][test_env=UT_T1_SPIMODE]") { sdmmc_host_t config = SDSPI_HOST_DEFAULT(); sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT(); @@ -206,7 +206,7 @@ TEST_CASE("can write and read back blocks(using SPI)", "[sdspi][test_env=UT_T1_S TEST_ESP_OK(sdspi_host_deinit()); } -TEST_CASE("reads and writes with an unaligned buffer", "[sd][test_env=UT_T1_SDMODE][ignore]") +TEST_CASE("reads and writes with an unaligned buffer", "[sd][test_env=UT_T1_SDMODE]") { sdmmc_host_t config = SDMMC_HOST_DEFAULT(); sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); From 4ba19abeb690b7fd276b6ed9721c538dd54bfda3 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 3 Apr 2018 18:12:47 +0800 Subject: [PATCH 012/187] esp_timer: add a function to get next alarm time --- components/esp32/esp_timer.c | 12 ++++++++++++ components/esp32/include/esp_timer.h | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/components/esp32/esp_timer.c b/components/esp32/esp_timer.c index 6987b4c64c..72bd9dd73b 100644 --- a/components/esp32/esp_timer.c +++ b/components/esp32/esp_timer.c @@ -455,6 +455,18 @@ esp_err_t esp_timer_dump(FILE* stream) return ESP_OK; } +int64_t IRAM_ATTR esp_timer_get_next_alarm() +{ + int64_t next_alarm = INT64_MAX; + timer_list_lock(); + esp_timer_handle_t it = LIST_FIRST(&s_timers); + if (it) { + next_alarm = it->alarm; + } + timer_list_unlock(); + return next_alarm; +} + int64_t IRAM_ATTR esp_timer_get_time() { return (int64_t) esp_timer_impl_get_time(); diff --git a/components/esp32/include/esp_timer.h b/components/esp32/include/esp_timer.h index 07e2372140..ff5c13ab4c 100644 --- a/components/esp32/include/esp_timer.h +++ b/components/esp32/include/esp_timer.h @@ -189,6 +189,13 @@ esp_err_t esp_timer_delete(esp_timer_handle_t timer); */ int64_t esp_timer_get_time(); +/** + * @brief Get the timestamp when the next timeout is expected to occur + * @return Timestamp of the nearest timer event, in microseconds. + * The timebase is the same as for the values returned by esp_timer_get_time. + */ +int64_t esp_timer_get_next_alarm(); + /** * @brief Dump the list of timers to a stream * From c61c2a63d0aa914098fd828a8e5a305cddd5261d Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 26 Apr 2018 16:47:35 +0800 Subject: [PATCH 013/187] unity: flush test name before starting the test, use printf everywhere Unit test runner expects to see the test name echoed after test selection is made. If the unit test immediately goes into sleep mode, UART output will not be complete, and test runner will not see the test name. This flushes the stream buffer and waits for UART FIFO to be empty before starting the test. Additionally some parts of code used unity_printf and some used printf. Since unity_printf was only useful during very early tests when newlib was not available, replace all its usages with printf. --- .../components/unity/unity_platform.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tools/unit-test-app/components/unity/unity_platform.c b/tools/unit-test-app/components/unity/unity_platform.c index 0a33eb66cc..fa1adf6333 100644 --- a/tools/unit-test-app/components/unity/unity_platform.c +++ b/tools/unit-test-app/components/unity/unity_platform.c @@ -17,8 +17,6 @@ #include "esp_heap_trace.h" #endif -#define unity_printf ets_printf - // Pointers to the head and tail of linked list of test description structs: static struct test_desc_t* s_unity_tests_first = NULL; static struct test_desc_t* s_unity_tests_last = NULL; @@ -153,10 +151,10 @@ void unity_testcase_register(struct test_desc_t* desc) * */ static void print_multiple_function_test_menu(const struct test_desc_t* test_ms) { - unity_printf("%s\n", test_ms->name); + printf("%s\n", test_ms->name); for (int i = 0; i < test_ms->test_fn_count; i++) { - unity_printf("\t(%d)\t\"%s\"\n", i+1, test_ms->test_fn_name[i]); + printf("\t(%d)\t\"%s\"\n", i+1, test_ms->test_fn_name[i]); } } @@ -189,6 +187,10 @@ void multiple_function_option(const struct test_desc_t* test_ms) static void unity_run_single_test(const struct test_desc_t* test) { printf("Running %s...\n", test->name); + // Unit test runner expects to see test name before the test starts + fflush(stdout); + uart_tx_wait_idle(CONFIG_CONSOLE_UART_NUM); + Unity.TestFile = test->file; Unity.CurrentDetail1 = test->desc; if(test->test_fn_count == 1) { @@ -293,17 +295,17 @@ static void trim_trailing_space(char* str) static int print_test_menu(void) { int test_counter = 0; - unity_printf("\n\nHere's the test menu, pick your combo:\n"); + printf("\n\nHere's the test menu, pick your combo:\n"); for (const struct test_desc_t* test = s_unity_tests_first; test != NULL; test = test->next, ++test_counter) { - unity_printf("(%d)\t\"%s\" %s\n", test_counter + 1, test->name, test->desc); + printf("(%d)\t\"%s\" %s\n", test_counter + 1, test->name, test->desc); if(test->test_fn_count > 1) { for (int i = 0; i < test->test_fn_count; i++) { - unity_printf("\t(%d)\t\"%s\"\n", i+1, test->test_fn_name[i]); + printf("\t(%d)\t\"%s\"\n", i+1, test->test_fn_name[i]); } } } @@ -324,7 +326,7 @@ static int get_test_count(void) void unity_run_menu() { - unity_printf("\n\nPress ENTER to see the list of tests.\n"); + printf("\n\nPress ENTER to see the list of tests.\n"); int test_count = get_test_count(); while (true) { From 48379b8bbe6e9d5ea448427d5834457c8471aa6c Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 26 Apr 2018 17:57:33 +0800 Subject: [PATCH 014/187] unit-test.py: increase timeout for test app start up --- tools/unit-test-app/unit_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/unit-test-app/unit_test.py b/tools/unit-test-app/unit_test.py index 4ea7ddf579..594a71becf 100644 --- a/tools/unit-test-app/unit_test.py +++ b/tools/unit-test-app/unit_test.py @@ -142,7 +142,7 @@ def run_unit_test_cases(env, extra_data): # to determine if DUT is ready to test. dut.write("-", flush=False) dut.expect_any(UT_APP_BOOT_UP_DONE, - "0 Tests 0 Failures 0 Ignored") + "0 Tests 0 Failures 0 Ignored", timeout=UT_TIMEOUT) # run test case dut.write("\"{}\"".format(one_case["name"])) From 487210221bef86f6022413d330300a44cd093f00 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 3 Apr 2018 18:13:22 +0800 Subject: [PATCH 015/187] esp_timer: add internal function to adjust time --- components/esp32/esp_timer_esp32.c | 12 ++++++++++++ components/esp32/esp_timer_impl.h | 9 +++++++++ 2 files changed, 21 insertions(+) diff --git a/components/esp32/esp_timer_esp32.c b/components/esp32/esp_timer_esp32.c index 4c21910e8a..1bc4885756 100644 --- a/components/esp32/esp_timer_esp32.c +++ b/components/esp32/esp_timer_esp32.c @@ -311,6 +311,18 @@ void IRAM_ATTR esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us) portEXIT_CRITICAL_ISR(&s_time_update_lock); } +void esp_timer_impl_advance(int64_t time_us) +{ + assert(time_us > 0 && "negative adjustments not supported yet"); + + portENTER_CRITICAL(&s_time_update_lock); + uint64_t count = REG_READ(FRC_TIMER_COUNT_REG(1)); + REG_WRITE(FRC_TIMER_LOAD_REG(1), 0); + s_time_base_us += count / s_timer_ticks_per_us + time_us; + esp_timer_impl_set_alarm(esp_timer_get_next_alarm()); + portEXIT_CRITICAL(&s_time_update_lock); +} + esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler) { s_alarm_handler = alarm_handler; diff --git a/components/esp32/esp_timer_impl.h b/components/esp32/esp_timer_impl.h index 7d49e3eeb0..9c4642c474 100644 --- a/components/esp32/esp_timer_impl.h +++ b/components/esp32/esp_timer_impl.h @@ -60,6 +60,15 @@ void esp_timer_impl_set_alarm(uint64_t timestamp); */ void esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us); +/** + * @brief Adjust current esp_timer time by a certain value + * + * Called from light sleep code to synchronize esp_timer time with RTC time. + * + * @param time_us adjustment to apply to esp_timer time, in microseconds + */ +void esp_timer_impl_advance(int64_t time_us); + /** * @brief Get time, in microseconds, since esp_timer_impl_init was called * @return timestamp in microseconds From 3c78faa0a929188598ef4ee6c24f6fafed29495d Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 3 Apr 2018 18:14:55 +0800 Subject: [PATCH 016/187] =?UTF-8?q?soc/rtc:=20don=E2=80=99t=20switch=20fre?= =?UTF-8?q?quency=20in=20rtc=5Fsleep=5Finit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/soc/esp32/include/soc/rtc.h | 2 -- components/soc/esp32/rtc_pm.c | 1 - components/soc/esp32/rtc_sleep.c | 13 ------------- 3 files changed, 16 deletions(-) diff --git a/components/soc/esp32/include/soc/rtc.h b/components/soc/esp32/include/soc/rtc.h index ec9935fd57..3fe26eed5d 100644 --- a/components/soc/esp32/include/soc/rtc.h +++ b/components/soc/esp32/include/soc/rtc.h @@ -427,7 +427,6 @@ void rtc_clk_wait_for_slow_cycle(); * @brief sleep configuration for rtc_sleep_init function */ typedef struct { - uint32_t soc_clk_sel : 2; //!< SoC clock select, see RTC_CNTL_SOC_CLK_SEL uint32_t lslp_mem_inf_fpu : 1; //!< force normal voltage in sleep mode (digital domain memory) uint32_t rtc_mem_inf_fpu : 1; //!< force normal voltage in sleep mode (RTC memory) uint32_t rtc_mem_inf_follow_cpu : 1;//!< keep low voltage in sleep mode (even if ULP/touch is used) @@ -455,7 +454,6 @@ typedef struct { * @param RTC_SLEEP_PD_x flags combined using bitwise OR */ #define RTC_SLEEP_CONFIG_DEFAULT(sleep_flags) { \ - .soc_clk_sel = RTC_CNTL_SOC_CLK_SEL_XTL, \ .lslp_mem_inf_fpu = 0, \ .rtc_mem_inf_fpu = 0, \ .rtc_mem_inf_follow_cpu = ((sleep_flags) & RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU) ? 1 : 0, \ diff --git a/components/soc/esp32/rtc_pm.c b/components/soc/esp32/rtc_pm.c index 2023bd824a..e5e7377259 100644 --- a/components/soc/esp32/rtc_pm.c +++ b/components/soc/esp32/rtc_pm.c @@ -48,7 +48,6 @@ pm_sw_reject_t pm_set_sleep_mode(pm_sleep_mode_t sleep_mode, void(*pmac_save_par } rtc_sleep_config_t cfg = { 0 }; - cfg.soc_clk_sel = RTC_CNTL_SOC_CLK_SEL_XTL; switch (sleep_mode) { case PM_LIGHT_SLEEP: diff --git a/components/soc/esp32/rtc_sleep.c b/components/soc/esp32/rtc_sleep.c index 82a04d8cab..60cddf17e8 100644 --- a/components/soc/esp32/rtc_sleep.c +++ b/components/soc/esp32/rtc_sleep.c @@ -89,9 +89,6 @@ static void rtc_sleep_pd(rtc_sleep_pd_config_t cfg) void rtc_sleep_init(rtc_sleep_config_t cfg) { - rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get(); - REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, cfg.soc_clk_sel); - //set 5 PWC state machine times to fit in main state machine time REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, 1); REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT, RTC_CNTL_XTL_BUF_WAIT_DEFAULT); @@ -112,16 +109,6 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_RTCMEM_POWERUP_TIMER, RTC_MEM_POWERUP_DELAY); REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_RTCMEM_WAIT_TIMER, RTC_MEM_WAIT_DELAY); - if (cfg.soc_clk_sel == RTC_CNTL_SOC_CLK_SEL_PLL) { - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, RTC_CNTL_PLL_BUF_WAIT_DEFAULT); - } else if (cfg.soc_clk_sel == RTC_CNTL_SOC_CLK_SEL_XTL) { - ets_update_cpu_frequency(xtal_freq); - rtc_clk_apb_freq_update(xtal_freq * MHZ); - } else if (cfg.soc_clk_sel == RTC_CNTL_SOC_CLK_SEL_8M) { - ets_update_cpu_frequency(8); - rtc_clk_apb_freq_update(8 * MHZ); - } - if (cfg.lslp_mem_inf_fpu) { SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU); } else { From b0a91630fb22577314ff15a26e5743f5819ae16c Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 3 Apr 2018 18:15:59 +0800 Subject: [PATCH 017/187] soc/rtc: allow main XTAL to be powered on in sleep --- components/soc/esp32/include/soc/rtc.h | 3 +++ components/soc/esp32/rtc_sleep.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/components/soc/esp32/include/soc/rtc.h b/components/soc/esp32/include/soc/rtc.h index 3fe26eed5d..2f8cf3fe43 100644 --- a/components/soc/esp32/include/soc/rtc.h +++ b/components/soc/esp32/include/soc/rtc.h @@ -443,6 +443,7 @@ typedef struct { uint32_t rtc_dbias_slp : 3; //!< set bias for RTC domain, in sleep mode uint32_t lslp_meminf_pd : 1; //!< remove all peripheral force power up flags uint32_t vddsdio_pd_en : 1; //!< power down VDDSDIO regulator + uint32_t xtal_fpu : 1; //!< keep main XTAL powered up in sleep } rtc_sleep_config_t; /** @@ -470,6 +471,7 @@ typedef struct { .rtc_dbias_slp = RTC_CNTL_DBIAS_0V90, \ .lslp_meminf_pd = 1, \ .vddsdio_pd_en = ((sleep_flags) & RTC_SLEEP_PD_VDDSDIO) ? 1 : 0, \ + .xtal_fpu = ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1 \ }; #define RTC_SLEEP_PD_DIG BIT(0) //!< Deep sleep (power down digital domain) @@ -478,6 +480,7 @@ typedef struct { #define RTC_SLEEP_PD_RTC_FAST_MEM BIT(3) //!< Power down RTC FAST memory #define RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU BIT(4) //!< RTC FAST and SLOW memories are automatically powered up and down along with the CPU #define RTC_SLEEP_PD_VDDSDIO BIT(5) //!< Power down VDDSDIO regulator +#define RTC_SLEEP_PD_XTAL BIT(6) //!< Power down main XTAL /** * @brief Prepare the chip to enter sleep mode diff --git a/components/soc/esp32/rtc_sleep.c b/components/soc/esp32/rtc_sleep.c index 60cddf17e8..ae34e273af 100644 --- a/components/soc/esp32/rtc_sleep.c +++ b/components/soc/esp32/rtc_sleep.c @@ -185,6 +185,8 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN, 0); } + REG_SET_FIELD(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, cfg.xtal_fpu); + /* enable VDDSDIO control by state machine */ REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE); REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN, cfg.vddsdio_pd_en); From d38b22b11bf03364eb32577329469c6c3cc6c37b Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 4 Apr 2018 15:04:29 +0800 Subject: [PATCH 018/187] =?UTF-8?q?soc/rtc,=20sleep:=20don=E2=80=99t=20low?= =?UTF-8?q?er=20the=20bias=20for=20wakeup=20state?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes watchdog resets occurring during wakeup from light sleep. --- components/soc/esp32/include/soc/rtc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/soc/esp32/include/soc/rtc.h b/components/soc/esp32/include/soc/rtc.h index 2f8cf3fe43..86beea5342 100644 --- a/components/soc/esp32/include/soc/rtc.h +++ b/components/soc/esp32/include/soc/rtc.h @@ -467,7 +467,7 @@ typedef struct { .wdt_flashboot_mod_en = 0, \ .dig_dbias_wak = RTC_CNTL_DBIAS_1V10, \ .dig_dbias_slp = RTC_CNTL_DBIAS_0V90, \ - .rtc_dbias_wak = RTC_CNTL_DBIAS_0V90, \ + .rtc_dbias_wak = RTC_CNTL_DBIAS_1V10, \ .rtc_dbias_slp = RTC_CNTL_DBIAS_0V90, \ .lslp_meminf_pd = 1, \ .vddsdio_pd_en = ((sleep_flags) & RTC_SLEEP_PD_VDDSDIO) ? 1 : 0, \ From ac623a97561929750c8cdcc8d679b21d288a2ab1 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 4 Apr 2018 15:05:16 +0800 Subject: [PATCH 019/187] soc/rtc: restore dbg attenuation when waking from sleep This fixes inability to enter deep sleep after waking up from light sleep --- components/soc/esp32/include/soc/rtc_cntl_reg.h | 2 +- components/soc/esp32/rtc_init.c | 2 +- components/soc/esp32/rtc_sleep.c | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/components/soc/esp32/include/soc/rtc_cntl_reg.h b/components/soc/esp32/include/soc/rtc_cntl_reg.h index d54a7dde7c..090b3f7072 100644 --- a/components/soc/esp32/include/soc/rtc_cntl_reg.h +++ b/components/soc/esp32/include/soc/rtc_cntl_reg.h @@ -1070,7 +1070,7 @@ #define RTC_CNTL_DBG_ATTEN_M ((RTC_CNTL_DBG_ATTEN_V)<<(RTC_CNTL_DBG_ATTEN_S)) #define RTC_CNTL_DBG_ATTEN_V 0x3 #define RTC_CNTL_DBG_ATTEN_S 24 - +#define RTC_CNTL_DBG_ATTEN_DEFAULT 3 #define RTC_CNTL_REG (DR_REG_RTCCNTL_BASE + 0x7c) /* RTC_CNTL_FORCE_PU : R/W ;bitpos:[31] ;default: 1'd1 ; */ /*description: RTC_REG force power up*/ diff --git a/components/soc/esp32/rtc_init.c b/components/soc/esp32/rtc_init.c index dfd0669087..43374d6b02 100644 --- a/components/soc/esp32/rtc_init.c +++ b/components/soc/esp32/rtc_init.c @@ -30,7 +30,7 @@ void rtc_init(rtc_config_t cfg) REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT, cfg.xtal_wait); REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, cfg.ck8m_wait); - REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN, 0x3); + REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN, RTC_CNTL_DBG_ATTEN_DEFAULT); SET_PERI_REG_MASK(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DEC_HEARTBEAT_WIDTH | RTC_CNTL_INC_HEARTBEAT_PERIOD); diff --git a/components/soc/esp32/rtc_sleep.c b/components/soc/esp32/rtc_sleep.c index ae34e273af..b0ffb2ff2b 100644 --- a/components/soc/esp32/rtc_sleep.c +++ b/components/soc/esp32/rtc_sleep.c @@ -219,5 +219,8 @@ uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt) uint32_t reject = REG_GET_FIELD(RTC_CNTL_INT_RAW_REG, RTC_CNTL_SLP_REJECT_INT_RAW); SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR); + + /* restore DBG_ATTEN to the default value */ + REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN, RTC_CNTL_DBG_ATTEN_DEFAULT); return reject; } From 94250e42a064e59f63d14b9eaf8e7dabb4ab6dd7 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 4 Apr 2018 15:05:50 +0800 Subject: [PATCH 020/187] sleep: optimize light sleep wakeup latency --- components/esp32/include/esp_sleep.h | 1 + components/esp32/sleep_modes.c | 150 +++++++++++++++++++-------- components/esp32/test/test_sleep.c | 127 +++++++++++++++++++++-- components/soc/esp32/rtc_sleep.c | 78 ++++++++------ 4 files changed, 269 insertions(+), 87 deletions(-) diff --git a/components/esp32/include/esp_sleep.h b/components/esp32/include/esp_sleep.h index 2bdeac474f..a8bce5f796 100644 --- a/components/esp32/include/esp_sleep.h +++ b/components/esp32/include/esp_sleep.h @@ -38,6 +38,7 @@ typedef enum { ESP_PD_DOMAIN_RTC_PERIPH, //!< RTC IO, sensors and ULP co-processor ESP_PD_DOMAIN_RTC_SLOW_MEM, //!< RTC slow memory ESP_PD_DOMAIN_RTC_FAST_MEM, //!< RTC fast memory + ESP_PD_DOMAIN_XTAL, //!< XTAL oscillator ESP_PD_DOMAIN_MAX //!< Number of domains } esp_sleep_pd_domain_t; diff --git a/components/esp32/sleep_modes.c b/components/esp32/sleep_modes.c index 1a9c449a2a..a5f14d7f2b 100644 --- a/components/esp32/sleep_modes.c +++ b/components/esp32/sleep_modes.c @@ -17,6 +17,7 @@ #include #include "esp_attr.h" #include "esp_sleep.h" +#include "esp_timer_impl.h" #include "esp_log.h" #include "esp_clk.h" #include "esp_newlib.h" @@ -42,6 +43,19 @@ // Time from VDD_SDIO power up to first flash read in ROM code #define VDD_SDIO_POWERUP_TO_FLASH_READ_US 700 +// Extra time it takes to enter and exit light sleep and deep sleep +// For deep sleep, this is until the wake stub runs (not the app). +#ifdef CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL +#define LIGHT_SLEEP_TIME_OVERHEAD_US (650 + 30 * 240 / CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ) +#define DEEP_SLEEP_TIME_OVERHEAD_US (650 + 100 * 240 / CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ) +#else +#define LIGHT_SLEEP_TIME_OVERHEAD_US (250 + 30 * 240 / CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ) +#define DEEP_SLEEP_TIME_OVERHEAD_US (250 + 100 * 240 / CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ) +#endif // CONFIG_ESP32_RTC_CLOCK_SOURCE + +// Minimal amount of time we can sleep for +#define LIGHT_SLEEP_MIN_TIME_US 200 + #define CHECK_SOURCE(source, value, mask) ((s_config.wakeup_triggers & mask) && \ (source == value)) @@ -56,9 +70,11 @@ typedef struct { uint32_t ext1_rtc_gpio_mask : 18; uint32_t ext0_trigger_level : 1; uint32_t ext0_rtc_gpio_num : 5; -} deep_sleep_config_t; + uint32_t sleep_time_adjustment; + uint64_t rtc_ticks_at_sleep_start; +} sleep_config_t; -static deep_sleep_config_t s_config = { +static sleep_config_t s_config = { .pd_options = { ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO }, .wakeup_triggers = 0 }; @@ -125,12 +141,31 @@ void esp_deep_sleep(uint64_t time_in_us) esp_deep_sleep_start(); } +static void IRAM_ATTR suspend_uarts() +{ + for (int i = 0; i < 3; ++i) { + REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XOFF); + uart_tx_wait_idle(i); + } +} + +static void IRAM_ATTR resume_uarts() +{ + for (int i = 0; i < 3; ++i) { + REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XOFF); + REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XON); + REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XON); + } +} + static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) { - // Flush UARTs so that output is not lost due to APB frequency change - uart_tx_wait_idle(0); - uart_tx_wait_idle(1); - uart_tx_wait_idle(2); + // Stop UART output so that output is not lost due to APB frequency change + suspend_uarts(); + + // Save current frequency and switch to XTAL + rtc_cpu_freq_t cpu_freq = rtc_clk_cpu_freq_get(); + rtc_clk_cpu_freq_set(RTC_CPU_FREQ_XTAL); // Configure pins for external wakeup if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) { @@ -143,20 +178,32 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) if (s_config.wakeup_triggers & RTC_ULP_TRIG_EN) { SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_WAKEUP_FORCE_EN); } + + // Enter sleep + rtc_sleep_config_t config = RTC_SLEEP_CONFIG_DEFAULT(pd_flags); + rtc_sleep_init(config); + // Configure timer wakeup if ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) && s_config.sleep_duration > 0) { timer_wakeup_prepare(); } + uint32_t result = rtc_sleep_start(s_config.wakeup_triggers, 0); - // Enter sleep - rtc_sleep_config_t config = RTC_SLEEP_CONFIG_DEFAULT(pd_flags); - rtc_sleep_init(config); - return rtc_sleep_start(s_config.wakeup_triggers, 0); + // Restore CPU frequency + rtc_clk_cpu_freq_set(cpu_freq); + + // re-enable UART output + resume_uarts(); + + return result; } void IRAM_ATTR esp_deep_sleep_start() { + // record current RTC time + s_config.rtc_ticks_at_sleep_start = rtc_time_get(); + // Configure wake stub if (esp_get_deep_sleep_wake_stub() == NULL) { esp_set_deep_sleep_wake_stub(esp_wake_deep_sleep); @@ -165,8 +212,11 @@ void IRAM_ATTR esp_deep_sleep_start() // Decide which power domains can be powered down uint32_t pd_flags = get_power_down_flags(); + // Correct the sleep time + s_config.sleep_time_adjustment = DEEP_SLEEP_TIME_OVERHEAD_US; + // Enter sleep - esp_sleep_start(RTC_SLEEP_PD_DIG | RTC_SLEEP_PD_VDDSDIO | pd_flags); + esp_sleep_start(RTC_SLEEP_PD_DIG | RTC_SLEEP_PD_VDDSDIO | RTC_SLEEP_PD_XTAL | pd_flags); // Because RTC is in a slower clock domain than the CPU, it // can take several CPU cycles for the sleep mode to start. @@ -201,11 +251,11 @@ static void rtc_wdt_disable() * Placed into IRAM as flash may need some time to be powered on. */ static esp_err_t esp_light_sleep_inner(uint32_t pd_flags, - rtc_cpu_freq_t cpu_freq, uint32_t flash_enable_time_us, + uint32_t flash_enable_time_us, rtc_vddsdio_config_t vddsdio_config) IRAM_ATTR __attribute__((noinline)); static esp_err_t esp_light_sleep_inner(uint32_t pd_flags, - rtc_cpu_freq_t cpu_freq, uint32_t flash_enable_time_us, + uint32_t flash_enable_time_us, rtc_vddsdio_config_t vddsdio_config) { // Enter sleep @@ -217,9 +267,6 @@ static esp_err_t esp_light_sleep_inner(uint32_t pd_flags, rtc_vddsdio_set_config(vddsdio_config); } - // Restore CPU frequency - rtc_clk_cpu_freq_set(cpu_freq); - // If SPI flash was powered down, wait for it to become ready if (pd_flags & RTC_SLEEP_PD_VDDSDIO) { // Wait for the flash chip to start up @@ -231,53 +278,61 @@ static esp_err_t esp_light_sleep_inner(uint32_t pd_flags, esp_err_t esp_light_sleep_start() { static portMUX_TYPE light_sleep_lock = portMUX_INITIALIZER_UNLOCKED; - portENTER_CRITICAL(&light_sleep_lock); - int other_cpu = xPortGetCoreID() ? 0 : 1; - esp_cpu_stall(other_cpu); - - // Other CPU is stalled, need to disable DPORT protection - esp_dport_access_int_pause(); + s_config.rtc_ticks_at_sleep_start = rtc_time_get(); + uint64_t frc_time_at_start = esp_timer_get_time(); + DPORT_STALL_OTHER_CPU_START(); // Decide which power domains can be powered down uint32_t pd_flags = get_power_down_flags(); + // Amount of time to subtract from actual sleep time. + // This is spent on entering and leaving light sleep. + s_config.sleep_time_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US; + // Decide if VDD_SDIO needs to be powered down; // If it needs to be powered down, adjust sleep time. const uint32_t flash_enable_time_us = VDD_SDIO_POWERUP_TO_FLASH_READ_US + CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY; - // Don't power down VDD_SDIO if pSRAM is used. #ifndef CONFIG_SPIRAM_SUPPORT - if (s_config.sleep_duration > FLASH_PD_MIN_SLEEP_TIME_US && - s_config.sleep_duration > flash_enable_time_us) { + const uint32_t vddsdio_pd_sleep_duration = MAX(FLASH_PD_MIN_SLEEP_TIME_US, + flash_enable_time_us + LIGHT_SLEEP_TIME_OVERHEAD_US + LIGHT_SLEEP_MIN_TIME_US); + + if (s_config.sleep_duration > vddsdio_pd_sleep_duration) { pd_flags |= RTC_SLEEP_PD_VDDSDIO; - s_config.sleep_duration -= flash_enable_time_us; + s_config.sleep_time_adjustment += flash_enable_time_us; } #endif //CONFIG_SPIRAM_SUPPORT + rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config(); // Safety net: enable WDT in case exit from light sleep fails rtc_wdt_enable(1000); - // Save current CPU frequency, light sleep will switch to XTAL - rtc_cpu_freq_t cpu_freq = rtc_clk_cpu_freq_get(); - // Enter sleep, then wait for flash to be ready on wakeup - esp_err_t err = esp_light_sleep_inner(pd_flags, cpu_freq, + esp_err_t err = esp_light_sleep_inner(pd_flags, flash_enable_time_us, vddsdio_config); - // At this point, if FRC1 is used for timekeeping, time will be lagging behind. - // This will update the microsecond count based on RTC timer. + // FRC1 has been clock gated for the duration of the sleep, correct for that. + uint64_t rtc_ticks_at_end = rtc_time_get(); + uint64_t frc_time_at_end = esp_timer_get_time(); + + uint64_t rtc_time_diff = rtc_time_slowclk_to_us(rtc_ticks_at_end - s_config.rtc_ticks_at_sleep_start, + esp_clk_slowclk_cal_get()); + uint64_t frc_time_diff = frc_time_at_end - frc_time_at_start; + + int64_t time_diff = rtc_time_diff - frc_time_diff; + /* Small negative values (up to 1 RTC_SLOW clock period) are possible, + * for very small values of sleep_duration. Ignore those to keep esp_timer + * monotonic. + */ + if (time_diff > 0) { + esp_timer_impl_advance(time_diff); + } esp_set_time_from_rtc(); - // However, we do not advance RTOS ticks here; doing so would be rather messy, - // as ticks can only be advanced on CPU0. - // If this is needed by the application, automatic light sleep (tickless idle) - // will handle that better. - - esp_cpu_unstall(other_cpu); - esp_dport_access_int_resume(); + DPORT_STALL_OTHER_CPU_END(); rtc_wdt_disable(); portEXIT_CRITICAL(&light_sleep_lock); return err; @@ -343,9 +398,13 @@ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us) static void timer_wakeup_prepare() { uint32_t period = esp_clk_slowclk_cal_get(); - uint64_t rtc_count_delta = rtc_time_us_to_slowclk(s_config.sleep_duration, period); - uint64_t cur_rtc_count = rtc_time_get(); - rtc_sleep_set_wakeup_time(cur_rtc_count + rtc_count_delta); + int64_t sleep_duration = (int64_t) s_config.sleep_duration - (int64_t) s_config.sleep_time_adjustment; + if (sleep_duration < 0) { + sleep_duration = 0; + } + int64_t rtc_count_delta = rtc_time_us_to_slowclk(sleep_duration, period); + + rtc_sleep_set_wakeup_time(s_config.rtc_ticks_at_sleep_start + rtc_count_delta); } esp_err_t esp_sleep_enable_touchpad_wakeup() @@ -561,6 +620,10 @@ static uint32_t get_power_down_flags() } } + if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] == ESP_PD_OPTION_AUTO) { + s_config.pd_options[ESP_PD_DOMAIN_XTAL] = ESP_PD_OPTION_OFF; + } + const char* option_str[] = {"OFF", "ON", "AUTO(OFF)" /* Auto works as OFF */}; ESP_LOGD(TAG, "RTC_PERIPH: %s, RTC_SLOW_MEM: %s, RTC_FAST_MEM: %s", option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH]], @@ -578,5 +641,8 @@ static uint32_t get_power_down_flags() if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] != ESP_PD_OPTION_ON) { pd_flags |= RTC_SLEEP_PD_RTC_PERIPH; } + if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] != ESP_PD_OPTION_ON) { + pd_flags |= RTC_SLEEP_PD_XTAL; + } return pd_flags; } diff --git a/components/esp32/test/test_sleep.c b/components/esp32/test/test_sleep.c index fa1b902ac2..ac090fff98 100644 --- a/components/esp32/test/test_sleep.c +++ b/components/esp32/test/test_sleep.c @@ -1,10 +1,16 @@ #include "unity.h" #include +#include #include "esp_sleep.h" +#include "esp_clk.h" #include "driver/rtc_io.h" +#include "soc/gpio_reg.h" +#include "soc/rtc.h" +#include "soc/uart_reg.h" +#include "rom/uart.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" - +#include "freertos/semphr.h" #include "soc/rtc.h" // for wakeup trigger defines #include "soc/rtc_cntl_reg.h" // for read rtc registers directly (cause) #include "soc/soc.h" // for direct register read macros @@ -14,10 +20,6 @@ static struct timeval tv_start, tv_stop; -TEST_CASE("esp_deepsleep works", "[deepsleep][reset=DEEPSLEEP_RESET]") -{ - esp_deep_sleep(2000000); -} static void deep_sleep_task(void *arg) { @@ -36,12 +38,19 @@ static void do_deep_sleep_from_app_cpu() } } -TEST_CASE("wake up using timer", "[deepsleep][reset=DEEPSLEEP_RESET]") +TEST_CASE("wake up from deep sleep using timer", "[deepsleep][reset=DEEPSLEEP_RESET]") { esp_sleep_enable_timer_wakeup(2000000); esp_deep_sleep_start(); } +TEST_CASE("light sleep followed by deep sleep", "[deepsleep][reset=DEEPSLEEP_RESET]") +{ + esp_sleep_enable_timer_wakeup(1000000); + esp_light_sleep_start(); + esp_deep_sleep_start(); +} + TEST_CASE("wake up from light sleep using timer", "[deepsleep]") { esp_sleep_enable_timer_wakeup(2000000); @@ -54,6 +63,103 @@ TEST_CASE("wake up from light sleep using timer", "[deepsleep]") TEST_ASSERT_INT32_WITHIN(500, 2000, (int) dt); } +static void test_light_sleep(void* arg) +{ + vTaskDelay(2); + for (int i = 0; i < 1000; ++i) { + printf("%d %d\n", xPortGetCoreID(), i); + fflush(stdout); + esp_light_sleep_start(); + } + SemaphoreHandle_t done = (SemaphoreHandle_t) arg; + xSemaphoreGive(done); + vTaskDelete(NULL); +} + +TEST_CASE("light sleep stress test", "[deepsleep]") +{ + SemaphoreHandle_t done = xSemaphoreCreateCounting(2, 0); + esp_sleep_enable_timer_wakeup(1000); + xTaskCreatePinnedToCore(&test_light_sleep, "ls0", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 0); +#if portNUM_PROCESSORS == 2 + xTaskCreatePinnedToCore(&test_light_sleep, "ls1", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 1); +#endif + xSemaphoreTake(done, portMAX_DELAY); +#if portNUM_PROCESSORS == 2 + xSemaphoreTake(done, portMAX_DELAY); +#endif + vSemaphoreDelete(done); +} + +#ifdef CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL +#define MAX_SLEEP_TIME_ERROR_US 200 +#else +#define MAX_SLEEP_TIME_ERROR_US 100 +#endif + + +TEST_CASE("light sleep duration is correct", "[deepsleep]") +{ + // don't power down XTAL — powering it up takes different time on + // different boards + esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON); + + // run one light sleep without checking timing, to warm up the cache + esp_sleep_enable_timer_wakeup(1000); + esp_light_sleep_start(); + + const int sleep_intervals_ms[] = { + 1, 1, 2, 3, 4, 5, 6, 7, 8, 10, 15, + 20, 25, 50, 100, 200, 500, + }; + + const int sleep_intervals_count = sizeof(sleep_intervals_ms)/sizeof(sleep_intervals_ms[0]); + for (int i = 0; i < sleep_intervals_count; ++i) { + uint64_t sleep_time = sleep_intervals_ms[i] * 1000; + esp_sleep_enable_timer_wakeup(sleep_time); + for (int repeat = 0; repeat < 5; ++repeat) { + uint64_t start = esp_clk_rtc_time(); + int64_t start_hs = esp_timer_get_time(); + esp_light_sleep_start(); + int64_t stop_hs = esp_timer_get_time(); + uint64_t stop = esp_clk_rtc_time(); + + int diff_us = (int) (stop - start); + int diff_hs_us = (int) (stop_hs - start_hs); + printf("%lld %d\n", sleep_time, (int) (diff_us - sleep_time)); + int32_t threshold = MAX(sleep_time / 100, MAX_SLEEP_TIME_ERROR_US); + TEST_ASSERT_INT32_WITHIN(threshold, sleep_time, diff_us); + TEST_ASSERT_INT32_WITHIN(threshold, sleep_time, diff_hs_us); + fflush(stdout); + } + + vTaskDelay(10/portTICK_PERIOD_MS); + } +} + + +TEST_CASE("light sleep and frequency switching", "[deepsleep]") +{ +#ifndef CONFIG_PM_ENABLE + const int uart_clk_freq = REF_CLK_FREQ; + CLEAR_PERI_REG_MASK(UART_CONF0_REG(CONFIG_CONSOLE_UART_NUM), UART_TICK_REF_ALWAYS_ON); + uart_div_modify(CONFIG_CONSOLE_UART_NUM, (uart_clk_freq << 4) / CONFIG_CONSOLE_UART_BAUDRATE); +#endif + + esp_sleep_enable_timer_wakeup(1000); + rtc_cpu_freq_t default_freq = rtc_clk_cpu_freq_get(); + for (int i = 0; i < 1000; ++i) { + if (i % 2 == 0) { + rtc_clk_cpu_freq_set_fast(RTC_CPU_FREQ_XTAL); + } else { + rtc_clk_cpu_freq_set_fast(default_freq); + } + printf("%d\n", i); + fflush(stdout); + esp_light_sleep_start(); + } +} + #ifndef CONFIG_FREERTOS_UNICORE TEST_CASE("enter deep sleep on APP CPU and wake up using timer", "[deepsleep][reset=DEEPSLEEP_RESET]") { @@ -138,7 +244,7 @@ TEST_CASE("disable source trigger behavior", "[deepsleep]") { float dt = 0; - printf("Setup timer and ext0 to wakeup imediately from GPIO_13 \n"); + printf("Setup timer and ext0 to wake up immediately from GPIO_13 \n"); // Setup ext0 configuration to wake up almost immediately // The wakeup time is proportional to input capacitance * pullup resistance @@ -159,7 +265,7 @@ TEST_CASE("disable source trigger behavior", "[deepsleep]") // Check wakeup from Ext0 using time measurement because wakeup cause is // not available in light sleep mode - TEST_ASSERT_INT32_WITHIN(299, 300, (int) dt); + TEST_ASSERT_INT32_WITHIN(100, 100, (int) dt); TEST_ASSERT((get_cause() & RTC_EXT0_TRIG_EN) != 0); @@ -175,7 +281,7 @@ TEST_CASE("disable source trigger behavior", "[deepsleep]") TEST_ASSERT_INT32_WITHIN(500, 2000, (int) dt); - // Additionaly check wakeup cause + // Additionally check wakeup cause TEST_ASSERT((get_cause() & RTC_TIMER_TRIG_EN) != 0); // Disable timer source. @@ -195,12 +301,11 @@ TEST_CASE("disable source trigger behavior", "[deepsleep]") dt = get_time_ms(); printf("Ext0 sleep time = %d \n", (int) dt); - TEST_ASSERT_INT32_WITHIN(199, 200, (int) dt); + TEST_ASSERT_INT32_WITHIN(100, 100, (int) dt); TEST_ASSERT((get_cause() & RTC_EXT0_TRIG_EN) != 0); // Check error message when source is already disabled esp_err_t err_code = esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER); TEST_ASSERT(err_code == ESP_ERR_INVALID_STATE); - printf("Test case completed successfully."); } diff --git a/components/soc/esp32/rtc_sleep.c b/components/soc/esp32/rtc_sleep.c index b0ffb2ff2b..041c2d1b6b 100644 --- a/components/soc/esp32/rtc_sleep.c +++ b/components/soc/esp32/rtc_sleep.c @@ -29,16 +29,26 @@ #define MHZ (1000000) /* Various delays to be programmed into power control state machines */ -#define ROM_RAM_POWERUP_DELAY 3 -#define ROM_RAM_WAIT_DELAY 3 -#define WIFI_POWERUP_DELAY 3 -#define WIFI_WAIT_DELAY 3 -#define RTC_POWERUP_DELAY 3 -#define RTC_WAIT_DELAY 3 -#define DG_WRAP_POWERUP_DELAY 3 -#define DG_WRAP_WAIT_DELAY 3 -#define RTC_MEM_POWERUP_DELAY 3 -#define RTC_MEM_WAIT_DELAY 3 +#define RTC_CNTL_XTL_BUF_WAIT_SLP 2 +#define RTC_CNTL_PLL_BUF_WAIT_SLP 2 +#define RTC_CNTL_CK8M_WAIT_SLP 4 +#define OTHER_BLOCKS_POWERUP 1 +#define OTHER_BLOCKS_WAIT 1 + +#define ROM_RAM_POWERUP_CYCLES OTHER_BLOCKS_POWERUP +#define ROM_RAM_WAIT_CYCLES OTHER_BLOCKS_WAIT + +#define WIFI_POWERUP_CYCLES OTHER_BLOCKS_POWERUP +#define WIFI_WAIT_CYCLES OTHER_BLOCKS_WAIT + +#define RTC_POWERUP_CYCLES OTHER_BLOCKS_POWERUP +#define RTC_WAIT_CYCLES OTHER_BLOCKS_WAIT + +#define DG_WRAP_POWERUP_CYCLES OTHER_BLOCKS_POWERUP +#define DG_WRAP_WAIT_CYCLES OTHER_BLOCKS_WAIT + +#define RTC_MEM_POWERUP_CYCLES OTHER_BLOCKS_POWERUP +#define RTC_MEM_WAIT_CYCLES OTHER_BLOCKS_WAIT /** * @brief Power down flags for rtc_sleep_pd function @@ -89,31 +99,31 @@ static void rtc_sleep_pd(rtc_sleep_pd_config_t cfg) void rtc_sleep_init(rtc_sleep_config_t cfg) { - //set 5 PWC state machine times to fit in main state machine time - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, 1); - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT, RTC_CNTL_XTL_BUF_WAIT_DEFAULT); - REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT); - //set rom&ram timer - REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_ROM_RAM_POWERUP_TIMER, ROM_RAM_POWERUP_DELAY); - REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_ROM_RAM_WAIT_TIMER, ROM_RAM_WAIT_DELAY); - //set wifi timer - REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_POWERUP_TIMER, WIFI_POWERUP_DELAY); - REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_WAIT_TIMER, WIFI_WAIT_DELAY); - //set rtc peri timer - REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_POWERUP_TIMER, RTC_POWERUP_DELAY); - REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_WAIT_TIMER, RTC_WAIT_DELAY); - //set digital wrap timer - REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_DG_WRAP_POWERUP_TIMER, DG_WRAP_POWERUP_DELAY); - REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_DG_WRAP_WAIT_TIMER, DG_WRAP_WAIT_DELAY); - //set rtc memory timer - REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_RTCMEM_POWERUP_TIMER, RTC_MEM_POWERUP_DELAY); - REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_RTCMEM_WAIT_TIMER, RTC_MEM_WAIT_DELAY); + // set 5 PWC state machine times to fit in main state machine time + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, RTC_CNTL_PLL_BUF_WAIT_SLP); + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT, RTC_CNTL_XTL_BUF_WAIT_SLP); + REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_SLP); - if (cfg.lslp_mem_inf_fpu) { - SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU); - } else { - CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU); - } + // set shortest possible sleep time limit + REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_MIN_SLP_VAL, RTC_CNTL_MIN_SLP_VAL_MIN); + + // set rom&ram timer + REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_ROM_RAM_POWERUP_TIMER, ROM_RAM_POWERUP_CYCLES); + REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_ROM_RAM_WAIT_TIMER, ROM_RAM_WAIT_CYCLES); + // set wifi timer + REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_POWERUP_TIMER, WIFI_POWERUP_CYCLES); + REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_WAIT_TIMER, WIFI_WAIT_CYCLES); + // set rtc peri timer + REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_POWERUP_TIMER, RTC_POWERUP_CYCLES); + REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_WAIT_TIMER, RTC_WAIT_CYCLES); + // set digital wrap timer + REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_DG_WRAP_POWERUP_TIMER, DG_WRAP_POWERUP_CYCLES); + REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_DG_WRAP_WAIT_TIMER, DG_WRAP_WAIT_CYCLES); + // set rtc memory timer + REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_RTCMEM_POWERUP_TIMER, RTC_MEM_POWERUP_CYCLES); + REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_RTCMEM_WAIT_TIMER, RTC_MEM_WAIT_CYCLES); + + REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU, cfg.lslp_mem_inf_fpu); rtc_sleep_pd_config_t pd_cfg = RTC_SLEEP_PD_CONFIG_ALL(cfg.lslp_meminf_pd); rtc_sleep_pd(pd_cfg); From 8646913cbfa2ba632c76dc52845973a769f8b3c0 Mon Sep 17 00:00:00 2001 From: Tian Hao Date: Tue, 16 Jan 2018 18:36:31 +0800 Subject: [PATCH 021/187] component/bt : add class bt read RSSI delta (golden range) --- components/bt/bluedroid/api/esp_gap_bt_api.c | 13 +++ .../api/include/api/esp_gap_bt_api.h | 36 +++++++-- components/bt/bluedroid/btc/core/btc_task.c | 2 +- components/bt/bluedroid/btc/core/btc_util.c | 67 ++++++++++++++++ .../bt/bluedroid/btc/include/btc/btc_util.h | 3 + .../btc/profile/std/gap/btc_gap_ble.c | 80 +------------------ .../btc/profile/std/gap/btc_gap_bt.c | 41 ++++++++++ .../btc/profile/std/include/btc_gap_bt.h | 6 ++ 8 files changed, 163 insertions(+), 85 deletions(-) diff --git a/components/bt/bluedroid/api/esp_gap_bt_api.c b/components/bt/bluedroid/api/esp_gap_bt_api.c index 9f3f427861..8e357200b2 100644 --- a/components/bt/bluedroid/api/esp_gap_bt_api.c +++ b/components/bt/bluedroid/api/esp_gap_bt_api.c @@ -178,4 +178,17 @@ esp_err_t esp_bt_gap_get_cod(esp_bt_cod_t *cod) return btc_gap_bt_get_cod(cod); } +esp_err_t esp_bt_gap_read_rssi_delta(esp_bd_addr_t remote_addr) +{ + btc_msg_t msg; + btc_gap_bt_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BT; + msg.act = BTC_GAP_BT_ACT_READ_RSSI_DELTA; + memcpy(arg.read_rssi_delta.bda.address, remote_addr, sizeof(esp_bd_addr_t)); + + return (btc_transfer_context(&msg, &arg, sizeof(btc_gap_bt_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + #endif /* #if BTC_GAP_BT_INCLUDED == TRUE */ diff --git a/components/bt/bluedroid/api/include/api/esp_gap_bt_api.h b/components/bt/bluedroid/api/include/api/esp_gap_bt_api.h index e840650c37..8631bac76a 100644 --- a/components/bt/bluedroid/api/include/api/esp_gap_bt_api.h +++ b/components/bt/bluedroid/api/include/api/esp_gap_bt_api.h @@ -23,13 +23,17 @@ extern "C" { #endif +/// RSSI threshold +#define ESP_BT_GAP_RSSI_HIGH_THRLD -20 /*!< High RSSI threshold */ +#define ESP_BT_GAP_RSSI_LOW_THRLD -45 /*!< Low RSSI threshold */ + /// Class of device typedef struct { - uint32_t reserved_2: 2; /*!< undefined */ - uint32_t minor: 6; /*!< minor class */ - uint32_t major: 5; /*!< major class */ - uint32_t service: 11; /*!< service class */ - uint32_t reserved_8: 8; /*!< undefined */ + uint32_t reserved_2: 2; /*!< undefined */ + uint32_t minor: 6; /*!< minor class */ + uint32_t major: 5; /*!< major class */ + uint32_t service: 11; /*!< service class */ + uint32_t reserved_8: 8; /*!< undefined */ } esp_bt_cod_t; /// class of device settings @@ -144,6 +148,8 @@ typedef enum { ESP_BT_GAP_DISC_STATE_CHANGED_EVT, /*!< discovery state changed event */ ESP_BT_GAP_RMT_SRVCS_EVT, /*!< get remote services event */ ESP_BT_GAP_RMT_SRVC_REC_EVT, /*!< get remote service record event */ + ESP_BT_GAP_READ_RSSI_DELTA_EVT, /*!< read rssi event */ + ESP_BT_GAP_EVT_MAX, } esp_bt_gap_cb_event_t; /** Inquiry Mode */ @@ -192,6 +198,14 @@ typedef union { esp_bt_status_t stat; /*!< service search status */ } rmt_srvc_rec; /*!< specific service record from remote device parameter struct */ + /** + * @brief ESP_BT_GAP_READ_RSSI_DELTA_EVT * + */ + struct read_rssi_delta_param { + esp_bd_addr_t bda; /*!< remote bluetooth device address*/ + esp_bt_status_t stat; /*!< read rssi status */ + int8_t rssi_delta; /*!< rssi delta value range -128 ~127, The value zero indicates that the RSSI is inside the Golden Receive Power Range, the Golden Receive Power Range is from ESP_BT_GAP_RSSI_LOW_THRLD to ESP_BT_GAP_RSSI_HIGH_THRLD */ + } read_rssi_delta; /*!< read rssi parameter struct */ } esp_bt_gap_cb_param_t; /** @@ -372,6 +386,18 @@ esp_err_t esp_bt_gap_set_cod(esp_bt_cod_t cod, esp_bt_cod_mode_t mode); */ esp_err_t esp_bt_gap_get_cod(esp_bt_cod_t *cod); +/** + * @brief This function is called to read RSSI delta by address after connected. The RSSI value returned by ESP_BT_GAP_READ_RSSI_DELTA_EVT. + * + * + * @param[in] remote_addr - remote device address, corresponding to a certain connection handle. + * @return + * - ESP_OK : Succeed + * - ESP_FAIL: others + * + */ +esp_err_t esp_bt_gap_read_rssi_delta(esp_bd_addr_t remote_addr); + #ifdef __cplusplus } #endif diff --git a/components/bt/bluedroid/btc/core/btc_task.c b/components/bt/bluedroid/btc/core/btc_task.c index be198082cf..d98e6b4c33 100644 --- a/components/bt/bluedroid/btc/core/btc_task.c +++ b/components/bt/bluedroid/btc/core/btc_task.c @@ -70,7 +70,7 @@ static btc_func_t profile_tab[BTC_PID_NUM] = { [BTC_PID_ALARM] = {btc_alarm_handler, NULL }, #if CONFIG_CLASSIC_BT_ENABLED #if (BTC_GAP_BT_INCLUDED == TRUE) - [BTC_PID_GAP_BT] = {btc_gap_bt_call_handler, NULL }, + [BTC_PID_GAP_BT] = {btc_gap_bt_call_handler, btc_gap_bt_cb_handler }, #endif /* (BTC_GAP_BT_INCLUDED == TRUE) */ [BTC_PID_PRF_QUE] = {btc_profile_queue_handler, NULL }, #if BTC_AV_INCLUDED diff --git a/components/bt/bluedroid/btc/core/btc_util.c b/components/bt/bluedroid/btc/core/btc_util.c index fa95f42163..633b03c60d 100644 --- a/components/bt/bluedroid/btc/core/btc_util.c +++ b/components/bt/bluedroid/btc/core/btc_util.c @@ -31,6 +31,7 @@ #include "bta/bta_av_api.h" #endif ///BTA_AV_INCLUDED == TRUE #include "common/bt_defs.h" +#include "stack/btm_api.h" /************************************************************************************ ** Constants & Macros @@ -179,3 +180,69 @@ void uuid_to_string_legacy(bt_uuid_t *p_uuid, char *str) ntohl(uuid4), ntohs(uuid5)); return; } + +esp_bt_status_t btc_hci_to_esp_status(uint8_t hci_status) +{ + esp_bt_status_t esp_status = ESP_BT_STATUS_FAIL; + switch(hci_status) { + case HCI_SUCCESS: + esp_status = ESP_BT_STATUS_SUCCESS; + break; + case HCI_ERR_HOST_TIMEOUT: + esp_status = ESP_BT_STATUS_TIMEOUT; + break; + case HCI_ERR_ILLEGAL_COMMAND: + esp_status = ESP_BT_STATUS_PENDING; + break; + case HCI_ERR_UNACCEPT_CONN_INTERVAL: + esp_status = ESP_BT_STATUS_UNACCEPT_CONN_INTERVAL; + break; + case HCI_ERR_PARAM_OUT_OF_RANGE: + esp_status = ESP_BT_STATUS_PARAM_OUT_OF_RANGE; + break; + case HCI_ERR_ILLEGAL_PARAMETER_FMT: + esp_status = ESP_BT_STATUS_ERR_ILLEGAL_PARAMETER_FMT; + break; + default: + esp_status = ESP_BT_STATUS_FAIL; + break; + } + + return esp_status; +} + +esp_bt_status_t btc_btm_status_to_esp_status (uint8_t btm_status) +{ + esp_bt_status_t esp_status = ESP_BT_STATUS_FAIL; + switch(btm_status){ + case BTM_SUCCESS: + esp_status = ESP_BT_STATUS_SUCCESS; + break; + case BTM_BUSY: + esp_status = ESP_BT_STATUS_BUSY; + break; + case BTM_NO_RESOURCES: + esp_status = ESP_BT_STATUS_NOMEM; + break; + case BTM_ERR_PROCESSING: + esp_status = ESP_BT_STATUS_PENDING; + break; + case BTM_PEER_LE_DATA_LEN_UNSUPPORTED: + esp_status = ESP_BT_STATUS_PEER_LE_DATA_LEN_UNSUPPORTED; + break; + case BTM_CONTROL_LE_DATA_LEN_UNSUPPORTED: + esp_status = ESP_BT_STATUS_CONTROL_LE_DATA_LEN_UNSUPPORTED; + break; + case BTM_SET_PRIVACY_SUCCESS: + esp_status = ESP_BT_STATUS_SUCCESS; + break; + case BTM_SET_PRIVACY_FAIL: + esp_status = ESP_BT_STATUS_FAIL; + break; + default: + esp_status = ESP_BT_STATUS_FAIL; + break; + } + + return esp_status; +} diff --git a/components/bt/bluedroid/btc/include/btc/btc_util.h b/components/bt/bluedroid/btc/include/btc/btc_util.h index 9787a91946..df44297c3b 100644 --- a/components/bt/bluedroid/btc/include/btc/btc_util.h +++ b/components/bt/bluedroid/btc/include/btc/btc_util.h @@ -44,4 +44,7 @@ void uuid128_be_to_esp_uuid(esp_bt_uuid_t *u, uint8_t* uuid128); void uuid_to_string_legacy(bt_uuid_t *p_uuid, char *str); +esp_bt_status_t btc_hci_to_esp_status(uint8_t hci_status); +esp_bt_status_t btc_btm_status_to_esp_status (uint8_t btm_status); + #endif /* __BTC_UTIL_H__ */ diff --git a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c index 741a76dfbf..e0654e6f5e 100644 --- a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c +++ b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c @@ -27,6 +27,7 @@ #include "esp_gap_ble_api.h" #include "btc/btc_ble_storage.h" #include "btc/btc_dm.h" +#include "btc/btc_util.h" static tBTA_BLE_ADV_DATA gl_bta_adv_data; static tBTA_BLE_ADV_DATA gl_bta_scan_rsp_data; @@ -107,85 +108,6 @@ static void btc_cleanup_adv_data(tBTA_BLE_ADV_DATA *bta_adv_data) btc_gap_adv_point_cleanup((void **) &bta_adv_data->p_sol_service_128b); } - -static esp_bt_status_t btc_hci_to_esp_status(uint8_t hci_status) -{ - esp_bt_status_t esp_status = ESP_BT_STATUS_FAIL; - switch(hci_status) { - case HCI_SUCCESS: - esp_status = ESP_BT_STATUS_SUCCESS; - break; - case HCI_ERR_ESP_VENDOR_FAIL: - esp_status = ESP_BT_STATUS_FAIL; - break; - case HCI_ERR_HOST_TIMEOUT: - esp_status = ESP_BT_STATUS_TIMEOUT; - break; - case HCI_ERR_ILLEGAL_COMMAND: - esp_status = ESP_BT_STATUS_PENDING; - break; - case HCI_ERR_UNACCEPT_CONN_INTERVAL: - esp_status = ESP_BT_STATUS_UNACCEPT_CONN_INTERVAL; - break; - case HCI_ERR_PARAM_OUT_OF_RANGE: - esp_status = ESP_BT_STATUS_PARAM_OUT_OF_RANGE; - break; - case HCI_ERR_ILLEGAL_PARAMETER_FMT: - esp_status = ESP_BT_STATUS_ERR_ILLEGAL_PARAMETER_FMT; - break; - case HCI_ERR_MEMORY_FULL: - esp_status = ESP_BT_STATUS_MEMORY_FULL; - break; - default: - esp_status = ESP_BT_STATUS_FAIL; - break; - } - - return esp_status; -} - -static esp_bt_status_t btc_btm_status_to_esp_status (uint8_t btm_status) -{ - esp_bt_status_t esp_status = ESP_BT_STATUS_FAIL; - switch(btm_status){ - case BTM_SUCCESS: - esp_status = ESP_BT_STATUS_SUCCESS; - break; - case BTM_BUSY: - esp_status = ESP_BT_STATUS_BUSY; - break; - case BTM_NO_RESOURCES: - esp_status = ESP_BT_STATUS_NOMEM; - break; - case BTM_ERR_PROCESSING: - esp_status = ESP_BT_STATUS_PENDING; - break; - case BTM_PEER_LE_DATA_LEN_UNSUPPORTED: - esp_status = ESP_BT_STATUS_PEER_LE_DATA_LEN_UNSUPPORTED; - break; - case BTM_CONTROL_LE_DATA_LEN_UNSUPPORTED: - esp_status = ESP_BT_STATUS_CONTROL_LE_DATA_LEN_UNSUPPORTED; - break; - case BTM_SET_PRIVACY_SUCCESS: - esp_status = ESP_BT_STATUS_SUCCESS; - break; - case BTM_SET_PRIVACY_FAIL: - esp_status = ESP_BT_STATUS_FAIL; - break; - case BTM_INVALID_STATIC_RAND_ADDR: - esp_status = ESP_BT_STATUS_INVALID_STATIC_RAND_ADDR; - break; - case BTM_SET_STATIC_RAND_ADDR_FAIL: - esp_status = ESP_BT_STATUS_FAIL; - break; - default: - esp_status = ESP_BT_STATUS_FAIL; - break; - } - - return esp_status; -} - static void btc_to_bta_adv_data(esp_ble_adv_data_t *p_adv_data, tBTA_BLE_ADV_DATA *bta_adv_data, uint32_t *data_mask) { uint32_t mask; diff --git a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c index 20f7d32811..ad588568a2 100644 --- a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c +++ b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c @@ -594,6 +594,32 @@ esp_err_t btc_gap_bt_get_cod(esp_bt_cod_t *cod) return ESP_BT_STATUS_SUCCESS; } +static void btc_gap_bt_read_rssi_delta_cmpl_callback(void *p_data) +{ + tBTA_RSSI_RESULTS *result = (tBTA_RSSI_RESULTS *)p_data; + esp_bt_gap_cb_param_t param; + bt_status_t ret; + btc_msg_t msg; + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BT; + msg.act = ESP_BT_GAP_READ_RSSI_DELTA_EVT; + memcpy(param.read_rssi_delta.bda, result->rem_bda, sizeof(BD_ADDR)); + param.read_rssi_delta.stat = btc_btm_status_to_esp_status(result->status); + param.read_rssi_delta.rssi_delta = result->rssi; + + ret = btc_transfer_context(&msg, ¶m, + sizeof(esp_bt_gap_cb_param_t), NULL); + + if (ret != BT_STATUS_SUCCESS) { + LOG_ERROR("%s btc_transfer_context failed\n", __func__); + } +} + +static void btc_gap_bt_read_rssi_delta(btc_gap_bt_args_t *arg) +{ + BTA_DmBleReadRSSI(arg->read_rssi_delta.bda.address, btc_gap_bt_read_rssi_delta_cmpl_callback); +} + void btc_gap_bt_call_handler(btc_msg_t *msg) { btc_gap_bt_args_t *arg = (btc_gap_bt_args_t *)msg->arg; @@ -635,6 +661,10 @@ void btc_gap_bt_call_handler(btc_msg_t *msg) btc_gap_bt_set_cod(msg->arg); break; } + case BTC_GAP_BT_ACT_READ_RSSI_DELTA: { + btc_gap_bt_read_rssi_delta(msg->arg); + break; + } default: break; } @@ -658,4 +688,15 @@ void btc_gap_bt_busy_level_updated(uint8_t bl_flags) } } +void btc_gap_bt_cb_handler(btc_msg_t *msg) +{ + esp_bt_gap_cb_param_t *param = (esp_bt_gap_cb_param_t *)msg->arg; + + if (msg->act < ESP_BT_GAP_EVT_MAX) { + btc_gap_bt_cb_to_app(msg->act, param); + } else { + LOG_ERROR("%s, unknow msg->act = %d", __func__, msg->act); + } + +} #endif /* (BTC_GAP_BT_INCLUDED == TRUE) */ diff --git a/components/bt/bluedroid/btc/profile/std/include/btc_gap_bt.h b/components/bt/bluedroid/btc/profile/std/include/btc_gap_bt.h index 1dc6653125..4ca1803fdc 100644 --- a/components/bt/bluedroid/btc/profile/std/include/btc_gap_bt.h +++ b/components/bt/bluedroid/btc/profile/std/include/btc_gap_bt.h @@ -34,6 +34,7 @@ typedef enum { BTC_GAP_BT_ACT_GET_REMOTE_SERVICE_RECORD, BTC_GAP_BT_ACT_SEARCH_SERVICE_RECORD, BTC_GAP_BT_ACT_SET_COD, + BTC_GAP_BT_ACT_READ_RSSI_DELTA, } btc_gap_bt_act_t; /* btc_bt_gap_args_t */ @@ -65,9 +66,14 @@ typedef union { esp_bt_cod_mode_t mode; } set_cod; + //BTC_GAP_BT_ACT_READ_RSSI_DELTA, + struct bt_read_rssi_delta_args { + bt_bdaddr_t bda; + } read_rssi_delta; } btc_gap_bt_args_t; void btc_gap_bt_call_handler(btc_msg_t *msg); +void btc_gap_bt_cb_handler(btc_msg_t *msg); void btc_gap_bt_busy_level_updated(uint8_t bl_flags); From 8f015e3e48c297581a544ecde94c3671d7926b2a Mon Sep 17 00:00:00 2001 From: Yulong Date: Thu, 26 Apr 2018 09:01:53 -0400 Subject: [PATCH 022/187] component/bt: Check the value received from the peer device when sent the data used prepare write. component/bt: Fix misspellings of "corret" in comments in bta_gattc_write_cmpl function. --- components/bt/bluedroid/bta/gatt/bta_gattc_act.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c index c3e729f48b..455a761b21 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c @@ -1278,11 +1278,16 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) if (p_clcb->p_q_cmd->api_write.hdr.event == BTA_GATTC_API_WRITE_EVT && p_clcb->p_q_cmd->api_write.write_type == BTA_GATTC_WRITE_PREPARE) { + // Should check the value received from the peer device is correct or not. + if (memcmp(p_clcb->p_q_cmd->api_write.p_value, p_data->p_cmpl->att_value.value, + p_data->p_cmpl->att_value.len) != 0) { + cb_data.write.status = BTA_GATT_INVALID_PDU; + } event = BTA_GATTC_PREP_WRITE_EVT; - } else { + } else { event = p_clcb->p_q_cmd->api_write.cmpl_evt; - } + } //free the command data store in the queue. bta_gattc_free_command_data(p_clcb); bta_gattc_pop_command_to_send(p_clcb); From e236ffd91f08310a017d8576f70358b866efc44d Mon Sep 17 00:00:00 2001 From: zhiweijian Date: Thu, 26 Apr 2018 17:17:35 +0800 Subject: [PATCH 023/187] Component/bt: get end_handle when get include services --- components/bt/bluedroid/api/include/api/esp_gatt_defs.h | 3 ++- components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/components/bt/bluedroid/api/include/api/esp_gatt_defs.h b/components/bt/bluedroid/api/include/api/esp_gatt_defs.h index 5383f70e0e..77cdcd6526 100644 --- a/components/bt/bluedroid/api/include/api/esp_gatt_defs.h +++ b/components/bt/bluedroid/api/include/api/esp_gatt_defs.h @@ -450,7 +450,8 @@ typedef struct { */ typedef struct { uint16_t handle; /*!< The include service current attribute handle */ - uint16_t incl_srvc_s_handle; /*!< The start hanlde of the service which has been included */ + uint16_t incl_srvc_s_handle; /*!< The start handle of the service which has been included */ + uint16_t incl_srvc_e_handle; /*!< The end handle of the service which has been included */ esp_bt_uuid_t uuid; /*!< The include service uuid */ } esp_gattc_incl_svc_elem_t; /*!< The gattc inclue service element */ diff --git a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c index a6273d14bb..ea86459fc3 100644 --- a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c +++ b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c @@ -284,6 +284,7 @@ static void btc_gattc_fill_gatt_db_conversion(uint16_t count, uint16_t num, esp_ for (int i = 0; i < db_size; i++) { incl_result->handle = db[offset + i].attribute_handle; incl_result->incl_srvc_s_handle = db[offset + i].start_handle; + incl_result->incl_srvc_e_handle = db[offset + i].end_handle; btc128_to_bta_uuid(&bta_uuid, db[offset + i].uuid.uu); bta_to_btc_uuid(&incl_result->uuid, &bta_uuid); incl_result++; From fd7baaf4ba9992fa024d0324958f1c732028e00d Mon Sep 17 00:00:00 2001 From: Hrishikesh Dhayagude Date: Mon, 16 Apr 2018 12:23:16 +0530 Subject: [PATCH 024/187] components/bt: Make modifications to the support of GAP appearance/icon characateristic 1. In addition to mentioning in the documentation, use the standard appearance values already present and return appropriate error in case an incorrect value is passed 2. Add ESP_BLE_APPEARANCE* macros corresponding to BTM_BLE_APPEARANCE* and use them from the API instead 3. Add the missing appearance parameter values from https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml 4. Fix some minor typos Signed-off-by: Hrishikesh Dhayagude --- components/bt/bluedroid/api/esp_gap_ble_api.c | 77 +++++++++++++++++-- .../bluedroid/api/include/api/esp_bt_device.h | 2 +- .../api/include/api/esp_gap_ble_api.h | 66 +++++++++++++++- components/bt/bluedroid/bta/dm/bta_dm_act.c | 4 +- .../bt/bluedroid/stack/btm/btm_ble_gap.c | 4 +- .../stack/include/stack/btm_ble_api.h | 11 ++- 6 files changed, 149 insertions(+), 15 deletions(-) diff --git a/components/bt/bluedroid/api/esp_gap_ble_api.c b/components/bt/bluedroid/api/esp_gap_ble_api.c index a73eca9d67..1089d72361 100644 --- a/components/bt/bluedroid/api/esp_gap_ble_api.c +++ b/components/bt/bluedroid/api/esp_gap_ble_api.c @@ -197,17 +197,82 @@ esp_err_t esp_ble_gap_config_local_privacy (bool privacy_enable) esp_err_t esp_ble_gap_config_local_icon (uint16_t icon) { + esp_err_t ret; btc_msg_t msg; btc_ble_gap_args_t arg; ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); - msg.sig = BTC_SIG_API_CALL; - msg.pid = BTC_PID_GAP_BLE; - msg.act = BTC_GAP_BLE_ACT_CONFIG_LOCAL_ICON; - arg.cfg_local_icon.icon = icon; - - return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); + switch (icon) { + case ESP_BLE_APPEARANCE_GENERIC_PHONE: + case ESP_BLE_APPEARANCE_GENERIC_COMPUTER: + case ESP_BLE_APPEARANCE_GENERIC_REMOTE: + case ESP_BLE_APPEARANCE_GENERIC_THERMOMETER: + case ESP_BLE_APPEARANCE_THERMOMETER_EAR: + case ESP_BLE_APPEARANCE_GENERIC_HEART_RATE: + case ESP_BLE_APPEARANCE_HEART_RATE_BELT: + case ESP_BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE: + case ESP_BLE_APPEARANCE_BLOOD_PRESSURE_ARM: + case ESP_BLE_APPEARANCE_BLOOD_PRESSURE_WRIST: + case ESP_BLE_APPEARANCE_GENERIC_PULSE_OXIMETER: + case ESP_BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP: + case ESP_BLE_APPEARANCE_PULSE_OXIMETER_WRIST: + case ESP_BLE_APPEARANCE_GENERIC_GLUCOSE: + case ESP_BLE_APPEARANCE_GENERIC_WEIGHT: + case ESP_BLE_APPEARANCE_GENERIC_WALKING: + case ESP_BLE_APPEARANCE_WALKING_IN_SHOE: + case ESP_BLE_APPEARANCE_WALKING_ON_SHOE: + case ESP_BLE_APPEARANCE_WALKING_ON_HIP: + case ESP_BLE_APPEARANCE_GENERIC_WATCH: + case ESP_BLE_APPEARANCE_SPORTS_WATCH: + case ESP_BLE_APPEARANCE_GENERIC_EYEGLASSES: + case ESP_BLE_APPEARANCE_GENERIC_DISPLAY: + case ESP_BLE_APPEARANCE_GENERIC_MEDIA_PLAYER: + case ESP_BLE_APPEARANCE_GENERIC_BARCODE_SCANNER: + case ESP_BLE_APPEARANCE_HID_BARCODE_SCANNER: + case ESP_BLE_APPEARANCE_GENERIC_HID: + case ESP_BLE_APPEARANCE_HID_KEYBOARD: + case ESP_BLE_APPEARANCE_HID_MOUSE: + case ESP_BLE_APPEARANCE_HID_JOYSTICK: + case ESP_BLE_APPEARANCE_HID_GAMEPAD: + case ESP_BLE_APPEARANCE_HID_DIGITIZER_TABLET: + case ESP_BLE_APPEARANCE_HID_CARD_READER: + case ESP_BLE_APPEARANCE_HID_DIGITAL_PEN: + case ESP_BLE_APPEARANCE_UNKNOWN: + case ESP_BLE_APPEARANCE_GENERIC_CLOCK: + case ESP_BLE_APPEARANCE_GENERIC_TAG: + case ESP_BLE_APPEARANCE_GENERIC_KEYRING: + case ESP_BLE_APPEARANCE_GENERIC_CYCLING: + case ESP_BLE_APPEARANCE_CYCLING_COMPUTER: + case ESP_BLE_APPEARANCE_CYCLING_SPEED: + case ESP_BLE_APPEARANCE_CYCLING_CADENCE: + case ESP_BLE_APPEARANCE_CYCLING_POWER: + case ESP_BLE_APPEARANCE_CYCLING_SPEED_CADENCE: + case ESP_BLE_APPEARANCE_GENERIC_PERSONAL_MOBILITY_DEVICE: + case ESP_BLE_APPEARANCE_POWERED_WHEELCHAIR: + case ESP_BLE_APPEARANCE_MOBILITY_SCOOTER: + case ESP_BLE_APPEARANCE_GENERIC_CONTINUOUS_GLUCOSE_MONITOR: + case ESP_BLE_APPEARANCE_GENERIC_INSULIN_PUMP: + case ESP_BLE_APPEARANCE_INSULIN_PUMP_DURABLE_PUMP: + case ESP_BLE_APPEARANCE_INSULIN_PUMP_PATCH_PUMP: + case ESP_BLE_APPEARANCE_INSULIN_PEN: + case ESP_BLE_APPEARANCE_GENERIC_MEDICATION_DELIVERY: + case ESP_BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS: + case ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION: + case ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_AND_NAV: + case ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD: + case ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD_AND_NAV: + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BLE; + msg.act = BTC_GAP_BLE_ACT_CONFIG_LOCAL_ICON; + arg.cfg_local_icon.icon = icon; + ret = (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); + break; + default: + ret = ESP_ERR_INVALID_ARG; + break; + } + return ret; } esp_err_t esp_ble_gap_update_whitelist(bool add_remove, esp_bd_addr_t remote_bda) diff --git a/components/bt/bluedroid/api/include/api/esp_bt_device.h b/components/bt/bluedroid/api/include/api/esp_bt_device.h index 0dca449978..76fb1b9d34 100644 --- a/components/bt/bluedroid/api/include/api/esp_bt_device.h +++ b/components/bt/bluedroid/api/include/api/esp_bt_device.h @@ -44,7 +44,7 @@ const uint8_t *esp_bt_dev_get_address(void); * @return * - ESP_OK : Succeed * - ESP_ERR_INVALID_ARG : if name is NULL pointer or empty, or string length out of limit - * - ESP_INVALID_STATE : if bluetooth stack is not yet enabled + * - ESP_ERR_INVALID_STATE : if bluetooth stack is not yet enabled * - ESP_FAIL : others */ esp_err_t esp_bt_dev_set_device_name(const char *name); diff --git a/components/bt/bluedroid/api/include/api/esp_gap_ble_api.h b/components/bt/bluedroid/api/include/api/esp_gap_ble_api.h index fe5bd04eeb..5bf7e0b139 100644 --- a/components/bt/bluedroid/api/include/api/esp_gap_ble_api.h +++ b/components/bt/bluedroid/api/include/api/esp_gap_ble_api.h @@ -66,6 +66,66 @@ typedef uint8_t esp_ble_auth_req_t; /*!< combination of the above bit #define ESP_IO_CAP_IN 2 /*!< KeyboardOnly */ /* relate to BTM_IO_CAP_IN in stack/btm_api.h */ #define ESP_IO_CAP_NONE 3 /*!< NoInputNoOutput */ /* relate to BTM_IO_CAP_NONE in stack/btm_api.h */ #define ESP_IO_CAP_KBDISP 4 /*!< Keyboard display */ /* relate to BTM_IO_CAP_KBDISP in stack/btm_api.h */ + +#define ESP_BLE_APPEARANCE_UNKNOWN 0x0000 /* relate to BTM_BLE_APPEARANCE_UNKNOWN in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_PHONE 0x0040 /* relate to BTM_BLE_APPEARANCE_GENERIC_PHONE in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_COMPUTER 0x0080 /* relate to BTM_BLE_APPEARANCE_GENERIC_COMPUTER in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_WATCH 0x00C0 /* relate to BTM_BLE_APPEARANCE_GENERIC_WATCH in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_SPORTS_WATCH 0x00C1 /* relate to BTM_BLE_APPEARANCE_SPORTS_WATCH in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_CLOCK 0x0100 /* relate to BTM_BLE_APPEARANCE_GENERIC_CLOCK in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_DISPLAY 0x0140 /* relate to BTM_BLE_APPEARANCE_GENERIC_DISPLAY in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_REMOTE 0x0180 /* relate to BTM_BLE_APPEARANCE_GENERIC_REMOTE in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_EYEGLASSES 0x01C0 /* relate to BTM_BLE_APPEARANCE_GENERIC_EYEGLASSES in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_TAG 0x0200 /* relate to BTM_BLE_APPEARANCE_GENERIC_TAG in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_KEYRING 0x0240 /* relate to BTM_BLE_APPEARANCE_GENERIC_KEYRING in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_MEDIA_PLAYER 0x0280 /* relate to BTM_BLE_APPEARANCE_GENERIC_MEDIA_PLAYER in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_BARCODE_SCANNER 0x02C0 /* relate to BTM_BLE_APPEARANCE_GENERIC_BARCODE_SCANNER in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_THERMOMETER 0x0300 /* relate to BTM_BLE_APPEARANCE_GENERIC_THERMOMETER in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_THERMOMETER_EAR 0x0301 /* relate to BTM_BLE_APPEARANCE_THERMOMETER_EAR in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_HEART_RATE 0x0340 /* relate to BTM_BLE_APPEARANCE_GENERIC_HEART_RATE in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_HEART_RATE_BELT 0x0341 /* relate to BTM_BLE_APPEARANCE_HEART_RATE_BELT in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE 0x0380 /* relate to BTM_BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_BLOOD_PRESSURE_ARM 0x0381 /* relate to BTM_BLE_APPEARANCE_BLOOD_PRESSURE_ARM in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_BLOOD_PRESSURE_WRIST 0x0382 /* relate to BTM_BLE_APPEARANCE_BLOOD_PRESSURE_WRIST in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_HID 0x03C0 /* relate to BTM_BLE_APPEARANCE_GENERIC_HID in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_HID_KEYBOARD 0x03C1 /* relate to BTM_BLE_APPEARANCE_HID_KEYBOARD in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_HID_MOUSE 0x03C2 /* relate to BTM_BLE_APPEARANCE_HID_MOUSE in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_HID_JOYSTICK 0x03C3 /* relate to BTM_BLE_APPEARANCE_HID_JOYSTICK in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_HID_GAMEPAD 0x03C4 /* relate to BTM_BLE_APPEARANCE_HID_GAMEPAD in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_HID_DIGITIZER_TABLET 0x03C5 /* relate to BTM_BLE_APPEARANCE_HID_DIGITIZER_TABLET in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_HID_CARD_READER 0x03C6 /* relate to BTM_BLE_APPEARANCE_HID_CARD_READER in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_HID_DIGITAL_PEN 0x03C7 /* relate to BTM_BLE_APPEARANCE_HID_DIGITAL_PEN in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_HID_BARCODE_SCANNER 0x03C8 /* relate to BTM_BLE_APPEARANCE_HID_BARCODE_SCANNER in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_GLUCOSE 0x0400 /* relate to BTM_BLE_APPEARANCE_GENERIC_GLUCOSE in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_WALKING 0x0440 /* relate to BTM_BLE_APPEARANCE_GENERIC_WALKING in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_WALKING_IN_SHOE 0x0441 /* relate to BTM_BLE_APPEARANCE_WALKING_IN_SHOE in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_WALKING_ON_SHOE 0x0442 /* relate to BTM_BLE_APPEARANCE_WALKING_ON_SHOE in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_WALKING_ON_HIP 0x0443 /* relate to BTM_BLE_APPEARANCE_WALKING_ON_HIP in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_CYCLING 0x0480 /* relate to BTM_BLE_APPEARANCE_GENERIC_CYCLING in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_CYCLING_COMPUTER 0x0481 /* relate to BTM_BLE_APPEARANCE_CYCLING_COMPUTER in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_CYCLING_SPEED 0x0482 /* relate to BTM_BLE_APPEARANCE_CYCLING_SPEED in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_CYCLING_CADENCE 0x0483 /* relate to BTM_BLE_APPEARANCE_CYCLING_CADENCE in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_CYCLING_POWER 0x0484 /* relate to BTM_BLE_APPEARANCE_CYCLING_POWER in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_CYCLING_SPEED_CADENCE 0x0485 /* relate to BTM_BLE_APPEARANCE_CYCLING_SPEED_CADENCE in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_PULSE_OXIMETER 0x0C40 /* relate to BTM_BLE_APPEARANCE_GENERIC_PULSE_OXIMETER in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP 0x0C41 /* relate to BTM_BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_PULSE_OXIMETER_WRIST 0x0C42 /* relate to BTM_BLE_APPEARANCE_PULSE_OXIMETER_WRIST in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_WEIGHT 0x0C80 /* relate to BTM_BLE_APPEARANCE_GENERIC_WEIGHT in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_PERSONAL_MOBILITY_DEVICE 0x0CC0 /* relate to BTM_BLE_APPEARANCE_GENERIC_PERSONAL_MOBILITY_DEVICE in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_POWERED_WHEELCHAIR 0x0CC1 /* relate to BTM_BLE_APPEARANCE_POWERED_WHEELCHAIR in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_MOBILITY_SCOOTER 0x0CC2 /* relate to BTM_BLE_APPEARANCE_MOBILITY_SCOOTER in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_CONTINUOUS_GLUCOSE_MONITOR 0x0D00 /* relate to BTM_BLE_APPEARANCE_GENERIC_CONTINUOUS_GLUCOSE_MONITOR in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_INSULIN_PUMP 0x0D40 /* relate to BTM_BLE_APPEARANCE_GENERIC_INSULIN_PUMP in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_INSULIN_PUMP_DURABLE_PUMP 0x0D41 /* relate to BTM_BLE_APPEARANCE_INSULIN_PUMP_DURABLE_PUMP in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_INSULIN_PUMP_PATCH_PUMP 0x0D44 /* relate to BTM_BLE_APPEARANCE_INSULIN_PUMP_PATCH_PUMP in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_INSULIN_PEN 0x0D48 /* relate to BTM_BLE_APPEARANCE_INSULIN_PEN in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_MEDICATION_DELIVERY 0x0D80 /* relate to BTM_BLE_APPEARANCE_GENERIC_MEDICATION_DELIVERY in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS 0x1440 /* relate to BTM_BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION 0x1441 /* relate to BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_AND_NAV 0x1442 /* relate to BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_AND_NAV in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD 0x1443 /* relate to BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD in stack/btm_ble_api.h */ +#define ESP_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD_AND_NAV 0x1444 /* relate to BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD_AND_NAV in stack/btm_ble_api.h */ + typedef uint8_t esp_ble_io_cap_t; /*!< combination of the io capability */ /// GAP BLE callback event type @@ -777,11 +837,11 @@ esp_err_t esp_ble_gap_config_local_privacy (bool privacy_enable); /** * @brief set local gap appearance icon - * * - * @param[in] icon - Appearance value, these vlues are Defined by the Bluetooth organization, please refer to + * + * @param[in] icon - External appearance value, these values are defined by the Bluetooth SIG, please refer to * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml - * + * * @return * - ESP_OK : success * - other : failed diff --git a/components/bt/bluedroid/bta/dm/bta_dm_act.c b/components/bt/bluedroid/bta/dm/bta_dm_act.c index fa87d3fe6c..3bf5487731 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_act.c @@ -4684,9 +4684,9 @@ void bta_dm_ble_config_local_privacy (tBTA_DM_MSG *p_data) /******************************************************************************* ** -** Function bta_dm_ble_config_local_privacy +** Function bta_dm_ble_config_local_icon ** -** Description This function set the local device LE privacy settings. +** Description This function sets the local icon value. ** ** *******************************************************************************/ diff --git a/components/bt/bluedroid/stack/btm/btm_ble_gap.c b/components/bt/bluedroid/stack/btm/btm_ble_gap.c index 090b3d53bd..bb4ec9fd8d 100644 --- a/components/bt/bluedroid/stack/btm/btm_ble_gap.c +++ b/components/bt/bluedroid/stack/btm/btm_ble_gap.c @@ -829,7 +829,7 @@ void BTM_BleConfigLocalIcon(uint16_t icon) p_value.icon = icon; GAP_BleAttrDBUpdate(GATT_UUID_GAP_ICON, &p_value); #else - BTM_TRACE_ERROR("%s\n", __func__); + BTM_TRACE_ERROR("%s\n", __func__); #endif } /******************************************************************************* @@ -2833,7 +2833,7 @@ static void btm_ble_appearance_to_cod(UINT16 appearance, UINT8 *dev_class) dev_class[1] = BTM_COD_MAJOR_PERIPHERAL; dev_class[2] = BTM_COD_MINOR_DIGITAL_PAN; break; - case BTM_BLE_APPEARANCE_UKNOWN: + case BTM_BLE_APPEARANCE_UNKNOWN: case BTM_BLE_APPEARANCE_GENERIC_CLOCK: case BTM_BLE_APPEARANCE_GENERIC_TAG: case BTM_BLE_APPEARANCE_GENERIC_KEYRING: diff --git a/components/bt/bluedroid/stack/include/stack/btm_ble_api.h b/components/bt/bluedroid/stack/include/stack/btm_ble_api.h index 796f8bbe20..0e93959afc 100644 --- a/components/bt/bluedroid/stack/include/stack/btm_ble_api.h +++ b/components/bt/bluedroid/stack/include/stack/btm_ble_api.h @@ -206,7 +206,7 @@ typedef UINT8 BLE_SIGNATURE[BTM_BLE_AUTH_SIGN_LEN]; /* Device address */ #endif /* Appearance Values Reported with BTM_BLE_AD_TYPE_APPEARANCE */ -#define BTM_BLE_APPEARANCE_UKNOWN 0x0000 +#define BTM_BLE_APPEARANCE_UNKNOWN 0x0000 #define BTM_BLE_APPEARANCE_GENERIC_PHONE 0x0040 #define BTM_BLE_APPEARANCE_GENERIC_COMPUTER 0x0080 #define BTM_BLE_APPEARANCE_GENERIC_WATCH 0x00C0 @@ -250,6 +250,15 @@ typedef UINT8 BLE_SIGNATURE[BTM_BLE_AUTH_SIGN_LEN]; /* Device address */ #define BTM_BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP 0x0C41 #define BTM_BLE_APPEARANCE_PULSE_OXIMETER_WRIST 0x0C42 #define BTM_BLE_APPEARANCE_GENERIC_WEIGHT 0x0C80 +#define BTM_BLE_APPEARANCE_GENERIC_PERSONAL_MOBILITY_DEVICE 0x0CC0 +#define BTM_BLE_APPEARANCE_POWERED_WHEELCHAIR 0x0CC1 +#define BTM_BLE_APPEARANCE_MOBILITY_SCOOTER 0x0CC2 +#define BTM_BLE_APPEARANCE_GENERIC_CONTINUOUS_GLUCOSE_MONITOR 0x0D00 +#define BTM_BLE_APPEARANCE_GENERIC_INSULIN_PUMP 0x0D40 +#define BTM_BLE_APPEARANCE_INSULIN_PUMP_DURABLE_PUMP 0x0D41 +#define BTM_BLE_APPEARANCE_INSULIN_PUMP_PATCH_PUMP 0x0D44 +#define BTM_BLE_APPEARANCE_INSULIN_PEN 0x0D48 +#define BTM_BLE_APPEARANCE_GENERIC_MEDICATION_DELIVERY 0x0D80 #define BTM_BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS 0x1440 #define BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION 0x1441 #define BTM_BLE_APPEARANCE_OUTDOOR_SPORTS_LOCATION_AND_NAV 0x1442 From 5549ea3439b54d18f22fa292005e957415b1d8a1 Mon Sep 17 00:00:00 2001 From: zhiweijian Date: Sat, 28 Apr 2018 16:22:38 +0800 Subject: [PATCH 025/187] Component/bt: fix version exchange issue - Android 7.0 version issue - version exchange late in some phones - can not get version in smp --- components/bt/bluedroid/stack/btm/btm_acl.c | 17 +++++++++++------ components/bt/bluedroid/stack/smp/smp_act.c | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/components/bt/bluedroid/stack/btm/btm_acl.c b/components/bt/bluedroid/stack/btm/btm_acl.c index 8e786abb69..84fa0d6b71 100644 --- a/components/bt/bluedroid/stack/btm/btm_acl.c +++ b/components/bt/bluedroid/stack/btm/btm_acl.c @@ -335,7 +335,7 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn, btsnd_hcic_ble_read_remote_feat(p->hci_handle); } else if (HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED(controller_get_interface()->get_features_ble()->as_array) && link_role == HCI_ROLE_SLAVE) { - btsnd_hcic_ble_read_remote_feat(p->hci_handle); + btsnd_hcic_rmt_ver_req (p->hci_handle); } else { btm_establish_continue(p); } @@ -906,12 +906,17 @@ void btm_read_remote_version_complete (UINT8 *p) } #if BLE_INCLUDED == TRUE if (p_acl_cb->transport == BT_TRANSPORT_LE) { - if (HCI_LE_DATA_LEN_EXT_SUPPORTED(p_acl_cb->peer_le_features)) { - uint16_t data_length = controller_get_interface()->get_ble_default_data_packet_length(); - uint16_t data_txtime = controller_get_interface()->get_ble_default_data_packet_txtime(); - btsnd_hcic_ble_set_data_length(p_acl_cb->hci_handle, data_length, data_txtime); + if(p_acl_cb->link_role == HCI_ROLE_MASTER) { + if (HCI_LE_DATA_LEN_EXT_SUPPORTED(p_acl_cb->peer_le_features)) { + uint16_t data_length = controller_get_interface()->get_ble_default_data_packet_length(); + uint16_t data_txtime = controller_get_interface()->get_ble_default_data_packet_txtime(); + btsnd_hcic_ble_set_data_length(p_acl_cb->hci_handle, data_length, data_txtime); + } + l2cble_notify_le_connection (p_acl_cb->remote_addr); + } else { + //slave role, read remote feature + btsnd_hcic_ble_read_remote_feat(p_acl_cb->hci_handle); } - l2cble_notify_le_connection (p_acl_cb->remote_addr); } #endif break; diff --git a/components/bt/bluedroid/stack/smp/smp_act.c b/components/bt/bluedroid/stack/smp/smp_act.c index 65370e6776..0b5d50be2e 100644 --- a/components/bt/bluedroid/stack/smp/smp_act.c +++ b/components/bt/bluedroid/stack/smp/smp_act.c @@ -58,7 +58,7 @@ static bool lmp_version_below(BD_ADDR bda, uint8_t version) SMP_TRACE_WARNING("%s cannot retrieve LMP version...", __func__); return false; } - SMP_TRACE_WARNING("%s LMP version %d < %d", __func__, acl->lmp_version, version); + SMP_TRACE_DEBUG("%s LMP version %d < %d", __func__, acl->lmp_version, version); return acl->lmp_version < version; } From be707f1c6b0a196489c98508f203abe6a0ca21e2 Mon Sep 17 00:00:00 2001 From: Wayne Keenan Date: Mon, 30 Apr 2018 08:03:35 +0100 Subject: [PATCH 026/187] Fix potential NULL pointer dereference crash. --- examples/protocols/mdns/main/mdns_example_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c index 44984c2682..fb805545ab 100755 --- a/examples/protocols/mdns/main/mdns_example_main.c +++ b/examples/protocols/mdns/main/mdns_example_main.c @@ -137,7 +137,7 @@ static void mdns_print_results(mdns_result_t * results){ if(r->txt_count){ printf(" TXT : [%u] ", r->txt_count); for(t=0; ttxt_count; t++){ - printf("%s=%s; ", r->txt[t].key, r->txt[t].value); + printf("%s=%s; ", r->txt[t].key, r->txt[t].value?r->txt[t].value:"NULL"); } printf("\n"); } From 9356d6af3f34f1aaf9e96a2f5e2fdebb1771b982 Mon Sep 17 00:00:00 2001 From: Anuj Deshpande Date: Fri, 27 Apr 2018 15:25:07 +0530 Subject: [PATCH 027/187] cJSON : Include only source file objects - test.c can cause issues if there is another main function - Closes https://github.com/espressif/esp-idf/issues/1883 --- components/json/component.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/components/json/component.mk b/components/json/component.mk index a6a424e6db..7fbd5db1e2 100644 --- a/components/json/component.mk +++ b/components/json/component.mk @@ -4,3 +4,4 @@ COMPONENT_ADD_INCLUDEDIRS := cJSON COMPONENT_SRCDIRS := cJSON COMPONENT_SUBMODULES := cJSON +COMPONENT_OBJS := cJSON/cJSON.o cJSON/cJSON_Utils.o From b3894dba97123aea30a64f20c669f70526083dde Mon Sep 17 00:00:00 2001 From: Anuj Deshpande Date: Mon, 30 Apr 2018 14:21:03 +0530 Subject: [PATCH 028/187] console: Free alloc'd memory after error conditions Closes https://github.com/espressif/esp-idf/issues/1901 --- components/console/commands.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/console/commands.c b/components/console/commands.c index c52c7061da..32fb86f0fe 100644 --- a/components/console/commands.c +++ b/components/console/commands.c @@ -91,9 +91,11 @@ esp_err_t esp_console_cmd_register(const esp_console_cmd_t *cmd) return ESP_ERR_NO_MEM; } if (cmd->command == NULL) { + free(item); return ESP_ERR_INVALID_ARG; } if (strchr(cmd->command, ' ') != NULL) { + free(item); return ESP_ERR_INVALID_ARG; } item->command = cmd->command; @@ -186,10 +188,12 @@ esp_err_t esp_console_run(const char* cmdline, int* cmd_ret) size_t argc = esp_console_split_argv(s_tmp_line_buf, argv, s_config.max_cmdline_args); if (argc == 0) { + free(argv); return ESP_ERR_INVALID_ARG; } const cmd_item_t* cmd = find_command_by_name(argv[0]); if (cmd == NULL) { + free(argv); return ESP_ERR_NOT_FOUND; } *cmd_ret = (*cmd->func)(argc, argv); From 87adbd322969977a50d70f9ea958ebd70c36212b Mon Sep 17 00:00:00 2001 From: Anuj Deshpande Date: Mon, 30 Apr 2018 14:22:45 +0530 Subject: [PATCH 029/187] console: Fix formatting --- components/console/commands.c | 64 +++++++++++++++++------------------ 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/components/console/commands.c b/components/console/commands.c index 32fb86f0fe..b1f6bda96e 100644 --- a/components/console/commands.c +++ b/components/console/commands.c @@ -28,18 +28,18 @@ typedef struct cmd_item_ { /** * Command name (statically allocated by application) */ - const char* command; + const char *command; /** * Help text (statically allocated by application), may be NULL. */ - const char* help; + const char *help; /** * Hint text, usually lists possible arguments, dynamically allocated. * May be NULL. */ - char* hint; + char *hint; esp_console_cmd_func_t func; //!< pointer to the command handler - void* argtable; //!< optional pointer to arg table + void *argtable; //!< optional pointer to arg table SLIST_ENTRY(cmd_item_) next; //!< next command in the list } cmd_item_t; @@ -50,11 +50,11 @@ static SLIST_HEAD(cmd_list_, cmd_item_) s_cmd_list; static esp_console_config_t s_config; /** temporary buffer used for command line parsing */ -static char* s_tmp_line_buf; +static char *s_tmp_line_buf; -static const cmd_item_t* find_command_by_name(const char* name); +static const cmd_item_t *find_command_by_name(const char *name); -esp_err_t esp_console_init(const esp_console_config_t* config) +esp_err_t esp_console_init(const esp_console_config_t *config) { if (s_tmp_line_buf) { return ESP_ERR_INVALID_STATE; @@ -91,11 +91,11 @@ esp_err_t esp_console_cmd_register(const esp_console_cmd_t *cmd) return ESP_ERR_NO_MEM; } if (cmd->command == NULL) { - free(item); + free(item); return ESP_ERR_INVALID_ARG; } if (strchr(cmd->command, ' ') != NULL) { - free(item); + free(item); return ESP_ERR_INVALID_ARG; } item->command = cmd->command; @@ -107,9 +107,9 @@ esp_err_t esp_console_cmd_register(const esp_console_cmd_t *cmd) asprintf(&item->hint, " %s", cmd->hint); } else if (cmd->argtable) { /* Generate hint based on cmd->argtable */ - char* buf = NULL; + char *buf = NULL; size_t buf_size = 0; - FILE* f = open_memstream(&buf, &buf_size); + FILE *f = open_memstream(&buf, &buf_size); if (f != NULL) { arg_print_syntax(f, cmd->argtable, NULL); fclose(f); @@ -118,11 +118,11 @@ esp_err_t esp_console_cmd_register(const esp_console_cmd_t *cmd) } item->argtable = cmd->argtable; item->func = cmd->func; - cmd_item_t* last = SLIST_FIRST(&s_cmd_list); + cmd_item_t *last = SLIST_FIRST(&s_cmd_list); if (last == NULL) { SLIST_INSERT_HEAD(&s_cmd_list, item, next); } else { - cmd_item_t* it; + cmd_item_t *it; while ((it = SLIST_NEXT(last, next)) != NULL) { last = it; } @@ -137,7 +137,7 @@ void esp_console_get_completion(const char *buf, linenoiseCompletions *lc) if (len == 0) { return; } - cmd_item_t* it; + cmd_item_t *it; SLIST_FOREACH(it, &s_cmd_list, next) { /* Check if command starts with buf */ if (strncmp(buf, it->command, len) == 0) { @@ -146,10 +146,10 @@ void esp_console_get_completion(const char *buf, linenoiseCompletions *lc) } } -const char* esp_console_get_hint(const char *buf, int *color, int *bold) +const char *esp_console_get_hint(const char *buf, int *color, int *bold) { int len = strlen(buf); - cmd_item_t* it; + cmd_item_t *it; SLIST_FOREACH(it, &s_cmd_list, next) { if (strlen(it->command) == len && strncmp(buf, it->command, len) == 0) { @@ -161,10 +161,10 @@ const char* esp_console_get_hint(const char *buf, int *color, int *bold) return NULL; } -static const cmd_item_t* find_command_by_name(const char* name) +static const cmd_item_t *find_command_by_name(const char *name) { - const cmd_item_t* cmd = NULL; - cmd_item_t* it; + const cmd_item_t *cmd = NULL; + cmd_item_t *it; SLIST_FOREACH(it, &s_cmd_list, next) { if (strcmp(name, it->command) == 0) { cmd = it; @@ -174,26 +174,26 @@ static const cmd_item_t* find_command_by_name(const char* name) return cmd; } -esp_err_t esp_console_run(const char* cmdline, int* cmd_ret) +esp_err_t esp_console_run(const char *cmdline, int *cmd_ret) { if (s_tmp_line_buf == NULL) { return ESP_ERR_INVALID_STATE; } - char** argv = (char**) calloc(s_config.max_cmdline_args, sizeof(char*)); + char **argv = (char **) calloc(s_config.max_cmdline_args, sizeof(char *)); if (argv == NULL) { return ESP_ERR_NO_MEM; } strlcpy(s_tmp_line_buf, cmdline, s_config.max_cmdline_length); size_t argc = esp_console_split_argv(s_tmp_line_buf, argv, - s_config.max_cmdline_args); + s_config.max_cmdline_args); if (argc == 0) { - free(argv); + free(argv); return ESP_ERR_INVALID_ARG; } - const cmd_item_t* cmd = find_command_by_name(argv[0]); + const cmd_item_t *cmd = find_command_by_name(argv[0]); if (cmd == NULL) { - free(argv); + free(argv); return ESP_ERR_NOT_FOUND; } *cmd_ret = (*cmd->func)(argc, argv); @@ -201,9 +201,9 @@ esp_err_t esp_console_run(const char* cmdline, int* cmd_ret) return ESP_OK; } -static int help_command(int argc, char** argv) +static int help_command(int argc, char **argv) { - cmd_item_t* it; + cmd_item_t *it; /* Print summary of each command */ SLIST_FOREACH(it, &s_cmd_list, next) { @@ -213,7 +213,7 @@ static int help_command(int argc, char** argv) /* First line: command name and hint * Pad all the hints to the same column */ - const char* hint = (it->hint) ? it->hint : ""; + const char *hint = (it->hint) ? it->hint : ""; printf("%-s %s\n", it->command, hint); /* Second line: print help. * Argtable has a nice helper function for this which does line @@ -223,7 +223,7 @@ static int help_command(int argc, char** argv) arg_print_formatted(stdout, 2, 78, it->help); /* Finally, print the list of arguments */ if (it->argtable) { - arg_print_glossary(stdout, (void**) it->argtable, " %12s %s\n"); + arg_print_glossary(stdout, (void **) it->argtable, " %12s %s\n"); } printf("\n"); } @@ -234,9 +234,9 @@ static int help_command(int argc, char** argv) esp_err_t esp_console_register_help_command() { esp_console_cmd_t command = { - .command = "help", - .help = "Print the list of registered commands", - .func = &help_command + .command = "help", + .help = "Print the list of registered commands", + .func = &help_command }; return esp_console_cmd_register(&command); } From c23915939d79bca226f5e3e97c9d08710610ee17 Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Thu, 22 Feb 2018 20:52:01 +0800 Subject: [PATCH 030/187] esp32: mark WiFi auto connect API as obsolete Mark esp_wifi_set/get_auto_connect as obsolete --- components/esp32/include/esp_wifi.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h index b34aec7a22..0b24b71cb2 100755 --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -757,7 +757,7 @@ esp_err_t esp_wifi_set_storage(wifi_storage_t storage); * - ESP_ERR_WIFI_MODE: WiFi internal error, the station/soft-AP control block is invalid * - others: refer to error code in esp_err.h */ -esp_err_t esp_wifi_set_auto_connect(bool en); +esp_err_t esp_wifi_set_auto_connect(bool en) __attribute__ ((deprecated)); /** * @brief Get the auto connect flag @@ -769,7 +769,7 @@ esp_err_t esp_wifi_set_auto_connect(bool en); * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init * - ESP_ERR_INVALID_ARG: invalid argument */ -esp_err_t esp_wifi_get_auto_connect(bool *en); +esp_err_t esp_wifi_get_auto_connect(bool *en) __attribute__ ((deprecated)); /** * @brief Set 802.11 Vendor-Specific Information Element From b9126e69bcceec922374626cb5bb5b12917cb053 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 2 May 2018 15:11:21 +1000 Subject: [PATCH 031/187] wifi: Set default wifi library log level based on sdkconfig Has to be set at runtime, due to precompiled wifi libraries. Prompted by discussion on forum: https://esp32.com/viewtopic.php?f=2&t=5570&p=24216#p24216 --- components/esp32/wifi_init.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/components/esp32/wifi_init.c b/components/esp32/wifi_init.c index be0ba781cf..bd4437a5b4 100644 --- a/components/esp32/wifi_init.c +++ b/components/esp32/wifi_init.c @@ -27,6 +27,15 @@ mesh_event_cb_t g_mesh_event_cb = NULL; static esp_pm_lock_handle_t s_wifi_modem_sleep_lock; #endif +static void __attribute__((constructor)) s_set_default_wifi_log_level() +{ + /* WiFi libraries aren't compiled to know CONFIG_LOG_DEFAULT_LEVEL, + so set it at runtime startup. Done here not in esp_wifi_init() to allow + the user to set the level again before esp_wifi_init() is called. + */ + esp_log_level_set("wifi", CONFIG_LOG_DEFAULT_LEVEL); +} + esp_err_t esp_wifi_init(const wifi_init_config_t *config) { #ifdef CONFIG_PM_ENABLE From 7ae1df1c5e0a21687d494f9a1389d1282631544d Mon Sep 17 00:00:00 2001 From: Sagar Bijwe Date: Fri, 27 Apr 2018 12:40:29 +0530 Subject: [PATCH 032/187] nvs: Fix recovery from power-off while page is being freed Currently when page is being freed, items are individually moved from FREEING page to ACTIVE page and erased. If power-off happens during the process, the remaining entries are moved to ACTIVE page during recovery. The problem with this approach is there may not be enough space on ACTIVE page for all items if an item was partially written before power-off and erased during recovery. This change moves all the items from FREEING to ACTIVE page and then erased the FREEING page, If power-off happens during the process, then ACTIVE page is erased and the process is restarted. --- components/nvs_flash/src/nvs_page.cpp | 44 ++++++++++++------- components/nvs_flash/src/nvs_page.hpp | 2 +- components/nvs_flash/src/nvs_pagemanager.cpp | 43 +++++++++--------- .../nvs_flash/test_nvs_host/test_nvs.cpp | 42 ++++++++++++++++++ 4 files changed, 93 insertions(+), 38 deletions(-) diff --git a/components/nvs_flash/src/nvs_page.cpp b/components/nvs_flash/src/nvs_page.cpp index 54d6db7bd3..9fc1a6edad 100644 --- a/components/nvs_flash/src/nvs_page.cpp +++ b/components/nvs_flash/src/nvs_page.cpp @@ -382,7 +382,7 @@ void Page::updateFirstUsedEntry(size_t index, size_t span) } } -esp_err_t Page::moveItem(Page& other) +esp_err_t Page::copyItems(Page& other) { if (mFirstUsedEntry == INVALID_ENTRY) { return ESP_ERR_NVS_NOT_FOUND; @@ -396,29 +396,41 @@ esp_err_t Page::moveItem(Page& other) } Item entry; - auto err = readEntry(mFirstUsedEntry, entry); - if (err != ESP_OK) { - return err; - } - other.mHashList.insert(entry, other.mNextFreeEntry); - err = other.writeEntry(entry); - if (err != ESP_OK) { - return err; - } + size_t readEntryIndex = mFirstUsedEntry; - size_t span = entry.span; - size_t end = mFirstUsedEntry + span; + while (readEntryIndex < ENTRY_COUNT) { - assert(mFirstUsedEntry != INVALID_ENTRY || span == 1); + if (mEntryTable.get(readEntryIndex) != EntryState::WRITTEN) { + assert(readEntryIndex != mFirstUsedEntry); + readEntryIndex++; + continue; + } + auto err = readEntry(readEntryIndex, entry); + if (err != ESP_OK) { + return err; + } - for (size_t i = mFirstUsedEntry + 1; i < end; ++i) { - readEntry(i, entry); + other.mHashList.insert(entry, other.mNextFreeEntry); err = other.writeEntry(entry); if (err != ESP_OK) { return err; } + size_t span = entry.span; + size_t end = readEntryIndex + span; + + assert(end <= ENTRY_COUNT); + + for (size_t i = readEntryIndex + 1; i < end; ++i) { + readEntry(i, entry); + err = other.writeEntry(entry); + if (err != ESP_OK) { + return err; + } + } + readEntryIndex = end; + } - return eraseEntryAndSpan(mFirstUsedEntry); + return ESP_OK; } esp_err_t Page::mLoadEntryTable() diff --git a/components/nvs_flash/src/nvs_page.hpp b/components/nvs_flash/src/nvs_page.hpp index 7aa8b9fd83..9baa76dbf1 100644 --- a/components/nvs_flash/src/nvs_page.hpp +++ b/components/nvs_flash/src/nvs_page.hpp @@ -127,7 +127,7 @@ public: esp_err_t markFreeing(); - esp_err_t moveItem(Page& other); + esp_err_t copyItems(Page& other); esp_err_t erase(); diff --git a/components/nvs_flash/src/nvs_pagemanager.cpp b/components/nvs_flash/src/nvs_pagemanager.cpp index c7401717f1..3f3c5f01cd 100644 --- a/components/nvs_flash/src/nvs_pagemanager.cpp +++ b/components/nvs_flash/src/nvs_pagemanager.cpp @@ -67,7 +67,9 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount) if (lastItemIndex != SIZE_MAX) { auto last = PageManager::TPageListIterator(&lastPage); for (auto it = begin(); it != last; ++it) { - if (it->eraseItem(item.nsIndex, item.datatype, item.key) == ESP_OK) { + + if ((it->state() != Page::PageState::FREEING) && + (it->eraseItem(item.nsIndex, item.datatype, item.key) == ESP_OK)) { break; } } @@ -77,23 +79,26 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount) for (auto it = begin(); it!= end(); ++it) { if (it->state() == Page::PageState::FREEING) { Page* newPage = &mPageList.back(); - if (newPage->state() != Page::PageState::ACTIVE) { - auto err = activatePage(); + if (newPage->state() == Page::PageState::ACTIVE) { + auto err = newPage->erase(); if (err != ESP_OK) { return err; } - newPage = &mPageList.back(); + mPageList.erase(newPage); + mFreePageList.push_back(newPage); } - while (true) { - auto err = it->moveItem(*newPage); - if (err == ESP_ERR_NVS_NOT_FOUND) { - break; - } else if (err != ESP_OK) { - return err; - } + auto err = activatePage(); + if (err != ESP_OK) { + return err; + } + newPage = &mPageList.back(); + + err = it->copyItems(*newPage); + if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) { + return err; } - auto err = it->erase(); + err = it->erase(); if (err != ESP_OK) { return err; } @@ -109,7 +114,7 @@ esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount) if (mFreePageList.size() == 0) { return ESP_ERR_NVS_NO_FREE_PAGES; } - + return ESP_OK; } @@ -156,13 +161,9 @@ esp_err_t PageManager::requestNewPage() if (err != ESP_OK) { return err; } - while (true) { - err = erasedPage->moveItem(*newPage); - if (err == ESP_ERR_NVS_NOT_FOUND) { - break; - } else if (err != ESP_OK) { - return err; - } + err = erasedPage->copyItems(*newPage); + if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) { + return err; } err = erasedPage->erase(); @@ -173,7 +174,7 @@ esp_err_t PageManager::requestNewPage() #ifndef NDEBUG assert(usedEntries == newPage->getUsedEntryCount()); #endif - + mPageList.erase(maxUnusedItemsPageIt); mFreePageList.push_back(erasedPage); diff --git a/components/nvs_flash/test_nvs_host/test_nvs.cpp b/components/nvs_flash/test_nvs_host/test_nvs.cpp index dd013e24ac..6a06658ff1 100644 --- a/components/nvs_flash/test_nvs_host/test_nvs.cpp +++ b/components/nvs_flash/test_nvs_host/test_nvs.cpp @@ -1456,6 +1456,48 @@ TEST_CASE("Recovery from power-off when the entry being erased is not on active nvs_close(handle); } +TEST_CASE("Recovery from power-off when page is being freed.", "[nvs]") +{ + const size_t blob_size = (Page::ENTRY_COUNT-3) * Page::ENTRY_SIZE; + size_t read_size = blob_size/2; + uint8_t blob[blob_size] = {0}; + SpiFlashEmulator emu(3); + TEST_ESP_OK(nvs_flash_init_custom(NVS_DEFAULT_PART_NAME, 0, 3)); + nvs_handle handle; + TEST_ESP_OK(nvs_open("test", NVS_READWRITE, &handle)); + // Fill first page + TEST_ESP_OK(nvs_set_blob(handle, "1a", blob, blob_size/3)); + TEST_ESP_OK(nvs_set_blob(handle, "1b", blob, blob_size/3)); + TEST_ESP_OK(nvs_set_blob(handle, "1c", blob, blob_size/4)); + // Fill second page + TEST_ESP_OK(nvs_set_blob(handle, "2a", blob, blob_size/2)); + TEST_ESP_OK(nvs_set_blob(handle, "2b", blob, blob_size/2)); + + TEST_ESP_OK(nvs_erase_key(handle, "1c")); + + emu.clearStats(); + emu.failAfter(6 * Page::ENTRY_COUNT); + TEST_ESP_ERR(nvs_set_blob(handle, "1d", blob, blob_size/4), ESP_ERR_FLASH_OP_FAIL); + + TEST_ESP_OK(nvs_flash_init_custom(NVS_DEFAULT_PART_NAME, 0, 3)); + + read_size = blob_size/3; + TEST_ESP_OK( nvs_get_blob(handle, "1a", blob, &read_size)); + TEST_ESP_OK( nvs_get_blob(handle, "1b", blob, &read_size)); + + read_size = blob_size /4; + TEST_ESP_ERR( nvs_get_blob(handle, "1c", blob, &read_size), ESP_ERR_NVS_NOT_FOUND); + TEST_ESP_ERR( nvs_get_blob(handle, "1d", blob, &read_size), ESP_ERR_NVS_NOT_FOUND); + + read_size = blob_size /2; + TEST_ESP_OK( nvs_get_blob(handle, "2a", blob, &read_size)); + TEST_ESP_OK( nvs_get_blob(handle, "2b", blob, &read_size)); + + TEST_ESP_OK(nvs_commit(handle)); + nvs_close(handle); +} + + /* Add new tests above */ /* This test has to be the final one */ From b4ca03c48b757206e20ad37bd0e42ca3fbbdc6ea Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Thu, 8 Feb 2018 15:25:34 +0800 Subject: [PATCH 033/187] example: set default SPI flash mode to 40Mhz for iperf example Set default SPI flash frequency to 40Mhz for iperf example to avoid random crash for ESP32-WROVER-KIT (v3). --- examples/wifi/iperf/README.md | 6 ++++++ examples/wifi/iperf/sdkconfig.defaults | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/wifi/iperf/README.md b/examples/wifi/iperf/README.md index c5fd968fce..18f94f9a6e 100644 --- a/examples/wifi/iperf/README.md +++ b/examples/wifi/iperf/README.md @@ -1,5 +1,11 @@ # Iperf Example +## Note about 80Mhz flash frequency +The iperf can get better throughput if the SPI flash frequency is set to 80Mhz, but the system may crash in 80Mhz mode for ESP-WROVER-KIT V3. +Removing R140~R145 from the board can fix this issue. Currently the default SPI frequency is set to 40Mhz, if you want to change the SPI flash +frequency to 80Mhz, please make sure R140~R145 are removed from ESP-WROVER-KIT V3 or use ESP32 DevKitC. + +## Introduction This example implements the protocol used by the common performance measurement tool [iPerf](https://iperf.fr/). Performance can be measured between two ESP32s running this example, or between a single ESP32 and a computer running the iPerf tool diff --git a/examples/wifi/iperf/sdkconfig.defaults b/examples/wifi/iperf/sdkconfig.defaults index 52b0cbaef6..9c03a72861 100644 --- a/examples/wifi/iperf/sdkconfig.defaults +++ b/examples/wifi/iperf/sdkconfig.defaults @@ -24,6 +24,6 @@ CONFIG_TCPIP_RECVMBOX_SIZE=64 CONFIG_LWIP_ETHARP_TRUST_IP_MAC= CONFIG_FLASHMODE_QIO=y -CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_ESPTOOLPY_FLASHFREQ_40M=y CONFIG_LWIP_IRAM_OPTIMIZATION=y From dd911525891a1a42dff75091f25d297ef8fe3ce7 Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Wed, 18 Apr 2018 14:36:26 +0800 Subject: [PATCH 034/187] example(spi_master): add descriptions about LCD example --- .../spi_master/main/spi_master_example_main.c | 73 +++++++++++++++---- 1 file changed, 60 insertions(+), 13 deletions(-) diff --git a/examples/peripherals/spi_master/main/spi_master_example_main.c b/examples/peripherals/spi_master/main/spi_master_example_main.c index 77bfe5fa97..8b55fe268a 100644 --- a/examples/peripherals/spi_master/main/spi_master_example_main.c +++ b/examples/peripherals/spi_master/main/spi_master_example_main.c @@ -20,7 +20,7 @@ /* This code displays some fancy graphics on the 320x240 LCD on an ESP-WROVER_KIT board. - This example demonstrates the use of both spi_device_transmit as well as + This example demonstrates the use of both spi_device_transmit as well as spi_device_queue_trans/spi_device_get_trans_result and pre-transmit callbacks. Some info about the ILI9341/ST7789V: It has an C/D line, which is connected to a GPIO here. It expects this @@ -38,7 +38,7 @@ #define PIN_NUM_RST 18 #define PIN_NUM_BCKL 5 -//To speed up transfers, every SPI transfer sends a bunch of lines. This define specifies how many. More means more memory use, +//To speed up transfers, every SPI transfer sends a bunch of lines. This define specifies how many. More means more memory use, //but less overhead for setting up / finishing transfers. Make sure 240 is dividable by this. #define PARALLEL_LINES 16 @@ -59,54 +59,101 @@ typedef enum { //Place data into DRAM. Constant data gets placed into DROM by default, which is not accessible by DMA. DRAM_ATTR static const lcd_init_cmd_t st_init_cmds[]={ + /* Memory Data Access Control, MX=MV=1, MY=ML=MH=0, RGB=0 */ {0x36, {(1<<5)|(1<<6)}, 1}, + /* Interface Pixel Format, 16bits/pixel for RGB/MCU interface */ {0x3A, {0x55}, 1}, + /* Porch Setting */ {0xB2, {0x0c, 0x0c, 0x00, 0x33, 0x33}, 5}, + /* Gate Control, Vgh=13.65V, Vgl=-10.43V */ {0xB7, {0x45}, 1}, + /* VCOM Setting, VCOM=1.175V */ {0xBB, {0x2B}, 1}, + /* LCM Control, XOR: BGR, MX, MH */ {0xC0, {0x2C}, 1}, + /* VDV and VRH Command Enable, enable=1 */ {0xC2, {0x01, 0xff}, 2}, + /* VRH Set, Vap=4.4+... */ {0xC3, {0x11}, 1}, + /* VDV Set, VDV=0 */ {0xC4, {0x20}, 1}, + /* Frame Rate Control, 60Hz, inversion=0 */ {0xC6, {0x0f}, 1}, + /* Power Control 1, AVDD=6.8V, AVCL=-4.8V, VDDS=2.3V */ {0xD0, {0xA4, 0xA1}, 1}, + /* Positive Voltage Gamma Control */ {0xE0, {0xD0, 0x00, 0x05, 0x0E, 0x15, 0x0D, 0x37, 0x43, 0x47, 0x09, 0x15, 0x12, 0x16, 0x19}, 14}, + /* Negative Voltage Gamma Control */ {0xE1, {0xD0, 0x00, 0x05, 0x0D, 0x0C, 0x06, 0x2D, 0x44, 0x40, 0x0E, 0x1C, 0x18, 0x16, 0x19}, 14}, + /* Sleep Out */ {0x11, {0}, 0x80}, + /* Display On */ {0x29, {0}, 0x80}, {0, {0}, 0xff} }; DRAM_ATTR static const lcd_init_cmd_t ili_init_cmds[]={ + /* Power contorl B, power control = 0, DC_ENA = 1 */ {0xCF, {0x00, 0x83, 0X30}, 3}, + /* Power on sequence control, + * cp1 keeps 1 frame, 1st frame enable + * vcl = 0, ddvdh=3, vgh=1, vgl=2 + * DDVDH_ENH=1 + */ {0xED, {0x64, 0x03, 0X12, 0X81}, 4}, + /* Driver timing control A, + * non-overlap=default +1 + * EQ=default - 1, CR=default + * pre-charge=default - 1 + */ {0xE8, {0x85, 0x01, 0x79}, 3}, + /* Power control A, Vcore=1.6V, DDVDH=5.6V */ {0xCB, {0x39, 0x2C, 0x00, 0x34, 0x02}, 5}, + /* Pump ratio control, DDVDH=2xVCl */ {0xF7, {0x20}, 1}, + /* Driver timing control, all=0 unit */ {0xEA, {0x00, 0x00}, 2}, + /* Power control 1, GVDD=4.75V */ {0xC0, {0x26}, 1}, + /* Power control 2, DDVDH=VCl*2, VGH=VCl*7, VGL=-VCl*3 */ {0xC1, {0x11}, 1}, + /* VCOM control 1, VCOMH=4.025V, VCOML=-0.950V */ {0xC5, {0x35, 0x3E}, 2}, + /* VCOM control 2, VCOMH=VMH-2, VCOML=VML-2 */ {0xC7, {0xBE}, 1}, + /* Memory access contorl, MX=MY=0, MV=1, ML=0, BGR=1, MH=0 */ {0x36, {0x28}, 1}, + /* Pixel format, 16bits/pixel for RGB/MCU interface */ {0x3A, {0x55}, 1}, + /* Frame rate control, f=fosc, 70Hz fps */ {0xB1, {0x00, 0x1B}, 2}, + /* Enable 3G, disabled */ {0xF2, {0x08}, 1}, + /* Gamma set, curve 1 */ {0x26, {0x01}, 1}, + /* Positive gamma correction */ {0xE0, {0x1F, 0x1A, 0x18, 0x0A, 0x0F, 0x06, 0x45, 0X87, 0x32, 0x0A, 0x07, 0x02, 0x07, 0x05, 0x00}, 15}, + /* Negative gamma correction */ {0XE1, {0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3A, 0x78, 0x4D, 0x05, 0x18, 0x0D, 0x38, 0x3A, 0x1F}, 15}, + /* Column address set, SC=0, EC=0xEF */ {0x2A, {0x00, 0x00, 0x00, 0xEF}, 4}, - {0x2B, {0x00, 0x00, 0x01, 0x3f}, 4}, + /* Page address set, SP=0, EP=0x013F */ + {0x2B, {0x00, 0x00, 0x01, 0x3f}, 4}, + /* Memory write */ {0x2C, {0}, 0}, + /* Entry mode set, Low vol detect disabled, normal display */ {0xB7, {0x07}, 1}, + /* Display function control */ {0xB6, {0x0A, 0x82, 0x27, 0x00}, 4}, + /* Sleep out */ {0x11, {0}, 0x80}, + /* Display on */ {0x29, {0}, 0x80}, {0, {0}, 0xff}, }; //Send a command to the LCD. Uses spi_device_transmit, which waits until the transfer is complete. -void lcd_cmd(spi_device_handle_t spi, const uint8_t cmd) +void lcd_cmd(spi_device_handle_t spi, const uint8_t cmd) { esp_err_t ret; spi_transaction_t t; @@ -119,7 +166,7 @@ void lcd_cmd(spi_device_handle_t spi, const uint8_t cmd) } //Send data to the LCD. Uses spi_device_transmit, which waits until the transfer is complete. -void lcd_data(spi_device_handle_t spi, const uint8_t *data, int len) +void lcd_data(spi_device_handle_t spi, const uint8_t *data, int len) { esp_err_t ret; spi_transaction_t t; @@ -134,13 +181,13 @@ void lcd_data(spi_device_handle_t spi, const uint8_t *data, int len) //This function is called (in irq context!) just before a transmission starts. It will //set the D/C line to the value indicated in the user field. -void lcd_spi_pre_transfer_callback(spi_transaction_t *t) +void lcd_spi_pre_transfer_callback(spi_transaction_t *t) { int dc=(int)t->user; gpio_set_level(PIN_NUM_DC, dc); } -uint32_t lcd_get_id(spi_device_handle_t spi) +uint32_t lcd_get_id(spi_device_handle_t spi) { //get_id cmd lcd_cmd( spi, 0x04); @@ -158,7 +205,7 @@ uint32_t lcd_get_id(spi_device_handle_t spi) } //Initialize the display -void lcd_init(spi_device_handle_t spi) +void lcd_init(spi_device_handle_t spi) { int cmd=0; const lcd_init_cmd_t* lcd_init_cmds; @@ -226,7 +273,7 @@ void lcd_init(spi_device_handle_t spi) //before sending the line data itself; a total of 6 transactions. (We can't put all of this in just one transaction //because the D/C line needs to be toggled in the middle.) //This routine queues these commands up so they get sent as quickly as possible. -static void send_lines(spi_device_handle_t spi, int ypos, uint16_t *linedata) +static void send_lines(spi_device_handle_t spi, int ypos, uint16_t *linedata) { esp_err_t ret; int x; @@ -277,7 +324,7 @@ static void send_lines(spi_device_handle_t spi, int ypos, uint16_t *linedata) } -static void send_line_finish(spi_device_handle_t spi) +static void send_line_finish(spi_device_handle_t spi) { spi_transaction_t *rtrans; esp_err_t ret; @@ -291,9 +338,9 @@ static void send_line_finish(spi_device_handle_t spi) //Simple routine to generate some patterns and send them to the LCD. Don't expect anything too -//impressive. Because the SPI driver handles transactions in the background, we can calculate the next line +//impressive. Because the SPI driver handles transactions in the background, we can calculate the next line //while the previous one is being sent. -static void display_pretty_colors(spi_device_handle_t spi) +static void display_pretty_colors(spi_device_handle_t spi) { uint16_t *lines[2]; //Allocate memory for the pixel buffers @@ -305,7 +352,7 @@ static void display_pretty_colors(spi_device_handle_t spi) //Indexes of the line currently being sent to the LCD and the line we're calculating. int sending_line=-1; int calc_line=0; - + while(1) { frame++; for (int y=0; y<240; y+=PARALLEL_LINES) { From 402dee17a150df94f3fd5f838b58a085795859ba Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Thu, 3 May 2018 15:48:14 +0800 Subject: [PATCH 035/187] esp32: fix potential PHY calibration bug 1. Add error log if failed to store calibration version/mac/data 2. Change the NVS calibration version/mac/data store sequence 3. Pass the init_data instead of NULL to esp_phy_rf_init() in esp_phy_load_cal_and_init() --- components/esp32/phy_init.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/components/esp32/phy_init.c b/components/esp32/phy_init.c index 6d0b1dd0dc..027e6733aa 100644 --- a/components/esp32/phy_init.c +++ b/components/esp32/phy_init.c @@ -483,19 +483,34 @@ static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle, const esp_phy_calibration_data_t* cal_data) { esp_err_t err; - uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16)); - ESP_LOGV(TAG, "phy_get_rf_cal_version: %d\n", cal_format_version); - err = nvs_set_u32(handle, PHY_CAL_VERSION_KEY, cal_format_version); + + err = nvs_set_blob(handle, PHY_CAL_DATA_KEY, cal_data, sizeof(*cal_data)); if (err != ESP_OK) { + ESP_LOGE(TAG, "%s: store calibration data failed(0x%x)\n", __func__, err); return err; } + uint8_t sta_mac[6]; esp_efuse_mac_get_default(sta_mac); err = nvs_set_blob(handle, PHY_CAL_MAC_KEY, sta_mac, sizeof(sta_mac)); if (err != ESP_OK) { + ESP_LOGE(TAG, "%s: store calibration mac failed(0x%x)\n", __func__, err); return err; } - err = nvs_set_blob(handle, PHY_CAL_DATA_KEY, cal_data, sizeof(*cal_data)); + + uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16)); + ESP_LOGV(TAG, "phy_get_rf_cal_version: %d\n", cal_format_version); + err = nvs_set_u32(handle, PHY_CAL_VERSION_KEY, cal_format_version); + if (err != ESP_OK) { + ESP_LOGE(TAG, "%s: store calibration version failed(0x%x)\n", __func__, err); + return err; + } + + err = nvs_commit(handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "%s: store calibration nvs commit failed(0x%x)\n", __func__, err); + } + return err; } @@ -533,7 +548,7 @@ void esp_phy_load_cal_and_init(phy_rf_module_t module) err = ESP_OK; } #else - esp_phy_rf_init(NULL, PHY_RF_CAL_FULL, cal_data, module); + esp_phy_rf_init(init_data, PHY_RF_CAL_FULL, cal_data, module); #endif esp_phy_release_init_data(init_data); From c22c070e073341ccb8921239c78107beb60c179f Mon Sep 17 00:00:00 2001 From: baohongde Date: Thu, 3 May 2018 19:05:57 +0800 Subject: [PATCH 036/187] component/bt: Add APIs of get and remove bond device 1. Add APIs of get and remove bond device 2. Add ESP_BT_GAP_AUTH_CMPL_EVT --- components/bt/bluedroid/api/esp_gap_ble_api.c | 10 +-- components/bt/bluedroid/api/esp_gap_bt_api.c | 51 +++++++++++++- .../api/include/api/esp_gap_ble_api.h | 2 +- .../api/include/api/esp_gap_bt_api.h | 51 +++++++++++++- components/bt/bluedroid/btc/core/btc_dm.c | 21 +++++- .../bt/bluedroid/btc/core/btc_storage.c | 68 +++++++++++++++++++ .../bluedroid/btc/include/btc/btc_storage.h | 24 +++++++ .../btc/profile/std/gap/btc_gap_bt.c | 18 ++++- .../btc/profile/std/include/btc_gap_bt.h | 6 ++ examples/bluetooth/a2dp_source/main/main.c | 10 +++ 10 files changed, 251 insertions(+), 10 deletions(-) diff --git a/components/bt/bluedroid/api/esp_gap_ble_api.c b/components/bt/bluedroid/api/esp_gap_ble_api.c index 1089d72361..8ece6ecff8 100644 --- a/components/bt/bluedroid/api/esp_gap_ble_api.c +++ b/components/bt/bluedroid/api/esp_gap_ble_api.c @@ -35,7 +35,7 @@ esp_err_t esp_ble_gap_config_adv_data(esp_ble_adv_data_t *adv_data) { btc_msg_t msg; btc_ble_gap_args_t arg; - + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); if (adv_data == NULL) { @@ -60,7 +60,7 @@ esp_err_t esp_ble_gap_set_scan_params(esp_ble_scan_params_t *scan_params) { btc_msg_t msg; btc_ble_gap_args_t arg; - + ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); if (scan_params == NULL) { @@ -353,7 +353,7 @@ esp_err_t esp_ble_gap_get_local_used_addr(esp_bd_addr_t local_used_addr, uint8_t if(esp_bluedroid_get_status() != (ESP_BLUEDROID_STATUS_ENABLED)) { LOG_ERROR("%s, bluedroid status error", __func__); return ESP_FAIL; - } + } if(!BTM_BleGetCurrentAddress(local_used_addr, addr_type)) { return ESP_FAIL; } @@ -542,7 +542,9 @@ esp_err_t esp_ble_remove_bond_device(esp_bd_addr_t bd_addr) int esp_ble_get_bond_device_num(void) { - ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_FAIL; + } return btc_storage_get_num_ble_bond_devices(); } diff --git a/components/bt/bluedroid/api/esp_gap_bt_api.c b/components/bt/bluedroid/api/esp_gap_bt_api.c index 8e357200b2..ebe3d5bfc0 100644 --- a/components/bt/bluedroid/api/esp_gap_bt_api.c +++ b/components/bt/bluedroid/api/esp_gap_bt_api.c @@ -19,6 +19,7 @@ #include "common/bt_trace.h" #include "btc/btc_manage.h" #include "btc_gap_bt.h" +#include "btc/btc_storage.h" #if (BTC_GAP_BT_INCLUDED == TRUE) @@ -178,11 +179,11 @@ esp_err_t esp_bt_gap_get_cod(esp_bt_cod_t *cod) return btc_gap_bt_get_cod(cod); } + esp_err_t esp_bt_gap_read_rssi_delta(esp_bd_addr_t remote_addr) { btc_msg_t msg; btc_gap_bt_args_t arg; - msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_GAP_BT; msg.act = BTC_GAP_BT_ACT_READ_RSSI_DELTA; @@ -191,4 +192,52 @@ esp_err_t esp_bt_gap_read_rssi_delta(esp_bd_addr_t remote_addr) return (btc_transfer_context(&msg, &arg, sizeof(btc_gap_bt_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +esp_err_t esp_bt_gap_remove_bond_device(esp_bd_addr_t bd_addr) +{ + btc_msg_t msg; + btc_gap_bt_args_t arg; + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BT; + msg.act = BTC_GAP_BT_ACT_REMOVE_BOND_DEVICE; + + memcpy(arg.rm_bond_device.bda.address, bd_addr, sizeof(esp_bd_addr_t)); + return (btc_transfer_context(&msg, &arg, sizeof(btc_gap_bt_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +int esp_bt_gap_get_bond_device_num(void) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_FAIL; + } + return btc_storage_get_num_bt_bond_devices(); +} + +esp_err_t esp_bt_gap_get_bond_device_list(int *dev_num, esp_bd_addr_t *dev_list) +{ + int ret; + int dev_num_total; + + if (dev_num == NULL || dev_list == NULL) { + return ESP_ERR_INVALID_ARG; + } + + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + dev_num_total = btc_storage_get_num_bt_bond_devices(); + if (*dev_num > dev_num_total) { + *dev_num = dev_num_total; + } + + ret = btc_storage_get_bonded_bt_devices_list((bt_bdaddr_t *)dev_list, *dev_num); + + return (ret == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + #endif /* #if BTC_GAP_BT_INCLUDED == TRUE */ diff --git a/components/bt/bluedroid/api/include/api/esp_gap_ble_api.h b/components/bt/bluedroid/api/include/api/esp_gap_ble_api.h index 5bf7e0b139..08feb13caf 100644 --- a/components/bt/bluedroid/api/include/api/esp_gap_ble_api.h +++ b/components/bt/bluedroid/api/include/api/esp_gap_ble_api.h @@ -1056,7 +1056,7 @@ esp_err_t esp_ble_remove_bond_device(esp_bd_addr_t bd_addr); * It will return the device bonded number immediately. * * @return - >= 0 : bonded devices number. -* - < 0 : failed +* - ESP_FAIL : failed * */ int esp_ble_get_bond_device_num(void); diff --git a/components/bt/bluedroid/api/include/api/esp_gap_bt_api.h b/components/bt/bluedroid/api/include/api/esp_gap_bt_api.h index 8631bac76a..d30767e72f 100644 --- a/components/bt/bluedroid/api/include/api/esp_gap_bt_api.h +++ b/components/bt/bluedroid/api/include/api/esp_gap_bt_api.h @@ -148,7 +148,8 @@ typedef enum { ESP_BT_GAP_DISC_STATE_CHANGED_EVT, /*!< discovery state changed event */ ESP_BT_GAP_RMT_SRVCS_EVT, /*!< get remote services event */ ESP_BT_GAP_RMT_SRVC_REC_EVT, /*!< get remote service record event */ - ESP_BT_GAP_READ_RSSI_DELTA_EVT, /*!< read rssi event */ + ESP_BT_GAP_AUTH_CMPL_EVT, /*!< AUTH complete event */ + ESP_BT_GAP_READ_RSSI_DELTA_EVT, /*!< read rssi event */ ESP_BT_GAP_EVT_MAX, } esp_bt_gap_cb_event_t; @@ -206,6 +207,15 @@ typedef union { esp_bt_status_t stat; /*!< read rssi status */ int8_t rssi_delta; /*!< rssi delta value range -128 ~127, The value zero indicates that the RSSI is inside the Golden Receive Power Range, the Golden Receive Power Range is from ESP_BT_GAP_RSSI_LOW_THRLD to ESP_BT_GAP_RSSI_HIGH_THRLD */ } read_rssi_delta; /*!< read rssi parameter struct */ + + /** + * @brief ESP_BT_GAP_AUTH_CMPL_EVT + */ + struct auth_cmpl_param { + esp_bd_addr_t bda; /*!< remote bluetooth device address*/ + esp_bt_status_t stat; /*!< authentication complete status */ + uint8_t device_name[ESP_BT_GAP_MAX_BDNAME_LEN + 1]; /*!< device name */ + } auth_cmpl; /*!< authentication complete parameter struct */ } esp_bt_gap_cb_param_t; /** @@ -398,6 +408,45 @@ esp_err_t esp_bt_gap_get_cod(esp_bt_cod_t *cod); */ esp_err_t esp_bt_gap_read_rssi_delta(esp_bd_addr_t remote_addr); +/** +* @brief Removes a device from the security database list of +* peer device. +* +* @param[in] bd_addr : BD address of the peer device +* +* @return - ESP_OK : success +* - ESP_FAIL : failed +* +*/ +esp_err_t esp_bt_gap_remove_bond_device(esp_bd_addr_t bd_addr); + +/** +* @brief Get the device number from the security database list of peer device. +* It will return the device bonded number immediately. +* +* @return - >= 0 : bonded devices number. +* - ESP_FAIL : failed +* +*/ +int esp_bt_gap_get_bond_device_num(void); + +/** +* @brief Get the device from the security database list of peer device. +* It will return the device bonded information immediately. +* @param[inout] dev_num: Indicate the dev_list array(buffer) size as input. +* If dev_num is large enough, it means the actual number as output. +* Suggest that dev_num value equal to esp_ble_get_bond_device_num(). +* +* @param[out] dev_list: an array(buffer) of `esp_bd_addr_t` type. Use for storing the bonded devices address. +* The dev_list should be allocated by who call this API. +* +* @return +* - ESP_OK : Succeed +* - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled +* - ESP_FAIL: others +*/ +esp_err_t esp_bt_gap_get_bond_device_list(int *dev_num, esp_bd_addr_t *dev_list); + #ifdef __cplusplus } #endif diff --git a/components/bt/bluedroid/btc/core/btc_dm.c b/components/bt/bluedroid/btc/core/btc_dm.c index ff82b45f58..d6d41e2346 100644 --- a/components/bt/bluedroid/btc/core/btc_dm.c +++ b/components/bt/bluedroid/btc/core/btc_dm.c @@ -27,11 +27,20 @@ #include "bta/bta_api.h" #include "bta/bta_gatt_api.h" #include "osi/allocator.h" +#include "btc/btc_manage.h" + #if (BTC_GAP_BT_INCLUDED == TRUE) #include "btc_gap_bt.h" -#endif /* BTC_GAP_BT_INCLUDED == TRUE */ +static inline void btc_gap_bt_cb_to_app(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) +{ + esp_bt_gap_cb_t cb = (esp_bt_gap_cb_t)btc_profile_cb_get(BTC_PID_GAP_BT); + if (cb) { + cb(event, param); + } +} +#endif /* BTC_GAP_BT_INCLUDED == TRUE */ /****************************************************************************** ** Constants & Macros ******************************************************************************/ @@ -309,6 +318,7 @@ static void btc_dm_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) // Skip SDP for certain HID Devices if (p_auth_cmpl->success) { + status = BT_STATUS_SUCCESS; } else { // Map the HCI fail reason to bt status switch (p_auth_cmpl->fail_reason) { @@ -348,6 +358,13 @@ static void btc_dm_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) status = BT_STATUS_FAIL; } } +#if (BTC_GAP_BT_INCLUDED == TRUE) + esp_bt_gap_cb_param_t param; + param.auth_cmpl.stat = status; + memcpy(param.auth_cmpl.bda, p_auth_cmpl->bd_addr, ESP_BD_ADDR_LEN); + memcpy(param.auth_cmpl.device_name, p_auth_cmpl->bd_name, ESP_BT_GAP_MAX_BDNAME_LEN + 1); + btc_gap_bt_cb_to_app(ESP_BT_GAP_AUTH_CMPL_EVT, ¶m); +#endif /* BTC_GAP_BT_INCLUDED == TRUE */ (void) status; } @@ -467,7 +484,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) #if (SMP_INCLUDED == TRUE) bt_bdaddr_t bd_addr; rsp_app = true; - LOG_ERROR("BTA_DM_DEV_UNPAIRED_EVT"); + LOG_DEBUG("BTA_DM_DEV_UNPAIRED_EVT"); memcpy(bd_addr.address, p_data->link_down.bd_addr, sizeof(BD_ADDR)); btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN); param.remove_bond_dev_cmpl.status = ESP_BT_STATUS_FAIL; diff --git a/components/bt/bluedroid/btc/core/btc_storage.c b/components/bt/bluedroid/btc/core/btc_storage.c index 4109bb7a84..5114a6befd 100644 --- a/components/bt/bluedroid/btc/core/btc_storage.c +++ b/components/bt/bluedroid/btc/core/btc_storage.c @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +#include #include "btc/btc_storage.h" #include "btc/btc_util.h" @@ -165,3 +166,70 @@ bt_status_t btc_storage_remove_bonded_device(bt_bdaddr_t *remote_bd_addr) return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; } + +/******************************************************************************* +** +** Function btc_storage_get_num_bt_bond_devices +** +** Description BTC storage API - get the num of the bonded device from NVRAM +** +** Returns the num of the bonded device +** +*******************************************************************************/ +int btc_storage_get_num_bt_bond_devices(void) +{ + int num_dev = 0; + + btc_config_lock(); + for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end(); + iter = btc_config_section_next(iter)) { + const char *name = btc_config_section_name(iter); + if (string_is_bdaddr(name) && + btc_config_exist(name, BTC_STORAGE_LINK_KEY_TYPE_STR) && + btc_config_exist(name, BTC_STORAGE_PIN_LENGTH_STR) && + btc_config_exist(name, BTC_STORAGE_LINK_KEY_STR)) { + num_dev++; + } + } + btc_config_unlock(); + + return num_dev; +} + +/******************************************************************************* +** +** Function btc_storage_get_bonded_bt_devices_list +** +** Description BTC storage API - get the list of the bonded device from NVRAM +** +** Returns BT_STATUS_SUCCESS if get the list successful, +** BT_STATUS_FAIL otherwise +** +*******************************************************************************/ +bt_status_t btc_storage_get_bonded_bt_devices_list(bt_bdaddr_t *bond_dev, int dev_num) +{ + bt_bdaddr_t bd_addr; + + btc_config_lock(); + for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end(); + iter = btc_config_section_next(iter)) { + + if (dev_num-- <= 0) { + break; + } + + const char *name = btc_config_section_name(iter); + + if (string_is_bdaddr(name) && + btc_config_exist(name, BTC_STORAGE_LINK_KEY_TYPE_STR) && + btc_config_exist(name, BTC_STORAGE_PIN_LENGTH_STR) && + btc_config_exist(name, BTC_STORAGE_LINK_KEY_STR)) { + string_to_bdaddr(name, &bd_addr); + memcpy(bond_dev, &bd_addr, sizeof(bt_bdaddr_t)); + bond_dev++; + } + } + btc_config_unlock(); + + return BT_STATUS_SUCCESS; +} \ No newline at end of file diff --git a/components/bt/bluedroid/btc/include/btc/btc_storage.h b/components/bt/bluedroid/btc/include/btc/btc_storage.h index 5e54cb705b..f40b169d46 100644 --- a/components/bt/bluedroid/btc/include/btc/btc_storage.h +++ b/components/bt/bluedroid/btc/include/btc/btc_storage.h @@ -18,6 +18,7 @@ #include #include "common/bt_defs.h" #include "stack/bt_types.h" +#include "esp_gap_bt_api.h" #define BTC_STORAGE_DEV_CLASS_STR "DevClass" @@ -65,4 +66,27 @@ bt_status_t btc_storage_remove_bonded_device(bt_bdaddr_t *remote_bd_addr); *******************************************************************************/ bt_status_t btc_storage_load_bonded_devices(void); +/******************************************************************************* +** +** Function btc_storage_get_num_bt_bond_devices +** +** Description BTC storage API - get the num of the bonded device from NVRAM +** +** Returns the num of the bonded device +** +*******************************************************************************/ +int btc_storage_get_num_bt_bond_devices(void); + +/******************************************************************************* +** +** Function btc_storage_get_bonded_bt_devices_list +** +** Description BTC storage API - get the list of the bonded device from NVRAM +** +** Returns BT_STATUS_SUCCESS if get the list successful, +** BT_STATUS_FAIL otherwise +** +*******************************************************************************/ +bt_status_t btc_storage_get_bonded_bt_devices_list(bt_bdaddr_t *bond_dev, int dev_num); + #endif /* BTC_STORAGE_H */ diff --git a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c index ad588568a2..c612009c18 100644 --- a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c +++ b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c @@ -16,6 +16,7 @@ #include "esp_bt_defs.h" #include "esp_gap_bt_api.h" #include "btc_gap_bt.h" +#include "btc/btc_storage.h" #include "bta/bta_api.h" #include "common/bt_trace.h" #include "common/bt_target.h" @@ -620,6 +621,17 @@ static void btc_gap_bt_read_rssi_delta(btc_gap_bt_args_t *arg) BTA_DmBleReadRSSI(arg->read_rssi_delta.bda.address, btc_gap_bt_read_rssi_delta_cmpl_callback); } +esp_err_t btc_gap_bt_remove_bond_device(btc_gap_bt_args_t *arg) +{ + BD_ADDR bd_addr; + memcpy(bd_addr, arg->rm_bond_device.bda.address, sizeof(BD_ADDR)); + if(BTA_DmRemoveDevice(bd_addr) == BTA_SUCCESS){ + btc_storage_remove_bonded_device(&(arg->rm_bond_device.bda)); + return ESP_BT_STATUS_SUCCESS; + } + return ESP_BT_STATUS_FAIL; +} + void btc_gap_bt_call_handler(btc_msg_t *msg) { btc_gap_bt_args_t *arg = (btc_gap_bt_args_t *)msg->arg; @@ -665,6 +677,10 @@ void btc_gap_bt_call_handler(btc_msg_t *msg) btc_gap_bt_read_rssi_delta(msg->arg); break; } + case BTC_GAP_BT_ACT_REMOVE_BOND_DEVICE:{ + btc_gap_bt_remove_bond_device(msg->arg); + break; + } default: break; } @@ -697,6 +713,6 @@ void btc_gap_bt_cb_handler(btc_msg_t *msg) } else { LOG_ERROR("%s, unknow msg->act = %d", __func__, msg->act); } - + } #endif /* (BTC_GAP_BT_INCLUDED == TRUE) */ diff --git a/components/bt/bluedroid/btc/profile/std/include/btc_gap_bt.h b/components/bt/bluedroid/btc/profile/std/include/btc_gap_bt.h index 4ca1803fdc..d33ab9182e 100644 --- a/components/bt/bluedroid/btc/profile/std/include/btc_gap_bt.h +++ b/components/bt/bluedroid/btc/profile/std/include/btc_gap_bt.h @@ -35,6 +35,7 @@ typedef enum { BTC_GAP_BT_ACT_SEARCH_SERVICE_RECORD, BTC_GAP_BT_ACT_SET_COD, BTC_GAP_BT_ACT_READ_RSSI_DELTA, + BTC_GAP_BT_ACT_REMOVE_BOND_DEVICE, } btc_gap_bt_act_t; /* btc_bt_gap_args_t */ @@ -70,6 +71,11 @@ typedef union { struct bt_read_rssi_delta_args { bt_bdaddr_t bda; } read_rssi_delta; + + // BTC_GAP_BT_ACT_REMOVE_BOND_DEVICE + struct rm_bond_device_args { + bt_bdaddr_t bda; + } rm_bond_device; } btc_gap_bt_args_t; void btc_gap_bt_call_handler(btc_msg_t *msg); diff --git a/examples/bluetooth/a2dp_source/main/main.c b/examples/bluetooth/a2dp_source/main/main.c index e6dd46f633..a03080923a 100644 --- a/examples/bluetooth/a2dp_source/main/main.c +++ b/examples/bluetooth/a2dp_source/main/main.c @@ -244,6 +244,16 @@ void bt_app_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) } case ESP_BT_GAP_RMT_SRVCS_EVT: case ESP_BT_GAP_RMT_SRVC_REC_EVT: + break; + case ESP_BT_GAP_AUTH_CMPL_EVT:{ + if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) { + ESP_LOGI(BT_AV_TAG, "authentication success: %s", param->auth_cmpl.device_name); + esp_log_buffer_hex(BT_AV_TAG, param->auth_cmpl.bda, ESP_BD_ADDR_LEN); + } else { + ESP_LOGI(BT_AV_TAG, "authentication failed, status:%d", param->auth_cmpl.stat); + } + } + default: { ESP_LOGI(BT_AV_TAG, "event: %d", event); break; From d530036ad1fcc14f4813819d17be1c0f9bbdaef5 Mon Sep 17 00:00:00 2001 From: Hrishikesh Dhayagude Date: Thu, 3 May 2018 18:19:57 +0530 Subject: [PATCH 037/187] Fix few typos in the docs Signed-off-by: Hrishikesh Dhayagude --- docs/README.md | 2 +- docs/en/get-started/establish-serial-connection.rst | 2 +- docs/en/get-started/index.rst | 2 +- docs/en/resources.rst | 2 +- docs/en/security/flash-encryption.rst | 2 +- docs/en/security/secure-boot.rst | 6 +++--- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/README.md b/docs/README.md index dbd27c9001..f240d9ebb4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ # Documentation Source Folder -This folder contains source files of **ESP-IDF documentation** avialable in [English](https://esp-idf.readthedocs.io/en/latest/) and [中文](https://esp-idf.readthedocs.io/zh_CN/latest/). +This folder contains source files of **ESP-IDF documentation** available in [English](https://esp-idf.readthedocs.io/en/latest/) and [中文](https://esp-idf.readthedocs.io/zh_CN/latest/). The sources do not render well in GitHub and some information is not visible at all. diff --git a/docs/en/get-started/establish-serial-connection.rst b/docs/en/get-started/establish-serial-connection.rst index d8753a6bb5..22e08b0fc1 100644 --- a/docs/en/get-started/establish-serial-connection.rst +++ b/docs/en/get-started/establish-serial-connection.rst @@ -69,7 +69,7 @@ Make sure you re-login to enable read and write permissions for the serial port. Verify serial connection ------------------------ -Now verify that the serial connection is operational. You can do this using a serial terminal program. In this example we will use `PuTTY SSH Client `_ that is avilable for both Windows and Linux. You can use other serial program and set communication parameters like below. +Now verify that the serial connection is operational. You can do this using a serial terminal program. In this example we will use `PuTTY SSH Client `_ that is available for both Windows and Linux. You can use other serial program and set communication parameters like below. Run terminal, set identified serial port, baud rate = 115200, data bits = 8, stop bits = 1, and parity = N. Below are example screen shots of setting the port and such transmission parameters (in short described as 115200-8-1-N) on Windows and Linux. Remember to select exactly the same serial port you have identified in steps above. diff --git a/docs/en/get-started/index.rst b/docs/en/get-started/index.rst index dffffb929f..9a2d3779ca 100644 --- a/docs/en/get-started/index.rst +++ b/docs/en/get-started/index.rst @@ -2,7 +2,7 @@ Get Started *********** -This document is intended to help users set up the software environment for developement of applications using hardware based on the Espressif ESP32. Through a simple example we would like to illustrate how to use ESP-IDF (Espressif IoT Development Framework), including the menu based configuration, compiling the ESP-IDF and firmware download to ESP32 boards. +This document is intended to help users set up the software environment for development of applications using hardware based on the Espressif ESP32. Through a simple example we would like to illustrate how to use ESP-IDF (Espressif IoT Development Framework), including the menu based configuration, compiling the ESP-IDF and firmware download to ESP32 boards. Introduction diff --git a/docs/en/resources.rst b/docs/en/resources.rst index 06c6236d07..f4775acd91 100644 --- a/docs/en/resources.rst +++ b/docs/en/resources.rst @@ -6,7 +6,7 @@ Resources * Check the `Issues `_ section on GitHub if you find a bug or have a feature request. Please check existing `Issues `_ before opening a new one. -* A comprehensive collection of `solutions `_, `practical applications `_, `components and drivers `_ based on ESP-IDF is avialable in `ESP32 IoT Solution `_ repository. In most of cases descriptions are provided both in English and in 中文. +* A comprehensive collection of `solutions `_, `practical applications `_, `components and drivers `_ based on ESP-IDF is available in `ESP32 IoT Solution `_ repository. In most of cases descriptions are provided both in English and in 中文. * To develop applications using Arduino platform, refer to `Arduino core for ESP32 WiFi chip `_. diff --git a/docs/en/security/flash-encryption.rst b/docs/en/security/flash-encryption.rst index 866cff498f..f44fa18bb5 100644 --- a/docs/en/security/flash-encryption.rst +++ b/docs/en/security/flash-encryption.rst @@ -32,7 +32,7 @@ Background - Although software running on the chip can transparently decrypt flash contents, by default it is made impossible for the UART bootloader to decrypt (or encrypt) data when flash encryption is enabled. -- If flash encrption may be enabled, the programmer must take certain precautions when writing code that :ref:`uses encrypted flash `. +- If flash encryption may be enabled, the programmer must take certain precautions when writing code that :ref:`uses encrypted flash `. .. _flash-encryption-initialisation: diff --git a/docs/en/security/secure-boot.rst b/docs/en/security/secure-boot.rst index dcd6d4b60e..da9a203d36 100644 --- a/docs/en/security/secure-boot.rst +++ b/docs/en/security/secure-boot.rst @@ -14,7 +14,7 @@ Background - Most data is stored in flash. Flash access does not need to be protected from physical access in order for secure boot to function, because critical data is stored (non-software-accessible) in Efuses internal to the chip. -- Efuses are used to store the secure bootloader key (in efuse BLOCK2), and also a single Efuse bit (ABS_DONE_0) is burned (written to 1) to permanently enable secure boot on the chip. For more details about efuse, see Chapter 11 "eFuse Controller" in the Technical Referecnce Manual. +- Efuses are used to store the secure bootloader key (in efuse BLOCK2), and also a single Efuse bit (ABS_DONE_0) is burned (written to 1) to permanently enable secure boot on the chip. For more details about efuse, see Chapter 11 "eFuse Controller" in the Technical Reference Manual. - To understand the secure boot process, first familiarise yourself with the standard :doc:`ESP-IDF boot process <../api-guides/general-notes>`. @@ -51,7 +51,7 @@ The following keys are used by the secure boot process: - "secure boot signing key" is a standard ECDSA public/private key pair (see :ref:`secure-boot-image-signing-algorithm`) in PEM format. - - The public key from this key pair (for signature verificaton but not signature creation) is compiled into the software bootloader and used to verify the second stage of booting (partition table, app image) before booting continues. The public key can be freely distributed, it does not need to be kept secret. + - The public key from this key pair (for signature verification but not signature creation) is compiled into the software bootloader and used to verify the second stage of booting (partition table, app image) before booting continues. The public key can be freely distributed, it does not need to be kept secret. - The private key from this key pair *must be securely kept private*, as anyone who has this key can authenticate to any bootloader that is configured with secure boot and the matching public key. @@ -82,7 +82,7 @@ How To Enable Secure Boot *NOTE*: ``make flash`` doesn't flash the bootloader if secure boot is enabled. -8. Reset the ESP32 and it will boot the software bootloader you flashed. The software bootloader will enable secure boot on the chip, and then it verifies the app image signature and boots the app. You should watch the serial console output from the ESP32 to verify that secure boot is enabled and no errors have occured due to the build configuration. +8. Reset the ESP32 and it will boot the software bootloader you flashed. The software bootloader will enable secure boot on the chip, and then it verifies the app image signature and boots the app. You should watch the serial console output from the ESP32 to verify that secure boot is enabled and no errors have occurred due to the build configuration. **NOTE** Secure boot won't be enabled until after a valid partition table and app image have been flashed. This is to prevent accidents before the system is fully configured. From e3a59746516e491c1b06709892f12eb22a7e22c0 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 4 May 2018 02:06:04 +0800 Subject: [PATCH 038/187] docs: make conf.py python3 compatible --- docs/conf_common.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf_common.py b/docs/conf_common.py index e5dd9df6e0..bc6d7e401d 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -31,7 +31,7 @@ if 'BUILDDIR' in os.environ: builddir = os.environ['BUILDDIR'] # Call Doxygen to get XML files from the header files -print "Calling Doxygen to generate latest XML files" +print("Calling Doxygen to generate latest XML files") os.system("doxygen ../Doxyfile") # Doxygen has generated XML files in 'xml' directory. # Copy them to 'xml_in', only touching the files which have changed. @@ -115,7 +115,7 @@ version = run_cmd_get_output('git describe') # The full version, including alpha/beta/rc tags. # If needed, nearest tag is returned by 'git describe --abbrev=0'. release = version -print 'Version: {0} Release: {1}'.format(version, release) +print('Version: {0} Release: {1}'.format(version, release)) # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: From 0dca2d4c686dc854d877855f8307ceef30e468dd Mon Sep 17 00:00:00 2001 From: kooho <2229179028@qq.com> Date: Tue, 24 Apr 2018 16:11:02 +0800 Subject: [PATCH 039/187] driver(uart): Fix uart_get_baudrate incorrect return value when using ref_tick --- components/driver/test/test_uart.c | 48 ++++++++++++++++++++++++++++++ components/driver/uart.c | 6 +++- 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 components/driver/test/test_uart.c diff --git a/components/driver/test/test_uart.c b/components/driver/test/test_uart.c new file mode 100644 index 0000000000..f49c73ef7c --- /dev/null +++ b/components/driver/test/test_uart.c @@ -0,0 +1,48 @@ +#include +#include "unity.h" +#include "driver/uart.h" +#include "esp_log.h" + +#define UART_TAG "Uart" +#define UART_NUM1 (UART_NUM_1) +#define BUF_SIZE (100) +#define UART1_RX_PIN (22) +#define UART1_TX_PIN (23) +#define UART_BAUD_11520 (11520) +#define UART_BAUD_115200 (115200) +#define TOLERANCE (0.02) //baud rate error tolerance 2%. + +#define UART_TOLERANCE_CHECK(val, uper_limit, lower_limit) ( (val) <= (uper_limit) && (val) >= (lower_limit) ) + +static void uart_config(uint32_t baud_rate, bool use_ref_tick) +{ + uart_config_t uart_config = { + .baud_rate = baud_rate, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .use_ref_tick = use_ref_tick, + }; + uart_param_config(UART_NUM1, &uart_config); + uart_set_pin(UART_NUM1, UART1_TX_PIN, UART1_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); + uart_driver_install(UART_NUM1, BUF_SIZE * 2, BUF_SIZE * 2, 20, NULL, 0); +} + +TEST_CASE("test uart get baud-rate","[uart]") +{ + uint32_t baud_rate1 = 0; + uint32_t baud_rate2 = 0; + printf("init uart%d, use reftick, baud rate : %d\n", (int)UART_NUM1, (int)UART_BAUD_11520); + uart_config(UART_BAUD_11520, true); + uart_get_baudrate(UART_NUM1, &baud_rate1); + printf("init uart%d, unuse reftick, baud rate : %d\n", (int)UART_NUM1, (int)UART_BAUD_115200); + uart_config(UART_BAUD_115200, false); + uart_get_baudrate(UART_NUM1, &baud_rate2); + printf("get baud rate when use reftick: %d\n", (int)baud_rate1); + printf("get baud rate when don't use reftick: %d\n", (int)baud_rate2); + uart_driver_delete(UART_NUM1); + TEST_ASSERT(UART_TOLERANCE_CHECK(baud_rate1, (1.0 + TOLERANCE)*UART_BAUD_11520, (1.0 - TOLERANCE)*UART_BAUD_11520)) + TEST_ASSERT(UART_TOLERANCE_CHECK(baud_rate2, (1.0 + TOLERANCE)*UART_BAUD_115200, (1.0 - TOLERANCE)*UART_BAUD_115200)) + ESP_LOGI(UART_TAG, "get baud-rate test passed ....\n"); +} \ No newline at end of file diff --git a/components/driver/uart.c b/components/driver/uart.c index efd56abf84..96cfd1eb5f 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -210,7 +210,11 @@ esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate) UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); uint32_t clk_div = (UART[uart_num]->clk_div.div_int << 4) | UART[uart_num]->clk_div.div_frag; UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); - (*baudrate) = ((UART_CLK_FREQ) << 4) / clk_div; + uint32_t uart_clk_freq = esp_clk_apb_freq(); + if(UART[uart_num]->conf0.tick_ref_always_on == 0) { + uart_clk_freq = REF_CLK_FREQ; + } + (*baudrate) = ((uart_clk_freq) << 4) / clk_div; return ESP_OK; } From 017f109f6e9ab50094509a8720a8f04c10b0c9ff Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Fri, 4 May 2018 10:36:04 +0800 Subject: [PATCH 040/187] esp32: optimize wifi lock Replace portENTER_CRITICAL/portEXIT_CRITICAL with semaphore lock if the protected resource is only accessed by different tasks --- components/esp32/lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp32/lib b/components/esp32/lib index 8cd9fd455e..7c8fc4a8f1 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 8cd9fd455e98a5c818f2796b4b83107884b7874c +Subproject commit 7c8fc4a8f158097d116e1ce94dfff097b9281129 From cbab7fec766134146887eb8b9e988ddbf2ef1c1d Mon Sep 17 00:00:00 2001 From: baohongde Date: Fri, 4 May 2018 19:44:40 +0800 Subject: [PATCH 041/187] component/bt: Fix bug a2dp have disconnect state when connecting with iphone 7 --- .../bluedroid/btc/profile/std/a2dp/btc_av.c | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/components/bt/bluedroid/btc/profile/std/a2dp/btc_av.c b/components/bt/bluedroid/btc/profile/std/a2dp/btc_av.c index b9099a76d6..3256293755 100644 --- a/components/bt/bluedroid/btc/profile/std/a2dp/btc_av.c +++ b/components/bt/bluedroid/btc/profile/std/a2dp/btc_av.c @@ -38,6 +38,7 @@ #include "btc_a2dp_sink.h" #include "btc_a2dp_source.h" #include "esp_a2dp_api.h" +#include "osi/alarm.h" #if BTC_AV_INCLUDED @@ -80,7 +81,7 @@ typedef struct { } btc_av_cb_t; typedef struct { - bt_bdaddr_t *target_bda; + bt_bdaddr_t target_bda; uint16_t uuid; } btc_av_connect_req_t; @@ -88,7 +89,10 @@ typedef struct { ** Static variables ******************************************************************************/ static btc_av_cb_t btc_av_cb = {0}; -static TIMER_LIST_ENT tle_av_open_on_rc; + +#if BTC_AV_SRC_INCLUDED +static osi_alarm_t *tle_av_open_on_rc = NULL; +#endif /* BTC_AV_SRC_INCLUDED */ /* both interface and media task needs to be ready to alloc incoming request */ #define CHECK_BTAV_INIT() do \ @@ -204,6 +208,7 @@ UNUSED_ATTR static const char *dump_av_sm_event_name(btc_av_sm_event_t event) /**************************************************************************** ** Local helper functions *****************************************************************************/ +#if BTC_AV_SRC_INCLUDED /******************************************************************************* ** ** Function btc_initiate_av_open_tmr_hdlr @@ -215,23 +220,23 @@ UNUSED_ATTR static const char *dump_av_sm_event_name(btc_av_sm_event_t event) ** Returns void ** *******************************************************************************/ -static void btc_initiate_av_open_tmr_hdlr(TIMER_LIST_ENT *tle) +static void btc_initiate_av_open_tmr_hdlr(void *arg) { + UNUSED(arg); BD_ADDR peer_addr; - UNUSED(tle); btc_av_connect_req_t connect_req; - UNUSED(tle); /* is there at least one RC connection - There should be */ if (btc_rc_get_connected_peer(peer_addr)) { LOG_DEBUG("%s Issuing connect to the remote RC peer", __FUNCTION__); /* In case of AVRCP connection request, we will initiate SRC connection */ - connect_req.target_bda = (bt_bdaddr_t *)&peer_addr; + memcpy(connect_req.target_bda.address, peer_addr, sizeof(bt_bdaddr_t)); connect_req.uuid = UUID_SERVCLASS_AUDIO_SOURCE; - btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_CONNECT_REQ_EVT, (char *)&connect_req); + btc_dispatch_sm_event(BTC_AV_CONNECT_REQ_EVT, &connect_req, sizeof(btc_av_connect_req_t)); } else { LOG_ERROR("%s No connected RC peers", __FUNCTION__); } } +#endif /* BTC_AV_SRC_INCLUDED */ /***************************************************************************** ** Static functions @@ -303,7 +308,7 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data) case BTA_AV_PENDING_EVT: case BTC_AV_CONNECT_REQ_EVT: { if (event == BTC_AV_CONNECT_REQ_EVT) { - memcpy(&btc_av_cb.peer_bda, ((btc_av_connect_req_t *)p_data)->target_bda, + memcpy(&btc_av_cb.peer_bda, &((btc_av_connect_req_t *)p_data)->target_bda, sizeof(bt_bdaddr_t)); BTA_AvOpen(btc_av_cb.peer_bda.address, btc_av_cb.bta_handle, TRUE, BTA_SEC_AUTHENTICATE, ((btc_av_connect_req_t *)p_data)->uuid); @@ -326,11 +331,11 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data) * TODO: We may need to do this only on an AVRCP Play. FixMe */ +#if BTC_AV_SRC_INCLUDED LOG_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV"); - memset(&tle_av_open_on_rc, 0, sizeof(tle_av_open_on_rc)); - tle_av_open_on_rc.param = (UINT32)btc_initiate_av_open_tmr_hdlr; - btu_start_timer(&tle_av_open_on_rc, BTU_TTYPE_USER_FUNC, - BTC_TIMEOUT_AV_OPEN_ON_RC_SECS); + tle_av_open_on_rc = osi_alarm_new("AVconn", btc_initiate_av_open_tmr_hdlr, NULL, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000); + osi_alarm_set(tle_av_open_on_rc, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000); +#endif /* BTC_AV_SRC_INCLUDED */ btc_rc_handler(event, p_data); break; @@ -343,10 +348,12 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data) break; case BTA_AV_RC_CLOSE_EVT: - if (tle_av_open_on_rc.in_use) { - LOG_DEBUG("BTA_AV_RC_CLOSE_EVT: Stopping AV timer."); - btu_stop_timer(&tle_av_open_on_rc); +#if BTC_AV_SRC_INCLUDED + if (tle_av_open_on_rc) { + osi_alarm_free(tle_av_open_on_rc); + tle_av_open_on_rc = NULL; } +#endif /* BTC_AV_SRC_INCLUDED */ btc_rc_handler(event, p_data); break; @@ -681,7 +688,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data) break; case BTC_AV_CONNECT_REQ_EVT: - if (memcmp ((bt_bdaddr_t *)p_data, &(btc_av_cb.peer_bda), + if (memcmp (&((btc_av_connect_req_t *)p_data)->target_bda, &(btc_av_cb.peer_bda), sizeof(btc_av_cb.peer_bda)) == 0) { LOG_DEBUG("%s: Ignore BTC_AVCONNECT_REQ_EVT for same device\n", __func__); } else { @@ -996,7 +1003,7 @@ static bt_status_t btc_av_init(int service_id) static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid) { btc_av_connect_req_t connect_req; - connect_req.target_bda = bd_addr; + memcpy(&connect_req.target_bda, bd_addr, sizeof(bt_bdaddr_t)); connect_req.uuid = uuid; LOG_DEBUG("%s\n", __FUNCTION__); @@ -1021,6 +1028,10 @@ static void clean_up(int service_id) if (service_id == BTA_A2DP_SOURCE_SERVICE_ID) { #if BTC_AV_SRC_INCLUDED btc_a2dp_source_shutdown(); + if (tle_av_open_on_rc) { + osi_alarm_free(tle_av_open_on_rc); + tle_av_open_on_rc = NULL; + } #endif /* BTC_AV_SRC_INCLUDED */ } @@ -1371,6 +1382,9 @@ void btc_a2dp_call_handler(btc_msg_t *msg) btc_a2dp_control_datapath_ctrl(arg->dp_evt); break; } + case BTC_AV_CONNECT_REQ_EVT: + btc_sm_dispatch(btc_av_cb.sm_handle, msg->act, (char *)msg->arg); + break; // case BTC_AV_DISCONNECT_REQ_EVT: case BTC_AV_START_STREAM_REQ_EVT: case BTC_AV_STOP_STREAM_REQ_EVT: From a9dfa06125f3f607717a28beb1ddff1137c26147 Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Sun, 6 May 2018 17:29:06 +0800 Subject: [PATCH 042/187] esp32: fix two wifi bugs 1. Fix the bug that WiFi receives duplicate MPDU 2. Deauth the station if soft-AP already has max WiFi connections --- components/esp32/lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp32/lib b/components/esp32/lib index 7c8fc4a8f1..e21cf48e26 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 7c8fc4a8f158097d116e1ce94dfff097b9281129 +Subproject commit e21cf48e265f86878d89e31457eb0f1722b410d8 From b90ad81f223ae227d78088e9d36e7bd45448126c Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 7 May 2018 09:03:48 +0800 Subject: [PATCH 043/187] driver: Add notes to SPI driver docs about thread safety --- components/driver/include/driver/spi_master.h | 12 +++++++----- docs/en/api-reference/peripherals/spi_master.rst | 7 +++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/components/driver/include/driver/spi_master.h b/components/driver/include/driver/spi_master.h index ba77b9fb2b..232ad36eb7 100644 --- a/components/driver/include/driver/spi_master.h +++ b/components/driver/include/driver/spi_master.h @@ -226,15 +226,17 @@ esp_err_t spi_device_get_trans_result(spi_device_handle_t handle, spi_transactio /** - * @brief Do a SPI transaction + * @brief Send a SPI transaction, wait for it to complete, and return the result * - * Essentially does the same as spi_device_queue_trans followed by spi_device_get_trans_result. Do - * not use this when there is still a transaction queued that hasn't been finalized - * using spi_device_get_trans_result. + * This function is the equivalent of calling spi_device_queue_trans() followed by spi_device_get_trans_result(). + * Do not use this when there is still a transaction separately queued from spi_device_queue_trans() that hasn't been finalized + * using spi_device_get_trans_result(). + * + * @note This function is not thread safe when multiple tasks access the same SPI device. * * @param handle Device handle obtained using spi_host_add_dev * @param trans_desc Description of transaction to execute - * @return + * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_OK on success */ diff --git a/docs/en/api-reference/peripherals/spi_master.rst b/docs/en/api-reference/peripherals/spi_master.rst index 412c72c947..05474190d7 100644 --- a/docs/en/api-reference/peripherals/spi_master.rst +++ b/docs/en/api-reference/peripherals/spi_master.rst @@ -264,6 +264,13 @@ And if the host only writes, the *dummy bit workaround* is not used and the freq | 40 | 80 | +-------------+----------------------+ +Thread Safety +------------- + +The SPI driver API is thread safe when multiple SPI devices on the same bus are accessed from different tasks. However, the driver is not thread safe if the same SPI device is accessed from multiple tasks. + +In this case, it is recommended to either refactor your application so only a single task accesses each SPI device, or to add mutex locking around access of the shared device. + .. _spi_known_issues: Known Issues From 5129bca67c000b5c29d10185f16cb44e19cbff93 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Mon, 7 May 2018 09:01:56 +0200 Subject: [PATCH 044/187] VFS: Use smaller numbers as file descriptors --- .gitlab-ci.yml | 7 + components/idf_test/include/idf_performance.h | 2 +- components/lwip/include/lwip/lwip/sockets.h | 2 - .../lwip/include/lwip/port/arch/vfs_lwip.h | 5 - components/lwip/include/lwip/port/lwipopts.h | 12 +- components/lwip/port/vfs_lwip.c | 26 +- components/newlib/include/sys/types.h | 4 - components/vfs/README.rst | 33 +-- components/vfs/include/esp_vfs.h | 41 ++- components/vfs/test/test_vfs_fd.c | 261 ++++++++++++++++++ components/vfs/vfs.c | 209 +++++++++----- components/vfs/vfs_uart.c | 28 +- 12 files changed, 454 insertions(+), 176 deletions(-) create mode 100644 components/vfs/test/test_vfs_fd.c diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a0e579ea1a..b013c847d4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -890,6 +890,13 @@ UT_004_09: - UT_T1_1 - UT_psram +UT_004_10: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + - UT_psram + IT_001_01: <<: *test_template tags: diff --git a/components/idf_test/include/idf_performance.h b/components/idf_test/include/idf_performance.h index 2e118c8916..cd5a463d75 100644 --- a/components/idf_test/include/idf_performance.h +++ b/components/idf_test/include/idf_performance.h @@ -16,5 +16,5 @@ #define IDF_PERFORMANCE_MAX_ESP_TIMER_GET_TIME_PER_CALL 1000 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 30 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 27 - +#define IDF_PERFORMANCE_MAX_VFS_OPEN_WRITE_CLOSE_TIME 20000 diff --git a/components/lwip/include/lwip/lwip/sockets.h b/components/lwip/include/lwip/lwip/sockets.h index d8e4c7ffbe..c3cadd8730 100755 --- a/components/lwip/include/lwip/lwip/sockets.h +++ b/components/lwip/include/lwip/lwip/sockets.h @@ -446,8 +446,6 @@ typedef struct fd_set unsigned char fd_bits [(FD_SETSIZE+7)/8]; } fd_set; -#elif LWIP_SOCKET_OFFSET -#error LWIP_SOCKET_OFFSET does not work with external FD_SET! #endif /* FD_SET */ /** LWIP_TIMEVAL_PRIVATE: if you want to use the struct timeval provided diff --git a/components/lwip/include/lwip/port/arch/vfs_lwip.h b/components/lwip/include/lwip/port/arch/vfs_lwip.h index 88714b03b9..1957304b9f 100644 --- a/components/lwip/include/lwip/port/arch/vfs_lwip.h +++ b/components/lwip/include/lwip/port/arch/vfs_lwip.h @@ -16,11 +16,6 @@ extern "C" { #endif -/* Internal declarations used to ingreate LWIP port layer - to ESP-IDF VFS for POSIX I/O. -*/ -extern int lwip_socket_offset; - void esp_vfs_lwip_sockets_register(); #ifdef __cplusplus diff --git a/components/lwip/include/lwip/port/lwipopts.h b/components/lwip/include/lwip/port/lwipopts.h index 3e8d26ee3b..4f43ed990c 100644 --- a/components/lwip/include/lwip/port/lwipopts.h +++ b/components/lwip/include/lwip/port/lwipopts.h @@ -38,6 +38,7 @@ #include #include #include +#include #include "esp_task.h" #include "esp_system.h" #include "sdkconfig.h" @@ -698,12 +699,15 @@ */ #define LWIP_POSIX_SOCKETS_IO_NAMES 0 - /** - * Socket offset is also determined via the VFS layer at - * filesystem registration time (see port/vfs_lwip.c) + * FD_SETSIZE from sys/types.h is the maximum number of supported file + * descriptors and CONFIG_LWIP_MAX_SOCKETS defines the number of sockets; + * LWIP_SOCKET_OFFSET is configured to use the largest numbers of file + * descriptors for sockets. File descriptors from 0 to LWIP_SOCKET_OFFSET-1 + * are non-socket descriptors and from LWIP_SOCKET_OFFSET to FD_SETSIZE are + * socket descriptors. */ -#define LWIP_SOCKET_OFFSET lwip_socket_offset +#define LWIP_SOCKET_OFFSET (FD_SETSIZE - CONFIG_LWIP_MAX_SOCKETS) /* Enable all Espressif-only options */ diff --git a/components/lwip/port/vfs_lwip.c b/components/lwip/port/vfs_lwip.c index aa623f0103..2ce639e4e4 100644 --- a/components/lwip/port/vfs_lwip.c +++ b/components/lwip/port/vfs_lwip.c @@ -25,19 +25,11 @@ #include "lwip/sockets.h" #include "sdkconfig.h" -/* LWIP is a special case for VFS use. - - From the LWIP side: - - We set LWIP_SOCKET_OFFSET dynamically at VFS registration time so that native LWIP socket functions & VFS functions - see the same fd space. This is necessary to mix POSIX file operations defined in VFS with POSIX socket operations defined - in LWIP, without needing to wrap all of them. - - From the VFS side: - - ESP_VFS_FLAG_SHARED_FD_SPACE is set, so unlike other VFS implementations the FDs that the LWIP "VFS" sees and the - FDs that the user sees are the same FDs. +/* Non-LWIP file descriptors are from 0 to (LWIP_SOCKET_OFFSET-1). + * LWIP file descriptors are from LWIP_SOCKET_OFFSET to FD_SETSIZE-1. */ -int lwip_socket_offset; +_Static_assert(MAX_FDS >= CONFIG_LWIP_MAX_SOCKETS, "MAX_FDS < CONFIG_LWIP_MAX_SOCKETS"); static int lwip_fcntl_r_wrapper(int fd, int cmd, va_list args); static int lwip_ioctl_r_wrapper(int fd, int cmd, va_list args); @@ -45,7 +37,7 @@ static int lwip_ioctl_r_wrapper(int fd, int cmd, va_list args); void esp_vfs_lwip_sockets_register() { esp_vfs_t vfs = { - .flags = ESP_VFS_FLAG_DEFAULT | ESP_VFS_FLAG_SHARED_FD_SPACE, + .flags = ESP_VFS_FLAG_DEFAULT, .write = &lwip_write_r, .open = NULL, .fstat = NULL, @@ -54,14 +46,8 @@ void esp_vfs_lwip_sockets_register() .fcntl = &lwip_fcntl_r_wrapper, .ioctl = &lwip_ioctl_r_wrapper, }; - int max_fd; - ESP_ERROR_CHECK(esp_vfs_register_socket_space(&vfs, NULL, &lwip_socket_offset, &max_fd)); - - /* LWIP can't be allowed to create more sockets than fit in the per-VFS fd space. Currently this isn't configurable - * but it's set much larger than CONFIG_LWIP_MAX_SOCKETS should ever be (max 2^12 FDs). - */ - assert(max_fd >= lwip_socket_offset && CONFIG_LWIP_MAX_SOCKETS <= max_fd - lwip_socket_offset); + ESP_ERROR_CHECK(esp_vfs_register_fd_range(&vfs, NULL, LWIP_SOCKET_OFFSET, MAX_FDS)); } static int lwip_fcntl_r_wrapper(int fd, int cmd, va_list args) @@ -73,5 +59,3 @@ static int lwip_ioctl_r_wrapper(int fd, int cmd, va_list args) { return lwip_ioctl_r(fd, cmd, va_arg(args, void *)); } - - diff --git a/components/newlib/include/sys/types.h b/components/newlib/include/sys/types.h index 446946a36b..ed33e0a617 100644 --- a/components/newlib/include/sys/types.h +++ b/components/newlib/include/sys/types.h @@ -221,9 +221,6 @@ typedef unsigned int mode_t _ST_INT32; typedef unsigned short nlink_t; -/* FD_SET and friends are still LWIP only */ -# if !defined(ESP_PLATFORM) - /* We don't define fd_set and friends if we are compiling POSIX source, or if we have included (or may include as indicated by __USE_W32_SOCKETS) the W32api winsock[2].h header which @@ -269,7 +266,6 @@ typedef struct _types_fd_set { })) # endif /* !(defined (_POSIX_SOURCE) || defined (_WINSOCK_H) || defined (_WINSOCKAPI_) || defined (__USE_W32_SOCKETS)) */ -#endif /* !defined(ESP_PLATFORM) */ #undef __MS_types__ #undef _ST_INT32 diff --git a/components/vfs/README.rst b/components/vfs/README.rst index b99c72134b..7a25ca542d 100644 --- a/components/vfs/README.rst +++ b/components/vfs/README.rst @@ -93,41 +93,10 @@ When opening files, FS driver will only be given relative path to files. For exa VFS doesn't impose a limit on total file path length, but it does limit FS path prefix to ``ESP_VFS_PATH_MAX`` characters. Individual FS drivers may have their own filename length limitations. - File descriptors ---------------- -It is suggested that filesystem drivers should use small positive integers as file descriptors. VFS component assumes that ``CONFIG_MAX_FD_BITS`` bits (12 by default) are sufficient to represent a file descriptor. - -While file descriptors returned by VFS component to newlib library are rarely seen by the application, the following details may be useful for debugging purposes. File descriptors returned by VFS component are composed of two parts: FS driver ID, and the actual file descriptor. Because newlib stores file descriptors as 16-bit integers, VFS component is also limited by 16 bits to store both parts. - -Lower ``CONFIG_MAX_FD_BITS`` bits are used to store zero-based file descriptor. The per-filesystem FD obtained from the FS ``open`` call, and this result is stored in the lower bits of the FD. Higher bits are used to save the index of FS in the internal table of registered filesystems. - -When VFS component receives a call from newlib which has a file descriptor, this file descriptor is translated back to the FS-specific file descriptor. First, higher bits of FD are used to identify the FS. Then only the lower ``CONFIG_MAX_FD_BITS`` bits of the fd are masked in, and resulting FD is passed to the FS driver. - -.. highlight:: none - -:: - - FD as seen by newlib FD as seen by FS driver - - +-------+---------------+ +------------------------+ - | FS id | Zero—based FD | +--------------------------> | - +---+---+------+--------+ | +------------------------+ - | | | - | +--------------+ - | - | +-------------+ - | | Table of | - | | registered | - | | filesystems | - | +-------------+ +-------------+ - +-------> entry +----> esp_vfs_t | - index +-------------+ | structure | - | | | | - | | | | - +-------------+ +-------------+ - +File descriptors are small positive integers from ``0`` to ``FD_SETSIZE - 1`` where ``FD_SETSIZE`` is defined in newlib's ``sys/types.h``. The largest file descriptors (configured by ``CONFIG_LWIP_MAX_SOCKETS``) are reserved for sockets. The VFS component contains a lookup-table called ``s_fd_table`` for mapping global file descriptors to VFS driver indexes registered in the ``s_vfs`` array. Standard IO streams (stdin, stdout, stderr) ------------------------------------------- diff --git a/components/vfs/include/esp_vfs.h b/components/vfs/include/esp_vfs.h index ab645fccf6..54aaaba26d 100644 --- a/components/vfs/include/esp_vfs.h +++ b/components/vfs/include/esp_vfs.h @@ -28,6 +28,15 @@ extern "C" { #endif +#ifndef _SYS_TYPES_FD_SET +#error "VFS should be used with FD_SETSIZE and FD_SET from sys/types.h" +#endif + +/** + * Maximum number of (global) file descriptors. + */ +#define MAX_FDS FD_SETSIZE /* for compatibility with fd_set and select() */ + /** * Maximum length of path prefix (not including zero terminator) */ @@ -43,21 +52,6 @@ extern "C" { */ #define ESP_VFS_FLAG_CONTEXT_PTR 1 -/** - * Flag which indicates that the FD space of the VFS implementation should be made - * the same as the FD space in newlib. This means that the normal masking off - * of VFS-independent fd bits is ignored and the full user-facing fd is passed to - * the VFS implementation. - * - * Set the p_minimum_fd & p_maximum_fd pointers when registering the socket in - * order to know what range of FDs can be used with the registered VFS. - * - * This is mostly useful for LWIP which shares the socket FD space with - * socket-specific functions. - * - */ -#define ESP_VFS_FLAG_SHARED_FD_SPACE 2 - /** * @brief VFS definition structure * @@ -81,7 +75,7 @@ extern "C" { */ typedef struct { - int flags; /*!< ESP_VFS_FLAG_CONTEXT_PTR or ESP_VFS_FLAG_DEFAULT, plus optionally ESP_VFS_FLAG_SHARED_FD_SPACE */ + int flags; /*!< ESP_VFS_FLAG_CONTEXT_PTR or ESP_VFS_FLAG_DEFAULT */ union { ssize_t (*write_p)(void* p, int fd, const void * data, size_t size); ssize_t (*write)(int fd, const void * data, size_t size); @@ -193,19 +187,20 @@ esp_err_t esp_vfs_register(const char* base_path, const esp_vfs_t* vfs, void* ct /** * Special case function for registering a VFS that uses a method other than - * open() to open new file descriptors. + * open() to open new file descriptors from the interval flags. - * @param p_max_fd If non-NULL, on success this variable is written with one higher than the maximum (global/user-facing) FD that this VFS will use. This is useful when ESP_VFS_FLAG_SHARED_FD_SPACE is set in vfs->flags. + * @param min_fd The smallest file descriptor this VFS will use. + * @param max_fd Upper boundary for file descriptors this VFS will use (the biggest file descriptor plus one). * * @return ESP_OK if successful, ESP_ERR_NO_MEM if too many VFSes are - * registered. + * registered, ESP_ERR_INVALID_ARG if the file descriptor boundaries + * are incorrect. */ -esp_err_t esp_vfs_register_socket_space(const esp_vfs_t *vfs, void *ctx, int *p_min_fd, int *p_max_fd); +esp_err_t esp_vfs_register_fd_range(const esp_vfs_t *vfs, void *ctx, int min_fd, int max_fd); /** * Unregister a virtual filesystem for given path prefix @@ -233,10 +228,8 @@ int esp_vfs_unlink(struct _reent *r, const char *path); int esp_vfs_rename(struct _reent *r, const char *src, const char *dst); /**@}*/ - #ifdef __cplusplus } // extern "C" #endif - #endif //__ESP_VFS_H__ diff --git a/components/vfs/test/test_vfs_fd.c b/components/vfs/test/test_vfs_fd.c new file mode 100644 index 0000000000..a3c6236534 --- /dev/null +++ b/components/vfs/test/test_vfs_fd.c @@ -0,0 +1,261 @@ +// 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 +#include +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.h" +#include "esp_vfs.h" +#include "unity.h" +#include "esp_log.h" + +#define VFS_PREF1 "/vfs1" +#define VFS_PREF2 "/vfs2" +#define FILE1 "/file1" + +typedef struct { + const char *path; + int fd; +} collision_test_vfs_param_t; + +static int collision_test_vfs_open(void* ctx, const char * path, int flags, int mode) +{ + const collision_test_vfs_param_t *param = (collision_test_vfs_param_t *) ctx; + if (strcmp(param->path, path) == 0) { + return param->fd; + } + errno = ENOENT; + return -1; +} + +static int collision_test_vfs_close(void* ctx, int fd) +{ + const collision_test_vfs_param_t *param = (collision_test_vfs_param_t *) ctx; + if (fd == param->fd) { + return 0; + } + errno = EBADF; + return -1; +} + +TEST_CASE("FDs from different VFSs don't collide", "[vfs]") +{ + collision_test_vfs_param_t param = { + .path = FILE1, + .fd = 1, + }; + + esp_vfs_t desc = { + .flags = ESP_VFS_FLAG_CONTEXT_PTR, + .open_p = collision_test_vfs_open, + .close_p = collision_test_vfs_close, + }; + TEST_ESP_OK( esp_vfs_register(VFS_PREF1, &desc, ¶m) ); + TEST_ESP_OK( esp_vfs_register(VFS_PREF2, &desc, ¶m) ); + + const int fd1 = open(VFS_PREF1 FILE1, 0, 0); + const int fd2 = open(VFS_PREF2 FILE1, 0, 0); + + TEST_ASSERT_NOT_EQUAL(fd1, -1); + TEST_ASSERT_NOT_EQUAL(fd2, -1); + // Both VFS drivers return local FD 1 but the global FDs returned by + // open() should not be the same + TEST_ASSERT_NOT_EQUAL(fd1, fd2); + + TEST_ASSERT_NOT_EQUAL(close(fd1), -1); + TEST_ASSERT_NOT_EQUAL(close(fd2), -1); + + TEST_ESP_OK( esp_vfs_unregister(VFS_PREF1) ); + TEST_ESP_OK( esp_vfs_unregister(VFS_PREF2) ); +} + +#define FILE2 "/file2" +#define FILE3 "/file3" +#define FILE4 "/file4" +#define CONCURRENT_TEST_STACK_SIZE (2*1024) +#define CONCURRENT_TEST_MAX_WAIT (1000 / portTICK_PERIOD_MS) + +typedef struct { + const char *path; + SemaphoreHandle_t done; +} concurrent_test_task_param_t; + +typedef struct { + const char *path; + int local_fd; +} concurrent_test_path_to_fd_t; + +static concurrent_test_path_to_fd_t concurrent_test_path_to_fd[] = { + { .path = FILE1, .local_fd = 1 }, + { .path = FILE2, .local_fd = 2 }, + { .path = FILE3, .local_fd = 3 }, + { .path = FILE4, .local_fd = 4 }, +}; + +static int concurrent_test_vfs_open(const char * path, int flags, int mode) +{ + for (int i = 0; i < sizeof(concurrent_test_path_to_fd)/sizeof(concurrent_test_path_to_fd[0]); ++i) { + if (strcmp(concurrent_test_path_to_fd[i].path, path) == 0) { + // This behaves like UART: opening the same file gives always the + // same local FD (even when opening at the same time multiple FDs) + return concurrent_test_path_to_fd[i].local_fd; + } + } + + errno = ENOENT; + return -1; +} + +static int concurrent_test_vfs_close(int fd) +{ + for (int i = 0; i < sizeof(concurrent_test_path_to_fd)/sizeof(concurrent_test_path_to_fd[0]); ++i) { + if (concurrent_test_path_to_fd[i].local_fd == fd) { + return 0; + } + } + errno = EBADF; + return -1; +} + +static inline void test_delay_rand_ms(int ms) +{ + vTaskDelay((rand() % ms) / portTICK_PERIOD_MS); +} + +static void concurrent_task(void *param) +{ + concurrent_test_task_param_t *task_param = (concurrent_test_task_param_t *) param; + + test_delay_rand_ms(10); + for (int i = 0; i < 10; ++i) { + const int global_fd = open(task_param->path, 0, 0); + TEST_ASSERT_NOT_EQUAL(global_fd, -1); + test_delay_rand_ms(10); + TEST_ASSERT_NOT_EQUAL(close(global_fd), -1); + test_delay_rand_ms(10); + } + xSemaphoreGive(task_param->done); + vTaskDelete(NULL); +} + +TEST_CASE("VFS can handle concurrent open/close requests", "[vfs]") +{ + esp_vfs_t desc = { + .flags = ESP_VFS_FLAG_DEFAULT, + .open = concurrent_test_vfs_open, + .close = concurrent_test_vfs_close, + }; + + TEST_ESP_OK( esp_vfs_register(VFS_PREF1, &desc, NULL) ); + + concurrent_test_task_param_t param1 = { .path = VFS_PREF1 FILE1, .done = xSemaphoreCreateBinary() }; + concurrent_test_task_param_t param2 = { .path = VFS_PREF1 FILE1, .done = xSemaphoreCreateBinary() }; + concurrent_test_task_param_t param3 = { .path = VFS_PREF1 FILE2, .done = xSemaphoreCreateBinary() }; + concurrent_test_task_param_t param4 = { .path = VFS_PREF1 FILE2, .done = xSemaphoreCreateBinary() }; + concurrent_test_task_param_t param5 = { .path = VFS_PREF1 FILE3, .done = xSemaphoreCreateBinary() }; + concurrent_test_task_param_t param6 = { .path = VFS_PREF1 FILE3, .done = xSemaphoreCreateBinary() }; + concurrent_test_task_param_t param7 = { .path = VFS_PREF1 FILE4, .done = xSemaphoreCreateBinary() }; + concurrent_test_task_param_t param8 = { .path = VFS_PREF1 FILE4, .done = xSemaphoreCreateBinary() }; + + TEST_ASSERT_NOT_NULL(param1.done); + TEST_ASSERT_NOT_NULL(param2.done); + TEST_ASSERT_NOT_NULL(param3.done); + TEST_ASSERT_NOT_NULL(param4.done); + TEST_ASSERT_NOT_NULL(param5.done); + TEST_ASSERT_NOT_NULL(param6.done); + TEST_ASSERT_NOT_NULL(param7.done); + TEST_ASSERT_NOT_NULL(param8.done); + + const int cpuid0 = 0; + const int cpuid1 = portNUM_PROCESSORS - 1; + + srand(time(NULL)); + + xTaskCreatePinnedToCore(concurrent_task, "t1", CONCURRENT_TEST_STACK_SIZE, ¶m1, 3, NULL, cpuid0); + xTaskCreatePinnedToCore(concurrent_task, "t2", CONCURRENT_TEST_STACK_SIZE, ¶m2, 3, NULL, cpuid1); + xTaskCreatePinnedToCore(concurrent_task, "t3", CONCURRENT_TEST_STACK_SIZE, ¶m3, 3, NULL, cpuid0); + xTaskCreatePinnedToCore(concurrent_task, "t4", CONCURRENT_TEST_STACK_SIZE, ¶m4, 3, NULL, cpuid1); + xTaskCreatePinnedToCore(concurrent_task, "t5", CONCURRENT_TEST_STACK_SIZE, ¶m5, 3, NULL, cpuid0); + xTaskCreatePinnedToCore(concurrent_task, "t6", CONCURRENT_TEST_STACK_SIZE, ¶m6, 3, NULL, cpuid1); + xTaskCreatePinnedToCore(concurrent_task, "t7", CONCURRENT_TEST_STACK_SIZE, ¶m7, 3, NULL, cpuid0); + xTaskCreatePinnedToCore(concurrent_task, "t8", CONCURRENT_TEST_STACK_SIZE, ¶m8, 3, NULL, cpuid1); + + TEST_ASSERT_EQUAL(xSemaphoreTake(param1.done, CONCURRENT_TEST_MAX_WAIT), pdTRUE); + TEST_ASSERT_EQUAL(xSemaphoreTake(param2.done, CONCURRENT_TEST_MAX_WAIT), pdTRUE); + TEST_ASSERT_EQUAL(xSemaphoreTake(param3.done, CONCURRENT_TEST_MAX_WAIT), pdTRUE); + TEST_ASSERT_EQUAL(xSemaphoreTake(param4.done, CONCURRENT_TEST_MAX_WAIT), pdTRUE); + TEST_ASSERT_EQUAL(xSemaphoreTake(param5.done, CONCURRENT_TEST_MAX_WAIT), pdTRUE); + TEST_ASSERT_EQUAL(xSemaphoreTake(param6.done, CONCURRENT_TEST_MAX_WAIT), pdTRUE); + TEST_ASSERT_EQUAL(xSemaphoreTake(param7.done, CONCURRENT_TEST_MAX_WAIT), pdTRUE); + TEST_ASSERT_EQUAL(xSemaphoreTake(param8.done, CONCURRENT_TEST_MAX_WAIT), pdTRUE); + + vSemaphoreDelete(param1.done); + vSemaphoreDelete(param2.done); + vSemaphoreDelete(param3.done); + vSemaphoreDelete(param4.done); + vSemaphoreDelete(param5.done); + vSemaphoreDelete(param6.done); + vSemaphoreDelete(param7.done); + vSemaphoreDelete(param8.done); + + TEST_ESP_OK( esp_vfs_unregister(VFS_PREF1) ); +} + +static int time_test_vfs_open(const char *path, int flags, int mode) +{ + return 1; +} + +static int time_test_vfs_close(int fd) +{ + return 1; +} + +int time_test_vfs_write(int fd, const void *data, size_t size) +{ + return size; +} + +TEST_CASE("Open & write & close through VFS passes performance test", "[vfs]") +{ + esp_vfs_t desc = { + .flags = ESP_VFS_FLAG_DEFAULT, + .open = time_test_vfs_open, + .close = time_test_vfs_close, + .write = time_test_vfs_write, + }; + + TEST_ESP_OK( esp_vfs_register(VFS_PREF1, &desc, NULL) ); + + const int64_t begin = esp_timer_get_time(); + const int iter_count = 1000; + + for (int i = 0; i < iter_count; ++i) { + const int fd = open(VFS_PREF1 FILE1, 0, 0); + TEST_ASSERT_NOT_EQUAL(fd, -1); + + write(fd, "a", 1); + + TEST_ASSERT_NOT_EQUAL(close(fd), -1); + } + + const int64_t time_diff_us = esp_timer_get_time() - begin; + const int ns_per_iter = (int) (time_diff_us * 1000 / iter_count); + TEST_ESP_OK( esp_vfs_unregister(VFS_PREF1) ); + TEST_PERFORMANCE_LESS_THAN(VFS_OPEN_WRITE_CLOSE_TIME, "%dns", ns_per_iter); +} diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index 5dbd462c2e..2e84571b3e 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -19,33 +19,27 @@ #include #include #include +#include #include #include "esp_vfs.h" #include "esp_log.h" -/* - * File descriptors visible by the applications are composed of two parts. - * Lower CONFIG_MAX_FD_BITS bits are used for the actual file descriptor. - * Next (16 - CONFIG_MAX_FD_BITS - 1) bits are used to identify the VFS this - * descriptor corresponds to. - * Highest bit is zero. - * We can only use 16 bits because newlib stores file descriptor as short int. - */ - -#ifndef CONFIG_MAX_FD_BITS -#define CONFIG_MAX_FD_BITS 12 -#endif - -#define MAX_VFS_ID_BITS (16 - CONFIG_MAX_FD_BITS - 1) -// mask of actual file descriptor (e.g. 0x00000fff) -#define VFS_FD_MASK ((1 << CONFIG_MAX_FD_BITS) - 1) -// max number of VFS entries -#define VFS_MAX_COUNT ((1 << MAX_VFS_ID_BITS) - 1) -// mask of VFS id (e.g. 0x00007000) -#define VFS_INDEX_MASK (VFS_MAX_COUNT << CONFIG_MAX_FD_BITS) -#define VFS_INDEX_S CONFIG_MAX_FD_BITS - +#define VFS_MAX_COUNT 8 /* max number of VFS entries (registered filesystems) */ #define LEN_PATH_PREFIX_IGNORED SIZE_MAX /* special length value for VFS which is never recognised by open() */ +#define FD_TABLE_ENTRY_UNUSED (fd_table_t) { .permanent = false, .vfs_index = -1, .local_fd = -1 } + +typedef uint8_t local_fd_t; +_Static_assert((1 << (sizeof(local_fd_t)*8)) >= MAX_FDS, "file descriptor type too small"); + +typedef int8_t vfs_index_t; +_Static_assert((1 << (sizeof(vfs_index_t)*8)) >= VFS_MAX_COUNT, "VFS index type too small"); +_Static_assert(((vfs_index_t) -1) < 0, "vfs_index_t must be a signed type"); + +typedef struct { + bool permanent; + vfs_index_t vfs_index; + local_fd_t local_fd; +} fd_table_t; typedef struct vfs_entry_ { esp_vfs_t vfs; // contains pointers to VFS functions @@ -58,7 +52,10 @@ typedef struct vfs_entry_ { static vfs_entry_t* s_vfs[VFS_MAX_COUNT] = { 0 }; static size_t s_vfs_count = 0; -static esp_err_t esp_vfs_register_common(const char* base_path, size_t len, const esp_vfs_t* vfs, void* ctx, int *p_minimum_fd, int *p_maximum_fd) +static fd_table_t s_fd_table[MAX_FDS] = { [0 ... MAX_FDS-1] = FD_TABLE_ENTRY_UNUSED }; +static _lock_t s_fd_table_lock; + +static esp_err_t esp_vfs_register_common(const char* base_path, size_t len, const esp_vfs_t* vfs, void* ctx, int *vfs_index) { if (len != LEN_PATH_PREFIX_IGNORED) { if ((len != 0 && len < 2) || (len > ESP_VFS_PATH_MAX)) { @@ -96,11 +93,8 @@ static esp_err_t esp_vfs_register_common(const char* base_path, size_t len, cons entry->ctx = ctx; entry->offset = index; - if (p_minimum_fd != NULL) { - *p_minimum_fd = index << VFS_INDEX_S; - } - if (p_maximum_fd != NULL) { - *p_maximum_fd = (index + 1) << VFS_INDEX_S; + if (vfs_index) { + *vfs_index = index; } return ESP_OK; @@ -108,12 +102,40 @@ static esp_err_t esp_vfs_register_common(const char* base_path, size_t len, cons esp_err_t esp_vfs_register(const char* base_path, const esp_vfs_t* vfs, void* ctx) { - return esp_vfs_register_common(base_path, strlen(base_path), vfs, ctx, NULL, NULL); + return esp_vfs_register_common(base_path, strlen(base_path), vfs, ctx, NULL); } -esp_err_t esp_vfs_register_socket_space(const esp_vfs_t *vfs, void *ctx, int *p_min_fd, int *p_max_fd) +esp_err_t esp_vfs_register_fd_range(const esp_vfs_t *vfs, void *ctx, int min_fd, int max_fd) { - return esp_vfs_register_common("", LEN_PATH_PREFIX_IGNORED, vfs, ctx, p_min_fd, p_max_fd); + if (min_fd < 0 || max_fd < 0 || min_fd > MAX_FDS || max_fd > MAX_FDS || min_fd > max_fd) { + return ESP_ERR_INVALID_ARG; + } + + int index = -1; + esp_err_t ret = esp_vfs_register_common("", LEN_PATH_PREFIX_IGNORED, vfs, ctx, &index); + + if (ret == ESP_OK) { + _lock_acquire(&s_fd_table_lock); + for (int i = min_fd; i < max_fd; ++i) { + if (s_fd_table[i].vfs_index != -1) { + free(s_vfs[i]); + s_vfs[i] = NULL; + for (int j = min_fd; j < i; ++j) { + if (s_fd_table[j].vfs_index == index) { + s_fd_table[j] = FD_TABLE_ENTRY_UNUSED; + } + } + _lock_release(&s_fd_table_lock); + return ESP_ERR_INVALID_ARG; + } + s_fd_table[i].permanent = true; + s_fd_table[i].vfs_index = index; + s_fd_table[i].local_fd = i; + } + _lock_release(&s_fd_table_lock); + } + + return ret; } esp_err_t esp_vfs_unregister(const char* base_path) @@ -126,28 +148,55 @@ esp_err_t esp_vfs_unregister(const char* base_path) if (memcmp(base_path, vfs->path_prefix, vfs->path_prefix_len) == 0) { free(vfs); s_vfs[i] = NULL; + + _lock_acquire(&s_fd_table_lock); + // Delete all references from the FD lookup-table + for (int j = 0; j < MAX_FDS; ++j) { + if (s_fd_table[j].vfs_index == i) { + s_fd_table[j] = FD_TABLE_ENTRY_UNUSED; + } + } + _lock_release(&s_fd_table_lock); + return ESP_OK; } } return ESP_ERR_INVALID_STATE; } -static const vfs_entry_t* get_vfs_for_fd(int fd) +static inline const vfs_entry_t *get_vfs_for_index(int index) { - int index = ((fd & VFS_INDEX_MASK) >> VFS_INDEX_S); - if (index >= s_vfs_count) { + if (index < 0 || index >= s_vfs_count) { return NULL; + } else { + return s_vfs[index]; } - return s_vfs[index]; } -static int translate_fd(const vfs_entry_t* vfs, int fd) +static inline bool fd_valid(int fd) { - if (vfs->vfs.flags & ESP_VFS_FLAG_SHARED_FD_SPACE) { - return fd; - } else { - return fd & VFS_FD_MASK; + return (fd < MAX_FDS) && (fd >= 0); +} + +static const vfs_entry_t *get_vfs_for_fd(int fd) +{ + const vfs_entry_t *vfs = NULL; + if (fd_valid(fd)) { + const int index = s_fd_table[fd].vfs_index; // single read -> no locking is required + vfs = get_vfs_for_index(index); } + return vfs; +} + +static inline int get_local_fd(const vfs_entry_t *vfs, int fd) +{ + int local_fd = -1; + + if (vfs && fd_valid(fd)) { + local_fd = s_fd_table[fd].local_fd; // single read -> no locking is required + } + + return local_fd; } static const char* translate_path(const vfs_entry_t* vfs, const char* src_path) @@ -248,28 +297,44 @@ static const vfs_entry_t* get_vfs_for_path(const char* path) int esp_vfs_open(struct _reent *r, const char * path, int flags, int mode) { - const vfs_entry_t* vfs = get_vfs_for_path(path); + const vfs_entry_t *vfs = get_vfs_for_path(path); if (vfs == NULL) { __errno_r(r) = ENOENT; return -1; } - const char* path_within_vfs = translate_path(vfs, path); - int ret; - CHECK_AND_CALL(ret, r, vfs, open, path_within_vfs, flags, mode); - if (ret < 0) { - return ret; + const char *path_within_vfs = translate_path(vfs, path); + int fd_within_vfs; + CHECK_AND_CALL(fd_within_vfs, r, vfs, open, path_within_vfs, flags, mode); + if (fd_within_vfs >= 0) { + _lock_acquire(&s_fd_table_lock); + for (int i = 0; i < MAX_FDS; ++i) { + if (s_fd_table[i].vfs_index == -1) { + s_fd_table[i].permanent = false; + s_fd_table[i].vfs_index = vfs->offset; + s_fd_table[i].local_fd = fd_within_vfs; + _lock_release(&s_fd_table_lock); + return i; + } + } + _lock_release(&s_fd_table_lock); + int ret; + CHECK_AND_CALL(ret, r, vfs, close, fd_within_vfs); + (void) ret; // remove "set but not used" warning + __errno_r(r) = ENOMEM; + return -1; } - return ret + (vfs->offset << VFS_INDEX_S); + __errno_r(r) = ENOENT; + return -1; } ssize_t esp_vfs_write(struct _reent *r, int fd, const void * data, size_t size) { const vfs_entry_t* vfs = get_vfs_for_fd(fd); - if (vfs == NULL) { + const int local_fd = get_local_fd(vfs, fd); + if (vfs == NULL || local_fd < 0) { __errno_r(r) = EBADF; return -1; } - int local_fd = translate_fd(vfs, fd); ssize_t ret; CHECK_AND_CALL(ret, r, vfs, write, local_fd, data, size); return ret; @@ -278,11 +343,11 @@ ssize_t esp_vfs_write(struct _reent *r, int fd, const void * data, size_t size) off_t esp_vfs_lseek(struct _reent *r, int fd, off_t size, int mode) { const vfs_entry_t* vfs = get_vfs_for_fd(fd); - if (vfs == NULL) { + const int local_fd = get_local_fd(vfs, fd); + if (vfs == NULL || local_fd < 0) { __errno_r(r) = EBADF; return -1; } - int local_fd = translate_fd(vfs, fd); off_t ret; CHECK_AND_CALL(ret, r, vfs, lseek, local_fd, size, mode); return ret; @@ -291,11 +356,11 @@ off_t esp_vfs_lseek(struct _reent *r, int fd, off_t size, int mode) ssize_t esp_vfs_read(struct _reent *r, int fd, void * dst, size_t size) { const vfs_entry_t* vfs = get_vfs_for_fd(fd); - if (vfs == NULL) { + const int local_fd = get_local_fd(vfs, fd); + if (vfs == NULL || local_fd < 0) { __errno_r(r) = EBADF; return -1; } - int local_fd = translate_fd(vfs, fd); ssize_t ret; CHECK_AND_CALL(ret, r, vfs, read, local_fd, dst, size); return ret; @@ -305,24 +370,30 @@ ssize_t esp_vfs_read(struct _reent *r, int fd, void * dst, size_t size) int esp_vfs_close(struct _reent *r, int fd) { const vfs_entry_t* vfs = get_vfs_for_fd(fd); - if (vfs == NULL) { + const int local_fd = get_local_fd(vfs, fd); + if (vfs == NULL || local_fd < 0) { __errno_r(r) = EBADF; return -1; } - int local_fd = translate_fd(vfs, fd); int ret; CHECK_AND_CALL(ret, r, vfs, close, local_fd); + + _lock_acquire(&s_fd_table_lock); + if (!s_fd_table[fd].permanent) { + s_fd_table[fd] = FD_TABLE_ENTRY_UNUSED; + } + _lock_release(&s_fd_table_lock); return ret; } int esp_vfs_fstat(struct _reent *r, int fd, struct stat * st) { const vfs_entry_t* vfs = get_vfs_for_fd(fd); - if (vfs == NULL) { + const int local_fd = get_local_fd(vfs, fd); + if (vfs == NULL || local_fd < 0) { __errno_r(r) = EBADF; return -1; } - int local_fd = translate_fd(vfs, fd); int ret; CHECK_AND_CALL(ret, r, vfs, fstat, local_fd, st); return ret; @@ -404,14 +475,14 @@ DIR* opendir(const char* name) DIR* ret; CHECK_AND_CALLP(ret, r, vfs, opendir, path_within_vfs); if (ret != NULL) { - ret->dd_vfs_idx = vfs->offset << VFS_INDEX_S; + ret->dd_vfs_idx = vfs->offset; } return ret; } struct dirent* readdir(DIR* pdir) { - const vfs_entry_t* vfs = get_vfs_for_fd(pdir->dd_vfs_idx); + const vfs_entry_t* vfs = get_vfs_for_index(pdir->dd_vfs_idx); struct _reent* r = __getreent(); if (vfs == NULL) { __errno_r(r) = EBADF; @@ -424,7 +495,7 @@ struct dirent* readdir(DIR* pdir) int readdir_r(DIR* pdir, struct dirent* entry, struct dirent** out_dirent) { - const vfs_entry_t* vfs = get_vfs_for_fd(pdir->dd_vfs_idx); + const vfs_entry_t* vfs = get_vfs_for_index(pdir->dd_vfs_idx); struct _reent* r = __getreent(); if (vfs == NULL) { errno = EBADF; @@ -437,7 +508,7 @@ int readdir_r(DIR* pdir, struct dirent* entry, struct dirent** out_dirent) long telldir(DIR* pdir) { - const vfs_entry_t* vfs = get_vfs_for_fd(pdir->dd_vfs_idx); + const vfs_entry_t* vfs = get_vfs_for_index(pdir->dd_vfs_idx); struct _reent* r = __getreent(); if (vfs == NULL) { errno = EBADF; @@ -450,7 +521,7 @@ long telldir(DIR* pdir) void seekdir(DIR* pdir, long loc) { - const vfs_entry_t* vfs = get_vfs_for_fd(pdir->dd_vfs_idx); + const vfs_entry_t* vfs = get_vfs_for_index(pdir->dd_vfs_idx); struct _reent* r = __getreent(); if (vfs == NULL) { errno = EBADF; @@ -466,7 +537,7 @@ void rewinddir(DIR* pdir) int closedir(DIR* pdir) { - const vfs_entry_t* vfs = get_vfs_for_fd(pdir->dd_vfs_idx); + const vfs_entry_t* vfs = get_vfs_for_index(pdir->dd_vfs_idx); struct _reent* r = __getreent(); if (vfs == NULL) { errno = EBADF; @@ -508,12 +579,12 @@ int rmdir(const char* name) int fcntl(int fd, int cmd, ...) { const vfs_entry_t* vfs = get_vfs_for_fd(fd); + const int local_fd = get_local_fd(vfs, fd); struct _reent* r = __getreent(); - if (vfs == NULL) { + if (vfs == NULL || local_fd < 0) { __errno_r(r) = EBADF; return -1; } - int local_fd = translate_fd(vfs, fd); int ret; va_list args; va_start(args, cmd); @@ -525,12 +596,12 @@ int fcntl(int fd, int cmd, ...) int ioctl(int fd, int cmd, ...) { const vfs_entry_t* vfs = get_vfs_for_fd(fd); + const int local_fd = get_local_fd(vfs, fd); struct _reent* r = __getreent(); - if (vfs == NULL) { + if (vfs == NULL || local_fd < 0) { __errno_r(r) = EBADF; return -1; } - int local_fd = translate_fd(vfs, fd); int ret; va_list args; va_start(args, cmd); @@ -542,12 +613,12 @@ int ioctl(int fd, int cmd, ...) int fsync(int fd) { const vfs_entry_t* vfs = get_vfs_for_fd(fd); + const int local_fd = get_local_fd(vfs, fd); struct _reent* r = __getreent(); - if (vfs == NULL) { + if (vfs == NULL || local_fd < 0) { __errno_r(r) = EBADF; return -1; } - int local_fd = translate_fd(vfs, fd); int ret; CHECK_AND_CALL(ret, r, vfs, fsync, local_fd); return ret; diff --git a/components/vfs/vfs_uart.c b/components/vfs/vfs_uart.c index 033ff6345f..13b227aad5 100644 --- a/components/vfs/vfs_uart.c +++ b/components/vfs/vfs_uart.c @@ -291,22 +291,22 @@ void esp_vfs_dev_uart_set_tx_line_endings(esp_line_endings_t mode) s_tx_mode = mode; } -void esp_vfs_dev_uart_use_nonblocking(int fd) +void esp_vfs_dev_uart_use_nonblocking(int uart_num) { - _lock_acquire_recursive(&s_uart_read_locks[fd]); - _lock_acquire_recursive(&s_uart_write_locks[fd]); - s_uart_tx_func[fd] = uart_tx_char; - s_uart_rx_func[fd] = uart_rx_char; - _lock_release_recursive(&s_uart_write_locks[fd]); - _lock_release_recursive(&s_uart_read_locks[fd]); + _lock_acquire_recursive(&s_uart_read_locks[uart_num]); + _lock_acquire_recursive(&s_uart_write_locks[uart_num]); + s_uart_tx_func[uart_num] = uart_tx_char; + s_uart_rx_func[uart_num] = uart_rx_char; + _lock_release_recursive(&s_uart_write_locks[uart_num]); + _lock_release_recursive(&s_uart_read_locks[uart_num]); } -void esp_vfs_dev_uart_use_driver(int fd) +void esp_vfs_dev_uart_use_driver(int uart_num) { - _lock_acquire_recursive(&s_uart_read_locks[fd]); - _lock_acquire_recursive(&s_uart_write_locks[fd]); - s_uart_tx_func[fd] = uart_tx_char_via_driver; - s_uart_rx_func[fd] = uart_rx_char_via_driver; - _lock_release_recursive(&s_uart_write_locks[fd]); - _lock_release_recursive(&s_uart_read_locks[fd]); + _lock_acquire_recursive(&s_uart_read_locks[uart_num]); + _lock_acquire_recursive(&s_uart_write_locks[uart_num]); + s_uart_tx_func[uart_num] = uart_tx_char_via_driver; + s_uart_rx_func[uart_num] = uart_rx_char_via_driver; + _lock_release_recursive(&s_uart_write_locks[uart_num]); + _lock_release_recursive(&s_uart_read_locks[uart_num]); } From 80ff8d55ace6b15aab2fec77f8e727614aa99a06 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Mon, 7 May 2018 09:01:56 +0200 Subject: [PATCH 045/187] bluedroid: use the new socket registering API --- .../bt/bluedroid/btc/profile/std/spp/btc_spp.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c b/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c index 82d84b2d02..dcab978657 100644 --- a/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c +++ b/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c @@ -29,7 +29,12 @@ #include #include "esp_vfs.h" #include "esp_vfs_dev.h" +#include "lwip/opt.h" // just for LWIP_SOCKET_OFFSET +/** + * BTC_SPP_FDS is the number of file descriptors this VFS driver registers + */ +#define BTC_SPP_FDS 32 #if (defined BTC_SPP_INCLUDED && BTC_SPP_INCLUDED == TRUE) @@ -828,7 +833,7 @@ static ssize_t spp_vfs_read(int fd, void * dst, size_t size) void btc_spp_vfs_register() { esp_vfs_t vfs = { - .flags = ESP_VFS_FLAG_DEFAULT | ESP_VFS_FLAG_SHARED_FD_SPACE, + .flags = ESP_VFS_FLAG_DEFAULT, .write = spp_vfs_write, .open = NULL, .fstat = NULL, @@ -836,8 +841,15 @@ void btc_spp_vfs_register() .read = spp_vfs_read, .fcntl = NULL }; - ESP_ERROR_CHECK(esp_vfs_register_socket_space(&vfs, NULL, &spp_local_param.spp_min_fd, &spp_local_param.spp_max_fd)); + // File descriptors from LWIP_SOCKET_OFFSET to MAX_FDS-1 are registered + // for sockets. So here we register from (LWIP_SOCKET_OFFSET - BTC_SPP_FDS) + // to (LWIP_SOCKET_OFFSET-1) leaving unregistered from 0 to + // .(LWIP_SOCKET_OFFSET - BTC_SPP_FDS - 1). + spp_local_param.spp_min_fd = LWIP_SOCKET_OFFSET - BTC_SPP_FDS; + assert(spp_local_param.spp_min_fd >= 0); //TODO return error instead + spp_local_param.spp_max_fd = LWIP_SOCKET_OFFSET; + ESP_ERROR_CHECK(esp_vfs_register_fd_range(&vfs, NULL, spp_local_param.spp_min_fd, spp_local_param.spp_max_fd));//TODO return error if fails spp_local_param.spp_fd = spp_local_param.spp_min_fd; } -#endif ///defined BTC_SPP_INCLUDED && BTC_SPP_INCLUDED == TRUE \ No newline at end of file +#endif ///defined BTC_SPP_INCLUDED && BTC_SPP_INCLUDED == TRUE From 6238459dd77487bcac244ca5360932b9043584c3 Mon Sep 17 00:00:00 2001 From: Anuj Deshpande Date: Mon, 7 May 2018 12:24:20 +0530 Subject: [PATCH 046/187] docs: Fix broken link in nvs and jtag example - Closes https://github.com/espressif/esp-idf/issues/1922 --- examples/storage/nvs_rw_blob/README.md | 2 +- examples/storage/nvs_rw_value/README.md | 2 +- examples/system/app_trace_to_host/README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/storage/nvs_rw_blob/README.md b/examples/storage/nvs_rw_blob/README.md index b39c289038..8fe7f30d88 100644 --- a/examples/storage/nvs_rw_blob/README.md +++ b/examples/storage/nvs_rw_blob/README.md @@ -9,6 +9,6 @@ Example also shows how to implement diagnostics if read / write operation was su If not done already, consider checking simpler example *storage/nvs_rw_value*, that has been used as a starting point for preparing this one. -Detailed functional description of NVS and API is provided in [documentation](https://esp-idf.readthedocs.io/en/latest/api-reference/nvs_flash.html). +Detailed functional description of NVS and API is provided in [documentation](https://esp-idf.readthedocs.io/en/latest/api-reference/storage/nvs_flash.html). See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/storage/nvs_rw_value/README.md b/examples/storage/nvs_rw_value/README.md index eec9f3163e..4cdee4a406 100644 --- a/examples/storage/nvs_rw_value/README.md +++ b/examples/storage/nvs_rw_value/README.md @@ -8,6 +8,6 @@ Example also shows how to check if read / write operation was successful, or cer Check another example *storage/nvs_rw_blob*, that shows how to read and write variable length binary data (blob). -Detailed functional description of NVS and API is provided in [documentation](https://esp-idf.readthedocs.io/en/latest/api-reference/nvs_flash.html). +Detailed functional description of NVS and API is provided in [documentation](https://esp-idf.readthedocs.io/en/latest/api-reference/storage/nvs_flash.html). See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/system/app_trace_to_host/README.md b/examples/system/app_trace_to_host/README.md index d88371af8b..c7955ceb80 100644 --- a/examples/system/app_trace_to_host/README.md +++ b/examples/system/app_trace_to_host/README.md @@ -87,7 +87,7 @@ To run the example and retrieve the log from the host, do the following: 1. Connect JTAG interface to ESP32 board, power up both JTAG and ESP32. For details how to setup JTAG interface see [JTAG Debugging](https://esp-idf.readthedocs.io/en/latest/api-guides/jtag-debugging/index.html). -2. [Run OpenOCD](https://esp-idf.readthedocs.io/en/latest/api-guides/jtag-debugging/index.html#run-openocd). If you are using the [binary distribution of OpenOCD](https://esp-idf.readthedocs.io/en/latest/api-guides/jtag-debugging/index.html#jtag-debugging-setup-openocd) and one of versions of [ESP-WROVER-KIT](https://esp-idf.readthedocs.io/en/latest/hw-reference/modules-and-boards.html#esp32-wrover-kit-v1-esp32-devkitj-v1), respective command line will look as follows: +2. [Run OpenOCD](https://esp-idf.readthedocs.io/en/latest/api-guides/jtag-debugging/index.html#run-openocd). If you are using the [binary distribution of OpenOCD](https://esp-idf.readthedocs.io/en/latest/api-guides/jtag-debugging/index.html#jtag-debugging-setup-openocd) and one of versions of [ESP-WROVER-KIT](https://esp-idf.readthedocs.io/en/latest/hw-reference/modules-and-boards.html#esp-wrover-kit-v3), respective command line will look as follows: ``` cd ~/esp/openocd-esp32 From 8cd9deed5c77c9870082f90a32a80cf44b5bf4a2 Mon Sep 17 00:00:00 2001 From: Tian Hao Date: Sat, 5 May 2018 12:50:13 +0800 Subject: [PATCH 047/187] component/esp32 : improve wifi and bluetooth coexistence performance 1. update coexistence and wifi libraries. Coexist version update to v0.9.2 2. Cancel the restriction of use AMPDU when SW_COEXIST_ENABLE is y. --- components/esp32/Kconfig | 14 ++++---------- components/esp32/lib | 2 +- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index 3c12667220..c820ba7028 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -835,9 +835,9 @@ choice SW_COEXIST_PREFERENCE default SW_COEXIST_PREFERENCE_BALANCE help Choose Bluetooth/WiFi/Balance for different preference. - If choose WiFi, it will make WiFi performance better. Such, keep WiFi Audio more smooth. - If choose Bluetooth, it will make Bluetooth performance better. Such, keep Bluetooth(A2DP) Audio more smooth. - If choose Balance, the performance of WiFi and bluetooth will be balance. It's default. + If choose WiFi, it will make WiFi performance better. Such, keep WiFi Audio more fluent. + If choose Bluetooth, it will make Bluetooth performance better. Such, keep Bluetooth(A2DP) Audio more fluent. + If choose Balance, the performance of WiFi and bluetooth will be balance. It's default. Normally, just choose balance, the A2DP audio can play fluently, too. Except config preference in menuconfig, you can also call esp_coex_preference_set() dynamically. config SW_COEXIST_PREFERENCE_WIFI @@ -948,33 +948,27 @@ config ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM config ESP32_WIFI_AMPDU_TX_ENABLED bool "WiFi AMPDU TX" - default y if SW_COEXIST_ENABLE default y help Select this option to enable AMPDU TX feature - Suggest enable it when SW_COEXIST_ENABLE is defined. config ESP32_WIFI_TX_BA_WIN int "WiFi AMPDU TX BA window size" depends on ESP32_WIFI_AMPDU_TX_ENABLED range 2 32 - default 2 if SW_COEXIST_ENABLE default 6 help Set the size of WiFi Block Ack TX window. Generally a bigger value means higher throughput but more memory. Most of time we should NOT change the default value unless special reason, e.g. test the maximum UDP TX throughput with iperf etc. For iperf test in shieldbox, the recommended - value is 9~12. If SW_COEXIST_ENABLE is defined, suggest value is 2. + value is 9~12. config ESP32_WIFI_AMPDU_RX_ENABLED bool "WiFi AMPDU RX" - depends on !SW_COEXIST_ENABLE - default y default y help Select this option to enable AMPDU RX feature - Suggest disable this option when SW_COEXIST_ENABLE is enabled. It can improve WiFi RX performance normally. config ESP32_WIFI_RX_BA_WIN int "WiFi AMPDU RX BA window size" diff --git a/components/esp32/lib b/components/esp32/lib index e21cf48e26..f46327a4c6 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit e21cf48e265f86878d89e31457eb0f1722b410d8 +Subproject commit f46327a4c68b1e4e6a3fb3febd3ba3312df16ff1 From 1f085b1a3b1380b82096662e49c0fc849320e500 Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Tue, 24 Apr 2018 01:23:12 +0800 Subject: [PATCH 048/187] feat(gpio): add function allowing switching input source from GPIO back to IOMUX --- components/driver/gpio.c | 15 ++++++++++++++- components/driver/include/driver/gpio.h | 22 +++++++++++++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/components/driver/gpio.c b/components/driver/gpio.c index 9563b15066..e017cd87df 100644 --- a/components/driver/gpio.c +++ b/components/driver/gpio.c @@ -546,4 +546,17 @@ esp_err_t gpio_hold_dis(gpio_num_t gpio_num) r = ESP_ERR_NOT_SUPPORTED; } return r == ESP_OK ? ESP_OK : ESP_ERR_NOT_SUPPORTED; -} \ No newline at end of file +} + +void gpio_iomux_in(uint32_t gpio, uint32_t signal_idx) +{ + GPIO.func_in_sel_cfg[signal_idx].sig_in_sel = 0; + PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio]); +} + +void gpio_iomux_out(uint8_t gpio_num, int func, bool oen_inv) +{ + GPIO.func_out_sel_cfg[gpio_num].oen_sel = 0; + GPIO.func_out_sel_cfg[gpio_num].oen_inv_sel = oen_inv; + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], func); +} diff --git a/components/driver/include/driver/gpio.h b/components/driver/include/driver/gpio.h index f8900d32e8..d5cb7c08c0 100644 --- a/components/driver/include/driver/gpio.h +++ b/components/driver/include/driver/gpio.h @@ -31,11 +31,11 @@ extern "C" { #define GPIO_SEL_0 (BIT(0)) /*!< Pin 0 selected */ #define GPIO_SEL_1 (BIT(1)) /*!< Pin 1 selected */ -#define GPIO_SEL_2 (BIT(2)) /*!< Pin 2 selected +#define GPIO_SEL_2 (BIT(2)) /*!< Pin 2 selected @note There are more macros like that up to pin 39, excluding pins 20, 24 and 28..31. - They are not shown here + They are not shown here to reduce redundant information. */ /** @cond */ #define GPIO_SEL_3 (BIT(3)) /*!< Pin 3 selected */ @@ -172,7 +172,7 @@ typedef enum { GPIO_NUM_38 = 38, /*!< GPIO38, input mode only */ GPIO_NUM_39 = 39, /*!< GPIO39, input mode only */ GPIO_NUM_MAX = 40, -/** @endcond */ +/** @endcond */ } gpio_num_t; typedef enum { @@ -550,6 +550,22 @@ esp_err_t gpio_hold_en(gpio_num_t gpio_num); */ esp_err_t gpio_hold_dis(gpio_num_t gpio_num); +/** + * @brief Set pad input to a peripheral signal through the IOMUX. + * @param gpio_num GPIO number of the pad. + * @param signal_idx Peripheral signal id to input. One of the ``*_IN_IDX`` signals in ``soc/gpio_sig_map.h``. + */ +void gpio_iomux_in(uint32_t gpio_num, uint32_t signal_idx); + +/** + * @brief Set peripheral output to an GPIO pad through the IOMUX. + * @param gpio_num gpio_num GPIO number of the pad. + * @param func The function number of the peripheral pin to output pin. + * One of the ``FUNC_X_*`` of specified pin (X) in ``soc/io_mux_reg.h``. + * @param oen_inv True if the output enable needs to be inversed, otherwise False. + */ +void gpio_iomux_out(uint8_t gpio_num, int func, bool oen_inv); + #ifdef __cplusplus } #endif From 28beafc624628ab5841903478efcb10c1d0c07f4 Mon Sep 17 00:00:00 2001 From: michael Date: Tue, 24 Apr 2018 15:34:07 +0800 Subject: [PATCH 049/187] fix(spi): fix the issue that native pins don't work after SPI initialized before --- components/driver/spi_common.c | 57 ++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/components/driver/spi_common.c b/components/driver/spi_common.c index 0aab4ee026..d6a2dbd829 100644 --- a/components/driver/spi_common.c +++ b/components/driver/spi_common.c @@ -46,6 +46,9 @@ static const char *SPI_TAG = "spi"; typedef struct spi_device_t spi_device_t; +#define FUNC_SPI 1 //all pins of HSPI and VSPI shares this function number +#define FUNC_GPIO PIN_FUNC_GPIO + /* Stores a bunch of per-spi-peripheral data. */ @@ -220,7 +223,7 @@ bool spicommon_dma_chan_free(int dma_chan) /* Do the common stuff to hook up a SPI host to a bus defined by a bunch of GPIO pins. Feed it a host number and a -bus config struct and it'll set up the GPIO matrix and enable the device. If a pin is set to non-negative value, +bus config struct and it'll set up the GPIO matrix and enable the device. If a pin is set to non-negative value, it should be able to be initialized. */ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_config_t *bus_config, int dma_chan, uint32_t flags, uint32_t* flags_o) @@ -250,7 +253,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf } if (bus_config->quadhd_io_num>=0) { SPI_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(bus_config->quadhd_io_num), "spihd not valid", ESP_ERR_INVALID_ARG); - if (bus_config->quadhd_io_num != io_signal[host].spihd_native) native = false; + if (bus_config->quadhd_io_num != io_signal[host].spihd_native) native = false; } else { quad_pins_exist = false; SPI_CHECK((flags&SPICOMMON_BUSFLAG_WPHD)==0, "spihd pin required.", ESP_ERR_INVALID_ARG); @@ -277,11 +280,11 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf } else { SPI_CHECK((flags&SPICOMMON_BUSFLAG_MISO)==0, "miso pin required.", ESP_ERR_INVALID_ARG); } - //set flags for DUAL mode according to output-capability of MOSI and MISO pins. - if ( (bus_config->mosi_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(bus_config->mosi_io_num)) && + //set flags for DUAL mode according to output-capability of MOSI and MISO pins. + if ( (bus_config->mosi_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(bus_config->mosi_io_num)) && (bus_config->miso_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(bus_config->miso_io_num)) ) { temp_flag |= SPICOMMON_BUSFLAG_DUAL; - } + } //set flags for QUAD mode according to the existence of wp and hd if (quad_pins_exist) temp_flag |= SPICOMMON_BUSFLAG_WPHD; //check native pins if required. @@ -291,17 +294,32 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf //All SPI native pin selections resolve to 1, so we put that here instead of trying to figure //out which FUNC_GPIOx_xSPIxx to grab; they all are defined to 1 anyway. ESP_LOGD(SPI_TAG, "SPI%d use native pins.", host ); - if (bus_config->mosi_io_num >= 0) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->mosi_io_num], 1); - if (bus_config->miso_io_num >= 0) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->miso_io_num], 1); - if (bus_config->quadwp_io_num >= 0) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num], 1); - if (bus_config->quadhd_io_num >= 0) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num], 1); - if (bus_config->sclk_io_num >= 0) PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->sclk_io_num], 1); + if (bus_config->mosi_io_num >= 0) { + gpio_iomux_in(bus_config->mosi_io_num, io_signal[host].spid_in); + gpio_iomux_out(bus_config->mosi_io_num, FUNC_SPI, false); + } + if (bus_config->miso_io_num >= 0) { + gpio_iomux_in(bus_config->miso_io_num, io_signal[host].spiq_in); + gpio_iomux_out(bus_config->miso_io_num, FUNC_SPI, false); + } + if (bus_config->quadwp_io_num >= 0) { + gpio_iomux_in(bus_config->quadwp_io_num, io_signal[host].spiwp_in); + gpio_iomux_out(bus_config->quadwp_io_num, FUNC_SPI, false); + } + if (bus_config->quadhd_io_num >= 0) { + gpio_iomux_in(bus_config->quadhd_io_num, io_signal[host].spihd_in); + gpio_iomux_out(bus_config->quadhd_io_num, FUNC_SPI, false); + } + if (bus_config->sclk_io_num >= 0) { + gpio_iomux_in(bus_config->sclk_io_num, io_signal[host].spiclk_in); + gpio_iomux_out(bus_config->sclk_io_num, FUNC_SPI, false); + } temp_flag |= SPICOMMON_BUSFLAG_NATIVE_PINS; } else { //Use GPIO matrix - ESP_LOGD(SPI_TAG, "SPI%d use gpio matrix.", host ); + ESP_LOGD(SPI_TAG, "SPI%d use gpio matrix.", host ); if (bus_config->mosi_io_num >= 0) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->mosi_io_num], PIN_FUNC_GPIO); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->mosi_io_num], FUNC_GPIO); if (mosi_output) { gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT_OUTPUT); gpio_matrix_out(bus_config->mosi_io_num, io_signal[host].spid_out, false, false); @@ -311,29 +329,29 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf gpio_matrix_in(bus_config->mosi_io_num, io_signal[host].spid_in, false); } if (bus_config->miso_io_num >= 0) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->miso_io_num], PIN_FUNC_GPIO); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->miso_io_num], FUNC_GPIO); if (miso_output) { gpio_set_direction(bus_config->miso_io_num, GPIO_MODE_INPUT_OUTPUT); gpio_matrix_out(bus_config->miso_io_num, io_signal[host].spiq_out, false, false); } else { gpio_set_direction(bus_config->miso_io_num, GPIO_MODE_INPUT); } - gpio_matrix_in(bus_config->miso_io_num, io_signal[host].spiq_in, false); + gpio_matrix_in(bus_config->miso_io_num, io_signal[host].spiq_in, false); } if (bus_config->quadwp_io_num >= 0) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num], PIN_FUNC_GPIO); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num], FUNC_GPIO); gpio_set_direction(bus_config->quadwp_io_num, GPIO_MODE_INPUT_OUTPUT); gpio_matrix_out(bus_config->quadwp_io_num, io_signal[host].spiwp_out, false, false); gpio_matrix_in(bus_config->quadwp_io_num, io_signal[host].spiwp_in, false); } if (bus_config->quadhd_io_num >= 0) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num], PIN_FUNC_GPIO); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num], FUNC_GPIO); gpio_set_direction(bus_config->quadhd_io_num, GPIO_MODE_INPUT_OUTPUT); gpio_matrix_out(bus_config->quadhd_io_num, io_signal[host].spihd_out, false, false); gpio_matrix_in(bus_config->quadhd_io_num, io_signal[host].spihd_in, false); } if (bus_config->sclk_io_num >= 0) { - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->sclk_io_num], PIN_FUNC_GPIO); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->sclk_io_num], FUNC_GPIO); gpio_set_direction(bus_config->sclk_io_num, GPIO_MODE_INPUT_OUTPUT); gpio_matrix_out(bus_config->sclk_io_num, io_signal[host].spiclk_out, false, false); gpio_matrix_in(bus_config->sclk_io_num, io_signal[host].spiclk_in, false); @@ -377,10 +395,11 @@ void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num, { if (!force_gpio_matrix && cs_io_num == io_signal[host].spics0_native && cs_num == 0) { //The cs0s for all SPI peripherals map to pin mux source 1, so we use that instead of a define. - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[cs_io_num], 1); + gpio_iomux_in(cs_io_num, io_signal[host].spics_in); + gpio_iomux_out(cs_io_num, FUNC_SPI, false); } else { //Use GPIO matrix - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[cs_io_num], PIN_FUNC_GPIO); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[cs_io_num], FUNC_GPIO); gpio_matrix_out(cs_io_num, io_signal[host].spics_out[cs_num], false, false); if (cs_num == 0) gpio_matrix_in(cs_io_num, io_signal[host].spics_in, false); } From 197f594b0673c40fc92c130842264d9939ff24e0 Mon Sep 17 00:00:00 2001 From: michael Date: Thu, 26 Apr 2018 15:38:21 +0800 Subject: [PATCH 050/187] fix(spi): fix the issue when bus flag not set, dual mode cannot be used. --- components/driver/spi_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/driver/spi_common.c b/components/driver/spi_common.c index d6a2dbd829..52f239af3b 100644 --- a/components/driver/spi_common.c +++ b/components/driver/spi_common.c @@ -320,7 +320,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf ESP_LOGD(SPI_TAG, "SPI%d use gpio matrix.", host ); if (bus_config->mosi_io_num >= 0) { PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->mosi_io_num], FUNC_GPIO); - if (mosi_output) { + if (mosi_output || (temp_flag&SPICOMMON_BUSFLAG_DUAL)) { gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT_OUTPUT); gpio_matrix_out(bus_config->mosi_io_num, io_signal[host].spid_out, false, false); } else { @@ -330,7 +330,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf } if (bus_config->miso_io_num >= 0) { PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->miso_io_num], FUNC_GPIO); - if (miso_output) { + if (miso_output || (temp_flag&SPICOMMON_BUSFLAG_DUAL)) { gpio_set_direction(bus_config->miso_io_num, GPIO_MODE_INPUT_OUTPUT); gpio_matrix_out(bus_config->miso_io_num, io_signal[host].spiq_out, false, false); } else { From b00d256d5b1f3016f3ae3acb46465a1e5c7b56dc Mon Sep 17 00:00:00 2001 From: Deng Xin Date: Fri, 20 Apr 2018 11:33:04 +0800 Subject: [PATCH 051/187] wpa_supplicant:move part of codes to IDF --- components/esp32/include/esp_wpa2.h | 10 +- components/esp32/lib | 2 +- components/wpa_supplicant/component.mk | 4 +- components/wpa_supplicant/include/wpa/list.h | 2 + components/wpa_supplicant/include/wpa/wpa.h | 32 +- .../wpa_supplicant/include/wpa/wpa_debug.h | 20 +- .../include/wpa2/eap_peer/eap.h | 34 +- .../include/wpa2/eap_peer/eap_config.h | 31 +- .../include/wpa2/eap_peer/eap_i.h | 57 +- .../include/wpa2/eap_peer/eap_methods.h | 35 + .../include/wpa2/eap_peer/eap_peap_common.h | 16 + .../include/wpa2/eap_peer/eap_tlv_common.h | 112 + .../include/wpa2/eap_peer/eap_ttls.h | 65 + .../include/wpa2/eap_peer/mschapv2.h | 24 + .../include/wpa2/tls/libtommath.h | 122 +- .../include/wpa2/utils/base64.h | 4 +- .../include/wpa2/utils/ext_password.h | 8 +- .../wpa_supplicant/include/wps/utils/uuid.h | 18 + components/wpa_supplicant/include/wps/wps.h | 1067 +++++ .../include/wps/wps_attr_parse.h | 108 + .../wpa_supplicant/include/wps/wps_defs.h | 342 ++ .../wpa_supplicant/include/wps/wps_dev_attr.h | 39 + components/wpa_supplicant/include/wps/wps_i.h | 217 + components/wpa_supplicant/port/include/os.h | 5 + .../wpa_supplicant/src/wpa2/eap_peer/chap.c | 27 + .../wpa_supplicant/src/wpa2/eap_peer/eap.c | 731 ++++ .../src/wpa2/eap_peer/eap_common.c | 205 + .../src/wpa2/eap_peer/eap_mschapv2.c | 671 +++ .../src/wpa2/eap_peer/eap_peap.c | 1357 ++++++ .../src/wpa2/eap_peer/eap_peap_common.c | 90 + .../src/wpa2/eap_peer/eap_tls.c | 232 ++ .../src/wpa2/eap_peer/eap_tls_common.c | 1063 +++++ .../src/wpa2/eap_peer/eap_ttls.c | 1673 ++++++++ .../src/wpa2/eap_peer/mschapv2.c | 97 + components/wpa_supplicant/src/wpa2/tls/asn1.c | 207 + .../wpa_supplicant/src/wpa2/tls/bignum.c | 244 ++ .../wpa_supplicant/src/wpa2/tls/pkcs1.c | 195 + .../wpa_supplicant/src/wpa2/tls/pkcs5.c | 262 ++ .../wpa_supplicant/src/wpa2/tls/pkcs8.c | 186 + components/wpa_supplicant/src/wpa2/tls/rsa.c | 353 ++ .../src/wpa2/tls/tls_internal.c | 716 ++++ .../src/wpa2/tls/tlsv1_client.c | 837 ++++ .../src/wpa2/tls/tlsv1_client_read.c | 1001 +++++ .../src/wpa2/tls/tlsv1_client_write.c | 901 ++++ .../src/wpa2/tls/tlsv1_common.c | 337 ++ .../wpa_supplicant/src/wpa2/tls/tlsv1_cred.c | 505 +++ .../src/wpa2/tls/tlsv1_record.c | 553 +++ .../src/wpa2/tls/tlsv1_server.c | 656 +++ .../src/wpa2/tls/tlsv1_server_read.c | 1278 ++++++ .../src/wpa2/tls/tlsv1_server_write.c | 819 ++++ .../wpa_supplicant/src/wpa2/tls/x509v3.c | 2013 +++++++++ .../wpa_supplicant/src/wpa2/utils/base64.c | 155 + .../src/wpa2/utils/ext_password.c | 114 + .../wpa_supplicant/src/wps/eap_common.c | 205 + components/wpa_supplicant/src/wps/uuid.c | 71 + components/wpa_supplicant/src/wps/wps.c | 641 +++ .../wpa_supplicant/src/wps/wps_attr_build.c | 438 ++ .../wpa_supplicant/src/wps/wps_attr_parse.c | 640 +++ .../wpa_supplicant/src/wps/wps_attr_process.c | 351 ++ .../wpa_supplicant/src/wps/wps_common.c | 671 +++ .../wpa_supplicant/src/wps/wps_dev_attr.c | 451 ++ .../wpa_supplicant/src/wps/wps_enrollee.c | 1574 +++++++ .../wpa_supplicant/src/wps/wps_registrar.c | 3635 +++++++++++++++++ .../wpa_supplicant/src/wps/wps_validate.c | 2375 +++++++++++ 64 files changed, 30799 insertions(+), 105 deletions(-) create mode 100644 components/wpa_supplicant/include/wpa2/eap_peer/eap_methods.h create mode 100644 components/wpa_supplicant/include/wpa2/eap_peer/eap_peap_common.h create mode 100644 components/wpa_supplicant/include/wpa2/eap_peer/eap_tlv_common.h create mode 100644 components/wpa_supplicant/include/wpa2/eap_peer/eap_ttls.h create mode 100644 components/wpa_supplicant/include/wpa2/eap_peer/mschapv2.h create mode 100644 components/wpa_supplicant/include/wps/utils/uuid.h create mode 100644 components/wpa_supplicant/include/wps/wps.h create mode 100644 components/wpa_supplicant/include/wps/wps_attr_parse.h create mode 100644 components/wpa_supplicant/include/wps/wps_defs.h create mode 100644 components/wpa_supplicant/include/wps/wps_dev_attr.h create mode 100644 components/wpa_supplicant/include/wps/wps_i.h create mode 100644 components/wpa_supplicant/src/wpa2/eap_peer/chap.c create mode 100644 components/wpa_supplicant/src/wpa2/eap_peer/eap.c create mode 100644 components/wpa_supplicant/src/wpa2/eap_peer/eap_common.c create mode 100644 components/wpa_supplicant/src/wpa2/eap_peer/eap_mschapv2.c create mode 100644 components/wpa_supplicant/src/wpa2/eap_peer/eap_peap.c create mode 100644 components/wpa_supplicant/src/wpa2/eap_peer/eap_peap_common.c create mode 100644 components/wpa_supplicant/src/wpa2/eap_peer/eap_tls.c create mode 100644 components/wpa_supplicant/src/wpa2/eap_peer/eap_tls_common.c create mode 100644 components/wpa_supplicant/src/wpa2/eap_peer/eap_ttls.c create mode 100644 components/wpa_supplicant/src/wpa2/eap_peer/mschapv2.c create mode 100644 components/wpa_supplicant/src/wpa2/tls/asn1.c create mode 100644 components/wpa_supplicant/src/wpa2/tls/bignum.c create mode 100644 components/wpa_supplicant/src/wpa2/tls/pkcs1.c create mode 100644 components/wpa_supplicant/src/wpa2/tls/pkcs5.c create mode 100644 components/wpa_supplicant/src/wpa2/tls/pkcs8.c create mode 100644 components/wpa_supplicant/src/wpa2/tls/rsa.c create mode 100644 components/wpa_supplicant/src/wpa2/tls/tls_internal.c create mode 100644 components/wpa_supplicant/src/wpa2/tls/tlsv1_client.c create mode 100644 components/wpa_supplicant/src/wpa2/tls/tlsv1_client_read.c create mode 100644 components/wpa_supplicant/src/wpa2/tls/tlsv1_client_write.c create mode 100644 components/wpa_supplicant/src/wpa2/tls/tlsv1_common.c create mode 100644 components/wpa_supplicant/src/wpa2/tls/tlsv1_cred.c create mode 100644 components/wpa_supplicant/src/wpa2/tls/tlsv1_record.c create mode 100644 components/wpa_supplicant/src/wpa2/tls/tlsv1_server.c create mode 100644 components/wpa_supplicant/src/wpa2/tls/tlsv1_server_read.c create mode 100644 components/wpa_supplicant/src/wpa2/tls/tlsv1_server_write.c create mode 100644 components/wpa_supplicant/src/wpa2/tls/x509v3.c create mode 100644 components/wpa_supplicant/src/wpa2/utils/base64.c create mode 100644 components/wpa_supplicant/src/wpa2/utils/ext_password.c create mode 100644 components/wpa_supplicant/src/wps/eap_common.c create mode 100644 components/wpa_supplicant/src/wps/uuid.c create mode 100644 components/wpa_supplicant/src/wps/wps.c create mode 100644 components/wpa_supplicant/src/wps/wps_attr_build.c create mode 100644 components/wpa_supplicant/src/wps/wps_attr_parse.c create mode 100644 components/wpa_supplicant/src/wps/wps_attr_process.c create mode 100644 components/wpa_supplicant/src/wps/wps_common.c create mode 100644 components/wpa_supplicant/src/wps/wps_dev_attr.c create mode 100644 components/wpa_supplicant/src/wps/wps_enrollee.c create mode 100644 components/wpa_supplicant/src/wps/wps_registrar.c create mode 100644 components/wpa_supplicant/src/wps/wps_validate.c diff --git a/components/esp32/include/esp_wpa2.h b/components/esp32/include/esp_wpa2.h index fa73dbe287..1b2dfa5103 100644 --- a/components/esp32/include/esp_wpa2.h +++ b/components/esp32/include/esp_wpa2.h @@ -15,6 +15,8 @@ #ifndef ESP_WPA2_H #define ESP_WPA2_H +#include + #include "esp_err.h" #include "esp_wifi_crypto_types.h" @@ -121,7 +123,7 @@ void esp_wifi_sta_wpa2_ent_clear_password(void); * @attention 1. The API only passes the parameter password to the global pointer variable in wpa2 enterprise module. * @attention 2. The new password is used to substitute the old password when eap-mschapv2 failure request message with error code ERROR_PASSWD_EXPIRED is received. * - * @param password: point to address where stores the password; + * @param new_password: point to address where stores the password; * @param len: length of password * * @return @@ -130,7 +132,7 @@ void esp_wifi_sta_wpa2_ent_clear_password(void); * - ESP_ERR_NO_MEM: fail(internal memory malloc fail) */ -esp_err_t esp_wifi_sta_wpa2_ent_set_new_password(const unsigned char *password, int len); +esp_err_t esp_wifi_sta_wpa2_ent_set_new_password(const unsigned char *new_password, int len); /** * @brief Clear new password for MSCHAPv2 method.. @@ -144,12 +146,12 @@ void esp_wifi_sta_wpa2_ent_clear_new_password(void); * @attention 2. The ca_cert should be zero terminated. * * @param ca_cert: point to address where stores the CA certificate; - * @param len: length of ca_cert + * @param ca_cert_len: length of ca_cert * * @return * - ESP_OK: succeed */ -esp_err_t esp_wifi_sta_wpa2_ent_set_ca_cert(const unsigned char *ca_cert, int len); +esp_err_t esp_wifi_sta_wpa2_ent_set_ca_cert(const unsigned char *ca_cert, int ca_cert_len); /** * @brief Clear CA certificate for PEAP/TTLS method. diff --git a/components/esp32/lib b/components/esp32/lib index f46327a4c6..92a091649f 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit f46327a4c68b1e4e6a3fb3febd3ba3312df16ff1 +Subproject commit 92a091649f7c8476580177e2a769b15d9c4c191f diff --git a/components/wpa_supplicant/component.mk b/components/wpa_supplicant/component.mk index f34cb95f31..d2120dbc39 100644 --- a/components/wpa_supplicant/component.mk +++ b/components/wpa_supplicant/component.mk @@ -1,4 +1,4 @@ COMPONENT_ADD_INCLUDEDIRS := include port/include ../esp32/include -COMPONENT_SRCDIRS := src/crypto port src/fast_crypto +COMPONENT_SRCDIRS := src/crypto port src/fast_crypto src/wpa2/eap_peer src/wpa2/tls src/wpa2/utils src/wps -CFLAGS += -DEMBEDDED_SUPP -D__ets__ -Wno-strict-aliasing +CFLAGS += -DEMBEDDED_SUPP -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_MSCHAPv2 -DEAP_TTLS -DEAP_TLS -DEAP_PEAP -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -D__ets__ -Wno-strict-aliasing diff --git a/components/wpa_supplicant/include/wpa/list.h b/components/wpa_supplicant/include/wpa/list.h index c8dccee83d..a67a04966c 100644 --- a/components/wpa_supplicant/include/wpa/list.h +++ b/components/wpa_supplicant/include/wpa/list.h @@ -15,6 +15,8 @@ #ifndef LIST_H #define LIST_H +#include + /** * struct dl_list - Doubly-linked list */ diff --git a/components/wpa_supplicant/include/wpa/wpa.h b/components/wpa_supplicant/include/wpa/wpa.h index 2a1adfc567..9d50bb1ba5 100644 --- a/components/wpa_supplicant/include/wpa/wpa.h +++ b/components/wpa_supplicant/include/wpa/wpa.h @@ -15,15 +15,11 @@ #ifndef WPA_H #define WPA_H -#include "c_types.h" -#include "os_type.h" +#include "rom/ets_sys.h" #include "common.h" -#include "ets_sys.h" #include "wpa/defs.h" #include "wpa/wpa_common.h" -//#include "net80211/ieee80211_var.h" -//#include "net80211/ieee80211_node.h" #define WPA_SM_STATE(_sm) ((_sm)->wpa_state) @@ -51,10 +47,6 @@ struct wpa_sm { u8 pmk[PMK_LEN]; size_t pmk_len; -// char *passphrase; //wlan password -// u8 *ssid; //wlan network name -// size_t ssid_len; - struct wpa_ptk ptk, tptk; int ptk_set, tptk_set; u8 snonce[WPA_NONCE_LEN]; @@ -64,8 +56,6 @@ struct wpa_sm { int rx_replay_counter_set; u8 request_counter[WPA_REPLAY_COUNTER_LEN]; -// void *network_ctx; - unsigned int pairwise_cipher; unsigned int group_cipher; unsigned int key_mgmt; @@ -74,7 +64,7 @@ struct wpa_sm { int rsn_enabled; /* Whether RSN is enabled in configuration */ int countermeasures; /*TKIP countermeasures state flag, 1:in countermeasures state*/ - os_timer_t cm_timer; + ETSTimer cm_timer; u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */ size_t assoc_wpa_ie_len; @@ -95,21 +85,17 @@ struct wpa_sm { struct install_key install_ptk; struct install_key install_gtk; int key_entry_valid; //present current avaliable entry for bssid, for pairkey:0,5,10,15,20, gtk: pairkey_no+i (i:1~4) - -// char *msg; //send eapol msg buff -// size_t msg_len; //msg length:6 + sizeof(eth) + data_len -// struct netif *ifp; struct pbuf *pb; void (* sendto) (struct pbuf *pb); - void (*config_assoc_ie) (uint8 proto, u8 *assoc_buf, u32 assoc_wpa_ie_len); - void (*install_ppkey) (enum wpa_alg alg, uint8 *addr, int key_idx, int set_tx, - uint8 *seq, size_t seq_len, uint8 *key, size_t key_len, int key_entry_valid); - void (*wpa_deauthenticate)(uint8 reason_code); + void (*config_assoc_ie) (u8 proto, u8 *assoc_buf, u32 assoc_wpa_ie_len); + void (*install_ppkey) (enum wpa_alg alg, u8 *addr, int key_idx, int set_tx, + u8 *seq, unsigned int seq_len, u8 *key, unsigned int key_len, int key_entry_valid); + void (*wpa_deauthenticate)(u8 reason_code); void (*wpa_neg_complete)(); struct wpa_gtk_data gd; //used for calllback save param - uint16 key_info; //used for txcallback param + u16 key_info; //used for txcallback param }; struct l2_ethhdr { @@ -185,9 +171,9 @@ struct l2_ethhdr { #define KEYENTRY_TABLE_MAP(key_entry_valid) ((key_entry_valid)%5) -void pp_michael_mic_failure(uint16 isunicast); - void wpa_sm_set_state(enum wpa_states state); +char * dup_binstr(const void *src, size_t len); + #endif /* WPA_H */ diff --git a/components/wpa_supplicant/include/wpa/wpa_debug.h b/components/wpa_supplicant/include/wpa/wpa_debug.h index b78a657e05..10fe928c3e 100644 --- a/components/wpa_supplicant/include/wpa/wpa_debug.h +++ b/components/wpa_supplicant/include/wpa/wpa_debug.h @@ -15,8 +15,22 @@ #ifndef WPA_DEBUG_H #define WPA_DEBUG_H +#include "wpabuf.h" +#include "esp_log.h" +#ifdef ESPRESSIF_USE + +#define TAG "wpa" + +#define MSG_ERROR ESP_LOG_ERROR +#define MSG_WARNING ESP_LOG_WARN +#define MSG_INFO ESP_LOG_INFO +#define MSG_DEBUG ESP_LOG_DEBUG +#define MSG_MSGDUMP ESP_LOG_VERBOSE + +#else enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR }; +#endif /** EAP authentication completed successfully */ #define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS " @@ -44,8 +58,8 @@ void wpa_debug_print_timestamp(void); * * Note: New line '\n' is added to the end of the text when printing to stdout. */ -//#define DEBUG_PRINT -//#define MSG_PRINT +#define DEBUG_PRINT +#define MSG_PRINT /** * wpa_hexdump - conditional hex dump @@ -59,7 +73,7 @@ void wpa_debug_print_timestamp(void); * configuration. The contents of buf is printed out has hex dump. */ #ifdef DEBUG_PRINT -#define wpa_printf(level,fmt, args...) ets_printf(fmt,## args) +#define wpa_printf(level,fmt, args...) ESP_LOG_LEVEL_LOCAL(level, TAG, fmt, ##args) static inline void wpa_hexdump_ascii(int level, const char *title, const u8 *buf, size_t len) { diff --git a/components/wpa_supplicant/include/wpa2/eap_peer/eap.h b/components/wpa_supplicant/include/wpa2/eap_peer/eap.h index e2cd2dd81d..9e1c3efa94 100644 --- a/components/wpa_supplicant/include/wpa2/eap_peer/eap.h +++ b/components/wpa_supplicant/include/wpa2/eap_peer/eap.h @@ -10,15 +10,45 @@ #define EAP_H #include "wpa/defs.h" -#include "eap/eap_defs.h" +#include "wpa2/eap_peer/eap_defs.h" struct eap_sm; struct eap_method_type { int vendor; - u32 method; + EapType method; }; +u8 *g_wpa_anonymous_identity; +int g_wpa_anonymous_identity_len; +u8 *g_wpa_username; +int g_wpa_username_len; +const u8 *g_wpa_client_cert; +int g_wpa_client_cert_len; +const u8 *g_wpa_private_key; +int g_wpa_private_key_len; +const u8 *g_wpa_private_key_passwd; +int g_wpa_private_key_passwd_len; + +const u8 *g_wpa_ca_cert; +int g_wpa_ca_cert_len; + +u8 *g_wpa_password; +int g_wpa_password_len; + +u8 *g_wpa_new_password; +int g_wpa_new_password_len; + const u8 * eap_get_eapKeyData(struct eap_sm *sm, size_t *len); +void eap_deinit_prev_method(struct eap_sm *sm, const char *txt); +struct wpabuf * eap_sm_build_nak(struct eap_sm *sm, EapType type, u8 id); +int eap_peer_blob_init(struct eap_sm *sm); +void eap_peer_blob_deinit(struct eap_sm *sm); +int eap_peer_config_init( + struct eap_sm *sm, u8 *private_key_passwd, + int private_key_passwd_len); +void eap_peer_config_deinit(struct eap_sm *sm); +void eap_sm_abort(struct eap_sm *sm); +int eap_peer_register_methods(void); #endif /* EAP_H */ diff --git a/components/wpa_supplicant/include/wpa2/eap_peer/eap_config.h b/components/wpa_supplicant/include/wpa2/eap_peer/eap_config.h index f35cbf43d7..f95dcda3a1 100644 --- a/components/wpa_supplicant/include/wpa2/eap_peer/eap_config.h +++ b/components/wpa_supplicant/include/wpa2/eap_peer/eap_config.h @@ -26,6 +26,10 @@ struct eap_peer_config { */ size_t identity_len; + u8 *anonymous_identity; + + size_t anonymous_identity_len; + /** * password - Password string for EAP * @@ -139,8 +143,29 @@ struct eap_peer_config { */ u8 *private_key_passwd; + /** + * Phase 2 + */ + u8 *ca_cert2; + + u8 *ca_path2; + + u8 *client_cert2; + + u8 *private_key2; + + u8 *private_key2_password; + + /** + * eap_methods - Allowed EAP methods + */ + struct eap_method_type *eap_methods; + + char *phase1; + char *phase2; + /** * pin - PIN for USIM, GSM SIM, and smartcards * @@ -152,6 +177,10 @@ struct eap_peer_config { */ char *pin; + int mschapv2_retry; + u8 *new_password; + size_t new_password_len; + /** * fragment_size - Maximum EAP fragment size in bytes (default 1398) * @@ -204,7 +233,7 @@ struct wpa_config_blob { /** * data - Pointer to binary data */ - u8 *data; + const u8 *data; /** * len - Length of binary data diff --git a/components/wpa_supplicant/include/wpa2/eap_peer/eap_i.h b/components/wpa_supplicant/include/wpa2/eap_peer/eap_i.h index a4779d13f8..6204f46538 100644 --- a/components/wpa_supplicant/include/wpa2/eap_peer/eap_i.h +++ b/components/wpa_supplicant/include/wpa2/eap_peer/eap_i.h @@ -13,6 +13,7 @@ #include "eap.h" #include "eap_common.h" #include "eap_config.h" +#include "esp_wpa2.h" /* RFC 4137 - EAP Peer state machine */ @@ -54,11 +55,48 @@ struct eap_method_ret { Boolean allowNotifications; }; +struct eap_sm; + +struct eap_method { + /** + * vendor -EAP Vendor-ID + */ + int vendor; + + /** + * method - EAP type number + */ + EapType method; + + /** + * name - Name of the method (e.g., "TLS") + */ + const char *name; + + struct eap_method *next; + + void * (*init)(struct eap_sm *sm); + void (*deinit)(struct eap_sm *sm, void *priv); + struct wpabuf * (*process)(struct eap_sm *sm, void *priv, + struct eap_method_ret *ret, + const struct wpabuf *reqData); + bool (*isKeyAvailable)(struct eap_sm *sm, void *priv); + u8 * (*getKey)(struct eap_sm *sm, void *priv, size_t *len); + int (*get_status)(struct eap_sm *sm, void *priv, char *buf, + size_t buflen, int verbose); + const u8 * (*get_identity)(struct eap_sm *sm, void *priv, size_t *len); + void (*free)(struct eap_method *method); + bool (*has_reauth_data)(struct eap_sm *sm, void *priv); + void (*deinit_for_reauth)(struct eap_sm *sm, void *priv); + void * (*init_for_reauth)(struct eap_sm *sm, void *priv); + u8 * (*getSessionId)(struct eap_sm *sm, void *priv, size_t *len); +}; + #define CLIENT_CERT_NAME "CLC" #define CA_CERT_NAME "CAC" #define PRIVATE_KEY_NAME "PVK" #define BLOB_NAME_LEN 3 -#define BLOB_NUM 2 +#define BLOB_NUM 3 /** * struct eap_sm - EAP state machine data @@ -80,9 +118,26 @@ struct eap_sm { u8 wpa2_sig_cnt[SIG_WPA2_NUM]; #endif u8 finish_state; + + int init_phase2; + bool peap_done; + + u8 *eapKeyData; + size_t eapKeyDataLen; + struct wpabuf *lastRespData; + const struct eap_method *m; }; +wpa2_crypto_funcs_t wpa2_crypto_funcs; + +const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len); +const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len); +const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash); +const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len); struct eap_peer_config * eap_get_config(struct eap_sm *sm); const struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm, const char *name); +bool wifi_sta_get_enterprise_disable_time_check(void); + +struct wpabuf * eap_sm_build_identity_resp(struct eap_sm *sm, u8 id, int encrypted); #endif /* EAP_I_H */ diff --git a/components/wpa_supplicant/include/wpa2/eap_peer/eap_methods.h b/components/wpa_supplicant/include/wpa2/eap_peer/eap_methods.h new file mode 100644 index 0000000000..baa493d292 --- /dev/null +++ b/components/wpa_supplicant/include/wpa2/eap_peer/eap_methods.h @@ -0,0 +1,35 @@ +/* + * EAP peer: Method registration + * Copyright (c) 2004-2007, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef EAP_METHODS_H +#define EAP_METHODS_H + +#include "eap_defs.h" + +const struct eap_method * eap_peer_get_eap_method(int vendor, EapType method); +const struct eap_method * eap_peer_get_methods(size_t *count); + +u32 eap_get_phase2_type(const char *name, int *vendor); +struct eap_method_type * eap_get_phase2_types(struct eap_peer_config *config, + size_t *count); + +struct eap_method * eap_peer_method_alloc(int verdor, EapType method, + const char *name); + +void eap_peer_method_free(struct eap_method *method); +int eap_peer_method_register(struct eap_method *method); + +void eap_peer_unregister_methods(void); + +//int eap_peer_md5_register(void); +int eap_peer_tls_register(void); +int eap_peer_peap_register(void); +int eap_peer_ttls_register(void); +int eap_peer_mschapv2_register(void); + +#endif /* EAP_METHODS_H */ diff --git a/components/wpa_supplicant/include/wpa2/eap_peer/eap_peap_common.h b/components/wpa_supplicant/include/wpa2/eap_peer/eap_peap_common.h new file mode 100644 index 0000000000..c0dc6ed833 --- /dev/null +++ b/components/wpa_supplicant/include/wpa2/eap_peer/eap_peap_common.h @@ -0,0 +1,16 @@ +/* + * EAP-PEAP common routines + * Copyright (c) 2008-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef EAP_PEAP_COMMON_H +#define EAP_PEAP_COMMON_H + +int peap_prfplus(int version, const u8 *key, size_t key_len, + const char *label, const u8 *seed, size_t seed_len, + u8 *buf, size_t buf_len); + +#endif /* EAP_PEAP_COMMON_H */ diff --git a/components/wpa_supplicant/include/wpa2/eap_peer/eap_tlv_common.h b/components/wpa_supplicant/include/wpa2/eap_peer/eap_tlv_common.h new file mode 100644 index 0000000000..8f0f83f7a4 --- /dev/null +++ b/components/wpa_supplicant/include/wpa2/eap_peer/eap_tlv_common.h @@ -0,0 +1,112 @@ +/* + * EAP-TLV definitions (draft-josefsson-pppext-eap-tls-eap-10.txt) + * Copyright (c) 2004-2008, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef EAP_TLV_COMMON_H +#define EAP_TLV_COMMON_H + +/* EAP-TLV TLVs (draft-josefsson-ppext-eap-tls-eap-10.txt) */ +#define EAP_TLV_RESULT_TLV 3 /* Acknowledged Result */ +#define EAP_TLV_NAK_TLV 4 +#define EAP_TLV_ERROR_CODE_TLV 5 +#define EAP_TLV_CONNECTION_BINDING_TLV 6 +#define EAP_TLV_VENDOR_SPECIFIC_TLV 7 +#define EAP_TLV_URI_TLV 8 +#define EAP_TLV_EAP_PAYLOAD_TLV 9 +#define EAP_TLV_INTERMEDIATE_RESULT_TLV 10 +#define EAP_TLV_PAC_TLV 11 /* RFC 5422, Section 4.2 */ +#define EAP_TLV_CRYPTO_BINDING_TLV 12 +#define EAP_TLV_CALLING_STATION_ID_TLV 13 +#define EAP_TLV_CALLED_STATION_ID_TLV 14 +#define EAP_TLV_NAS_PORT_TYPE_TLV 15 +#define EAP_TLV_SERVER_IDENTIFIER_TLV 16 +#define EAP_TLV_IDENTITY_TYPE_TLV 17 +#define EAP_TLV_SERVER_TRUSTED_ROOT_TLV 18 +#define EAP_TLV_REQUEST_ACTION_TLV 19 +#define EAP_TLV_PKCS7_TLV 20 + +#define EAP_TLV_RESULT_SUCCESS 1 +#define EAP_TLV_RESULT_FAILURE 2 + +#define EAP_TLV_TYPE_MANDATORY 0x8000 +#define EAP_TLV_TYPE_MASK 0x3fff + +#ifdef _MSC_VER +#pragma pack(push, 1) +#endif /* _MSC_VER */ + +struct eap_tlv_hdr { + be16 tlv_type; + be16 length; +} STRUCT_PACKED; + +struct eap_tlv_nak_tlv { + be16 tlv_type; + be16 length; + be32 vendor_id; + be16 nak_type; +} STRUCT_PACKED; + +struct eap_tlv_result_tlv { + be16 tlv_type; + be16 length; + be16 status; +} STRUCT_PACKED; + +/* RFC 4851, Section 4.2.7 - Intermediate-Result TLV */ +struct eap_tlv_intermediate_result_tlv { + be16 tlv_type; + be16 length; + be16 status; + /* Followed by optional TLVs */ +} STRUCT_PACKED; + +/* RFC 4851, Section 4.2.8 - Crypto-Binding TLV */ +struct eap_tlv_crypto_binding_tlv { + be16 tlv_type; + be16 length; + u8 reserved; + u8 version; + u8 received_version; + u8 subtype; + u8 nonce[32]; + u8 compound_mac[20]; +} STRUCT_PACKED; + +struct eap_tlv_pac_ack_tlv { + be16 tlv_type; + be16 length; + be16 pac_type; + be16 pac_len; + be16 result; +} STRUCT_PACKED; + +/* RFC 4851, Section 4.2.9 - Request-Action TLV */ +struct eap_tlv_request_action_tlv { + be16 tlv_type; + be16 length; + be16 action; +} STRUCT_PACKED; + +/* RFC 5422, Section 4.2.6 - PAC-Type TLV */ +struct eap_tlv_pac_type_tlv { + be16 tlv_type; /* PAC_TYPE_PAC_TYPE */ + be16 length; + be16 pac_type; +} STRUCT_PACKED; + +#ifdef _MSC_VER +#pragma pack(pop) +#endif /* _MSC_VER */ + +#define EAP_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST 0 +#define EAP_TLV_CRYPTO_BINDING_SUBTYPE_RESPONSE 1 + +#define EAP_TLV_ACTION_PROCESS_TLV 1 +#define EAP_TLV_ACTION_NEGOTIATE_EAP 2 + +#endif /* EAP_TLV_COMMON_H */ diff --git a/components/wpa_supplicant/include/wpa2/eap_peer/eap_ttls.h b/components/wpa_supplicant/include/wpa2/eap_peer/eap_ttls.h new file mode 100644 index 0000000000..568038d0d9 --- /dev/null +++ b/components/wpa_supplicant/include/wpa2/eap_peer/eap_ttls.h @@ -0,0 +1,65 @@ +/* + * EAP server/peer: EAP-TTLS (RFC 5281) + * Copyright (c) 2004-2007, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef EAP_TTLS_H +#define EAP_TTLS_H + +struct ttls_avp { + be32 avp_code; + be32 avp_length; /* 8-bit flags, 24-bit length; + * length includes AVP header */ + /* optional 32-bit Vendor-ID */ + /* Data */ +}; + +struct ttls_avp_vendor { + be32 avp_code; + be32 avp_length; /* 8-bit flags, 24-bit length; + * length includes AVP header */ + be32 vendor_id; + /* Data */ +}; + +#define AVP_FLAGS_VENDOR 0x80 +#define AVP_FLAGS_MANDATORY 0x40 + +#define AVP_PAD(start, pos) \ +do { \ + int __pad; \ + __pad = (4 - (((pos) - (start)) & 3)) & 3; \ + os_memset((pos), 0, __pad); \ + pos += __pad; \ +} while (0) + + +/* RFC 2865 */ +#define RADIUS_ATTR_USER_NAME 1 +#define RADIUS_ATTR_USER_PASSWORD 2 +#define RADIUS_ATTR_CHAP_PASSWORD 3 +#define RADIUS_ATTR_REPLY_MESSAGE 18 +#define RADIUS_ATTR_CHAP_CHALLENGE 60 +#define RADIUS_ATTR_EAP_MESSAGE 79 + +/* RFC 2548 */ +#define RADIUS_VENDOR_ID_MICROSOFT 311 +#define RADIUS_ATTR_MS_CHAP_RESPONSE 1 +#define RADIUS_ATTR_MS_CHAP_ERROR 2 +#define RADIUS_ATTR_MS_CHAP_NT_ENC_PW 6 +#define RADIUS_ATTR_MS_CHAP_CHALLENGE 11 +#define RADIUS_ATTR_MS_CHAP2_RESPONSE 25 +#define RADIUS_ATTR_MS_CHAP2_SUCCESS 26 +#define RADIUS_ATTR_MS_CHAP2_CPW 27 + +#define EAP_TTLS_MSCHAPV2_CHALLENGE_LEN 16 +#define EAP_TTLS_MSCHAPV2_RESPONSE_LEN 50 +#define EAP_TTLS_MSCHAP_CHALLENGE_LEN 8 +#define EAP_TTLS_MSCHAP_RESPONSE_LEN 50 +#define EAP_TTLS_CHAP_CHALLENGE_LEN 16 +#define EAP_TTLS_CHAP_PASSWORD_LEN 16 + +#endif /* EAP_TTLS_H */ diff --git a/components/wpa_supplicant/include/wpa2/eap_peer/mschapv2.h b/components/wpa_supplicant/include/wpa2/eap_peer/mschapv2.h new file mode 100644 index 0000000000..ef750819ff --- /dev/null +++ b/components/wpa_supplicant/include/wpa2/eap_peer/mschapv2.h @@ -0,0 +1,24 @@ +/* + * MSCHAPV2 + */ + + +#ifndef MSCHAPV2_H +#define MSCHAPV2_H + +#define MSCHAPV2_CHAL_LEN 16 +#define MSCHAPV2_NT_RESPONSE_LEN 24 +#define MSCHAPV2_AUTH_RESPONSE_LEN 20 +#define MSCHAPV2_MASTER_KEY_LEN 16 + +const u8 * mschapv2_remove_domain(const u8 *username, size_t *len); +int mschapv2_derive_response(const u8 *username, size_t username_len, + const u8 *password, size_t password_len, + int pwhash, + const u8 *auth_challenge, + const u8 *peer_challenge, + u8 *nt_response, u8 *auth_response, + u8 *master_key); +int mschapv2_verify_auth_response(const u8 *auth_response, + const u8 *buf, size_t buf_len); +#endif /* MSCHAPV2_H */ diff --git a/components/wpa_supplicant/include/wpa2/tls/libtommath.h b/components/wpa_supplicant/include/wpa2/tls/libtommath.h index c0409b5e33..9be311e86a 100644 --- a/components/wpa_supplicant/include/wpa2/tls/libtommath.h +++ b/components/wpa_supplicant/include/wpa2/tls/libtommath.h @@ -13,7 +13,6 @@ * If CONFIG_INTERNAL_LIBTOMMATH is defined, bignum.c includes this * libtommath.c file instead of using the external LibTomMath library. */ -#include "c_types.h" #include "os.h" #include "stdarg.h" @@ -193,7 +192,7 @@ static int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); /* reverse an array, used for radix code */ -static void ICACHE_FLASH_ATTR +static void bn_reverse (unsigned char *s, int len) { int ix, iy; @@ -212,7 +211,7 @@ bn_reverse (unsigned char *s, int len) /* low level addition, based on HAC pp.594, Algorithm 14.7 */ -static int ICACHE_FLASH_ATTR +static int s_mp_add (mp_int * a, mp_int * b, mp_int * c) { mp_int *x; @@ -301,7 +300,7 @@ s_mp_add (mp_int * a, mp_int * b, mp_int * c) /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ -static int ICACHE_FLASH_ATTR +static int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) { int olduse, res, min, max; @@ -369,7 +368,7 @@ s_mp_sub (mp_int * a, mp_int * b, mp_int * c) /* init a new mp_int */ -static int ICACHE_FLASH_ATTR +static int mp_init (mp_int * a) { int i; @@ -396,7 +395,7 @@ mp_init (mp_int * a) /* clear one (frees) */ -static void ICACHE_FLASH_ATTR +static void mp_clear (mp_int * a) { int i; @@ -420,7 +419,7 @@ mp_clear (mp_int * a) /* high level addition (handles signs) */ -static int ICACHE_FLASH_ATTR +static int mp_add (mp_int * a, mp_int * b, mp_int * c) { int sa, sb, res; @@ -453,7 +452,7 @@ mp_add (mp_int * a, mp_int * b, mp_int * c) /* high level subtraction (handles signs) */ -static int ICACHE_FLASH_ATTR +static int mp_sub (mp_int * a, mp_int * b, mp_int * c) { int sa, sb, res; @@ -491,7 +490,7 @@ mp_sub (mp_int * a, mp_int * b, mp_int * c) /* high level multiplication (handles sign) */ -static int ICACHE_FLASH_ATTR +static int mp_mul (mp_int * a, mp_int * b, mp_int * c) { int res, neg; @@ -539,7 +538,7 @@ mp_mul (mp_int * a, mp_int * b, mp_int * c) /* d = a * b (mod c) */ -static int ICACHE_FLASH_ATTR +static int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) { int res; @@ -560,7 +559,7 @@ mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) /* c = a mod b, 0 <= c < b */ -static int ICACHE_FLASH_ATTR +static int mp_mod (mp_int * a, mp_int * b, mp_int * c) { mp_int t; @@ -592,10 +591,12 @@ mp_mod (mp_int * a, mp_int * b, mp_int * c) * embedded in the normal function but that wasted a lot of stack space * for nothing (since 99% of the time the Montgomery code would be called) */ -static int ICACHE_FLASH_ATTR +static int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) { - int dr; +#if defined(BN_MP_DR_IS_MODULUS_C)||defined(BN_MP_REDUCE_IS_2K_C)||defined(BN_MP_EXPTMOD_FAST_C) + int dr = 0; +#endif /* modulus P must be positive */ if (P->sign == MP_NEG) { @@ -652,9 +653,6 @@ mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) #ifdef BN_MP_DR_IS_MODULUS_C /* is it a DR modulus? */ dr = mp_dr_is_modulus(P); -#else - /* default to no */ - dr = 0; #endif #ifdef BN_MP_REDUCE_IS_2K_C @@ -685,7 +683,7 @@ mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) /* compare two ints (signed)*/ -static int ICACHE_FLASH_ATTR +static int mp_cmp (mp_int * a, mp_int * b) { /* compare based on sign */ @@ -708,7 +706,7 @@ mp_cmp (mp_int * a, mp_int * b) /* compare a digit */ -static int ICACHE_FLASH_ATTR +static int mp_cmp_d(mp_int * a, mp_digit b) { /* compare based on sign */ @@ -734,7 +732,7 @@ mp_cmp_d(mp_int * a, mp_digit b) #ifndef LTM_NO_NEG_EXP /* hac 14.61, pp608 */ -static int ICACHE_FLASH_ATTR +static int mp_invmod (mp_int * a, mp_int * b, mp_int * c) { /* b cannot be negative */ @@ -764,7 +762,7 @@ mp_invmod (mp_int * a, mp_int * b, mp_int * c) /* get the size for an unsigned equivalent */ -static int ICACHE_FLASH_ATTR +static int mp_unsigned_bin_size (mp_int * a) { int size = mp_count_bits (a); @@ -774,7 +772,7 @@ mp_unsigned_bin_size (mp_int * a) #ifndef LTM_NO_NEG_EXP /* hac 14.61, pp608 */ -static int ICACHE_FLASH_ATTR +static int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) { mp_int x, y, u, v, A, B, C, D; @@ -931,7 +929,7 @@ LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL); /* compare maginitude of two ints (unsigned) */ -static int ICACHE_FLASH_ATTR +static int mp_cmp_mag (mp_int * a, mp_int * b) { int n; @@ -967,7 +965,7 @@ mp_cmp_mag (mp_int * a, mp_int * b) /* reads a unsigned char array, assumes the msb is stored first [big endian] */ -static int ICACHE_FLASH_ATTR +static int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c) { int res; @@ -1003,7 +1001,7 @@ mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c) /* store in unsigned [big endian] format */ -static int ICACHE_FLASH_ATTR +static int mp_to_unsigned_bin (mp_int * a, unsigned char *b) { int x, res; @@ -1032,7 +1030,7 @@ mp_to_unsigned_bin (mp_int * a, unsigned char *b) /* shift right by a certain bit count (store quotient in c, optional remainder in d) */ -static int ICACHE_FLASH_ATTR +static int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d) { mp_digit D, r, rr; @@ -1109,7 +1107,7 @@ mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d) } -static int ICACHE_FLASH_ATTR +static int mp_init_copy (mp_int * a, mp_int * b) { int res; @@ -1122,7 +1120,7 @@ mp_init_copy (mp_int * a, mp_int * b) /* set to zero */ -static void ICACHE_FLASH_ATTR +static void mp_zero (mp_int * a) { int n; @@ -1139,7 +1137,7 @@ mp_zero (mp_int * a) /* copy, b = a */ -static int ICACHE_FLASH_ATTR +static int mp_copy (mp_int * a, mp_int * b) { int res, n; @@ -1187,7 +1185,7 @@ mp_copy (mp_int * a, mp_int * b) /* shift right a certain amount of digits */ -static void ICACHE_FLASH_ATTR +static void mp_rshd (mp_int * a, int b) { int x; @@ -1242,7 +1240,7 @@ mp_rshd (mp_int * a, int b) /* swap the elements of two integers, for cases where you can't simply swap the * mp_int pointers around */ -static void ICACHE_FLASH_ATTR +static void mp_exch (mp_int * a, mp_int * b) { mp_int t; @@ -1260,7 +1258,7 @@ mp_exch (mp_int * a, mp_int * b) * Typically very fast. Also fixes the sign if there * are no more leading digits */ -static void ICACHE_FLASH_ATTR +static void mp_clamp (mp_int * a) { /* decrease used while the most significant digit is @@ -1278,7 +1276,7 @@ mp_clamp (mp_int * a) /* grow as required */ -static int ICACHE_FLASH_ATTR +static int mp_grow (mp_int * a, int size) { int i; @@ -1320,7 +1318,7 @@ mp_grow (mp_int * a, int size) * * Simple function copies the input and fixes the sign to positive */ -static int ICACHE_FLASH_ATTR +static int mp_abs (mp_int * a, mp_int * b) { int res; @@ -1341,7 +1339,7 @@ mp_abs (mp_int * a, mp_int * b) /* set to a digit */ -static void ICACHE_FLASH_ATTR +static void mp_set (mp_int * a, mp_digit b) { mp_zero (a); @@ -1352,7 +1350,7 @@ mp_set (mp_int * a, mp_digit b) #ifndef LTM_NO_NEG_EXP /* b = a/2 */ -static int ICACHE_FLASH_ATTR +static int mp_div_2(mp_int * a, mp_int * b) { int x, res, oldused; @@ -1402,7 +1400,7 @@ mp_div_2(mp_int * a, mp_int * b) /* shift left by a certain bit count */ -static int ICACHE_FLASH_ATTR +static int mp_mul_2d (mp_int * a, int b, mp_int * c) { mp_digit d; @@ -1468,7 +1466,7 @@ mp_mul_2d (mp_int * a, int b, mp_int * c) #ifdef BN_MP_INIT_MULTI_C -static int ICACHE_FLASH_ATTR +static int mp_init_multi(mp_int *mp, ...) { mp_err res = MP_OKAY; /* Assume ok until proven otherwise */ @@ -1508,7 +1506,7 @@ mp_init_multi(mp_int *mp, ...) #ifdef BN_MP_CLEAR_MULTI_C -static void ICACHE_FLASH_ATTR +static void mp_clear_multi(mp_int *mp, ...) { mp_int* next_mp = mp; @@ -1524,7 +1522,7 @@ mp_clear_multi(mp_int *mp, ...) /* shift left a certain amount of digits */ -static int ICACHE_FLASH_ATTR +static int mp_lshd (mp_int * a, int b) { int x, res; @@ -1572,7 +1570,7 @@ mp_lshd (mp_int * a, int b) /* returns the number of bits in an int */ -static int ICACHE_FLASH_ATTR +static int mp_count_bits (mp_int * a) { int r; @@ -1597,7 +1595,7 @@ mp_count_bits (mp_int * a) /* calc a value mod 2**b */ -static int ICACHE_FLASH_ATTR +static int mp_mod_2d (mp_int * a, int b, mp_int * c) { int x, res; @@ -1634,7 +1632,7 @@ mp_mod_2d (mp_int * a, int b, mp_int * c) #ifdef BN_MP_DIV_SMALL /* slower bit-bang division... also smaller */ -static int ICACHE_FLASH_ATTR +static int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d) { mp_int ta, tb, tq, q; @@ -1717,7 +1715,7 @@ LBL_ERR: * The overall algorithm is as described as * 14.20 from HAC but fixed to treat these cases. */ -static int ICACHE_FLASH_ATTR +static int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d) { mp_int q, x, y, t1, t2; @@ -1910,7 +1908,7 @@ LBL_Q:mp_clear (&q); #define TAB_SIZE 256 #endif -static int ICACHE_FLASH_ATTR +static int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) { mp_int M[TAB_SIZE], res, mu; @@ -2139,7 +2137,7 @@ LBL_M: /* computes b = a*a */ -static int ICACHE_FLASH_ATTR +static int mp_sqr (mp_int * a, mp_int * b) { int res; @@ -2181,7 +2179,7 @@ if (a->used >= KARATSUBA_SQR_CUTOFF) { This differs from reduce_2k since "d" can be larger than a single digit. */ -static int ICACHE_FLASH_ATTR +static int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d) { mp_int q; @@ -2220,7 +2218,7 @@ ERR: /* determines the setup value */ -static int ICACHE_FLASH_ATTR +static int mp_reduce_2k_setup_l(mp_int *a, mp_int *d) { int res; @@ -2249,7 +2247,7 @@ ERR: * Simple algorithm which zeroes the int, grows it then just sets one bit * as required. */ -static int ICACHE_FLASH_ATTR +static int mp_2expt (mp_int * a, int b) { int res; @@ -2275,7 +2273,7 @@ mp_2expt (mp_int * a, int b) /* pre-calculate the value required for Barrett reduction * For a given modulus "b" it calulates the value required in "a" */ -static int ICACHE_FLASH_ATTR +static int mp_reduce_setup (mp_int * a, mp_int * b) { int res; @@ -2291,7 +2289,7 @@ mp_reduce_setup (mp_int * a, mp_int * b) * precomputed via mp_reduce_setup. * From HAC pp.604 Algorithm 14.42 */ -static int ICACHE_FLASH_ATTR +static int mp_reduce (mp_int * x, mp_int * m, mp_int * mu) { mp_int q; @@ -2375,7 +2373,7 @@ CLEANUP: * HAC pp. 595, Algorithm 14.12 Modified so you can control how * many digits of output are created. */ -static int ICACHE_FLASH_ATTR +static int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) { mp_int t; @@ -2458,7 +2456,7 @@ s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) * Based on Algorithm 14.12 on pp.595 of HAC. * */ -static int ICACHE_FLASH_ATTR +static int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) { int olduse, res, pa, ix, iz; @@ -2531,7 +2529,7 @@ fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) /* init an mp_init for a given size */ -static int ICACHE_FLASH_ATTR +static int mp_init_size (mp_int * a, int size) { int x; @@ -2560,7 +2558,7 @@ mp_init_size (mp_int * a, int size) /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ -static int ICACHE_FLASH_ATTR +static int s_mp_sqr (mp_int * a, mp_int * b) { mp_int t; @@ -2627,7 +2625,7 @@ s_mp_sqr (mp_int * a, mp_int * b) /* multiplies |a| * |b| and does not compute the lower digs digits * [meant to get the higher part of the product] */ -static int ICACHE_FLASH_ATTR +static int s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) { mp_int t; @@ -2687,7 +2685,7 @@ s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) #ifdef BN_MP_MONTGOMERY_SETUP_C /* setups the montgomery reduction stuff */ -static int ICACHE_FLASH_ATTR +static int mp_montgomery_setup (mp_int * n, mp_digit * rho) { mp_digit x, b; @@ -2735,7 +2733,7 @@ mp_montgomery_setup (mp_int * n, mp_digit * rho) * * Based on Algorithm 14.32 on pp.601 of HAC. */ -int ICACHE_FLASH_ATTR +int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) { int ix, res, olduse; @@ -2883,7 +2881,7 @@ fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) #ifdef BN_MP_MUL_2_C /* b = a*2 */ -static int ICACHE_FLASH_ATTR +static int mp_mul_2(mp_int * a, mp_int * b) { int x, res, oldused; @@ -2953,7 +2951,7 @@ mp_mul_2(mp_int * a, mp_int * b) * The method is slightly modified to shift B unconditionally up to just under * the leading bit of b. This saves a lot of multiple precision shifting. */ -static int ICACHE_FLASH_ATTR +static int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) { int x, bits, res; @@ -2997,7 +2995,7 @@ mp_montgomery_calc_normalization (mp_int * a, mp_int * b) * Uses Montgomery or Diminished Radix reduction [whichever appropriate] */ -static int ICACHE_FLASH_ATTR +static int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) { mp_int M[TAB_SIZE], res; @@ -3296,7 +3294,7 @@ LBL_M: After that loop you do the squares and add them in. */ -static int ICACHE_FLASH_ATTR +static int fast_s_mp_sqr (mp_int * a, mp_int * b) { int olduse, res, pa, ix, iz; @@ -3384,7 +3382,7 @@ fast_s_mp_sqr (mp_int * a, mp_int * b) #ifdef BN_MP_MUL_D_C /* multiply by a digit */ -static int ICACHE_FLASH_ATTR +static int mp_mul_d (mp_int * a, mp_digit b, mp_int * c) { mp_digit u, *tmpa, *tmpc; diff --git a/components/wpa_supplicant/include/wpa2/utils/base64.h b/components/wpa_supplicant/include/wpa2/utils/base64.h index 91eb874198..aa21fd0fc1 100644 --- a/components/wpa_supplicant/include/wpa2/utils/base64.h +++ b/components/wpa_supplicant/include/wpa2/utils/base64.h @@ -9,9 +9,9 @@ #ifndef BASE64_H #define BASE64_H -unsigned char * _base64_encode(const unsigned char *src, size_t len, +unsigned char * base64_encode(const unsigned char *src, size_t len, size_t *out_len); -unsigned char * _base64_decode(const unsigned char *src, size_t len, +unsigned char * base64_decode(const unsigned char *src, size_t len, size_t *out_len); #endif /* BASE64_H */ diff --git a/components/wpa_supplicant/include/wpa2/utils/ext_password.h b/components/wpa_supplicant/include/wpa2/utils/ext_password.h index e3e46ea084..dfe8e6f0e7 100644 --- a/components/wpa_supplicant/include/wpa2/utils/ext_password.h +++ b/components/wpa_supplicant/include/wpa2/utils/ext_password.h @@ -23,10 +23,10 @@ void ext_password_free(struct wpabuf *pw); #else /* CONFIG_EXT_PASSWORD */ -#define ext_password_init(b, p) ((void *) 1) -#define ext_password_deinit(d) do { } while (0) -#define ext_password_get(d, n) (NULL) -#define ext_password_free(p) do { } while (0) +#define ext_password_init(b, p) +#define ext_password_deinit(d) +#define ext_password_get(d, n) +#define ext_password_free(p) #endif /* CONFIG_EXT_PASSWORD */ diff --git a/components/wpa_supplicant/include/wps/utils/uuid.h b/components/wpa_supplicant/include/wps/utils/uuid.h new file mode 100644 index 0000000000..5e860cbc59 --- /dev/null +++ b/components/wpa_supplicant/include/wps/utils/uuid.h @@ -0,0 +1,18 @@ +/* + * Universally Unique IDentifier (UUID) + * Copyright (c) 2008, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef UUID_H +#define UUID_H + +#define UUID_LEN 16 + +int uuid_str2bin(const char *str, u8 *bin); +int uuid_bin2str(const u8 *bin, char *str, size_t max_len); +int is_nil_uuid(const u8 *uuid); + +#endif /* UUID_H */ diff --git a/components/wpa_supplicant/include/wps/wps.h b/components/wpa_supplicant/include/wps/wps.h new file mode 100644 index 0000000000..c69aedb30d --- /dev/null +++ b/components/wpa_supplicant/include/wps/wps.h @@ -0,0 +1,1067 @@ +/* + * Wi-Fi Protected Setup + * Copyright (c) 2007-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPS_H +#define WPS_H + +#include "rom/ets_sys.h" +#include "wps_defs.h" +#include "esp_wifi_types.h" + +/** + * enum wsc_op_code - EAP-WSC OP-Code values + */ +enum wsc_op_code { + WSC_UPnP = 0 /* No OP Code in UPnP transport */, + WSC_Start = 0x01, + WSC_ACK = 0x02, + WSC_NACK = 0x03, + WSC_MSG = 0x04, + WSC_Done = 0x05, + WSC_FRAG_ACK = 0x06 +}; + +struct wps_registrar; +//struct upnp_wps_device_sm; +struct wps_er; +struct wps_parse_attr; + +/** + * struct wps_credential - WPS Credential + * @ssid: SSID + * @ssid_len: Length of SSID + * @auth_type: Authentication Type (WPS_WIFI_AUTH_OPEN, .. flags) + * @encr_type: Encryption Type (WPS_ENCR_NONE, .. flags) + * @key_idx: Key index + * @key: Key + * @key_len: Key length in octets + * @mac_addr: MAC address of the Credential receiver + * @cred_attr: Unparsed Credential attribute data (used only in cred_cb()); + * this may be %NULL, if not used + * @cred_attr_len: Length of cred_attr in octets + * @ap_channel: AP channel + */ +struct wps_credential { + u8 ssid[32]; + size_t ssid_len; + u16 auth_type; + u16 encr_type; + u8 key_idx; + u8 key[64]; + size_t key_len; + u8 mac_addr[ETH_ALEN]; + const u8 *cred_attr; + size_t cred_attr_len; + u16 ap_channel; +}; + +#define WPS_DEV_TYPE_LEN 8 +#define WPS_DEV_TYPE_BUFSIZE 21 +#define WPS_SEC_DEV_TYPE_MAX_LEN 128 +/* maximum number of advertised WPS vendor extension attributes */ +#define MAX_WPS_VENDOR_EXTENSIONS 10 +/* maximum size of WPS Vendor extension attribute */ +#define WPS_MAX_VENDOR_EXT_LEN 1024 +/* maximum number of parsed WPS vendor extension attributes */ +#define MAX_WPS_PARSE_VENDOR_EXT 10 + +/** + * struct wps_device_data - WPS Device Data + * @mac_addr: Device MAC address + * @device_name: Device Name (0..32 octets encoded in UTF-8) + * @manufacturer: Manufacturer (0..64 octets encoded in UTF-8) + * @model_name: Model Name (0..32 octets encoded in UTF-8) + * @model_number: Model Number (0..32 octets encoded in UTF-8) + * @serial_number: Serial Number (0..32 octets encoded in UTF-8) + * @pri_dev_type: Primary Device Type + * @sec_dev_type: Array of secondary device types + * @num_sec_dev_type: Number of secondary device types + * @os_version: OS Version + * @rf_bands: RF bands (WPS_RF_24GHZ, WPS_RF_50GHZ flags) + * @p2p: Whether the device is a P2P device + */ +struct wps_device_data { + u8 mac_addr[ETH_ALEN]; + char *device_name; + char *manufacturer; + char *model_name; + char *model_number; + char *serial_number; + u8 pri_dev_type[WPS_DEV_TYPE_LEN]; +#define WPS_SEC_DEVICE_TYPES 5 + u8 sec_dev_type[WPS_SEC_DEVICE_TYPES][WPS_DEV_TYPE_LEN]; + u8 num_sec_dev_types; + u32 os_version; + u8 rf_bands; + u16 config_methods; + struct wpabuf *vendor_ext_m1; + struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS]; + + int p2p; +}; + +/** + * struct wps_config - WPS configuration for a single registration protocol run + */ +struct wps_config { + /** + * wps - Pointer to long term WPS context + */ + struct wps_context *wps; + + /** + * registrar - Whether this end is a Registrar + */ + int registrar; + + /** + * pin - Enrollee Device Password (%NULL for Registrar or PBC) + */ + const u8 *pin; + + /** + * pin_len - Length on pin in octets + */ + size_t pin_len; + + /** + * pbc - Whether this is protocol run uses PBC + */ + int pbc; + + /** + * assoc_wps_ie: (Re)AssocReq WPS IE (in AP; %NULL if not AP) + */ + const struct wpabuf *assoc_wps_ie; + + /** + * new_ap_settings - New AP settings (%NULL if not used) + * + * This parameter provides new AP settings when using a wireless + * stations as a Registrar to configure the AP. %NULL means that AP + * will not be reconfigured, i.e., the station will only learn the + * current AP settings by using AP PIN. + */ + const struct wps_credential *new_ap_settings; + + /** + * peer_addr: MAC address of the peer in AP; %NULL if not AP + */ + const u8 *peer_addr; + + /** + * use_psk_key - Use PSK format key in Credential + * + * Force PSK format to be used instead of ASCII passphrase when + * building Credential for an Enrollee. The PSK value is set in + * struct wpa_context::psk. + */ + int use_psk_key; + + /** + * dev_pw_id - Device Password ID for Enrollee when PIN is used + */ + u16 dev_pw_id; + + /** + * p2p_dev_addr - P2P Device Address from (Re)Association Request + * + * On AP/GO, this is set to the P2P Device Address of the associating + * P2P client if a P2P IE is included in the (Re)Association Request + * frame and the P2P Device Address is included. Otherwise, this is set + * to %NULL to indicate the station does not have a P2P Device Address. + */ + const u8 *p2p_dev_addr; + + /** + * pbc_in_m1 - Do not remove PushButton config method in M1 (AP) + * + * This can be used to enable a workaround to allow Windows 7 to use + * PBC with the AP. + */ + int pbc_in_m1; +}; + +/* Bssid of the discard AP which is discarded for not select reg or other reason */ +struct discard_ap_list_t{ + u8 bssid[6]; +}; + +//struct wps_data * wps_init(const struct wps_config *cfg); +struct wps_data * wps_init(void); + +//void wps_deinit(struct wps_data *data); +void wps_deinit(void); + +/** + * enum wps_process_res - WPS message processing result + */ +enum wps_process_res { + /** + * WPS_DONE - Processing done + */ + WPS_DONE, + + /** + * WPS_CONTINUE - Processing continues + */ + WPS_CONTINUE, + + /** + * WPS_FAILURE - Processing failed + */ + WPS_FAILURE, + + /** + * WPS_PENDING - Processing continues, but waiting for an external + * event (e.g., UPnP message from an external Registrar) + */ + WPS_PENDING, + WPS_IGNORE, /* snake, ignore the re-packge */ + + WPS_FRAGMENT /* Tim, send wsc fragment ack */ +}; +enum wps_process_res wps_process_msg(struct wps_data *wps, + enum wsc_op_code op_code, + const struct wpabuf *msg); + +struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code); + +int wps_is_selected_pbc_registrar(const struct wpabuf *msg, u8 *bssid); +#ifdef CONFIG_WPS_PIN +int wps_is_selected_pin_registrar(const struct wpabuf *msg, u8 *bssid); +#endif +int wps_ap_priority_compar(const struct wpabuf *wps_a, + const struct wpabuf *wps_b); +int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr, + int ver1_compat); +const u8 * wps_get_uuid_e(const struct wpabuf *msg); +int wps_is_20(const struct wpabuf *msg); + +struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type); +struct wpabuf * wps_build_assoc_resp_ie(void); +struct wpabuf * wps_build_probe_req_ie(u16 pw_id, struct wps_device_data *dev, + const u8 *uuid, + enum wps_request_type req_type, + unsigned int num_req_dev_types, + const u8 *req_dev_types); + + +/** + * struct wps_registrar_config - WPS Registrar configuration + */ +struct wps_registrar_config { + /** + * new_psk_cb - Callback for new PSK + * @ctx: Higher layer context data (cb_ctx) + * @mac_addr: MAC address of the Enrollee + * @psk: The new PSK + * @psk_len: The length of psk in octets + * Returns: 0 on success, -1 on failure + * + * This callback is called when a new per-device PSK is provisioned. + */ + int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *psk, + size_t psk_len); + + /** + * set_ie_cb - Callback for WPS IE changes + * @ctx: Higher layer context data (cb_ctx) + * @beacon_ie: WPS IE for Beacon + * @probe_resp_ie: WPS IE for Probe Response + * Returns: 0 on success, -1 on failure + * + * This callback is called whenever the WPS IE in Beacon or Probe + * Response frames needs to be changed (AP only). Callee is responsible + * for freeing the buffers. + */ + int (*set_ie_cb)(void *ctx, struct wpabuf *beacon_ie, + struct wpabuf *probe_resp_ie); + + /** + * pin_needed_cb - Callback for requesting a PIN + * @ctx: Higher layer context data (cb_ctx) + * @uuid_e: UUID-E of the unknown Enrollee + * @dev: Device Data from the unknown Enrollee + * + * This callback is called whenever an unknown Enrollee requests to use + * PIN method and a matching PIN (Device Password) is not found in + * Registrar data. + */ + void (*pin_needed_cb)(void *ctx, const u8 *uuid_e, + const struct wps_device_data *dev); + + /** + * reg_success_cb - Callback for reporting successful registration + * @ctx: Higher layer context data (cb_ctx) + * @mac_addr: MAC address of the Enrollee + * @uuid_e: UUID-E of the Enrollee + * @dev_pw: Device Password (PIN) used during registration + * @dev_pw_len: Length of dev_pw in octets + * + * This callback is called whenever an Enrollee completes registration + * successfully. + */ + void (*reg_success_cb)(void *ctx, const u8 *mac_addr, + const u8 *uuid_e, const u8 *dev_pw, + size_t dev_pw_len); + + /** + * set_sel_reg_cb - Callback for reporting selected registrar changes + * @ctx: Higher layer context data (cb_ctx) + * @sel_reg: Whether the Registrar is selected + * @dev_passwd_id: Device Password ID to indicate with method or + * specific password the Registrar intends to use + * @sel_reg_config_methods: Bit field of active config methods + * + * This callback is called whenever the Selected Registrar state + * changes (e.g., a new PIN becomes available or PBC is invoked). This + * callback is only used by External Registrar implementation; + * set_ie_cb() is used by AP implementation in similar caes, but it + * provides the full WPS IE data instead of just the minimal Registrar + * state information. + */ + void (*set_sel_reg_cb)(void *ctx, int sel_reg, u16 dev_passwd_id, + u16 sel_reg_config_methods); + + /** + * enrollee_seen_cb - Callback for reporting Enrollee based on ProbeReq + * @ctx: Higher layer context data (cb_ctx) + * @addr: MAC address of the Enrollee + * @uuid_e: UUID of the Enrollee + * @pri_dev_type: Primary device type + * @config_methods: Config Methods + * @dev_password_id: Device Password ID + * @request_type: Request Type + * @dev_name: Device Name (if available) + */ + void (*enrollee_seen_cb)(void *ctx, const u8 *addr, const u8 *uuid_e, + const u8 *pri_dev_type, u16 config_methods, + u16 dev_password_id, u8 request_type, + const char *dev_name); + + /** + * cb_ctx: Higher layer context data for Registrar callbacks + */ + void *cb_ctx; + + /** + * skip_cred_build: Do not build credential + * + * This option can be used to disable internal code that builds + * Credential attribute into M8 based on the current network + * configuration and Enrollee capabilities. The extra_cred data will + * then be used as the Credential(s). + */ + int skip_cred_build; + + /** + * extra_cred: Additional Credential attribute(s) + * + * This optional data (set to %NULL to disable) can be used to add + * Credential attribute(s) for other networks into M8. If + * skip_cred_build is set, this will also override the automatically + * generated Credential attribute. + */ + const u8 *extra_cred; + + /** + * extra_cred_len: Length of extra_cred in octets + */ + size_t extra_cred_len; + + /** + * disable_auto_conf - Disable auto-configuration on first registration + * + * By default, the AP that is started in not configured state will + * generate a random PSK and move to configured state when the first + * registration protocol run is completed successfully. This option can + * be used to disable this functionality and leave it up to an external + * program to take care of configuration. This requires the extra_cred + * to be set with a suitable Credential and skip_cred_build being used. + */ + int disable_auto_conf; + + /** + * static_wep_only - Whether the BSS supports only static WEP + */ + int static_wep_only; + + /** + * dualband - Whether this is a concurrent dualband AP + */ + int dualband; +}; + + +/** + * enum wps_event - WPS event types + */ +enum wps_event { + /** + * WPS_EV_M2D - M2D received (Registrar did not know us) + */ + WPS_EV_M2D, + + /** + * WPS_EV_FAIL - Registration failed + */ + WPS_EV_FAIL, + + /** + * WPS_EV_SUCCESS - Registration succeeded + */ + WPS_EV_SUCCESS, + + /** + * WPS_EV_PWD_AUTH_FAIL - Password authentication failed + */ + WPS_EV_PWD_AUTH_FAIL, + + /** + * WPS_EV_PBC_OVERLAP - PBC session overlap detected + */ + WPS_EV_PBC_OVERLAP, + + /** + * WPS_EV_PBC_TIMEOUT - PBC walktime expired before protocol run start + */ + WPS_EV_PBC_TIMEOUT, + + /** + * WPS_EV_ER_AP_ADD - ER: AP added + */ + WPS_EV_ER_AP_ADD, + + /** + * WPS_EV_ER_AP_REMOVE - ER: AP removed + */ + WPS_EV_ER_AP_REMOVE, + + /** + * WPS_EV_ER_ENROLLEE_ADD - ER: Enrollee added + */ + WPS_EV_ER_ENROLLEE_ADD, + + /** + * WPS_EV_ER_ENROLLEE_REMOVE - ER: Enrollee removed + */ + WPS_EV_ER_ENROLLEE_REMOVE, + + /** + * WPS_EV_ER_AP_SETTINGS - ER: AP Settings learned + */ + WPS_EV_ER_AP_SETTINGS, + + /** + * WPS_EV_ER_SET_SELECTED_REGISTRAR - ER: SetSelectedRegistrar event + */ + WPS_EV_ER_SET_SELECTED_REGISTRAR, + + /** + * WPS_EV_AP_PIN_SUCCESS - External Registrar used correct AP PIN + */ + WPS_EV_AP_PIN_SUCCESS +}; + +/** + * union wps_event_data - WPS event data + */ +union wps_event_data { + /** + * struct wps_event_m2d - M2D event data + */ + struct wps_event_m2d { + u16 config_methods; + const u8 *manufacturer; + size_t manufacturer_len; + const u8 *model_name; + size_t model_name_len; + const u8 *model_number; + size_t model_number_len; + const u8 *serial_number; + size_t serial_number_len; + const u8 *dev_name; + size_t dev_name_len; + const u8 *primary_dev_type; /* 8 octets */ + u16 config_error; + u16 dev_password_id; + } m2d; + + /** + * struct wps_event_fail - Registration failure information + * @msg: enum wps_msg_type + */ + struct wps_event_fail { + int msg; + u16 config_error; + u16 error_indication; + } fail; + + struct wps_event_pwd_auth_fail { + int enrollee; + int part; + } pwd_auth_fail; + + struct wps_event_er_ap { + const u8 *uuid; + const u8 *mac_addr; + const char *friendly_name; + const char *manufacturer; + const char *manufacturer_url; + const char *model_description; + const char *model_name; + const char *model_number; + const char *model_url; + const char *serial_number; + const char *upc; + const u8 *pri_dev_type; + u8 wps_state; + } ap; + + struct wps_event_er_enrollee { + const u8 *uuid; + const u8 *mac_addr; + int m1_received; + u16 config_methods; + u16 dev_passwd_id; + const u8 *pri_dev_type; + const char *dev_name; + const char *manufacturer; + const char *model_name; + const char *model_number; + const char *serial_number; + } enrollee; + + struct wps_event_er_ap_settings { + const u8 *uuid; + const struct wps_credential *cred; + } ap_settings; + + struct wps_event_er_set_selected_registrar { + const u8 *uuid; + int sel_reg; + u16 dev_passwd_id; + u16 sel_reg_config_methods; + enum { + WPS_ER_SET_SEL_REG_START, + WPS_ER_SET_SEL_REG_DONE, + WPS_ER_SET_SEL_REG_FAILED + } state; + } set_sel_reg; +}; +#ifdef CONFIG_WPS_UPNP +/** + * struct upnp_pending_message - Pending PutWLANResponse messages + * @next: Pointer to next pending message or %NULL + * @addr: NewWLANEventMAC + * @msg: NewMessage + * @type: Message Type + */ +struct upnp_pending_message { + struct upnp_pending_message *next; + u8 addr[ETH_ALEN]; + struct wpabuf *msg; + enum wps_msg_type type; +}; +void wps_free_pending_msgs(struct upnp_pending_message *msgs); +#endif +/** + * struct wps_context - Long term WPS context data + * + * This data is stored at the higher layer Authenticator or Supplicant data + * structures and it is maintained over multiple registration protocol runs. + */ +struct wps_context { + /** + * ap - Whether the local end is an access point + */ + int ap; + + /** + * registrar - Pointer to WPS registrar data from wps_registrar_init() + */ + struct wps_registrar *registrar; + + /** + * wps_state - Current WPS state + */ + enum wps_state wps_state; + + /** + * ap_setup_locked - Whether AP setup is locked (only used at AP) + */ + int ap_setup_locked; + + /** + * uuid - Own UUID + */ + u8 uuid[16]; + + /** + * ssid - SSID + * + * This SSID is used by the Registrar to fill in information for + * Credentials. In addition, AP uses it when acting as an Enrollee to + * notify Registrar of the current configuration. + */ + u8 ssid[32]; + + /** + * ssid_len - Length of ssid in octets + */ + size_t ssid_len; + + /** + * dev - Own WPS device data + */ + struct wps_device_data dev; + + /** + * dh_ctx - Context data for Diffie-Hellman operation + */ + void *dh_ctx; + + /** + * dh_privkey - Diffie-Hellman private key + */ + struct wpabuf *dh_privkey; + + /** + * dh_pubkey_oob - Diffie-Hellman public key + */ + struct wpabuf *dh_pubkey; + + /** + * config_methods - Enabled configuration methods + * + * Bit field of WPS_CONFIG_* + */ + u16 config_methods; + + /** + * encr_types - Enabled encryption types (bit field of WPS_ENCR_*) + */ + u16 encr_types; + + /** + * auth_types - Authentication types (bit field of WPS_AUTH_*) + */ + u16 auth_types; + + /** + * network_key - The current Network Key (PSK) or %NULL to generate new + * + * If %NULL, Registrar will generate per-device PSK. In addition, AP + * uses this when acting as an Enrollee to notify Registrar of the + * current configuration. + * + * When using WPA/WPA2-Person, this key can be either the ASCII + * passphrase (8..63 characters) or the 32-octet PSK (64 hex + * characters). When this is set to the ASCII passphrase, the PSK can + * be provided in the psk buffer and used per-Enrollee to control which + * key type is included in the Credential (e.g., to reduce calculation + * need on low-powered devices by provisioning PSK while still allowing + * other devices to get the passphrase). + */ + u8 *network_key; + + /** + * network_key_len - Length of network_key in octets + */ + size_t network_key_len; + + /** + * psk - The current network PSK + * + * This optional value can be used to provide the current PSK if + * network_key is set to the ASCII passphrase. + */ + u8 psk[32]; + + /** + * psk_set - Whether psk value is set + */ + int psk_set; + + /** + * ap_settings - AP Settings override for M7 (only used at AP) + * + * If %NULL, AP Settings attributes will be generated based on the + * current network configuration. + */ + u8 *ap_settings; + + /** + * ap_settings_len - Length of ap_settings in octets + */ + size_t ap_settings_len; + + /** + * friendly_name - Friendly Name (required for UPnP) + */ + char *friendly_name; + + /** + * manufacturer_url - Manufacturer URL (optional for UPnP) + */ + char *manufacturer_url; + + /** + * model_description - Model Description (recommended for UPnP) + */ + char *model_description; + + /** + * model_url - Model URL (optional for UPnP) + */ + char *model_url; + + /** + * upc - Universal Product Code (optional for UPnP) + */ + char *upc; + + /** + * cred_cb - Callback to notify that new Credentials were received + * @ctx: Higher layer context data (cb_ctx) + * @cred: The received Credential + * Return: 0 on success, -1 on failure + */ + int (*cred_cb)(void *ctx, const struct wps_credential *cred); + + /** + * event_cb - Event callback (state information about progress) + * @ctx: Higher layer context data (cb_ctx) + * @event: Event type + * @data: Event data + */ + void (*event_cb)(void *ctx, enum wps_event event, + union wps_event_data *data); + + /** + * cb_ctx: Higher layer context data for callbacks + */ + void *cb_ctx; + + //struct upnp_wps_device_sm *wps_upnp; + + /* Pending messages from UPnP PutWLANResponse */ + //struct upnp_pending_message *upnp_msgs; +#ifdef CONFIG_WPS_NFC + + u16 ap_nfc_dev_pw_id; + struct wpabuf *ap_nfc_dh_pubkey; + struct wpabuf *ap_nfc_dh_privkey; + struct wpabuf *ap_nfc_dev_pw; +#endif +}; + +struct wps_registrar * +wps_registrar_init(struct wps_context *wps, + const struct wps_registrar_config *cfg); +void wps_registrar_deinit(struct wps_registrar *reg); +#ifdef CONFIG_WPS_PIN + +int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *addr, + const u8 *uuid, const u8 *pin, size_t pin_len, + int timeout); +int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid); +int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid); +#endif +int wps_registrar_wps_cancel(struct wps_registrar *reg); + +int wps_registrar_button_pushed(struct wps_registrar *reg, + const u8 *p2p_dev_addr); +void wps_registrar_complete(struct wps_registrar *registrar, const u8 *uuid_e, + const u8 *dev_pw, size_t dev_pw_len); +void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr, + const struct wpabuf *wps_data, + int p2p_wildcard); +int wps_registrar_update_ie(struct wps_registrar *reg); +int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr, + char *buf, size_t buflen); +int wps_registrar_config_ap(struct wps_registrar *reg, + struct wps_credential *cred); +#ifdef CONFIG_WPS_NFC + +int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg, + const u8 *pubkey_hash, u16 pw_id, + const u8 *dev_pw, size_t dev_pw_len); +int wps_registrar_add_nfc_password_token(struct wps_registrar *reg, + const u8 *oob_dev_pw, + size_t oob_dev_pw_len); +#endif +int wps_build_credential_wrap(struct wpabuf *msg, + const struct wps_credential *cred); +#ifdef CONFIG_WPS_PIN + +unsigned int wps_pin_checksum(unsigned int pin); +unsigned int wps_pin_valid(unsigned int pin); +unsigned int wps_generate_pin(void); +int wps_pin_str_valid(const char *pin); +#endif + +#ifdef CONFIG_WPS_OOB + +struct wpabuf * wps_get_oob_cred(struct wps_context *wps); +int wps_oob_use_cred(struct wps_context *wps, struct wps_parse_attr *attr); +#endif +int wps_attr_text(struct wpabuf *data, char *buf, char *end); + +struct wps_er * wps_er_init(struct wps_context *wps, const char *ifname, + const char *filter); +void wps_er_refresh(struct wps_er *er); +void wps_er_deinit(struct wps_er *er, void (*cb)(void *ctx), void *ctx); +void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id, + u16 sel_reg_config_methods); +int wps_er_pbc(struct wps_er *er, const u8 *uuid); +int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *pin, + size_t pin_len); +int wps_er_set_config(struct wps_er *er, const u8 *uuid, + const struct wps_credential *cred); +int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *pin, + size_t pin_len, const struct wps_credential *cred); +#ifdef CONFIG_WPS_NFC + +struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid); + +#endif + +int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]); +char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf, + size_t buf_len); +void uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid); +u16 wps_config_methods_str2bin(const char *str); + +#ifdef CONFIG_WPS_NFC + +struct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id, + const struct wpabuf *pubkey, + const struct wpabuf *dev_pw); +struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey, + struct wpabuf **privkey, + struct wpabuf **dev_pw); +#endif + +/* ndef.c */ +struct wpabuf * ndef_parse_wifi(const struct wpabuf *buf); +struct wpabuf * ndef_build_wifi(const struct wpabuf *buf); +struct wpabuf * ndef_build_wifi_hr(void); + +#ifdef CONFIG_WPS_STRICT +int wps_validate_beacon(const struct wpabuf *wps_ie); +int wps_validate_beacon_probe_resp(const struct wpabuf *wps_ie, int probe, + const u8 *addr); +int wps_validate_probe_req(const struct wpabuf *wps_ie, const u8 *addr); +int wps_validate_assoc_req(const struct wpabuf *wps_ie); +int wps_validate_assoc_resp(const struct wpabuf *wps_ie); +int wps_validate_m1(const struct wpabuf *tlvs); +int wps_validate_m2(const struct wpabuf *tlvs); +int wps_validate_m2d(const struct wpabuf *tlvs); +int wps_validate_m3(const struct wpabuf *tlvs); +int wps_validate_m4(const struct wpabuf *tlvs); +int wps_validate_m4_encr(const struct wpabuf *tlvs, int wps2); +int wps_validate_m5(const struct wpabuf *tlvs); +int wps_validate_m5_encr(const struct wpabuf *tlvs, int wps2); +int wps_validate_m6(const struct wpabuf *tlvs); +int wps_validate_m6_encr(const struct wpabuf *tlvs, int wps2); +int wps_validate_m7(const struct wpabuf *tlvs); +int wps_validate_m7_encr(const struct wpabuf *tlvs, int ap, int wps2); +int wps_validate_m8(const struct wpabuf *tlvs); +int wps_validate_m8_encr(const struct wpabuf *tlvs, int ap, int wps2); +int wps_validate_wsc_ack(const struct wpabuf *tlvs); +int wps_validate_wsc_nack(const struct wpabuf *tlvs); +int wps_validate_wsc_done(const struct wpabuf *tlvs); +int wps_validate_upnp_set_selected_registrar(const struct wpabuf *tlvs); +#else /* CONFIG_WPS_STRICT */ +static inline int wps_validate_beacon(const struct wpabuf *wps_ie){ + return 0; +} + +static inline int wps_validate_beacon_probe_resp(const struct wpabuf *wps_ie, + int probe, const u8 *addr) +{ + return 0; +} + +static inline int wps_validate_probe_req(const struct wpabuf *wps_ie, + const u8 *addr) +{ + return 0; +} + +static inline int wps_validate_assoc_req(const struct wpabuf *wps_ie) +{ + return 0; +} + +static inline int wps_validate_assoc_resp(const struct wpabuf *wps_ie) +{ + return 0; +} + +static inline int wps_validate_m1(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m2(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m2d(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m3(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m4(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m4_encr(const struct wpabuf *tlvs, int wps2) +{ + return 0; +} + +static inline int wps_validate_m5(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m5_encr(const struct wpabuf *tlvs, int wps2) +{ + return 0; +} + +static inline int wps_validate_m6(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m6_encr(const struct wpabuf *tlvs, int wps2) +{ + return 0; +} + +static inline int wps_validate_m7(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m7_encr(const struct wpabuf *tlvs, int ap, + int wps2) +{ + return 0; +} + +static inline int wps_validate_m8(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m8_encr(const struct wpabuf *tlvs, int ap, + int wps2) +{ + return 0; +} + +static inline int wps_validate_wsc_ack(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_wsc_nack(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_wsc_done(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_upnp_set_selected_registrar( + const struct wpabuf *tlvs) +{ + return 0; +} +#endif /* CONFIG_WPS_STRICT */ + +enum wps_cb_status { + WPS_CB_ST_SUCCESS = 0, + WPS_CB_ST_FAILED, + WPS_CB_ST_TIMEOUT, + WPS_CB_ST_WEP, + WPS_CB_ST_SCAN_ERR, +}; + +typedef void (*wps_st_cb_t)(int status); + +#ifdef USE_WPS_TASK +#define SIG_WPS_START 0 +#define SIG_WPS_RX 1 +#define SIG_WPS_NUM 2 +#endif + +#define WPS_EAP_EXT_VENDOR_TYPE "WFA-SimpleConfig-Enrollee-1-0" +#define WPS_OUTBUF_SIZE 500 +struct wps_sm { + struct wps_config *wps_cfg; + struct wps_context *wps_ctx; + struct wps_data *wps; + char identity[32]; + u8 identity_len; + u8 ownaddr[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + u8 ssid[32]; + u8 ssid_len; + struct wps_device_data *dev; + u8 uuid[16]; + u8 eapol_version; + char key[64]; + u8 key_len; + ETSTimer wps_timeout_timer; + ETSTimer wps_msg_timeout_timer; + ETSTimer wps_scan_timer; + ETSTimer wps_success_cb_timer; + ETSTimer wps_eapol_start_timer; + wps_st_cb_t st_cb; + u8 current_identifier; + bool is_wps_scan; + u8 channel; + u8 scan_cnt; +#ifdef USE_WPS_TASK + u8 wps_sig_cnt[SIG_WPS_NUM]; +#endif + u8 discover_ssid_cnt; + bool ignore_sel_reg; + struct discard_ap_list_t dis_ap_list[WPS_MAX_DIS_AP_NUM]; + u8 discard_ap_cnt; + wifi_sta_config_t config; +}; + +#define IEEE80211_CAPINFO_PRIVACY 0x0010 + +struct wps_sm *wps_sm_get(void); +int wps_ssid_save(u8 *ssid, u8 ssid_len); +int wps_key_save(char *key, u8 key_len); +int wps_station_wps_register_cb(wps_st_cb_t cb); +int wps_station_wps_unregister_cb(void); +int wps_start_pending(void); +int wps_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len); + +int wps_dev_deinit(struct wps_device_data *dev); +#endif /* WPS_H */ diff --git a/components/wpa_supplicant/include/wps/wps_attr_parse.h b/components/wpa_supplicant/include/wps/wps_attr_parse.h new file mode 100644 index 0000000000..86061aea06 --- /dev/null +++ b/components/wpa_supplicant/include/wps/wps_attr_parse.h @@ -0,0 +1,108 @@ +/* + * Wi-Fi Protected Setup - attribute parsing + * Copyright (c) 2008-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPS_ATTR_PARSE_H +#define WPS_ATTR_PARSE_H + +#include "wps/wps.h" + +struct wps_parse_attr { + /* fixed length fields */ + const u8 *version; /* 1 octet */ + const u8 *version2; /* 1 octet */ + const u8 *msg_type; /* 1 octet */ + const u8 *enrollee_nonce; /* WPS_NONCE_LEN (16) octets */ + const u8 *registrar_nonce; /* WPS_NONCE_LEN (16) octets */ + const u8 *uuid_r; /* WPS_UUID_LEN (16) octets */ + const u8 *uuid_e; /* WPS_UUID_LEN (16) octets */ + const u8 *auth_type_flags; /* 2 octets */ + const u8 *encr_type_flags; /* 2 octets */ + const u8 *conn_type_flags; /* 1 octet */ + const u8 *config_methods; /* 2 octets */ + const u8 *sel_reg_config_methods; /* 2 octets */ + const u8 *primary_dev_type; /* 8 octets */ + const u8 *rf_bands; /* 1 octet */ + const u8 *assoc_state; /* 2 octets */ + const u8 *config_error; /* 2 octets */ + const u8 *dev_password_id; /* 2 octets */ + const u8 *os_version; /* 4 octets */ + const u8 *wps_state; /* 1 octet */ + const u8 *authenticator; /* WPS_AUTHENTICATOR_LEN (8) octets */ + const u8 *r_hash1; /* WPS_HASH_LEN (32) octets */ + const u8 *r_hash2; /* WPS_HASH_LEN (32) octets */ + const u8 *e_hash1; /* WPS_HASH_LEN (32) octets */ + const u8 *e_hash2; /* WPS_HASH_LEN (32) octets */ + const u8 *r_snonce1; /* WPS_SECRET_NONCE_LEN (16) octets */ + const u8 *r_snonce2; /* WPS_SECRET_NONCE_LEN (16) octets */ + const u8 *e_snonce1; /* WPS_SECRET_NONCE_LEN (16) octets */ + const u8 *e_snonce2; /* WPS_SECRET_NONCE_LEN (16) octets */ + const u8 *key_wrap_auth; /* WPS_KWA_LEN (8) octets */ + const u8 *auth_type; /* 2 octets */ + const u8 *encr_type; /* 2 octets */ + const u8 *network_idx; /* 1 octet */ + const u8 *network_key_idx; /* 1 octet */ + const u8 *mac_addr; /* ETH_ALEN (6) octets */ + const u8 *key_prov_auto; /* 1 octet (Bool) */ + const u8 *dot1x_enabled; /* 1 octet (Bool) */ + const u8 *selected_registrar; /* 1 octet (Bool) */ + const u8 *request_type; /* 1 octet */ + const u8 *response_type; /* 1 octet */ + const u8 *ap_setup_locked; /* 1 octet */ + const u8 *settings_delay_time; /* 1 octet */ + const u8 *network_key_shareable; /* 1 octet (Bool) */ + const u8 *request_to_enroll; /* 1 octet (Bool) */ + const u8 *ap_channel; /* 2 octets */ + + /* variable length fields */ + const u8 *manufacturer; + size_t manufacturer_len; + const u8 *model_name; + size_t model_name_len; + const u8 *model_number; + size_t model_number_len; + const u8 *serial_number; + size_t serial_number_len; + const u8 *dev_name; + size_t dev_name_len; + const u8 *public_key; + size_t public_key_len; + const u8 *encr_settings; + size_t encr_settings_len; + const u8 *ssid; /* <= 32 octets */ + size_t ssid_len; + const u8 *network_key; /* <= 64 octets */ + size_t network_key_len; + const u8 *eap_type; /* <= 8 octets */ + size_t eap_type_len; + const u8 *eap_identity; /* <= 64 octets */ + size_t eap_identity_len; + const u8 *authorized_macs; /* <= 30 octets */ + size_t authorized_macs_len; + const u8 *sec_dev_type_list; /* <= 128 octets */ + size_t sec_dev_type_list_len; + const u8 *oob_dev_password; /* 38..54 octets */ + size_t oob_dev_password_len; + + /* attributes that can occur multiple times */ +#define MAX_CRED_COUNT 10 + const u8 *cred[MAX_CRED_COUNT]; + size_t cred_len[MAX_CRED_COUNT]; + size_t num_cred; + +#define MAX_REQ_DEV_TYPE_COUNT 10 + const u8 *req_dev_type[MAX_REQ_DEV_TYPE_COUNT]; + size_t num_req_dev_type; + + const u8 *vendor_ext[MAX_WPS_PARSE_VENDOR_EXT]; + size_t vendor_ext_len[MAX_WPS_PARSE_VENDOR_EXT]; + size_t num_vendor_ext; +}; + +int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr); + +#endif /* WPS_ATTR_PARSE_H */ diff --git a/components/wpa_supplicant/include/wps/wps_defs.h b/components/wpa_supplicant/include/wps/wps_defs.h new file mode 100644 index 0000000000..d100202da6 --- /dev/null +++ b/components/wpa_supplicant/include/wps/wps_defs.h @@ -0,0 +1,342 @@ +/* + * Wi-Fi Protected Setup - message definitions + * Copyright (c) 2008, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPS_DEFS_H +#define WPS_DEFS_H + +#ifdef CONFIG_WPS_TESTING + +extern int wps_version_number; +extern int wps_testing_dummy_cred; +#define WPS_VERSION wps_version_number + +#else /* CONFIG_WPS_TESTING */ + +#ifdef CONFIG_WPS2 +#define WPS_VERSION 0x20 +#else /* CONFIG_WPS2 */ +#define WPS_VERSION 0x10 +#endif /* CONFIG_WPS2 */ + +#endif /* CONFIG_WPS_TESTING */ + +#define CONFIG_WPS_STRICT + +/* Diffie-Hellman 1536-bit MODP Group; RFC 3526, Group 5 */ +#define WPS_DH_GROUP 5 + +#define WPS_UUID_LEN 16 +#define WPS_NONCE_LEN 16 +#define WPS_AUTHENTICATOR_LEN 8 +#define WPS_AUTHKEY_LEN 32 +#define WPS_KEYWRAPKEY_LEN 16 +#define WPS_EMSK_LEN 32 +#define WPS_PSK_LEN 16 +#define WPS_SECRET_NONCE_LEN 16 +#define WPS_HASH_LEN 32 +#define WPS_KWA_LEN 8 +#define WPS_MGMTAUTHKEY_LEN 32 +#define WPS_MGMTENCKEY_LEN 16 +#define WPS_MGMT_KEY_ID_LEN 16 +#define WPS_OOB_DEVICE_PASSWORD_MIN_LEN 16 +#define WPS_OOB_DEVICE_PASSWORD_LEN 32 +#define WPS_OOB_PUBKEY_HASH_LEN 20 + +/* Attribute Types */ +enum wps_attribute { + ATTR_AP_CHANNEL = 0x1001, + ATTR_ASSOC_STATE = 0x1002, + ATTR_AUTH_TYPE = 0x1003, + ATTR_AUTH_TYPE_FLAGS = 0x1004, + ATTR_AUTHENTICATOR = 0x1005, + ATTR_CONFIG_METHODS = 0x1008, + ATTR_CONFIG_ERROR = 0x1009, + ATTR_CONFIRM_URL4 = 0x100a, + ATTR_CONFIRM_URL6 = 0x100b, + ATTR_CONN_TYPE = 0x100c, + ATTR_CONN_TYPE_FLAGS = 0x100d, + ATTR_CRED = 0x100e, + ATTR_ENCR_TYPE = 0x100f, + ATTR_ENCR_TYPE_FLAGS = 0x1010, + ATTR_DEV_NAME = 0x1011, + ATTR_DEV_PASSWORD_ID = 0x1012, + ATTR_E_HASH1 = 0x1014, + ATTR_E_HASH2 = 0x1015, + ATTR_E_SNONCE1 = 0x1016, + ATTR_E_SNONCE2 = 0x1017, + ATTR_ENCR_SETTINGS = 0x1018, + ATTR_ENROLLEE_NONCE = 0x101a, + ATTR_FEATURE_ID = 0x101b, + ATTR_IDENTITY = 0x101c, + ATTR_IDENTITY_PROOF = 0x101d, + ATTR_KEY_WRAP_AUTH = 0x101e, + ATTR_KEY_ID = 0x101f, + ATTR_MAC_ADDR = 0x1020, + ATTR_MANUFACTURER = 0x1021, + ATTR_MSG_TYPE = 0x1022, + ATTR_MODEL_NAME = 0x1023, + ATTR_MODEL_NUMBER = 0x1024, + ATTR_NETWORK_INDEX = 0x1026, + ATTR_NETWORK_KEY = 0x1027, + ATTR_NETWORK_KEY_INDEX = 0x1028, + ATTR_NEW_DEVICE_NAME = 0x1029, + ATTR_NEW_PASSWORD = 0x102a, + ATTR_OOB_DEVICE_PASSWORD = 0x102c, + ATTR_OS_VERSION = 0x102d, + ATTR_POWER_LEVEL = 0x102f, + ATTR_PSK_CURRENT = 0x1030, + ATTR_PSK_MAX = 0x1031, + ATTR_PUBLIC_KEY = 0x1032, + ATTR_RADIO_ENABLE = 0x1033, + ATTR_REBOOT = 0x1034, + ATTR_REGISTRAR_CURRENT = 0x1035, + ATTR_REGISTRAR_ESTABLISHED = 0x1036, + ATTR_REGISTRAR_LIST = 0x1037, + ATTR_REGISTRAR_MAX = 0x1038, + ATTR_REGISTRAR_NONCE = 0x1039, + ATTR_REQUEST_TYPE = 0x103a, + ATTR_RESPONSE_TYPE = 0x103b, + ATTR_RF_BANDS = 0x103c, + ATTR_R_HASH1 = 0x103d, + ATTR_R_HASH2 = 0x103e, + ATTR_R_SNONCE1 = 0x103f, + ATTR_R_SNONCE2 = 0x1040, + ATTR_SELECTED_REGISTRAR = 0x1041, + ATTR_SERIAL_NUMBER = 0x1042, + ATTR_WPS_STATE = 0x1044, + ATTR_SSID = 0x1045, + ATTR_TOTAL_NETWORKS = 0x1046, + ATTR_UUID_E = 0x1047, + ATTR_UUID_R = 0x1048, + ATTR_VENDOR_EXT = 0x1049, + ATTR_VERSION = 0x104a, + ATTR_X509_CERT_REQ = 0x104b, + ATTR_X509_CERT = 0x104c, + ATTR_EAP_IDENTITY = 0x104d, + ATTR_MSG_COUNTER = 0x104e, + ATTR_PUBKEY_HASH = 0x104f, + ATTR_REKEY_KEY = 0x1050, + ATTR_KEY_LIFETIME = 0x1051, + ATTR_PERMITTED_CFG_METHODS = 0x1052, + ATTR_SELECTED_REGISTRAR_CONFIG_METHODS = 0x1053, + ATTR_PRIMARY_DEV_TYPE = 0x1054, + ATTR_SECONDARY_DEV_TYPE_LIST = 0x1055, + ATTR_PORTABLE_DEV = 0x1056, + ATTR_AP_SETUP_LOCKED = 0x1057, + ATTR_APPLICATION_EXT = 0x1058, + ATTR_EAP_TYPE = 0x1059, + ATTR_IV = 0x1060, + ATTR_KEY_PROVIDED_AUTO = 0x1061, + ATTR_802_1X_ENABLED = 0x1062, + ATTR_APPSESSIONKEY = 0x1063, + ATTR_WEPTRANSMITKEY = 0x1064, + ATTR_REQUESTED_DEV_TYPE = 0x106a, + ATTR_EXTENSIBILITY_TEST = 0x10fa /* _NOT_ defined in the spec */ +}; + +#define WPS_VENDOR_ID_WFA 14122 + +/* WFA Vendor Extension subelements */ +enum { + WFA_ELEM_VERSION2 = 0x00, + WFA_ELEM_AUTHORIZEDMACS = 0x01, + WFA_ELEM_NETWORK_KEY_SHAREABLE = 0x02, + WFA_ELEM_REQUEST_TO_ENROLL = 0x03, + WFA_ELEM_SETTINGS_DELAY_TIME = 0x04 +}; + +/* Device Password ID */ +enum wps_dev_password_id { + DEV_PW_DEFAULT = 0x0000, + DEV_PW_USER_SPECIFIED = 0x0001, + DEV_PW_MACHINE_SPECIFIED = 0x0002, + DEV_PW_REKEY = 0x0003, + DEV_PW_PUSHBUTTON = 0x0004, + DEV_PW_REGISTRAR_SPECIFIED = 0x0005 +}; + +/* WPS message flag */ +enum wps_msg_flag { + WPS_MSG_FLAG_MORE = 0x01, + WPS_MSG_FLAG_LEN = 0x02 +}; + +/* Message Type */ +enum wps_msg_type { + WPS_Beacon = 0x01, + WPS_ProbeRequest = 0x02, + WPS_ProbeResponse = 0x03, + WPS_M1 = 0x04, + WPS_M2 = 0x05, + WPS_M2D = 0x06, + WPS_M3 = 0x07, + WPS_M4 = 0x08, + WPS_M5 = 0x09, + WPS_M6 = 0x0a, + WPS_M7 = 0x0b, + WPS_M8 = 0x0c, + WPS_WSC_ACK = 0x0d, + WPS_WSC_NACK = 0x0e, + WPS_WSC_DONE = 0x0f +}; + +/* Authentication Type Flags */ +#define WPS_WIFI_AUTH_OPEN 0x0001 +#define WPS_AUTH_WPAPSK 0x0002 +#define WPS_AUTH_SHARED 0x0004 +#define WPS_AUTH_WPA 0x0008 +#define WPS_AUTH_WPA2 0x0010 +#define WPS_AUTH_WPA2PSK 0x0020 +#define WPS_AUTH_TYPES (WPS_WIFI_AUTH_OPEN | WPS_AUTH_WPAPSK | WPS_AUTH_SHARED | \ + WPS_AUTH_WPA | WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK) + +/* Encryption Type Flags */ +#define WPS_ENCR_NONE 0x0001 +#define WPS_ENCR_WEP 0x0002 +#define WPS_ENCR_TKIP 0x0004 +#define WPS_ENCR_AES 0x0008 +#define WPS_ENCR_TYPES (WPS_ENCR_NONE | WPS_ENCR_WEP | WPS_ENCR_TKIP | \ + WPS_ENCR_AES) + +/* Configuration Error */ +enum wps_config_error { + WPS_CFG_NO_ERROR = 0, + WPS_CFG_OOB_IFACE_READ_ERROR = 1, + WPS_CFG_DECRYPTION_CRC_FAILURE = 2, + WPS_CFG_24_CHAN_NOT_SUPPORTED = 3, + WPS_CFG_50_CHAN_NOT_SUPPORTED = 4, + WPS_CFG_SIGNAL_TOO_WEAK = 5, + WPS_CFG_NETWORK_AUTH_FAILURE = 6, + WPS_CFG_NETWORK_ASSOC_FAILURE = 7, + WPS_CFG_NO_DHCP_RESPONSE = 8, + WPS_CFG_FAILED_DHCP_CONFIG = 9, + WPS_CFG_IP_ADDR_CONFLICT = 10, + WPS_CFG_NO_CONN_TO_REGISTRAR = 11, + WPS_CFG_MULTIPLE_PBC_DETECTED = 12, + WPS_CFG_ROGUE_SUSPECTED = 13, + WPS_CFG_DEVICE_BUSY = 14, + WPS_CFG_SETUP_LOCKED = 15, + WPS_CFG_MSG_TIMEOUT = 16, + WPS_CFG_REG_SESS_TIMEOUT = 17, + WPS_CFG_DEV_PASSWORD_AUTH_FAILURE = 18 +}; + +/* Vendor specific Error Indication for WPS event messages */ +enum wps_error_indication { + WPS_EI_NO_ERROR, + WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED, + WPS_EI_SECURITY_WEP_PROHIBITED, + NUM_WPS_EI_VALUES +}; + +/* RF Bands */ +#define WPS_RF_24GHZ 0x01 +#define WPS_RF_50GHZ 0x02 + +/* Config Methods */ +#define WPS_CONFIG_USBA 0x0001 +#define WPS_CONFIG_ETHERNET 0x0002 +#define WPS_CONFIG_LABEL 0x0004 +#define WPS_CONFIG_DISPLAY 0x0008 +#define WPS_CONFIG_EXT_NFC_TOKEN 0x0010 +#define WPS_CONFIG_INT_NFC_TOKEN 0x0020 +#define WPS_CONFIG_NFC_INTERFACE 0x0040 +#define WPS_CONFIG_PUSHBUTTON 0x0080 +#define WPS_CONFIG_KEYPAD 0x0100 +#ifdef CONFIG_WPS2 +#define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280 +#define WPS_CONFIG_PHY_PUSHBUTTON 0x0480 +#define WPS_CONFIG_VIRT_DISPLAY 0x2008 +#define WPS_CONFIG_PHY_DISPLAY 0x4008 +#endif /* CONFIG_WPS2 */ + +/* Connection Type Flags */ +#define WPS_CONN_ESS 0x01 +#define WPS_CONN_IBSS 0x02 + +/* Wi-Fi Protected Setup State */ +enum wps_state { + WPS_STATE_NOT_CONFIGURED = 1, + WPS_STATE_CONFIGURED = 2 +}; + +/* Association State */ +enum wps_assoc_state { + WPS_ASSOC_NOT_ASSOC = 0, + WPS_ASSOC_CONN_SUCCESS = 1, + WPS_ASSOC_CFG_FAILURE = 2, + WPS_ASSOC_FAILURE = 3, + WPS_ASSOC_IP_FAILURE = 4 +}; + + +#define WPS_DEV_OUI_WFA 0x0050f204 + +enum wps_dev_categ { + WPS_DEV_COMPUTER = 1, + WPS_DEV_INPUT = 2, + WPS_DEV_PRINTER = 3, + WPS_DEV_CAMERA = 4, + WPS_DEV_STORAGE = 5, + WPS_DEV_NETWORK_INFRA = 6, + WPS_DEV_DISPLAY = 7, + WPS_DEV_MULTIMEDIA = 8, + WPS_DEV_GAMING = 9, + WPS_DEV_PHONE = 10 +}; + +enum wps_dev_subcateg { + WPS_DEV_COMPUTER_PC = 1, + WPS_DEV_COMPUTER_SERVER = 2, + WPS_DEV_COMPUTER_MEDIA_CENTER = 3, + WPS_DEV_PRINTER_PRINTER = 1, + WPS_DEV_PRINTER_SCANNER = 2, + WPS_DEV_CAMERA_DIGITAL_STILL_CAMERA = 1, + WPS_DEV_STORAGE_NAS = 1, + WPS_DEV_NETWORK_INFRA_AP = 1, + WPS_DEV_NETWORK_INFRA_ROUTER = 2, + WPS_DEV_NETWORK_INFRA_SWITCH = 3, + WPS_DEV_DISPLAY_TV = 1, + WPS_DEV_DISPLAY_PICTURE_FRAME = 2, + WPS_DEV_DISPLAY_PROJECTOR = 3, + WPS_DEV_MULTIMEDIA_DAR = 1, + WPS_DEV_MULTIMEDIA_PVR = 2, + WPS_DEV_MULTIMEDIA_MCX = 3, + WPS_DEV_GAMING_XBOX = 1, + WPS_DEV_GAMING_XBOX360 = 2, + WPS_DEV_GAMING_PLAYSTATION = 3, + WPS_DEV_PHONE_WINDOWS_MOBILE = 1 +}; + + +/* Request Type */ +enum wps_request_type { + WPS_REQ_ENROLLEE_INFO = 0, + WPS_REQ_ENROLLEE = 1, + WPS_REQ_REGISTRAR = 2, + WPS_REQ_WLAN_MANAGER_REGISTRAR = 3 +}; + +/* Response Type */ +enum wps_response_type { + WPS_RESP_ENROLLEE_INFO = 0, + WPS_RESP_ENROLLEE = 1, + WPS_RESP_REGISTRAR = 2, + WPS_RESP_AP = 3 +}; + +/* Walk Time for push button configuration (in seconds) */ +#define WPS_PBC_WALK_TIME 120 + +#define WPS_MAX_AUTHORIZED_MACS 5 + +#define WPS_IGNORE_SEL_REG_MAX_CNT 4 + +#define WPS_MAX_DIS_AP_NUM 10 + +#endif /* WPS_DEFS_H */ diff --git a/components/wpa_supplicant/include/wps/wps_dev_attr.h b/components/wpa_supplicant/include/wps/wps_dev_attr.h new file mode 100644 index 0000000000..200c9c45ad --- /dev/null +++ b/components/wpa_supplicant/include/wps/wps_dev_attr.h @@ -0,0 +1,39 @@ +/* + * Wi-Fi Protected Setup - device attributes + * Copyright (c) 2008, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPS_DEV_ATTR_H +#define WPS_DEV_ATTR_H + +struct wps_parse_attr; + +int wps_build_manufacturer(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_model_name(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_model_number(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_vendor_ext_m1(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_primary_dev_type(struct wps_device_data *dev, + struct wpabuf *msg); +int wps_build_secondary_dev_type(struct wps_device_data *dev, + struct wpabuf *msg); +int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg); +int wps_process_device_attrs(struct wps_device_data *dev, + struct wps_parse_attr *attr); +int wps_process_os_version(struct wps_device_data *dev, const u8 *ver); +int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands); +void wps_device_data_dup(struct wps_device_data *dst, + const struct wps_device_data *src); +void wps_device_data_free(struct wps_device_data *dev); +int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_req_dev_type(struct wps_device_data *dev, struct wpabuf *msg, + unsigned int num_req_dev_types, + const u8 *req_dev_types); + +#endif /* WPS_DEV_ATTR_H */ diff --git a/components/wpa_supplicant/include/wps/wps_i.h b/components/wpa_supplicant/include/wps/wps_i.h new file mode 100644 index 0000000000..c20d5ef917 --- /dev/null +++ b/components/wpa_supplicant/include/wps/wps_i.h @@ -0,0 +1,217 @@ +/* + * Wi-Fi Protected Setup - internal definitions + * Copyright (c) 2008-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPS_I_H +#define WPS_I_H + +#include "wps.h" +#include "wps_attr_parse.h" +#include "esp_wifi_crypto_types.h" + +#ifdef CONFIG_WPS_NFC +struct wps_nfc_pw_token; +#endif +/** + * struct wps_data - WPS registration protocol data + * + * This data is stored at the EAP-WSC server/peer method and it is kept for a + * single registration protocol run. + */ +struct wps_data { + /** + * wps - Pointer to long term WPS context + */ + struct wps_context *wps; + + /** + * registrar - Whether this end is a Registrar + */ + int registrar; + + /** + * er - Whether the local end is an external registrar + */ + int er; + + enum { + /* Enrollee states */ + SEND_M1, RECV_M2, SEND_M3, RECV_M4, SEND_M5, RECV_M6, SEND_M7, + RECV_M8, RECEIVED_M2D, WPS_MSG_DONE, RECV_ACK, WPS_FINISHED, + SEND_WSC_NACK, + + /* Registrar states */ + RECV_M1, SEND_M2, RECV_M3, SEND_M4, RECV_M5, SEND_M6, + RECV_M7, SEND_M8, RECV_DONE, SEND_M2D, RECV_M2D_ACK + } state; + + u8 uuid_e[WPS_UUID_LEN]; + u8 uuid_r[WPS_UUID_LEN]; + u8 mac_addr_e[ETH_ALEN]; + u8 nonce_e[WPS_NONCE_LEN]; + u8 nonce_r[WPS_NONCE_LEN]; + u8 psk1[WPS_PSK_LEN]; + u8 psk2[WPS_PSK_LEN]; + u8 snonce[2 * WPS_SECRET_NONCE_LEN]; + u8 peer_hash1[WPS_HASH_LEN]; + u8 peer_hash2[WPS_HASH_LEN]; + + struct wpabuf *dh_privkey; + struct wpabuf *dh_pubkey_e; + struct wpabuf *dh_pubkey_r; + u8 authkey[WPS_AUTHKEY_LEN]; + u8 keywrapkey[WPS_KEYWRAPKEY_LEN]; + u8 emsk[WPS_EMSK_LEN]; + + struct wpabuf *last_msg; + + u8 *dev_password; + size_t dev_password_len; + u16 dev_pw_id; + int pbc; + + /** + * request_type - Request Type attribute from (Re)AssocReq + */ + u8 request_type; + + /** + * encr_type - Available encryption types + */ + u16 encr_type; + + /** + * auth_type - Available authentication types + */ + u16 auth_type; + + u8 *new_psk; + size_t new_psk_len; + + int wps_pin_revealed; + struct wps_credential cred; + + struct wps_device_data peer_dev; + + /** + * config_error - Configuration Error value to be used in NACK + */ + u16 config_error; + u16 error_indication; + + int ext_reg; + int int_reg; + + struct wps_credential *new_ap_settings; + + void *dh_ctx; + + void (*ap_settings_cb)(void *ctx, const struct wps_credential *cred); + void *ap_settings_cb_ctx; + + struct wps_credential *use_cred; + + int use_psk_key; + u8 p2p_dev_addr[ETH_ALEN]; /* P2P Device Address of the client or + * 00:00:00:00:00:00 if not a P2p client */ + int pbc_in_m1; +#ifdef CONFIG_WPS_NFC + struct wps_nfc_pw_token *nfc_pw_token; +#endif +}; + +wps_crypto_funcs_t wps_crypto_funcs; + +/* wps_common.c */ +void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, + const char *label, u8 *res, size_t res_len); +int wps_derive_keys(struct wps_data *wps); +void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, + size_t dev_passwd_len); +struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, + size_t encr_len); +void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg, + u16 config_error, u16 error_indication); +void wps_success_event(struct wps_context *wps); +void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part); +void wps_pbc_overlap_event(struct wps_context *wps); +void wps_pbc_timeout_event(struct wps_context *wps); + +struct wpabuf * wps_build_wsc_ack(struct wps_data *wps); +struct wpabuf * wps_build_wsc_nack(struct wps_data *wps); + +typedef enum wps_calc_key_mode { + WPS_CALC_KEY_NORMAL = 0, + WPS_CALC_KEY_NO_CALC, + WPS_CALC_KEY_PRE_CALC, + WPS_CALC_KEY_MAX, +} wps_key_mode_t; + +/* wps_attr_build.c */ +int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg, wps_key_mode_t mode); +int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type); +int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type); +int wps_build_config_methods(struct wpabuf *msg, u16 methods); +int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid); +int wps_build_dev_password_id(struct wpabuf *msg, u16 id); +int wps_build_config_error(struct wpabuf *msg, u16 err); +int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg); +int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg); +int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, + struct wpabuf *plain); +int wps_build_version(struct wpabuf *msg); +int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll, + const u8 *auth_macs, size_t auth_macs_count); +int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type); +int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg); +int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg); +int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg); +int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg); +int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg); +int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg); +int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id, + const struct wpabuf *pubkey, const u8 *dev_pw, + size_t dev_pw_len); +struct wpabuf * wps_ie_encapsulate(struct wpabuf *data); + +/* wps_attr_process.c */ +int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator, + const struct wpabuf *msg); +int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg, + const u8 *key_wrap_auth); +int wps_process_cred(struct wps_parse_attr *attr, + struct wps_credential *cred); +int wps_process_ap_settings(struct wps_parse_attr *attr, + struct wps_credential *cred); + +/* wps_enrollee.c */ +struct wpabuf * wps_enrollee_get_msg(struct wps_data *wps, + enum wsc_op_code *op_code); +enum wps_process_res wps_enrollee_process_msg(struct wps_data *wps, + enum wsc_op_code op_code, + const struct wpabuf *msg); + +/* wps_registrar.c */ +struct wpabuf * wps_registrar_get_msg(struct wps_data *wps, + enum wsc_op_code *op_code); +enum wps_process_res wps_registrar_process_msg(struct wps_data *wps, + enum wsc_op_code op_code, + const struct wpabuf *msg); +int wps_build_cred(struct wps_data *wps, struct wpabuf *msg); +int wps_device_store(struct wps_registrar *reg, + struct wps_device_data *dev, const u8 *uuid); +void wps_registrar_selected_registrar_changed(struct wps_registrar *reg); +const u8 * wps_authorized_macs(struct wps_registrar *reg, size_t *count); +int wps_registrar_pbc_overlap(struct wps_registrar *reg, + const u8 *addr, const u8 *uuid_e); +#ifdef CONFIG_WPS_NFC + +void wps_registrar_remove_nfc_pw_token(struct wps_registrar *reg, + struct wps_nfc_pw_token *token); +#endif + +#endif /* WPS_I_H */ diff --git a/components/wpa_supplicant/port/include/os.h b/components/wpa_supplicant/port/include/os.h index 468d54ffe8..48f7ab85e4 100644 --- a/components/wpa_supplicant/port/include/os.h +++ b/components/wpa_supplicant/port/include/os.h @@ -18,6 +18,7 @@ #include #include #include +#include "esp_err.h" #include "rom/ets_sys.h" typedef long os_time_t; @@ -201,6 +202,10 @@ char * os_readfile(const char *name, size_t *len); #define os_free(p) free((p)) #endif +#ifndef os_bzero +#define os_bzero(s, n) bzero(s, n) +#endif + #ifndef os_strdup #ifdef _MSC_VER diff --git a/components/wpa_supplicant/src/wpa2/eap_peer/chap.c b/components/wpa_supplicant/src/wpa2/eap_peer/chap.c new file mode 100644 index 0000000000..eb613ca4c1 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/eap_peer/chap.c @@ -0,0 +1,27 @@ +/* + * CHAP-MD5 + * + */ +#ifdef CHAP_MD5 + +#include "wpa/includes.h" +#include "wpa/common.h" +#include "crypto/crypto.h" +#include "wpa2/eap_peer/chap.h" + +int chap_md5(u8 id, const u8 *secret, size_t secret_len, const u8 *challenge, + size_t challenge_len, u8 *response) +{ + const u8 *addr[3]; + size_t len[3]; + + addr[0] = &id; + len[0] = 1; + addr[1] = secret; + len[1] = secret_len; + addr[2] = challenge; + len[2] = challenge_len; + return md5_vector(3, addr, len, response); +} + +#endif /* CHAP_MD5 */ diff --git a/components/wpa_supplicant/src/wpa2/eap_peer/eap.c b/components/wpa_supplicant/src/wpa2/eap_peer/eap.c new file mode 100644 index 0000000000..d492831fd6 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/eap_peer/eap.c @@ -0,0 +1,731 @@ +/* + * EAP peer state machines (RFC 4137) + * Copyright (c) 2004-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + * + * This file implements the Peer State Machine as defined in RFC 4137. The used + * states and state transitions match mostly with the RFC. However, there are + * couple of additional transitions for working around small issues noticed + * during testing. These exceptions are explained in comments within the + * functions in this file. The method functions, m.func(), are similar to the + * ones used in RFC 4137, but some small changes have used here to optimize + * operations and to add functionality needed for fast re-authentication + * (session resumption). + */ +#include + +#include "esp_err.h" + +#include "wpa/includes.h" +#include "wpa/common.h" +#include "wpa/wpa_debug.h" +#include "wpa/eapol_common.h" +#include "wpa/ieee802_11_defs.h" +#include "wpa/state_machine.h" +#include "wpa/wpa.h" + +#include "crypto/crypto.h" + +#include "wpa2/utils/ext_password.h" +#include "wpa2/tls/tls.h" +#include "wpa2/eap_peer/eap_i.h" +#include "wpa2/eap_peer/eap_config.h" +#include "wpa2/eap_peer/eap.h" +#include "wpa2/eap_peer/eap_tls.h" +#ifdef EAP_PEER_METHOD +#include "wpa2/eap_peer/eap_methods.h" +#endif + + +static bool gl_disable_time_check = true; +void eap_peer_config_deinit(struct eap_sm *sm); +void eap_peer_blob_deinit(struct eap_sm *sm); +void eap_deinit_prev_method(struct eap_sm *sm, const char *txt); + +extern bool ieee80211_unregister_wpa2_cb(void); + +#ifdef EAP_PEER_METHOD +static struct eap_method *eap_methods = NULL; + +const struct eap_method * eap_peer_get_eap_method(int vendor, EapType method) +{ + struct eap_method *m; + for (m = eap_methods; m; m = m->next) { + if (m->vendor == vendor && m->method == method) + return m; + } + return NULL; +} + +const struct eap_method * eap_peer_get_methods(size_t *count) +{ + int c = 0; + struct eap_method *m; + + for (m = eap_methods; m; m = m->next) + c++; + + *count = c; + return eap_methods; +} + +EapType eap_peer_get_type(const char *name, int *vendor) +{ + struct eap_method *m; + for (m = eap_methods; m; m = m->next) { + if (os_strcmp(m->name, name) == 0) { + *vendor = m->vendor; + return m->method; + } + } + *vendor = EAP_VENDOR_IETF; + return EAP_TYPE_NONE; +} + +static int +eap_allowed_phase2_type(int vendor, int type) +{ + if (vendor != EAP_VENDOR_IETF) + return 0; + return type != EAP_TYPE_PEAP && type != EAP_TYPE_TTLS && + type != EAP_TYPE_FAST; +} + +u32 eap_get_phase2_type(const char *name, int *vendor) +{ + int v; + u8 type = eap_peer_get_type(name, &v); + if (eap_allowed_phase2_type(v, type)) { + *vendor = v; + return type; + } + *vendor = EAP_VENDOR_IETF; + return EAP_TYPE_NONE; +} + +struct eap_method_type * eap_get_phase2_types(struct eap_peer_config *config, + size_t *count) +{ + struct eap_method_type *buf; + u32 method; + int vendor; + size_t mcount; + const struct eap_method *methods, *m; + + methods = eap_peer_get_methods(&mcount); + if (methods == NULL) + return NULL; + *count = 0; + buf = os_malloc(mcount * sizeof(struct eap_method_type)); + if (buf == NULL) + return NULL; + + for (m = methods; m; m = m->next) { + vendor = m->vendor; + method = m->method; + if (eap_allowed_phase2_type(vendor, method)) { + if (vendor == EAP_VENDOR_IETF && + method == EAP_TYPE_TLS && config && + config->private_key2 == NULL) + continue; + buf[*count].vendor = vendor; + buf[*count].method = method; + (*count)++; + } + } + + return buf; +} + +struct eap_method * eap_peer_method_alloc(int vendor, EapType method, + const char *name) +{ + struct eap_method *eap; + eap = (struct eap_method *)os_zalloc(sizeof(*eap)); + if (eap == NULL) + return NULL; + eap->vendor = vendor; + eap->method = method; + eap->name = name; + return eap; +} + +void eap_peer_method_free(struct eap_method *method) +{ + os_free(method); +} + +int eap_peer_method_register(struct eap_method *method) +{ + struct eap_method *m, *last = NULL; + + if (method == NULL || method->name == NULL) + return -1; + for (m = eap_methods; m; m = m->next) { + if (m->vendor == method->vendor && + m->method == method->method && + os_strcmp(m->name, method->name)) + return -2; + last = m; + } + if (last) + last->next = method; + else + eap_methods = method; + return 0; +} + +void eap_peer_unregister_methods(void) +{ + struct eap_method *m; + while (eap_methods) { + m = eap_methods; + eap_methods = eap_methods->next; + + if (m->free) + m->free(m); + else + eap_peer_method_free(m); + } +} + +int eap_peer_register_methods(void) +{ + int ret = 0; + +#ifdef EAP_MD5 + if (ret == 0) + ret = eap_peer_md5_register(); +#endif + +#ifdef EAP_TLS + if (ret == 0) + ret = eap_peer_tls_register(); +#endif + +#ifdef EAP_MSCHAPv2 + if (ret == 0) + ret = eap_peer_mschapv2_register(); +#endif + +#ifdef EAP_PEAP + if (ret == 0) + ret = eap_peer_peap_register(); +#endif + +#ifdef EAP_TTLS + if (ret == 0) + ret = eap_peer_ttls_register(); +#endif + + return ret; +} + +void eap_deinit_prev_method(struct eap_sm *sm, const char *txt) +{ + if (sm->m == NULL || sm->eap_method_priv == NULL) + return; + sm->m->deinit(sm, sm->eap_method_priv); + sm->eap_method_priv = NULL; + sm->m = NULL; +} + +struct wpabuf * eap_sm_build_identity_resp(struct eap_sm *sm, u8 id, int encrypted) +{ + const u8 *identity; + size_t identity_len; + struct wpabuf *eap_buf = NULL; + struct eap_peer_config *config = eap_get_config(sm); + + if (config == NULL) { + wpa_printf(MSG_ERROR, "EAP: Build Identity Resp-> configuration was not available\n"); + return NULL; + } + + if (sm->m && sm->m->get_identity) { + identity = sm->m->get_identity(sm, + sm->eap_method_priv, + &identity_len); + } else if (!encrypted && config->anonymous_identity) { + identity = config->anonymous_identity; + identity_len = config->anonymous_identity_len; + } else { + identity = config->identity; + identity_len = config->identity_len; + } + + if (identity == NULL) { + wpa_printf(MSG_ERROR, "EAP: Build Identity Resp-> identity was not available\n"); + return NULL; + } + + eap_buf = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_IDENTITY, + identity_len, EAP_CODE_RESPONSE, id); + if (!eap_buf) { + return NULL; + } + + wpabuf_put_data(eap_buf, identity, identity_len); + return eap_buf; +} + +struct wpabuf * eap_sm_build_nak(struct eap_sm *sm, EapType type, u8 id) +{ + size_t count = 0; + int found = 0; + struct wpabuf *resp; + const struct eap_method *methods, *m; + + methods = eap_peer_get_methods(&count); + if (methods == NULL) + return NULL; + + if (type == EAP_TYPE_EXPANDED) { + /*Build Expanded NAK*/ + resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EXPANDED, + 8 + 8 * (count + 1), EAP_CODE_RESPONSE, id); + if (resp == NULL) + return NULL; + wpabuf_put_be24(resp, EAP_VENDOR_IETF); + wpabuf_put_be32(resp, EAP_TYPE_NAK); + } else { + resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK, + sizeof(struct eap_hdr) + 1 + count + 1, + EAP_CODE_RESPONSE, id); + if (resp == NULL) + return NULL; + wpabuf_put(resp, 0); + } + + for (m = methods; m; m = m->next) { + if (type == EAP_TYPE_EXPANDED) { + wpabuf_put_u8(resp, EAP_TYPE_EXPANDED); + wpabuf_put_be24(resp, m->vendor); + wpabuf_put_be32(resp, m->method); + } else + wpabuf_put_u8(resp, EAP_TYPE_NONE); + found++; + } + if (!found) { + if (type == EAP_TYPE_EXPANDED) { + wpabuf_put_u8(resp, EAP_TYPE_EXPANDED); + wpabuf_put_be24(resp, EAP_VENDOR_IETF); + wpabuf_put_be32(resp, EAP_TYPE_NONE); + } else + wpabuf_put_u8(resp, EAP_TYPE_NONE); + } + eap_update_len(resp); + return resp; +} +#endif + +int eap_peer_config_init( + struct eap_sm *sm, u8 *private_key_passwd, + int private_key_passwd_len) +{ + if (!sm) + return -1; + + sm->config.anonymous_identity = NULL; + sm->config.identity = NULL; + sm->config.password = NULL; + sm->config.new_password = NULL; + + sm->config.private_key_passwd = private_key_passwd; + sm->config.client_cert = (u8 *)sm->blob[0].name; + sm->config.private_key = (u8 *)sm->blob[1].name; + sm->config.ca_cert = (u8 *)sm->blob[2].name; + + sm->config.ca_path = NULL; + + sm->config.fragment_size = 1400; /* fragment size */ + + /* anonymous identity */ + if (g_wpa_anonymous_identity && g_wpa_anonymous_identity_len > 0) { + sm->config.anonymous_identity_len = g_wpa_anonymous_identity_len; + sm->config.anonymous_identity = (u8 *)os_zalloc(sm->config.anonymous_identity_len); + if (sm->config.anonymous_identity == NULL) + return -2; + os_memcpy(sm->config.anonymous_identity, g_wpa_anonymous_identity, g_wpa_anonymous_identity_len); + } + + /* Configre identity */ + if (g_wpa_username && g_wpa_username_len > 0) { + sm->config.identity_len = g_wpa_username_len; + sm->config.identity = (u8 *)os_zalloc(sm->config.identity_len); + if (sm->config.identity == NULL) { + return -2; + } + os_memcpy(sm->config.identity, g_wpa_username, g_wpa_username_len); + } + + if (g_wpa_password && g_wpa_password_len) { + sm->config.password_len = g_wpa_password_len; + sm->config.password = (u8 *)os_zalloc(sm->config.password_len); + if (sm->config.password == NULL) + return -2; + os_memcpy(sm->config.password, g_wpa_password, sm->config.password_len); + } + + if (g_wpa_new_password && g_wpa_new_password_len) { + sm->config.new_password_len = g_wpa_new_password_len; + sm->config.new_password = (u8 *)os_zalloc(sm->config.new_password_len); + if (sm->config.new_password == NULL) + return -2; + os_memcpy(sm->config.new_password, g_wpa_new_password, + sm->config.new_password_len); + } + + return 0; + +} + +void eap_peer_config_deinit(struct eap_sm *sm) +{ + if (!sm) + return; + + os_free(sm->config.anonymous_identity); + os_free(sm->config.identity); + os_free(sm->config.password); + os_free(sm->config.new_password); + os_bzero(&sm->config, sizeof(struct eap_peer_config)); +} + +int eap_peer_blob_init(struct eap_sm *sm) +{ + int i, ret; + + if (!sm) + return -1; + + if (g_wpa_client_cert && g_wpa_client_cert_len) { + sm->blob[0].name = (char *)os_zalloc(BLOB_NAME_LEN+1); + if (sm->blob[0].name == NULL) { + ret = -2; + goto _out; + } + os_strncpy(sm->blob[0].name, CLIENT_CERT_NAME, BLOB_NAME_LEN); + sm->blob[0].len = g_wpa_client_cert_len; + sm->blob[0].data = g_wpa_client_cert; + } + + if (g_wpa_private_key && g_wpa_private_key_len) { + sm->blob[1].name = (char *)os_zalloc(BLOB_NAME_LEN+1); + if (sm->blob[1].name == NULL) { + ret = -2; + goto _out; + } + os_strncpy(sm->blob[1].name, PRIVATE_KEY_NAME, BLOB_NAME_LEN); + sm->blob[1].len = g_wpa_private_key_len; + sm->blob[1].data = g_wpa_private_key; + } + + if (g_wpa_ca_cert && g_wpa_ca_cert_len) { + sm->blob[2].name = (char *)os_zalloc(BLOB_NAME_LEN+1); + if (sm->blob[2].name == NULL) { + ret = -2; + goto _out; + } + os_strncpy(sm->blob[2].name, CA_CERT_NAME, BLOB_NAME_LEN); + sm->blob[2].len = g_wpa_ca_cert_len; + sm->blob[2].data = g_wpa_ca_cert; + } + + return 0; +_out: + for (i = 0; i < BLOB_NUM; i++) { + if (sm->blob[i].name) { + os_free(sm->blob[i].name); + sm->blob[i].name = NULL; + } + } + os_bzero(&sm->blob[0], sizeof(struct wpa_config_blob)*BLOB_NUM); + + return ret; +} + +void eap_peer_blob_deinit(struct eap_sm *sm) +{ + int i; + for (i = 0; i < BLOB_NUM; i++) { + if (sm->blob[i].name) { + os_free(sm->blob[i].name); + sm->blob[i].name = NULL; + } + } + os_bzero(&sm->blob[0], sizeof(struct wpa_config_blob)*BLOB_NUM); + + sm->config.client_cert = NULL; + sm->config.private_key = NULL; + sm->config.ca_cert = NULL; +} + +void eap_sm_abort(struct eap_sm *sm) +{ + wpabuf_free(sm->lastRespData); + sm->lastRespData = NULL; + //os_free(sm->eapKeyData); + //sm->eapKeyData = NULL; +} + +/** + * eap_get_config - Get current network configuration + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * Returns: Pointer to the current network configuration or %NULL if not found + * + * EAP peer methods should avoid using this function if they can use other + * access functions, like eap_get_config_identity() and + * eap_get_config_password(), that do not require direct access to + * struct eap_peer_config. + */ +struct eap_peer_config * eap_get_config(struct eap_sm *sm) +{ + return &sm->config; +} + +const u8 * eap_get_config_identity(struct eap_sm *sm, size_t *len) +{ + struct eap_peer_config *config = eap_get_config(sm); + if (config == NULL) + return NULL; + *len = config->identity_len; + return config->identity; +} + +const u8 * eap_get_config_password(struct eap_sm *sm, size_t *len) +{ + struct eap_peer_config *config = eap_get_config(sm); + if (config == NULL) + return NULL; + *len = config->password_len; + return config->password; +} + +const u8 * eap_get_config_password2(struct eap_sm *sm, size_t *len, int *hash) +{ + struct eap_peer_config *config = eap_get_config(sm); + if (config == NULL) + return NULL; + + *len = config->password_len; + if (hash) + *hash = !!(config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH); + return config->password; +} + +const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len) +{ + struct eap_peer_config *config = eap_get_config(sm); + if (config == NULL) + return NULL; + *len = config->new_password_len; + return config->new_password; +} +/** + * eap_get_config_blob - Get a named configuration blob + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @name: Name of the blob + * Returns: Pointer to blob data or %NULL if not found + */ +const struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm, + const char *name) +{ + int i; + + if (!sm) + return NULL; + + for (i = 0; i < BLOB_NUM; i++) { + if (sm->blob[i].name == NULL) + continue; + if (os_strncmp(name, sm->blob[i].name, BLOB_NAME_LEN) == 0) { + return &sm->blob[i]; + } + } + return NULL; +} + +esp_err_t esp_wifi_sta_wpa2_ent_set_cert_key(const unsigned char *client_cert, int client_cert_len, const unsigned char *private_key, int private_key_len, const unsigned char *private_key_passwd, int private_key_passwd_len) +{ + if (client_cert && client_cert_len > 0) { + g_wpa_client_cert = client_cert; + g_wpa_client_cert_len = client_cert_len; + } + if (private_key && private_key_len > 0) { + g_wpa_private_key = private_key; + g_wpa_private_key_len = private_key_len; + } + if (private_key_passwd && private_key_passwd_len > 0) { + g_wpa_private_key_passwd = private_key_passwd; + g_wpa_private_key_passwd_len = private_key_passwd_len; + } + + return ESP_OK; +} + +void esp_wifi_sta_wpa2_ent_clear_cert_key(void) +{ + ieee80211_unregister_wpa2_cb(); + + g_wpa_client_cert = NULL; + g_wpa_client_cert_len = 0; + g_wpa_private_key = NULL; + g_wpa_private_key_len = 0; + g_wpa_private_key_passwd = NULL; + g_wpa_private_key_passwd_len = 0; +} + +esp_err_t esp_wifi_sta_wpa2_ent_set_ca_cert(const unsigned char *ca_cert, int ca_cert_len) +{ + if (ca_cert && ca_cert_len > 0) { + g_wpa_ca_cert = ca_cert; + g_wpa_ca_cert_len = ca_cert_len; + } + + return ESP_OK; +} + +void esp_wifi_sta_wpa2_ent_clear_ca_cert(void) +{ + g_wpa_ca_cert = NULL; + g_wpa_ca_cert_len = 0; +} + +#define ANONYMOUS_ID_LEN_MAX 128 +esp_err_t esp_wifi_sta_wpa2_ent_set_identity(const unsigned char *identity, int len) +{ + if (len <= 0 || len > ANONYMOUS_ID_LEN_MAX) { + return ESP_ERR_INVALID_ARG; + } + + if (g_wpa_anonymous_identity) { + os_free(g_wpa_anonymous_identity); + g_wpa_anonymous_identity = NULL; + } + + g_wpa_anonymous_identity = (u8 *)os_zalloc(len); + if (g_wpa_anonymous_identity == NULL) { + return ESP_ERR_NO_MEM; + } + + os_memcpy(g_wpa_anonymous_identity, identity, len); + g_wpa_anonymous_identity_len = len; + + return ESP_OK; +} + +void esp_wifi_sta_wpa2_ent_clear_identity(void) +{ + if (g_wpa_anonymous_identity) + os_free(g_wpa_anonymous_identity); + + g_wpa_anonymous_identity = NULL; + g_wpa_anonymous_identity_len = 0; +} + +#define USERNAME_LEN_MAX 128 +esp_err_t esp_wifi_sta_wpa2_ent_set_username(const unsigned char *username, int len) +{ + if (len <= 0 || len > USERNAME_LEN_MAX) + return ESP_ERR_INVALID_ARG; + + if (g_wpa_username) { + os_free(g_wpa_username); + g_wpa_username = NULL; + } + + g_wpa_username = (u8 *)os_zalloc(len); + if (g_wpa_username == NULL) + return ESP_ERR_NO_MEM; + + os_memcpy(g_wpa_username, username, len); + g_wpa_username_len = len; + + return ESP_OK; +} + +void esp_wifi_sta_wpa2_ent_clear_username(void) +{ + if (g_wpa_username) + os_free(g_wpa_username); + + g_wpa_username = NULL; + g_wpa_username_len = 0; +} + +esp_err_t esp_wifi_sta_wpa2_ent_set_password(const unsigned char *password, int len) +{ + if (len <= 0) + return ESP_ERR_INVALID_ARG; + + if (g_wpa_password) { + os_free(g_wpa_password); + g_wpa_password = NULL; + } + + g_wpa_password = (u8 *)os_zalloc(len); + if (g_wpa_password == NULL) + return ESP_ERR_NO_MEM; + + os_memcpy(g_wpa_password, password, len); + g_wpa_password_len = len; + + return ESP_OK; +} + +void esp_wifi_sta_wpa2_ent_clear_password(void) +{ + if (g_wpa_password) + os_free(g_wpa_password); + g_wpa_password = NULL; + g_wpa_password_len = 0; +} + +esp_err_t esp_wifi_sta_wpa2_ent_set_new_password(const unsigned char *new_password, int len) +{ + if (len <= 0) + return ESP_ERR_INVALID_ARG; + + if (g_wpa_new_password) { + os_free(g_wpa_new_password); + g_wpa_new_password = NULL; + } + + g_wpa_new_password = (u8 *)os_zalloc(len); + if (g_wpa_new_password == NULL) + return ESP_ERR_NO_MEM; + + os_memcpy(g_wpa_new_password, new_password, len); + g_wpa_password_len = len; + + return ESP_OK; +} + +void esp_wifi_sta_wpa2_ent_clear_new_password(void) +{ + if (g_wpa_new_password) + os_free(g_wpa_new_password); + g_wpa_new_password = NULL; + g_wpa_new_password_len = 0; +} + +esp_err_t esp_wifi_sta_wpa2_ent_set_disable_time_check(bool disable) +{ + gl_disable_time_check = disable; + return ESP_OK; +} + +bool wifi_sta_get_enterprise_disable_time_check(void) +{ + return gl_disable_time_check; +} + +esp_err_t esp_wifi_sta_wpa2_ent_get_disable_time_check(bool *disable) +{ + *disable = wifi_sta_get_enterprise_disable_time_check(); + return ESP_OK; +} + diff --git a/components/wpa_supplicant/src/wpa2/eap_peer/eap_common.c b/components/wpa_supplicant/src/wpa2/eap_peer/eap_common.c new file mode 100644 index 0000000000..a1748b140f --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/eap_peer/eap_common.c @@ -0,0 +1,205 @@ +/* + * EAP common peer/server definitions + * Copyright (c) 2004-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "wpa2/eap_peer/eap_defs.h" +#include "wpa2/eap_peer/eap_common.h" + +/** + * eap_hdr_len_valid - Validate EAP header length field + * @msg: EAP frame (starting with EAP header) + * @min_payload: Minimum payload length needed + * Returns: 1 for valid header, 0 for invalid + * + * This is a helper function that does minimal validation of EAP messages. The + * length field is verified to be large enough to include the header and not + * too large to go beyond the end of the buffer. + */ +int eap_hdr_len_valid(const struct wpabuf *msg, size_t min_payload) +{ + const struct eap_hdr *hdr; + size_t len; + + if (msg == NULL) + return 0; + + hdr = wpabuf_head(msg); + + if (wpabuf_len(msg) < sizeof(*hdr)) { + wpa_printf(MSG_INFO, "EAP: Too short EAP frame"); + return 0; + } + + len = be_to_host16(hdr->length); + if (len < sizeof(*hdr) + min_payload || len > wpabuf_len(msg)) { + wpa_printf(MSG_INFO, "EAP: Invalid EAP length"); + return 0; + } + + return 1; +} + + +/** + * eap_hdr_validate - Validate EAP header + * @vendor: Expected EAP Vendor-Id (0 = IETF) + * @eap_type: Expected EAP type number + * @msg: EAP frame (starting with EAP header) + * @plen: Pointer to variable to contain the returned payload length + * Returns: Pointer to EAP payload (after type field), or %NULL on failure + * + * This is a helper function for EAP method implementations. This is usually + * called in the beginning of struct eap_method::process() function to verify + * that the received EAP request packet has a valid header. This function is + * able to process both legacy and expanded EAP headers and in most cases, the + * caller can just use the returned payload pointer (into *plen) for processing + * the payload regardless of whether the packet used the expanded EAP header or + * not. + */ +const u8 * eap_hdr_validate(int vendor, EapType eap_type, + const struct wpabuf *msg, size_t *plen) +{ + const struct eap_hdr *hdr; + const u8 *pos; + size_t len; + + if (!eap_hdr_len_valid(msg, 1)) + return NULL; + + hdr = wpabuf_head(msg); + len = be_to_host16(hdr->length); + pos = (const u8 *) (hdr + 1); + + if (*pos == EAP_TYPE_EXPANDED) { + int exp_vendor; + u32 exp_type; + if (len < sizeof(*hdr) + 8) { + wpa_printf(MSG_INFO, "EAP: Invalid expanded EAP " + "length"); + return NULL; + } + pos++; + exp_vendor = WPA_GET_BE24(pos); + pos += 3; + exp_type = WPA_GET_BE32(pos); + pos += 4; + if (exp_vendor != vendor || exp_type != (u32) eap_type) { + wpa_printf(MSG_INFO, "EAP: Invalid expanded frame " + "type"); + return NULL; + } + + *plen = len - sizeof(*hdr) - 8; + return pos; + } else { + if (vendor != EAP_VENDOR_IETF || *pos != eap_type) { + wpa_printf(MSG_INFO, "EAP: Invalid frame type"); + return NULL; + } + *plen = len - sizeof(*hdr) - 1; + return pos + 1; + } +} + + +/** + * eap_msg_alloc - Allocate a buffer for an EAP message + * @vendor: Vendor-Id (0 = IETF) + * @type: EAP type + * @payload_len: Payload length in bytes (data after Type) + * @code: Message Code (EAP_CODE_*) + * @identifier: Identifier + * Returns: Pointer to the allocated message buffer or %NULL on error + * + * This function can be used to allocate a buffer for an EAP message and fill + * in the EAP header. This function is automatically using expanded EAP header + * if the selected Vendor-Id is not IETF. In other words, most EAP methods do + * not need to separately select which header type to use when using this + * function to allocate the message buffers. The returned buffer has room for + * payload_len bytes and has the EAP header and Type field already filled in. + */ +struct wpabuf * eap_msg_alloc(int vendor, EapType type, size_t payload_len, + u8 code, u8 identifier) +{ + struct wpabuf *buf; + struct eap_hdr *hdr; + size_t len; + + len = sizeof(struct eap_hdr) + (vendor == EAP_VENDOR_IETF ? 1 : 8) + + payload_len; + buf = wpabuf_alloc(len); + if (buf == NULL) + return NULL; + + hdr = wpabuf_put(buf, sizeof(*hdr)); + hdr->code = code; + hdr->identifier = identifier; + hdr->length = host_to_be16(len); + + if (vendor == EAP_VENDOR_IETF) { + wpabuf_put_u8(buf, type); + } else { + wpabuf_put_u8(buf, EAP_TYPE_EXPANDED); + wpabuf_put_be24(buf, vendor); + wpabuf_put_be32(buf, type); + } + + return buf; +} + + +/** + * eap_update_len - Update EAP header length + * @msg: EAP message from eap_msg_alloc + * + * This function updates the length field in the EAP header to match with the + * current length for the buffer. This allows eap_msg_alloc() to be used to + * allocate a larger buffer than the exact message length (e.g., if exact + * message length is not yet known). + */ +void eap_update_len(struct wpabuf *msg) +{ + struct eap_hdr *hdr; + hdr = wpabuf_mhead(msg); + if (wpabuf_len(msg) < sizeof(*hdr)) + return; + hdr->length = host_to_be16(wpabuf_len(msg)); +} + + +/** + * eap_get_id - Get EAP Identifier from wpabuf + * @msg: Buffer starting with an EAP header + * Returns: The Identifier field from the EAP header + */ +u8 eap_get_id(const struct wpabuf *msg) +{ + const struct eap_hdr *eap; + + if (wpabuf_len(msg) < sizeof(*eap)) + return 0; + + eap = wpabuf_head(msg); + return eap->identifier; +} + + +/** + * eap_get_id - Get EAP Type from wpabuf + * @msg: Buffer starting with an EAP header + * Returns: The EAP Type after the EAP header + */ +EapType eap_get_type(const struct wpabuf *msg) +{ + if (wpabuf_len(msg) < sizeof(struct eap_hdr) + 1) + return EAP_TYPE_NONE; + + return ((const u8 *) wpabuf_head(msg))[sizeof(struct eap_hdr)]; +} diff --git a/components/wpa_supplicant/src/wpa2/eap_peer/eap_mschapv2.c b/components/wpa_supplicant/src/wpa2/eap_peer/eap_mschapv2.c new file mode 100644 index 0000000000..89d7b8fc19 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/eap_peer/eap_mschapv2.c @@ -0,0 +1,671 @@ +/* + * EAP peer method: EAP-MSCHAPV2 (draft-kamath-pppext-eap-mschapv2-00.txt) + * Copyright (c) 2004-2008, 2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + + +#ifdef EAP_MSCHAPv2 + +#include "wpa/wpa.h" +#include "wpa/includes.h" +#include "wpa/common.h" +#include "crypto/random.h" +#include "crypto/ms_funcs.h" +#include "wpa2/tls/tls.h" +#include "wpa2/eap_peer/eap_i.h" +#include "wpa2/eap_peer/eap_defs.h" +#include "wpa2/eap_peer/eap_tls_common.h" +#include "wpa2/eap_peer/eap_config.h" +#include "wpa2/eap_peer/mschapv2.h" +#include "wpa2/eap_peer/eap_methods.h" + +#define MSCHAPV2_OP_CHALLENGE 1 +#define MSCHAPV2_OP_RESPONSE 2 +#define MSCHAPV2_OP_SUCCESS 3 +#define MSCHAPV2_OP_FAILURE 4 +#define MSCHAPV2_OP_CHANGE_PASSWORD 7 + +#define PASSWD_CHANGE_CHAL_LEN 16 +#define MSCHAPV2_KEY_LEN 16 + +#define ERROR_RESTRICTED_LOGON_HOURS 646 +#define ERROR_ACCT_DISABLED 647 +#define ERROR_PASSWD_EXPIRED 648 +#define ERROR_NO_DIALIN_PERMISSION 649 +#define ERROR_AUTHENTICATION_FAILURE 691 +#define ERROR_CHANGING_PASSWORD 709 + +struct eap_mschapv2_hdr { + u8 op_code; + u8 mschapv2_id; + u8 ms_length[2]; +} __packed; + +struct ms_response { + u8 peer_challenge[MSCHAPV2_CHAL_LEN]; + u8 reserved[8]; + u8 nt_response[MSCHAPV2_NT_RESPONSE_LEN]; + u8 flags; +} __packed; + +struct ms_change_password { + u8 encr_password[516]; + u8 encr_hash[16]; + u8 peer_challenge[MSCHAPV2_CHAL_LEN]; + u8 reserved[8]; + u8 nt_response[MSCHAPV2_NT_RESPONSE_LEN]; + u8 flags[2]; +} __packed; + +struct eap_mschapv2_data { + u8 auth_response[MSCHAPV2_AUTH_RESPONSE_LEN]; + int auth_response_valid; + + int prev_error; + u8 passwd_change_challenge[PASSWD_CHANGE_CHAL_LEN]; + int passwd_change_challenge_valid; + int passwd_change_version; + + u8 *peer_challenge; + u8 *auth_challenge; + + int phase2; + u8 master_key[MSCHAPV2_MASTER_KEY_LEN]; + int master_key_valid; + int success; + + struct wpabuf *prev_challenge; +}; + +static void +eap_mschapv2_deinit(struct eap_sm *sm, void *priv) +{ + struct eap_mschapv2_data *data = priv; + + os_free(data->peer_challenge); + os_free(data->auth_challenge); + wpabuf_free(data->prev_challenge); + os_free(data); +} + +static void * +eap_mschapv2_init(struct eap_sm *sm) +{ + struct eap_mschapv2_data *data; + data = (struct eap_mschapv2_data *)os_zalloc(sizeof(*data)); + if (data == NULL) + return NULL; + + data->phase2 = sm->init_phase2; + + return data; +} + +static struct wpabuf * +eap_mschapv2_challenge_reply( + struct eap_sm *sm, struct eap_mschapv2_data *data, + u8 id, u8 mschapv2_id, const u8 *auth_challenge) +{ + struct wpabuf *resp; + struct eap_mschapv2_hdr *ms; + u8 *peer_challenge; + int ms_len; + struct ms_response *r; + size_t identity_len, password_len; + const u8 *identity, *password; + int pwhash; + + wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Generate Challenge Response\n"); + + identity = eap_get_config_identity(sm, &identity_len); + password = eap_get_config_password2(sm, &password_len, &pwhash); + if (identity == NULL || password == NULL) + return NULL; + + ms_len = sizeof(*ms) + 1 + sizeof(*r) + identity_len; + resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, + ms_len, EAP_CODE_RESPONSE, id); + if (resp == NULL) + return NULL; + + ms = wpabuf_put(resp, sizeof(*ms)); + ms->op_code = MSCHAPV2_OP_RESPONSE; + ms->mschapv2_id = mschapv2_id; + if (data->prev_error) + ms->mschapv2_id++; + WPA_PUT_BE16(ms->ms_length, ms_len); + wpabuf_put_u8(resp, sizeof(*r)); + + /* Response */ + r = wpabuf_put(resp, sizeof(*r)); + peer_challenge = r->peer_challenge; + if (data->peer_challenge) { + peer_challenge = data->peer_challenge; + os_memset(r->peer_challenge, 0, MSCHAPV2_CHAL_LEN); + } else if (random_get_bytes(peer_challenge, MSCHAPV2_CHAL_LEN)) { + wpabuf_free(resp); + return NULL; + } + os_memset(r->reserved, 0, 8); + if (data->auth_challenge) + auth_challenge = data->auth_challenge; + if (mschapv2_derive_response(identity, identity_len, password, + password_len, pwhash, auth_challenge, + peer_challenge, r->nt_response, + data->auth_response, data->master_key)) { + wpabuf_free(resp); + return NULL; + } + data->auth_response_valid = 1; + data->master_key_valid = 1; + + r->flags = 0; + + wpabuf_put_data(resp, identity, identity_len); + return resp; +} + +static struct wpabuf * +eap_mschapv2_challenge( + struct eap_sm *sm, struct eap_mschapv2_data *data, + struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req, + size_t req_len, u8 id) +{ + size_t len, challenge_len; + const u8 *pos, *challenge; + + if (eap_get_config_identity(sm, &len) == NULL || + eap_get_config_password(sm, &len) == NULL) + return NULL; + + if (req_len < sizeof(*req) + 1) { + ret->ignore = true; + return NULL; + } + pos = (const u8 *)(req + 1); + challenge_len = *pos++; + len = req_len - sizeof(*req) - 1; + if (challenge_len != MSCHAPV2_CHAL_LEN) { + ret->ignore = true; + return NULL; + } + + if (len < challenge_len) { + ret->ignore = true; + return NULL; + } + + if (data->passwd_change_challenge_valid) + challenge = data->passwd_change_challenge; + else + challenge = pos; + pos += challenge_len; + len -= challenge_len; + + ret->ignore = false; + ret->methodState = METHOD_MAY_CONT; + ret->decision = DECISION_FAIL; + ret->allowNotifications = true; + + return eap_mschapv2_challenge_reply(sm, data, id, req->mschapv2_id, + challenge); +} + +static void +eap_mschapv2_password_changed(struct eap_sm *sm, + struct eap_mschapv2_data *data) +{ + struct eap_peer_config *config = eap_get_config(sm); + if (config && config->new_password) { + data->prev_error = 0; + os_free(config->password); + if (config->flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) { + } else if (config->flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH) { + config->password = os_malloc(16); + config->password_len = 16; + if (config->password) { + nt_password_hash(config->new_password, + config->new_password_len, + config->password); + } + os_free(config->new_password); + } else { + config->password = config->new_password; + config->password_len = config->new_password_len; + } + config->new_password = NULL; + config->new_password_len = 0; + } +} + +static struct wpabuf * +eap_mschapv2_success(struct eap_sm *sm, + struct eap_mschapv2_data *data, + struct eap_method_ret *ret, + const struct eap_mschapv2_hdr *req, + size_t req_len, u8 id) +{ + struct wpabuf *resp; + const u8 *pos; + size_t len; + + len = req_len - sizeof(*req); + pos = (const u8 *)(req + 1); + if (!data->auth_response_valid || + mschapv2_verify_auth_response(data->auth_response, pos, len)) { + ret->methodState = METHOD_NONE; + ret->decision = DECISION_FAIL; + return NULL; + } + pos += 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN; + len -= 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN; + while (len > 0 && *pos == ' ') { + pos++; + len--; + } + + resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, 1, + EAP_CODE_RESPONSE, id); + if (resp == NULL) { + ret->ignore = true; + return NULL; + } + + wpabuf_put_u8(resp, MSCHAPV2_OP_SUCCESS); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_UNCOND_SUCC; + ret->allowNotifications = false; + data->success = 1; + + if (data->prev_error == ERROR_PASSWD_EXPIRED) + eap_mschapv2_password_changed(sm, data); + + return resp; +} + +static int +eap_mschapv2_failure_txt(struct eap_sm *sm, + struct eap_mschapv2_data *data, char *txt) +{ + char *pos; + //char *msg = ""; + int retry = 1; + struct eap_peer_config *config = eap_get_config(sm); + + pos = txt; + + if (pos && os_strncmp(pos, "E=", 2) == 0) { + pos += 2; + data->prev_error = atoi(pos); + pos = (char *)os_strchr(pos, ' '); + if (pos) + pos++; + } + + if (pos && os_strncmp(pos, "R=", 2) == 0) { + pos += 2; + retry = atoi(pos); + pos = (char *)os_strchr(pos, ' '); + if (pos) + pos++; + } + + if (pos && os_strncmp(pos, "C=", 2) == 0) { + int hex_len; + pos += 2; + hex_len = (char *)os_strchr(pos, ' ') - (char *)pos; + if (hex_len == PASSWD_CHANGE_CHAL_LEN * 2) { + if (hexstr2bin(pos, data->passwd_change_challenge, + PASSWD_CHANGE_CHAL_LEN)) { + wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: invalid failure challenge\n"); + } else { + data->passwd_change_challenge_valid = 1; + } + } else { + wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: required challenge field " + "was not present in failure message\n"); + } + } + + if (pos && os_strncmp(pos, "V=", 2) == 0) { + pos += 2; + data->passwd_change_version = atoi(pos); + pos = (char *)os_strchr(pos, ' '); + if (pos) + pos++; + } + + if (pos && os_strncmp(pos, "M=", 2) == 0) { + pos += 2; + //msg = pos; + } + #if 0 + wpa_printf(MSG_WARNING, "EAP-MSCHAPV2: failure message: '%s' (retry %sallowed, error %d)", + msg, retry == 1? "" : "not ", data->prev_error); + #endif + if (data->prev_error == ERROR_PASSWD_EXPIRED && + data->passwd_change_version == 3 && config) { + if (config->new_password == NULL) { + wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Password expired - " + "password change reqired\n"); + //eap_sm_request_new_password(sm); + } + } else if (retry == 1 && config) { + if (!config->mschapv2_retry) + //eap_sm_request_identity(sm); + //eap_sm_request_password(sm); + config->mschapv2_retry = 1; + } else if (config) { + config->mschapv2_retry = 0; + } + + return retry == 1; +} + +static struct wpabuf * +eap_mschapv2_change_password( + struct eap_sm *sm, struct eap_mschapv2_data *data, + struct eap_method_ret *ret, const struct eap_mschapv2_hdr *req, u8 id) +{ + struct wpabuf *resp; + int ms_len; + const u8 *username, *password, *new_password; + size_t username_len, password_len, new_password_len; + struct eap_mschapv2_hdr *ms; + struct ms_change_password *cp; + u8 password_hash[16], password_hash_hash[16]; + int pwhash; + + username = eap_get_config_identity(sm, &username_len); + password = eap_get_config_password2(sm, &password_len, &pwhash); + new_password = eap_get_config_new_password(sm, &new_password_len); + if (username == NULL || password == NULL || new_password == NULL) + return NULL; + + username = mschapv2_remove_domain(username, &username_len); + + ret->ignore = false; + ret->methodState = METHOD_MAY_CONT; + ret->decision = DECISION_COND_SUCC; + ret->allowNotifications = TRUE; + + ms_len = sizeof(*ms) + sizeof(*cp); + resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, + EAP_CODE_RESPONSE, id); + if (resp == NULL) + return NULL; + ms = wpabuf_put(resp, sizeof(*ms)); + ms->op_code = MSCHAPV2_OP_CHANGE_PASSWORD; + ms->mschapv2_id = req->mschapv2_id + 1; + WPA_PUT_BE16(ms->ms_length, ms_len); + cp = wpabuf_put(resp, sizeof(*cp)); + + if (pwhash) { + if (encrypt_pw_block_with_password_hash( + new_password, new_password_len, + password, cp->encr_password)) + goto fail; + } else { + if (new_password_encrypted_with_old_nt_password_hash( + new_password, new_password_len, + password, password_len, cp->encr_password)) + goto fail; + } + + if (pwhash) { + u8 new_password_hash[16]; + nt_password_hash(new_password, new_password_len, + new_password_hash); + nt_password_hash_encrypted_with_block(password, + new_password_hash, + cp->encr_hash); + } else { + old_nt_password_hash_encrypted_with_new_nt_password_hash( + new_password, new_password_len, + password, password_len, cp->encr_hash); + } + + if (random_get_bytes(cp->peer_challenge, MSCHAPV2_CHAL_LEN)) + goto fail; + + os_memset(cp->reserved, 0, 8); + + generate_nt_response(data->passwd_change_challenge, cp->peer_challenge, + username, username_len, new_password, + new_password_len, cp->nt_response); + + generate_authenticator_response(new_password, new_password_len, + cp->peer_challenge, + data->passwd_change_challenge, + username, username_len, + cp->nt_response, data->auth_response); + data->auth_response_valid = 1; + + nt_password_hash(new_password, new_password_len, password_hash); + hash_nt_password_hash(password_hash, password_hash_hash); + get_master_key(password_hash_hash, cp->nt_response, data->master_key); + data->master_key_valid = 1; + + os_memset(cp->flags, 0, 2); + + return resp; + +fail: + wpabuf_free(resp); + return NULL; +} + +static struct wpabuf * +eap_mschapv2_failure(struct eap_sm *sm, + struct eap_mschapv2_data *data, + struct eap_method_ret *ret, + const struct eap_mschapv2_hdr *req, + size_t req_len, u8 id) +{ + struct wpabuf *resp; + const u8 *msdata = (const u8 *)(req + 1); + char *buf; + size_t len = req_len - sizeof(*req); + int retry = 0; + + buf = (char *)dup_binstr(msdata, len); + if (buf) { + retry = eap_mschapv2_failure_txt(sm, data, buf); + os_free(buf); + } + + ret->ignore = false; + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + ret->allowNotifications = false; + + if (data->prev_error == ERROR_PASSWD_EXPIRED && + data->passwd_change_version == 3) { + struct eap_peer_config *config = eap_get_config(sm); + if (config && config->new_password) + return eap_mschapv2_change_password(sm, data, ret, + req, id); + //if (config && config->pending_req_new_password) + // return NULL; + } else if (retry && data->prev_error == ERROR_AUTHENTICATION_FAILURE) { + return NULL; + } + + resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, 1, + EAP_CODE_RESPONSE, id); + if (resp == NULL) + return NULL; + + wpabuf_put_u8(resp, MSCHAPV2_OP_FAILURE); + return resp; +} + +static int +eap_mschapv2_check_config(struct eap_sm *sm) +{ + struct eap_peer_config *config = eap_get_config(sm); + + if (config == NULL) + return -1; + + if (config->identity == NULL || + config->identity_len == 0) { + wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: idetity not configured\n"); + return -1; + } + + if (config->password == NULL || + config->password_len == 0) { + wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Password not configured\n"); + return -1; + } + + return 0; +} + +static int +eap_mschapv2_check_mslen(struct eap_sm *sm, size_t len, + const struct eap_mschapv2_hdr *ms) +{ + size_t ms_len = WPA_GET_BE16(ms->ms_length); + + if (ms_len == len) + return 0; + + if (sm->workaround) { + wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Workaround, ignore Invalid" + " header len=%lu ms_len=%lu\n", + (unsigned long)len, (unsigned long)ms_len); + return 0; + } + wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Invalid header len=%lu ms_len=%lu\n", + (unsigned long)len, (unsigned long)ms_len); + + return -1; +} + +static void +eap_mschapv2_copy_challenge(struct eap_mschapv2_data *data, + const struct wpabuf *reqData) +{ + wpabuf_free(data->prev_challenge); + data->prev_challenge = wpabuf_dup(reqData); +} + +static struct wpabuf * +eap_mschapv2_process(struct eap_sm *sm, void *priv, + struct eap_method_ret *ret, + const struct wpabuf *reqData) +{ + u8 id; + size_t len; + const u8 *pos; + int using_prev_challenge = 0; + const struct eap_mschapv2_hdr *ms; + struct eap_mschapv2_data *data = priv; + struct eap_peer_config *config = eap_get_config(sm); + + if (eap_mschapv2_check_config(sm)) { + ret->ignore = true; + return NULL; + } + + if (config->mschapv2_retry && data->prev_challenge && + data->prev_error == ERROR_AUTHENTICATION_FAILURE) { + reqData = data->prev_challenge; + using_prev_challenge = 1; + config->mschapv2_retry = 0; + } + + pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, + reqData, &len); + if (pos == NULL || len < sizeof(*ms) + 1) { + ret->ignore = true; + return NULL; + } + + ms = (const struct eap_mschapv2_hdr *)pos; + if (eap_mschapv2_check_mslen(sm, len, ms)) { + ret->ignore = true; + return NULL; + } + + id = eap_get_id(reqData); + wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: RX identifier %d mschapv2_id %d\n", + id, ms->mschapv2_id); + switch (ms->op_code) { + case MSCHAPV2_OP_CHALLENGE: + if (!using_prev_challenge) + eap_mschapv2_copy_challenge(data, reqData); + return eap_mschapv2_challenge(sm, data, ret, ms, len, id); + case MSCHAPV2_OP_SUCCESS: + return eap_mschapv2_success(sm, data, ret, ms, len, id); + case MSCHAPV2_OP_FAILURE: + return eap_mschapv2_failure(sm, data, ret, ms, len, id); + default: + wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: Unknow op code %d -ignored\n", + ms->op_code); + return NULL; + } +} + +static bool +eap_mschapv2_isKeyAvailable(struct eap_sm *sm, void *priv) +{ + struct eap_mschapv2_data *data = priv; + return data->success && data->master_key_valid; +} + +static u8 * +eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len) +{ + struct eap_mschapv2_data *data = priv; + u8 *key; + int key_len; + + if (!data->master_key_valid || !data->success) + return NULL; + + key_len = 2 * MSCHAPV2_KEY_LEN; + + key = os_malloc(key_len); + + /* MSK = server MS-MPPE-Recv-Key | MS-MPPE-Send-Key, + * peer MS-MPPE-Send-Key | MS-MPPE-Recv-Key */ + get_asymetric_start_key(data->master_key, key, + MSCHAPV2_KEY_LEN, 1, 0); + get_asymetric_start_key(data->master_key, key + MSCHAPV2_KEY_LEN, + MSCHAPV2_KEY_LEN, 0, 0); + + *len = key_len; + return key; +} + +int +eap_peer_mschapv2_register(void) +{ + struct eap_method *eap; + int ret; + + eap = eap_peer_method_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, + "MSCHAPV2"); + + if (eap == NULL) + return -1; + + eap->init = eap_mschapv2_init; + eap->deinit = eap_mschapv2_deinit; + eap->process = eap_mschapv2_process; + eap->isKeyAvailable = eap_mschapv2_isKeyAvailable; + eap->getKey = eap_mschapv2_getKey; + + ret = eap_peer_method_register(eap); + if (ret) + eap_peer_method_free(eap); + return ret; +} + +#endif /* EAP_MSCHAPv2 */ diff --git a/components/wpa_supplicant/src/wpa2/eap_peer/eap_peap.c b/components/wpa_supplicant/src/wpa2/eap_peer/eap_peap.c new file mode 100644 index 0000000000..42c0685571 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/eap_peer/eap_peap.c @@ -0,0 +1,1357 @@ +/* + * EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt) + * Copyright (c) 2004-2008, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#ifdef EAP_PEAP + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "crypto/sha1.h" +#include "wpa2/tls/tls.h" +#include "wpa2/eap_peer/eap_tlv_common.h" +#include "wpa2/eap_peer/eap_peap_common.h" +#include "wpa2/eap_peer/eap_i.h" +#include "wpa2/eap_peer/eap_tls_common.h" +#include "wpa2/eap_peer/eap_config.h" +#include "wpa2/eap_peer/eap_methods.h" +//#include "tncc.h" + +/* Maximum supported PEAP version + * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt + * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt + * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt + */ +#define EAP_PEAP_VERSION 1 + + +static void eap_peap_deinit(struct eap_sm *sm, void *priv); + + +struct eap_peap_data { + struct eap_ssl_data ssl; + + int peap_version, force_peap_version, force_new_label; + + const struct eap_method *phase2_method; + void *phase2_priv; + int phase2_success; + int phase2_eap_success; + int phase2_eap_started; + + struct eap_method_type phase2_type; + struct eap_method_type *phase2_types; + size_t num_phase2_types; + + int peap_outer_success; /* 0 = PEAP terminated on Phase 2 inner + * EAP-Success + * 1 = reply with tunneled EAP-Success to inner + * EAP-Success and expect AS to send outer + * (unencrypted) EAP-Success after this + * 2 = reply with PEAP/TLS ACK to inner + * EAP-Success and expect AS to send outer + * (unencrypted) EAP-Success after this */ + int resuming; /* starting a resumed session */ + int reauth; /* reauthentication */ + u8 *key_data; + u8 *session_id; + size_t id_len; + + struct wpabuf *pending_phase2_req; + enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding; + int crypto_binding_used; + u8 binding_nonce[32]; + u8 ipmk[40]; + u8 cmk[20]; + int soh; /* Whether IF-TNCCS-SOH (Statement of Health; Microsoft NAP) + * is enabled. */ +}; + + +static int +eap_peap_parse_phase1(struct eap_peap_data *data, + const char *phase1) +{ + const char *pos; + + pos = os_strstr(phase1, "peapver="); + if (pos) { + data->force_peap_version = atoi(pos + 8); + data->peap_version = data->force_peap_version; + wpa_printf(MSG_DEBUG, "EAP-PEAP: Forced PEAP version %d", + data->force_peap_version); + } + + if (os_strstr(phase1, "peaplabel=1")) { + data->force_new_label = 1; + wpa_printf(MSG_DEBUG, "EAP-PEAP: Force new label for key " + "derivation"); + } + + if (os_strstr(phase1, "peap_outer_success=0")) { + data->peap_outer_success = 0; + wpa_printf(MSG_DEBUG, "EAP-PEAP: terminate authentication on " + "tunneled EAP-Success"); + } else if (os_strstr(phase1, "peap_outer_success=1")) { + data->peap_outer_success = 1; + wpa_printf(MSG_DEBUG, "EAP-PEAP: send tunneled EAP-Success " + "after receiving tunneled EAP-Success"); + } else if (os_strstr(phase1, "peap_outer_success=2")) { + data->peap_outer_success = 2; + wpa_printf(MSG_DEBUG, "EAP-PEAP: send PEAP/TLS ACK after " + "receiving tunneled EAP-Success"); + } + + if (os_strstr(phase1, "crypto_binding=0")) { + data->crypto_binding = NO_BINDING; + wpa_printf(MSG_DEBUG, "EAP-PEAP: Do not use cryptobinding"); + } else if (os_strstr(phase1, "crypto_binding=1")) { + data->crypto_binding = OPTIONAL_BINDING; + wpa_printf(MSG_DEBUG, "EAP-PEAP: Optional cryptobinding"); + } else if (os_strstr(phase1, "crypto_binding=2")) { + data->crypto_binding = REQUIRE_BINDING; + wpa_printf(MSG_DEBUG, "EAP-PEAP: Require cryptobinding"); + } + +#ifdef EAP_TNC + if (os_strstr(phase1, "tnc=soh2")) { + data->soh = 2; + wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled"); + } else if (os_strstr(phase1, "tnc=soh1")) { + data->soh = 1; + wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 1 enabled"); + } else if (os_strstr(phase1, "tnc=soh")) { + data->soh = 2; + wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled"); + } +#endif /* EAP_TNC */ + + return 0; +} + + +static void * +eap_peap_init(struct eap_sm *sm) +{ + struct eap_peap_data *data; + struct eap_peer_config *config = eap_get_config(sm); + + data = (struct eap_peap_data *)os_zalloc(sizeof(*data)); + if (data == NULL) + return NULL; + sm->peap_done = FALSE; + data->peap_version = EAP_PEAP_VERSION; + data->force_peap_version = -1; + data->peap_outer_success = 2; + data->crypto_binding = OPTIONAL_BINDING; + + if (config && config->phase1 && + eap_peap_parse_phase1(data, config->phase1) < 0) { + eap_peap_deinit(sm, data); + return NULL; + } + + if (eap_peer_select_phase2_methods(config, "auth=", + &data->phase2_types, + &data->num_phase2_types) < 0) { + eap_peap_deinit(sm, data); + return NULL; + } + + data->phase2_type.vendor = EAP_VENDOR_IETF; + data->phase2_type.method = EAP_TYPE_NONE; + + if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_PEAP)) { + wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL."); + eap_peap_deinit(sm, data); + return NULL; + } + + return data; +} + + +static void +eap_peap_deinit(struct eap_sm *sm, void *priv) +{ + struct eap_peap_data *data = priv; + if (data == NULL) + return; + if (data->phase2_priv && data->phase2_method) + data->phase2_method->deinit(sm, data->phase2_priv); + os_free(data->phase2_types); + eap_peer_tls_ssl_deinit(sm, &data->ssl); + os_free(data->key_data); + os_free(data->session_id); + wpabuf_free(data->pending_phase2_req); + os_free(data); +} + + +/** + * eap_tlv_build_nak - Build EAP-TLV NAK message + * @id: EAP identifier for the header + * @nak_type: TLV type (EAP_TLV_*) + * Returns: Buffer to the allocated EAP-TLV NAK message or %NULL on failure + * + * This function builds an EAP-TLV NAK message. The caller is responsible for + * freeing the returned buffer. + */ +static struct wpabuf * +eap_tlv_build_nak(int id, u16 nak_type) +{ + struct wpabuf *msg; + + msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 10, + EAP_CODE_RESPONSE, id); + if (msg == NULL) + return NULL; + + wpabuf_put_u8(msg, 0x80); /* Mandatory */ + wpabuf_put_u8(msg, EAP_TLV_NAK_TLV); + wpabuf_put_be16(msg, 6); /* Length */ + wpabuf_put_be32(msg, 0); /* Vendor-Id */ + wpabuf_put_be16(msg, nak_type); /* NAK-Type */ + + return msg; +} + + +static int +eap_peap_get_isk(struct eap_sm *sm, struct eap_peap_data *data, + u8 *isk, size_t isk_len) +{ + u8 *key; + size_t key_len; + + os_memset(isk, 0, isk_len); + if (data->phase2_method == NULL || data->phase2_priv == NULL || + data->phase2_method->isKeyAvailable == NULL || + data->phase2_method->getKey == NULL) + return 0; + + if (!data->phase2_method->isKeyAvailable(sm, data->phase2_priv) || + (key = data->phase2_method->getKey(sm, data->phase2_priv, + &key_len)) == NULL) { + wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not get key material " + "from Phase 2"); + return -1; + } + + if (key_len > isk_len) + key_len = isk_len; + os_memcpy(isk, key, key_len); + os_free(key); + + return 0; +} + + +static int +eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data) +{ + u8 *tk; + u8 isk[32], imck[60]; + + /* + * Tunnel key (TK) is the first 60 octets of the key generated by + * phase 1 of PEAP (based on TLS). + */ + tk = data->key_data; + if (tk == NULL) + return -1; + wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60); + + if (data->reauth && + tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) { + /* Fast-connect: IPMK|CMK = TK */ + os_memcpy(data->ipmk, tk, 40); + wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK", + data->ipmk, 40); + os_memcpy(data->cmk, tk + 40, 20); + wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK from TK", + data->cmk, 20); + return 0; + } + + if (eap_peap_get_isk(sm, data, isk, sizeof(isk)) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk)); + + /* + * IPMK Seed = "Inner Methods Compound Keys" | ISK + * TempKey = First 40 octets of TK + * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60) + * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space + * in the end of the label just before ISK; is that just a typo?) + */ + wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40); + if (peap_prfplus(data->peap_version, tk, 40, + "Inner Methods Compound Keys", + isk, sizeof(isk), imck, sizeof(imck)) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)", + imck, sizeof(imck)); + + os_memcpy(data->ipmk, imck, 40); + wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40); + os_memcpy(data->cmk, imck + 40, 20); + wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20); + + return 0; +} + + +static int +eap_tlv_add_cryptobinding(struct eap_sm *sm, + struct eap_peap_data *data, + struct wpabuf *buf) +{ + u8 *mac; + u8 eap_type = EAP_TYPE_PEAP; + const u8 *addr[2]; + size_t len[2]; + u16 tlv_type; + + /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ + addr[0] = wpabuf_put(buf, 0); + len[0] = 60; + addr[1] = &eap_type; + len[1] = 1; + + tlv_type = EAP_TLV_CRYPTO_BINDING_TLV; + if (data->peap_version >= 2) + tlv_type |= EAP_TLV_TYPE_MANDATORY; + wpabuf_put_be16(buf, tlv_type); + wpabuf_put_be16(buf, 56); + + wpabuf_put_u8(buf, 0); /* Reserved */ + wpabuf_put_u8(buf, data->peap_version); /* Version */ + wpabuf_put_u8(buf, data->peap_version); /* RecvVersion */ + wpabuf_put_u8(buf, 1); /* SubType: 0 = Request, 1 = Response */ + wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */ + mac = wpabuf_put(buf, 20); /* Compound_MAC */ + wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", data->cmk, 20); + wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1", + addr[0], len[0]); + wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2", + addr[1], len[1]); + hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac); + wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", mac, SHA1_MAC_LEN); + data->crypto_binding_used = 1; + + return 0; +} + + +/** + * eap_tlv_build_result - Build EAP-TLV Result message + * @id: EAP identifier for the header + * @status: Status (EAP_TLV_RESULT_SUCCESS or EAP_TLV_RESULT_FAILURE) + * Returns: Buffer to the allocated EAP-TLV Result message or %NULL on failure + * + * This function builds an EAP-TLV Result message. The caller is responsible + * for freeing the returned buffer. + */ +static struct wpabuf * +eap_tlv_build_result(struct eap_sm *sm, + struct eap_peap_data *data, + int crypto_tlv_used, + int id, u16 status) +{ + struct wpabuf *msg; + size_t len; + + if (data->crypto_binding == NO_BINDING) + crypto_tlv_used = 0; + + len = 6; + if (crypto_tlv_used) + len += 60; /* Cryptobinding TLV */ + msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, len, + EAP_CODE_RESPONSE, id); + if (msg == NULL) + return NULL; + + wpabuf_put_u8(msg, 0x80); /* Mandatory */ + wpabuf_put_u8(msg, EAP_TLV_RESULT_TLV); + wpabuf_put_be16(msg, 2); /* Length */ + wpabuf_put_be16(msg, status); /* Status */ + + if (crypto_tlv_used && eap_tlv_add_cryptobinding(sm, data, msg)) { + wpabuf_free(msg); + return NULL; + } + + return msg; +} + + +static int +eap_tlv_validate_cryptobinding(struct eap_sm *sm, + struct eap_peap_data *data, + const u8 *crypto_tlv, + size_t crypto_tlv_len) +{ + u8 buf[61], mac[SHA1_MAC_LEN]; + const u8 *pos; + + if (eap_peap_derive_cmk(sm, data) < 0) { + wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not derive CMK"); + return -1; + } + + if (crypto_tlv_len != 4 + 56) { + wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV " + "length %d", (int) crypto_tlv_len); + return -1; + } + + pos = crypto_tlv; + pos += 4; /* TLV header */ + if (pos[1] != data->peap_version) { + wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version " + "mismatch (was %d; expected %d)", + pos[1], data->peap_version); + return -1; + } + + if (pos[3] != 0) { + wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV " + "SubType %d", pos[3]); + return -1; + } + pos += 4; + os_memcpy(data->binding_nonce, pos, 32); + pos += 32; /* Nonce */ + + /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */ + os_memcpy(buf, crypto_tlv, 60); + os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */ + buf[60] = EAP_TYPE_PEAP; + wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Compound_MAC data", + buf, sizeof(buf)); + hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac); + + if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) { + wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in " + "cryptobinding TLV"); + wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received MAC", + pos, SHA1_MAC_LEN); + wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Expected MAC", + mac, SHA1_MAC_LEN); + return -1; + } + + wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received"); + + return 0; +} + + +/** + * eap_tlv_process - Process a received EAP-TLV message and generate a response + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @ret: Return values from EAP request validation and processing + * @req: EAP-TLV request to be processed. The caller must have validated that + * the buffer is large enough to contain full request (hdr->length bytes) and + * that the EAP type is EAP_TYPE_TLV. + * @resp: Buffer to return a pointer to the allocated response message. This + * field should be initialized to %NULL before the call. The value will be + * updated if a response message is generated. The caller is responsible for + * freeing the allocated message. + * @force_failure: Force negotiation to fail + * Returns: 0 on success, -1 on failure + */ +static int +eap_tlv_process(struct eap_sm *sm, struct eap_peap_data *data, + struct eap_method_ret *ret, + const struct wpabuf *req, struct wpabuf **resp, + int force_failure) +{ + size_t left, tlv_len; + const u8 *pos; + const u8 *result_tlv = NULL, *crypto_tlv = NULL; + size_t result_tlv_len = 0, crypto_tlv_len = 0; + int tlv_type, mandatory; + + /* Parse TLVs */ + pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, req, &left); + if (pos == NULL) + return -1; + wpa_hexdump(MSG_DEBUG, "EAP-TLV: Received TLVs", pos, left); + while (left >= 4) { + mandatory = !!(pos[0] & 0x80); + tlv_type = WPA_GET_BE16(pos) & 0x3fff; + pos += 2; + tlv_len = WPA_GET_BE16(pos); + pos += 2; + left -= 4; + if (tlv_len > left) { + wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun " + "(tlv_len=%lu left=%lu)", + (unsigned long) tlv_len, + (unsigned long) left); + return -1; + } + switch (tlv_type) { + case EAP_TLV_RESULT_TLV: + result_tlv = pos; + result_tlv_len = tlv_len; + break; + case EAP_TLV_CRYPTO_BINDING_TLV: + crypto_tlv = pos; + crypto_tlv_len = tlv_len; + break; + default: + wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type " + "%d%s", tlv_type, + mandatory ? " (mandatory)" : ""); + if (mandatory) { + /* NAK TLV and ignore all TLVs in this packet. + */ + *resp = eap_tlv_build_nak(eap_get_id(req), + tlv_type); + return *resp == NULL ? -1 : 0; + } + /* Ignore this TLV, but process other TLVs */ + break; + } + + pos += tlv_len; + left -= tlv_len; + } + if (left) { + wpa_printf(MSG_DEBUG, "EAP-TLV: Last TLV too short in " + "Request (left=%lu)", (unsigned long) left); + return -1; + } + + /* Process supported TLVs */ + if (crypto_tlv && data->crypto_binding != NO_BINDING) { + wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV", + crypto_tlv, crypto_tlv_len); + if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4, + crypto_tlv_len + 4) < 0) { + if (result_tlv == NULL) + return -1; + force_failure = 1; + crypto_tlv = NULL; /* do not include Cryptobinding TLV + * in response, if the received + * cryptobinding was invalid. */ + } + } else if (!crypto_tlv && data->crypto_binding == REQUIRE_BINDING) { + wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV"); + return -1; + } + + if (result_tlv) { + int status, resp_status; + wpa_hexdump(MSG_DEBUG, "EAP-TLV: Result TLV", + result_tlv, result_tlv_len); + if (result_tlv_len < 2) { + wpa_printf(MSG_INFO, "EAP-TLV: Too short Result TLV " + "(len=%lu)", + (unsigned long) result_tlv_len); + return -1; + } + status = WPA_GET_BE16(result_tlv); + if (status == EAP_TLV_RESULT_SUCCESS) { + wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success " + "- EAP-TLV/Phase2 Completed"); + if (force_failure) { + wpa_printf(MSG_INFO, "EAP-TLV: Earlier failure" + " - force failed Phase 2"); + resp_status = EAP_TLV_RESULT_FAILURE; + ret->decision = DECISION_FAIL; + } else { + resp_status = EAP_TLV_RESULT_SUCCESS; + ret->decision = DECISION_UNCOND_SUCC; + } + } else if (status == EAP_TLV_RESULT_FAILURE) { + wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure"); + resp_status = EAP_TLV_RESULT_FAILURE; + ret->decision = DECISION_FAIL; + } else { + wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result " + "Status %d", status); + resp_status = EAP_TLV_RESULT_FAILURE; + ret->decision = DECISION_FAIL; + } + ret->methodState = METHOD_DONE; + + *resp = eap_tlv_build_result(sm, data, crypto_tlv != NULL, + eap_get_id(req), resp_status); + } + + return 0; +} + + +static struct wpabuf * +eap_peapv2_tlv_eap_payload(struct wpabuf *buf) +{ + struct wpabuf *e; + struct eap_tlv_hdr *tlv; + + if (buf == NULL) + return NULL; + + /* Encapsulate EAP packet in EAP-Payload TLV */ + wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV"); + e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf)); + if (e == NULL) { + wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory " + "for TLV encapsulation"); + wpabuf_free(buf); + return NULL; + } + tlv = wpabuf_put(e, sizeof(*tlv)); + tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | + EAP_TLV_EAP_PAYLOAD_TLV); + tlv->length = host_to_be16(wpabuf_len(buf)); + wpabuf_put_buf(e, buf); + wpabuf_free(buf); + return e; +} + + +static int eap_peap_phase2_request(struct eap_sm *sm, + struct eap_peap_data *data, + struct eap_method_ret *ret, + struct wpabuf *req, + struct wpabuf **resp) +{ + struct eap_hdr *hdr = wpabuf_mhead(req); + size_t len = be_to_host16(hdr->length); + u8 *pos; + struct eap_method_ret iret; + //struct eap_peer_config *config = eap_get_config(sm); + + if (len <= sizeof(struct eap_hdr)) { + wpa_printf(MSG_INFO, "EAP-PEAP: too short " + "Phase 2 request (len=%lu)", (unsigned long) len); + return -1; + } + pos = (u8 *) (hdr + 1); + wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: type=%d\n", *pos); + switch (*pos) { + case EAP_TYPE_IDENTITY: + *resp = eap_sm_build_identity_resp(sm, hdr->identifier, 1); + break; + case EAP_TYPE_TLV: + os_memset(&iret, 0, sizeof(iret)); + if (eap_tlv_process(sm, data, &iret, req, resp, + data->phase2_eap_started && + !data->phase2_eap_success)) { + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + return -1; + } + if (iret.methodState == METHOD_DONE || + iret.methodState == METHOD_MAY_CONT) { + ret->methodState = iret.methodState; + ret->decision = iret.decision; + data->phase2_success = 1; + } + break; + case EAP_TYPE_EXPANDED: +#ifdef EAP_TNC + if (data->soh) { + const u8 *epos; + size_t eleft; + + epos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21, + req, &eleft); + if (epos) { + struct wpabuf *buf; + wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH EAP Extensions"); + buf = tncc_process_soh_request(data->soh, + epos, eleft); + if (buf) { + *resp = eap_msg_alloc( + EAP_VENDOR_MICROSOFT, 0x21, + wpabuf_len(buf), + EAP_CODE_RESPONSE, + hdr->identifier); + if (*resp == NULL) { + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + return -1; + } + wpabuf_put_buf(*resp, buf); + wpabuf_free(buf); + break; + } + } + } +#endif /* EAP_TNC */ + /* fall through */ + default: + if (data->phase2_type.vendor == EAP_VENDOR_IETF && + data->phase2_type.method == EAP_TYPE_NONE) { + size_t i; + for (i = 0; i < data->num_phase2_types; i++) { + if (data->phase2_types[i].vendor != + EAP_VENDOR_IETF || + data->phase2_types[i].method != *pos) + continue; + + data->phase2_type.vendor = + data->phase2_types[i].vendor; + data->phase2_type.method = + data->phase2_types[i].method; + wpa_printf(MSG_DEBUG, "EAP-PEAP: Selected " + "Phase 2 EAP vendor %d method %d\n", + data->phase2_type.vendor, + data->phase2_type.method); + break; + } + } + if (*pos != data->phase2_type.method || + *pos == EAP_TYPE_NONE) { + if (eap_peer_tls_phase2_nak(data->phase2_types, + data->num_phase2_types, + hdr, resp)) + return -1; + return 0; + } + + if (data->phase2_priv == NULL) { + data->phase2_method = eap_peer_get_eap_method( + data->phase2_type.vendor, + data->phase2_type.method); + if (data->phase2_method) { + sm->init_phase2 = 1; + data->phase2_priv = + data->phase2_method->init(sm); + sm->init_phase2 = 0; + } + } + if (data->phase2_priv == NULL || data->phase2_method == NULL) { + wpa_printf(MSG_ERROR, "EAP-PEAP: failed to initialize " + "Phase 2 EAP method %d\n", *pos); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + return -1; + } + data->phase2_eap_started = 1; + os_memset(&iret, 0, sizeof(iret)); + *resp = data->phase2_method->process(sm, data->phase2_priv, + &iret, req); + if ((iret.methodState == METHOD_DONE || + iret.methodState == METHOD_MAY_CONT) && + (iret.decision == DECISION_UNCOND_SUCC || + iret.decision == DECISION_COND_SUCC)) { + data->phase2_eap_success = 1; + data->phase2_success = 1; + } + break; + } + + if (*resp == NULL) { + wpa_printf(MSG_ERROR, "phase 2 response failure\n"); + wpabuf_free(data->pending_phase2_req); + data->pending_phase2_req = wpabuf_alloc_copy(hdr, len); + } +/* + if (*resp == NULL && + (config->pending_req_identity || config->pending_req_password || + config->pending_req_otp || config->pending_req_new_password)) { + wpabuf_free(data->pending_phase2_req); + data->pending_phase2_req = wpabuf_alloc_copy(hdr, len); + } +*/ + + return 0; +} + + +static int +eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data, + struct eap_method_ret *ret, + const struct eap_hdr *req, + const struct wpabuf *in_data, + struct wpabuf **out_data) +{ + struct wpabuf *in_decrypted = NULL; + int res, skip_change = 0; + struct eap_hdr *hdr, *rhdr; + struct wpabuf *resp = NULL; + size_t len; + + wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for" + " Phase 2\n", (unsigned long) wpabuf_len(in_data)); + + if (data->pending_phase2_req) { + wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 request - " + "skip decryption and use old data"); + /* Clear TLS reassembly state. */ + eap_peer_tls_reset_input(&data->ssl); + in_decrypted = data->pending_phase2_req; + data->pending_phase2_req = NULL; + skip_change = 1; + goto continue_req; + } + + if (wpabuf_len(in_data) == 0 && sm->workaround && + data->phase2_success) { + /* + * Cisco ACS seems to be using TLS ACK to terminate + * EAP-PEAPv0/GTC. Try to reply with TLS ACK. + */ + wpa_printf(MSG_DEBUG, "EAP-PEAP: Received TLS ACK, but " + "expected data - acknowledge with TLS ACK since " + "Phase 2 has been completed"); + ret->decision = DECISION_COND_SUCC; + ret->methodState = METHOD_DONE; + return 1; + } else if (wpabuf_len(in_data) == 0) { + /* Received TLS ACK - requesting more fragments */ + return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP, + data->peap_version, + req->identifier, NULL, out_data); + } + + res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted); + if (res) + return res; + +continue_req: + wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP", + in_decrypted); + + hdr = wpabuf_mhead(in_decrypted); + if (wpabuf_len(in_decrypted) == 5 && hdr->code == EAP_CODE_REQUEST && + be_to_host16(hdr->length) == 5 && + eap_get_type(in_decrypted) == EAP_TYPE_IDENTITY) { + /* At least FreeRADIUS seems to send full EAP header with + * EAP Request Identity */ + skip_change = 1; + } + if (wpabuf_len(in_decrypted) >= 5 && hdr->code == EAP_CODE_REQUEST && + eap_get_type(in_decrypted) == EAP_TYPE_TLV) { + skip_change = 1; + } + + if (data->peap_version == 0 && !skip_change) { + struct eap_hdr *nhdr; + struct wpabuf *nmsg = wpabuf_alloc(sizeof(struct eap_hdr) + + wpabuf_len(in_decrypted)); + if (nmsg == NULL) { + wpabuf_free(in_decrypted); + return 0; + } + nhdr = wpabuf_put(nmsg, sizeof(*nhdr)); + wpabuf_put_buf(nmsg, in_decrypted); + nhdr->code = req->code; + nhdr->identifier = req->identifier; + nhdr->length = host_to_be16(sizeof(struct eap_hdr) + + wpabuf_len(in_decrypted)); + + wpabuf_free(in_decrypted); + in_decrypted = nmsg; + } + + if (data->peap_version >= 2) { + struct eap_tlv_hdr *tlv; + struct wpabuf *nmsg; + + if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) { + wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 " + "EAP TLV"); + wpabuf_free(in_decrypted); + return 0; + } + tlv = wpabuf_mhead(in_decrypted); + if ((be_to_host16(tlv->tlv_type) & 0x3fff) != + EAP_TLV_EAP_PAYLOAD_TLV) { + wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV"); + wpabuf_free(in_decrypted); + return 0; + } + if (sizeof(*tlv) + be_to_host16(tlv->length) > + wpabuf_len(in_decrypted)) { + wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV " + "length"); + wpabuf_free(in_decrypted); + return 0; + } + hdr = (struct eap_hdr *) (tlv + 1); + if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) { + wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full " + "EAP packet in EAP TLV"); + wpabuf_free(in_decrypted); + return 0; + } + + nmsg = wpabuf_alloc(be_to_host16(hdr->length)); + if (nmsg == NULL) { + wpabuf_free(in_decrypted); + return 0; + } + + wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length)); + wpabuf_free(in_decrypted); + in_decrypted = nmsg; + } + + hdr = wpabuf_mhead(in_decrypted); + if (wpabuf_len(in_decrypted) < sizeof(*hdr)) { + wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 " + "EAP frame (len=%lu)", + (unsigned long) wpabuf_len(in_decrypted)); + wpabuf_free(in_decrypted); + return 0; + } + len = be_to_host16(hdr->length); + if (len > wpabuf_len(in_decrypted)) { + wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in " + "Phase 2 EAP frame (len=%lu hdr->length=%lu)", + (unsigned long) wpabuf_len(in_decrypted), + (unsigned long) len); + wpabuf_free(in_decrypted); + return 0; + } + if (len < wpabuf_len(in_decrypted)) { + wpa_printf(MSG_INFO, "EAP-PEAP: Odd.. Phase 2 EAP header has " + "shorter length than full decrypted data " + "(%lu < %lu)", + (unsigned long) len, + (unsigned long) wpabuf_len(in_decrypted)); + } + wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d " + "identifier=%d length=%lu\n", hdr->code, hdr->identifier, + (unsigned long) len); + switch (hdr->code) { + case EAP_CODE_REQUEST: + if (eap_peap_phase2_request(sm, data, ret, in_decrypted, + &resp)) { + wpabuf_free(in_decrypted); + wpa_printf(MSG_ERROR, "EAP-PEAP: Phase2 Request " + "processing failed\n"); + return 0; + } + break; + case EAP_CODE_SUCCESS: + wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success\n"); + if (data->peap_version == 1) { + /* EAP-Success within TLS tunnel is used to indicate + * shutdown of the TLS channel. The authentication has + * been completed. */ + if (data->phase2_eap_started && + !data->phase2_eap_success) { + wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 " + "Success used to indicate success, " + "but Phase 2 EAP was not yet " + "completed successfully"); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + wpabuf_free(in_decrypted); + return 0; + } + wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - " + "EAP-Success within TLS tunnel - " + "authentication completed"); + ret->decision = DECISION_UNCOND_SUCC; + ret->methodState = METHOD_DONE; + data->phase2_success = 1; + if (data->peap_outer_success == 2) { + wpabuf_free(in_decrypted); + wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK " + "to finish authentication"); + return 1; + } else if (data->peap_outer_success == 1) { + /* Reply with EAP-Success within the TLS + * channel to complete the authentication. */ + resp = wpabuf_alloc(sizeof(struct eap_hdr)); + if (resp) { + rhdr = wpabuf_put(resp, sizeof(*rhdr)); + rhdr->code = EAP_CODE_SUCCESS; + rhdr->identifier = hdr->identifier; + rhdr->length = + host_to_be16(sizeof(*rhdr)); + } + } else { + /* No EAP-Success expected for Phase 1 (outer, + * unencrypted auth), so force EAP state + * machine to SUCCESS state. */ + sm->peap_done = TRUE; + } + } else { + /* FIX: ? */ + } + break; + case EAP_CODE_FAILURE: + wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure\n"); + ret->decision = DECISION_FAIL; + ret->methodState = METHOD_MAY_CONT; + ret->allowNotifications = FALSE; + /* Reply with EAP-Failure within the TLS channel to complete + * failure reporting. */ + resp = wpabuf_alloc(sizeof(struct eap_hdr)); + if (resp) { + rhdr = wpabuf_put(resp, sizeof(*rhdr)); + rhdr->code = EAP_CODE_FAILURE; + rhdr->identifier = hdr->identifier; + rhdr->length = host_to_be16(sizeof(*rhdr)); + } + break; + default: + wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in " + "Phase 2 EAP header", hdr->code); + break; + } + + wpabuf_free(in_decrypted); + + if (resp) { + int skip_change2 = 0; + struct wpabuf *rmsg, buf; + + wpa_hexdump_buf_key(MSG_DEBUG, + "EAP-PEAP: Encrypting Phase 2 data", resp); + /* PEAP version changes */ + if (data->peap_version >= 2) { + resp = eap_peapv2_tlv_eap_payload(resp); + if (resp == NULL) + return -1; + } + if (wpabuf_len(resp) >= 5 && + wpabuf_head_u8(resp)[0] == EAP_CODE_RESPONSE && + eap_get_type(resp) == EAP_TYPE_TLV) + skip_change2 = 1; + rmsg = resp; + if (data->peap_version == 0 && !skip_change2) { + wpabuf_set(&buf, wpabuf_head_u8(resp) + + sizeof(struct eap_hdr), + wpabuf_len(resp) - sizeof(struct eap_hdr)); + rmsg = &buf; + } + + if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP, + data->peap_version, req->identifier, + rmsg, out_data)) { + wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt " + "a Phase 2 frame"); + } + wpabuf_free(resp); + } + + return 0; +} + + +static struct wpabuf * +eap_peap_process(struct eap_sm *sm, void *priv, + struct eap_method_ret *ret, + const struct wpabuf *reqData) +{ + const struct eap_hdr *req; + size_t left; + int res; + u8 flags, id; + struct wpabuf *resp; + const u8 *pos; + struct eap_peap_data *data = priv; + + pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret, + reqData, &left, &flags); + if (pos == NULL) + return NULL; + req = wpabuf_head(reqData); + id = req->identifier; + + if (flags & EAP_TLS_FLAGS_START) { + wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own " + "ver=%d)", flags & EAP_TLS_VERSION_MASK, + data->peap_version); + if ((flags & EAP_TLS_VERSION_MASK) < data->peap_version) + data->peap_version = flags & EAP_TLS_VERSION_MASK; + if (data->force_peap_version >= 0 && + data->force_peap_version != data->peap_version) { + wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select " + "forced PEAP version %d", + data->force_peap_version); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + ret->allowNotifications = FALSE; + return NULL; + } + wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d", + data->peap_version); + left = 0; /* make sure that this frame is empty, even though it + * should always be, anyway */ + } + + resp = NULL; + if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && + !data->resuming) { + struct wpabuf msg; + wpabuf_set(&msg, pos, left); + res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp); + } else { + res = eap_peer_tls_process_helper(sm, &data->ssl, + EAP_TYPE_PEAP, + data->peap_version, id, pos, + left, &resp); + + if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { + char label[24]; + wpa_printf(MSG_DEBUG, "EAP-PEAP: TLS done, proceed to Phase 2"); + os_free(data->key_data); + /* draft-josefsson-ppext-eap-tls-eap-05.txt + * specifies that PEAPv1 would use "client PEAP + * encryption" as the label. However, most existing + * PEAPv1 implementations seem to be using the old + * label, "client EAP encryption", instead. Use the old + * label by default, but allow it to be configured with + * phase1 parameter peaplabel=1. */ + if (data->peap_version > 1 || data->force_new_label) + //label = "client PEAP encryption"; + strcpy(label, "client PEAP encryption"); + else + //label = "client EAP encryption"; + strcpy(label, "client EAP encryption"); + wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in " + "key derivation", label); + data->key_data = + eap_peer_tls_derive_key(sm, &data->ssl, label, + EAP_TLS_KEY_LEN); + if (data->key_data) { + wpa_hexdump_key(MSG_DEBUG, + "EAP-PEAP: Derived key", + data->key_data, + EAP_TLS_KEY_LEN); + } else { + wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to " + "derive key"); + } + + os_free(data->session_id); + data->session_id = + eap_peer_tls_derive_session_id(sm, &data->ssl, + EAP_TYPE_PEAP, + &data->id_len); + if (data->session_id) { + wpa_hexdump(MSG_DEBUG, + "EAP-PEAP: Derived Session-Id", + data->session_id, data->id_len); + } else { + wpa_printf(MSG_ERROR, "EAP-PEAP: Failed to " + "derive Session-Id"); + } + + if (sm->workaround && data->resuming) { + /* + * At least few RADIUS servers (Aegis v1.1.6; + * but not v1.1.4; and Cisco ACS) seem to be + * terminating PEAPv1 (Aegis) or PEAPv0 (Cisco + * ACS) session resumption with outer + * EAP-Success. This does not seem to follow + * draft-josefsson-pppext-eap-tls-eap-05.txt + * section 4.2, so only allow this if EAP + * workarounds are enabled. + */ + wpa_printf(MSG_DEBUG, "EAP-PEAP: Workaround - " + "allow outer EAP-Success to " + "terminate PEAP resumption"); + ret->decision = DECISION_COND_SUCC; + data->phase2_success = 1; + } + + data->resuming = 0; + } + + if (res == 2) { + struct wpabuf msg; + /* + * Application data included in the handshake message. + */ + wpabuf_free(data->pending_phase2_req); + data->pending_phase2_req = resp; + resp = NULL; + wpabuf_set(&msg, pos, left); + res = eap_peap_decrypt(sm, data, ret, req, &msg, + &resp); + } + } + + if (ret->methodState == METHOD_DONE) { + ret->allowNotifications = FALSE; + } + + if (res == 1) { + wpabuf_free(resp); + return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP, + data->peap_version); + } + + return resp; +} + + +static bool +eap_peap_has_reauth_data(struct eap_sm *sm, void *priv) +{ + struct eap_peap_data *data = priv; + return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && + data->phase2_success; +} + + +static void +eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv) +{ + struct eap_peap_data *data = priv; + wpabuf_free(data->pending_phase2_req); + data->pending_phase2_req = NULL; + data->crypto_binding_used = 0; +} + + +static void * +eap_peap_init_for_reauth(struct eap_sm *sm, void *priv) +{ + struct eap_peap_data *data = priv; + os_free(data->key_data); + data->key_data = NULL; + os_free(data->session_id); + data->session_id = NULL; + if (eap_peer_tls_reauth_init(sm, &data->ssl)) { + os_free(data); + return NULL; + } + if (data->phase2_priv && data->phase2_method && + data->phase2_method->init_for_reauth) + data->phase2_method->init_for_reauth(sm, data->phase2_priv); + data->phase2_success = 0; + data->phase2_eap_success = 0; + data->phase2_eap_started = 0; + data->resuming = 1; + data->reauth = 1; + sm->peap_done = FALSE; + return priv; +} + + +static int +eap_peap_get_status(struct eap_sm *sm, void *priv, char *buf, + size_t buflen, int verbose) +{ + struct eap_peap_data *data = priv; + int len, ret; + + len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); + if (data->phase2_method) { + ret = snprintf(buf + len, buflen - len, + "EAP-PEAPv%d Phase2 method=%d\n", + data->peap_version, + data->phase2_method->method); + if (ret < 0 || (size_t) ret >= buflen - len) + return len; + len += ret; + } + return len; +} + + +static bool +eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv) +{ + struct eap_peap_data *data = priv; + return data->key_data != NULL && data->phase2_success; +} + + +static u8 * +eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len) +{ + struct eap_peap_data *data = priv; + u8 *key; + + if (data->key_data == NULL || !data->phase2_success) + return NULL; + + key = os_malloc(EAP_TLS_KEY_LEN); + if (key == NULL) + return NULL; + + *len = EAP_TLS_KEY_LEN; + + if (data->crypto_binding_used) { + u8 csk[128]; + /* + * Note: It looks like Microsoft implementation requires null + * termination for this label while the one used for deriving + * IPMK|CMK did not use null termination. + */ + if (peap_prfplus(data->peap_version, data->ipmk, 40, + "Session Key Generating Function", + (u8 *) "\00", 1, csk, sizeof(csk)) < 0) { + os_free(key); + return NULL; + } + wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk)); + os_memcpy(key, csk, EAP_TLS_KEY_LEN); + wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key", + key, EAP_TLS_KEY_LEN); + } else + os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); + + return key; +} + + +static u8 * +eap_peap_get_session_id(struct eap_sm *sm, void *priv, size_t *len) +{ + struct eap_peap_data *data = priv; + u8 *id; + + if (data->session_id == NULL || !data->phase2_success) + return NULL; + + id = os_malloc(data->id_len); + if (id == NULL) + return NULL; + + *len = data->id_len; + os_memcpy(id, data->session_id, data->id_len); + + return id; +} + + +int +eap_peer_peap_register(void) +{ + struct eap_method *eap; + int ret; + + eap = eap_peer_method_alloc(EAP_VENDOR_IETF, EAP_TYPE_PEAP, + "PEAP"); + if (eap == NULL) + return -1; + + eap->init = eap_peap_init; + eap->deinit = eap_peap_deinit; + eap->process = eap_peap_process; + eap->isKeyAvailable = eap_peap_isKeyAvailable; + eap->getKey = eap_peap_getKey; + eap->get_status = eap_peap_get_status; + eap->has_reauth_data = eap_peap_has_reauth_data; + eap->deinit_for_reauth = eap_peap_deinit_for_reauth; + eap->init_for_reauth = eap_peap_init_for_reauth; + eap->getSessionId = eap_peap_get_session_id; + + ret = eap_peer_method_register(eap); + if (ret) + eap_peer_method_free(eap); + return ret; +} + +#endif /* EAP_PEAP */ diff --git a/components/wpa_supplicant/src/wpa2/eap_peer/eap_peap_common.c b/components/wpa_supplicant/src/wpa2/eap_peer/eap_peap_common.c new file mode 100644 index 0000000000..d3fbbfc479 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/eap_peer/eap_peap_common.c @@ -0,0 +1,90 @@ +/* + * EAP-PEAP common routines + * Copyright (c) 2008-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifdef EAP_PEAP + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "crypto/sha1.h" +#include "wpa2/eap_peer/eap_peap_common.h" + +int +peap_prfplus(int version, const u8 *key, size_t key_len, + const char *label, const u8 *seed, size_t seed_len, + u8 *buf, size_t buf_len) +{ + unsigned char counter = 0; + size_t pos, plen; + u8 hash[SHA1_MAC_LEN]; + size_t label_len = os_strlen(label); + u8 extra[2]; + const unsigned char *addr[5]; + size_t len[5]; + + addr[0] = hash; + len[0] = 0; + addr[1] = (unsigned char *) label; + len[1] = label_len; + addr[2] = seed; + len[2] = seed_len; + + if (version == 0) { + /* + * PRF+(K, S, LEN) = T1 | T2 | ... | Tn + * T1 = HMAC-SHA1(K, S | 0x01 | 0x00 | 0x00) + * T2 = HMAC-SHA1(K, T1 | S | 0x02 | 0x00 | 0x00) + * ... + * Tn = HMAC-SHA1(K, Tn-1 | S | n | 0x00 | 0x00) + */ + + extra[0] = 0; + extra[1] = 0; + + addr[3] = &counter; + len[3] = 1; + addr[4] = extra; + len[4] = 2; + } else { + /* + * PRF (K,S,LEN) = T1 | T2 | T3 | T4 | ... where: + * T1 = HMAC-SHA1(K, S | LEN | 0x01) + * T2 = HMAC-SHA1 (K, T1 | S | LEN | 0x02) + * T3 = HMAC-SHA1 (K, T2 | S | LEN | 0x03) + * T4 = HMAC-SHA1 (K, T3 | S | LEN | 0x04) + * ... + */ + + extra[0] = buf_len & 0xff; + + addr[3] = extra; + len[3] = 1; + addr[4] = &counter; + len[4] = 1; + } + + pos = 0; + while (pos < buf_len) { + counter++; + plen = buf_len - pos; + if (hmac_sha1_vector(key, key_len, 5, addr, len, hash) < 0) + return -1; + if (plen >= SHA1_MAC_LEN) { + os_memcpy(&buf[pos], hash, SHA1_MAC_LEN); + pos += SHA1_MAC_LEN; + } else { + os_memcpy(&buf[pos], hash, plen); + break; + } + len[0] = SHA1_MAC_LEN; + } + + return 0; +} + +#endif /* EAP_PEAP */ diff --git a/components/wpa_supplicant/src/wpa2/eap_peer/eap_tls.c b/components/wpa_supplicant/src/wpa2/eap_peer/eap_tls.c new file mode 100644 index 0000000000..00dabfe40a --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/eap_peer/eap_tls.c @@ -0,0 +1,232 @@ +/* + * EAP peer method: EAP-TLS (RFC 2716) + * Copyright (c) 2004-2008, 2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#ifdef EAP_TLS + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "wpa2/tls/tls.h" +#include "wpa2/eap_peer/eap_i.h" +#include "wpa2/eap_peer/eap_defs.h" +#include "wpa2/eap_peer/eap_tls_common.h" +#include "wpa2/eap_peer/eap_config.h" +#include "wpa2/eap_peer/eap_methods.h" + +struct eap_tls_data { + struct eap_ssl_data ssl; + u8 *key_data; + u8 *session_id; + size_t id_len; + void *ssl_ctx; + u8 eap_type; +}; + + + +static void eap_tls_deinit(struct eap_sm *sm, void *priv) +{ + struct eap_tls_data *data = priv; + if (data == NULL) + return; + eap_peer_tls_ssl_deinit(sm, &data->ssl); + os_free(data->key_data); + os_free(data->session_id); + os_free(data); +} + + +static void * eap_tls_init(struct eap_sm *sm) +{ + struct eap_tls_data *data; + struct eap_peer_config *config = eap_get_config(sm); + if (config == NULL || + config->private_key == 0) { + wpa_printf(MSG_INFO, "EAP-TLS: Private key not configured"); + return NULL; + } + + data = (struct eap_tls_data *)os_zalloc(sizeof(*data)); + if (data == NULL) + return NULL; + + data->ssl_ctx = sm->ssl_ctx; + + if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_TLS)) { + wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); + eap_tls_deinit(sm, data); + return NULL; + } + + data->eap_type = EAP_TYPE_TLS; + + return data; +} + +static struct wpabuf * eap_tls_failure(struct eap_sm *sm, + struct eap_tls_data *data, + struct eap_method_ret *ret, int res, + struct wpabuf *resp, u8 id) +{ + wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed"); + + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + + if (res == -1) { + struct eap_peer_config *config = eap_get_config(sm); + if (config) { + /* + * The TLS handshake failed. So better forget the old + * PIN. It may be wrong, we cannot be sure but trying + * the wrong one again might block it on the card--so + * better ask the user again. + */ + os_free(config->pin); + config->pin = NULL; + } + } + + if (resp) { + /* + * This is likely an alert message, so send it instead of just + * ACKing the error. + */ + return resp; + } + + return eap_peer_tls_build_ack(id, data->eap_type, 0); +} + + +static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, + struct eap_method_ret *ret) +{ + wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); + + ret->methodState = METHOD_DONE; + ret->decision = DECISION_UNCOND_SUCC; + + os_free(data->key_data); + data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, + "client EAP encryption", + EAP_TLS_KEY_LEN + + EAP_EMSK_LEN); + if (data->key_data) { + wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key", + data->key_data, EAP_TLS_KEY_LEN); + wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK", + data->key_data + EAP_TLS_KEY_LEN, + EAP_EMSK_LEN); + } else { + wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key"); + } + + os_free(data->session_id); + data->session_id = eap_peer_tls_derive_session_id(sm, &data->ssl, + EAP_TYPE_TLS, + &data->id_len); + if (data->session_id) { + wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived Session-Id", + data->session_id, data->id_len); + } else { + wpa_printf(MSG_ERROR, "EAP-TLS: Failed to derive Session-Id"); + } +} + + +static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, + struct eap_method_ret *ret, + const struct wpabuf *reqData) +{ + size_t left; + int res; + struct wpabuf *resp; + u8 flags, id; + const u8 *pos; + struct eap_tls_data *data = priv; + + pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret, + reqData, &left, &flags); + if (pos == NULL) + return NULL; + id = eap_get_id(reqData); + + if (flags & EAP_TLS_FLAGS_START) { + wpa_printf(MSG_DEBUG, "EAP-TLS: Start"); + left = 0; /* make sure that this frame is empty, even though it + * should always be, anyway */ + } + + resp = NULL; + res = eap_peer_tls_process_helper(sm, &data->ssl, data->eap_type, 0, + id, pos, left, &resp); + + if (res < 0) { + return eap_tls_failure(sm, data, ret, res, resp, id); + } + + if (tls_connection_established(data->ssl_ctx, data->ssl.conn)) + eap_tls_success(sm, data, ret); + + if (res == 1) { + wpabuf_free(resp); + return eap_peer_tls_build_ack(id, data->eap_type, 0); + } + + return resp; +} + +static bool eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv) +{ + struct eap_tls_data *data = priv; + + return data->key_data != NULL; +} +static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len) +{ + struct eap_tls_data *data = priv; + u8 *key; + + if (data->key_data == NULL) + return NULL; + + key = os_malloc(EAP_TLS_KEY_LEN); + if (key == NULL) + return NULL; + + *len = EAP_TLS_KEY_LEN; + os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); + + return key; +} + +int eap_peer_tls_register(void) +{ + struct eap_method *eap; + int ret; + + eap = eap_peer_method_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLS, + "TLS"); + + if (eap == NULL) + return -1; + + eap->init = eap_tls_init; + eap->deinit = eap_tls_deinit; + eap->process = eap_tls_process; + eap->isKeyAvailable = eap_tls_isKeyAvailable; + eap->getKey = eap_tls_getKey; + + ret = eap_peer_method_register(eap); + if (ret) + eap_peer_method_free(eap); + return ret; +} + + +#endif /* EAP_TLS */ diff --git a/components/wpa_supplicant/src/wpa2/eap_peer/eap_tls_common.c b/components/wpa_supplicant/src/wpa2/eap_peer/eap_tls_common.c new file mode 100644 index 0000000000..2c97e6c0f0 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/eap_peer/eap_tls_common.c @@ -0,0 +1,1063 @@ +/* + * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions + * Copyright (c) 2004-2013, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "crypto/sha1.h" +#include "wpa2/tls/tls.h" +#include "wpa2/eap_peer/eap_i.h" +#include "wpa2/eap_peer/eap_tls_common.h" +#include "wpa2/eap_peer/eap_config.h" +#include "wpa2/eap_peer/eap_methods.h" + +static struct wpabuf * eap_tls_msg_alloc(EapType type, size_t payload_len, + u8 code, u8 identifier) +{ + if (type == EAP_UNAUTH_TLS_TYPE) + return eap_msg_alloc(EAP_VENDOR_UNAUTH_TLS, + EAP_VENDOR_TYPE_UNAUTH_TLS, payload_len, + code, identifier); + return eap_msg_alloc(EAP_VENDOR_IETF, type, payload_len, code, + identifier); +} + + +static int eap_tls_check_blob(struct eap_sm *sm, const char **name, + const u8 **data, size_t *data_len) +{ + const struct wpa_config_blob *blob; + + if (*name == NULL)// || os_strncmp(*name, "blob://", 7) != 0) + return 0; + + blob = eap_get_config_blob(sm, *name);// + 7); + if (blob == NULL) { + wpa_printf(MSG_ERROR, "%s: Named configuration blob '%s' not " + "found", __func__, *name);// + 7); + return -1; + } + + *name = NULL; + *data = blob->data; + *data_len = blob->len; + + return 0; +} + + +static void eap_tls_params_flags(struct tls_connection_params *params, + const char *txt) +{ + if (txt == NULL) + return; + if (os_strstr(txt, "tls_allow_md5=1")) + params->flags |= TLS_CONN_ALLOW_SIGN_RSA_MD5; + if (os_strstr(txt, "tls_disable_time_checks=1")) + params->flags |= TLS_CONN_DISABLE_TIME_CHECKS; + if (os_strstr(txt, "tls_disable_session_ticket=1")) + params->flags |= TLS_CONN_DISABLE_SESSION_TICKET; + if (os_strstr(txt, "tls_disable_session_ticket=0")) + params->flags &= ~TLS_CONN_DISABLE_SESSION_TICKET; +} + +static void eap_tls_params_from_conf1(struct tls_connection_params *params, + struct eap_peer_config *config) +{ + params->ca_cert = (char *) config->ca_cert; + params->ca_path = (char *) config->ca_path; + params->client_cert = (char *) config->client_cert; + params->private_key = (char *) config->private_key; + params->private_key_passwd = (char *) config->private_key_passwd; + eap_tls_params_flags(params, config->phase1); + if (wifi_sta_get_enterprise_disable_time_check()) + params->flags |= TLS_CONN_DISABLE_TIME_CHECKS; + else + params->flags &= (~TLS_CONN_DISABLE_TIME_CHECKS); +} + +static int eap_tls_params_from_conf(struct eap_sm *sm, + struct eap_ssl_data *data, + struct tls_connection_params *params, + struct eap_peer_config *config) +{ + os_memset(params, 0, sizeof(*params)); + if (sm->workaround && data->eap_type != EAP_TYPE_FAST) { + /* + * Some deployed authentication servers seem to be unable to + * handle the TLS Session Ticket extension (they are supposed + * to ignore unrecognized TLS extensions, but end up rejecting + * the ClientHello instead). As a workaround, disable use of + * TLS Sesson Ticket extension for EAP-TLS, EAP-PEAP, and + * EAP-TTLS (EAP-FAST uses session ticket, so any server that + * supports EAP-FAST does not need this workaround). + */ + params->flags |= TLS_CONN_DISABLE_SESSION_TICKET; + } + + wpa_printf(MSG_DEBUG, "TLS: using phase1 config options"); + eap_tls_params_from_conf1(params, config); + + /* + * Use blob data, if available. Otherwise, leave reference to external + * file as-is. + */ + if (eap_tls_check_blob(sm, ¶ms->ca_cert, ¶ms->ca_cert_blob, + ¶ms->ca_cert_blob_len) || + eap_tls_check_blob(sm, ¶ms->client_cert, + ¶ms->client_cert_blob, + ¶ms->client_cert_blob_len) || + eap_tls_check_blob(sm, ¶ms->private_key, + ¶ms->private_key_blob, + ¶ms->private_key_blob_len)) { + wpa_printf(MSG_INFO, "SSL: Failed to get configuration blobs"); + return -1; + } + + return 0; +} + + +static int eap_tls_init_connection(struct eap_sm *sm, + struct eap_ssl_data *data, + struct eap_peer_config *config, + struct tls_connection_params *params) +{ + int res; + + if (config->ocsp) + params->flags |= TLS_CONN_REQUEST_OCSP; + if (config->ocsp == 2) + params->flags |= TLS_CONN_REQUIRE_OCSP; + data->conn = tls_connection_init(data->ssl_ctx); + if (data->conn == NULL) { + wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS " + "connection"); + return -1; + } + + res = tls_connection_set_params(data->ssl_ctx, data->conn, params); + + if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) { + /* + * At this point with the pkcs11 engine the PIN might be wrong. + * We reset the PIN in the configuration to be sure to not use + * it again and the calling function must request a new one. + */ + os_free(config->pin); + config->pin = NULL; + } else if (res == TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED) { + wpa_printf(MSG_INFO, "TLS: Failed to load private key"); + /* + * We do not know exactly but maybe the PIN was wrong, + * so ask for a new one. + */ + os_free(config->pin); + config->pin = NULL; + tls_connection_deinit(data->ssl_ctx, data->conn); + data->conn = NULL; + return -1; + } else if (res) { + wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection " + "parameters"); + tls_connection_deinit(data->ssl_ctx, data->conn); + data->conn = NULL; + return -1; + } + + return 0; +} + + +/** + * eap_peer_tls_ssl_init - Initialize shared TLS functionality + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @data: Data for TLS processing + * @config: Pointer to the network configuration + * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST) + * Returns: 0 on success, -1 on failure + * + * This function is used to initialize shared TLS functionality for EAP-TLS, + * EAP-PEAP, EAP-TTLS, and EAP-FAST. + */ +int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, + struct eap_peer_config *config, u8 eap_type) +{ + struct tls_connection_params params; + + if (config == NULL) + return -1; + + data->eap = sm; + data->eap_type = eap_type; + data->ssl_ctx = sm->ssl_ctx; + if (eap_tls_params_from_conf(sm, data, ¶ms, config) < 0) /* no phase2 */ + return -1; + + if (eap_tls_init_connection(sm, data, config, ¶ms) < 0) + return -1; + + data->tls_out_limit = config->fragment_size; + + if (config->phase1 && + os_strstr(config->phase1, "include_tls_length=1")) { + wpa_printf(MSG_INFO, "TLS: Include TLS Message Length in " + "unfragmented packets"); + data->include_tls_length = 1; + } + + return 0; +} + + +/** + * eap_peer_tls_ssl_deinit - Deinitialize shared TLS functionality + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @data: Data for TLS processing + * + * This function deinitializes shared TLS functionality that was initialized + * with eap_peer_tls_ssl_init(). + */ +void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) +{ + tls_connection_deinit(data->ssl_ctx, data->conn); + eap_peer_tls_reset_input(data); + eap_peer_tls_reset_output(data); +} + + +/** + * eap_peer_tls_derive_key - Derive a key based on TLS session data + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @data: Data for TLS processing + * @label: Label string for deriving the keys, e.g., "client EAP encryption" + * @len: Length of the key material to generate (usually 64 for MSK) + * Returns: Pointer to allocated key on success or %NULL on failure + * + * This function uses TLS-PRF to generate pseudo-random data based on the TLS + * session data (client/server random and master key). Each key type may use a + * different label to bind the key usage into the generated material. + * + * The caller is responsible for freeing the returned buffer. + */ +u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, + const char *label, size_t len) +{ + struct tls_keys keys; + u8 *rnd = NULL, *out; + + out = os_malloc(len); + if (out == NULL) + return NULL; + + /* First, try to use TLS library function for PRF, if available. */ + if (tls_connection_prf(data->ssl_ctx, data->conn, label, 0, out, len) + == 0) + return out; + + /* + * TLS library did not support key generation, so get the needed TLS + * session parameters and use an internal implementation of TLS PRF to + * derive the key. + */ + if (tls_connection_get_keys(data->ssl_ctx, data->conn, &keys)) + goto fail; + + if (keys.client_random == NULL || keys.server_random == NULL || + keys.master_key == NULL) + goto fail; + + rnd = os_malloc(keys.client_random_len + keys.server_random_len); + if (rnd == NULL) + goto fail; + os_memcpy(rnd, keys.client_random, keys.client_random_len); + os_memcpy(rnd + keys.client_random_len, keys.server_random, + keys.server_random_len); + + if (tls_prf_sha1_md5(keys.master_key, keys.master_key_len, + label, rnd, keys.client_random_len + + keys.server_random_len, out, len)) { + goto fail; + } + + os_free(rnd); + return out; + +fail: + os_free(out); + os_free(rnd); + return NULL; +} + + +/** + * eap_peer_tls_derive_session_id - Derive a Session-Id based on TLS data + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @data: Data for TLS processing + * @eap_type: EAP method used in Phase 1 (EAP_TYPE_TLS/PEAP/TTLS/FAST) + * @len: Pointer to length of the session ID generated + * Returns: Pointer to allocated Session-Id on success or %NULL on failure + * + * This function derive the Session-Id based on the TLS session data + * (client/server random and method type). + * + * The caller is responsible for freeing the returned buffer. + */ +u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm, + struct eap_ssl_data *data, u8 eap_type, + size_t *len) +{ + struct tls_keys keys; + u8 *out; + + /* + * TLS library did not support session ID generation, + * so get the needed TLS session parameters + */ + if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) + return NULL; + + if (keys.client_random == NULL || keys.server_random == NULL || + keys.master_key == NULL) + return NULL; + + *len = 1 + keys.client_random_len + keys.server_random_len; + out = os_malloc(*len); + if (out == NULL) + return NULL; + + /* Session-Id = EAP type || client.random || server.random */ + out[0] = eap_type; + os_memcpy(out + 1, keys.client_random, keys.client_random_len); + os_memcpy(out + 1 + keys.client_random_len, keys.server_random, + keys.server_random_len); + + return out; +} + + +/** + * eap_peer_tls_reassemble_fragment - Reassemble a received fragment + * @data: Data for TLS processing + * @in_data: Next incoming TLS segment + * Returns: 0 on success, 1 if more data is needed for the full message, or + * -1 on error + */ +static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data, + const struct wpabuf *in_data) +{ + size_t tls_in_len, in_len; + + tls_in_len = data->tls_in ? wpabuf_len(data->tls_in) : 0; + in_len = in_data ? wpabuf_len(in_data) : 0; + + if (tls_in_len + in_len == 0) { + /* No message data received?! */ + wpa_printf(MSG_WARNING, "SSL: Invalid reassembly state: " + "tls_in_left=%lu tls_in_len=%lu in_len=%lu", + (unsigned long) data->tls_in_left, + (unsigned long) tls_in_len, + (unsigned long) in_len); + eap_peer_tls_reset_input(data); + return -1; + } + + if (tls_in_len + in_len > 65536) { + /* + * Limit length to avoid rogue servers from causing large + * memory allocations. + */ + wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size over " + "64 kB)"); + eap_peer_tls_reset_input(data); + return -1; + } + + if (in_len > data->tls_in_left) { + /* Sender is doing something odd - reject message */ + wpa_printf(MSG_INFO, "SSL: more data than TLS message length " + "indicated"); + eap_peer_tls_reset_input(data); + return -1; + } + + if (wpabuf_resize(&data->tls_in, in_len) < 0) { + wpa_printf(MSG_INFO, "SSL: Could not allocate memory for TLS " + "data"); + eap_peer_tls_reset_input(data); + return -1; + } + if (in_data) + wpabuf_put_buf(data->tls_in, in_data); + data->tls_in_left -= in_len; + + if (data->tls_in_left > 0) { + wpa_printf(MSG_INFO, "SSL: Need %lu bytes more input " + "data", (unsigned long) data->tls_in_left); + return 1; + } + + return 0; +} + + +/** + * eap_peer_tls_data_reassemble - Reassemble TLS data + * @data: Data for TLS processing + * @in_data: Next incoming TLS segment + * @need_more_input: Variable for returning whether more input data is needed + * to reassemble this TLS packet + * Returns: Pointer to output data, %NULL on error or when more data is needed + * for the full message (in which case, *need_more_input is also set to 1). + * + * This function reassembles TLS fragments. Caller must not free the returned + * data buffer since an internal pointer to it is maintained. + */ +static const struct wpabuf * eap_peer_tls_data_reassemble( + struct eap_ssl_data *data, const struct wpabuf *in_data, + int *need_more_input) +{ + *need_more_input = 0; + + if (data->tls_in_left > wpabuf_len(in_data) || data->tls_in) { + /* Message has fragments */ + int res = eap_peer_tls_reassemble_fragment(data, in_data); + if (res) { + if (res == 1) + *need_more_input = 1; + return NULL; + } + + /* Message is now fully reassembled. */ + } else { + /* No fragments in this message, so just make a copy of it. */ + data->tls_in_left = 0; + data->tls_in = wpabuf_dup(in_data); + if (data->tls_in == NULL) + return NULL; + } + + return data->tls_in; +} + + +/** + * eap_tls_process_input - Process incoming TLS message + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @data: Data for TLS processing + * @in_data: Message received from the server + * @in_len: Length of in_data + * @out_data: Buffer for returning a pointer to application data (if available) + * Returns: 0 on success, 1 if more input data is needed, 2 if application data + * is available, -1 on failure + */ +static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data, + const u8 *in_data, size_t in_len, + struct wpabuf **out_data) +{ + const struct wpabuf *msg; + int need_more_input; + struct wpabuf *appl_data; + struct wpabuf buf; + + wpabuf_set(&buf, in_data, in_len); + msg = eap_peer_tls_data_reassemble(data, &buf, &need_more_input); + if (msg == NULL) + return need_more_input ? 1 : -1; + + /* Full TLS message reassembled - continue handshake processing */ + if (data->tls_out) { + /* This should not happen.. */ + wpa_printf(MSG_INFO, "SSL: eap_tls_process_input - pending " + "tls_out data even though tls_out_len = 0"); + wpabuf_free(data->tls_out); + //WPA_ASSERT(data->tls_out == NULL); + } + appl_data = NULL; + data->tls_out = tls_connection_handshake(data->ssl_ctx, data->conn, + msg, &appl_data); + + eap_peer_tls_reset_input(data); + if (appl_data && + tls_connection_established(data->ssl_ctx, data->conn) && + !tls_connection_get_failed(data->ssl_ctx, data->conn)) { + wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application data", + appl_data); + *out_data = appl_data; + return 2; + } + + wpabuf_free(appl_data); + + return 0; +} + + +/** + * eap_tls_process_output - Process outgoing TLS message + * @data: Data for TLS processing + * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) + * @peap_version: Version number for EAP-PEAP/TTLS + * @id: EAP identifier for the response + * @ret: Return value to use on success + * @out_data: Buffer for returning the allocated output buffer + * Returns: ret (0 or 1) on success, -1 on failure + */ +static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type, + int peap_version, u8 id, int ret, + struct wpabuf **out_data) +{ + size_t len; + u8 *flags; + int more_fragments, length_included; + + if (data->tls_out == NULL) + return -1; + len = wpabuf_len(data->tls_out) - data->tls_out_pos; + wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total " + "%lu bytes)", + (unsigned long) len, + (unsigned long) wpabuf_len(data->tls_out)); + + /* + * Limit outgoing message to the configured maximum size. Fragment + * message if needed. + */ + if (len > data->tls_out_limit) { + more_fragments = 1; + len = data->tls_out_limit; + wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments " + "will follow", (unsigned long) len); + } else + more_fragments = 0; + + length_included = data->tls_out_pos == 0 && + (wpabuf_len(data->tls_out) > data->tls_out_limit || + data->include_tls_length); + if (!length_included && + eap_type == EAP_TYPE_PEAP && peap_version == 0 && + !tls_connection_established(data->eap->ssl_ctx, data->conn)) { + /* + * Windows Server 2008 NPS really wants to have the TLS Message + * length included in phase 0 even for unfragmented frames or + * it will get very confused with Compound MAC calculation and + * Outer TLVs. + */ + length_included = 1; + } + + *out_data = eap_tls_msg_alloc(eap_type, 1 + length_included * 4 + len, + EAP_CODE_RESPONSE, id); + if (*out_data == NULL) { + printf("[Debug] out_data is null, return \n"); + return -1; + } + + flags = wpabuf_put(*out_data, 1); + *flags = peap_version; + if (more_fragments) + *flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; + if (length_included) { + *flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; + wpabuf_put_be32(*out_data, wpabuf_len(data->tls_out)); + } + wpabuf_put_data(*out_data, + wpabuf_head_u8(data->tls_out) + data->tls_out_pos, + len); + data->tls_out_pos += len; + + if (!more_fragments) + eap_peer_tls_reset_output(data); + + return ret; +} + + +/** + * eap_peer_tls_process_helper - Process TLS handshake message + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @data: Data for TLS processing + * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) + * @peap_version: Version number for EAP-PEAP/TTLS + * @id: EAP identifier for the response + * @in_data: Message received from the server + * @in_len: Length of in_data + * @out_data: Buffer for returning a pointer to the response message + * Returns: 0 on success, 1 if more input data is needed, 2 if application data + * is available, or -1 on failure + * + * This function can be used to process TLS handshake messages. It reassembles + * the received fragments and uses a TLS library to process the messages. The + * response data from the TLS library is fragmented to suitable output messages + * that the caller can send out. + * + * out_data is used to return the response message if the return value of this + * function is 0, 2, or -1. In case of failure, the message is likely a TLS + * alarm message. The caller is responsible for freeing the allocated buffer if + * *out_data is not %NULL. + * + * This function is called for each received TLS message during the TLS + * handshake after eap_peer_tls_process_init() call and possible processing of + * TLS Flags field. Once the handshake has been completed, i.e., when + * tls_connection_established() returns 1, EAP method specific decrypting of + * the tunneled data is used. + */ +int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, + EapType eap_type, int peap_version, + u8 id, const u8 *in_data, size_t in_len, + struct wpabuf **out_data) +{ + int ret = 0; + + *out_data = NULL; + + if (data->tls_out && wpabuf_len(data->tls_out) > 0 && in_len > 0) { + wpa_printf(MSG_DEBUG, "SSL: Received non-ACK when output " + "fragments are waiting to be sent out"); + return -1; + } + + if (data->tls_out == NULL || wpabuf_len(data->tls_out) == 0) { + /* + * No more data to send out - expect to receive more data from + * the AS. + */ + int res = eap_tls_process_input(sm, data, in_data, in_len, + out_data); + if (res) { + /* + * Input processing failed (res = -1) or more data is + * needed (res = 1). + */ + return res; + } + + /* + * The incoming message has been reassembled and processed. The + * response was allocated into data->tls_out buffer. + */ + } + + if (data->tls_out == NULL) { + /* + * No outgoing fragments remaining from the previous message + * and no new message generated. This indicates an error in TLS + * processing. + */ + eap_peer_tls_reset_output(data); + return -1; + } + + if (tls_connection_get_failed(data->ssl_ctx, data->conn)) { + /* TLS processing has failed - return error */ + wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to " + "report error"); + ret = -1; + /* TODO: clean pin if engine used? */ + } + + if (data->tls_out == NULL || wpabuf_len(data->tls_out) == 0) { + /* + * TLS negotiation should now be complete since all other cases + * needing more data should have been caught above based on + * the TLS Message Length field. + */ + wpa_printf(MSG_DEBUG, "SSL: No data to be sent out"); + wpabuf_free(data->tls_out); + data->tls_out = NULL; + return 1; + } + + /* Send the pending message (in fragments, if needed). */ + return eap_tls_process_output(data, eap_type, peap_version, id, ret, + out_data); +} + + +/** + * eap_peer_tls_build_ack - Build a TLS ACK frame + * @id: EAP identifier for the response + * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) + * @peap_version: Version number for EAP-PEAP/TTLS + * Returns: Pointer to the allocated ACK frame or %NULL on failure + */ +struct wpabuf * eap_peer_tls_build_ack(u8 id, EapType eap_type, + int peap_version) +{ + struct wpabuf *resp; + + resp = eap_tls_msg_alloc(eap_type, 1, EAP_CODE_RESPONSE, id); + if (resp == NULL) + return NULL; + wpa_printf(MSG_DEBUG, "SSL: Building ACK (type=%d id=%d ver=%d) \n", + (int) eap_type, id, peap_version); + wpabuf_put_u8(resp, peap_version); /* Flags */ + return resp; +} + + +/** + * eap_peer_tls_reauth_init - Re-initialize shared TLS for session resumption + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @data: Data for TLS processing + * Returns: 0 on success, -1 on failure + */ +int eap_peer_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data) +{ + eap_peer_tls_reset_input(data); + eap_peer_tls_reset_output(data); + return tls_connection_shutdown(data->ssl_ctx, data->conn); +} + + +/** + * eap_peer_tls_status - Get TLS status + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @data: Data for TLS processing + * @buf: Buffer for status information + * @buflen: Maximum buffer length + * @verbose: Whether to include verbose status information + * Returns: Number of bytes written to buf. + */ +int eap_peer_tls_status(struct eap_sm *sm, struct eap_ssl_data *data, + char *buf, size_t buflen, int verbose) +{ + char name[128]; + int len = 0, ret; + + if (tls_get_cipher(data->ssl_ctx, data->conn, name, sizeof(name)) == 0) + { + //ret = os_snprintf(buf + len, buflen - len, + ret = sprintf(buf + len, + "EAP TLS cipher=%s\n", name); + if (ret < 0 || (size_t) ret >= buflen - len) + return len; + len += ret; + } + + return len; +} + + +/** + * eap_peer_tls_process_init - Initial validation/processing of EAP requests + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @data: Data for TLS processing + * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) + * @ret: Return values from EAP request validation and processing + * @reqData: EAP request to be processed (eapReqData) + * @len: Buffer for returning length of the remaining payload + * @flags: Buffer for returning TLS flags + * Returns: Pointer to payload after TLS flags and length or %NULL on failure + * + * This function validates the EAP header and processes the optional TLS + * Message Length field. If this is the first fragment of a TLS message, the + * TLS reassembly code is initialized to receive the indicated number of bytes. + * + * EAP-TLS, EAP-PEAP, EAP-TTLS, and EAP-FAST methods are expected to use this + * function as the first step in processing received messages. They will need + * to process the flags (apart from Message Length Included) that are returned + * through the flags pointer and the message payload that will be returned (and + * the length is returned through the len pointer). Return values (ret) are set + * for continuation of EAP method processing. The caller is responsible for + * setting these to indicate completion (either success or failure) based on + * the authentication result. + */ +const u8 * eap_peer_tls_process_init(struct eap_sm *sm, + struct eap_ssl_data *data, + EapType eap_type, + struct eap_method_ret *ret, + const struct wpabuf *reqData, + size_t *len, u8 *flags) +{ + const u8 *pos; + size_t left; + unsigned int tls_msg_len; + + if (tls_get_errors(data->ssl_ctx)) { + wpa_printf(MSG_INFO, "SSL: TLS errors detected"); + ret->ignore = TRUE; + return NULL; + } + + if (eap_type == EAP_UNAUTH_TLS_TYPE) + pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS, + EAP_VENDOR_TYPE_UNAUTH_TLS, reqData, + &left); + else + pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, reqData, + &left); + if (pos == NULL) { + ret->ignore = TRUE; + return NULL; + } + if (left == 0) { + wpa_printf(MSG_DEBUG, "SSL: Invalid TLS message: no Flags " + "octet included"); + if (!sm->workaround) { + ret->ignore = TRUE; + return NULL; + } + + wpa_printf(MSG_DEBUG, "SSL: Workaround - assume no Flags " + "indicates ACK frame"); + *flags = 0; + } else { + *flags = *pos++; + left--; + } + wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - " + "Flags 0x%02x", (unsigned long) wpabuf_len(reqData), + *flags); + if (*flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { + if (left < 4) { + wpa_printf(MSG_INFO, "SSL: Short frame with TLS " + "length"); + ret->ignore = TRUE; + return NULL; + } + tls_msg_len = WPA_GET_BE32(pos); + wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d", + tls_msg_len); + if (data->tls_in_left == 0) { + data->tls_in_total = tls_msg_len; + data->tls_in_left = tls_msg_len; + wpabuf_free(data->tls_in); + data->tls_in = NULL; + } + pos += 4; + left -= 4; + + if (left > tls_msg_len) { + wpa_printf(MSG_INFO, "SSL: TLS Message Length (%d " + "bytes) smaller than this fragment (%d " + "bytes)", (int) tls_msg_len, (int) left); + ret->ignore = TRUE; + return NULL; + } + } + + ret->ignore = FALSE; + ret->methodState = METHOD_MAY_CONT; + ret->decision = DECISION_FAIL; + ret->allowNotifications = TRUE; + + *len = left; + return pos; +} + + +/** + * eap_peer_tls_reset_input - Reset input buffers + * @data: Data for TLS processing + * + * This function frees any allocated memory for input buffers and resets input + * state. + */ +void eap_peer_tls_reset_input(struct eap_ssl_data *data) +{ + data->tls_in_left = data->tls_in_total = 0; + wpabuf_free(data->tls_in); + data->tls_in = NULL; +} + + +/** + * eap_peer_tls_reset_output - Reset output buffers + * @data: Data for TLS processing + * + * This function frees any allocated memory for output buffers and resets + * output state. + */ +void eap_peer_tls_reset_output(struct eap_ssl_data *data) +{ + data->tls_out_pos = 0; + wpabuf_free(data->tls_out); + data->tls_out = NULL; +} + + +/** + * eap_peer_tls_decrypt - Decrypt received phase 2 TLS message + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @data: Data for TLS processing + * @in_data: Message received from the server + * @in_decrypted: Buffer for returning a pointer to the decrypted message + * Returns: 0 on success, 1 if more input data is needed, or -1 on failure + */ +int eap_peer_tls_decrypt(struct eap_sm *sm, struct eap_ssl_data *data, + const struct wpabuf *in_data, + struct wpabuf **in_decrypted) +{ + const struct wpabuf *msg; + int need_more_input; + + msg = eap_peer_tls_data_reassemble(data, in_data, &need_more_input); + if (msg == NULL) + return need_more_input ? 1 : -1; + + *in_decrypted = tls_connection_decrypt(data->ssl_ctx, data->conn, msg); + eap_peer_tls_reset_input(data); + if (*in_decrypted == NULL) { + wpa_printf(MSG_INFO, "SSL: Failed to decrypt Phase 2 data"); + return -1; + } + return 0; +} + + +/** + * eap_peer_tls_encrypt - Encrypt phase 2 TLS message + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @data: Data for TLS processing + * @eap_type: EAP type (EAP_TYPE_TLS, EAP_TYPE_PEAP, ...) + * @peap_version: Version number for EAP-PEAP/TTLS + * @id: EAP identifier for the response + * @in_data: Plaintext phase 2 data to encrypt or %NULL to continue fragments + * @out_data: Buffer for returning a pointer to the encrypted response message + * Returns: 0 on success, -1 on failure + */ +int eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *data, + EapType eap_type, int peap_version, u8 id, + const struct wpabuf *in_data, + struct wpabuf **out_data) +{ + if (in_data) { + eap_peer_tls_reset_output(data); + data->tls_out = tls_connection_encrypt(data->ssl_ctx, + data->conn, in_data); + if (data->tls_out == NULL) { + wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 " + "data (in_len=%lu)", + (unsigned long) wpabuf_len(in_data)); + eap_peer_tls_reset_output(data); + return -1; + } + } + + return eap_tls_process_output(data, eap_type, peap_version, id, 0, + out_data); +} + +/** + * eap_peer_select_phase2_methods - Select phase 2 EAP method + * @config: Pointer to the network configuration + * @prefix: 'phase2' configuration prefix, e.g., "auth=" + * @types: Buffer for returning allocated list of allowed EAP methods + * @num_types: Buffer for returning number of allocated EAP methods + * Returns: 0 on success, -1 on failure + * + * This function is used to parse EAP method list and select allowed methods + * for Phase2 authentication. + */ +int eap_peer_select_phase2_methods(struct eap_peer_config *config, + const char *prefix, + struct eap_method_type **types, + size_t *num_types) +{ + char *start, *pos, *buf; + struct eap_method_type *methods = NULL, *_methods; + u8 method; + size_t num_methods = 0, prefix_len; + + if (config == NULL || config->phase2 == NULL) + goto get_defaults; + + start = buf = os_strdup(config->phase2); + if (buf == NULL) + return -1; + + prefix_len = os_strlen(prefix); + + while (start && *start != '\0') { + int vendor; + pos = os_strstr(start, prefix); + if (pos == NULL) + break; + if (start != pos && *(pos - 1) != ' ') { + start = pos + prefix_len; + continue; + } + + start = pos + prefix_len; + pos = (char *)os_strchr(start, ' '); + if (pos) + *pos++ = '\0'; + method = eap_get_phase2_type(start, &vendor); + if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE) { + wpa_printf(MSG_INFO, "TLS: Unsupported Phase2 EAP " + "method '%s'\n", start); + } else { + num_methods++; + _methods = (struct eap_method_type *)os_realloc(methods, + num_methods * sizeof(*methods)); + if (_methods == NULL) { + os_free(methods); + os_free(buf); + return -1; + } + methods = _methods; + methods[num_methods - 1].vendor = vendor; + methods[num_methods - 1].method = method; + } + + start = pos; + } + + os_free(buf); + +get_defaults: + if (methods == NULL) + methods = eap_get_phase2_types(config, &num_methods); + if (methods == NULL) { + wpa_printf(MSG_ERROR, "TLS: No Phase EAP methods available\n"); + return -1; + } + wpa_hexdump(MSG_DEBUG, "TLS: Phase2 EAP types", + (u8 *) methods, + num_methods * sizeof(struct eap_method_type)); + + *types = methods; + *num_types = num_methods; + + return 0; +} + +/** + * eap_peer_tls_phase2_nak - Generate EAP-Nak for Phase 2 + * @types: Buffer for returning allocated list of allowed EAP methods + * @num_types: Buffer for returning number of allocated EAP methods + * @hdr: EAP-Request header (and the following EAP type octet) + * @resp: Buffer for returning the EAP-Nak message + * Returns: 0 on success, -1 on failure + */ +int eap_peer_tls_phase2_nak(struct eap_method_type *types, size_t num_types, + struct eap_hdr *hdr, struct wpabuf **resp) +{ + u8 *pos = (u8 *) (hdr + 1); + size_t i; + + /* TODO: add support for expanded Nak */ + wpa_printf(MSG_DEBUG, "TLS: Phase Request: Nak type=%d\n", *pos); + wpa_hexdump(MSG_DEBUG, "TLS: Allowed Phase2 EAP types", + (u8 *) types, num_types * sizeof(struct eap_method_type)); + *resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK, num_types, + EAP_CODE_RESPONSE, hdr->identifier); + if (*resp == NULL) + return -1; + + for (i = 0; i < num_types; i++) { + if (types[i].vendor == EAP_VENDOR_IETF && + types[i].method < 256) + wpabuf_put_u8(*resp, types[i].method); + } + + eap_update_len(*resp); + + return 0; +} diff --git a/components/wpa_supplicant/src/wpa2/eap_peer/eap_ttls.c b/components/wpa_supplicant/src/wpa2/eap_peer/eap_ttls.c new file mode 100644 index 0000000000..6e8984b350 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/eap_peer/eap_ttls.c @@ -0,0 +1,1673 @@ +/* + * EAP peer method: EAP-TTLS (RFC 5281) + * Copyright (c) 2004-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifdef EAP_TTLS + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "crypto/ms_funcs.h" +#include "crypto/sha1.h" +#include "wpa2/tls/tls.h" +//#include "eap_common/chap.h" +#include "wpa2/eap_peer/eap.h" +#include "wpa2/eap_peer/eap_ttls.h" +#include "wpa2/eap_peer/mschapv2.h" +//#include "wpa2/eap_peer/chap.h" +#include "wpa2/eap_peer/eap_i.h" +#include "wpa2/eap_peer/eap_tls_common.h" +#include "wpa2/eap_peer/eap_config.h" +#include "wpa2/eap_peer/eap_methods.h" + + +#define EAP_TTLS_VERSION 0 + +static void eap_ttls_deinit(struct eap_sm *sm, void *priv); + +struct eap_ttls_data { + struct eap_ssl_data ssl; + + int ttls_version; + + const struct eap_method *phase2_method; + void *phase2_priv; + int phase2_success; + int phase2_start; + + enum phase2_types { + EAP_TTLS_PHASE2_EAP, + EAP_TTLS_PHASE2_MSCHAPV2, + EAP_TTLS_PHASE2_MSCHAP, + EAP_TTLS_PHASE2_PAP, + EAP_TTLS_PHASE2_CHAP + } phase2_type; + struct eap_method_type phase2_eap_type; + struct eap_method_type *phase2_eap_types; + size_t num_phase2_eap_types; + + u8 auth_response[MSCHAPV2_AUTH_RESPONSE_LEN]; + int auth_response_valid; + u8 master_key[MSCHAPV2_MASTER_KEY_LEN]; /* MSCHAPv2 master key */ + u8 ident; + int resuming; /* starting a resumed session */ + int reauth; /* reauthentication */ + u8 *key_data; + u8 *session_id; + size_t id_len; + + struct wpabuf *pending_phase2_req; + +#ifdef EAP_TNC + int ready_for_tnc; + int tnc_started; +#endif /* EAP_TNC */ +}; + + +static void * eap_ttls_init(struct eap_sm *sm) +{ + struct eap_ttls_data *data; + struct eap_peer_config *config = eap_get_config(sm); + //char *selected; + + data = (struct eap_ttls_data *)os_zalloc(sizeof(*data)); + if (data == NULL) + return NULL; + data->ttls_version = EAP_TTLS_VERSION; + data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2; + +/* + selected = "MSCHAPV2"; + //TODO: Now only support EAP-TTLS/MSCHAPV2 + if (config && config->phase2) { + if (os_strstr(config->phase2, "autheap=")) { + selected = "EAP"; + data->phase2_type = EAP_TTLS_PHASE2_EAP; + } else if (os_strstr(config->phase2, "auth=MSCHAPV2")) { + selected = "MSCHAPV2"; + data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2; + } else if (os_strstr(config->phase2, "auth=MSCHAP")) { + selected = "MSCHAP"; + data->phase2_type = EAP_TTLS_PHASE2_MSCHAP; + } else if (os_strstr(config->phase2, "auth=PAP")) { + selected = "PAP"; + data->phase2_type = EAP_TTLS_PHASE2_PAP; + } else if (os_strstr(config->phase2, "auth=CHAP")) { + selected = "CHAP"; + data->phase2_type = EAP_TTLS_PHASE2_CHAP; + } + } + wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 type: %s", selected); + + if (data->phase2_type == EAP_TTLS_PHASE2_EAP) { + if (eap_peer_select_phase2_methods(config, "autheap=", + &data->phase2_eap_types, + &data->num_phase2_eap_types) + < 0) { + eap_ttls_deinit(sm, data); + return NULL; + } + + data->phase2_eap_type.vendor = EAP_VENDOR_IETF; + data->phase2_eap_type.method = EAP_TYPE_NONE; + } +*/ + + if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_TTLS)) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to initialize SSL.\n"); + eap_ttls_deinit(sm, data); + return NULL; + } + + return data; +} + +static void eap_ttls_phase2_eap_deinit(struct eap_sm *sm, + struct eap_ttls_data *data) +{ + if (data->phase2_priv && data->phase2_method) { + data->phase2_method->deinit(sm, data->phase2_priv); + data->phase2_method = NULL; + data->phase2_priv = NULL; + } +} + +static void eap_ttls_deinit(struct eap_sm *sm, void *priv) +{ + struct eap_ttls_data *data = priv; + if (data == NULL) + return; + eap_ttls_phase2_eap_deinit(sm, data); + os_free(data->phase2_eap_types); + eap_peer_tls_ssl_deinit(sm, &data->ssl); + os_free(data->key_data); + os_free(data->session_id); + wpabuf_free(data->pending_phase2_req); + os_free(data); +} + +static u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id, + int mandatory, size_t len) +{ + struct ttls_avp_vendor *avp; + u8 flags; + size_t hdrlen; + + avp = (struct ttls_avp_vendor *) avphdr; + flags = mandatory ? AVP_FLAGS_MANDATORY : 0; + if (vendor_id) { + flags |= AVP_FLAGS_VENDOR; + hdrlen = sizeof(*avp); + avp->vendor_id = host_to_be32(vendor_id); + } else { + hdrlen = sizeof(struct ttls_avp); + } + + avp->avp_code = host_to_be32(avp_code); + avp->avp_length = host_to_be32((flags << 24) | (u32) (hdrlen + len)); + + return avphdr + hdrlen; +} + + +static u8 * eap_ttls_avp_add(u8 *start, u8 *avphdr, u32 avp_code, + u32 vendor_id, int mandatory, + const u8 *data, size_t len) +{ + u8 *pos; + pos = eap_ttls_avp_hdr(avphdr, avp_code, vendor_id, mandatory, len); + os_memcpy(pos, data, len); + pos += len; + AVP_PAD(start, pos); + return pos; +} + +#if 0 +static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code, + int mandatory) +{ + struct wpabuf *msg; + u8 *avp, *pos; + + msg = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(*resp) + 4); + if (msg == NULL) { + wpabuf_free(*resp); + *resp = NULL; + return -1; + } + + avp = wpabuf_mhead(msg); + pos = eap_ttls_avp_hdr(avp, avp_code, 0, mandatory, wpabuf_len(*resp)); + os_memcpy(pos, wpabuf_head(*resp), wpabuf_len(*resp)); + pos += wpabuf_len(*resp); + AVP_PAD(avp, pos); + wpabuf_free(*resp); + wpabuf_put(msg, pos - avp); + *resp = msg; + return 0; +} +#endif + +static int eap_ttls_v0_derive_key(struct eap_sm *sm, + struct eap_ttls_data *data) +{ + os_free(data->key_data); + data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, + "ttls keying material", + EAP_TLS_KEY_LEN); + if (!data->key_data) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to derive key\n"); + return -1; + } + + os_free(data->session_id); + data->session_id = eap_peer_tls_derive_session_id(sm, &data->ssl, + EAP_TYPE_TTLS, + &data->id_len); + if (data->session_id) { + } else { + wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to derive Session-Id\n"); + } + + return 0; +} + + +static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm, + struct eap_ttls_data *data, size_t len) +{ + return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", len); +} + +#if 0 +static void eap_ttls_phase2_select_eap_method(struct eap_ttls_data *data, + u8 method) +{ + size_t i; + for (i = 0; i < data->num_phase2_eap_types; i++) { + if (data->phase2_eap_types[i].vendor != EAP_VENDOR_IETF || + data->phase2_eap_types[i].method != method) + continue; + + data->phase2_eap_type.vendor = + data->phase2_eap_types[i].vendor; + data->phase2_eap_type.method = + data->phase2_eap_types[i].method; + wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected " + "Phase 2 EAP vendor %d method %d\n", + data->phase2_eap_type.vendor, + data->phase2_eap_type.method); + break; + } +} + +static int eap_ttls_phase2_eap_process(struct eap_sm *sm, + struct eap_ttls_data *data, + struct eap_method_ret *ret, + struct eap_hdr *hdr, size_t len, + struct wpabuf **resp) +{ + struct wpabuf msg; + struct eap_method_ret iret; + + os_memset(&iret, 0, sizeof(iret)); + wpabuf_set(&msg, hdr, len); + *resp = data->phase2_method->process(sm, data->phase2_priv, &iret, + &msg); + if ((iret.methodState == METHOD_DONE || + iret.methodState == METHOD_MAY_CONT) && + (iret.decision == DECISION_UNCOND_SUCC || + iret.decision == DECISION_COND_SUCC || + iret.decision == DECISION_FAIL)) { + ret->methodState = iret.methodState; + ret->decision = iret.decision; + } + + return 0; +} + + +static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm, + struct eap_ttls_data *data, + struct eap_method_ret *ret, + struct eap_hdr *hdr, size_t len, + u8 method, struct wpabuf **resp) +{ +#ifdef EAP_TNC + if (data->tnc_started && data->phase2_method && + data->phase2_priv && method == EAP_TYPE_TNC && + data->phase2_eap_type.method == EAP_TYPE_TNC) + return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len, + resp); + + if (data->ready_for_tnc && !data->tnc_started && + method == EAP_TYPE_TNC) { + wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed " + "EAP method\n"); + data->tnc_started = 1; + } + + if (data->tnc_started) { + if (data->phase2_eap_type.vendor != EAP_VENDOR_IETF || + data->phase2_eap_type.method == EAP_TYPE_TNC) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Unexpected EAP " + "type %d for TNC\n", method); + return -1; + } + + data->phase2_eap_type.vendor = EAP_VENDOR_IETF; + data->phase2_eap_type.method = method; + wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected " + "Phase 2 EAP vendor %d method %d (TNC)\n", + data->phase2_eap_type.vendor, + data->phase2_eap_type.method); + + if (data->phase2_type == EAP_TTLS_PHASE2_EAP) + eap_ttls_phase2_eap_deinit(sm, data); + } +#endif /* EAP_TNC */ + + if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF && + data->phase2_eap_type.method == EAP_TYPE_NONE) + eap_ttls_phase2_select_eap_method(data, method); + + if (method != data->phase2_eap_type.method || method == EAP_TYPE_NONE) + { + return -1; + if (eap_peer_tls_phase2_nak(data->phase2_eap_types, + data->num_phase2_eap_types, + hdr, resp)) + return -1; + return 0; + + } + + if (data->phase2_priv == NULL) { + data->phase2_method = eap_peer_get_eap_method( + EAP_VENDOR_IETF, method); + if (data->phase2_method) { + sm->init_phase2 = 1; + data->phase2_priv = data->phase2_method->init(sm); + sm->init_phase2 = 0; + } + } + if (data->phase2_priv == NULL || data->phase2_method == NULL) { + wpa_printf(MSG_ERROR, "EAP-TTLS: failed to initialize " + "Phase 2 EAP method %d\n", method); + return -1; + } + + return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len, resp); +} + +#if 0 +static int eap_ttls_phase2_request_eap(struct eap_sm *sm, + struct eap_ttls_data *data, + struct eap_method_ret *ret, + struct eap_hdr *hdr, + struct wpabuf **resp) +{ + size_t len = be_to_host16(hdr->length); + u8 *pos; + struct eap_peer_config *config = eap_get_config(sm); + + if (len <= sizeof(struct eap_hdr)) { + wpa_printf(MSG_ERROR, "EAP-TTLS: too short " + "Phase 2 request (len=%lu)\n", (unsigned long) len); + return -1; + } + pos = (u8 *) (hdr + 1); + wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP Request: type=%d\n", *pos); + switch (*pos) { + case EAP_TYPE_IDENTITY: + *resp = eap_sm_build_identity_resp(sm, hdr->identifier, 1); + break; + default: + if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len, + *pos, resp) < 0) + return -1; + break; + } + + if (*resp == NULL && + (config->pending_req_identity || config->pending_req_password || + config->pending_req_otp)) { + return 0; + } + + if (*resp == NULL) + return -1; + + return eap_ttls_avp_encapsulate(resp, RADIUS_ATTR_EAP_MESSAGE, 1); +} +#endif +#endif + +static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm, + struct eap_ttls_data *data, + struct eap_method_ret *ret, + struct wpabuf **resp) +{ +#ifdef EAP_MSCHAPv2 + struct wpabuf *msg; + u8 *buf, *pos, *challenge, *peer_challenge; + const u8 *identity, *password; + size_t identity_len, password_len; + int pwhash; + + wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAPV2 Request\n"); + + identity = eap_get_config_identity(sm, &identity_len); + password = eap_get_config_password2(sm, &password_len, &pwhash); + if (identity == NULL || password == NULL) + return -1; + + msg = wpabuf_alloc(identity_len + 1000); + if (msg == NULL) { + wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to allocate memory\n"); + return -1; + } + pos = buf = wpabuf_mhead(msg); + + /* User-Name */ + pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, + identity, identity_len); + + /* MS-CHAP-Challenge */ + challenge = eap_ttls_implicit_challenge( + sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1); + if (challenge == NULL) { + wpabuf_free(msg); + wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive " + "implicit challenge\n"); + return -1; + } + + pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE, + RADIUS_VENDOR_ID_MICROSOFT, 1, + challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN); + + /* MS-CHAP2-Response */ + pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_RESPONSE, + RADIUS_VENDOR_ID_MICROSOFT, 1, + EAP_TTLS_MSCHAPV2_RESPONSE_LEN); + data->ident = challenge[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN]; + *pos++ = data->ident; + *pos++ = 0; /* Flags */ + if (os_get_random(pos, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN) < 0) { + os_free(challenge); + wpabuf_free(msg); + wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to get " + "random data for peer challenge\n"); + return -1; + } + peer_challenge = pos; + pos += EAP_TTLS_MSCHAPV2_CHALLENGE_LEN; + os_memset(pos, 0, 8); /* Reserved, must be zero */ + pos += 8; + if (mschapv2_derive_response(identity, identity_len, password, + password_len, pwhash, challenge, + peer_challenge, pos, data->auth_response, + data->master_key)) { + os_free(challenge); + wpabuf_free(msg); + wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive " + "response\n"); + return -1; + } + data->auth_response_valid = 1; + + pos += 24; + os_free(challenge); + AVP_PAD(buf, pos); + + wpabuf_put(msg, pos - buf); + *resp = msg; + + if (sm->workaround) { + /* At least FreeRADIUS seems to be terminating + * EAP-TTLS/MSHCAPV2 without the expected MS-CHAP-v2 Success + * packet. */ + wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: EAP workaround - " + "allow success without tunneled response\n"); + ret->methodState = METHOD_MAY_CONT; + ret->decision = DECISION_COND_SUCC; + } + + return 0; +#else /* EAP_MSCHAPv2 */ + printf("[Debug] Set EEEEE \n"); + wpa_printf(MSG_ERROR, "EAP-TTLS: MSCHAPv2 not included in the build\n"); + return -1; +#endif /* EAP_MSCHAPv2 */ +} + +#if 0 +//only support MSCHAPv2 +static int eap_ttls_phase2_request_mschap(struct eap_sm *sm, + struct eap_ttls_data *data, + struct eap_method_ret *ret, + struct wpabuf **resp) +{ + struct wpabuf *msg; + u8 *buf, *pos, *challenge; + const u8 *identity, *password; + size_t identity_len, password_len; + int pwhash; + + wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAP Request\n"); + + identity = eap_get_config_identity(sm, &identity_len); + password = eap_get_config_password2(sm, &password_len, &pwhash); + if (identity == NULL || password == NULL) + return -1; + + msg = wpabuf_alloc(identity_len + 1000); + if (msg == NULL) { + wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to allocate memory\n"); + return -1; + } + pos = buf = wpabuf_mhead(msg); + + // User-Name + pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, + identity, identity_len); + + // MS-CHAP-Challenge + challenge = eap_ttls_implicit_challenge( + sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1); + if (challenge == NULL) { + wpabuf_free(msg); + wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive " + "implicit challenge\n"); + return -1; + } + + pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE, + RADIUS_VENDOR_ID_MICROSOFT, 1, + challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN); + + // MS-CHAP-Response + pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_RESPONSE, + RADIUS_VENDOR_ID_MICROSOFT, 1, + EAP_TTLS_MSCHAP_RESPONSE_LEN); + data->ident = challenge[EAP_TTLS_MSCHAP_CHALLENGE_LEN]; + *pos++ = data->ident; + *pos++ = 1; // Flags: Use NT style passwords + os_memset(pos, 0, 24); // LM-Response + pos += 24; + if (pwhash) { + challenge_response(challenge, password, pos); // NT-Response + } else { + nt_challenge_response(challenge, password, password_len, + pos); // NT-Response + } + pos += 24; + os_free(challenge); + AVP_PAD(buf, pos); + + wpabuf_put(msg, pos - buf); + *resp = msg; + + // EAP-TTLS/MSCHAP does not provide tunneled success + // notification, so assume that Phase2 succeeds. + ret->methodState = METHOD_DONE; + ret->decision = DECISION_COND_SUCC; + + return 0; +} + + +static int eap_ttls_phase2_request_pap(struct eap_sm *sm, + struct eap_ttls_data *data, + struct eap_method_ret *ret, + struct wpabuf **resp) +{ + struct wpabuf *msg; + u8 *buf, *pos; + size_t pad; + const u8 *identity, *password; + size_t identity_len, password_len; + + wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 PAP Request\n"); + + identity = eap_get_config_identity(sm, &identity_len); + password = eap_get_config_password(sm, &password_len); + if (identity == NULL || password == NULL) + return -1; + + msg = wpabuf_alloc(identity_len + password_len + 100); + if (msg == NULL) { + wpa_printf(MSG_ERROR, "EAP-TTLS/PAP: Failed to allocate memory\n"); + return -1; + } + pos = buf = wpabuf_mhead(msg); + + // User-Name + pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, + identity, identity_len); + + // User-Password; in RADIUS, this is encrypted, but EAP-TTLS encrypts + // the data, so no separate encryption is used in the AVP itself. + // However, the password is padded to obfuscate its length. + pad = password_len == 0 ? 16 : (16 - (password_len & 15)) & 15; + pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_USER_PASSWORD, 0, 1, + password_len + pad); + os_memcpy(pos, password, password_len); + pos += password_len; + os_memset(pos, 0, pad); + pos += pad; + AVP_PAD(buf, pos); + + wpabuf_put(msg, pos - buf); + *resp = msg; + + // EAP-TTLS/PAP does not provide tunneled success notification, + // so assume that Phase2 succeeds. + ret->methodState = METHOD_DONE; + ret->decision = DECISION_COND_SUCC; + + return 0; +} + + +static int eap_ttls_phase2_request_chap(struct eap_sm *sm, + struct eap_ttls_data *data, + struct eap_method_ret *ret, + struct wpabuf **resp) +{ + struct wpabuf *msg; + u8 *buf, *pos, *challenge; + const u8 *identity, *password; + size_t identity_len, password_len; + + wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 CHAP Request\n"); + + identity = eap_get_config_identity(sm, &identity_len); + password = eap_get_config_password(sm, &password_len); + if (identity == NULL || password == NULL) + return -1; + + msg = wpabuf_alloc(identity_len + 1000); + if (msg == NULL) { + wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to allocate memory\n"); + return -1; + } + pos = buf = wpabuf_mhead(msg); + + // User-Name + pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1, + identity, identity_len); + + // CHAP-Challenge + challenge = eap_ttls_implicit_challenge( + sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1); + if (challenge == NULL) { + wpabuf_free(msg); + wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive " + "implicit challenge\n"); + return -1; + } + + pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_CHAP_CHALLENGE, 0, 1, + challenge, EAP_TTLS_CHAP_CHALLENGE_LEN); + + // CHAP-Password + pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_CHAP_PASSWORD, 0, 1, + 1 + EAP_TTLS_CHAP_PASSWORD_LEN); + data->ident = challenge[EAP_TTLS_CHAP_CHALLENGE_LEN]; + *pos++ = data->ident; + + // MD5(Ident + Password + Challenge) + chap_md5(data->ident, password, password_len, challenge, + EAP_TTLS_CHAP_CHALLENGE_LEN, pos); + + pos += EAP_TTLS_CHAP_PASSWORD_LEN; + os_free(challenge); + AVP_PAD(buf, pos); + + wpabuf_put(msg, pos - buf); + *resp = msg; + + // EAP-TTLS/CHAP does not provide tunneled success + // notification, so assume that Phase2 succeeds. + ret->methodState = METHOD_DONE; + ret->decision = DECISION_COND_SUCC; + + return 0; +} +#endif + +static int eap_ttls_phase2_request(struct eap_sm *sm, + struct eap_ttls_data *data, + struct eap_method_ret *ret, + struct eap_hdr *hdr, + struct wpabuf **resp) +{ + int res = 0; + size_t len; + enum phase2_types phase2_type = data->phase2_type; + +#ifdef EAP_TNC + if (data->tnc_started) { + printf("[debug] set phase2_type \n"); + wpa_printf(MSG_DEBUG, "EAP-TTLS: Processing TNC\n"); + phase2_type = EAP_TTLS_PHASE2_EAP; + } +#endif /* EAP_TNC */ + + if (phase2_type == EAP_TTLS_PHASE2_MSCHAPV2) { + if (eap_get_config_identity(sm, &len) == NULL) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Identity not configured\n"); + printf("[Debug] Return because no identity EAP_TTLS_PHASE2_MSCHAPV2\n"); + return 0; + } + if (eap_get_config_password(sm, &len) == NULL) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Password not configured\n"); + printf("[Debug] Return because no password EAP_TTLS_PHASE2_MSCHAPV2\n"); + return 0; + } + + res = eap_ttls_phase2_request_mschapv2(sm, data, ret, resp); + } else { + wpa_printf(MSG_ERROR, "EAP-TTLS: Phase 2 - Unknown type %d\n", phase2_type); + res = -1; + } + +/* if (phase2_type == EAP_TTLS_PHASE2_MSCHAPV2 || + phase2_type == EAP_TTLS_PHASE2_MSCHAP || + phase2_type == EAP_TTLS_PHASE2_PAP || + phase2_type == EAP_TTLS_PHASE2_CHAP) { + if (eap_get_config_identity(sm, &len) == NULL) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Identity not configured\n"); + //eap_sm_request_identity(sm); + if (eap_get_config_password(sm, &len) == NULL); + // eap_sm_request_password(sm); + printf("[Debug] Return because no identity EAP_TTLS_PHASE2_MSCHAPV2 EAP_TTLS_PHASE2_MSCHAP\n"); + return 0; + } + + if (eap_get_config_password(sm, &len) == NULL) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Password not configured\n"); + printf("[Debug] Return because no password EAP_TTLS_PHASE2_MSCHAPV2 EAP_TTLS_PHASE2_MSCHAP\n"); + //eap_sm_request_password(sm); + return 0; + } + } + + switch (phase2_type) { + case EAP_TTLS_PHASE2_EAP: + printf("[Debug] EAP_TTLS_PHASE2_EAP typed \n"); + res = eap_ttls_phase2_request_eap(sm, data, ret, hdr, resp); + break; + case EAP_TTLS_PHASE2_MSCHAPV2: + printf("[Debug] EAP_TTLS_PHASE2_MSCHAPV2 typed \n"); + res = eap_ttls_phase2_request_mschapv2(sm, data, ret, resp); + break; + case EAP_TTLS_PHASE2_MSCHAP: + printf("[Debug] EAP_TTLS_PHASE2_MSCHAP typed \n"); + res = eap_ttls_phase2_request_mschap(sm, data, ret, resp); + break; + case EAP_TTLS_PHASE2_PAP: + printf("[Debug] EAP_TTLS_PHASE2_PAP typed \n"); + res = eap_ttls_phase2_request_pap(sm, data, ret, resp); + break; + case EAP_TTLS_PHASE2_CHAP: + printf("[Debug] EAP_TTLS_PHASE2_CHAP typed \n"); + res = eap_ttls_phase2_request_chap(sm, data, ret, resp); + break; + default: + printf("[Debug] Default typed \n"); + wpa_printf(MSG_ERROR, "EAP-TTLS: Phase 2 - Unknown\n"); + res = -1; + break; + }*/ + + if (res < 0) { + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + } + + return res; +} + + +struct ttls_parse_avp { + u8 *mschapv2; + u8 *eapdata; + size_t eap_len; + int mschapv2_error; +}; + + +static int eap_ttls_parse_attr_eap(const u8 *dpos, size_t dlen, + struct ttls_parse_avp *parse) +{ + wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message\n"); + if (parse->eapdata == NULL) { + parse->eapdata = os_malloc(dlen); + if (parse->eapdata == NULL) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to allocate " + "memory for Phase 2 EAP data\n"); + return -1; + } + os_memcpy(parse->eapdata, dpos, dlen); + parse->eap_len = dlen; + } else { + u8 *neweap = (u8 *)os_realloc(parse->eapdata, parse->eap_len + dlen); + if (neweap == NULL) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to allocate " + "memory for Phase 2 EAP data\n"); + return -1; + } + os_memcpy(neweap + parse->eap_len, dpos, dlen); + parse->eapdata = neweap; + parse->eap_len += dlen; + } + + return 0; +} + + +static int eap_ttls_parse_avp(u8 *pos, size_t left, + struct ttls_parse_avp *parse) +{ + struct ttls_avp *avp; + u32 avp_code, avp_length, vendor_id = 0; + u8 avp_flags, *dpos; + size_t dlen; + + avp = (struct ttls_avp *) pos; + avp_code = be_to_host32(avp->avp_code); + avp_length = be_to_host32(avp->avp_length); + avp_flags = (avp_length >> 24) & 0xff; + avp_length &= 0xffffff; + wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP: code=%d flags=0x%02x " + "length=%d\n", (int) avp_code, avp_flags, + (int) avp_length); + + if (avp_length > left) { + wpa_printf(MSG_ERROR, "EAP-TTLS: AVP overflow " + "(len=%d, left=%lu) - dropped\n", + (int) avp_length, (unsigned long) left); + return -1; + } + + if (avp_length < sizeof(*avp)) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Invalid AVP length %d\n", + avp_length); + return -1; + } + + dpos = (u8 *) (avp + 1); + dlen = avp_length - sizeof(*avp); + if (avp_flags & AVP_FLAGS_VENDOR) { + if (dlen < 4) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Vendor AVP underflow\n"); + return -1; + } + vendor_id = WPA_GET_BE32(dpos); + wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP vendor_id %d\n", + (int) vendor_id); + dpos += 4; + dlen -= 4; + } + + if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) { + if (eap_ttls_parse_attr_eap(dpos, dlen, parse) < 0) + return -1; + } else if (vendor_id == 0 && avp_code == RADIUS_ATTR_REPLY_MESSAGE) { + /* This is an optional message that can be displayed to + * the user. */ + } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && + avp_code == RADIUS_ATTR_MS_CHAP2_SUCCESS) { + if (dlen != 43) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Unexpected " + "MS-CHAP2-Success length " + "(len=%lu, expected 43)\n", + (unsigned long) dlen); + return -1; + } + parse->mschapv2 = dpos; + } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT && + avp_code == RADIUS_ATTR_MS_CHAP_ERROR) { + parse->mschapv2_error = 1; + } else if (avp_flags & AVP_FLAGS_MANDATORY) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Unsupported mandatory AVP " + "code %d vendor_id %d - dropped\n", + (int) avp_code, (int) vendor_id); + return -1; + } else { + wpa_printf(MSG_INFO, "EAP-TTLS: Ignoring unsupported AVP " + "code %d vendor_id %d\n", + (int) avp_code, (int) vendor_id); + } + + return avp_length; +} + + +static int eap_ttls_parse_avps(struct wpabuf *in_decrypted, + struct ttls_parse_avp *parse) +{ + u8 *pos; + size_t left, pad; + int avp_length; + + pos = wpabuf_mhead(in_decrypted); + left = wpabuf_len(in_decrypted); + if (left < sizeof(struct ttls_avp)) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Too short Phase 2 AVP frame" + " len=%lu expected %lu or more - dropped\n", + (unsigned long) left, + (unsigned long) sizeof(struct ttls_avp)); + return -1; + } + + /* Parse AVPs */ + os_memset(parse, 0, sizeof(*parse)); + + while (left > 0) { + avp_length = eap_ttls_parse_avp(pos, left, parse); + if (avp_length < 0) + return -1; + + pad = (4 - (avp_length & 3)) & 3; + pos += avp_length + pad; + if (left < avp_length + pad) + left = 0; + else + left -= avp_length + pad; + } + + return 0; +} + + +static u8 * eap_ttls_fake_identity_request(void) +{ + struct eap_hdr *hdr; + u8 *buf; + + wpa_printf(MSG_DEBUG, "EAP-TTLS: empty data in beginning of " + "Phase 2 - use fake EAP-Request Identity\n"); + buf = os_malloc(sizeof(*hdr) + 1); + if (buf == NULL) { + wpa_printf(MSG_ERROR, "EAP-TTLS: failed to allocate " + "memory for fake EAP-Identity Request\n"); + return NULL; + } + + hdr = (struct eap_hdr *) buf; + hdr->code = EAP_CODE_REQUEST; + hdr->identifier = 0; + hdr->length = host_to_be16(sizeof(*hdr) + 1); + buf[sizeof(*hdr)] = EAP_TYPE_IDENTITY; + + return buf; +} + + +static int eap_ttls_encrypt_response(struct eap_sm *sm, + struct eap_ttls_data *data, + struct wpabuf *resp, u8 identifier, + struct wpabuf **out_data) +{ + if (resp == NULL) + return 0; + + if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TTLS, + data->ttls_version, identifier, + resp, out_data)) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Failed to encrypt a Phase 2 frame\n"); + return -1; + } + wpabuf_free(resp); + + return 0; +} + +#if 0 +static int eap_ttls_process_phase2_eap(struct eap_sm *sm, + struct eap_ttls_data *data, + struct eap_method_ret *ret, + struct ttls_parse_avp *parse, + struct wpabuf **resp) +{ + struct eap_hdr *hdr; + size_t len; + + if (parse->eapdata == NULL) { + wpa_printf(MSG_ERROR, "EAP-TTLS: No EAP Message in the " + "packet - dropped\n"); + return -1; + } + + hdr = (struct eap_hdr *) parse->eapdata; + + if (parse->eap_len < sizeof(*hdr)) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Too short Phase 2 EAP " + "frame (len=%lu, expected %lu or more) - dropped\n", + (unsigned long) parse->eap_len, + (unsigned long) sizeof(*hdr)); + return -1; + } + len = be_to_host16(hdr->length); + if (len > parse->eap_len) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Length mismatch in Phase 2 " + "EAP frame (EAP hdr len=%lu, EAP data len in " + "AVP=%lu)\n", + (unsigned long) len, + (unsigned long) parse->eap_len); + return -1; + } + wpa_printf(MSG_DEBUG, "EAP-TTLS: received Phase 2: code=%d " + "identifier=%d length=%lu\n", + hdr->code, hdr->identifier, (unsigned long) len); + switch (hdr->code) { + case EAP_CODE_REQUEST: + if (eap_ttls_phase2_request(sm, data, ret, hdr, resp)) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Phase2 Request " + "processing failed\n"); + return -1; + } + break; + default: + wpa_printf(MSG_ERROR, "EAP-TTLS: Unexpected code=%d in " + "Phase 2 EAP header\n", hdr->code); + return -1; + } + + return 0; +} +#endif + +static int eap_ttls_process_phase2_mschapv2(struct eap_sm *sm, + struct eap_ttls_data *data, + struct eap_method_ret *ret, + struct ttls_parse_avp *parse) +{ +#ifdef EAP_MSCHAPv2 + if (parse->mschapv2_error) { + wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Received " + "MS-CHAP-Error - failed\n"); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + /* Reply with empty data to ACK error */ + return 1; + } + + if (parse->mschapv2 == NULL) { +#ifdef EAP_TNC + if (data->phase2_success && parse->eapdata) { + /* + * Allow EAP-TNC to be started after successfully + * completed MSCHAPV2. + */ + return 1; + } +#endif /* EAP_TNC */ + wpa_printf(MSG_ERROR, "EAP-TTLS: no MS-CHAP2-Success AVP " + "received for Phase2 MSCHAPV2\n"); + return -1; + } + if (parse->mschapv2[0] != data->ident) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Ident mismatch for Phase 2 " + "MSCHAPV2 (received Ident 0x%02x, expected 0x%02x)\n", + parse->mschapv2[0], data->ident); + return -1; + } + if (!data->auth_response_valid || + mschapv2_verify_auth_response(data->auth_response, + parse->mschapv2 + 1, 42)) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Invalid authenticator " + "response in Phase 2 MSCHAPV2 success request\n"); + return -1; + } + + wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAPV2 " + "authentication succeeded\n"); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_UNCOND_SUCC; + data->phase2_success = 1; + + /* + * Reply with empty data; authentication server will reply + * with EAP-Success after this. + */ + return 1; +#else /* EAP_MSCHAPv2 */ + wpa_printf(MSG_ERROR, "EAP-TTLS: MSCHAPv2 not included in the build\n"); + return -1; +#endif /* EAP_MSCHAPv2 */ +} + + +#ifdef EAP_TNC +static int eap_ttls_process_tnc_start(struct eap_sm *sm, + struct eap_ttls_data *data, + struct eap_method_ret *ret, + struct ttls_parse_avp *parse, + struct wpabuf **resp) +{ + /* TNC uses inner EAP method after non-EAP TTLS phase 2. */ + if (parse->eapdata == NULL) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Phase 2 received " + "unexpected tunneled data (no EAP)\n"); + return -1; + } + + if (!data->ready_for_tnc) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Phase 2 received " + "EAP after non-EAP, but not ready for TNC\n"); + return -1; + } + + wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed " + "non-EAP method\n"); + data->tnc_started = 1; + + if (eap_ttls_process_phase2_eap(sm, data, ret, parse, resp) < 0) + return -1; + + return 0; +} +#endif /* EAP_TNC */ + + +static int eap_ttls_process_decrypted(struct eap_sm *sm, + struct eap_ttls_data *data, + struct eap_method_ret *ret, + u8 identifier, + struct ttls_parse_avp *parse, + struct wpabuf *in_decrypted, + struct wpabuf **out_data) +{ + struct wpabuf *resp = NULL; + //struct eap_peer_config *config = eap_get_config(sm); + int res; + enum phase2_types phase2_type = data->phase2_type; + +#ifdef EAP_TNC + if (data->tnc_started) + phase2_type = EAP_TTLS_PHASE2_EAP; +#endif /* EAP_TNC */ + + switch (phase2_type) { + case EAP_TTLS_PHASE2_MSCHAPV2: + res = eap_ttls_process_phase2_mschapv2(sm, data, ret, parse); +#ifdef EAP_TNC + if (res == 1 && parse->eapdata && data->phase2_success) { + /* + * TNC may be required as the next + * authentication method within the tunnel. + */ + ret->methodState = METHOD_MAY_CONT; + data->ready_for_tnc = 1; + if (eap_ttls_process_tnc_start(sm, data, ret, parse, + &resp) == 0) + break; + } +#endif /* EAP_TNC */ + return res; +/* case EAP_TTLS_PHASE2_EAP: + if (eap_ttls_process_phase2_eap(sm, data, ret, parse, &resp) < + 0) + return -1; + break; + case EAP_TTLS_PHASE2_MSCHAP: + case EAP_TTLS_PHASE2_PAP: + case EAP_TTLS_PHASE2_CHAP: +#ifdef EAP_TNC + if (eap_ttls_process_tnc_start(sm, data, ret, parse, &resp) < + 0) + return -1; + break; +#else // EAP_TNC + // EAP-TTLS/{MSCHAP,PAP,CHAP} should not send any TLS tunneled + // requests to the supplicant + wpa_printf(MSG_ERROR, "EAP-TTLS: Phase 2 received unexpected " + "tunneled data\n"); + return -1; +#endif // EAP_TNC +*/ + default: + return -1; + } + + if (resp) { + if (eap_ttls_encrypt_response(sm, data, resp, identifier, + out_data) < 0) + return -1; + } else { + wpabuf_free(data->pending_phase2_req); + data->pending_phase2_req = wpabuf_dup(in_decrypted); + }/* else if (config->pending_req_identity || + config->pending_req_password || + config->pending_req_otp || + config->pending_req_new_password) { + wpabuf_free(data->pending_phase2_req); + data->pending_phase2_req = wpabuf_dup(in_decrypted); + }*/ + + return 0; +} + + +static int eap_ttls_implicit_identity_request(struct eap_sm *sm, + struct eap_ttls_data *data, + struct eap_method_ret *ret, + u8 identifier, + struct wpabuf **out_data) +{ + int retval = 0; + struct eap_hdr *hdr; + struct wpabuf *resp; + + hdr = (struct eap_hdr *) eap_ttls_fake_identity_request(); + if (hdr == NULL) { + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + return -1; + } + + resp = NULL; + if (eap_ttls_phase2_request(sm, data, ret, hdr, &resp)) { + wpa_printf(MSG_ERROR, "EAP-TTLS: Phase2 Request " + "processing failed\n"); + retval = -1; + } else { + //struct eap_peer_config *config = eap_get_config(sm); + if (resp == NULL) {/* && + (config->pending_req_identity || + config->pending_req_password || + config->pending_req_otp || + config->pending_req_new_password)) {*/ + /* + * Use empty buffer to force implicit request + * processing when EAP request is re-processed after + * user input. + */ + wpabuf_free(data->pending_phase2_req); + data->pending_phase2_req = wpabuf_alloc(0); + } + + retval = eap_ttls_encrypt_response(sm, data, resp, identifier, + out_data); + } + + os_free(hdr); + + if (retval < 0) { + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + } + + return retval; +} + + +static int eap_ttls_phase2_start(struct eap_sm *sm, struct eap_ttls_data *data, + struct eap_method_ret *ret, u8 identifier, + struct wpabuf **out_data) +{ + data->phase2_start = 0; + + /* + * EAP-TTLS does not use Phase2 on fast re-auth; this must be done only + * if TLS part was indeed resuming a previous session. Most + * Authentication Servers terminate EAP-TTLS before reaching this + * point, but some do not. Make wpa_supplicant stop phase 2 here, if + * needed. + */ + if (data->reauth && + tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) { + wpa_printf(MSG_DEBUG, "EAP-TTLS: Session resumption - " + "skip phase 2\n"); + *out_data = eap_peer_tls_build_ack(identifier, EAP_TYPE_TTLS, + data->ttls_version); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_UNCOND_SUCC; + data->phase2_success = 1; + return 0; + } + + return eap_ttls_implicit_identity_request(sm, data, ret, identifier, + out_data); +} + + +static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data, + struct eap_method_ret *ret, u8 identifier, + const struct wpabuf *in_data, + struct wpabuf **out_data) +{ + struct wpabuf *in_decrypted = NULL; + int retval = 0; + struct ttls_parse_avp parse; + + os_memset(&parse, 0, sizeof(parse)); + + wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for" + " Phase 2\n", + in_data ? (unsigned long) wpabuf_len(in_data) : 0); + + if (data->pending_phase2_req) { + wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 request - " + "skip decryption and use old data\n"); + /* Clear TLS reassembly state. */ + eap_peer_tls_reset_input(&data->ssl); + + in_decrypted = data->pending_phase2_req; + data->pending_phase2_req = NULL; + if (wpabuf_len(in_decrypted) == 0) { + wpabuf_free(in_decrypted); + return eap_ttls_implicit_identity_request( + sm, data, ret, identifier, out_data); + } + goto continue_req; + } + + if ((in_data == NULL || wpabuf_len(in_data) == 0) && + data->phase2_start) { + return eap_ttls_phase2_start(sm, data, ret, identifier, + out_data); + } + + if (in_data == NULL || wpabuf_len(in_data) == 0) { + /* Received TLS ACK - requesting more fragments */ + return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TTLS, + data->ttls_version, + identifier, NULL, out_data); + } + + retval = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted); + if (retval) + goto done; + +continue_req: + data->phase2_start = 0; + + if (eap_ttls_parse_avps(in_decrypted, &parse) < 0) { + retval = -1; + goto done; + } + + retval = eap_ttls_process_decrypted(sm, data, ret, identifier, + &parse, in_decrypted, out_data); + +done: + wpabuf_free(in_decrypted); + os_free(parse.eapdata); + + if (retval < 0) { + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + } + + return retval; +} + + +static int eap_ttls_process_handshake(struct eap_sm *sm, + struct eap_ttls_data *data, + struct eap_method_ret *ret, + u8 identifier, + const u8 *in_data, size_t in_len, + struct wpabuf **out_data) +{ + int res; + + res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS, + data->ttls_version, identifier, + in_data, in_len, out_data); + + if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) { + wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS done, proceed to " + "Phase 2\n"); + if (data->resuming) { + wpa_printf(MSG_DEBUG, "EAP-TTLS: fast reauth - may " + "skip Phase 2\n"); + ret->decision = DECISION_COND_SUCC; + ret->methodState = METHOD_MAY_CONT; + } + data->phase2_start = 1; + eap_ttls_v0_derive_key(sm, data); + + if (*out_data == NULL || wpabuf_len(*out_data) == 0) { + if (eap_ttls_decrypt(sm, data, ret, identifier, + NULL, out_data)) { + wpa_printf(MSG_ERROR, "EAP-TTLS: " + "failed to process early " + "start for Phase 2\n"); + } + res = 0; + } + data->resuming = 0; + } + + if (res == 2) { + struct wpabuf msg; + /* + * Application data included in the handshake message. + */ + wpabuf_free(data->pending_phase2_req); + data->pending_phase2_req = *out_data; + *out_data = NULL; + wpabuf_set(&msg, in_data, in_len); + res = eap_ttls_decrypt(sm, data, ret, identifier, &msg, + out_data); + } + + return res; +} + + +static void eap_ttls_check_auth_status(struct eap_sm *sm, + struct eap_ttls_data *data, + struct eap_method_ret *ret) +{ + if (ret->methodState == METHOD_DONE) { + ret->allowNotifications = FALSE; + if (ret->decision == DECISION_UNCOND_SUCC || + ret->decision == DECISION_COND_SUCC) { + wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication " + "completed successfully"); + data->phase2_success = 1; +#ifdef EAP_TNC + if (!data->ready_for_tnc && !data->tnc_started) { + /* + * TNC may be required as the next + * authentication method within the tunnel. + */ + ret->methodState = METHOD_MAY_CONT; + data->ready_for_tnc = 1; + } +#endif /* EAP_TNC */ + } + } else if (ret->methodState == METHOD_MAY_CONT && + (ret->decision == DECISION_UNCOND_SUCC || + ret->decision == DECISION_COND_SUCC)) { + wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication " + "completed successfully (MAY_CONT)\n"); + data->phase2_success = 1; + } +} + + +static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv, + struct eap_method_ret *ret, + const struct wpabuf *reqData) +{ + size_t left; + int res; + u8 flags, id; + struct wpabuf *resp; + const u8 *pos; + struct eap_ttls_data *data = priv; + + pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TTLS, ret, + reqData, &left, &flags); + if (pos == NULL) + return NULL; + id = eap_get_id(reqData); + + if (flags & EAP_TLS_FLAGS_START) { + wpa_printf(MSG_DEBUG, "EAP-TTLS: Start (server ver=%d, own " + "ver=%d)\n", flags & EAP_TLS_VERSION_MASK, + data->ttls_version); + + /* RFC 5281, Ch. 9.2: + * "This packet MAY contain additional information in the form + * of AVPs, which may provide useful hints to the client" + * For now, ignore any potential extra data. + */ + left = 0; + } + + resp = NULL; + if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) && + !data->resuming) { + struct wpabuf msg; + wpabuf_set(&msg, pos, left); + res = eap_ttls_decrypt(sm, data, ret, id, &msg, &resp); + } else { + res = eap_ttls_process_handshake(sm, data, ret, id, + pos, left, &resp); + } + + eap_ttls_check_auth_status(sm, data, ret); + /* FIX: what about res == -1? Could just move all error processing into + * the other functions and get rid of this res==1 case here. */ + if (res == 1) { + wpabuf_free(resp); + return eap_peer_tls_build_ack(id, EAP_TYPE_TTLS, + data->ttls_version); + } + + return resp; +} + + +static bool eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv) +{ + struct eap_ttls_data *data = priv; + return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && + data->phase2_success; +} + + +static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv) +{ + struct eap_ttls_data *data = priv; + wpabuf_free(data->pending_phase2_req); + data->pending_phase2_req = NULL; +#ifdef EAP_TNC + data->ready_for_tnc = 0; + data->tnc_started = 0; +#endif /* EAP_TNC */ +} + + +static void * eap_ttls_init_for_reauth(struct eap_sm *sm, void *priv) +{ + struct eap_ttls_data *data = priv; + os_free(data->key_data); + data->key_data = NULL; + os_free(data->session_id); + data->session_id = NULL; + if (eap_peer_tls_reauth_init(sm, &data->ssl)) { + os_free(data); + return NULL; + } + if (data->phase2_priv && data->phase2_method && + data->phase2_method->init_for_reauth) + data->phase2_method->init_for_reauth(sm, data->phase2_priv); + data->phase2_start = 0; + data->phase2_success = 0; + data->resuming = 1; + data->reauth = 1; + return priv; +} + + +static int eap_ttls_get_status(struct eap_sm *sm, void *priv, char *buf, + size_t buflen, int verbose) +{ + struct eap_ttls_data *data = priv; + int len, ret; + + len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); + ret = snprintf(buf + len, buflen - len, + "EAP-TTLSv%d Phase2 method=", + data->ttls_version); + if (ret < 0 || (size_t) ret >= buflen - len) + return len; + len += ret; + switch (data->phase2_type) { + /*case EAP_TTLS_PHASE2_EAP: + ret = os_snprintf(buf + len, buflen - len, "EAP-%s\n", + data->phase2_method ? + data->phase2_method->name : "?"); + break;*/ + case EAP_TTLS_PHASE2_MSCHAPV2: + ret = snprintf(buf + len, buflen - len, "MSCHAPV2\n"); + break; + /*case EAP_TTLS_PHASE2_MSCHAP: + ret = os_snprintf(buf + len, buflen - len, "MSCHAP\n"); + break; + case EAP_TTLS_PHASE2_PAP: + ret = os_snprintf(buf + len, buflen - len, "PAP\n"); + break; + case EAP_TTLS_PHASE2_CHAP: + ret = os_snprintf(buf + len, buflen - len, "CHAP\n"); + break;*/ + default: + ret = 0; + break; + } + if (ret < 0 || (size_t) ret >= buflen - len) + return len; + len += ret; + + return len; +} + + +static bool eap_ttls_isKeyAvailable(struct eap_sm *sm, void *priv) +{ + struct eap_ttls_data *data = priv; + return data->key_data != NULL && data->phase2_success; +} + + +static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len) +{ + struct eap_ttls_data *data = priv; + u8 *key; + + if (data->key_data == NULL || !data->phase2_success) + return NULL; + + key = os_malloc(EAP_TLS_KEY_LEN); + if (key == NULL) + return NULL; + + *len = EAP_TLS_KEY_LEN; + os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); + + return key; +} + + +static u8 * eap_ttls_get_session_id(struct eap_sm *sm, void *priv, size_t *len) +{ + struct eap_ttls_data *data = priv; + u8 *id; + + if (data->session_id == NULL || !data->phase2_success) + return NULL; + + id = os_malloc(data->id_len); + if (id == NULL) + return NULL; + + *len = data->id_len; + os_memcpy(id, data->session_id, data->id_len); + + return id; +} + +int eap_peer_ttls_register(void) +{ + struct eap_method *eap; + int ret; + + eap = eap_peer_method_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS, + "TTLS"); + if (eap == NULL) + return -1; + + eap->init = eap_ttls_init; + eap->deinit = eap_ttls_deinit; + eap->process = eap_ttls_process; + eap->isKeyAvailable = eap_ttls_isKeyAvailable; + eap->getKey = eap_ttls_getKey; + eap->getSessionId = eap_ttls_get_session_id; + eap->get_status = eap_ttls_get_status; + eap->has_reauth_data = eap_ttls_has_reauth_data; + eap->deinit_for_reauth = eap_ttls_deinit_for_reauth; + eap->init_for_reauth = eap_ttls_init_for_reauth; + + ret = eap_peer_method_register(eap); + if (ret) + eap_peer_method_free(eap); + return ret; +} + +#endif /* EAP_TTLS */ diff --git a/components/wpa_supplicant/src/wpa2/eap_peer/mschapv2.c b/components/wpa_supplicant/src/wpa2/eap_peer/mschapv2.c new file mode 100644 index 0000000000..33351989b5 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/eap_peer/mschapv2.c @@ -0,0 +1,97 @@ +/* + * MSCHAPV2 + */ + +#ifdef EAP_MSCHAPv2 + +#include "wpa/includes.h" +#include "wpa/common.h" +#include "crypto/ms_funcs.h" +#include "wpa2/eap_peer/mschapv2.h" + +const u8 * mschapv2_remove_domain(const u8 *username, size_t *len) +{ + size_t i; + + /* + * MSCHAPV2 does not include optional domain name in the + * challenge-response calculation, so remove domain prefix + * (if present) + */ + for (i = 0; i < *len; i++) { + if (username[i] == '\\') { + *len -= i + 1; + return username + i + 1; + } + } + + return username; +} + +int mschapv2_derive_response(const u8 *identity, size_t identity_len, + const u8 *password, size_t password_len, + int pwhash, + const u8 *auth_challenge, + const u8 *peer_challenge, + u8 *nt_response, u8 *auth_response, + u8 *master_key) +{ + const u8 *username; + size_t username_len; + u8 password_hash[16], password_hash_hash[16]; + + username_len = identity_len; + username = mschapv2_remove_domain(identity, &username_len); + + if (pwhash) { + if (generate_nt_response_pwhash(auth_challenge, peer_challenge, + username, username_len, + password, nt_response) || + generate_authenticator_response_pwhash( + password, peer_challenge, auth_challenge, + username, username_len, nt_response, + auth_response)) + return -1; + } else { + if (generate_nt_response(auth_challenge, peer_challenge, + username, username_len, + password, password_len, + nt_response) || + generate_authenticator_response(password, password_len, + peer_challenge, + auth_challenge, + username, username_len, + nt_response, + auth_response)) + return -1; + } + + if (pwhash) { + if (hash_nt_password_hash(password, password_hash_hash)) + return -1; + } else { + if (nt_password_hash(password, password_len, password_hash) || + hash_nt_password_hash(password_hash, password_hash_hash)) + return -1; + } + if (get_master_key(password_hash_hash, nt_response, master_key)) + return -1; + + return 0; +} + +int mschapv2_verify_auth_response(const u8 *auth_response, + const u8 *buf, size_t buf_len) +{ + u8 recv_response[MSCHAPV2_AUTH_RESPONSE_LEN]; + if (buf_len < 2 + 2 * MSCHAPV2_AUTH_RESPONSE_LEN || + buf[0] != 'S' || buf[1] != '=' || + hexstr2bin((char *)(buf + 2), recv_response, + MSCHAPV2_AUTH_RESPONSE_LEN) || + os_memcmp(auth_response, recv_response, + MSCHAPV2_AUTH_RESPONSE_LEN) != 0) + return -1; + return 0; +} + +#endif /* EAP_MSCHAPv2 */ diff --git a/components/wpa_supplicant/src/wpa2/tls/asn1.c b/components/wpa_supplicant/src/wpa2/tls/asn1.c new file mode 100644 index 0000000000..ced8018464 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/tls/asn1.c @@ -0,0 +1,207 @@ +/* + * ASN.1 DER parsing + * Copyright (c) 2006, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "wpa2/tls/asn1.h" + +int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr) +{ + const u8 *pos, *end; + u8 tmp; + + os_memset(hdr, 0, sizeof(*hdr)); + pos = buf; + end = buf + len; + + hdr->identifier = *pos++; + hdr->class = hdr->identifier >> 6; + hdr->constructed = !!(hdr->identifier & (1 << 5)); + + if ((hdr->identifier & 0x1f) == 0x1f) { + hdr->tag = 0; + do { + if (pos >= end) { + wpa_printf(MSG_DEBUG, "ASN.1: Identifier " + "underflow"); + return -1; + } + tmp = *pos++; + wpa_printf(MSG_DEBUG, "ASN.1: Extended tag data: " + "0x%02x", tmp); + hdr->tag = (hdr->tag << 7) | (tmp & 0x7f); + } while (tmp & 0x80); + } else + hdr->tag = hdr->identifier & 0x1f; + + tmp = *pos++; + if (tmp & 0x80) { + if (tmp == 0xff) { + wpa_printf(MSG_DEBUG, "ASN.1: Reserved length " + "value 0xff used"); + return -1; + } + tmp &= 0x7f; /* number of subsequent octets */ + hdr->length = 0; + if (tmp > 4) { + wpa_printf(MSG_DEBUG, "ASN.1: Too long length field"); + return -1; + } + while (tmp--) { + if (pos >= end) { + wpa_printf(MSG_DEBUG, "ASN.1: Length " + "underflow"); + return -1; + } + hdr->length = (hdr->length << 8) | *pos++; + } + } else { + /* Short form - length 0..127 in one octet */ + hdr->length = tmp; + } + + if (end < pos || hdr->length > (unsigned int) (end - pos)) { + wpa_printf(MSG_DEBUG, "ASN.1: Contents underflow"); + return -1; + } + + hdr->payload = pos; + return 0; +} + + +int asn1_parse_oid(const u8 *buf, size_t len, struct asn1_oid *oid) +{ + const u8 *pos, *end; + unsigned long val; + u8 tmp; + + os_memset(oid, 0, sizeof(*oid)); + + pos = buf; + end = buf + len; + + while (pos < end) { + val = 0; + + do { + if (pos >= end) + return -1; + tmp = *pos++; + val = (val << 7) | (tmp & 0x7f); + } while (tmp & 0x80); + + if (oid->len >= ASN1_MAX_OID_LEN) { + wpa_printf(MSG_DEBUG, "ASN.1: Too long OID value"); + return -1; + } + if (oid->len == 0) { + /* + * The first octet encodes the first two object + * identifier components in (X*40) + Y formula. + * X = 0..2. + */ + oid->oid[0] = val / 40; + if (oid->oid[0] > 2) + oid->oid[0] = 2; + oid->oid[1] = val - oid->oid[0] * 40; + oid->len = 2; + } else + oid->oid[oid->len++] = val; + } + + return 0; +} + + +int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid, + const u8 **next) +{ + struct asn1_hdr hdr; + + if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0) + return -1; + + if (hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_OID) { + wpa_printf(MSG_DEBUG, "ASN.1: Expected OID - found class %d " + "tag 0x%x", hdr.class, hdr.tag); + return -1; + } + + *next = hdr.payload + hdr.length; + + return asn1_parse_oid(hdr.payload, hdr.length, oid); +} + + +void asn1_oid_to_str(struct asn1_oid *oid, char *buf, size_t len) +{ + char *pos = buf; + size_t i; + int ret; + + if (len == 0) + return; + + buf[0] = '\0'; + + for (i = 0; i < oid->len; i++) { + //ret = os_snprintf(pos, buf + len - pos, + ret = sprintf(pos, + "%s%lu", + i == 0 ? "" : ".", oid->oid[i]); + if (ret < 0 || ret >= buf + len - pos) + break; + pos += ret; + } + buf[len - 1] = '\0'; +} + + +static u8 rotate_bits(u8 octet) +{ + int i; + u8 res; + + res = 0; + for (i = 0; i < 8; i++) { + res <<= 1; + if (octet & 1) + res |= 1; + octet >>= 1; + } + + return res; +} + + +unsigned long asn1_bit_string_to_long(const u8 *buf, size_t len) +{ + unsigned long val = 0; + const u8 *pos = buf; + + /* BER requires that unused bits are zero, so we can ignore the number + * of unused bits */ + pos++; + + if (len >= 2) + val |= rotate_bits(*pos++); + if (len >= 3) + val |= ((unsigned long) rotate_bits(*pos++)) << 8; + if (len >= 4) + val |= ((unsigned long) rotate_bits(*pos++)) << 16; + if (len >= 5) + val |= ((unsigned long) rotate_bits(*pos++)) << 24; + if (len >= 6) + wpa_printf(MSG_DEBUG, "X509: %s - some bits ignored " + "(BIT STRING length %lu)", + __func__, (unsigned long) len); + + return val; +} diff --git a/components/wpa_supplicant/src/wpa2/tls/bignum.c b/components/wpa_supplicant/src/wpa2/tls/bignum.c new file mode 100644 index 0000000000..aef8f953b3 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/tls/bignum.c @@ -0,0 +1,244 @@ +/* + * Big number math + * Copyright (c) 2006, Jouni Malinen + * + * 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 "wpa/wpabuf.h" +#include "wpa/wpa_debug.h" +#include "wpa2/tls/bignum.h" + +#define CONFIG_INTERNAL_LIBTOMMATH +#ifdef CONFIG_INTERNAL_LIBTOMMATH +#include "wpa2/tls/libtommath.h" +#else /* CONFIG_INTERNAL_LIBTOMMATH */ +#include +#endif /* CONFIG_INTERNAL_LIBTOMMATH */ + + +/* + * The current version is just a wrapper for LibTomMath library, so + * struct bignum is just typecast to mp_int. + */ + +/** + * bignum_init - Allocate memory for bignum + * Returns: Pointer to allocated bignum or %NULL on failure + */ +struct bignum * +bignum_init(void) +{ + struct bignum *n = (struct bignum *)os_zalloc(sizeof(mp_int)); + if (n == NULL) + return NULL; + if (mp_init((mp_int *) n) != MP_OKAY) { + os_free(n); + n = NULL; + } + return n; +} + + +/** + * bignum_deinit - Free bignum + * @n: Bignum from bignum_init() + */ +void +bignum_deinit(struct bignum *n) +{ + if (n) { + mp_clear((mp_int *) n); + os_free(n); + } +} + + +/** + * bignum_get_unsigned_bin - Get length of bignum as an unsigned binary buffer + * @n: Bignum from bignum_init() + * Returns: Length of n if written to a binary buffer + */ +size_t +bignum_get_unsigned_bin_len(struct bignum *n) +{ + return mp_unsigned_bin_size((mp_int *) n); +} + + +/** + * bignum_get_unsigned_bin - Set binary buffer to unsigned bignum + * @n: Bignum from bignum_init() + * @buf: Buffer for the binary number + * @len: Length of the buffer, can be %NULL if buffer is known to be long + * enough. Set to used buffer length on success if not %NULL. + * Returns: 0 on success, -1 on failure + */ +int +bignum_get_unsigned_bin(const struct bignum *n, u8 *buf, size_t *len) +{ + size_t need = mp_unsigned_bin_size((mp_int *) n); + if (len && need > *len) { + *len = need; + return -1; + } + if (mp_to_unsigned_bin((mp_int *) n, buf) != MP_OKAY) { + wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); + return -1; + } + if (len) + *len = need; + return 0; +} + + +/** + * bignum_set_unsigned_bin - Set bignum based on unsigned binary buffer + * @n: Bignum from bignum_init(); to be set to the given value + * @buf: Buffer with unsigned binary value + * @len: Length of buf in octets + * Returns: 0 on success, -1 on failure + */ +int +bignum_set_unsigned_bin(struct bignum *n, const u8 *buf, size_t len) +{ + if (mp_read_unsigned_bin((mp_int *) n, (u8 *) buf, len) != MP_OKAY) { + wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); + return -1; + } + return 0; +} + + +/** + * bignum_cmp - Signed comparison + * @a: Bignum from bignum_init() + * @b: Bignum from bignum_init() + * Returns: 0 on success, -1 on failure + */ +int +bignum_cmp(const struct bignum *a, const struct bignum *b) +{ + return mp_cmp((mp_int *) a, (mp_int *) b); +} + + +/** + * bignum_cmd_d - Compare bignum to standard integer + * @a: Bignum from bignum_init() + * @b: Small integer + * Returns: 0 on success, -1 on failure + */ +int +bignum_cmp_d(const struct bignum *a, unsigned long b) +{ + return mp_cmp_d((mp_int *) a, b); +} + + +/** + * bignum_add - c = a + b + * @a: Bignum from bignum_init() + * @b: Bignum from bignum_init() + * @c: Bignum from bignum_init(); used to store the result of a + b + * Returns: 0 on success, -1 on failure + */ +int +bignum_add(const struct bignum *a, const struct bignum *b, + struct bignum *c) +{ + if (mp_add((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) { + wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); + return -1; + } + return 0; +} + + +/** + * bignum_sub - c = a - b + * @a: Bignum from bignum_init() + * @b: Bignum from bignum_init() + * @c: Bignum from bignum_init(); used to store the result of a - b + * Returns: 0 on success, -1 on failure + */ +int +bignum_sub(const struct bignum *a, const struct bignum *b, + struct bignum *c) +{ + if (mp_sub((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) { + wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); + return -1; + } + return 0; +} + + +/** + * bignum_mul - c = a * b + * @a: Bignum from bignum_init() + * @b: Bignum from bignum_init() + * @c: Bignum from bignum_init(); used to store the result of a * b + * Returns: 0 on success, -1 on failure + */ +int +bignum_mul(const struct bignum *a, const struct bignum *b, + struct bignum *c) +{ + if (mp_mul((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) { + wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); + return -1; + } + return 0; +} + + +/** + * bignum_mulmod - d = a * b (mod c) + * @a: Bignum from bignum_init() + * @b: Bignum from bignum_init() + * @c: Bignum from bignum_init(); modulus + * @d: Bignum from bignum_init(); used to store the result of a * b (mod c) + * Returns: 0 on success, -1 on failure + */ +int +bignum_mulmod(const struct bignum *a, const struct bignum *b, + const struct bignum *c, struct bignum *d) +{ + if (mp_mulmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d) + != MP_OKAY) { + wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); + return -1; + } + return 0; +} + + +/** + * bignum_exptmod - Modular exponentiation: d = a^b (mod c) + * @a: Bignum from bignum_init(); base + * @b: Bignum from bignum_init(); exponent + * @c: Bignum from bignum_init(); modulus + * @d: Bignum from bignum_init(); used to store the result of a^b (mod c) + * Returns: 0 on success, -1 on failure + */ +int +bignum_exptmod(const struct bignum *a, const struct bignum *b, + const struct bignum *c, struct bignum *d) +{ + if (mp_exptmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d) + != MP_OKAY) { + wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__); + return -1; + } + return 0; +} diff --git a/components/wpa_supplicant/src/wpa2/tls/pkcs1.c b/components/wpa_supplicant/src/wpa2/tls/pkcs1.c new file mode 100644 index 0000000000..6266806bc1 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/tls/pkcs1.c @@ -0,0 +1,195 @@ +/* + * PKCS #1 (RSA Encryption) + * Copyright (c) 2006-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "wpa2/tls/rsa.h" +#include "wpa2/tls/pkcs1.h" + + +static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen, + const u8 *in, size_t inlen, + u8 *out, size_t *outlen) +{ + size_t ps_len; + u8 *pos; + + /* + * PKCS #1 v1.5, 8.1: + * + * EB = 00 || BT || PS || 00 || D + * BT = 00 or 01 for private-key operation; 02 for public-key operation + * PS = k-3-||D||; at least eight octets + * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero) + * k = length of modulus in octets (modlen) + */ + + if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) { + wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer " + "lengths (modlen=%lu outlen=%lu inlen=%lu)", + __func__, (unsigned long) modlen, + (unsigned long) *outlen, + (unsigned long) inlen); + return -1; + } + + pos = out; + *pos++ = 0x00; + *pos++ = block_type; /* BT */ + ps_len = modlen - inlen - 3; + switch (block_type) { + case 0: + os_memset(pos, 0x00, ps_len); + pos += ps_len; + break; + case 1: + os_memset(pos, 0xff, ps_len); + pos += ps_len; + break; + case 2: + if (os_get_random(pos, ps_len) < 0) { + wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get " + "random data for PS", __func__); + return -1; + } + while (ps_len--) { + if (*pos == 0x00) + *pos = 0x01; + pos++; + } + break; + default: + wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type " + "%d", __func__, block_type); + return -1; + } + *pos++ = 0x00; + os_memcpy(pos, in, inlen); /* D */ + + return 0; +} + + +int pkcs1_encrypt(int block_type, struct crypto_rsa_key *key, + int use_private, const u8 *in, size_t inlen, + u8 *out, size_t *outlen) +{ + size_t modlen; + + modlen = crypto_rsa_get_modulus_len(key); + + if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen, + out, outlen) < 0) + return -1; + + return crypto_rsa_exptmod(out, modlen, out, outlen, key, use_private); +} + + +int pkcs1_v15_private_key_decrypt(struct crypto_rsa_key *key, + const u8 *in, size_t inlen, + u8 *out, size_t *outlen) +{ + int res; + u8 *pos, *end; + + res = crypto_rsa_exptmod(in, inlen, out, outlen, key, 1); + if (res) + return res; + + if (*outlen < 2 || out[0] != 0 || out[1] != 2) + return -1; + + /* Skip PS (pseudorandom non-zero octets) */ + pos = out + 2; + end = out + *outlen; + while (*pos && pos < end) + pos++; + if (pos == end) + return -1; + pos++; + + *outlen -= pos - out; + + /* Strip PKCS #1 header */ + os_memmove(out, pos, *outlen); + + return 0; +} + + +int pkcs1_decrypt_public_key(struct crypto_rsa_key *key, + const u8 *crypt, size_t crypt_len, + u8 *plain, size_t *plain_len) +{ + size_t len; + u8 *pos; + + len = *plain_len; + if (crypto_rsa_exptmod(crypt, crypt_len, plain, &len, key, 0) < 0) + return -1; + + /* + * PKCS #1 v1.5, 8.1: + * + * EB = 00 || BT || PS || 00 || D + * BT = 00 or 01 + * PS = k-3-||D|| times (00 if BT=00) or (FF if BT=01) + * k = length of modulus in octets + */ + + if (len < 3 + 8 + 16 /* min hash len */ || + plain[0] != 0x00 || (plain[1] != 0x00 && plain[1] != 0x01)) { + wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " + "structure"); + return -1; + } + + pos = plain + 3; + if (plain[1] == 0x00) { + /* BT = 00 */ + if (plain[2] != 0x00) { + wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature " + "PS (BT=00)"); + return -1; + } + while (pos + 1 < plain + len && *pos == 0x00 && pos[1] == 0x00) + pos++; + } else { + /* BT = 01 */ + if (plain[2] != 0xff) { + wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature " + "PS (BT=01)"); + return -1; + } + while (pos < plain + len && *pos == 0xff) + pos++; + } + + if (pos - plain - 2 < 8) { + /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ + wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " + "padding"); + return -1; + } + + if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { + wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " + "structure (2)"); + return -1; + } + pos++; + len -= pos - plain; + + /* Strip PKCS #1 header */ + os_memmove(plain, pos, len); + *plain_len = len; + + return 0; +} diff --git a/components/wpa_supplicant/src/wpa2/tls/pkcs5.c b/components/wpa_supplicant/src/wpa2/tls/pkcs5.c new file mode 100644 index 0000000000..0a0ac9e3f6 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/tls/pkcs5.c @@ -0,0 +1,262 @@ +/* + * PKCS #5 (Password-based Encryption) + * Copyright (c) 2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "crypto/crypto.h" +#include "crypto/md5.h" +#include "wpa2/tls/asn1.h" +#include "wpa2/tls/pkcs5.h" + +#include "wpa2/eap_peer/eap_i.h" + +struct pkcs5_params { + enum pkcs5_alg { + PKCS5_ALG_UNKNOWN, + PKCS5_ALG_MD5_DES_CBC + } alg; + u8 salt[8]; + size_t salt_len; + unsigned int iter_count; +}; + + +static enum pkcs5_alg pkcs5_get_alg(struct asn1_oid *oid) +{ + if (oid->len == 7 && + oid->oid[0] == 1 /* iso */ && + oid->oid[1] == 2 /* member-body */ && + oid->oid[2] == 840 /* us */ && + oid->oid[3] == 113549 /* rsadsi */ && + oid->oid[4] == 1 /* pkcs */ && + oid->oid[5] == 5 /* pkcs-5 */ && + oid->oid[6] == 3 /* pbeWithMD5AndDES-CBC */) + return PKCS5_ALG_MD5_DES_CBC; + + return PKCS5_ALG_UNKNOWN; +} + + +static int pkcs5_get_params(const u8 *enc_alg, size_t enc_alg_len, + struct pkcs5_params *params) +{ + struct asn1_hdr hdr; + const u8 *enc_alg_end, *pos, *end; + struct asn1_oid oid; + char obuf[80]; + + /* AlgorithmIdentifier */ + + enc_alg_end = enc_alg + enc_alg_len; + + os_memset(params, 0, sizeof(*params)); + + if (asn1_get_oid(enc_alg, enc_alg_end - enc_alg, &oid, &pos)) { + wpa_printf(MSG_DEBUG, "PKCS #5: Failed to parse OID " + "(algorithm)"); + return -1; + } + + asn1_oid_to_str(&oid, obuf, sizeof(obuf)); + wpa_printf(MSG_DEBUG, "PKCS #5: encryption algorithm %s", obuf); + params->alg = pkcs5_get_alg(&oid); + if (params->alg == PKCS5_ALG_UNKNOWN) { + wpa_printf(MSG_INFO, "PKCS #5: unsupported encryption " + "algorithm %s", obuf); + return -1; + } + + /* + * PKCS#5, Section 8 + * PBEParameter ::= SEQUENCE { + * salt OCTET STRING SIZE(8), + * iterationCount INTEGER } + */ + + if (asn1_get_next(pos, enc_alg_end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "PKCS #5: Expected SEQUENCE " + "(PBEParameter) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + pos = hdr.payload; + end = hdr.payload + hdr.length; + + /* salt OCTET STRING SIZE(8) */ + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_OCTETSTRING || + hdr.length != 8) { + wpa_printf(MSG_DEBUG, "PKCS #5: Expected OCTETSTRING SIZE(8) " + "(salt) - found class %d tag 0x%x size %d", + hdr.class, hdr.tag, hdr.length); + return -1; + } + pos = hdr.payload + hdr.length; + os_memcpy(params->salt, hdr.payload, hdr.length); + params->salt_len = hdr.length; + wpa_hexdump(MSG_DEBUG, "PKCS #5: salt", + params->salt, params->salt_len); + + /* iterationCount INTEGER */ + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { + wpa_printf(MSG_DEBUG, "PKCS #5: Expected INTEGER - found " + "class %d tag 0x%x", hdr.class, hdr.tag); + return -1; + } + if (hdr.length == 1) + params->iter_count = *hdr.payload; + else if (hdr.length == 2) + params->iter_count = WPA_GET_BE16(hdr.payload); + else if (hdr.length == 4) + params->iter_count = WPA_GET_BE32(hdr.payload); + else { + wpa_hexdump(MSG_DEBUG, "PKCS #5: Unsupported INTEGER value " + " (iterationCount)", + hdr.payload, hdr.length); + return -1; + } + wpa_printf(MSG_DEBUG, "PKCS #5: iterationCount=0x%x", + params->iter_count); + if (params->iter_count == 0 || params->iter_count > 0xffff) { + wpa_printf(MSG_INFO, "PKCS #5: Unsupported " + "iterationCount=0x%x", params->iter_count); + return -1; + } + + return 0; +} + + +static struct crypto_cipher * pkcs5_crypto_init(struct pkcs5_params *params, + const char *passwd) +{ + unsigned int i; + u8 hash[MD5_MAC_LEN]; + const u8 *addr[2]; + size_t len[2]; + + if (params->alg != PKCS5_ALG_MD5_DES_CBC) { + return NULL; + } + + addr[0] = (const u8 *) passwd; + len[0] = os_strlen(passwd); + addr[1] = params->salt; + len[1] = params->salt_len; + if (md5_vector(2, addr, len, hash) < 0) + return NULL; + addr[0] = hash; + len[0] = MD5_MAC_LEN; + for (i = 1; i < params->iter_count; i++) { + if (md5_vector(1, addr, len, hash) < 0) + return NULL; + } + /* TODO: DES key parity bits(?) */ + wpa_hexdump_key(MSG_DEBUG, "PKCS #5: DES key", hash, 8); + wpa_hexdump_key(MSG_DEBUG, "PKCS #5: DES IV", hash + 8, 8); + + if (wpa2_crypto_funcs.crypto_cipher_init) { + return wpa2_crypto_funcs.crypto_cipher_init(CRYPTO_CIPHER_ALG_DES, hash + 8, hash, 8); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register crypto_cipher_init function! \r\n", __FUNCTION__); + return NULL; + } +} + +u8 * pkcs5_decrypt(const u8 *enc_alg, size_t enc_alg_len, + const u8 *enc_data, size_t enc_data_len, + const char *passwd, size_t *data_len) +{ + struct crypto_cipher *ctx = NULL; + u8 *eb, pad; + struct pkcs5_params params; + unsigned int i; + + if (pkcs5_get_params(enc_alg, enc_alg_len, ¶ms) < 0) { + wpa_printf(MSG_DEBUG, "PKCS #5: Unsupported parameters"); + return NULL; + } + + ctx = pkcs5_crypto_init(¶ms, passwd); + + if (ctx == NULL) { + wpa_printf(MSG_DEBUG, "PKCS #5: Failed to initialize crypto"); + return NULL; + } + + /* PKCS #5, Section 7 - Decryption process */ + if (enc_data_len < 16 || enc_data_len % 8) { + wpa_printf(MSG_INFO, "PKCS #5: invalid length of ciphertext " + "%d", (int) enc_data_len); + if (wpa2_crypto_funcs.crypto_cipher_deinit) { + wpa2_crypto_funcs.crypto_cipher_deinit(ctx); + } else { + wpa_printf(MSG_ERROR, "Fail to register crypto cipher deinit function!\r\n"); + return NULL; + } + return NULL; + } + + eb = os_malloc(enc_data_len); + if (eb == NULL) { + if (wpa2_crypto_funcs.crypto_cipher_deinit) { + wpa2_crypto_funcs.crypto_cipher_deinit(ctx); + } else { + wpa_printf(MSG_ERROR, "Fail to register crypto cipher deinit function!\r\n"); + return NULL; + } + return NULL; + } + + if (wpa2_crypto_funcs.crypto_cipher_decrypt) { + if ((int)wpa2_crypto_funcs.crypto_cipher_decrypt(ctx, enc_data, eb, enc_data_len) < 0) { + wpa_printf(MSG_DEBUG, "PKCS #5: Failed to decrypt EB"); + wpa2_crypto_funcs.crypto_cipher_deinit(ctx); + os_free(eb); + return NULL; + } + } else { + wpa_printf(MSG_ERROR, "Fail to register crypto cipher decrypt function.\r\n"); + wpa2_crypto_funcs.crypto_cipher_deinit(ctx); + os_free(eb); + return NULL; + } + + if (wpa2_crypto_funcs.crypto_cipher_deinit) { + wpa2_crypto_funcs.crypto_cipher_deinit(ctx); + } else { + wpa_printf(MSG_ERROR, "Fail to register crypto cipher deinit function!\r\n"); + return NULL; + } + + pad = eb[enc_data_len - 1]; + if (pad > 8) { + wpa_printf(MSG_INFO, "PKCS #5: Invalid PS octet 0x%x", pad); + os_free(eb); + return NULL; + } + for (i = enc_data_len - pad; i < enc_data_len; i++) { + if (eb[i] != pad) { + wpa_hexdump(MSG_INFO, "PKCS #5: Invalid PS", + eb + enc_data_len - pad, pad); + os_free(eb); + return NULL; + } + } + + wpa_hexdump_key(MSG_MSGDUMP, "PKCS #5: message M (encrypted key)", + eb, enc_data_len - pad); + + *data_len = enc_data_len - pad; + return eb; +} diff --git a/components/wpa_supplicant/src/wpa2/tls/pkcs8.c b/components/wpa_supplicant/src/wpa2/tls/pkcs8.c new file mode 100644 index 0000000000..0f39c4558e --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/tls/pkcs8.c @@ -0,0 +1,186 @@ +/* + * PKCS #8 (Private-key information syntax) + * Copyright (c) 2006-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "wpa2/tls/asn1.h" +#include "wpa2/tls/bignum.h" +#include "wpa2/tls/rsa.h" +#include "wpa2/tls/pkcs5.h" +#include "wpa2/tls/pkcs8.h" + +struct crypto_private_key * pkcs8_key_import(const u8 *buf, size_t len) +{ + struct asn1_hdr hdr; + const u8 *pos, *end; + struct bignum *zero; + struct asn1_oid oid; + char obuf[80]; + + /* PKCS #8, Chapter 6 */ + + /* PrivateKeyInfo ::= SEQUENCE */ + if (asn1_get_next(buf, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 " + "header (SEQUENCE); assume PKCS #8 not used"); + return NULL; + } + pos = hdr.payload; + end = pos + hdr.length; + + /* version Version (Version ::= INTEGER) */ + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { + wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found " + "class %d tag 0x%x; assume PKCS #8 not used", + hdr.class, hdr.tag); + return NULL; + } + + zero = bignum_init(); + if (zero == NULL) + return NULL; + + if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) { + wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER"); + bignum_deinit(zero); + return NULL; + } + pos = hdr.payload + hdr.length; + + if (bignum_cmp_d(zero, 0) != 0) { + wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the " + "beginning of private key; not found; assume " + "PKCS #8 not used"); + bignum_deinit(zero); + return NULL; + } + bignum_deinit(zero); + + /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier + * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */ + if (asn1_get_next(pos, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE " + "(AlgorithmIdentifier) - found class %d tag 0x%x; " + "assume PKCS #8 not used", + hdr.class, hdr.tag); + return NULL; + } + + if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) { + wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID " + "(algorithm); assume PKCS #8 not used"); + return NULL; + } + + asn1_oid_to_str(&oid, obuf, sizeof(obuf)); + wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf); + + if (oid.len != 7 || + oid.oid[0] != 1 /* iso */ || + oid.oid[1] != 2 /* member-body */ || + oid.oid[2] != 840 /* us */ || + oid.oid[3] != 113549 /* rsadsi */ || + oid.oid[4] != 1 /* pkcs */ || + oid.oid[5] != 1 /* pkcs-1 */ || + oid.oid[6] != 1 /* rsaEncryption */) { + wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key " + "algorithm %s", obuf); + return NULL; + } + + pos = hdr.payload + hdr.length; + + /* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */ + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_OCTETSTRING) { + wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING " + "(privateKey) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return NULL; + } + wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey"); + + return (struct crypto_private_key *) + crypto_rsa_import_private_key(hdr.payload, hdr.length); +} + + +struct crypto_private_key * +pkcs8_enc_key_import(const u8 *buf, size_t len, const char *passwd) +{ + struct asn1_hdr hdr; + const u8 *pos, *end, *enc_alg; + size_t enc_alg_len; + u8 *data; + size_t data_len; + + if (passwd == NULL) + return NULL; + + /* + * PKCS #8, Chapter 7 + * EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData } + * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * EncryptedData ::= OCTET STRING + */ + + if (asn1_get_next(buf, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 " + "header (SEQUENCE); assume encrypted PKCS #8 not " + "used"); + return NULL; + } + pos = hdr.payload; + end = pos + hdr.length; + + /* encryptionAlgorithm EncryptionAlgorithmIdentifier */ + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE " + "(AlgorithmIdentifier) - found class %d tag 0x%x; " + "assume encrypted PKCS #8 not used", + hdr.class, hdr.tag); + return NULL; + } + enc_alg = hdr.payload; + enc_alg_len = hdr.length; + pos = hdr.payload + hdr.length; + + /* encryptedData EncryptedData */ + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_OCTETSTRING) { + wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING " + "(encryptedData) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return NULL; + } + + data = pkcs5_decrypt(enc_alg, enc_alg_len, hdr.payload, hdr.length, + passwd, &data_len); + if (data) { + struct crypto_private_key *key; + key = pkcs8_key_import(data, data_len); + os_free(data); + return key; + } + + return NULL; +} diff --git a/components/wpa_supplicant/src/wpa2/tls/rsa.c b/components/wpa_supplicant/src/wpa2/tls/rsa.c new file mode 100644 index 0000000000..0b09d4d807 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/tls/rsa.c @@ -0,0 +1,353 @@ +/* + * RSA + * Copyright (c) 2006, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "wpa2/tls/asn1.h" +#include "wpa2/tls/bignum.h" +#include "wpa2/tls/rsa.h" +#include "soc/dport_reg.h" + +struct crypto_rsa_key { + int private_key; /* whether private key is set */ + struct bignum *n; /* modulus (p * q) */ + struct bignum *e; /* public exponent */ + /* The following parameters are available only if private_key is set */ + struct bignum *d; /* private exponent */ + struct bignum *p; /* prime p (factor of n) */ + struct bignum *q; /* prime q (factor of n) */ + struct bignum *dmp1; /* d mod (p - 1); CRT exponent */ + struct bignum *dmq1; /* d mod (q - 1); CRT exponent */ + struct bignum *iqmp; /* 1 / q mod p; CRT coefficient */ +}; + + +static const u8 * crypto_rsa_parse_integer(const u8 *pos, const u8 *end, + struct bignum *num) +{ + struct asn1_hdr hdr; + + if (pos == NULL) + return NULL; + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { + wpa_printf(MSG_DEBUG, "RSA: Expected INTEGER - found class %d " + "tag 0x%x", hdr.class, hdr.tag); + return NULL; + } + + if (bignum_set_unsigned_bin(num, hdr.payload, hdr.length) < 0) { + wpa_printf(MSG_DEBUG, "RSA: Failed to parse INTEGER"); + return NULL; + } + + return hdr.payload + hdr.length; +} + + +/** + * crypto_rsa_import_public_key - Import an RSA public key + * @buf: Key buffer (DER encoded RSA public key) + * @len: Key buffer length in bytes + * Returns: Pointer to the public key or %NULL on failure + */ +struct crypto_rsa_key * +crypto_rsa_import_public_key(const u8 *buf, size_t len) +{ + struct crypto_rsa_key *key; + struct asn1_hdr hdr; + const u8 *pos, *end; + + key = (struct crypto_rsa_key *)os_zalloc(sizeof(*key)); + if (key == NULL) + return NULL; + + key->n = bignum_init(); + key->e = bignum_init(); + if (key->n == NULL || key->e == NULL) { + crypto_rsa_free(key); + return NULL; + } + + /* + * PKCS #1, 7.1: + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ + + if (asn1_get_next(buf, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "RSA: Expected SEQUENCE " + "(public key) - found class %d tag 0x%x", + hdr.class, hdr.tag); + goto error; + } + pos = hdr.payload; + end = pos + hdr.length; + + pos = crypto_rsa_parse_integer(pos, end, key->n); + pos = crypto_rsa_parse_integer(pos, end, key->e); + + if (pos == NULL) + goto error; + + if (pos != end) { + wpa_hexdump(MSG_DEBUG, + "RSA: Extra data in public key SEQUENCE", + pos, end - pos); + goto error; + } + + return key; + +error: + crypto_rsa_free(key); + return NULL; +} + + +/** + * crypto_rsa_import_private_key - Import an RSA private key + * @buf: Key buffer (DER encoded RSA private key) + * @len: Key buffer length in bytes + * Returns: Pointer to the private key or %NULL on failure + */ +struct crypto_rsa_key * +crypto_rsa_import_private_key(const u8 *buf, size_t len) +{ + struct crypto_rsa_key *key; + struct bignum *zero; + struct asn1_hdr hdr; + const u8 *pos, *end; + + key = (struct crypto_rsa_key *)os_zalloc(sizeof(*key)); + if (key == NULL) + return NULL; + + key->private_key = 1; + + key->n = bignum_init(); + key->e = bignum_init(); + key->d = bignum_init(); + key->p = bignum_init(); + key->q = bignum_init(); + key->dmp1 = bignum_init(); + key->dmq1 = bignum_init(); + key->iqmp = bignum_init(); + + if (key->n == NULL || key->e == NULL || key->d == NULL || + key->p == NULL || key->q == NULL || key->dmp1 == NULL || + key->dmq1 == NULL || key->iqmp == NULL) { + crypto_rsa_free(key); + return NULL; + } + + /* + * PKCS #1, 7.2: + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER -- (inverse of q) mod p + * } + * + * Version ::= INTEGER -- shall be 0 for this version of the standard + */ + if (asn1_get_next(buf, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "RSA: Expected SEQUENCE " + "(public key) - found class %d tag 0x%x", + hdr.class, hdr.tag); + goto error; + } + pos = hdr.payload; + end = pos + hdr.length; + + zero = bignum_init(); + if (zero == NULL) + goto error; + pos = crypto_rsa_parse_integer(pos, end, zero); + if (pos == NULL || bignum_cmp_d(zero, 0) != 0) { + wpa_printf(MSG_DEBUG, "RSA: Expected zero INTEGER in the " + "beginning of private key; not found"); + bignum_deinit(zero); + goto error; + } + bignum_deinit(zero); + + pos = crypto_rsa_parse_integer(pos, end, key->n); + pos = crypto_rsa_parse_integer(pos, end, key->e); + pos = crypto_rsa_parse_integer(pos, end, key->d); + pos = crypto_rsa_parse_integer(pos, end, key->p); + pos = crypto_rsa_parse_integer(pos, end, key->q); + pos = crypto_rsa_parse_integer(pos, end, key->dmp1); + pos = crypto_rsa_parse_integer(pos, end, key->dmq1); + pos = crypto_rsa_parse_integer(pos, end, key->iqmp); + + if (pos == NULL) + goto error; + + if (pos != end) { + wpa_hexdump(MSG_DEBUG, + "RSA: Extra data in public key SEQUENCE", + pos, end - pos); + goto error; + } + + return key; + +error: + crypto_rsa_free(key); + return NULL; +} + + +/** + * crypto_rsa_get_modulus_len - Get the modulus length of the RSA key + * @key: RSA key + * Returns: Modulus length of the key + */ +size_t crypto_rsa_get_modulus_len(struct crypto_rsa_key *key) +{ + return bignum_get_unsigned_bin_len(key->n); +} + + +/** + * crypto_rsa_exptmod - RSA modular exponentiation + * @in: Input data + * @inlen: Input data length + * @out: Buffer for output data + * @outlen: Maximum size of the output buffer and used size on success + * @key: RSA key + * @use_private: 1 = Use RSA private key, 0 = Use RSA public key + * Returns: 0 on success, -1 on failure + */ +int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen, + struct crypto_rsa_key *key, int use_private) +{ + struct bignum *tmp, *a = NULL, *b = NULL; + int ret = -1; + size_t modlen; + + if (use_private && !key->private_key) + return -1; + + tmp = bignum_init(); + if (tmp == NULL) + return -1; + + if (bignum_set_unsigned_bin(tmp, in, inlen) < 0) + goto error; + if (bignum_cmp(key->n, tmp) < 0) { + /* Too large input value for the RSA key modulus */ + goto error; + } + + if (use_private) { + /* + * Decrypt (or sign) using Chinese remainer theorem to speed + * up calculation. This is equivalent to tmp = tmp^d mod n + * (which would require more CPU to calculate directly). + * + * dmp1 = (1/e) mod (p-1) + * dmq1 = (1/e) mod (q-1) + * iqmp = (1/q) mod p, where p > q + * m1 = c^dmp1 mod p + * m2 = c^dmq1 mod q + * h = q^-1 (m1 - m2) mod p + * m = m2 + hq + */ + a = bignum_init(); + b = bignum_init(); + if (a == NULL || b == NULL) + goto error; + + /* a = tmp^dmp1 mod p */ + if (bignum_exptmod(tmp, key->dmp1, key->p, a) < 0) + goto error; + + /* b = tmp^dmq1 mod q */ + if (bignum_exptmod(tmp, key->dmq1, key->q, b) < 0) + goto error; + + /* tmp = (a - b) * (1/q mod p) (mod p) */ + if (bignum_sub(a, b, tmp) < 0 || + bignum_mulmod(tmp, key->iqmp, key->p, tmp) < 0) + goto error; + + /* tmp = b + q * tmp */ + if (bignum_mul(tmp, key->q, tmp) < 0 || + bignum_add(tmp, b, tmp) < 0) + goto error; + } else { + /* Encrypt (or verify signature) */ + /* tmp = tmp^e mod N */ + if (bignum_exptmod(tmp, key->e, key->n, tmp) < 0) + goto error; + } + + modlen = crypto_rsa_get_modulus_len(key); + if (modlen > *outlen) { + *outlen = modlen; + goto error; + } + + if (bignum_get_unsigned_bin_len(tmp) > modlen) + goto error; /* should never happen */ + + *outlen = modlen; + os_memset(out, 0, modlen); + if (bignum_get_unsigned_bin( + tmp, out + + (modlen - bignum_get_unsigned_bin_len(tmp)), NULL) < 0) + goto error; + + ret = 0; + +error: + + bignum_deinit(tmp); + bignum_deinit(a); + bignum_deinit(b); + return ret; +} + + +/** + * crypto_rsa_free - Free RSA key + * @key: RSA key to be freed + * + * This function frees an RSA key imported with either + * crypto_rsa_import_public_key() or crypto_rsa_import_private_key(). + */ +void crypto_rsa_free(struct crypto_rsa_key *key) +{ + if (key) { + bignum_deinit(key->n); + bignum_deinit(key->e); + bignum_deinit(key->d); + bignum_deinit(key->p); + bignum_deinit(key->q); + bignum_deinit(key->dmp1); + bignum_deinit(key->dmq1); + bignum_deinit(key->iqmp); + os_free(key); + } +} diff --git a/components/wpa_supplicant/src/wpa2/tls/tls_internal.c b/components/wpa_supplicant/src/wpa2/tls/tls_internal.c new file mode 100644 index 0000000000..682d457c58 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/tls/tls_internal.c @@ -0,0 +1,716 @@ +/* + * TLS interface functions and an internal TLS implementation + * Copyright (c) 2004-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + * + * This file interface functions for hostapd/wpa_supplicant to use the + * integrated TLSv1 implementation. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "crypto/sha1.h" +#include "crypto/md5.h" +#include "wpa2/tls/tls.h" +#include "wpa2/tls/tlsv1_client.h" +#include "wpa2/tls/tlsv1_server.h" + +#ifndef CONFIG_TLS_INTERNAL_CLIENT +#define CONFIG_TLS_INTERNAL_CLIENT +#endif + +static int tls_ref_count = 0; + +struct tls_global { + int server; + struct tlsv1_credentials *server_cred; + int check_crl; +}; + +struct tls_connection { + struct tlsv1_client *client; + struct tlsv1_server *server; +}; + + +void * tls_init(void) +{ + struct tls_global *global; + + if (tls_ref_count == 0) { +#ifdef CONFIG_TLS_INTERNAL_CLIENT + if (tlsv1_client_global_init()) + return NULL; +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (tlsv1_server_global_init()) + return NULL; +#endif /* CONFIG_TLS_INTERNAL_SERVER */ + } + tls_ref_count++; + + global = (struct tls_global *)os_zalloc(sizeof(*global)); + if (global == NULL) + return NULL; + + return global; +} + +void tls_deinit(void *ssl_ctx) +{ + struct tls_global *global = ssl_ctx; + tls_ref_count--; + if (tls_ref_count == 0) { +#ifdef CONFIG_TLS_INTERNAL_CLIENT + tlsv1_client_global_deinit(); +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ +#ifdef CONFIG_TLS_INTERNAL_SERVER + tlsv1_cred_free(global->server_cred); + tlsv1_server_global_deinit(); +#endif /* CONFIG_TLS_INTERNAL_SERVER */ + } + os_free(global); +} + + +int tls_get_errors(void *tls_ctx) +{ + return 0; +} + + +struct tls_connection * tls_connection_init(void *tls_ctx) +{ + struct tls_connection *conn; + struct tls_global *global = tls_ctx; + + conn = (struct tls_connection *)os_zalloc(sizeof(*conn)); + if (conn == NULL) + return NULL; +#ifdef CONFIG_TLS_INTERNAL_CLIENT + if (!global->server) { + conn->client = tlsv1_client_init(); + if (conn->client == NULL) { + os_free(conn); + return NULL; + } + } +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (global->server) { + conn->server = tlsv1_server_init(global->server_cred); + if (conn->server == NULL) { + os_free(conn); + return NULL; + } + } +#endif /* CONFIG_TLS_INTERNAL_SERVER */ + + return conn; +} + + +void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) +{ + if (conn == NULL) + return; +#ifdef CONFIG_TLS_INTERNAL_CLIENT + if (conn->client) + tlsv1_client_deinit(conn->client); +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (conn->server) + tlsv1_server_deinit(conn->server); +#endif /* CONFIG_TLS_INTERNAL_SERVER */ + os_free(conn); +} + + +int tls_connection_established(void *tls_ctx, struct tls_connection *conn) +{ +#ifdef CONFIG_TLS_INTERNAL_CLIENT + if (conn->client) + return tlsv1_client_established(conn->client); +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (conn->server) + return tlsv1_server_established(conn->server); +#endif /* CONFIG_TLS_INTERNAL_SERVER */ + return 0; +} + + +int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) +{ +#ifdef CONFIG_TLS_INTERNAL_CLIENT + if (conn->client) + return tlsv1_client_shutdown(conn->client); +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (conn->server) + return tlsv1_server_shutdown(conn->server); +#endif /* CONFIG_TLS_INTERNAL_SERVER */ + return -1; +} + + +int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, + const struct tls_connection_params *params) +{ +#ifdef CONFIG_TLS_INTERNAL_CLIENT + struct tlsv1_credentials *cred; + + if (conn->client == NULL) + return -1; + + cred = tlsv1_cred_alloc(); + if (cred == NULL) + return -1; + + if (tlsv1_set_ca_cert(cred, params->ca_cert, + params->ca_cert_blob, params->ca_cert_blob_len, + params->ca_path)) { + wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA " + "certificates"); + tlsv1_cred_free(cred); + return -1; + } + + if (tlsv1_set_cert(cred, params->client_cert, + params->client_cert_blob, + params->client_cert_blob_len)) { + wpa_printf(MSG_INFO, "TLS: Failed to configure client " + "certificate"); + tlsv1_cred_free(cred); + return -1; + } + + if (tlsv1_set_private_key(cred, params->private_key, + params->private_key_passwd, + params->private_key_blob, + params->private_key_blob_len)) { + wpa_printf(MSG_INFO, "TLS: Failed to load private key"); + tlsv1_cred_free(cred); + return -1; + } + + if (tlsv1_client_set_cred(conn->client, cred) < 0) { + tlsv1_cred_free(cred); + return -1; + } + + tlsv1_client_set_time_checks( + conn->client, !(params->flags & TLS_CONN_DISABLE_TIME_CHECKS)); + //conn->client, !(TLS_CONN_DISABLE_TIME_CHECKS)); //snake + + return 0; +#else /* CONFIG_TLS_INTERNAL_CLIENT */ + return -1; +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ +} + + +int tls_global_set_params(void *tls_ctx, + const struct tls_connection_params *params) +{ +#ifdef CONFIG_TLS_INTERNAL_SERVER + struct tls_global *global = tls_ctx; + struct tlsv1_credentials *cred; + + /* Currently, global parameters are only set when running in server + * mode. */ + global->server = 1; + tlsv1_cred_free(global->server_cred); + global->server_cred = cred = tlsv1_cred_alloc(); + if (cred == NULL) + return -1; + + if (tlsv1_set_ca_cert(cred, params->ca_cert, params->ca_cert_blob, + params->ca_cert_blob_len, params->ca_path)) { + wpa_printf(MSG_INFO, "TLS: Failed to configure trusted CA " + "certificates"); + return -1; + } + + if (tlsv1_set_cert(cred, params->client_cert, params->client_cert_blob, + params->client_cert_blob_len)) { + wpa_printf(MSG_INFO, "TLS: Failed to configure server " + "certificate"); + return -1; + } + + if (tlsv1_set_private_key(cred, params->private_key, + params->private_key_passwd, + params->private_key_blob, + params->private_key_blob_len)) { + wpa_printf(MSG_INFO, "TLS: Failed to load private key"); + return -1; + } + + if (tlsv1_set_dhparams(cred, params->dh_file, params->dh_blob, + params->dh_blob_len)) { + wpa_printf(MSG_INFO, "TLS: Failed to load DH parameters"); + return -1; + } + + return 0; +#else /* CONFIG_TLS_INTERNAL_SERVER */ + return -1; +#endif /* CONFIG_TLS_INTERNAL_SERVER */ +} + + +int tls_global_set_verify(void *tls_ctx, int check_crl) +{ + struct tls_global *global = tls_ctx; + global->check_crl = check_crl; + return 0; +} + + +int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, + int verify_peer) +{ +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (conn->server) + return tlsv1_server_set_verify(conn->server, verify_peer); +#endif /* CONFIG_TLS_INTERNAL_SERVER */ + return -1; +} + + +int tls_connection_get_keys(void *tls_ctx, struct tls_connection *conn, + struct tls_keys *keys) +{ +#ifdef CONFIG_TLS_INTERNAL_CLIENT + if (conn->client) + return tlsv1_client_get_keys(conn->client, keys); +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (conn->server) + return tlsv1_server_get_keys(conn->server, keys); +#endif /* CONFIG_TLS_INTERNAL_SERVER */ + return -1; +} + + +int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, + const char *label, int server_random_first, + u8 *out, size_t out_len) +{ +#ifdef CONFIG_TLS_INTERNAL_CLIENT + if (conn->client) { + return tlsv1_client_prf(conn->client, label, + server_random_first, + out, out_len); + } +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (conn->server) { + return tlsv1_server_prf(conn->server, label, + server_random_first, + out, out_len); + } +#endif /* CONFIG_TLS_INTERNAL_SERVER */ + return -1; +} + + +struct wpabuf * tls_connection_handshake(void *tls_ctx, + struct tls_connection *conn, + const struct wpabuf *in_data, + struct wpabuf **appl_data) +{ + return tls_connection_handshake2(tls_ctx, conn, in_data, appl_data, + NULL); +} + + +struct wpabuf * tls_connection_handshake2(void *tls_ctx, + struct tls_connection *conn, + const struct wpabuf *in_data, + struct wpabuf **appl_data, + int *need_more_data) +{ +#ifdef CONFIG_TLS_INTERNAL_CLIENT + u8 *res, *ad; + size_t res_len, ad_len; + struct wpabuf *out; + + if (conn->client == NULL) + return NULL; + + ad = NULL; + res = tlsv1_client_handshake(conn->client, + in_data ? wpabuf_head(in_data) : NULL, + in_data ? wpabuf_len(in_data) : 0, + &res_len, &ad, &ad_len, need_more_data); + if (res == NULL) { + return NULL; + } + out = wpabuf_alloc_ext_data(res, res_len); + if (out == NULL) { + os_free(res); + os_free(ad); + return NULL; + } + if (appl_data) { + if (ad) { + *appl_data = wpabuf_alloc_ext_data(ad, ad_len); + if (*appl_data == NULL) + os_free(ad); + } else + *appl_data = NULL; + } else + os_free(ad); + + return out; +#else /* CONFIG_TLS_INTERNAL_CLIENT */ + return NULL; +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ +} + + +struct wpabuf * tls_connection_server_handshake(void *tls_ctx, + struct tls_connection *conn, + const struct wpabuf *in_data, + struct wpabuf **appl_data) +{ +#ifdef CONFIG_TLS_INTERNAL_SERVER + u8 *res; + size_t res_len; + struct wpabuf *out; + + if (conn->server == NULL) + return NULL; + + if (appl_data) + *appl_data = NULL; + + res = tlsv1_server_handshake(conn->server, wpabuf_head(in_data), + wpabuf_len(in_data), &res_len); + if (res == NULL && tlsv1_server_established(conn->server)) + return wpabuf_alloc(0); + if (res == NULL) + return NULL; + out = wpabuf_alloc_ext_data(res, res_len); + if (out == NULL) { + os_free(res); + return NULL; + } + + return out; +#else /* CONFIG_TLS_INTERNAL_SERVER */ + return NULL; +#endif /* CONFIG_TLS_INTERNAL_SERVER */ +} + + +struct wpabuf * tls_connection_encrypt(void *tls_ctx, + struct tls_connection *conn, + const struct wpabuf *in_data) +{ +#ifdef CONFIG_TLS_INTERNAL_CLIENT + if (conn->client) { + struct wpabuf *buf; + int res; + buf = wpabuf_alloc(wpabuf_len(in_data) + 300); + if (buf == NULL) + return NULL; + res = tlsv1_client_encrypt(conn->client, wpabuf_head(in_data), + wpabuf_len(in_data), + wpabuf_mhead(buf), + wpabuf_size(buf)); + if (res < 0) { + wpabuf_free(buf); + return NULL; + } + wpabuf_put(buf, res); + return buf; + } +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (conn->server) { + struct wpabuf *buf; + int res; + buf = wpabuf_alloc(wpabuf_len(in_data) + 300); + if (buf == NULL) + return NULL; + res = tlsv1_server_encrypt(conn->server, wpabuf_head(in_data), + wpabuf_len(in_data), + wpabuf_mhead(buf), + wpabuf_size(buf)); + if (res < 0) { + wpabuf_free(buf); + return NULL; + } + wpabuf_put(buf, res); + return buf; + } +#endif /* CONFIG_TLS_INTERNAL_SERVER */ + return NULL; +} + + +struct wpabuf * tls_connection_decrypt(void *tls_ctx, + struct tls_connection *conn, + const struct wpabuf *in_data) +{ + return tls_connection_decrypt2(tls_ctx, conn, in_data, NULL); +} + + +struct wpabuf * tls_connection_decrypt2(void *tls_ctx, + struct tls_connection *conn, + const struct wpabuf *in_data, + int *need_more_data) +{ + if (need_more_data) + *need_more_data = 0; + +#ifdef CONFIG_TLS_INTERNAL_CLIENT + if (conn->client) { + return tlsv1_client_decrypt(conn->client, wpabuf_head(in_data), + wpabuf_len(in_data), + need_more_data); + } +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (conn->server) { + struct wpabuf *buf; + int res; + buf = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); + if (buf == NULL) + return NULL; + res = tlsv1_server_decrypt(conn->server, wpabuf_head(in_data), + wpabuf_len(in_data), + wpabuf_mhead(buf), + wpabuf_size(buf)); + if (res < 0) { + wpabuf_free(buf); + return NULL; + } + wpabuf_put(buf, res); + return buf; + } +#endif /* CONFIG_TLS_INTERNAL_SERVER */ + return NULL; +} + + +int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) +{ +#ifdef CONFIG_TLS_INTERNAL_CLIENT + if (conn->client) + return tlsv1_client_resumed(conn->client); +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (conn->server) + return tlsv1_server_resumed(conn->server); +#endif /* CONFIG_TLS_INTERNAL_SERVER */ + return -1; +} + + +int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, + u8 *ciphers) +{ +#ifdef CONFIG_TLS_INTERNAL_CLIENT + if (conn->client) + return tlsv1_client_set_cipher_list(conn->client, ciphers); +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (conn->server) + return tlsv1_server_set_cipher_list(conn->server, ciphers); +#endif /* CONFIG_TLS_INTERNAL_SERVER */ + return -1; +} + + +int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, + char *buf, size_t buflen) +{ + if (conn == NULL) + return -1; +#ifdef CONFIG_TLS_INTERNAL_CLIENT + if (conn->client) + return tlsv1_client_get_cipher(conn->client, buf, buflen); +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (conn->server) + return tlsv1_server_get_cipher(conn->server, buf, buflen); +#endif /* CONFIG_TLS_INTERNAL_SERVER */ + return -1; +} + + +int tls_connection_enable_workaround(void *tls_ctx, + struct tls_connection *conn) +{ + return -1; +} + + +int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, + int ext_type, const u8 *data, + size_t data_len) +{ +#ifdef CONFIG_TLS_INTERNAL_CLIENT + if (conn->client) { + return tlsv1_client_hello_ext(conn->client, ext_type, + data, data_len); + } +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ + return -1; +} + + +int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) +{ + return 0; +} + + +int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) +{ + return 0; +} + + +int tls_connection_get_write_alerts(void *tls_ctx, + struct tls_connection *conn) +{ + return 0; +} + + +int tls_connection_get_keyblock_size(void *tls_ctx, + struct tls_connection *conn) +{ +#ifdef CONFIG_TLS_INTERNAL_CLIENT + if (conn->client) + return tlsv1_client_get_keyblock_size(conn->client); +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (conn->server) + return tlsv1_server_get_keyblock_size(conn->server); +#endif /* CONFIG_TLS_INTERNAL_SERVER */ + return -1; +} + + +unsigned int tls_capabilities(void *tls_ctx) +{ + return 0; +} + + +int tls_connection_set_session_ticket_cb(void *tls_ctx, + struct tls_connection *conn, + tls_session_ticket_cb cb, + void *ctx) +{ +#ifdef CONFIG_TLS_INTERNAL_CLIENT + if (conn->client) { + tlsv1_client_set_session_ticket_cb(conn->client, cb, ctx); + return 0; + } +#endif /* CONFIG_TLS_INTERNAL_CLIENT */ +#ifdef CONFIG_TLS_INTERNAL_SERVER + if (conn->server) { + tlsv1_server_set_session_ticket_cb(conn->server, cb, ctx); + return 0; + } +#endif /* CONFIG_TLS_INTERNAL_SERVER */ + return -1; +} + + + +/** + * tls_prf_sha1_md5 - Pseudo-Random Function for TLS (TLS-PRF, RFC 2246) + * @secret: Key for PRF + * @secret_len: Length of the key in bytes + * @label: A unique label for each purpose of the PRF + * @seed: Seed value to bind into the key + * @seed_len: Length of the seed + * @out: Buffer for the generated pseudo-random key + * @outlen: Number of bytes of key to generate + * Returns: 0 on success, -1 on failure. + * + * This function is used to derive new, cryptographically separate keys from a + * given key in TLS. This PRF is defined in RFC 2246, Chapter 5. + */ +int tls_prf_sha1_md5(const u8 *secret, size_t secret_len, const char *label, + const u8 *seed, size_t seed_len, u8 *out, size_t outlen) +{ + size_t L_S1, L_S2, i; + const u8 *S1, *S2; + u8 A_MD5[MD5_MAC_LEN], A_SHA1[SHA1_MAC_LEN]; + u8 P_MD5[MD5_MAC_LEN], P_SHA1[SHA1_MAC_LEN]; + int MD5_pos, SHA1_pos; + const u8 *MD5_addr[3]; + size_t MD5_len[3]; + const unsigned char *SHA1_addr[3]; + size_t SHA1_len[3]; + + if (secret_len & 1) + return -1; + + MD5_addr[0] = A_MD5; + MD5_len[0] = MD5_MAC_LEN; + MD5_addr[1] = (unsigned char *) label; + MD5_len[1] = os_strlen(label); + MD5_addr[2] = seed; + MD5_len[2] = seed_len; + + SHA1_addr[0] = A_SHA1; + SHA1_len[0] = SHA1_MAC_LEN; + SHA1_addr[1] = (unsigned char *) label; + SHA1_len[1] = os_strlen(label); + SHA1_addr[2] = seed; + SHA1_len[2] = seed_len; + + /* RFC 2246, Chapter 5 + * A(0) = seed, A(i) = HMAC(secret, A(i-1)) + * P_hash = HMAC(secret, A(1) + seed) + HMAC(secret, A(2) + seed) + .. + * PRF = P_MD5(S1, label + seed) XOR P_SHA-1(S2, label + seed) + */ + + L_S1 = L_S2 = (secret_len + 1) / 2; + S1 = secret; + S2 = secret + L_S1; + if (secret_len & 1) { + /* The last byte of S1 will be shared with S2 */ + S2--; + } + + hmac_md5_vector(S1, L_S1, 2, &MD5_addr[1], &MD5_len[1], A_MD5); + hmac_sha1_vector(S2, L_S2, 2, &SHA1_addr[1], &SHA1_len[1], A_SHA1); + + MD5_pos = MD5_MAC_LEN; + SHA1_pos = SHA1_MAC_LEN; + for (i = 0; i < outlen; i++) { + if (MD5_pos == MD5_MAC_LEN) { + hmac_md5_vector(S1, L_S1, 3, MD5_addr, MD5_len, P_MD5); + MD5_pos = 0; + hmac_md5(S1, L_S1, A_MD5, MD5_MAC_LEN, A_MD5); + } + if (SHA1_pos == SHA1_MAC_LEN) { + hmac_sha1_vector(S2, L_S2, 3, SHA1_addr, SHA1_len, + P_SHA1); + SHA1_pos = 0; + hmac_sha1(S2, L_S2, A_SHA1, SHA1_MAC_LEN, A_SHA1); + } + + out[i] = P_MD5[MD5_pos] ^ P_SHA1[SHA1_pos]; + + MD5_pos++; + SHA1_pos++; + } + + return 0; +} diff --git a/components/wpa_supplicant/src/wpa2/tls/tlsv1_client.c b/components/wpa_supplicant/src/wpa2/tls/tlsv1_client.c new file mode 100644 index 0000000000..5283af2c41 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/tls/tlsv1_client.c @@ -0,0 +1,837 @@ +/* + * TLS v1.0/v1.1/v1.2 client (RFC 2246, RFC 4346, RFC 5246) + * Copyright (c) 2006-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "crypto/sha1.h" +#include "wpa2/tls/tls.h" +#include "wpa2/tls/tlsv1_common.h" +#include "wpa2/tls/tlsv1_record.h" +#include "wpa2/tls/tlsv1_client.h" +#include "wpa2/tls/tlsv1_client_i.h" + +/* TODO: + * Support for a message fragmented across several records (RFC 2246, 6.2.1) + */ + + +void tls_alert(struct tlsv1_client *conn, u8 level, u8 description) +{ + conn->alert_level = level; + conn->alert_description = description; +} + + +void tlsv1_client_free_dh(struct tlsv1_client *conn) +{ + os_free(conn->dh_p); + os_free(conn->dh_g); + os_free(conn->dh_ys); + conn->dh_p = conn->dh_g = conn->dh_ys = NULL; +} + + +int tls_derive_pre_master_secret(u8 *pre_master_secret) +{ + WPA_PUT_BE16(pre_master_secret, TLS_VERSION); + if (os_get_random(pre_master_secret + 2, + TLS_PRE_MASTER_SECRET_LEN - 2)) + return -1; + return 0; +} + + +int tls_derive_keys(struct tlsv1_client *conn, + const u8 *pre_master_secret, size_t pre_master_secret_len) +{ + u8 seed[2 * TLS_RANDOM_LEN]; + u8 key_block[TLS_MAX_KEY_BLOCK_LEN]; + u8 *pos; + size_t key_block_len; + + if (pre_master_secret) { + wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret", + pre_master_secret, pre_master_secret_len); + os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); + os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, + TLS_RANDOM_LEN); + if (tls_prf(conn->rl.tls_version, + pre_master_secret, pre_master_secret_len, + "master secret", seed, 2 * TLS_RANDOM_LEN, + conn->master_secret, TLS_MASTER_SECRET_LEN)) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive " + "master_secret"); + return -1; + } + wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret", + conn->master_secret, TLS_MASTER_SECRET_LEN); + } + + os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); + os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); + key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len); + if (conn->rl.tls_version == TLS_VERSION_1) + key_block_len += 2 * conn->rl.iv_size; + if (tls_prf(conn->rl.tls_version, + conn->master_secret, TLS_MASTER_SECRET_LEN, + "key expansion", seed, 2 * TLS_RANDOM_LEN, + key_block, key_block_len)) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block"); + return -1; + } + wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block", + key_block, key_block_len); + + pos = key_block; + + /* client_write_MAC_secret */ + os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size); + pos += conn->rl.hash_size; + /* server_write_MAC_secret */ + os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size); + pos += conn->rl.hash_size; + + /* client_write_key */ + os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len); + pos += conn->rl.key_material_len; + /* server_write_key */ + os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len); + pos += conn->rl.key_material_len; + + if (conn->rl.tls_version == TLS_VERSION_1) { + /* client_write_IV */ + os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size); + pos += conn->rl.iv_size; + /* server_write_IV */ + os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size); + pos += conn->rl.iv_size; + } else { + /* + * Use IV field to set the mask value for TLS v1.1. A fixed + * mask of zero is used per the RFC 4346, 6.2.3.2 CBC Block + * Cipher option 2a. + */ + os_memset(conn->rl.write_iv, 0, conn->rl.iv_size); + } + + return 0; +} + + +/** + * tlsv1_client_handshake - Process TLS handshake + * @conn: TLSv1 client connection data from tlsv1_client_init() + * @in_data: Input data from TLS peer + * @in_len: Input data length + * @out_len: Length of the output buffer. + * @appl_data: Pointer to application data pointer, or %NULL if dropped + * @appl_data_len: Pointer to variable that is set to appl_data length + * @need_more_data: Set to 1 if more data would be needed to complete + * processing + * Returns: Pointer to output data, %NULL on failure + */ +u8 * tlsv1_client_handshake(struct tlsv1_client *conn, + const u8 *in_data, size_t in_len, + size_t *out_len, u8 **appl_data, + size_t *appl_data_len, int *need_more_data) +{ + const u8 *pos, *end; + u8 *msg = NULL, *in_msg = NULL, *in_pos, *in_end, alert, ct; + size_t in_msg_len; + int no_appl_data; + int used; + + if (need_more_data) + *need_more_data = 0; + + if (conn->state == CLIENT_HELLO) { + if (in_len) + return NULL; + return tls_send_client_hello(conn, out_len); + } + + if (conn->partial_input) { + if (wpabuf_resize(&conn->partial_input, in_len) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " + "memory for pending record"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + goto failed; + } + wpabuf_put_data(conn->partial_input, in_data, in_len); + in_data = wpabuf_head(conn->partial_input); + in_len = wpabuf_len(conn->partial_input); + } + + if (in_data == NULL || in_len == 0) + return NULL; + + pos = in_data; + end = in_data + in_len; + in_msg = os_malloc(in_len); + if (in_msg == NULL) + return NULL; + + /* Each received packet may include multiple records */ + while (pos < end) { + in_msg_len = in_len; + used = tlsv1_record_receive(&conn->rl, pos, end - pos, + in_msg, &in_msg_len, &alert); + if (used < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Processing received " + "record failed"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); + goto failed; + } + if (used == 0) { + struct wpabuf *partial; + wpa_printf(MSG_DEBUG, "TLSv1: Need more data"); + partial = wpabuf_alloc_copy(pos, end - pos); + wpabuf_free(conn->partial_input); + conn->partial_input = partial; + if (conn->partial_input == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to " + "allocate memory for pending " + "record"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + goto failed; + } + os_free(in_msg); + if (need_more_data) + *need_more_data = 1; + return NULL; + } + ct = pos[0]; + + in_pos = in_msg; + in_end = in_msg + in_msg_len; + + /* Each received record may include multiple messages of the + * same ContentType. */ + while (in_pos < in_end) { + in_msg_len = in_end - in_pos; + if (tlsv1_client_process_handshake(conn, ct, in_pos, + &in_msg_len, + appl_data, + appl_data_len) < 0) + goto failed; + in_pos += in_msg_len; + } + + pos += used; + } + + os_free(in_msg); + in_msg = NULL; + + no_appl_data = appl_data == NULL || *appl_data == NULL; + msg = tlsv1_client_handshake_write(conn, out_len, no_appl_data); + +failed: + os_free(in_msg); + if (conn->alert_level) { + wpabuf_free(conn->partial_input); + conn->partial_input = NULL; + conn->state = FAILED; + os_free(msg); + msg = tlsv1_client_send_alert(conn, conn->alert_level, + conn->alert_description, + out_len); + } else if (msg == NULL) { + msg = (u8 *)os_zalloc(1); + *out_len = 0; + } + + if (need_more_data == NULL || !(*need_more_data)) { + wpabuf_free(conn->partial_input); + conn->partial_input = NULL; + } + + return msg; +} + + +/** + * tlsv1_client_encrypt - Encrypt data into TLS tunnel + * @conn: TLSv1 client connection data from tlsv1_client_init() + * @in_data: Pointer to plaintext data to be encrypted + * @in_len: Input buffer length + * @out_data: Pointer to output buffer (encrypted TLS data) + * @out_len: Maximum out_data length + * Returns: Number of bytes written to out_data, -1 on failure + * + * This function is used after TLS handshake has been completed successfully to + * send data in the encrypted tunnel. + */ +int tlsv1_client_encrypt(struct tlsv1_client *conn, + const u8 *in_data, size_t in_len, + u8 *out_data, size_t out_len) +{ + size_t rlen; + + wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData", + in_data, in_len); + + if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA, + out_data, out_len, in_data, in_len, &rlen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + return rlen; +} + + +/** + * tlsv1_client_decrypt - Decrypt data from TLS tunnel + * @conn: TLSv1 client connection data from tlsv1_client_init() + * @in_data: Pointer to input buffer (encrypted TLS data) + * @in_len: Input buffer length + * @need_more_data: Set to 1 if more data would be needed to complete + * processing + * Returns: Decrypted data or %NULL on failure + * + * This function is used after TLS handshake has been completed successfully to + * receive data from the encrypted tunnel. + */ +struct wpabuf * tlsv1_client_decrypt(struct tlsv1_client *conn, + const u8 *in_data, size_t in_len, + int *need_more_data) +{ + const u8 *in_end, *pos; + int used; + u8 alert, *out_pos, ct; + size_t olen; + struct wpabuf *buf = NULL; + + if (need_more_data) + *need_more_data = 0; + + if (conn->partial_input) { + if (wpabuf_resize(&conn->partial_input, in_len) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " + "memory for pending record"); + alert = TLS_ALERT_INTERNAL_ERROR; + goto fail; + } + wpabuf_put_data(conn->partial_input, in_data, in_len); + in_data = wpabuf_head(conn->partial_input); + in_len = wpabuf_len(conn->partial_input); + } + + pos = in_data; + in_end = in_data + in_len; + + while (pos < in_end) { + ct = pos[0]; + if (wpabuf_resize(&buf, in_end - pos) < 0) { + alert = TLS_ALERT_INTERNAL_ERROR; + goto fail; + } + out_pos = wpabuf_put(buf, 0); + olen = wpabuf_tailroom(buf); + used = tlsv1_record_receive(&conn->rl, pos, in_end - pos, + out_pos, &olen, &alert); + if (used < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing " + "failed"); + goto fail; + } + if (used == 0) { + struct wpabuf *partial; + wpa_printf(MSG_DEBUG, "TLSv1: Need more data"); + partial = wpabuf_alloc_copy(pos, in_end - pos); + wpabuf_free(conn->partial_input); + conn->partial_input = partial; + if (conn->partial_input == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to " + "allocate memory for pending " + "record"); + alert = TLS_ALERT_INTERNAL_ERROR; + goto fail; + } + if (need_more_data) + *need_more_data = 1; + return buf; + } + + if (ct == TLS_CONTENT_TYPE_ALERT) { + if (olen < 2) { + wpa_printf(MSG_DEBUG, "TLSv1: Alert " + "underflow"); + alert = TLS_ALERT_DECODE_ERROR; + goto fail; + } + wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", + out_pos[0], out_pos[1]); + if (out_pos[0] == TLS_ALERT_LEVEL_WARNING) { + /* Continue processing */ + pos += used; + continue; + } + + alert = out_pos[1]; + goto fail; + } + + if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type " + "0x%x when decrypting application data", + pos[0]); + alert = TLS_ALERT_UNEXPECTED_MESSAGE; + goto fail; + } + + wpabuf_put(buf, olen); + + pos += used; + } + + wpabuf_free(conn->partial_input); + conn->partial_input = NULL; + return buf; + +fail: + wpabuf_free(buf); + wpabuf_free(conn->partial_input); + conn->partial_input = NULL; + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); + return NULL; +} + + +/** + * tlsv1_client_global_init - Initialize TLSv1 client + * Returns: 0 on success, -1 on failure + * + * This function must be called before using any other TLSv1 client functions. + */ +int tlsv1_client_global_init(void) +{ + return crypto_global_init(); +} + + +/** + * tlsv1_client_global_deinit - Deinitialize TLSv1 client + * + * This function can be used to deinitialize the TLSv1 client that was + * initialized by calling tlsv1_client_global_init(). No TLSv1 client functions + * can be called after this before calling tlsv1_client_global_init() again. + */ +void tlsv1_client_global_deinit(void) +{ + crypto_global_deinit(); +} + + +/** + * tlsv1_client_init - Initialize TLSv1 client connection + * Returns: Pointer to TLSv1 client connection data or %NULL on failure + */ +struct tlsv1_client * tlsv1_client_init(void) +{ + struct tlsv1_client *conn; + size_t count; + u16 *suites; + + conn = (struct tlsv1_client *)os_zalloc(sizeof(*conn)); + if (conn == NULL) + return NULL; + + conn->state = CLIENT_HELLO; + + if (tls_verify_hash_init(&conn->verify) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify " + "hash"); + os_free(conn); + return NULL; + } + + count = 0; + suites = conn->cipher_suites; + suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA256; + suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; + suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA256; + suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; + suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; + suites[count++] = TLS_RSA_WITH_RC4_128_SHA; + suites[count++] = TLS_RSA_WITH_RC4_128_MD5; + conn->num_cipher_suites = count; + + conn->rl.tls_version = TLS_VERSION; + + return conn; +} + + +/** + * tlsv1_client_deinit - Deinitialize TLSv1 client connection + * @conn: TLSv1 client connection data from tlsv1_client_init() + */ +void tlsv1_client_deinit(struct tlsv1_client *conn) +{ + crypto_public_key_free(conn->server_rsa_key); + tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); + tlsv1_record_change_write_cipher(&conn->rl); + tlsv1_record_change_read_cipher(&conn->rl); + tls_verify_hash_free(&conn->verify); + os_free(conn->client_hello_ext); + tlsv1_client_free_dh(conn); + tlsv1_cred_free(conn->cred); + wpabuf_free(conn->partial_input); + os_free(conn); +} + + +/** + * tlsv1_client_established - Check whether connection has been established + * @conn: TLSv1 client connection data from tlsv1_client_init() + * Returns: 1 if connection is established, 0 if not + */ +int tlsv1_client_established(struct tlsv1_client *conn) +{ + return conn->state == ESTABLISHED; +} + + +/** + * tlsv1_client_prf - Use TLS-PRF to derive keying material + * @conn: TLSv1 client connection data from tlsv1_client_init() + * @label: Label (e.g., description of the key) for PRF + * @server_random_first: seed is 0 = client_random|server_random, + * 1 = server_random|client_random + * @out: Buffer for output data from TLS-PRF + * @out_len: Length of the output buffer + * Returns: 0 on success, -1 on failure + */ +int tlsv1_client_prf(struct tlsv1_client *conn, const char *label, + int server_random_first, u8 *out, size_t out_len) +{ + u8 seed[2 * TLS_RANDOM_LEN]; + + if (conn->state != ESTABLISHED) + return -1; + + if (server_random_first) { + os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); + os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, + TLS_RANDOM_LEN); + } else { + os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); + os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, + TLS_RANDOM_LEN); + } + + return tls_prf(conn->rl.tls_version, + conn->master_secret, TLS_MASTER_SECRET_LEN, + label, seed, 2 * TLS_RANDOM_LEN, out, out_len); +} + + +/** + * tlsv1_client_get_cipher - Get current cipher name + * @conn: TLSv1 client connection data from tlsv1_client_init() + * @buf: Buffer for the cipher name + * @buflen: buf size + * Returns: 0 on success, -1 on failure + * + * Get the name of the currently used cipher. + */ +int tlsv1_client_get_cipher(struct tlsv1_client *conn, char *buf, + size_t buflen) +{ +#ifndef ESPRESSIF_USE + char *cipher; + + switch (conn->rl.cipher_suite) { + case TLS_RSA_WITH_RC4_128_MD5: + cipher = "RC4-MD5"; + break; + case TLS_RSA_WITH_RC4_128_SHA: + cipher = "RC4-SHA"; + break; + case TLS_RSA_WITH_DES_CBC_SHA: + cipher = "DES-CBC-SHA"; + break; + case TLS_RSA_WITH_3DES_EDE_CBC_SHA: + cipher = "DES-CBC3-SHA"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA256: + cipher = "ADH-AES-128-SHA256"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + cipher = "ADH-AES-128-SHA"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA: + cipher = "AES-256-SHA"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA256: + cipher = "AES-256-SHA256"; + break; + case TLS_RSA_WITH_AES_128_CBC_SHA: + cipher = "AES-128-SHA"; + break; + case TLS_RSA_WITH_AES_128_CBC_SHA256: + cipher = "AES-128-SHA256"; + break; + default: + return -1; + } + + os_memcpy((u8 *)buf, (u8 *)cipher, buflen); + + return 0; +#else + char cipher[20]; + + switch (conn->rl.cipher_suite) { + case TLS_RSA_WITH_RC4_128_MD5: + strcpy(cipher, "RC4-MD5"); + break; + case TLS_RSA_WITH_RC4_128_SHA: + strcpy(cipher, "RC4-SHA"); + break; + case TLS_RSA_WITH_DES_CBC_SHA: + strcpy(cipher, "DES-CBC-SHA"); + break; + case TLS_RSA_WITH_3DES_EDE_CBC_SHA: + strcpy(cipher, "DES-CBC3-SHA"); + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA256: + strcpy(cipher, "ADH-AES-128-SHA256"); + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + strcpy(cipher, "ADH-AES-128-SHA"); + break; + case TLS_RSA_WITH_AES_256_CBC_SHA: + strcpy(cipher, "AES-256-SHA"); + break; + case TLS_RSA_WITH_AES_256_CBC_SHA256: + strcpy(cipher, "AES-256-SHA256"); + break; + case TLS_RSA_WITH_AES_128_CBC_SHA: + strcpy(cipher, "AES-128-SHA"); + break; + case TLS_RSA_WITH_AES_128_CBC_SHA256: + strcpy(cipher, "AES-128-SHA256"); + break; + default: + return -1; + } + + os_memcpy((u8 *)buf, (u8 *)cipher, buflen); + + return 0; +#endif +} + + +/** + * tlsv1_client_shutdown - Shutdown TLS connection + * @conn: TLSv1 client connection data from tlsv1_client_init() + * Returns: 0 on success, -1 on failure + */ +int tlsv1_client_shutdown(struct tlsv1_client *conn) +{ + conn->state = CLIENT_HELLO; + + if (tls_verify_hash_init(&conn->verify) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify " + "hash"); + return -1; + } + + tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); + tlsv1_record_change_write_cipher(&conn->rl); + tlsv1_record_change_read_cipher(&conn->rl); + + conn->certificate_requested = 0; + crypto_public_key_free(conn->server_rsa_key); + conn->server_rsa_key = NULL; + conn->session_resumed = 0; + + return 0; +} + + +/** + * tlsv1_client_resumed - Was session resumption used + * @conn: TLSv1 client connection data from tlsv1_client_init() + * Returns: 1 if current session used session resumption, 0 if not + */ +int tlsv1_client_resumed(struct tlsv1_client *conn) +{ + return !!conn->session_resumed; +} + + +/** + * tlsv1_client_hello_ext - Set TLS extension for ClientHello + * @conn: TLSv1 client connection data from tlsv1_client_init() + * @ext_type: Extension type + * @data: Extension payload (%NULL to remove extension) + * @data_len: Extension payload length + * Returns: 0 on success, -1 on failure + */ +int tlsv1_client_hello_ext(struct tlsv1_client *conn, int ext_type, + const u8 *data, size_t data_len) +{ + u8 *pos; + + conn->session_ticket_included = 0; + os_free(conn->client_hello_ext); + conn->client_hello_ext = NULL; + conn->client_hello_ext_len = 0; + + if (data == NULL || data_len == 0) + return 0; + + pos = conn->client_hello_ext = os_malloc(6 + data_len); + if (pos == NULL) + return -1; + + WPA_PUT_BE16(pos, 4 + data_len); + pos += 2; + WPA_PUT_BE16(pos, ext_type); + pos += 2; + WPA_PUT_BE16(pos, data_len); + pos += 2; + os_memcpy(pos, data, data_len); + conn->client_hello_ext_len = 6 + data_len; + + if (ext_type == TLS_EXT_PAC_OPAQUE) { + conn->session_ticket_included = 1; + wpa_printf(MSG_DEBUG, "TLSv1: Using session ticket"); + } + + return 0; +} + + +/** + * tlsv1_client_get_keys - Get master key and random data from TLS connection + * @conn: TLSv1 client connection data from tlsv1_client_init() + * @keys: Structure of key/random data (filled on success) + * Returns: 0 on success, -1 on failure + */ +int tlsv1_client_get_keys(struct tlsv1_client *conn, struct tls_keys *keys) +{ + os_memset(keys, 0, sizeof(*keys)); + if (conn->state == CLIENT_HELLO) + return -1; + + keys->client_random = conn->client_random; + keys->client_random_len = TLS_RANDOM_LEN; + + if (conn->state != SERVER_HELLO) { + keys->server_random = conn->server_random; + keys->server_random_len = TLS_RANDOM_LEN; + keys->master_key = conn->master_secret; + keys->master_key_len = TLS_MASTER_SECRET_LEN; + } + + return 0; +} + + +/** + * tlsv1_client_get_keyblock_size - Get TLS key_block size + * @conn: TLSv1 client connection data from tlsv1_client_init() + * Returns: Size of the key_block for the negotiated cipher suite or -1 on + * failure + */ +int tlsv1_client_get_keyblock_size(struct tlsv1_client *conn) +{ + if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO) + return -1; + + return 2 * (conn->rl.hash_size + conn->rl.key_material_len + + conn->rl.iv_size); +} + + +/** + * tlsv1_client_set_cipher_list - Configure acceptable cipher suites + * @conn: TLSv1 client connection data from tlsv1_client_init() + * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers + * (TLS_CIPHER_*). + * Returns: 0 on success, -1 on failure + */ +int tlsv1_client_set_cipher_list(struct tlsv1_client *conn, u8 *ciphers) +{ + size_t count; + u16 *suites; + + /* TODO: implement proper configuration of cipher suites */ + if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) { + count = 0; + suites = conn->cipher_suites; + suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA256; + suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA; + suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA256; + suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; + suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA; + suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5; + suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA; + + /* + * Cisco AP (at least 350 and 1200 series) local authentication + * server does not know how to search cipher suites from the + * list and seem to require that the last entry in the list is + * the one that it wants to use. However, TLS specification + * requires the list to be in the client preference order. As a + * workaround, add anon-DH AES-128-SHA1 again at the end of the + * list to allow the Cisco code to find it. + */ + suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; + conn->num_cipher_suites = count; + } + + return 0; +} + + +/** + * tlsv1_client_set_cred - Set client credentials + * @conn: TLSv1 client connection data from tlsv1_client_init() + * @cred: Credentials from tlsv1_cred_alloc() + * Returns: 0 on success, -1 on failure + * + * On success, the client takes ownership of the credentials block and caller + * must not free it. On failure, caller is responsible for freeing the + * credential block. + */ +int tlsv1_client_set_cred(struct tlsv1_client *conn, + struct tlsv1_credentials *cred) +{ + tlsv1_cred_free(conn->cred); + conn->cred = cred; + return 0; +} + + +void tlsv1_client_set_time_checks(struct tlsv1_client *conn, int enabled) +{ + conn->disable_time_checks = !enabled; +} + + +void tlsv1_client_set_session_ticket_cb(struct tlsv1_client *conn, + tlsv1_client_session_ticket_cb cb, + void *ctx) +{ + wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)", + cb, ctx); + conn->session_ticket_cb = cb; + conn->session_ticket_cb_ctx = ctx; +} diff --git a/components/wpa_supplicant/src/wpa2/tls/tlsv1_client_read.c b/components/wpa_supplicant/src/wpa2/tls/tlsv1_client_read.c new file mode 100644 index 0000000000..13330bdbf1 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/tls/tlsv1_client_read.c @@ -0,0 +1,1001 @@ +/* + * TLSv1 client - read handshake message + * Copyright (c) 2006-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "crypto/md5.h" +#include "crypto/sha1.h" +#include "crypto/sha256.h" +#include "wpa2/tls/tls.h" +#include "wpa2/tls/x509v3.h" +#include "wpa2/tls/tlsv1_common.h" +#include "wpa2/tls/tlsv1_record.h" +#include "wpa2/tls/tlsv1_client.h" +#include "wpa2/tls/tlsv1_client_i.h" +#include "wpa2/eap_peer/eap_i.h" + +static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct, + const u8 *in_data, size_t *in_len); +static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct, + const u8 *in_data, size_t *in_len); +static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct, + const u8 *in_data, size_t *in_len); + + +static int tls_process_server_hello(struct tlsv1_client *conn, u8 ct, + const u8 *in_data, size_t *in_len) +{ + const u8 *pos, *end; + size_t left, len, i; + u16 cipher_suite; + u16 tls_version; + + if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " + "received content type 0x%x", ct); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + pos = in_data; + left = *in_len; + + if (left < 4) + goto decode_error; + + /* HandshakeType msg_type */ + if (*pos != TLS_HANDSHAKE_TYPE_SERVER_HELLO) { + wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " + "message %d (expected ServerHello)", *pos); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHello"); + pos++; + /* uint24 length */ + len = WPA_GET_BE24(pos); + pos += 3; + left -= 4; + + if (len > left) + goto decode_error; + + /* body - ServerHello */ + + wpa_hexdump(MSG_MSGDUMP, "TLSv1: ServerHello", pos, len); + end = pos + len; + + /* ProtocolVersion server_version */ + if (end - pos < 2) + goto decode_error; + tls_version = WPA_GET_BE16(pos); + if (!tls_version_ok(tls_version)) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in " + "ServerHello %u.%u", pos[0], pos[1]); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_PROTOCOL_VERSION); + return -1; + } + pos += 2; + + wpa_printf(MSG_DEBUG, "TLSv1: Using TLS v%s", + tls_version_str(tls_version)); + conn->rl.tls_version = tls_version; + + /* Random random */ + if (end - pos < TLS_RANDOM_LEN) + goto decode_error; + + os_memcpy(conn->server_random, pos, TLS_RANDOM_LEN); + pos += TLS_RANDOM_LEN; + wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random", + conn->server_random, TLS_RANDOM_LEN); + + /* SessionID session_id */ + if (end - pos < 1) + goto decode_error; + if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN) + goto decode_error; + if (conn->session_id_len && conn->session_id_len == *pos && + os_memcmp(conn->session_id, pos + 1, conn->session_id_len) == 0) { + pos += 1 + conn->session_id_len; + wpa_printf(MSG_DEBUG, "TLSv1: Resuming old session"); + conn->session_resumed = 1; + } else { + conn->session_id_len = *pos; + pos++; + os_memcpy(conn->session_id, pos, conn->session_id_len); + pos += conn->session_id_len; + } + wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id", + conn->session_id, conn->session_id_len); + + /* CipherSuite cipher_suite */ + if (end - pos < 2) + goto decode_error; + cipher_suite = WPA_GET_BE16(pos); + pos += 2; + for (i = 0; i < conn->num_cipher_suites; i++) { + if (cipher_suite == conn->cipher_suites[i]) + break; + } + if (i == conn->num_cipher_suites) { + wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected " + "cipher suite 0x%04x", cipher_suite); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_ILLEGAL_PARAMETER); + return -1; + } + + if (conn->session_resumed && cipher_suite != conn->prev_cipher_suite) { + wpa_printf(MSG_DEBUG, "TLSv1: Server selected a different " + "cipher suite for a resumed connection (0x%04x != " + "0x%04x)", cipher_suite, conn->prev_cipher_suite); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_ILLEGAL_PARAMETER); + return -1; + } + + if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for " + "record layer"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + conn->prev_cipher_suite = cipher_suite; + + /* CompressionMethod compression_method */ + if (end - pos < 1) + goto decode_error; + if (*pos != TLS_COMPRESSION_NULL) { + wpa_printf(MSG_INFO, "TLSv1: Server selected unexpected " + "compression 0x%02x", *pos); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_ILLEGAL_PARAMETER); + return -1; + } + pos++; + + if (end != pos) { + /* TODO: ServerHello extensions */ + wpa_hexdump(MSG_DEBUG, "TLSv1: Unexpected extra data in the " + "end of ServerHello", pos, end - pos); + goto decode_error; + } + + if (conn->session_ticket_included && conn->session_ticket_cb) { + /* TODO: include SessionTicket extension if one was included in + * ServerHello */ + int res = conn->session_ticket_cb( + conn->session_ticket_cb_ctx, NULL, 0, + conn->client_random, conn->server_random, + conn->master_secret); + if (res < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback " + "indicated failure"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_HANDSHAKE_FAILURE); + return -1; + } + conn->use_session_ticket = !!res; + } + + if ((conn->session_resumed || conn->use_session_ticket) && + tls_derive_keys(conn, NULL, 0)) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + *in_len = end - in_data; + + conn->state = (conn->session_resumed || conn->use_session_ticket) ? + SERVER_CHANGE_CIPHER_SPEC : SERVER_CERTIFICATE; + + return 0; + +decode_error: + wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ServerHello"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); + return -1; +} + + +static int tls_process_certificate(struct tlsv1_client *conn, u8 ct, + const u8 *in_data, size_t *in_len) +{ + const u8 *pos, *end; + size_t left, len, list_len, cert_len, idx; + u8 type; + struct x509_certificate *chain = NULL, *last = NULL, *cert; + int reason; + + if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " + "received content type 0x%x", ct); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + pos = in_data; + left = *in_len; + + if (left < 4) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message " + "(len=%lu)", (unsigned long) left); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); + return -1; + } + + type = *pos++; + len = WPA_GET_BE24(pos); + pos += 3; + left -= 4; + + if (len > left) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message " + "length (len=%lu != left=%lu)", + (unsigned long) len, (unsigned long) left); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); + return -1; + } + + if (type == TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) + return tls_process_server_key_exchange(conn, ct, in_data, + in_len); + if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) + return tls_process_certificate_request(conn, ct, in_data, + in_len); + if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) + return tls_process_server_hello_done(conn, ct, in_data, + in_len); + if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) { + wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " + "message %d (expected Certificate/" + "ServerKeyExchange/CertificateRequest/" + "ServerHelloDone)", type); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + wpa_printf(MSG_DEBUG, "TLSv1: Received Certificate (certificate_list len %lu)", + (unsigned long) len); + + /* + * opaque ASN.1Cert<2^24-1>; + * + * struct { + * ASN.1Cert certificate_list<1..2^24-1>; + * } Certificate; + */ + + end = pos + len; + + if (end - pos < 3) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate " + "(left=%lu)", (unsigned long) left); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); + return -1; + } + + list_len = WPA_GET_BE24(pos); + pos += 3; + + if ((size_t) (end - pos) != list_len) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list " + "length (len=%lu left=%lu)", + (unsigned long) list_len, + (unsigned long) (end - pos)); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); + return -1; + } + + idx = 0; + while (pos < end) { + if (end - pos < 3) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " + "certificate_list"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + x509_certificate_chain_free(chain); + return -1; + } + + cert_len = WPA_GET_BE24(pos); + pos += 3; + + if ((size_t) (end - pos) < cert_len) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate " + "length (len=%lu left=%lu)", + (unsigned long) cert_len, + (unsigned long) (end - pos)); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + x509_certificate_chain_free(chain); + return -1; + } + + wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)", + (unsigned long) idx, (unsigned long) cert_len); + + if (idx == 0) { + crypto_public_key_free(conn->server_rsa_key); + if (tls_parse_cert(pos, cert_len, + &conn->server_rsa_key)) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " + "the certificate"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_BAD_CERTIFICATE); + x509_certificate_chain_free(chain); + return -1; + } + } + + cert = x509_certificate_parse(pos, cert_len); + if (cert == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " + "the certificate"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_BAD_CERTIFICATE); + x509_certificate_chain_free(chain); + return -1; + } + + if (last == NULL) + chain = cert; + else + last->next = cert; + last = cert; + + idx++; + pos += cert_len; + } + + if (conn->cred && + x509_certificate_chain_validate(conn->cred->trusted_certs, chain, + &reason, conn->disable_time_checks) + < 0) { + int tls_reason; + wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain " + "validation failed (reason=%d)", reason); + switch (reason) { + case X509_VALIDATE_BAD_CERTIFICATE: + tls_reason = TLS_ALERT_BAD_CERTIFICATE; + break; + case X509_VALIDATE_UNSUPPORTED_CERTIFICATE: + tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE; + break; + case X509_VALIDATE_CERTIFICATE_REVOKED: + tls_reason = TLS_ALERT_CERTIFICATE_REVOKED; + break; + case X509_VALIDATE_CERTIFICATE_EXPIRED: + tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED; + break; + case X509_VALIDATE_CERTIFICATE_UNKNOWN: + tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN; + break; + case X509_VALIDATE_UNKNOWN_CA: + tls_reason = TLS_ALERT_UNKNOWN_CA; + break; + default: + tls_reason = TLS_ALERT_BAD_CERTIFICATE; + break; + } + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason); + x509_certificate_chain_free(chain); + return -1; + } + + x509_certificate_chain_free(chain); + + *in_len = end - in_data; + conn->state = SERVER_KEY_EXCHANGE; + + return 0; +} + + +static int tlsv1_process_diffie_hellman(struct tlsv1_client *conn, + const u8 *buf, size_t len) +{ + const u8 *pos, *end; + + tlsv1_client_free_dh(conn); + + pos = buf; + end = buf + len; + + if (end - pos < 3) + goto fail; + conn->dh_p_len = WPA_GET_BE16(pos); + pos += 2; + if (conn->dh_p_len == 0 || end - pos < (int) conn->dh_p_len) { + wpa_printf(MSG_DEBUG, "TLSv1: Invalid dh_p length %lu", + (unsigned long) conn->dh_p_len); + goto fail; + } + conn->dh_p = os_malloc(conn->dh_p_len); + if (conn->dh_p == NULL) + goto fail; + os_memcpy(conn->dh_p, pos, conn->dh_p_len); + pos += conn->dh_p_len; + wpa_hexdump(MSG_DEBUG, "TLSv1: DH p (prime)", + conn->dh_p, conn->dh_p_len); + + if (end - pos < 3) + goto fail; + conn->dh_g_len = WPA_GET_BE16(pos); + pos += 2; + if (conn->dh_g_len == 0 || end - pos < (int) conn->dh_g_len) + goto fail; + conn->dh_g = os_malloc(conn->dh_g_len); + if (conn->dh_g == NULL) + goto fail; + os_memcpy(conn->dh_g, pos, conn->dh_g_len); + pos += conn->dh_g_len; + wpa_hexdump(MSG_DEBUG, "TLSv1: DH g (generator)", + conn->dh_g, conn->dh_g_len); + if (conn->dh_g_len == 1 && conn->dh_g[0] < 2) + goto fail; + + if (end - pos < 3) + goto fail; + conn->dh_ys_len = WPA_GET_BE16(pos); + pos += 2; + if (conn->dh_ys_len == 0 || end - pos < (int) conn->dh_ys_len) + goto fail; + conn->dh_ys = os_malloc(conn->dh_ys_len); + if (conn->dh_ys == NULL) + goto fail; + os_memcpy(conn->dh_ys, pos, conn->dh_ys_len); + pos += conn->dh_ys_len; + wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)", + conn->dh_ys, conn->dh_ys_len); + + return 0; + +fail: + wpa_printf(MSG_DEBUG, "TLSv1: Processing DH params failed"); + tlsv1_client_free_dh(conn); + return -1; +} + + +static int tls_process_server_key_exchange(struct tlsv1_client *conn, u8 ct, + const u8 *in_data, size_t *in_len) +{ + const u8 *pos, *end; + size_t left, len; + u8 type; + const struct tls_cipher_suite *suite; + + if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " + "received content type 0x%x", ct); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + pos = in_data; + left = *in_len; + + if (left < 4) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerKeyExchange " + "(Left=%lu)", (unsigned long) left); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); + return -1; + } + + type = *pos++; + len = WPA_GET_BE24(pos); + pos += 3; + left -= 4; + + if (len > left) { + wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerKeyExchange " + "length (len=%lu != left=%lu)", + (unsigned long) len, (unsigned long) left); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); + return -1; + } + + end = pos + len; + + if (type == TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) + return tls_process_certificate_request(conn, ct, in_data, + in_len); + if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) + return tls_process_server_hello_done(conn, ct, in_data, + in_len); + if (type != TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE) { + wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " + "message %d (expected ServerKeyExchange/" + "CertificateRequest/ServerHelloDone)", type); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + wpa_printf(MSG_DEBUG, "TLSv1: Received ServerKeyExchange"); + + if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) { + wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not allowed " + "with the selected cipher suite"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + wpa_hexdump(MSG_DEBUG, "TLSv1: ServerKeyExchange", pos, len); + suite = tls_get_cipher_suite(conn->rl.cipher_suite); + if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) { + if (tlsv1_process_diffie_hellman(conn, pos, len) < 0) { + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + } else { + wpa_printf(MSG_DEBUG, "TLSv1: UnexpectedServerKeyExchange"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + *in_len = end - in_data; + conn->state = SERVER_CERTIFICATE_REQUEST; + + return 0; +} + + +static int tls_process_certificate_request(struct tlsv1_client *conn, u8 ct, + const u8 *in_data, size_t *in_len) +{ + const u8 *pos, *end; + size_t left, len; + u8 type; + + if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " + "received content type 0x%x", ct); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + pos = in_data; + left = *in_len; + + if (left < 4) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateRequest " + "(left=%lu)", (unsigned long) left); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); + return -1; + } + + type = *pos++; + len = WPA_GET_BE24(pos); + pos += 3; + left -= 4; + + if (len > left) { + wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in CertificateRequest " + "length (len=%lu != left=%lu)", + (unsigned long) len, (unsigned long) left); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); + return -1; + } + + end = pos + len; + + if (type == TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) + return tls_process_server_hello_done(conn, ct, in_data, + in_len); + if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST) { + wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " + "message %d (expected CertificateRequest/" + "ServerHelloDone)", type); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateRequest"); + + conn->certificate_requested = 1; + + *in_len = end - in_data; + conn->state = SERVER_HELLO_DONE; + + return 0; +} + + +static int tls_process_server_hello_done(struct tlsv1_client *conn, u8 ct, + const u8 *in_data, size_t *in_len) +{ + const u8 *pos, *end; + size_t left, len; + u8 type; + + if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " + "received content type 0x%x", ct); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + pos = in_data; + left = *in_len; + + if (left < 4) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short ServerHelloDone " + "(left=%lu)", (unsigned long) left); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); + return -1; + } + + type = *pos++; + len = WPA_GET_BE24(pos); + pos += 3; + left -= 4; + + if (len > left) { + wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ServerHelloDone " + "length (len=%lu != left=%lu)", + (unsigned long) len, (unsigned long) left); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); + return -1; + } + end = pos + len; + + if (type != TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE) { + wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " + "message %d (expected ServerHelloDone)", type); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + wpa_printf(MSG_DEBUG, "TLSv1: Received ServerHelloDone"); + + *in_len = end - in_data; + conn->state = CLIENT_KEY_EXCHANGE; + + return 0; +} + + +static int tls_process_server_change_cipher_spec(struct tlsv1_client *conn, + u8 ct, const u8 *in_data, + size_t *in_len) +{ + const u8 *pos; + size_t left; + + if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " + "received content type 0x%x", ct); + if (conn->use_session_ticket) { + int res; + wpa_printf(MSG_DEBUG, "TLSv1: Server may have " + "rejected SessionTicket"); + conn->use_session_ticket = 0; + + /* Notify upper layers that SessionTicket failed */ + res = conn->session_ticket_cb( + conn->session_ticket_cb_ctx, NULL, 0, NULL, + NULL, NULL); + if (res < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket " + "callback indicated failure"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_HANDSHAKE_FAILURE); + return -1; + } + printf("[Debug] set the state to server certificate \n"); + conn->state = SERVER_CERTIFICATE; + return tls_process_certificate(conn, ct, in_data, + in_len); + } + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + pos = in_data; + left = *in_len; + + if (left < 1) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); + return -1; + } + + if (*pos != TLS_CHANGE_CIPHER_SPEC) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " + "received data 0x%x", *pos); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec"); + if (tlsv1_record_change_read_cipher(&conn->rl) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher " + "for record layer"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + *in_len = pos + 1 - in_data; + conn->state = SERVER_FINISHED; + + return 0; +} + + +static int tls_process_server_finished(struct tlsv1_client *conn, u8 ct, + const u8 *in_data, size_t *in_len) +{ + const u8 *pos, *end; + size_t left, len, hlen; + u8 verify_data[TLS_VERIFY_DATA_LEN]; + u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; + + if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; " + "received content type 0x%x", ct); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + pos = in_data; + left = *in_len; + + if (left < 4) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for " + "Finished", + (unsigned long) left); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + + if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received " + "type 0x%x", pos[0]); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + len = WPA_GET_BE24(pos + 1); + + pos += 4; + left -= 4; + + if (len > left) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished " + "(len=%lu > left=%lu)", + (unsigned long) len, (unsigned long) left); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + end = pos + len; + if (len != TLS_VERIFY_DATA_LEN) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length " + "in Finished: %lu (expected %d)", + (unsigned long) len, TLS_VERIFY_DATA_LEN); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished", + pos, TLS_VERIFY_DATA_LEN); + +#ifdef CONFIG_TLSV12 + if (conn->rl.tls_version >= TLS_VERSION_1_2) { + hlen = SHA256_MAC_LEN; + if (wpa2_crypto_funcs.crypto_hash_finish) { + if (conn->verify.sha256_server == NULL || + wpa_crypto_funcs.crypto_hash_finish(conn->verify.sha256_server, hash, &hlen) < 0) { + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); + conn->verify.sha256_server = NULL; + return -1; + } + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register crypto_hash_finish function!\r\n", __FUNCTION__); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_INTERNAL_ERROR); + conn->verify.sha256_server = NULL; + return -1; + } + conn->verify.sha256_server = NULL; + } else { +#endif /* CONFIG_TLSV12 */ + + hlen = MD5_MAC_LEN; + if (conn->verify.md5_server == NULL || + crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + conn->verify.md5_server = NULL; + crypto_hash_finish(conn->verify.sha1_server, NULL, NULL); + conn->verify.sha1_server = NULL; + return -1; + } + conn->verify.md5_server = NULL; + hlen = SHA1_MAC_LEN; + if (conn->verify.sha1_server == NULL || + crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN, + &hlen) < 0) { + conn->verify.sha1_server = NULL; + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + conn->verify.sha1_server = NULL; + hlen = MD5_MAC_LEN + SHA1_MAC_LEN; + +#ifdef CONFIG_TLSV12 + } +#endif /* CONFIG_TLSV12 */ + + if (tls_prf(conn->rl.tls_version, + conn->master_secret, TLS_MASTER_SECRET_LEN, + "server finished", hash, hlen, + verify_data, TLS_VERIFY_DATA_LEN)) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECRYPT_ERROR); + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)", + verify_data, TLS_VERIFY_DATA_LEN); + + if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) { + wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data"); + return -1; + } + + wpa_printf(MSG_DEBUG, "TLSv1: Received Finished"); + + *in_len = end - in_data; + + conn->state = (conn->session_resumed || conn->use_session_ticket) ? + CHANGE_CIPHER_SPEC : ACK_FINISHED; + return 0; +} + + +static int tls_process_application_data(struct tlsv1_client *conn, u8 ct, + const u8 *in_data, size_t *in_len, + u8 **out_data, size_t *out_len) +{ + const u8 *pos; + size_t left; + + if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected Application Data; " + "received content type 0x%x", ct); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + pos = in_data; + left = *in_len; + + wpa_hexdump(MSG_DEBUG, "TLSv1: Application Data included in Handshake", + pos, left); + + *out_data = os_malloc(left); + if (*out_data) { + os_memcpy(*out_data, pos, left); + *out_len = left; + } + + return 0; +} + + +int tlsv1_client_process_handshake(struct tlsv1_client *conn, u8 ct, + const u8 *buf, size_t *len, + u8 **out_data, size_t *out_len) +{ + if (ct == TLS_CONTENT_TYPE_ALERT) { + if (*len < 2) { + wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", + buf[0], buf[1]); + *len = 2; + conn->state = FAILED; + return -1; + } + + if (ct == TLS_CONTENT_TYPE_HANDSHAKE && *len >= 4 && + buf[0] == TLS_HANDSHAKE_TYPE_HELLO_REQUEST) { + size_t hr_len = WPA_GET_BE24(buf + 1); + if (hr_len > *len - 4) { + wpa_printf(MSG_DEBUG, "TLSv1: HelloRequest underflow"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + wpa_printf(MSG_DEBUG, "TLSv1: Ignored HelloRequest"); + *len = 4 + hr_len; + return 0; + } + + switch (conn->state) { + case SERVER_HELLO: + if (tls_process_server_hello(conn, ct, buf, len)) + return -1; + break; + case SERVER_CERTIFICATE: + if (tls_process_certificate(conn, ct, buf, len)) + return -1; + break; + case SERVER_KEY_EXCHANGE: + if (tls_process_server_key_exchange(conn, ct, buf, len)) + return -1; + break; + case SERVER_CERTIFICATE_REQUEST: + if (tls_process_certificate_request(conn, ct, buf, len)) + return -1; + break; + case SERVER_HELLO_DONE: + if (tls_process_server_hello_done(conn, ct, buf, len)) + return -1; + break; + case SERVER_CHANGE_CIPHER_SPEC: + if (tls_process_server_change_cipher_spec(conn, ct, buf, len)) + return -1; + break; + case SERVER_FINISHED: + if (tls_process_server_finished(conn, ct, buf, len)) { + printf("[debug] server finish process fall \n"); + return -1; + } + break; + case ACK_FINISHED: + if (out_data && + tls_process_application_data(conn, ct, buf, len, out_data, + out_len)) + return -1; + break; + default: + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d " + "while processing received message", + conn->state); + return -1; + } + + if (ct == TLS_CONTENT_TYPE_HANDSHAKE) { + tls_verify_hash_add(&conn->verify, buf, *len); + } + + return 0; +} diff --git a/components/wpa_supplicant/src/wpa2/tls/tlsv1_client_write.c b/components/wpa_supplicant/src/wpa2/tls/tlsv1_client_write.c new file mode 100644 index 0000000000..55644a046c --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/tls/tlsv1_client_write.c @@ -0,0 +1,901 @@ +/* + * TLSv1 client - write handshake message + * Copyright (c) 2006-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "crypto/md5.h" +#include "crypto/sha1.h" +#include "crypto/sha256.h" +#include "crypto/random.h" +#include "wpa2/tls/tls.h" +#include "wpa2/tls/x509v3.h" +#include "wpa2/tls/tlsv1_common.h" +#include "wpa2/tls/tlsv1_record.h" +#include "wpa2/tls/tlsv1_client.h" +#include "wpa2/tls/tlsv1_client_i.h" + +#include "wpa2/eap_peer/eap_i.h" + +static size_t tls_client_cert_chain_der_len(struct tlsv1_client *conn) +{ + size_t len = 0; + struct x509_certificate *cert; + + if (conn->cred == NULL) + return 0; + + cert = conn->cred->cert; + while (cert) { + len += 3 + cert->cert_len; + if (x509_certificate_self_signed(cert)) + break; + cert = x509_certificate_get_subject(conn->cred->trusted_certs, + &cert->issuer); + } + + return len; +} + + +u8 * tls_send_client_hello(struct tlsv1_client *conn, size_t *out_len) +{ + u8 *hello, *end, *pos, *hs_length, *hs_start, *rhdr; + struct os_time now; + size_t len, i; + + wpa_printf(MSG_DEBUG, "TLSv1: Send ClientHello"); + *out_len = 0; + + os_get_time(&now); + WPA_PUT_BE32(conn->client_random, now.sec); + if (random_get_bytes(conn->client_random + 4, TLS_RANDOM_LEN - 4)) { + wpa_printf(MSG_ERROR, "TLSv1: Could not generate " + "client_random"); + return NULL; + } + wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random", + conn->client_random, TLS_RANDOM_LEN); + + len = 100 + conn->num_cipher_suites * 2 + conn->client_hello_ext_len; + hello = os_malloc(len); + if (hello == NULL) + return NULL; + end = hello + len; + + rhdr = hello; + pos = rhdr + TLS_RECORD_HEADER_LEN; + + /* opaque fragment[TLSPlaintext.length] */ + + /* Handshake */ + hs_start = pos; + /* HandshakeType msg_type */ + *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_HELLO; + /* uint24 length (to be filled) */ + hs_length = pos; + pos += 3; + /* body - ClientHello */ + /* ProtocolVersion client_version */ + WPA_PUT_BE16(pos, TLS_VERSION); + pos += 2; + /* Random random: uint32 gmt_unix_time, opaque random_bytes */ + os_memcpy(pos, conn->client_random, TLS_RANDOM_LEN); + pos += TLS_RANDOM_LEN; + /* SessionID session_id */ + *pos++ = conn->session_id_len; + os_memcpy(pos, conn->session_id, conn->session_id_len); + pos += conn->session_id_len; + /* CipherSuite cipher_suites<2..2^16-1> */ + WPA_PUT_BE16(pos, 2 * conn->num_cipher_suites); + pos += 2; + for (i = 0; i < conn->num_cipher_suites; i++) { + WPA_PUT_BE16(pos, conn->cipher_suites[i]); + pos += 2; + } + /* CompressionMethod compression_methods<1..2^8-1> */ + *pos++ = 1; + *pos++ = TLS_COMPRESSION_NULL; + + if (conn->client_hello_ext) { + os_memcpy(pos, conn->client_hello_ext, + conn->client_hello_ext_len); + pos += conn->client_hello_ext_len; + } + + WPA_PUT_BE24(hs_length, pos - hs_length - 3); + tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); + + if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, + rhdr, end - rhdr, hs_start, pos - hs_start, + out_len) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + os_free(hello); + return NULL; + } + + conn->state = SERVER_HELLO; + + return hello; +} + + +static int tls_write_client_certificate(struct tlsv1_client *conn, + u8 **msgpos, u8 *end) +{ + u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start; + size_t rlen; + struct x509_certificate *cert; + + pos = *msgpos; + + wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate"); + rhdr = pos; + pos += TLS_RECORD_HEADER_LEN; + + /* opaque fragment[TLSPlaintext.length] */ + + /* Handshake */ + hs_start = pos; + /* HandshakeType msg_type */ + *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE; + /* uint24 length (to be filled) */ + hs_length = pos; + pos += 3; + /* body - Certificate */ + /* uint24 length (to be filled) */ + cert_start = pos; + pos += 3; + cert = conn->cred ? conn->cred->cert : NULL; + while (cert) { + if (pos + 3 + cert->cert_len > end) { + wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space " + "for Certificate (cert_len=%lu left=%lu)", + (unsigned long) cert->cert_len, + (unsigned long) (end - pos)); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + WPA_PUT_BE24(pos, cert->cert_len); + pos += 3; + os_memcpy(pos, cert->cert_start, cert->cert_len); + pos += cert->cert_len; + + if (x509_certificate_self_signed(cert)) + break; + cert = x509_certificate_get_subject(conn->cred->trusted_certs, + &cert->issuer); + } + if (conn->cred == NULL || cert == conn->cred->cert || cert == NULL) { + /* + * Client was not configured with all the needed certificates + * to form a full certificate chain. The server may fail to + * validate the chain unless it is configured with all the + * missing CA certificates. + */ + wpa_printf(MSG_DEBUG, "TLSv1: Full client certificate chain " + "not configured - validation may fail"); + } + WPA_PUT_BE24(cert_start, pos - cert_start - 3); + + WPA_PUT_BE24(hs_length, pos - hs_length - 3); + + if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, + rhdr, end - rhdr, hs_start, pos - hs_start, + &rlen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + pos = rhdr + rlen; + + tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); + + *msgpos = pos; + + return 0; +} + + +static int tlsv1_key_x_anon_dh(struct tlsv1_client *conn, u8 **pos, u8 *end) +{ + /* ClientDiffieHellmanPublic */ + u8 *csecret, *csecret_start, *dh_yc, *shared; + size_t csecret_len, dh_yc_len, shared_len; + + csecret_len = conn->dh_p_len; + csecret = os_malloc(csecret_len); + if (csecret == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " + "memory for Yc (Diffie-Hellman)"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + if (random_get_bytes(csecret, csecret_len)) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " + "data for Diffie-Hellman"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + os_free(csecret); + return -1; + } + + if (os_memcmp(csecret, conn->dh_p, csecret_len) > 0) + csecret[0] = 0; /* make sure Yc < p */ + + csecret_start = csecret; + while (csecret_len > 1 && *csecret_start == 0) { + csecret_start++; + csecret_len--; + } + wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH client's secret value", + csecret_start, csecret_len); + + /* Yc = g^csecret mod p */ + dh_yc_len = conn->dh_p_len; + dh_yc = os_malloc(dh_yc_len); + if (dh_yc == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " + "memory for Diffie-Hellman"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + os_free(csecret); + return -1; + } + if (wpa2_crypto_funcs.crypto_mod_exp) { + if(wpa2_crypto_funcs.crypto_mod_exp(conn->dh_g, conn->dh_g_len, + csecret_start, csecret_len, + conn->dh_p, conn->dh_p_len, + dh_yc, &dh_yc_len)) { + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + os_free(csecret); + os_free(dh_yc); + return -1; + } + } else { + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + os_free(csecret); + os_free(dh_yc); + wpa_printf(MSG_ERROR, "Fail to register crypto_mod_exp function!\r\n"); + return -1; + } + + wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", + dh_yc, dh_yc_len); + + WPA_PUT_BE16(*pos, dh_yc_len); + *pos += 2; + if (*pos + dh_yc_len > end) { + wpa_printf(MSG_DEBUG, "TLSv1: Not enough room in the " + "message buffer for Yc"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + os_free(csecret); + os_free(dh_yc); + return -1; + } + os_memcpy(*pos, dh_yc, dh_yc_len); + *pos += dh_yc_len; + os_free(dh_yc); + + shared_len = conn->dh_p_len; + shared = os_malloc(shared_len); + if (shared == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " + "DH"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + os_free(csecret); + return -1; + } + + /* shared = Ys^csecret mod p */ + if (wpa2_crypto_funcs.crypto_mod_exp) { + if(wpa2_crypto_funcs.crypto_mod_exp(conn->dh_ys, conn->dh_ys_len, + csecret_start, csecret_len, + conn->dh_p, conn->dh_p_len, + shared, &shared_len)) { + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + os_free(csecret); + os_free(shared); + return -1; + } + } else { + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + os_free(csecret); + os_free(shared); + wpa_printf(MSG_ERROR, "Fail to register crypto_mod_exp function!\r\n"); + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", + shared, shared_len); + + os_memset(csecret_start, 0, csecret_len); + os_free(csecret); + if (tls_derive_keys(conn, shared, shared_len)) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + os_free(shared); + return -1; + } + os_memset(shared, 0, shared_len); + os_free(shared); + tlsv1_client_free_dh(conn); + return 0; +} + + +static int tlsv1_key_x_rsa(struct tlsv1_client *conn, u8 **pos, u8 *end) +{ + u8 pre_master_secret[TLS_PRE_MASTER_SECRET_LEN]; + size_t clen; + int res; + + if (tls_derive_pre_master_secret(pre_master_secret) < 0 || + tls_derive_keys(conn, pre_master_secret, + TLS_PRE_MASTER_SECRET_LEN)) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + /* EncryptedPreMasterSecret */ + if (conn->server_rsa_key == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: No server RSA key to " + "use for encrypting pre-master secret"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + /* RSA encrypted value is encoded with PKCS #1 v1.5 block type 2. */ + *pos += 2; + clen = end - *pos; + res = crypto_public_key_encrypt_pkcs1_v15( + conn->server_rsa_key, + pre_master_secret, TLS_PRE_MASTER_SECRET_LEN, + *pos, &clen); + os_memset(pre_master_secret, 0, TLS_PRE_MASTER_SECRET_LEN); + if (res < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: RSA encryption failed"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + WPA_PUT_BE16(*pos - 2, clen); + wpa_hexdump(MSG_MSGDUMP, "TLSv1: Encrypted pre_master_secret", + *pos, clen); + *pos += clen; + + return 0; +} + + +static int tls_write_client_key_exchange(struct tlsv1_client *conn, + u8 **msgpos, u8 *end) +{ + u8 *pos, *rhdr, *hs_start, *hs_length; + size_t rlen; + tls_key_exchange keyx; + const struct tls_cipher_suite *suite; + + suite = tls_get_cipher_suite(conn->rl.cipher_suite); + if (suite == NULL) + keyx = TLS_KEY_X_NULL; + else + keyx = suite->key_exchange; + + pos = *msgpos; + + wpa_printf(MSG_DEBUG, "TLSv1: Send ClientKeyExchange"); + + rhdr = pos; + pos += TLS_RECORD_HEADER_LEN; + + /* opaque fragment[TLSPlaintext.length] */ + + /* Handshake */ + hs_start = pos; + /* HandshakeType msg_type */ + *pos++ = TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE; + /* uint24 length (to be filled) */ + hs_length = pos; + pos += 3; + /* body - ClientKeyExchange */ + if (keyx == TLS_KEY_X_DH_anon) { + if (tlsv1_key_x_anon_dh(conn, &pos, end) < 0) + return -1; + } else { + if (tlsv1_key_x_rsa(conn, &pos, end) < 0) + return -1; + } + + WPA_PUT_BE24(hs_length, pos - hs_length - 3); + + if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, + rhdr, end - rhdr, hs_start, pos - hs_start, + &rlen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + pos = rhdr + rlen; + tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); + + *msgpos = pos; + + return 0; +} + + +static int tls_write_client_certificate_verify(struct tlsv1_client *conn, + u8 **msgpos, u8 *end) +{ + u8 *pos, *rhdr, *hs_start, *hs_length, *signed_start; + size_t rlen, hlen, clen; + u8 hash[100], *hpos; + enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA; + + pos = *msgpos; + + wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateVerify"); + rhdr = pos; + pos += TLS_RECORD_HEADER_LEN; + + /* Handshake */ + hs_start = pos; + /* HandshakeType msg_type */ + *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY; + /* uint24 length (to be filled) */ + hs_length = pos; + pos += 3; + + /* + * RFC 2246: 7.4.3 and 7.4.8: + * Signature signature + * + * RSA: + * digitally-signed struct { + * opaque md5_hash[16]; + * opaque sha_hash[20]; + * }; + * + * DSA: + * digitally-signed struct { + * opaque sha_hash[20]; + * }; + * + * The hash values are calculated over all handshake messages sent or + * received starting at ClientHello up to, but not including, this + * CertificateVerify message, including the type and length fields of + * the handshake messages. + */ + + hpos = hash; + +#ifdef CONFIG_TLSV12 + if (conn->rl.tls_version == TLS_VERSION_1_2) { + hlen = SHA256_MAC_LEN; + if (wpa2_crypto_funcs.crypto_hash_finish) { + if (conn->verify.sha256_cert == NULL || + wpa2_crypto_funcs.crypto_hash_finish(conn->verify.sha256_cert, hpos, &hlen) < + 0) { + conn->verify.sha256_cert = NULL; + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + } else { + conn->verify.sha256_cert = NULL; + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + wpa_printf(MSG_ERROR, "In function %s, fail to register crypto_hash_finish function!\r\n", __FUNCTION__); + return -1; + } + conn->verify.sha256_cert = NULL; + + /* + * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5 + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithm, + * digest OCTET STRING + * } + * + * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11} + * + * DER encoded DigestInfo for SHA256 per RFC 3447: + * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || + * H + */ + os_memmove(hash + 19, hash, hlen); + hlen += 19; + os_memcpy(hash, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65" + "\x03\x04\x02\x01\x05\x00\x04\x20", 19); + } else { +#endif /* CONFIG_TLSV12 */ + + if (alg == SIGN_ALG_RSA) { + hlen = MD5_MAC_LEN; + if (conn->verify.md5_cert == NULL || + crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) + { + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + conn->verify.md5_cert = NULL; + crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL); + conn->verify.sha1_cert = NULL; + return -1; + } + hpos += MD5_MAC_LEN; + } else + crypto_hash_finish(conn->verify.md5_cert, NULL, NULL); + + conn->verify.md5_cert = NULL; + hlen = SHA1_MAC_LEN; + if (conn->verify.sha1_cert == NULL || + crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) { + conn->verify.sha1_cert = NULL; + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + conn->verify.sha1_cert = NULL; + + if (alg == SIGN_ALG_RSA) + hlen += MD5_MAC_LEN; + +#ifdef CONFIG_TLSV12 + } +#endif /* CONFIG_TLSV12 */ + + wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); + +#ifdef CONFIG_TLSV12 + if (conn->rl.tls_version >= TLS_VERSION_1_2) { + /* + * RFC 5246, 4.7: + * TLS v1.2 adds explicit indication of the used signature and + * hash algorithms. + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + */ + *pos++ = TLS_HASH_ALG_SHA256; + *pos++ = TLS_SIGN_ALG_RSA; + } +#endif /* CONFIG_TLSV12 */ + + /* + * RFC 2246, 4.7: + * In digital signing, one-way hash functions are used as input for a + * signing algorithm. A digitally-signed element is encoded as an + * opaque vector <0..2^16-1>, where the length is specified by the + * signing algorithm and key. + * + * In RSA signing, a 36-byte structure of two hashes (one SHA and one + * MD5) is signed (encrypted with the private key). It is encoded with + * PKCS #1 block type 0 or type 1 as described in [PKCS1]. + */ + signed_start = pos; /* length to be filled */ + pos += 2; + clen = end - pos; + if (conn->cred == NULL || + crypto_private_key_sign_pkcs1(conn->cred->key, hash, hlen, + pos, &clen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to sign hash (PKCS #1)"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + WPA_PUT_BE16(signed_start, clen); + + pos += clen; + + WPA_PUT_BE24(hs_length, pos - hs_length - 3); + + if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, + rhdr, end - rhdr, hs_start, pos - hs_start, + &rlen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + pos = rhdr + rlen; + + tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); + + *msgpos = pos; + + return 0; +} + + +static int tls_write_client_change_cipher_spec(struct tlsv1_client *conn, + u8 **msgpos, u8 *end) +{ + size_t rlen; + u8 payload[1]; + + wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec"); + + payload[0] = TLS_CHANGE_CIPHER_SPEC; + + if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, + *msgpos, end - *msgpos, payload, sizeof(payload), + &rlen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " + "record layer"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + *msgpos += rlen; + + return 0; +} + + +static int tls_write_client_finished(struct tlsv1_client *conn, + u8 **msgpos, u8 *end) +{ + u8 *pos, *hs_start; + size_t rlen, hlen; + u8 verify_data[1 + 3 + TLS_VERIFY_DATA_LEN]; + u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; + + wpa_printf(MSG_DEBUG, "TLSv1: Send Finished"); + + /* Encrypted Handshake Message: Finished */ + +#ifdef CONFIG_TLSV12 + if (conn->rl.tls_version >= TLS_VERSION_1_2) { + hlen = SHA256_MAC_LEN; + if (wpa2_crypto_funcs.crypto_hash_finish) { + if (conn->verify.sha256_client == NULL || + wpa2_crypto_funcs.crypto_hash_finish(conn->verify.sha256_client, hash, &hlen) + < 0) { + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + conn->verify.sha256_client = NULL; + return -1; + } + } else { + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + conn->verify.sha256_client = NULL; + wpa_printf(MSG_ERROR, "In function %s, fail to register crypto_hash_finish function!\r\n", __FUNCTION__); + return -1; + } + conn->verify.sha256_client = NULL; + } else { +#endif /* CONFIG_TLSV12 */ + + hlen = MD5_MAC_LEN; + if (conn->verify.md5_client == NULL || + crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + conn->verify.md5_client = NULL; + crypto_hash_finish(conn->verify.sha1_client, NULL, NULL); + conn->verify.sha1_client = NULL; + return -1; + } + conn->verify.md5_client = NULL; + hlen = SHA1_MAC_LEN; + if (conn->verify.sha1_client == NULL || + crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN, + &hlen) < 0) { + conn->verify.sha1_client = NULL; + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + conn->verify.sha1_client = NULL; + hlen = MD5_MAC_LEN + SHA1_MAC_LEN; + +#ifdef CONFIG_TLSV12 + } +#endif /* CONFIG_TLSV12 */ + + if (tls_prf(conn->rl.tls_version, + conn->master_secret, TLS_MASTER_SECRET_LEN, + "client finished", hash, hlen, + verify_data + 1 + 3, TLS_VERIFY_DATA_LEN)) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)", + verify_data + 1 + 3, TLS_VERIFY_DATA_LEN); + + /* Handshake */ + pos = hs_start = verify_data; + /* HandshakeType msg_type */ + *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; + /* uint24 length */ + WPA_PUT_BE24(pos, TLS_VERIFY_DATA_LEN); + pos += 3; + pos += TLS_VERIFY_DATA_LEN; /* verify_data already in place */ + tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); + + if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, + *msgpos, end - *msgpos, hs_start, pos - hs_start, + &rlen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); + tls_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + *msgpos += rlen; + + return 0; +} + + +static u8 * tls_send_client_key_exchange(struct tlsv1_client *conn, + size_t *out_len) +{ + u8 *msg, *end, *pos; + size_t msglen; + + *out_len = 0; + + msglen = 2000; + if (conn->certificate_requested) + msglen += tls_client_cert_chain_der_len(conn); + + msg = os_malloc(msglen); + if (msg == NULL) + return NULL; + + pos = msg; + end = msg + msglen; + + if (conn->certificate_requested) { + if (tls_write_client_certificate(conn, &pos, end) < 0) { + os_free(msg); + return NULL; + } + } + + if (tls_write_client_key_exchange(conn, &pos, end) < 0 || + (conn->certificate_requested && conn->cred && conn->cred->key && + tls_write_client_certificate_verify(conn, &pos, end) < 0) || + tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || + tls_write_client_finished(conn, &pos, end) < 0) { + os_free(msg); + return NULL; + } + + *out_len = pos - msg; + conn->state = SERVER_CHANGE_CIPHER_SPEC; + + return msg; +} + + +static u8 * tls_send_change_cipher_spec(struct tlsv1_client *conn, + size_t *out_len) +{ + u8 *msg, *end, *pos; + + *out_len = 0; + + msg = os_malloc(1000); + if (msg == NULL) + return NULL; + + pos = msg; + end = msg + 1000; + + if (tls_write_client_change_cipher_spec(conn, &pos, end) < 0 || + tls_write_client_finished(conn, &pos, end) < 0) { + os_free(msg); + return NULL; + } + + *out_len = pos - msg; + + wpa_printf(MSG_DEBUG, "TLSv1: Session resumption completed " + "successfully"); + + conn->state = ESTABLISHED; + + return msg; +} + + +u8 * tlsv1_client_handshake_write(struct tlsv1_client *conn, size_t *out_len, + int no_appl_data) +{ + switch (conn->state) { + case CLIENT_KEY_EXCHANGE: + return tls_send_client_key_exchange(conn, out_len); + case CHANGE_CIPHER_SPEC: + return tls_send_change_cipher_spec(conn, out_len); + case ACK_FINISHED: + wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed " + "successfully"); + conn->state = ESTABLISHED; + *out_len = 0; + if (no_appl_data) { + /* Need to return something to get final TLS ACK. */ + return os_malloc(1); + } + return NULL; + default: + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while " + "generating reply", conn->state); + return NULL; + } +} + + +u8 * tlsv1_client_send_alert(struct tlsv1_client *conn, u8 level, + u8 description, size_t *out_len) +{ + u8 *alert, *pos, *length; + + wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description); + *out_len = 0; + + alert = os_malloc(10); + if (alert == NULL) + return NULL; + + pos = alert; + + /* TLSPlaintext */ + /* ContentType type */ + *pos++ = TLS_CONTENT_TYPE_ALERT; + /* ProtocolVersion version */ + WPA_PUT_BE16(pos, conn->rl.tls_version ? conn->rl.tls_version : + TLS_VERSION); + pos += 2; + /* uint16 length (to be filled) */ + length = pos; + pos += 2; + /* opaque fragment[TLSPlaintext.length] */ + + /* Alert */ + /* AlertLevel level */ + *pos++ = level; + /* AlertDescription description */ + *pos++ = description; + + WPA_PUT_BE16(length, pos - length - 2); + *out_len = pos - alert; + + return alert; +} diff --git a/components/wpa_supplicant/src/wpa2/tls/tlsv1_common.c b/components/wpa_supplicant/src/wpa2/tls/tlsv1_common.c new file mode 100644 index 0000000000..9d17928dbc --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/tls/tlsv1_common.c @@ -0,0 +1,337 @@ +/* + * TLSv1 common routines + * Copyright (c) 2006-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "crypto/sha1.h" +#include "crypto/sha256.h" +#include "wpa2/tls/tls.h" +#include "wpa2/tls/x509v3.h" +#include "wpa2/tls/tlsv1_common.h" +#include "wpa2/eap_peer/eap_i.h" + + +/* + * TODO: + * RFC 2246 Section 9: Mandatory to implement TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA + * Add support for commonly used cipher suites; don't bother with exportable + * suites. + */ + +static const struct tls_cipher_suite tls_cipher_suites[] = { + { TLS_NULL_WITH_NULL_NULL, TLS_KEY_X_NULL, TLS_CIPHER_NULL, + TLS_HASH_NULL }, + { TLS_RSA_WITH_RC4_128_MD5, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128, + TLS_HASH_MD5 }, + { TLS_RSA_WITH_RC4_128_SHA, TLS_KEY_X_RSA, TLS_CIPHER_RC4_128, + TLS_HASH_SHA }, + { TLS_RSA_WITH_DES_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_DES_CBC, + TLS_HASH_SHA }, + { TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_RSA, + TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA }, + { TLS_DH_anon_WITH_RC4_128_MD5, TLS_KEY_X_DH_anon, + TLS_CIPHER_RC4_128, TLS_HASH_MD5 }, + { TLS_DH_anon_WITH_DES_CBC_SHA, TLS_KEY_X_DH_anon, + TLS_CIPHER_DES_CBC, TLS_HASH_SHA }, + { TLS_DH_anon_WITH_3DES_EDE_CBC_SHA, TLS_KEY_X_DH_anon, + TLS_CIPHER_3DES_EDE_CBC, TLS_HASH_SHA }, + { TLS_RSA_WITH_AES_128_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_128_CBC, + TLS_HASH_SHA }, + { TLS_DH_anon_WITH_AES_128_CBC_SHA, TLS_KEY_X_DH_anon, + TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA }, + { TLS_RSA_WITH_AES_256_CBC_SHA, TLS_KEY_X_RSA, TLS_CIPHER_AES_256_CBC, + TLS_HASH_SHA }, + { TLS_DH_anon_WITH_AES_256_CBC_SHA, TLS_KEY_X_DH_anon, + TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA }, + { TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_KEY_X_RSA, + TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA256 }, + { TLS_RSA_WITH_AES_256_CBC_SHA256, TLS_KEY_X_RSA, + TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA256 }, + { TLS_DH_anon_WITH_AES_128_CBC_SHA256, TLS_KEY_X_DH_anon, + TLS_CIPHER_AES_128_CBC, TLS_HASH_SHA256 }, + { TLS_DH_anon_WITH_AES_256_CBC_SHA256, TLS_KEY_X_DH_anon, + TLS_CIPHER_AES_256_CBC, TLS_HASH_SHA256 } +}; + +#define NUM_ELEMS(a) (sizeof(a) / sizeof((a)[0])) +#define NUM_TLS_CIPHER_SUITES NUM_ELEMS(tls_cipher_suites) + + +static const struct tls_cipher_data tls_ciphers[] = { + { TLS_CIPHER_NULL, TLS_CIPHER_STREAM, 0, 0, 0, + CRYPTO_CIPHER_NULL }, + { TLS_CIPHER_IDEA_CBC, TLS_CIPHER_BLOCK, 16, 16, 8, + CRYPTO_CIPHER_NULL }, + { TLS_CIPHER_RC2_CBC_40, TLS_CIPHER_BLOCK, 5, 16, 0, + CRYPTO_CIPHER_ALG_RC2 }, + { TLS_CIPHER_RC4_40, TLS_CIPHER_STREAM, 5, 16, 0, + CRYPTO_CIPHER_ALG_RC4 }, + { TLS_CIPHER_RC4_128, TLS_CIPHER_STREAM, 16, 16, 0, + CRYPTO_CIPHER_ALG_RC4 }, + { TLS_CIPHER_DES40_CBC, TLS_CIPHER_BLOCK, 5, 8, 8, + CRYPTO_CIPHER_ALG_DES }, + { TLS_CIPHER_DES_CBC, TLS_CIPHER_BLOCK, 8, 8, 8, + CRYPTO_CIPHER_ALG_DES }, + { TLS_CIPHER_3DES_EDE_CBC, TLS_CIPHER_BLOCK, 24, 24, 8, + CRYPTO_CIPHER_ALG_3DES }, + { TLS_CIPHER_AES_128_CBC, TLS_CIPHER_BLOCK, 16, 16, 16, + CRYPTO_CIPHER_ALG_AES }, + { TLS_CIPHER_AES_256_CBC, TLS_CIPHER_BLOCK, 32, 32, 16, + CRYPTO_CIPHER_ALG_AES } +}; + +#define NUM_TLS_CIPHER_DATA NUM_ELEMS(tls_ciphers) + + +/** + * tls_get_cipher_suite - Get TLS cipher suite + * @suite: Cipher suite identifier + * Returns: Pointer to the cipher data or %NULL if not found + */ +const struct tls_cipher_suite * tls_get_cipher_suite(u16 suite) +{ + size_t i; + for (i = 0; i < NUM_TLS_CIPHER_SUITES; i++) + if (tls_cipher_suites[i].suite == suite) + return &tls_cipher_suites[i]; + return NULL; +} + + +const struct tls_cipher_data * tls_get_cipher_data(tls_cipher cipher) +{ + size_t i; + for (i = 0; i < NUM_TLS_CIPHER_DATA; i++) + if (tls_ciphers[i].cipher == cipher) + return &tls_ciphers[i]; + return NULL; +} + + +int tls_server_key_exchange_allowed(tls_cipher cipher) +{ + const struct tls_cipher_suite *suite; + + /* RFC 2246, Section 7.4.3 */ + suite = tls_get_cipher_suite(cipher); + if (suite == NULL) + return 0; + + switch (suite->key_exchange) { + case TLS_KEY_X_DHE_DSS: + case TLS_KEY_X_DHE_DSS_EXPORT: + case TLS_KEY_X_DHE_RSA: + case TLS_KEY_X_DHE_RSA_EXPORT: + case TLS_KEY_X_DH_anon_EXPORT: + case TLS_KEY_X_DH_anon: + return 1; + case TLS_KEY_X_RSA_EXPORT: + return 1 /* FIX: public key len > 512 bits */; + default: + return 0; + } +} + + +/** + * tls_parse_cert - Parse DER encoded X.509 certificate and get public key + * @buf: ASN.1 DER encoded certificate + * @len: Length of the buffer + * @pk: Buffer for returning the allocated public key + * Returns: 0 on success, -1 on failure + * + * This functions parses an ASN.1 DER encoded X.509 certificate and retrieves + * the public key from it. The caller is responsible for freeing the public key + * by calling crypto_public_key_free(). + */ +int tls_parse_cert(const u8 *buf, size_t len, struct crypto_public_key **pk) +{ + struct x509_certificate *cert; + + wpa_hexdump(MSG_MSGDUMP, "TLSv1: Parse ASN.1 DER certificate", + buf, len); + + *pk = crypto_public_key_from_cert(buf, len); + if (*pk) + return 0; + + cert = x509_certificate_parse(buf, len); + if (cert == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse X.509 " + "certificate"); + return -1; + } + + /* TODO + * verify key usage (must allow encryption) + * + * All certificate profiles, key and cryptographic formats are + * defined by the IETF PKIX working group [PKIX]. When a key + * usage extension is present, the digitalSignature bit must be + * set for the key to be eligible for signing, as described + * above, and the keyEncipherment bit must be present to allow + * encryption, as described above. The keyAgreement bit must be + * set on Diffie-Hellman certificates. (PKIX: RFC 3280) + */ + + *pk = crypto_public_key_import(cert->public_key, cert->public_key_len); + x509_certificate_free(cert); + + if (*pk == NULL) { + wpa_printf(MSG_ERROR, "TLSv1: Failed to import " + "server public key"); + return -1; + } + + return 0; +} + + +int tls_verify_hash_init(struct tls_verify_hash *verify) +{ + tls_verify_hash_free(verify); + verify->md5_client = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0); + verify->md5_server = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0); + verify->md5_cert = crypto_hash_init(CRYPTO_HASH_ALG_MD5, NULL, 0); + verify->sha1_client = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0); + verify->sha1_server = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0); + verify->sha1_cert = crypto_hash_init(CRYPTO_HASH_ALG_SHA1, NULL, 0); + if (verify->md5_client == NULL || verify->md5_server == NULL || + verify->md5_cert == NULL || verify->sha1_client == NULL || + verify->sha1_server == NULL || verify->sha1_cert == NULL) { + tls_verify_hash_free(verify); + return -1; + } +#ifdef CONFIG_TLSV12 + if (wpa2_crypto_funcs.crypto_hash_init) { + verify->sha256_client = wpa2_crypto_funcs.crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL, 0); + verify->sha256_server = wpa2_crypto_funcs.crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL, 0); + verify->sha256_cert = wpa2_crypto_funcs.crypto_hash_init(CRYPTO_HASH_ALG_SHA256, NULL, 0); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register crypto hash init function!\r\n", __FUNCTION__); + return -1; + } + if (verify->sha256_client == NULL || + verify->sha256_server == NULL || + verify->sha256_cert == NULL) { + tls_verify_hash_free(verify); + return -1; + } +#endif /* CONFIG_TLSV12 */ + return 0; +} + + +void tls_verify_hash_add(struct tls_verify_hash *verify, const u8 *buf, + size_t len) +{ + if (verify->md5_client && verify->sha1_client) { + crypto_hash_update(verify->md5_client, buf, len); + crypto_hash_update(verify->sha1_client, buf, len); + } + if (verify->md5_server && verify->sha1_server) { + crypto_hash_update(verify->md5_server, buf, len); + crypto_hash_update(verify->sha1_server, buf, len); + } + if (verify->md5_cert && verify->sha1_cert) { + crypto_hash_update(verify->md5_cert, buf, len); + crypto_hash_update(verify->sha1_cert, buf, len); + } +#ifdef CONFIG_TLSV12 + if (wpa2_crypto_funcs.crypto_hash_update) { + if (verify->sha256_client) + wpa2_crypto_funcs.crypto_hash_update(verify->sha256_client, buf, len); + if (verify->sha256_server) + wpa2_crypto_funcs.crypto_hash_update(verify->sha256_server, buf, len); + if (verify->sha256_cert) + wpa2_crypto_funcs.crypto_hash_update(verify->sha256_cert, buf, len); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register crypto hash update function!\r\n", __FUNCTION__); + return; + } +#endif /* CONFIG_TLSV12 */ +} + + +void tls_verify_hash_free(struct tls_verify_hash *verify) +{ + crypto_hash_finish(verify->md5_client, NULL, NULL); + crypto_hash_finish(verify->md5_server, NULL, NULL); + crypto_hash_finish(verify->md5_cert, NULL, NULL); + crypto_hash_finish(verify->sha1_client, NULL, NULL); + crypto_hash_finish(verify->sha1_server, NULL, NULL); + crypto_hash_finish(verify->sha1_cert, NULL, NULL); + verify->md5_client = NULL; + verify->md5_server = NULL; + verify->md5_cert = NULL; + verify->sha1_client = NULL; + verify->sha1_server = NULL; + verify->sha1_cert = NULL; +#ifdef CONFIG_TLSV12 + if (wpa2_crypto_funcs.crypto_hash_finish) { + wpa2_crypto_funcs.crypto_hash_finish(verify->sha256_client, NULL, NULL); + wpa2_crypto_funcs.crypto_hash_finish(verify->sha256_server, NULL, NULL); + wpa2_crypto_funcs.crypto_hash_finish(verify->sha256_cert, NULL, NULL); + verify->sha256_client = NULL; + verify->sha256_server = NULL; + verify->sha256_cert = NULL; + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register crypto hash finish function!\r\n", __FUNCTION__); + return; + } +#endif /* CONFIG_TLSV12 */ +} + + +int tls_version_ok(u16 ver) +{ + if (ver == TLS_VERSION_1) + return 1; +#ifdef CONFIG_TLSV11 + if (ver == TLS_VERSION_1_1) + return 1; +#endif /* CONFIG_TLSV11 */ +#ifdef CONFIG_TLSV12 + if (ver == TLS_VERSION_1_2) + return 1; +#endif /* CONFIG_TLSV12 */ + + return 0; +} + + +const char * tls_version_str(u16 ver) +{ + switch (ver) { + case TLS_VERSION_1: + return "1.0"; + case TLS_VERSION_1_1: + return "1.1"; + case TLS_VERSION_1_2: + return "1.2"; + } + + return "?"; +} + + +int tls_prf(u16 ver, const u8 *secret, size_t secret_len, const char *label, + const u8 *seed, size_t seed_len, u8 *out, size_t outlen) +{ +#ifdef CONFIG_TLSV12 + if (ver >= TLS_VERSION_1_2) { + tls_prf_sha256(secret, secret_len, label, seed, seed_len, + out, outlen); + return 0; + } +#endif /* CONFIG_TLSV12 */ + + return tls_prf_sha1_md5(secret, secret_len, label, seed, seed_len, out, + outlen); +} diff --git a/components/wpa_supplicant/src/wpa2/tls/tlsv1_cred.c b/components/wpa_supplicant/src/wpa2/tls/tlsv1_cred.c new file mode 100644 index 0000000000..fd359a2cc5 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/tls/tlsv1_cred.c @@ -0,0 +1,505 @@ +/* + * TLSv1 credentials + * Copyright (c) 2006-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "wpa2/utils/base64.h" +#include "crypto/crypto.h" +#include "wpa2/tls/x509v3.h" +#include "wpa2/tls/tlsv1_cred.h" + +struct tlsv1_credentials * tlsv1_cred_alloc(void) +{ + struct tlsv1_credentials *cred; + cred = (struct tlsv1_credentials *)os_zalloc(sizeof(*cred)); + return cred; +} + + +void tlsv1_cred_free(struct tlsv1_credentials *cred) +{ + if (cred == NULL) + return; + + x509_certificate_chain_free(cred->trusted_certs); + x509_certificate_chain_free(cred->cert); + crypto_private_key_free(cred->key); + os_free(cred->dh_p); + os_free(cred->dh_g); + os_free(cred); +} + + +static int tlsv1_add_cert_der(struct x509_certificate **chain, + const u8 *buf, size_t len) +{ + struct x509_certificate *cert, *p; + char name[128]; + + cert = x509_certificate_parse(buf, len); + if (cert == NULL) { + wpa_printf(MSG_INFO, "TLSv1: %s - failed to parse certificate", + __func__); + return -1; + } + + p = *chain; + while (p && p->next) + p = p->next; + if (p && x509_name_compare(&cert->subject, &p->issuer) == 0) { + /* + * The new certificate is the issuer of the last certificate in + * the chain - add the new certificate to the end. + */ + p->next = cert; + } else { + /* Add to the beginning of the chain */ + cert->next = *chain; + *chain = cert; + } + + x509_name_string(&cert->subject, name, sizeof(name)); + wpa_printf(MSG_DEBUG, "TLSv1: Added certificate: %s", name); + + return 0; +} + + +static const char *pem_cert_begin = "-----BEGIN CERTIFICATE-----"; +static const char *pem_cert_end = "-----END CERTIFICATE-----"; +static const char *pem_key_begin = "-----BEGIN RSA PRIVATE KEY-----"; +static const char *pem_key_end = "-----END RSA PRIVATE KEY-----"; +static const char *pem_key2_begin = "-----BEGIN PRIVATE KEY-----"; +static const char *pem_key2_end = "-----END PRIVATE KEY-----"; +static const char *pem_key_enc_begin = "-----BEGIN ENCRYPTED PRIVATE KEY-----"; +static const char *pem_key_enc_end = "-----END ENCRYPTED PRIVATE KEY-----"; + + +static const u8 * search_tag(const char *tag, const u8 *buf, size_t len) +{ + size_t i, plen; + + plen = os_strlen(tag); + if (len < plen) + return NULL; + + for (i = 0; i < len - plen; i++) { + if (os_memcmp(buf + i, tag, plen) == 0) + return buf + i; + } + + return NULL; +} + + +static int tlsv1_add_cert(struct x509_certificate **chain, + const u8 *buf, size_t len) +{ + const u8 *pos, *end; + unsigned char *der; + size_t der_len; + + pos = search_tag(pem_cert_begin, buf, len); + if (!pos) { + wpa_printf(MSG_DEBUG, "TLSv1: No PEM certificate tag found - " + "assume DER format"); + return tlsv1_add_cert_der(chain, buf, len); + } + + wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format certificate into " + "DER format"); + + while (pos) { + pos += os_strlen(pem_cert_begin); + end = search_tag(pem_cert_end, pos, buf + len - pos); + if (end == NULL) { + wpa_printf(MSG_INFO, "TLSv1: Could not find PEM " + "certificate end tag (%s)", pem_cert_end); + return -1; + } + + der = base64_decode(pos, end - pos, &der_len); + if (der == NULL) { + wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM " + "certificate"); + return -1; + } + + if (tlsv1_add_cert_der(chain, der, der_len) < 0) { + wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM " + "certificate after DER conversion"); + os_free(der); + return -1; + } + + os_free(der); + + end += os_strlen(pem_cert_end); + pos = search_tag(pem_cert_begin, end, buf + len - end); + } + + return 0; +} + + +static int tlsv1_set_cert_chain(struct x509_certificate **chain, + const char *cert, const u8 *cert_blob, + size_t cert_blob_len) +{ + if (cert_blob) + return tlsv1_add_cert(chain, cert_blob, cert_blob_len); + + if (cert) { + u8 *buf = NULL; + size_t len; + int ret; + + //buf = (u8 *) os_readfile(cert, &len); + if (buf == NULL) { + wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", + cert); + return -1; + } + + ret = tlsv1_add_cert(chain, buf, len); + os_free(buf); + return ret; + } + + return 0; +} + + +/** + * tlsv1_set_ca_cert - Set trusted CA certificate(s) + * @cred: TLSv1 credentials from tlsv1_cred_alloc() + * @cert: File or reference name for X.509 certificate in PEM or DER format + * @cert_blob: cert as inlined data or %NULL if not used + * @cert_blob_len: ca_cert_blob length + * @path: Path to CA certificates (not yet supported) + * Returns: 0 on success, -1 on failure + */ +int tlsv1_set_ca_cert(struct tlsv1_credentials *cred, const char *cert, + const u8 *cert_blob, size_t cert_blob_len, + const char *path) +{ + if (tlsv1_set_cert_chain(&cred->trusted_certs, cert, + cert_blob, cert_blob_len) < 0) + return -1; + + if (path) { + /* TODO: add support for reading number of certificate files */ + wpa_printf(MSG_INFO, "TLSv1: Use of CA certificate directory " + "not yet supported"); + return -1; + } + + return 0; +} + + +/** + * tlsv1_set_cert - Set certificate + * @cred: TLSv1 credentials from tlsv1_cred_alloc() + * @cert: File or reference name for X.509 certificate in PEM or DER format + * @cert_blob: cert as inlined data or %NULL if not used + * @cert_blob_len: cert_blob length + * Returns: 0 on success, -1 on failure + */ +int tlsv1_set_cert(struct tlsv1_credentials *cred, const char *cert, + const u8 *cert_blob, size_t cert_blob_len) +{ + return tlsv1_set_cert_chain(&cred->cert, cert, + cert_blob, cert_blob_len); +} + + +static struct crypto_private_key * tlsv1_set_key_pem(const u8 *key, size_t len) +{ + const u8 *pos, *end; + unsigned char *der; + size_t der_len; + struct crypto_private_key *pkey; + + pos = search_tag(pem_key_begin, key, len); + if (!pos) { + pos = search_tag(pem_key2_begin, key, len); + if (!pos) + return NULL; + pos += os_strlen(pem_key2_begin); + end = search_tag(pem_key2_end, pos, key + len - pos); + if (!end) + return NULL; + } else { + const u8 *pos2; + pos += os_strlen(pem_key_begin); + end = search_tag(pem_key_end, pos, key + len - pos); + if (!end) + return NULL; + pos2 = search_tag("Proc-Type: 4,ENCRYPTED", pos, end - pos); + if (pos2) { + wpa_printf(MSG_DEBUG, "TLSv1: Unsupported private key " + "format (Proc-Type/DEK-Info)"); + return NULL; + } + } + + der = base64_decode(pos, end - pos, &der_len); + if (!der) + return NULL; + pkey = crypto_private_key_import(der, der_len, NULL); + os_free(der); + return pkey; +} + + +static struct crypto_private_key * tlsv1_set_key_enc_pem(const u8 *key, + size_t len, + const char *passwd) +{ + const u8 *pos, *end; + unsigned char *der; + size_t der_len; + struct crypto_private_key *pkey; + + if (passwd == NULL) + return NULL; + pos = search_tag(pem_key_enc_begin, key, len); + if (!pos) + return NULL; + pos += os_strlen(pem_key_enc_begin); + end = search_tag(pem_key_enc_end, pos, key + len - pos); + if (!end) + return NULL; + + der = base64_decode(pos, end - pos, &der_len); + if (!der) + return NULL; + pkey = crypto_private_key_import(der, der_len, passwd); + os_free(der); + return pkey; +} + + +static int tlsv1_set_key(struct tlsv1_credentials *cred, + const u8 *key, size_t len, const char *passwd) +{ + cred->key = crypto_private_key_import(key, len, passwd); + if (cred->key == NULL) + cred->key = tlsv1_set_key_pem(key, len); + if (cred->key == NULL) + cred->key = tlsv1_set_key_enc_pem(key, len, passwd); + if (cred->key == NULL) { + wpa_printf(MSG_INFO, "TLSv1: Failed to parse private key"); + return -1; + } + return 0; +} + + +/** + * tlsv1_set_private_key - Set private key + * @cred: TLSv1 credentials from tlsv1_cred_alloc() + * @private_key: File or reference name for the key in PEM or DER format + * @private_key_passwd: Passphrase for decrypted private key, %NULL if no + * passphrase is used. + * @private_key_blob: private_key as inlined data or %NULL if not used + * @private_key_blob_len: private_key_blob length + * Returns: 0 on success, -1 on failure + */ +int tlsv1_set_private_key(struct tlsv1_credentials *cred, + const char *private_key, + const char *private_key_passwd, + const u8 *private_key_blob, + size_t private_key_blob_len) +{ + crypto_private_key_free(cred->key); + cred->key = NULL; + + if (private_key_blob) + return tlsv1_set_key(cred, private_key_blob, + private_key_blob_len, + private_key_passwd); + + if (private_key) { + u8 *buf = NULL; + size_t len; + int ret; + + //buf = (u8 *) os_readfile(private_key, &len); + if (buf == NULL) { + wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", + private_key); + return -1; + } + + ret = tlsv1_set_key(cred, buf, len, private_key_passwd); + os_free(buf); + return ret; + } + + return 0; +} + + +static int tlsv1_set_dhparams_der(struct tlsv1_credentials *cred, + const u8 *dh, size_t len) +{ + struct asn1_hdr hdr; + const u8 *pos, *end; + + pos = dh; + end = dh + len; + + /* + * DHParameter ::= SEQUENCE { + * prime INTEGER, -- p + * base INTEGER, -- g + * privateValueLength INTEGER OPTIONAL } + */ + + /* DHParamer ::= SEQUENCE */ + if (asn1_get_next(pos, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "DH: DH parameters did not start with a " + "valid SEQUENCE - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + pos = hdr.payload; + + /* prime INTEGER */ + if (asn1_get_next(pos, end - pos, &hdr) < 0) + return -1; + + if (hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_INTEGER) { + wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for p; " + "class=%d tag=0x%x", hdr.class, hdr.tag); + return -1; + } + + wpa_hexdump(MSG_MSGDUMP, "DH: prime (p)", hdr.payload, hdr.length); + if (hdr.length == 0) + return -1; + os_free(cred->dh_p); + cred->dh_p = os_malloc(hdr.length); + if (cred->dh_p == NULL) + return -1; + os_memcpy(cred->dh_p, hdr.payload, hdr.length); + cred->dh_p_len = hdr.length; + pos = hdr.payload + hdr.length; + + /* base INTEGER */ + if (asn1_get_next(pos, end - pos, &hdr) < 0) + return -1; + + if (hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_INTEGER) { + wpa_printf(MSG_DEBUG, "DH: No INTEGER tag found for g; " + "class=%d tag=0x%x", hdr.class, hdr.tag); + return -1; + } + + wpa_hexdump(MSG_MSGDUMP, "DH: base (g)", hdr.payload, hdr.length); + if (hdr.length == 0) + return -1; + os_free(cred->dh_g); + cred->dh_g = os_malloc(hdr.length); + if (cred->dh_g == NULL) + return -1; + os_memcpy(cred->dh_g, hdr.payload, hdr.length); + cred->dh_g_len = hdr.length; + + return 0; +} + + +static const char *pem_dhparams_begin = "-----BEGIN DH PARAMETERS-----"; +static const char *pem_dhparams_end = "-----END DH PARAMETERS-----"; + + +static int tlsv1_set_dhparams_blob(struct tlsv1_credentials *cred, + const u8 *buf, size_t len) +{ + const u8 *pos, *end; + unsigned char *der; + size_t der_len; + + pos = search_tag(pem_dhparams_begin, buf, len); + if (!pos) { + wpa_printf(MSG_DEBUG, "TLSv1: No PEM dhparams tag found - " + "assume DER format"); + return tlsv1_set_dhparams_der(cred, buf, len); + } + + wpa_printf(MSG_DEBUG, "TLSv1: Converting PEM format dhparams into DER " + "format"); + + pos += os_strlen(pem_dhparams_begin); + end = search_tag(pem_dhparams_end, pos, buf + len - pos); + if (end == NULL) { + wpa_printf(MSG_INFO, "TLSv1: Could not find PEM dhparams end " + "tag (%s)", pem_dhparams_end); + return -1; + } + + der = base64_decode(pos, end - pos, &der_len); + if (der == NULL) { + wpa_printf(MSG_INFO, "TLSv1: Could not decode PEM dhparams"); + return -1; + } + + if (tlsv1_set_dhparams_der(cred, der, der_len) < 0) { + wpa_printf(MSG_INFO, "TLSv1: Failed to parse PEM dhparams " + "DER conversion"); + os_free(der); + return -1; + } + + os_free(der); + + return 0; +} + + +/** + * tlsv1_set_dhparams - Set Diffie-Hellman parameters + * @cred: TLSv1 credentials from tlsv1_cred_alloc() + * @dh_file: File or reference name for the DH params in PEM or DER format + * @dh_blob: DH params as inlined data or %NULL if not used + * @dh_blob_len: dh_blob length + * Returns: 0 on success, -1 on failure + */ +int tlsv1_set_dhparams(struct tlsv1_credentials *cred, const char *dh_file, + const u8 *dh_blob, size_t dh_blob_len) +{ + if (dh_blob) + return tlsv1_set_dhparams_blob(cred, dh_blob, dh_blob_len); + + if (dh_file) { + u8 *buf = NULL; + size_t len; + int ret; + + //buf = (u8 *) os_readfile(dh_file, &len); + if (buf == NULL) { + wpa_printf(MSG_INFO, "TLSv1: Failed to read '%s'", + dh_file); + return -1; + } + + ret = tlsv1_set_dhparams_blob(cred, buf, len); + os_free(buf); + return ret; + } + + return 0; +} diff --git a/components/wpa_supplicant/src/wpa2/tls/tlsv1_record.c b/components/wpa_supplicant/src/wpa2/tls/tlsv1_record.c new file mode 100644 index 0000000000..879d9f5454 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/tls/tlsv1_record.c @@ -0,0 +1,553 @@ +/* + * TLSv1 Record Protocol + * Copyright (c) 2006-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "crypto/md5.h" +#include "crypto/sha1.h" +#include "crypto/sha256.h" +#include "wpa2/tls/tlsv1_common.h" +#include "wpa2/tls/tlsv1_record.h" + +#include "wpa2/eap_peer/eap_i.h" + +/** + * tlsv1_record_set_cipher_suite - TLS record layer: Set cipher suite + * @rl: Pointer to TLS record layer data + * @cipher_suite: New cipher suite + * Returns: 0 on success, -1 on failure + * + * This function is used to prepare TLS record layer for cipher suite change. + * tlsv1_record_change_write_cipher() and + * tlsv1_record_change_read_cipher() functions can then be used to change the + * currently used ciphers. + */ +int tlsv1_record_set_cipher_suite(struct tlsv1_record_layer *rl, + u16 cipher_suite) +{ + const struct tls_cipher_suite *suite; + const struct tls_cipher_data *data; + + wpa_printf(MSG_DEBUG, "TLSv1: Selected cipher suite: 0x%04x", + cipher_suite); + rl->cipher_suite = cipher_suite; + + suite = tls_get_cipher_suite(cipher_suite); + if (suite == NULL) + return -1; + + if (suite->hash == TLS_HASH_MD5) { + rl->hash_alg = CRYPTO_HASH_ALG_HMAC_MD5; + rl->hash_size = MD5_MAC_LEN; + } else if (suite->hash == TLS_HASH_SHA) { + rl->hash_alg = CRYPTO_HASH_ALG_HMAC_SHA1; + rl->hash_size = SHA1_MAC_LEN; + } else if (suite->hash == TLS_HASH_SHA256) { + rl->hash_alg = CRYPTO_HASH_ALG_HMAC_SHA256; + rl->hash_size = SHA256_MAC_LEN; + } + + data = tls_get_cipher_data(suite->cipher); + if (data == NULL) + return -1; + + rl->key_material_len = data->key_material; + rl->iv_size = data->block_size; + rl->cipher_alg = data->alg; + + return 0; +} + + +/** + * tlsv1_record_change_write_cipher - TLS record layer: Change write cipher + * @rl: Pointer to TLS record layer data + * Returns: 0 on success (cipher changed), -1 on failure + * + * This function changes TLS record layer to use the new cipher suite + * configured with tlsv1_record_set_cipher_suite() for writing. + */ +int tlsv1_record_change_write_cipher(struct tlsv1_record_layer *rl) +{ + wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - New write cipher suite " + "0x%04x", rl->cipher_suite); + rl->write_cipher_suite = rl->cipher_suite; + os_memset(rl->write_seq_num, 0, TLS_SEQ_NUM_LEN); + + if (rl->write_cbc) { + if (wpa2_crypto_funcs.crypto_cipher_deinit) { + wpa2_crypto_funcs.crypto_cipher_deinit(rl->write_cbc); + rl->write_cbc = NULL; + } else { + wpa_printf(MSG_ERROR, "Fail to register crypto cipher deinit function!\r\n"); + return -1; + } + } + if (rl->cipher_alg != CRYPTO_CIPHER_NULL) { + if (wpa2_crypto_funcs.crypto_cipher_init) { + rl->write_cbc = wpa2_crypto_funcs.crypto_cipher_init(rl->cipher_alg, + rl->write_iv, rl->write_key, + rl->key_material_len); + } else { + wpa_printf(MSG_ERROR, "Fail to register crypto_cipher_init function!\r\n"); + return -1; + } + + if (rl->write_cbc == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize " + "cipher"); + return -1; + } + } + + return 0; +} + + +/** + * tlsv1_record_change_read_cipher - TLS record layer: Change read cipher + * @rl: Pointer to TLS record layer data + * Returns: 0 on success (cipher changed), -1 on failure + * + * This function changes TLS record layer to use the new cipher suite + * configured with tlsv1_record_set_cipher_suite() for reading. + */ +int tlsv1_record_change_read_cipher(struct tlsv1_record_layer *rl) +{ + wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - New read cipher suite " + "0x%04x \n", rl->cipher_suite); + rl->read_cipher_suite = rl->cipher_suite; + os_memset(rl->read_seq_num, 0, TLS_SEQ_NUM_LEN); + + if (rl->read_cbc) { + if (wpa2_crypto_funcs.crypto_cipher_deinit) { + wpa2_crypto_funcs.crypto_cipher_deinit(rl->read_cbc); + rl->read_cbc = NULL; + } else { + wpa_printf(MSG_ERROR, "Fail to register crypto cipher deinit function!\r\n"); + return -1; + } + } + + if (rl->cipher_alg != CRYPTO_CIPHER_NULL) { + if(wpa2_crypto_funcs.crypto_cipher_init) { + rl->read_cbc = wpa2_crypto_funcs.crypto_cipher_init(rl->cipher_alg, + rl->read_iv, rl->read_key, + rl->key_material_len); + } else { + wpa_printf(MSG_ERROR, "Fail to register crypto_cipher_init function!\r\n"); + return -1; + } + if (rl->read_cbc == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize " + "cipher"); + return -1; + } + } + + return 0; +} + + +/** + * tlsv1_record_send - TLS record layer: Send a message + * @rl: Pointer to TLS record layer data + * @content_type: Content type (TLS_CONTENT_TYPE_*) + * @buf: Buffer for the generated TLS message (needs to have extra space for + * header, IV (TLS v1.1), and HMAC) + * @buf_size: Maximum buf size + * @payload: Payload to be sent + * @payload_len: Length of the payload + * @out_len: Buffer for returning the used buf length + * Returns: 0 on success, -1 on failure + * + * This function fills in the TLS record layer header, adds HMAC, and encrypts + * the data using the current write cipher. + */ +int tlsv1_record_send(struct tlsv1_record_layer *rl, u8 content_type, u8 *buf, + size_t buf_size, const u8 *payload, size_t payload_len, + size_t *out_len) +{ + u8 *pos, *ct_start, *length, *cpayload; + struct crypto_hash *hmac = NULL; + size_t clen; + int explicit_iv; + + pos = buf; + if (pos + TLS_RECORD_HEADER_LEN > buf + buf_size) + return -1; + + /* ContentType type */ + ct_start = pos; + *pos++ = content_type; + /* ProtocolVersion version */ + WPA_PUT_BE16(pos, rl->tls_version); + pos += 2; + /* uint16 length */ + length = pos; + WPA_PUT_BE16(length, payload_len); + pos += 2; + + cpayload = pos; + explicit_iv = rl->write_cipher_suite != TLS_NULL_WITH_NULL_NULL && + rl->iv_size && rl->tls_version >= TLS_VERSION_1_1; + if (explicit_iv) { + /* opaque IV[Cipherspec.block_length] */ + if (pos + rl->iv_size > buf + buf_size) + return -1; + + /* + * Use random number R per the RFC 4346, 6.2.3.2 CBC Block + * Cipher option 2a. + */ + + if (os_get_random(pos, rl->iv_size)) + return -1; + pos += rl->iv_size; + } + + /* + * opaque fragment[TLSPlaintext.length] + * (opaque content[TLSCompressed.length] in GenericBlockCipher) + */ + if (pos + payload_len > buf + buf_size) + return -1; + os_memmove(pos, payload, payload_len); + pos += payload_len; + + if (rl->write_cipher_suite != TLS_NULL_WITH_NULL_NULL) { + /* + * MAC calculated over seq_num + TLSCompressed.type + + * TLSCompressed.version + TLSCompressed.length + + * TLSCompressed.fragment + */ + if (wpa2_crypto_funcs.crypto_hash_init) { + hmac = wpa2_crypto_funcs.crypto_hash_init(rl->hash_alg, rl->write_mac_secret, rl->hash_size); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register crypto hash init!\r\n", __FUNCTION__); + return -1; + } + if (hmac == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " + "to initialize HMAC"); + return -1; + } + if (wpa2_crypto_funcs.crypto_hash_update) { + wpa2_crypto_funcs.crypto_hash_update(hmac, rl->write_seq_num, TLS_SEQ_NUM_LEN); + /* type + version + length + fragment */ + wpa2_crypto_funcs.crypto_hash_update(hmac, ct_start, TLS_RECORD_HEADER_LEN); + wpa2_crypto_funcs.crypto_hash_update(hmac, payload, payload_len); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register crypto hash update!\r\n", __FUNCTION__); + return -1; + } + clen = buf + buf_size - pos; + if (clen < rl->hash_size) { + wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Not " + "enough room for MAC"); + if (wpa2_crypto_funcs.crypto_hash_finish) { + wpa2_crypto_funcs.crypto_hash_finish(hmac, NULL, NULL); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register crypto hash finish function!\r\n", __FUNCTION__); + return -1; + } + + return -1; + } + + if (wpa2_crypto_funcs.crypto_hash_finish) { + if ((int)wpa2_crypto_funcs.crypto_hash_finish(hmac, pos, (int *)&clen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed to calculate HMAC"); + return -1; + } + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register crypto_hash_finish function!\r\n",__FUNCTION__); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Write HMAC", + pos, clen); + pos += clen; + if (rl->iv_size) { + size_t len = pos - cpayload; + size_t pad; + pad = (len + 1) % rl->iv_size; + if (pad) + pad = rl->iv_size - pad; + if (pos + pad + 1 > buf + buf_size) { + wpa_printf(MSG_DEBUG, "TLSv1: No room for " + "block cipher padding"); + return -1; + } + os_memset(pos, pad, pad + 1); + pos += pad + 1; + } + + if (wpa2_crypto_funcs.crypto_cipher_encrypt) { + if ((int)wpa2_crypto_funcs.crypto_cipher_encrypt(rl->write_cbc, cpayload, + cpayload, pos - cpayload) < 0) + return -1; + } else { + wpa_printf(MSG_ERROR, "Fail to register crypto_cipher_encrypt function!\r\n"); + return -1; + } + } + + WPA_PUT_BE16(length, pos - length - 2); + inc_byte_array(rl->write_seq_num, TLS_SEQ_NUM_LEN); + + *out_len = pos - buf; + + return 0; +} + + +/** + * tlsv1_record_receive - TLS record layer: Process a received message + * @rl: Pointer to TLS record layer data + * @in_data: Received data + * @in_len: Length of the received data + * @out_data: Buffer for output data (must be at least as long as in_data) + * @out_len: Set to maximum out_data length by caller; used to return the + * length of the used data + * @alert: Buffer for returning an alert value on failure + * Returns: Number of bytes used from in_data on success, 0 if record was not + * complete (more data needed), or -1 on failure + * + * This function decrypts the received message, verifies HMAC and TLS record + * layer header. + */ +int tlsv1_record_receive(struct tlsv1_record_layer *rl, + const u8 *in_data, size_t in_len, + u8 *out_data, size_t *out_len, u8 *alert) +{ + size_t i, rlen, hlen; + u8 padlen; + struct crypto_hash *hmac = NULL; + u8 len[2], hash[100]; + int force_mac_error = 0; + u8 ct; + + if (in_len < TLS_RECORD_HEADER_LEN) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short record (in_len=%lu) - " + "need more data", + (unsigned long) in_len); + wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Received", + in_data, in_len); + return 0; + } + + ct = in_data[0]; + rlen = WPA_GET_BE16(in_data + 3); + wpa_printf(MSG_DEBUG, "TLSv1: Received content type %d version %d.%d " + "length %d", ct, in_data[1], in_data[2], (int) rlen); + + /* + * TLS v1.0 and v1.1 RFCs were not exactly clear on the use of the + * protocol version in record layer. As such, accept any {03,xx} value + * to remain compatible with existing implementations. + */ + if (in_data[1] != 0x03) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version " + "%u.%u", in_data[1], in_data[2]); + *alert = TLS_ALERT_PROTOCOL_VERSION; + return -1; + } + + /* TLSCiphertext must not be more than 2^14+2048 bytes */ + if (TLS_RECORD_HEADER_LEN + rlen > 18432) { + wpa_printf(MSG_DEBUG, "TLSv1: Record overflow (len=%lu)", + (unsigned long) (TLS_RECORD_HEADER_LEN + rlen)); + *alert = TLS_ALERT_RECORD_OVERFLOW; + return -1; + } + + in_data += TLS_RECORD_HEADER_LEN; + in_len -= TLS_RECORD_HEADER_LEN; + + if (rlen > in_len) { + wpa_printf(MSG_DEBUG, "TLSv1: Not all record data included " + "(rlen=%lu > in_len=%lu)", + (unsigned long) rlen, (unsigned long) in_len); + return 0; + } + + wpa_hexdump(MSG_MSGDUMP, "TLSv1: Record Layer - Received", + in_data, rlen); + + if (ct != TLS_CONTENT_TYPE_HANDSHAKE && + ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC && + ct != TLS_CONTENT_TYPE_ALERT && + ct != TLS_CONTENT_TYPE_APPLICATION_DATA) { + wpa_printf(MSG_DEBUG, "TLSv1: Ignore record with unknown " + "content type 0x%x", ct); + *alert = TLS_ALERT_UNEXPECTED_MESSAGE; + return -1; + } + + in_len = rlen; + + if (*out_len < in_len) { + wpa_printf(MSG_DEBUG, "TLSv1: Not enough output buffer for " + "processing received record"); + *alert = TLS_ALERT_INTERNAL_ERROR; + return -1; + } + + if (rl->read_cipher_suite != TLS_NULL_WITH_NULL_NULL) { + size_t plen; + if (wpa2_crypto_funcs.crypto_cipher_decrypt) { + if ((int)wpa2_crypto_funcs.crypto_cipher_decrypt(rl->read_cbc, in_data, + out_data, in_len) < 0) { + *alert = TLS_ALERT_DECRYPTION_FAILED; + return -1; + } + } else { + wpa_printf(MSG_ERROR, "Fail to register crypto cipher decrypt function. \r\n"); + *alert = TLS_ALERT_DECRYPTION_FAILED; + return -1; + } + plen = in_len; + wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Record Layer - Decrypted " + "data", out_data, plen); + + if (rl->iv_size) { + /* + * TLS v1.0 defines different alert values for various + * failures. That may information to aid in attacks, so + * use the same bad_record_mac alert regardless of the + * issues. + * + * In addition, instead of returning immediately on + * error, run through the MAC check to make timing + * attacks more difficult. + */ + + if (rl->tls_version >= TLS_VERSION_1_1) { + /* Remove opaque IV[Cipherspec.block_length] */ + if (plen < rl->iv_size) { + wpa_printf(MSG_DEBUG, "TLSv1.1: Not " + "enough room for IV"); + force_mac_error = 1; + goto check_mac; + } + os_memmove(out_data, out_data + rl->iv_size, + plen - rl->iv_size); + plen -= rl->iv_size; + } + + /* Verify and remove padding */ + if (plen == 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short record" + " (no pad)"); + force_mac_error = 1; + goto check_mac; + } + padlen = out_data[plen - 1]; + if (padlen >= plen) { + wpa_printf(MSG_DEBUG, "TLSv1: Incorrect pad " + "length (%u, plen=%lu) in " + "received record", + padlen, (unsigned long) plen); + force_mac_error = 1; + goto check_mac; + } + for (i = plen - padlen - 1; i < plen - 1; i++) { + if (out_data[i] != padlen) { + wpa_hexdump(MSG_DEBUG, + "TLSv1: Invalid pad in " + "received record", + out_data + plen - padlen - + 1, padlen + 1); + force_mac_error = 1; + goto check_mac; + } + } + + plen -= padlen + 1; + + wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Record Layer - " + "Decrypted data with IV and padding " + "removed", out_data, plen); + } + + check_mac: + if (plen < rl->hash_size) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short record; no " + "hash value"); + *alert = TLS_ALERT_BAD_RECORD_MAC; + return -1; + } + + plen -= rl->hash_size; + + if (wpa2_crypto_funcs.crypto_hash_init) { + hmac = wpa2_crypto_funcs.crypto_hash_init(rl->hash_alg, rl->read_mac_secret, rl->hash_size); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register crypto_hash_init function!\r\n", __FUNCTION__); + return -1; + } + + if (hmac == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed " + "to initialize HMAC"); + *alert = TLS_ALERT_INTERNAL_ERROR; + return -1; + } + + if (wpa2_crypto_funcs.crypto_hash_update) { + wpa2_crypto_funcs.crypto_hash_update(hmac, rl->read_seq_num, TLS_SEQ_NUM_LEN); + /* type + version + length + fragment */ + wpa2_crypto_funcs.crypto_hash_update(hmac, in_data - TLS_RECORD_HEADER_LEN, 3); + WPA_PUT_BE16(len, plen); + wpa2_crypto_funcs.crypto_hash_update(hmac, len, 2); + wpa2_crypto_funcs.crypto_hash_update(hmac, out_data, plen); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register crypto hash update function!\r\n", __FUNCTION__); + return -1; + } + hlen = sizeof(hash); + if (wpa2_crypto_funcs.crypto_hash_finish) { + if ((int)wpa2_crypto_funcs.crypto_hash_finish(hmac, hash, (int *)&hlen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Record Layer - Failed to calculate HMAC"); + *alert = TLS_ALERT_INTERNAL_ERROR; + return -1; + } + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register crypto_hash_finish function!\r\n", __FUNCTION__); + *alert = TLS_ALERT_INTERNAL_ERROR; + return -1; + } + if (hlen != rl->hash_size || + os_memcmp(hash, out_data + plen, hlen) != 0 || + force_mac_error) { + wpa_printf(MSG_DEBUG, "TLSv1: Invalid HMAC value in " + "received message (force_mac_error=%d)", + force_mac_error); + *alert = TLS_ALERT_BAD_RECORD_MAC; + return -1; + } + + *out_len = plen; + } else { + os_memcpy(out_data, in_data, in_len); + *out_len = in_len; + } + + /* TLSCompressed must not be more than 2^14+1024 bytes */ + if (TLS_RECORD_HEADER_LEN + *out_len > 17408) { + wpa_printf(MSG_DEBUG, "TLSv1: Record overflow (len=%lu)", + (unsigned long) (TLS_RECORD_HEADER_LEN + *out_len)); + *alert = TLS_ALERT_RECORD_OVERFLOW; + return -1; + } + + inc_byte_array(rl->read_seq_num, TLS_SEQ_NUM_LEN); + + return TLS_RECORD_HEADER_LEN + rlen; +} diff --git a/components/wpa_supplicant/src/wpa2/tls/tlsv1_server.c b/components/wpa_supplicant/src/wpa2/tls/tlsv1_server.c new file mode 100644 index 0000000000..642b09c7b7 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/tls/tlsv1_server.c @@ -0,0 +1,656 @@ +/* + * TLS v1.0/v1.1/v1.2 server (RFC 2246, RFC 4346, RFC 5246) + * Copyright (c) 2006-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "crypto/sha1.h" +#include "wpa2/tls/tls.h" +#include "wpa2/tls/tlsv1_common.h" +#include "wpa2/tls/tlsv1_record.h" +#include "wpa2/tls/tlsv1_server.h" +#include "wpa2/tls/tlsv1_server_i.h" + +/* TODO: + * Support for a message fragmented across several records (RFC 2246, 6.2.1) + */ + + +void tlsv1_server_alert(struct tlsv1_server *conn, u8 level, u8 description) +{ + conn->alert_level = level; + conn->alert_description = description; +} + + +int tlsv1_server_derive_keys(struct tlsv1_server *conn, + const u8 *pre_master_secret, + size_t pre_master_secret_len) +{ + u8 seed[2 * TLS_RANDOM_LEN]; + u8 key_block[TLS_MAX_KEY_BLOCK_LEN]; + u8 *pos; + size_t key_block_len; + + if (pre_master_secret) { + wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: pre_master_secret", + pre_master_secret, pre_master_secret_len); + os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); + os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, + TLS_RANDOM_LEN); + if (tls_prf(conn->rl.tls_version, + pre_master_secret, pre_master_secret_len, + "master secret", seed, 2 * TLS_RANDOM_LEN, + conn->master_secret, TLS_MASTER_SECRET_LEN)) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive " + "master_secret"); + return -1; + } + wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: master_secret", + conn->master_secret, TLS_MASTER_SECRET_LEN); + } + + os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); + os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, TLS_RANDOM_LEN); + key_block_len = 2 * (conn->rl.hash_size + conn->rl.key_material_len + + conn->rl.iv_size); + if (tls_prf(conn->rl.tls_version, + conn->master_secret, TLS_MASTER_SECRET_LEN, + "key expansion", seed, 2 * TLS_RANDOM_LEN, + key_block, key_block_len)) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive key_block"); + return -1; + } + wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: key_block", + key_block, key_block_len); + + pos = key_block; + + /* client_write_MAC_secret */ + os_memcpy(conn->rl.read_mac_secret, pos, conn->rl.hash_size); + pos += conn->rl.hash_size; + /* server_write_MAC_secret */ + os_memcpy(conn->rl.write_mac_secret, pos, conn->rl.hash_size); + pos += conn->rl.hash_size; + + /* client_write_key */ + os_memcpy(conn->rl.read_key, pos, conn->rl.key_material_len); + pos += conn->rl.key_material_len; + /* server_write_key */ + os_memcpy(conn->rl.write_key, pos, conn->rl.key_material_len); + pos += conn->rl.key_material_len; + + /* client_write_IV */ + os_memcpy(conn->rl.read_iv, pos, conn->rl.iv_size); + pos += conn->rl.iv_size; + /* server_write_IV */ + os_memcpy(conn->rl.write_iv, pos, conn->rl.iv_size); + pos += conn->rl.iv_size; + + return 0; +} + + +/** + * tlsv1_server_handshake - Process TLS handshake + * @conn: TLSv1 server connection data from tlsv1_server_init() + * @in_data: Input data from TLS peer + * @in_len: Input data length + * @out_len: Length of the output buffer. + * Returns: Pointer to output data, %NULL on failure + */ +u8 * tlsv1_server_handshake(struct tlsv1_server *conn, + const u8 *in_data, size_t in_len, + size_t *out_len) +{ + const u8 *pos, *end; + u8 *msg = NULL, *in_msg, *in_pos, *in_end, alert, ct; + size_t in_msg_len; + int used; + + if (in_data == NULL || in_len == 0) { + wpa_printf(MSG_DEBUG, "TLSv1: No input data to server"); + return NULL; + } + + pos = in_data; + end = in_data + in_len; + in_msg = os_malloc(in_len); + if (in_msg == NULL) + return NULL; + + /* Each received packet may include multiple records */ + while (pos < end) { + in_msg_len = in_len; + used = tlsv1_record_receive(&conn->rl, pos, end - pos, + in_msg, &in_msg_len, &alert); + if (used < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Processing received " + "record failed"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); + goto failed; + } + if (used == 0) { + /* need more data */ + wpa_printf(MSG_DEBUG, "TLSv1: Partial processing not " + "yet supported"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); + goto failed; + } + ct = pos[0]; + + in_pos = in_msg; + in_end = in_msg + in_msg_len; + + /* Each received record may include multiple messages of the + * same ContentType. */ + while (in_pos < in_end) { + in_msg_len = in_end - in_pos; + if (tlsv1_server_process_handshake(conn, ct, in_pos, + &in_msg_len) < 0) + goto failed; + in_pos += in_msg_len; + } + + pos += used; + } + + os_free(in_msg); + in_msg = NULL; + + msg = tlsv1_server_handshake_write(conn, out_len); + +failed: + os_free(in_msg); + if (conn->alert_level) { + if (conn->state == FAILED) { + /* Avoid alert loops */ + wpa_printf(MSG_DEBUG, "TLSv1: Drop alert loop"); + os_free(msg); + return NULL; + } + conn->state = FAILED; + os_free(msg); + msg = tlsv1_server_send_alert(conn, conn->alert_level, + conn->alert_description, + out_len); + } + + return msg; +} + + +/** + * tlsv1_server_encrypt - Encrypt data into TLS tunnel + * @conn: TLSv1 server connection data from tlsv1_server_init() + * @in_data: Pointer to plaintext data to be encrypted + * @in_len: Input buffer length + * @out_data: Pointer to output buffer (encrypted TLS data) + * @out_len: Maximum out_data length + * Returns: Number of bytes written to out_data, -1 on failure + * + * This function is used after TLS handshake has been completed successfully to + * send data in the encrypted tunnel. + */ +int tlsv1_server_encrypt(struct tlsv1_server *conn, + const u8 *in_data, size_t in_len, + u8 *out_data, size_t out_len) +{ + size_t rlen; + + wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Plaintext AppData", + in_data, in_len); + + if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_APPLICATION_DATA, + out_data, out_len, in_data, in_len, &rlen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + return rlen; +} + + +/** + * tlsv1_server_decrypt - Decrypt data from TLS tunnel + * @conn: TLSv1 server connection data from tlsv1_server_init() + * @in_data: Pointer to input buffer (encrypted TLS data) + * @in_len: Input buffer length + * @out_data: Pointer to output buffer (decrypted data from TLS tunnel) + * @out_len: Maximum out_data length + * Returns: Number of bytes written to out_data, -1 on failure + * + * This function is used after TLS handshake has been completed successfully to + * receive data from the encrypted tunnel. + */ +int tlsv1_server_decrypt(struct tlsv1_server *conn, + const u8 *in_data, size_t in_len, + u8 *out_data, size_t out_len) +{ + const u8 *in_end, *pos; + int used; + u8 alert, *out_end, *out_pos, ct; + size_t olen; + + pos = in_data; + in_end = in_data + in_len; + out_pos = out_data; + out_end = out_data + out_len; + + while (pos < in_end) { + ct = pos[0]; + olen = out_end - out_pos; + used = tlsv1_record_receive(&conn->rl, pos, in_end - pos, + out_pos, &olen, &alert); + if (used < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Record layer processing " + "failed"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); + return -1; + } + if (used == 0) { + /* need more data */ + wpa_printf(MSG_DEBUG, "TLSv1: Partial processing not " + "yet supported"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, alert); + return -1; + } + + if (ct == TLS_CONTENT_TYPE_ALERT) { + if (olen < 2) { + wpa_printf(MSG_DEBUG, "TLSv1: Alert " + "underflow"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", + out_pos[0], out_pos[1]); + if (out_pos[0] == TLS_ALERT_LEVEL_WARNING) { + /* Continue processing */ + pos += used; + continue; + } + + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + out_pos[1]); + return -1; + } + + if (ct != TLS_CONTENT_TYPE_APPLICATION_DATA) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected content type " + "0x%x", pos[0]); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + out_pos += olen; + if (out_pos > out_end) { + wpa_printf(MSG_DEBUG, "TLSv1: Buffer not large enough " + "for processing the received record"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + pos += used; + } + + return out_pos - out_data; +} + + +/** + * tlsv1_server_global_init - Initialize TLSv1 server + * Returns: 0 on success, -1 on failure + * + * This function must be called before using any other TLSv1 server functions. + */ +int tlsv1_server_global_init(void) +{ + return crypto_global_init(); +} + + +/** + * tlsv1_server_global_deinit - Deinitialize TLSv1 server + * + * This function can be used to deinitialize the TLSv1 server that was + * initialized by calling tlsv1_server_global_init(). No TLSv1 server functions + * can be called after this before calling tlsv1_server_global_init() again. + */ +void tlsv1_server_global_deinit(void) +{ + crypto_global_deinit(); +} + + +/** + * tlsv1_server_init - Initialize TLSv1 server connection + * @cred: Pointer to server credentials from tlsv1_server_cred_alloc() + * Returns: Pointer to TLSv1 server connection data or %NULL on failure + */ +struct tlsv1_server * tlsv1_server_init(struct tlsv1_credentials *cred) +{ + struct tlsv1_server *conn; + size_t count; + u16 *suites; + + conn = (struct tlsv1_server *)os_zalloc(sizeof(*conn)); + if (conn == NULL) + return NULL; + + conn->cred = cred; + + conn->state = CLIENT_HELLO; + + if (tls_verify_hash_init(&conn->verify) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to initialize verify " + "hash"); + os_free(conn); + return NULL; + } + + count = 0; + suites = conn->cipher_suites; + suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; + suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; + suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; + suites[count++] = TLS_RSA_WITH_RC4_128_SHA; + suites[count++] = TLS_RSA_WITH_RC4_128_MD5; + conn->num_cipher_suites = count; + + return conn; +} + + +static void tlsv1_server_clear_data(struct tlsv1_server *conn) +{ + tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); + tlsv1_record_change_write_cipher(&conn->rl); + tlsv1_record_change_read_cipher(&conn->rl); + tls_verify_hash_free(&conn->verify); + + crypto_public_key_free(conn->client_rsa_key); + conn->client_rsa_key = NULL; + + os_free(conn->session_ticket); + conn->session_ticket = NULL; + conn->session_ticket_len = 0; + conn->use_session_ticket = 0; + + os_free(conn->dh_secret); + conn->dh_secret = NULL; + conn->dh_secret_len = 0; +} + + +/** + * tlsv1_server_deinit - Deinitialize TLSv1 server connection + * @conn: TLSv1 server connection data from tlsv1_server_init() + */ +void tlsv1_server_deinit(struct tlsv1_server *conn) +{ + tlsv1_server_clear_data(conn); + os_free(conn); +} + + +/** + * tlsv1_server_established - Check whether connection has been established + * @conn: TLSv1 server connection data from tlsv1_server_init() + * Returns: 1 if connection is established, 0 if not + */ +int tlsv1_server_established(struct tlsv1_server *conn) +{ + return conn->state == ESTABLISHED; +} + + +/** + * tlsv1_server_prf - Use TLS-PRF to derive keying material + * @conn: TLSv1 server connection data from tlsv1_server_init() + * @label: Label (e.g., description of the key) for PRF + * @server_random_first: seed is 0 = client_random|server_random, + * 1 = server_random|client_random + * @out: Buffer for output data from TLS-PRF + * @out_len: Length of the output buffer + * Returns: 0 on success, -1 on failure + */ +int tlsv1_server_prf(struct tlsv1_server *conn, const char *label, + int server_random_first, u8 *out, size_t out_len) +{ + u8 seed[2 * TLS_RANDOM_LEN]; + + if (conn->state != ESTABLISHED) + return -1; + + if (server_random_first) { + os_memcpy(seed, conn->server_random, TLS_RANDOM_LEN); + os_memcpy(seed + TLS_RANDOM_LEN, conn->client_random, + TLS_RANDOM_LEN); + } else { + os_memcpy(seed, conn->client_random, TLS_RANDOM_LEN); + os_memcpy(seed + TLS_RANDOM_LEN, conn->server_random, + TLS_RANDOM_LEN); + } + + return tls_prf(conn->rl.tls_version, + conn->master_secret, TLS_MASTER_SECRET_LEN, + label, seed, 2 * TLS_RANDOM_LEN, out, out_len); +} + + +/** + * tlsv1_server_get_cipher - Get current cipher name + * @conn: TLSv1 server connection data from tlsv1_server_init() + * @buf: Buffer for the cipher name + * @buflen: buf size + * Returns: 0 on success, -1 on failure + * + * Get the name of the currently used cipher. + */ +int tlsv1_server_get_cipher(struct tlsv1_server *conn, char *buf, + size_t buflen) +{ +#ifndef ESPRESSIF_USE + char *cipher; + + switch (conn->rl.cipher_suite) { + case TLS_RSA_WITH_RC4_128_MD5: + cipher = "RC4-MD5"; + break; + case TLS_RSA_WITH_RC4_128_SHA: + cipher = "RC4-SHA"; + break; + case TLS_RSA_WITH_DES_CBC_SHA: + cipher = "DES-CBC-SHA"; + break; + case TLS_RSA_WITH_3DES_EDE_CBC_SHA: + cipher = "DES-CBC3-SHA"; + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + cipher = "ADH-AES-128-SHA"; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA: + cipher = "AES-256-SHA"; + break; + case TLS_RSA_WITH_AES_128_CBC_SHA: + cipher = "AES-128-SHA"; + break; + default: + return -1; + } + + //if (os_strlcpy(buf, cipher, buflen) >= buflen) + // return -1; + + os_memcpy((u8 *)buf, (u8 *)cipher, buflen); + + return 0; +#else + char cipher[20]; + + switch (conn->rl.cipher_suite) { + case TLS_RSA_WITH_RC4_128_MD5: + strcpy(cipher, "RC4-MD5"); + break; + case TLS_RSA_WITH_RC4_128_SHA: + strcpy(cipher, "RC4-SHA"); + break; + case TLS_RSA_WITH_DES_CBC_SHA: + strcpy(cipher, "DES-CBC-SHA"); + break; + case TLS_RSA_WITH_3DES_EDE_CBC_SHA: + strcpy(cipher, "DES-CBC3-SHA"); + break; + case TLS_DH_anon_WITH_AES_128_CBC_SHA: + strcpy(cipher, "ADH-AES-128-SHA"); + break; + case TLS_RSA_WITH_AES_256_CBC_SHA: + strcpy(cipher, "AES-256-SHA"); + break; + case TLS_RSA_WITH_AES_128_CBC_SHA: + strcpy(cipher, "AES-128-SHA"); + break; + default: + return -1; + } + os_memcpy((u8 *)buf, (u8 *)cipher, buflen); + + return 0; +#endif +} + + +/** + * tlsv1_server_shutdown - Shutdown TLS connection + * @conn: TLSv1 server connection data from tlsv1_server_init() + * Returns: 0 on success, -1 on failure + */ +int tlsv1_server_shutdown(struct tlsv1_server *conn) +{ + conn->state = CLIENT_HELLO; + + if (tls_verify_hash_init(&conn->verify) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify " + "hash"); + return -1; + } + + tlsv1_server_clear_data(conn); + + return 0; +} + + +/** + * tlsv1_server_resumed - Was session resumption used + * @conn: TLSv1 server connection data from tlsv1_server_init() + * Returns: 1 if current session used session resumption, 0 if not + */ +int tlsv1_server_resumed(struct tlsv1_server *conn) +{ + return 0; +} + + +/** + * tlsv1_server_get_keys - Get master key and random data from TLS connection + * @conn: TLSv1 server connection data from tlsv1_server_init() + * @keys: Structure of key/random data (filled on success) + * Returns: 0 on success, -1 on failure + */ +int tlsv1_server_get_keys(struct tlsv1_server *conn, struct tls_keys *keys) +{ + os_memset(keys, 0, sizeof(*keys)); + if (conn->state == CLIENT_HELLO) + return -1; + + keys->client_random = conn->client_random; + keys->client_random_len = TLS_RANDOM_LEN; + + if (conn->state != SERVER_HELLO) { + keys->server_random = conn->server_random; + keys->server_random_len = TLS_RANDOM_LEN; + keys->master_key = conn->master_secret; + keys->master_key_len = TLS_MASTER_SECRET_LEN; + } + + return 0; +} + + +/** + * tlsv1_server_get_keyblock_size - Get TLS key_block size + * @conn: TLSv1 server connection data from tlsv1_server_init() + * Returns: Size of the key_block for the negotiated cipher suite or -1 on + * failure + */ +int tlsv1_server_get_keyblock_size(struct tlsv1_server *conn) +{ + if (conn->state == CLIENT_HELLO || conn->state == SERVER_HELLO) + return -1; + + return 2 * (conn->rl.hash_size + conn->rl.key_material_len + + conn->rl.iv_size); +} + + +/** + * tlsv1_server_set_cipher_list - Configure acceptable cipher suites + * @conn: TLSv1 server connection data from tlsv1_server_init() + * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers + * (TLS_CIPHER_*). + * Returns: 0 on success, -1 on failure + */ +int tlsv1_server_set_cipher_list(struct tlsv1_server *conn, u8 *ciphers) +{ + size_t count; + u16 *suites; + + /* TODO: implement proper configuration of cipher suites */ + if (ciphers[0] == TLS_CIPHER_ANON_DH_AES128_SHA) { + count = 0; + suites = conn->cipher_suites; + suites[count++] = TLS_RSA_WITH_AES_256_CBC_SHA; + suites[count++] = TLS_RSA_WITH_AES_128_CBC_SHA; + suites[count++] = TLS_RSA_WITH_3DES_EDE_CBC_SHA; + suites[count++] = TLS_RSA_WITH_RC4_128_SHA; + suites[count++] = TLS_RSA_WITH_RC4_128_MD5; + suites[count++] = TLS_DH_anon_WITH_AES_256_CBC_SHA; + suites[count++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; + suites[count++] = TLS_DH_anon_WITH_3DES_EDE_CBC_SHA; + suites[count++] = TLS_DH_anon_WITH_RC4_128_MD5; + suites[count++] = TLS_DH_anon_WITH_DES_CBC_SHA; + conn->num_cipher_suites = count; + } + + return 0; +} + + +int tlsv1_server_set_verify(struct tlsv1_server *conn, int verify_peer) +{ + conn->verify_peer = verify_peer; + return 0; +} + + +void tlsv1_server_set_session_ticket_cb(struct tlsv1_server *conn, + tlsv1_server_session_ticket_cb cb, + void *ctx) +{ + wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback set %p (ctx %p)", + cb, ctx); + conn->session_ticket_cb = cb; + conn->session_ticket_cb_ctx = ctx; +} diff --git a/components/wpa_supplicant/src/wpa2/tls/tlsv1_server_read.c b/components/wpa_supplicant/src/wpa2/tls/tlsv1_server_read.c new file mode 100644 index 0000000000..ee477c98a0 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/tls/tlsv1_server_read.c @@ -0,0 +1,1278 @@ +/* + * TLSv1 server - read handshake message + * Copyright (c) 2006-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "crypto/md5.h" +#include "crypto/sha1.h" +#include "crypto/sha256.h" +#include "wpa2/tls/tls.h" +#include "wpa2/tls/x509v3.h" +#include "wpa2/tls/tlsv1_common.h" +#include "wpa2/tls/tlsv1_record.h" +#include "wpa2/tls/tlsv1_server.h" +#include "wpa2/tls/tlsv1_server_i.h" + +#include "wpa2/eap_peer/eap_i.h" + +static int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct, + const u8 *in_data, size_t *in_len); +static int tls_process_change_cipher_spec(struct tlsv1_server *conn, + u8 ct, const u8 *in_data, + size_t *in_len); + + +static int tls_process_client_hello(struct tlsv1_server *conn, u8 ct, + const u8 *in_data, size_t *in_len) +{ + const u8 *pos, *end, *c; + size_t left, len, i, j; + u16 cipher_suite; + u16 num_suites; + int compr_null_found; + u16 ext_type, ext_len; + + if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " + "received content type 0x%x", ct); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + pos = in_data; + left = *in_len; + + if (left < 4) + goto decode_error; + + /* HandshakeType msg_type */ + if (*pos != TLS_HANDSHAKE_TYPE_CLIENT_HELLO) { + wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " + "message %d (expected ClientHello)", *pos); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + wpa_printf(MSG_DEBUG, "TLSv1: Received ClientHello"); + pos++; + /* uint24 length */ + len = WPA_GET_BE24(pos); + pos += 3; + left -= 4; + + if (len > left) + goto decode_error; + + /* body - ClientHello */ + + wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello", pos, len); + end = pos + len; + + /* ProtocolVersion client_version */ + if (end - pos < 2) + goto decode_error; + conn->client_version = WPA_GET_BE16(pos); + wpa_printf(MSG_DEBUG, "TLSv1: Client version %d.%d", + conn->client_version >> 8, conn->client_version & 0xff); + if (conn->client_version < TLS_VERSION_1) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected protocol version in " + "ClientHello %u.%u", + conn->client_version >> 8, + conn->client_version & 0xff); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_PROTOCOL_VERSION); + return -1; + } + pos += 2; + + if (TLS_VERSION == TLS_VERSION_1) + conn->rl.tls_version = TLS_VERSION_1; +#ifdef CONFIG_TLSV12 + else if (conn->client_version >= TLS_VERSION_1_2) + conn->rl.tls_version = TLS_VERSION_1_2; +#endif /* CONFIG_TLSV12 */ + else if (conn->client_version > TLS_VERSION_1_1) + conn->rl.tls_version = TLS_VERSION_1_1; + else + conn->rl.tls_version = conn->client_version; + wpa_printf(MSG_DEBUG, "TLSv1: Using TLS v%s", + tls_version_str(conn->rl.tls_version)); + + /* Random random */ + if (end - pos < TLS_RANDOM_LEN) + goto decode_error; + + os_memcpy(conn->client_random, pos, TLS_RANDOM_LEN); + pos += TLS_RANDOM_LEN; + wpa_hexdump(MSG_MSGDUMP, "TLSv1: client_random", + conn->client_random, TLS_RANDOM_LEN); + + /* SessionID session_id */ + if (end - pos < 1) + goto decode_error; + if (end - pos < 1 + *pos || *pos > TLS_SESSION_ID_MAX_LEN) + goto decode_error; + wpa_hexdump(MSG_MSGDUMP, "TLSv1: client session_id", pos + 1, *pos); + pos += 1 + *pos; + /* TODO: add support for session resumption */ + + /* CipherSuite cipher_suites<2..2^16-1> */ + if (end - pos < 2) + goto decode_error; + num_suites = WPA_GET_BE16(pos); + pos += 2; + if (end - pos < num_suites) + goto decode_error; + wpa_hexdump(MSG_MSGDUMP, "TLSv1: client cipher suites", + pos, num_suites); + if (num_suites & 1) + goto decode_error; + num_suites /= 2; + + cipher_suite = 0; + for (i = 0; !cipher_suite && i < conn->num_cipher_suites; i++) { + c = pos; + for (j = 0; j < num_suites; j++) { + u16 tmp = WPA_GET_BE16(c); + c += 2; + if (!cipher_suite && tmp == conn->cipher_suites[i]) { + cipher_suite = tmp; + break; + } + } + } + pos += num_suites * 2; + if (!cipher_suite) { + wpa_printf(MSG_INFO, "TLSv1: No supported cipher suite " + "available"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_ILLEGAL_PARAMETER); + return -1; + } + + if (tlsv1_record_set_cipher_suite(&conn->rl, cipher_suite) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to set CipherSuite for " + "record layer"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + conn->cipher_suite = cipher_suite; + + /* CompressionMethod compression_methods<1..2^8-1> */ + if (end - pos < 1) + goto decode_error; + num_suites = *pos++; + if (end - pos < num_suites) + goto decode_error; + wpa_hexdump(MSG_MSGDUMP, "TLSv1: client compression_methods", + pos, num_suites); + compr_null_found = 0; + for (i = 0; i < num_suites; i++) { + if (*pos++ == TLS_COMPRESSION_NULL) + compr_null_found = 1; + } + if (!compr_null_found) { + wpa_printf(MSG_INFO, "TLSv1: Client does not accept NULL " + "compression"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_ILLEGAL_PARAMETER); + return -1; + } + + if (end - pos == 1) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected extra octet in the " + "end of ClientHello: 0x%02x", *pos); + goto decode_error; + } + + if (end - pos >= 2) { + /* Extension client_hello_extension_list<0..2^16-1> */ + ext_len = WPA_GET_BE16(pos); + pos += 2; + + wpa_printf(MSG_DEBUG, "TLSv1: %u bytes of ClientHello " + "extensions", ext_len); + if (end - pos != ext_len) { + wpa_printf(MSG_DEBUG, "TLSv1: Invalid ClientHello " + "extension list length %u (expected %u)", + ext_len, (unsigned int) (end - pos)); + goto decode_error; + } + + /* + * struct { + * ExtensionType extension_type (0..65535) + * opaque extension_data<0..2^16-1> + * } Extension; + */ + + while (pos < end) { + if (end - pos < 2) { + wpa_printf(MSG_DEBUG, "TLSv1: Invalid " + "extension_type field"); + goto decode_error; + } + + ext_type = WPA_GET_BE16(pos); + pos += 2; + + if (end - pos < 2) { + wpa_printf(MSG_DEBUG, "TLSv1: Invalid " + "extension_data length field"); + goto decode_error; + } + + ext_len = WPA_GET_BE16(pos); + pos += 2; + + if (end - pos < ext_len) { + wpa_printf(MSG_DEBUG, "TLSv1: Invalid " + "extension_data field"); + goto decode_error; + } + + wpa_printf(MSG_DEBUG, "TLSv1: ClientHello Extension " + "type %u", ext_type); + wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientHello " + "Extension data", pos, ext_len); + + if (ext_type == TLS_EXT_SESSION_TICKET) { + os_free(conn->session_ticket); + conn->session_ticket = os_malloc(ext_len); + if (conn->session_ticket) { + os_memcpy(conn->session_ticket, pos, + ext_len); + conn->session_ticket_len = ext_len; + } + } + + pos += ext_len; + } + } + + *in_len = end - in_data; + + wpa_printf(MSG_DEBUG, "TLSv1: ClientHello OK - proceed to " + "ServerHello"); + conn->state = SERVER_HELLO; + + return 0; + +decode_error: + wpa_printf(MSG_DEBUG, "TLSv1: Failed to decode ClientHello"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; +} + + +static int tls_process_certificate(struct tlsv1_server *conn, u8 ct, + const u8 *in_data, size_t *in_len) +{ + const u8 *pos, *end; + size_t left, len, list_len, cert_len, idx; + u8 type; + struct x509_certificate *chain = NULL, *last = NULL, *cert; + int reason; + + if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " + "received content type 0x%x", ct); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + pos = in_data; + left = *in_len; + + if (left < 4) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message " + "(len=%lu)", (unsigned long) left); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + + type = *pos++; + len = WPA_GET_BE24(pos); + pos += 3; + left -= 4; + + if (len > left) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message " + "length (len=%lu != left=%lu)", + (unsigned long) len, (unsigned long) left); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + + if (type == TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) { + if (conn->verify_peer) { + wpa_printf(MSG_DEBUG, "TLSv1: Client did not include " + "Certificate"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + return tls_process_client_key_exchange(conn, ct, in_data, + in_len); + } + if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) { + wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " + "message %d (expected Certificate/" + "ClientKeyExchange)", type); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + wpa_printf(MSG_DEBUG, "TLSv1: Received Certificate (certificate_list len %lu)", + (unsigned long) len); + + /* + * opaque ASN.1Cert<2^24-1>; + * + * struct { + * ASN.1Cert certificate_list<1..2^24-1>; + * } Certificate; + */ + + end = pos + len; + + if (end - pos < 3) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate " + "(left=%lu)", (unsigned long) left); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + + list_len = WPA_GET_BE24(pos); + pos += 3; + + if ((size_t) (end - pos) != list_len) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list " + "length (len=%lu left=%lu)", + (unsigned long) list_len, + (unsigned long) (end - pos)); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + + idx = 0; + while (pos < end) { + if (end - pos < 3) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " + "certificate_list"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + x509_certificate_chain_free(chain); + return -1; + } + + cert_len = WPA_GET_BE24(pos); + pos += 3; + + if ((size_t) (end - pos) < cert_len) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate " + "length (len=%lu left=%lu)", + (unsigned long) cert_len, + (unsigned long) (end - pos)); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + x509_certificate_chain_free(chain); + return -1; + } + + wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)", + (unsigned long) idx, (unsigned long) cert_len); + + if (idx == 0) { + crypto_public_key_free(conn->client_rsa_key); + if (tls_parse_cert(pos, cert_len, + &conn->client_rsa_key)) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " + "the certificate"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_BAD_CERTIFICATE); + x509_certificate_chain_free(chain); + return -1; + } + } + + cert = x509_certificate_parse(pos, cert_len); + if (cert == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " + "the certificate"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_BAD_CERTIFICATE); + x509_certificate_chain_free(chain); + return -1; + } + + if (last == NULL) + chain = cert; + else + last->next = cert; + last = cert; + + idx++; + pos += cert_len; + } + + if (x509_certificate_chain_validate(conn->cred->trusted_certs, chain, + &reason, 0) < 0) { + int tls_reason; + wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain " + "validation failed (reason=%d)", reason); + switch (reason) { + case X509_VALIDATE_BAD_CERTIFICATE: + tls_reason = TLS_ALERT_BAD_CERTIFICATE; + break; + case X509_VALIDATE_UNSUPPORTED_CERTIFICATE: + tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE; + break; + case X509_VALIDATE_CERTIFICATE_REVOKED: + tls_reason = TLS_ALERT_CERTIFICATE_REVOKED; + break; + case X509_VALIDATE_CERTIFICATE_EXPIRED: + tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED; + break; + case X509_VALIDATE_CERTIFICATE_UNKNOWN: + tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN; + break; + case X509_VALIDATE_UNKNOWN_CA: + tls_reason = TLS_ALERT_UNKNOWN_CA; + break; + default: + tls_reason = TLS_ALERT_BAD_CERTIFICATE; + break; + } + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason); + x509_certificate_chain_free(chain); + return -1; + } + + x509_certificate_chain_free(chain); + + *in_len = end - in_data; + + conn->state = CLIENT_KEY_EXCHANGE; + + return 0; +} + + +static int tls_process_client_key_exchange_rsa( + struct tlsv1_server *conn, const u8 *pos, const u8 *end) +{ + u8 *out; + size_t outlen, outbuflen; + u16 encr_len; + int res; + int use_random = 0; + + if (end - pos < 2) { + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + + encr_len = WPA_GET_BE16(pos); + pos += 2; + if (pos + encr_len > end) { + wpa_printf(MSG_DEBUG, "TLSv1: Invalid ClientKeyExchange " + "format: encr_len=%u left=%u", + encr_len, (unsigned int) (end - pos)); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + + outbuflen = outlen = end - pos; + out = os_malloc(outlen >= TLS_PRE_MASTER_SECRET_LEN ? + outlen : TLS_PRE_MASTER_SECRET_LEN); + if (out == NULL) { + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + /* + * struct { + * ProtocolVersion client_version; + * opaque random[46]; + * } PreMasterSecret; + * + * struct { + * public-key-encrypted PreMasterSecret pre_master_secret; + * } EncryptedPreMasterSecret; + */ + + /* + * Note: To avoid Bleichenbacher attack, we do not report decryption or + * parsing errors from EncryptedPreMasterSecret processing to the + * client. Instead, a random pre-master secret is used to force the + * handshake to fail. + */ + + if (crypto_private_key_decrypt_pkcs1_v15(conn->cred->key, + pos, encr_len, + out, &outlen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt " + "PreMasterSecret (encr_len=%u outlen=%lu)", + encr_len, (unsigned long) outlen); + use_random = 1; + } + + if (!use_random && outlen != TLS_PRE_MASTER_SECRET_LEN) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected PreMasterSecret " + "length %lu", (unsigned long) outlen); + use_random = 1; + } + + if (!use_random && WPA_GET_BE16(out) != conn->client_version) { + wpa_printf(MSG_DEBUG, "TLSv1: Client version in " + "ClientKeyExchange does not match with version in " + "ClientHello"); + use_random = 1; + } + + if (use_random) { + wpa_printf(MSG_DEBUG, "TLSv1: Using random premaster secret " + "to avoid revealing information about private key"); + outlen = TLS_PRE_MASTER_SECRET_LEN; + if (os_get_random(out, outlen)) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " + "data"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + os_free(out); + return -1; + } + } + + res = tlsv1_server_derive_keys(conn, out, outlen); + + /* Clear the pre-master secret since it is not needed anymore */ + os_memset(out, 0, outbuflen); + os_free(out); + + if (res) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + return 0; +} + + +static int tls_process_client_key_exchange_dh_anon( + struct tlsv1_server *conn, const u8 *pos, const u8 *end) +{ + const u8 *dh_yc; + u16 dh_yc_len; + u8 *shared; + size_t shared_len; + int res; + + /* + * struct { + * select (PublicValueEncoding) { + * case implicit: struct { }; + * case explicit: opaque dh_Yc<1..2^16-1>; + * } dh_public; + * } ClientDiffieHellmanPublic; + */ + + wpa_hexdump(MSG_MSGDUMP, "TLSv1: ClientDiffieHellmanPublic", + pos, end - pos); + + if (end == pos) { + wpa_printf(MSG_DEBUG, "TLSv1: Implicit public value encoding " + "not supported"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + if (end - pos < 3) { + wpa_printf(MSG_DEBUG, "TLSv1: Invalid client public value " + "length"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + + dh_yc_len = WPA_GET_BE16(pos); + dh_yc = pos + 2; + + if (dh_yc + dh_yc_len > end) { + wpa_printf(MSG_DEBUG, "TLSv1: Client public value overflow " + "(length %d)", dh_yc_len); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + + wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)", + dh_yc, dh_yc_len); + + if (conn->cred == NULL || conn->cred->dh_p == NULL || + conn->dh_secret == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + shared_len = conn->cred->dh_p_len; + shared = os_malloc(shared_len); + if (shared == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: Could not allocate memory for " + "DH"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + /* shared = Yc^secret mod p */ + if (wpa2_crypto_funcs.crypto_mod_exp) { + if (wpa2_crypto_funcs.crypto_mod_exp(dh_yc, dh_yc_len, conn->dh_secret, + conn->dh_secret_len, + conn->cred->dh_p, conn->cred->dh_p_len, + shared, &shared_len)) { + os_free(shared); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + } else { + wpa_printf(MSG_ERROR, "Fail to register crypto_mod_exp function!\r\n"); + os_free(shared); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + wpa_hexdump_key(MSG_DEBUG, "TLSv1: Shared secret from DH key exchange", + shared, shared_len); + + os_memset(conn->dh_secret, 0, conn->dh_secret_len); + os_free(conn->dh_secret); + conn->dh_secret = NULL; + + res = tlsv1_server_derive_keys(conn, shared, shared_len); + + /* Clear the pre-master secret since it is not needed anymore */ + os_memset(shared, 0, shared_len); + os_free(shared); + + if (res) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive keys"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + return 0; +} + + +static int tls_process_client_key_exchange(struct tlsv1_server *conn, u8 ct, + const u8 *in_data, size_t *in_len) +{ + const u8 *pos, *end; + size_t left, len; + u8 type; + tls_key_exchange keyx; + const struct tls_cipher_suite *suite; + + if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " + "received content type 0x%x", ct); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + pos = in_data; + left = *in_len; + + if (left < 4) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short ClientKeyExchange " + "(Left=%lu)", (unsigned long) left); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + + type = *pos++; + len = WPA_GET_BE24(pos); + pos += 3; + left -= 4; + + if (len > left) { + wpa_printf(MSG_DEBUG, "TLSv1: Mismatch in ClientKeyExchange " + "length (len=%lu != left=%lu)", + (unsigned long) len, (unsigned long) left); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + + end = pos + len; + + if (type != TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) { + wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " + "message %d (expected ClientKeyExchange)", type); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + wpa_printf(MSG_DEBUG, "TLSv1: Received ClientKeyExchange"); + + wpa_hexdump(MSG_DEBUG, "TLSv1: ClientKeyExchange", pos, len); + + suite = tls_get_cipher_suite(conn->rl.cipher_suite); + if (suite == NULL) + keyx = TLS_KEY_X_NULL; + else + keyx = suite->key_exchange; + + if (keyx == TLS_KEY_X_DH_anon && + tls_process_client_key_exchange_dh_anon(conn, pos, end) < 0) + return -1; + + if (keyx != TLS_KEY_X_DH_anon && + tls_process_client_key_exchange_rsa(conn, pos, end) < 0) + return -1; + + *in_len = end - in_data; + + conn->state = CERTIFICATE_VERIFY; + + return 0; +} + + +static int tls_process_certificate_verify(struct tlsv1_server *conn, u8 ct, + const u8 *in_data, size_t *in_len) +{ + const u8 *pos, *end; + size_t left, len; + u8 type; + size_t hlen, buflen; + u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN], *hpos, *buf; + enum { SIGN_ALG_RSA, SIGN_ALG_DSA } alg = SIGN_ALG_RSA; + u16 slen; + + if (ct == TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { + if (conn->verify_peer) { + wpa_printf(MSG_DEBUG, "TLSv1: Client did not include " + "CertificateVerify"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + return tls_process_change_cipher_spec(conn, ct, in_data, + in_len); + } + + if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " + "received content type 0x%x", ct); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + pos = in_data; + left = *in_len; + + if (left < 4) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short CertificateVerify " + "message (len=%lu)", (unsigned long) left); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + + type = *pos++; + len = WPA_GET_BE24(pos); + pos += 3; + left -= 4; + + if (len > left) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected CertificateVerify " + "message length (len=%lu != left=%lu)", + (unsigned long) len, (unsigned long) left); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + + end = pos + len; + + if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE_VERIFY) { + wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " + "message %d (expected CertificateVerify)", type); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + wpa_printf(MSG_DEBUG, "TLSv1: Received CertificateVerify"); + + /* + * struct { + * Signature signature; + * } CertificateVerify; + */ + + hpos = hash; + +#ifdef CONFIG_TLSV12 + if (conn->rl.tls_version == TLS_VERSION_1_2) { + /* + * RFC 5246, 4.7: + * TLS v1.2 adds explicit indication of the used signature and + * hash algorithms. + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + */ + if (end - pos < 2) { + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + if (pos[0] != TLS_HASH_ALG_SHA256 || + pos[1] != TLS_SIGN_ALG_RSA) { + wpa_printf(MSG_DEBUG, "TLSv1.2: Unsupported hash(%u)/" + "signature(%u) algorithm", + pos[0], pos[1]); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + pos += 2; + + hlen = SHA256_MAC_LEN; + if (wpa2_crypto_funcs.crypto_hash_finish) { + if (conn->verify.sha256_cert == NULL || + wpa2_crypto_funcs.crypto_hash_finish(conn->verify.sha256_cert, hpos, &hlen) < + 0) { + conn->verify.sha256_cert = NULL; + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + } else { + conn->verify.sha256_cert = NULL; + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + wpa_printf(MSG_ERROR, "In function %s, fail to register crypto_hash_finish function!\r\n", __FUNCTION__); + return -1; + } + conn->verify.sha256_cert = NULL; + } else { +#endif /* CONFIG_TLSV12 */ + + if (alg == SIGN_ALG_RSA) { + hlen = MD5_MAC_LEN; + if (conn->verify.md5_cert == NULL || + crypto_hash_finish(conn->verify.md5_cert, hpos, &hlen) < 0) + { + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + conn->verify.md5_cert = NULL; + crypto_hash_finish(conn->verify.sha1_cert, NULL, NULL); + conn->verify.sha1_cert = NULL; + return -1; + } + hpos += MD5_MAC_LEN; + } else + crypto_hash_finish(conn->verify.md5_cert, NULL, NULL); + + conn->verify.md5_cert = NULL; + hlen = SHA1_MAC_LEN; + if (conn->verify.sha1_cert == NULL || + crypto_hash_finish(conn->verify.sha1_cert, hpos, &hlen) < 0) { + conn->verify.sha1_cert = NULL; + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + conn->verify.sha1_cert = NULL; + + if (alg == SIGN_ALG_RSA) + hlen += MD5_MAC_LEN; + +#ifdef CONFIG_TLSV12 + } +#endif /* CONFIG_TLSV12 */ + + wpa_hexdump(MSG_MSGDUMP, "TLSv1: CertificateVerify hash", hash, hlen); + + if (end - pos < 2) { + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + slen = WPA_GET_BE16(pos); + pos += 2; + if (end - pos < slen) { + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + + wpa_hexdump(MSG_MSGDUMP, "TLSv1: Signature", pos, end - pos); + if (conn->client_rsa_key == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: No client public key to verify " + "signature"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + buflen = end - pos; + buf = os_malloc(end - pos); + if (crypto_public_key_decrypt_pkcs1(conn->client_rsa_key, + pos, end - pos, buf, &buflen) < 0) + { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to decrypt signature"); + os_free(buf); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECRYPT_ERROR); + return -1; + } + + wpa_hexdump_key(MSG_MSGDUMP, "TLSv1: Decrypted Signature", + buf, buflen); + +#ifdef CONFIG_TLSV12 + if (conn->rl.tls_version >= TLS_VERSION_1_2) { + /* + * RFC 3447, A.2.4 RSASSA-PKCS1-v1_5 + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithm, + * digest OCTET STRING + * } + * + * SHA-256 OID: sha256WithRSAEncryption ::= {pkcs-1 11} + * + * DER encoded DigestInfo for SHA256 per RFC 3447: + * 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 || + * H + */ + if (buflen >= 19 + 32 && + os_memcmp(buf, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01" + "\x65\x03\x04\x02\x01\x05\x00\x04\x20", 19) == 0) + { + wpa_printf(MSG_DEBUG, "TLSv1.2: DigestAlgorithn = " + "SHA-256"); + os_memmove(buf, buf + 19, buflen - 19); + buflen -= 19; + } else { + wpa_printf(MSG_DEBUG, "TLSv1.2: Unrecognized " + "DigestInfo"); + os_free(buf); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECRYPT_ERROR); + return -1; + } + } +#endif /* CONFIG_TLSV12 */ + + if (buflen != hlen || os_memcmp(buf, hash, buflen) != 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Invalid Signature in " + "CertificateVerify - did not match with calculated " + "hash"); + os_free(buf); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECRYPT_ERROR); + return -1; + } + + os_free(buf); + + *in_len = end - in_data; + + conn->state = CHANGE_CIPHER_SPEC; + + return 0; +} + + +static int tls_process_change_cipher_spec(struct tlsv1_server *conn, + u8 ct, const u8 *in_data, + size_t *in_len) +{ + const u8 *pos; + size_t left; + + if (ct != TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " + "received content type 0x%x", ct); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + pos = in_data; + left = *in_len; + + if (left < 1) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short ChangeCipherSpec"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + + if (*pos != TLS_CHANGE_CIPHER_SPEC) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected ChangeCipherSpec; " + "received data 0x%x", *pos); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + wpa_printf(MSG_DEBUG, "TLSv1: Received ChangeCipherSpec"); + if (tlsv1_record_change_read_cipher(&conn->rl) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to change read cipher " + "for record layer"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + *in_len = pos + 1 - in_data; + + conn->state = CLIENT_FINISHED; + + return 0; +} + + +static int tls_process_client_finished(struct tlsv1_server *conn, u8 ct, + const u8 *in_data, size_t *in_len) +{ + const u8 *pos, *end; + size_t left, len, hlen; + u8 verify_data[TLS_VERIFY_DATA_LEN]; + u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; + + if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; " + "received content type 0x%x", ct); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + pos = in_data; + left = *in_len; + + if (left < 4) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short record (left=%lu) for " + "Finished", + (unsigned long) left); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + + if (pos[0] != TLS_HANDSHAKE_TYPE_FINISHED) { + wpa_printf(MSG_DEBUG, "TLSv1: Expected Finished; received " + "type 0x%x", pos[0]); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_UNEXPECTED_MESSAGE); + return -1; + } + + len = WPA_GET_BE24(pos + 1); + + pos += 4; + left -= 4; + + if (len > left) { + wpa_printf(MSG_DEBUG, "TLSv1: Too short buffer for Finished " + "(len=%lu > left=%lu)", + (unsigned long) len, (unsigned long) left); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + end = pos + len; + if (len != TLS_VERIFY_DATA_LEN) { + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected verify_data length " + "in Finished: %lu (expected %d)", + (unsigned long) len, TLS_VERIFY_DATA_LEN); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "TLSv1: verify_data in Finished", + pos, TLS_VERIFY_DATA_LEN); + +#ifdef CONFIG_TLSV12 + if (conn->rl.tls_version >= TLS_VERSION_1_2) { + hlen = SHA256_MAC_LEN; + if (wpa2_crypto_funcs.crypto_hash_finish) { + if (conn->verify.sha256_client == NULL || + crypto_hash_finish(conn->verify.sha256_client, hash, &hlen) + < 0) { + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + conn->verify.sha256_client = NULL; + return -1; + } + } else { + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + conn->verify.sha256_client = NULL; + wpa_printf(MSG_ERROR, "In function %s, fail to register crypto_hash_finish function!\r\n", __FUNCTION__); + return -1; + } + conn->verify.sha256_client = NULL; + } else { +#endif /* CONFIG_TLSV12 */ + + hlen = MD5_MAC_LEN; + if (conn->verify.md5_client == NULL || + crypto_hash_finish(conn->verify.md5_client, hash, &hlen) < 0) { + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + conn->verify.md5_client = NULL; + crypto_hash_finish(conn->verify.sha1_client, NULL, NULL); + conn->verify.sha1_client = NULL; + return -1; + } + conn->verify.md5_client = NULL; + hlen = SHA1_MAC_LEN; + if (conn->verify.sha1_client == NULL || + crypto_hash_finish(conn->verify.sha1_client, hash + MD5_MAC_LEN, + &hlen) < 0) { + conn->verify.sha1_client = NULL; + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + conn->verify.sha1_client = NULL; + hlen = MD5_MAC_LEN + SHA1_MAC_LEN; + +#ifdef CONFIG_TLSV12 + } +#endif /* CONFIG_TLSV12 */ + + if (tls_prf(conn->rl.tls_version, + conn->master_secret, TLS_MASTER_SECRET_LEN, + "client finished", hash, hlen, + verify_data, TLS_VERIFY_DATA_LEN)) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to derive verify_data"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECRYPT_ERROR); + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (client)", + verify_data, TLS_VERIFY_DATA_LEN); + + if (os_memcmp(pos, verify_data, TLS_VERIFY_DATA_LEN) != 0) { + wpa_printf(MSG_INFO, "TLSv1: Mismatch in verify_data"); + return -1; + } + + wpa_printf(MSG_DEBUG, "TLSv1: Received Finished"); + + *in_len = end - in_data; + + if (conn->use_session_ticket) { + /* Abbreviated handshake using session ticket; RFC 4507 */ + wpa_printf(MSG_DEBUG, "TLSv1: Abbreviated handshake completed " + "successfully"); + conn->state = ESTABLISHED; + } else { + /* Full handshake */ + conn->state = SERVER_CHANGE_CIPHER_SPEC; + } + + return 0; +} + + +int tlsv1_server_process_handshake(struct tlsv1_server *conn, u8 ct, + const u8 *buf, size_t *len) +{ + if (ct == TLS_CONTENT_TYPE_ALERT) { + if (*len < 2) { + wpa_printf(MSG_DEBUG, "TLSv1: Alert underflow"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_DECODE_ERROR); + return -1; + } + wpa_printf(MSG_DEBUG, "TLSv1: Received alert %d:%d", + buf[0], buf[1]); + *len = 2; + conn->state = FAILED; + return -1; + } + + switch (conn->state) { + case CLIENT_HELLO: + if (tls_process_client_hello(conn, ct, buf, len)) + return -1; + break; + case CLIENT_CERTIFICATE: + if (tls_process_certificate(conn, ct, buf, len)) + return -1; + break; + case CLIENT_KEY_EXCHANGE: + if (tls_process_client_key_exchange(conn, ct, buf, len)) + return -1; + break; + case CERTIFICATE_VERIFY: + if (tls_process_certificate_verify(conn, ct, buf, len)) + return -1; + break; + case CHANGE_CIPHER_SPEC: + if (tls_process_change_cipher_spec(conn, ct, buf, len)) + return -1; + break; + case CLIENT_FINISHED: + if (tls_process_client_finished(conn, ct, buf, len)) + return -1; + break; + default: + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d " + "while processing received message", + conn->state); + return -1; + } + + if (ct == TLS_CONTENT_TYPE_HANDSHAKE) + tls_verify_hash_add(&conn->verify, buf, *len); + + return 0; +} diff --git a/components/wpa_supplicant/src/wpa2/tls/tlsv1_server_write.c b/components/wpa_supplicant/src/wpa2/tls/tlsv1_server_write.c new file mode 100644 index 0000000000..55eff1af6f --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/tls/tlsv1_server_write.c @@ -0,0 +1,819 @@ +/* + * TLSv1 server - write handshake message + * Copyright (c) 2006-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "crypto/md5.h" +#include "crypto/sha1.h" +#include "crypto/sha256.h" +#include "crypto/random.h" +#include "wpa2/tls/tls.h" +#include "wpa2/tls/x509v3.h" +#include "wpa2/tls/tlsv1_common.h" +#include "wpa2/tls/tlsv1_record.h" +#include "wpa2/tls/tlsv1_server.h" +#include "wpa2/tls/tlsv1_server_i.h" + +#include "wpa2/eap_peer/eap_i.h" + +static size_t tls_server_cert_chain_der_len(struct tlsv1_server *conn) +{ + size_t len = 0; + struct x509_certificate *cert; + + cert = conn->cred->cert; + while (cert) { + len += 3 + cert->cert_len; + if (x509_certificate_self_signed(cert)) + break; + cert = x509_certificate_get_subject(conn->cred->trusted_certs, + &cert->issuer); + } + + return len; +} + + +static int tls_write_server_hello(struct tlsv1_server *conn, + u8 **msgpos, u8 *end) +{ + u8 *pos, *rhdr, *hs_start, *hs_length; + struct os_time now; + size_t rlen; + + pos = *msgpos; + + wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHello"); + rhdr = pos; + pos += TLS_RECORD_HEADER_LEN; + + os_get_time(&now); + WPA_PUT_BE32(conn->server_random, now.sec); + if (random_get_bytes(conn->server_random + 4, TLS_RANDOM_LEN - 4)) { + wpa_printf(MSG_ERROR, "TLSv1: Could not generate " + "server_random"); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "TLSv1: server_random", + conn->server_random, TLS_RANDOM_LEN); + + conn->session_id_len = TLS_SESSION_ID_MAX_LEN; + if (random_get_bytes(conn->session_id, conn->session_id_len)) { + wpa_printf(MSG_ERROR, "TLSv1: Could not generate " + "session_id"); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "TLSv1: session_id", + conn->session_id, conn->session_id_len); + + /* opaque fragment[TLSPlaintext.length] */ + + /* Handshake */ + hs_start = pos; + /* HandshakeType msg_type */ + *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO; + /* uint24 length (to be filled) */ + hs_length = pos; + pos += 3; + /* body - ServerHello */ + /* ProtocolVersion server_version */ + WPA_PUT_BE16(pos, conn->rl.tls_version); + pos += 2; + /* Random random: uint32 gmt_unix_time, opaque random_bytes */ + os_memcpy(pos, conn->server_random, TLS_RANDOM_LEN); + pos += TLS_RANDOM_LEN; + /* SessionID session_id */ + *pos++ = conn->session_id_len; + os_memcpy(pos, conn->session_id, conn->session_id_len); + pos += conn->session_id_len; + /* CipherSuite cipher_suite */ + WPA_PUT_BE16(pos, conn->cipher_suite); + pos += 2; + /* CompressionMethod compression_method */ + *pos++ = TLS_COMPRESSION_NULL; + + if (conn->session_ticket && conn->session_ticket_cb) { + int res = conn->session_ticket_cb( + conn->session_ticket_cb_ctx, + conn->session_ticket, conn->session_ticket_len, + conn->client_random, conn->server_random, + conn->master_secret); + if (res < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: SessionTicket callback " + "indicated failure"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_HANDSHAKE_FAILURE); + return -1; + } + conn->use_session_ticket = res; + + if (conn->use_session_ticket) { + if (tlsv1_server_derive_keys(conn, NULL, 0) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to " + "derive keys"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + } + + /* + * RFC 4507 specifies that server would include an empty + * SessionTicket extension in ServerHello and a + * NewSessionTicket message after the ServerHello. However, + * EAP-FAST (RFC 4851), i.e., the only user of SessionTicket + * extension at the moment, does not use such extensions. + * + * TODO: Add support for configuring RFC 4507 behavior and make + * EAP-FAST disable it. + */ + } + + WPA_PUT_BE24(hs_length, pos - hs_length - 3); + tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); + + if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, + rhdr, end - rhdr, hs_start, pos - hs_start, + &rlen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to create TLS record"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + pos = rhdr + rlen; + + *msgpos = pos; + + return 0; +} + + +static int tls_write_server_certificate(struct tlsv1_server *conn, + u8 **msgpos, u8 *end) +{ + u8 *pos, *rhdr, *hs_start, *hs_length, *cert_start; + size_t rlen; + struct x509_certificate *cert; + const struct tls_cipher_suite *suite; + + suite = tls_get_cipher_suite(conn->rl.cipher_suite); + if (suite && suite->key_exchange == TLS_KEY_X_DH_anon) { + wpa_printf(MSG_DEBUG, "TLSv1: Do not send Certificate when " + "using anonymous DH"); + return 0; + } + + pos = *msgpos; + + wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate"); + rhdr = pos; + pos += TLS_RECORD_HEADER_LEN; + + /* opaque fragment[TLSPlaintext.length] */ + + /* Handshake */ + hs_start = pos; + /* HandshakeType msg_type */ + *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE; + /* uint24 length (to be filled) */ + hs_length = pos; + pos += 3; + /* body - Certificate */ + /* uint24 length (to be filled) */ + cert_start = pos; + pos += 3; + cert = conn->cred->cert; + while (cert) { + if (pos + 3 + cert->cert_len > end) { + wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space " + "for Certificate (cert_len=%lu left=%lu)", + (unsigned long) cert->cert_len, + (unsigned long) (end - pos)); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + WPA_PUT_BE24(pos, cert->cert_len); + pos += 3; + os_memcpy(pos, cert->cert_start, cert->cert_len); + pos += cert->cert_len; + + if (x509_certificate_self_signed(cert)) + break; + cert = x509_certificate_get_subject(conn->cred->trusted_certs, + &cert->issuer); + } + if (cert == conn->cred->cert || cert == NULL) { + /* + * Server was not configured with all the needed certificates + * to form a full certificate chain. The client may fail to + * validate the chain unless it is configured with all the + * missing CA certificates. + */ + wpa_printf(MSG_DEBUG, "TLSv1: Full server certificate chain " + "not configured - validation may fail"); + } + WPA_PUT_BE24(cert_start, pos - cert_start - 3); + + WPA_PUT_BE24(hs_length, pos - hs_length - 3); + + if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, + rhdr, end - rhdr, hs_start, pos - hs_start, + &rlen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + pos = rhdr + rlen; + + tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); + + *msgpos = pos; + + return 0; +} + + +static int tls_write_server_key_exchange(struct tlsv1_server *conn, + u8 **msgpos, u8 *end) +{ + tls_key_exchange keyx; + const struct tls_cipher_suite *suite; + u8 *pos, *rhdr, *hs_start, *hs_length; + size_t rlen; + u8 *dh_ys; + size_t dh_ys_len; + + suite = tls_get_cipher_suite(conn->rl.cipher_suite); + if (suite == NULL) + keyx = TLS_KEY_X_NULL; + else + keyx = suite->key_exchange; + + if (!tls_server_key_exchange_allowed(conn->rl.cipher_suite)) { + wpa_printf(MSG_DEBUG, "TLSv1: No ServerKeyExchange needed"); + return 0; + } + + if (keyx != TLS_KEY_X_DH_anon) { + /* TODO? */ + wpa_printf(MSG_DEBUG, "TLSv1: ServerKeyExchange not yet " + "supported with key exchange type %d", keyx); + return -1; + } + + if (conn->cred == NULL || conn->cred->dh_p == NULL || + conn->cred->dh_g == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: No DH parameters available for " + "ServerKeyExhcange"); + return -1; + } + + os_free(conn->dh_secret); + conn->dh_secret_len = conn->cred->dh_p_len; + conn->dh_secret = os_malloc(conn->dh_secret_len); + if (conn->dh_secret == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate " + "memory for secret (Diffie-Hellman)"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + if (random_get_bytes(conn->dh_secret, conn->dh_secret_len)) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to get random " + "data for Diffie-Hellman"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + os_free(conn->dh_secret); + conn->dh_secret = NULL; + return -1; + } + + if (os_memcmp(conn->dh_secret, conn->cred->dh_p, conn->dh_secret_len) > + 0) + conn->dh_secret[0] = 0; /* make sure secret < p */ + + pos = conn->dh_secret; + while (pos + 1 < conn->dh_secret + conn->dh_secret_len && *pos == 0) + pos++; + if (pos != conn->dh_secret) { + os_memmove(conn->dh_secret, pos, + conn->dh_secret_len - (pos - conn->dh_secret)); + conn->dh_secret_len -= pos - conn->dh_secret; + } + wpa_hexdump_key(MSG_DEBUG, "TLSv1: DH server's secret value", + conn->dh_secret, conn->dh_secret_len); + + /* Ys = g^secret mod p */ + dh_ys_len = conn->cred->dh_p_len; + dh_ys = os_malloc(dh_ys_len); + if (dh_ys == NULL) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to allocate memory for " + "Diffie-Hellman"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + if(wpa2_crypto_funcs.crypto_mod_exp) { + if (wpa2_crypto_funcs.crypto_mod_exp(conn->cred->dh_g, conn->cred->dh_g_len, + conn->dh_secret, conn->dh_secret_len, + conn->cred->dh_p, conn->cred->dh_p_len, + dh_ys, &dh_ys_len)) { + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + os_free(dh_ys); + return -1; + } + } else { + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + os_free(dh_ys); + wpa_printf(MSG_ERROR, "Fail to register crypto_mod_exp function!\r\n"); + return -1; + } + + + wpa_hexdump(MSG_DEBUG, "TLSv1: DH Ys (server's public value)", + dh_ys, dh_ys_len); + + /* + * struct { + * select (KeyExchangeAlgorithm) { + * case diffie_hellman: + * ServerDHParams params; + * Signature signed_params; + * case rsa: + * ServerRSAParams params; + * Signature signed_params; + * }; + * } ServerKeyExchange; + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + + pos = *msgpos; + + wpa_printf(MSG_DEBUG, "TLSv1: Send ServerKeyExchange"); + rhdr = pos; + pos += TLS_RECORD_HEADER_LEN; + + /* opaque fragment[TLSPlaintext.length] */ + + /* Handshake */ + hs_start = pos; + /* HandshakeType msg_type */ + *pos++ = TLS_HANDSHAKE_TYPE_SERVER_KEY_EXCHANGE; + /* uint24 length (to be filled) */ + hs_length = pos; + pos += 3; + + /* body - ServerDHParams */ + /* dh_p */ + if (pos + 2 + conn->cred->dh_p_len > end) { + wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " + "dh_p"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + os_free(dh_ys); + return -1; + } + WPA_PUT_BE16(pos, conn->cred->dh_p_len); + pos += 2; + os_memcpy(pos, conn->cred->dh_p, conn->cred->dh_p_len); + pos += conn->cred->dh_p_len; + + /* dh_g */ + if (pos + 2 + conn->cred->dh_g_len > end) { + wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " + "dh_g"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + os_free(dh_ys); + return -1; + } + WPA_PUT_BE16(pos, conn->cred->dh_g_len); + pos += 2; + os_memcpy(pos, conn->cred->dh_g, conn->cred->dh_g_len); + pos += conn->cred->dh_g_len; + + /* dh_Ys */ + if (pos + 2 + dh_ys_len > end) { + wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for " + "dh_Ys"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + os_free(dh_ys); + return -1; + } + WPA_PUT_BE16(pos, dh_ys_len); + pos += 2; + os_memcpy(pos, dh_ys, dh_ys_len); + pos += dh_ys_len; + os_free(dh_ys); + + WPA_PUT_BE24(hs_length, pos - hs_length - 3); + + if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, + rhdr, end - rhdr, hs_start, pos - hs_start, + &rlen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + pos = rhdr + rlen; + + tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); + + *msgpos = pos; + + return 0; +} + + +static int tls_write_server_certificate_request(struct tlsv1_server *conn, + u8 **msgpos, u8 *end) +{ + u8 *pos, *rhdr, *hs_start, *hs_length; + size_t rlen; + + if (!conn->verify_peer) { + wpa_printf(MSG_DEBUG, "TLSv1: No CertificateRequest needed"); + return 0; + } + + pos = *msgpos; + + wpa_printf(MSG_DEBUG, "TLSv1: Send CertificateRequest"); + rhdr = pos; + pos += TLS_RECORD_HEADER_LEN; + + /* opaque fragment[TLSPlaintext.length] */ + + /* Handshake */ + hs_start = pos; + /* HandshakeType msg_type */ + *pos++ = TLS_HANDSHAKE_TYPE_CERTIFICATE_REQUEST; + /* uint24 length (to be filled) */ + hs_length = pos; + pos += 3; + /* body - CertificateRequest */ + + /* + * enum { + * rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4), + * (255) + * } ClientCertificateType; + * ClientCertificateType certificate_types<1..2^8-1> + */ + *pos++ = 1; + *pos++ = 1; /* rsa_sign */ + + /* + * opaque DistinguishedName<1..2^16-1> + * DistinguishedName certificate_authorities<3..2^16-1> + */ + /* TODO: add support for listing DNs for trusted CAs */ + WPA_PUT_BE16(pos, 0); + pos += 2; + + WPA_PUT_BE24(hs_length, pos - hs_length - 3); + + if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, + rhdr, end - rhdr, hs_start, pos - hs_start, + &rlen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + pos = rhdr + rlen; + + tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); + + *msgpos = pos; + + return 0; +} + + +static int tls_write_server_hello_done(struct tlsv1_server *conn, + u8 **msgpos, u8 *end) +{ + u8 *pos; + size_t rlen; + u8 payload[4]; + + wpa_printf(MSG_DEBUG, "TLSv1: Send ServerHelloDone"); + + /* opaque fragment[TLSPlaintext.length] */ + + /* Handshake */ + pos = payload; + /* HandshakeType msg_type */ + *pos++ = TLS_HANDSHAKE_TYPE_SERVER_HELLO_DONE; + /* uint24 length */ + WPA_PUT_BE24(pos, 0); + pos += 3; + /* body - ServerHelloDone (empty) */ + + if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, + *msgpos, end - *msgpos, payload, pos - payload, + &rlen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate a record"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + tls_verify_hash_add(&conn->verify, payload, pos - payload); + + *msgpos += rlen; + + return 0; +} + + +static int tls_write_server_change_cipher_spec(struct tlsv1_server *conn, + u8 **msgpos, u8 *end) +{ + size_t rlen; + u8 payload[1]; + + wpa_printf(MSG_DEBUG, "TLSv1: Send ChangeCipherSpec"); + + payload[0] = TLS_CHANGE_CIPHER_SPEC; + + if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC, + *msgpos, end - *msgpos, payload, sizeof(payload), + &rlen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + if (tlsv1_record_change_write_cipher(&conn->rl) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to set write cipher for " + "record layer"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + *msgpos += rlen; + + return 0; +} + + +static int tls_write_server_finished(struct tlsv1_server *conn, + u8 **msgpos, u8 *end) +{ + u8 *pos, *hs_start; + size_t rlen, hlen; + u8 verify_data[1 + 3 + TLS_VERIFY_DATA_LEN]; + u8 hash[MD5_MAC_LEN + SHA1_MAC_LEN]; + + pos = *msgpos; + + wpa_printf(MSG_DEBUG, "TLSv1: Send Finished"); + + /* Encrypted Handshake Message: Finished */ + +#ifdef CONFIG_TLSV12 + if (conn->rl.tls_version >= TLS_VERSION_1_2) { + hlen = SHA256_MAC_LEN; + if (wpa2_crypto_funcs.crypto_hash_finish) { + if (conn->verify.sha256_server == NULL || + wpa2_crypto_funcs.crypto_hash_finish(conn->verify.sha256_server, hash, &hlen) + < 0) { + conn->verify.sha256_server = NULL; + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + } else { + conn->verify.sha256_server = NULL; + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + wpa_printf(MSG_ERROR, "In function %s, fail to register crypto_hash_finish function!\r\n", __FUNCTION__); + return -1; + } + conn->verify.sha256_server = NULL; + } else { +#endif /* CONFIG_TLSV12 */ + + hlen = MD5_MAC_LEN; + if (conn->verify.md5_server == NULL || + crypto_hash_finish(conn->verify.md5_server, hash, &hlen) < 0) { + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + conn->verify.md5_server = NULL; + crypto_hash_finish(conn->verify.sha1_server, NULL, NULL); + conn->verify.sha1_server = NULL; + return -1; + } + conn->verify.md5_server = NULL; + hlen = SHA1_MAC_LEN; + if (conn->verify.sha1_server == NULL || + crypto_hash_finish(conn->verify.sha1_server, hash + MD5_MAC_LEN, + &hlen) < 0) { + conn->verify.sha1_server = NULL; + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + conn->verify.sha1_server = NULL; + hlen = MD5_MAC_LEN + SHA1_MAC_LEN; + +#ifdef CONFIG_TLSV12 + } +#endif /* CONFIG_TLSV12 */ + + if (tls_prf(conn->rl.tls_version, + conn->master_secret, TLS_MASTER_SECRET_LEN, + "server finished", hash, hlen, + verify_data + 1 + 3, TLS_VERIFY_DATA_LEN)) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to generate verify_data"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "TLSv1: verify_data (server)", + verify_data + 1 + 3, TLS_VERIFY_DATA_LEN); + + /* Handshake */ + pos = hs_start = verify_data; + /* HandshakeType msg_type */ + *pos++ = TLS_HANDSHAKE_TYPE_FINISHED; + /* uint24 length */ + WPA_PUT_BE24(pos, TLS_VERIFY_DATA_LEN); + pos += 3; + pos += TLS_VERIFY_DATA_LEN; + tls_verify_hash_add(&conn->verify, hs_start, pos - hs_start); + + if (tlsv1_record_send(&conn->rl, TLS_CONTENT_TYPE_HANDSHAKE, + *msgpos, end - *msgpos, hs_start, pos - hs_start, + &rlen) < 0) { + wpa_printf(MSG_DEBUG, "TLSv1: Failed to create a record"); + tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, + TLS_ALERT_INTERNAL_ERROR); + return -1; + } + + *msgpos += rlen; + + return 0; +} + + +static u8 * tls_send_server_hello(struct tlsv1_server *conn, size_t *out_len) +{ + u8 *msg, *end, *pos; + size_t msglen; + + *out_len = 0; + + msglen = 1000 + tls_server_cert_chain_der_len(conn); + + msg = os_malloc(msglen); + if (msg == NULL) + return NULL; + + pos = msg; + end = msg + msglen; + + if (tls_write_server_hello(conn, &pos, end) < 0) { + os_free(msg); + return NULL; + } + + if (conn->use_session_ticket) { + /* Abbreviated handshake using session ticket; RFC 4507 */ + if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 || + tls_write_server_finished(conn, &pos, end) < 0) { + os_free(msg); + return NULL; + } + + *out_len = pos - msg; + + conn->state = CHANGE_CIPHER_SPEC; + + return msg; + } + + /* Full handshake */ + if (tls_write_server_certificate(conn, &pos, end) < 0 || + tls_write_server_key_exchange(conn, &pos, end) < 0 || + tls_write_server_certificate_request(conn, &pos, end) < 0 || + tls_write_server_hello_done(conn, &pos, end) < 0) { + os_free(msg); + return NULL; + } + + *out_len = pos - msg; + + conn->state = CLIENT_CERTIFICATE; + + return msg; +} + + +static u8 * tls_send_change_cipher_spec(struct tlsv1_server *conn, + size_t *out_len) +{ + u8 *msg, *end, *pos; + + *out_len = 0; + + msg = os_malloc(1000); + if (msg == NULL) + return NULL; + + pos = msg; + end = msg + 1000; + + if (tls_write_server_change_cipher_spec(conn, &pos, end) < 0 || + tls_write_server_finished(conn, &pos, end) < 0) { + os_free(msg); + return NULL; + } + + *out_len = pos - msg; + + wpa_printf(MSG_DEBUG, "TLSv1: Handshake completed successfully"); + conn->state = ESTABLISHED; + + return msg; +} + + +u8 * tlsv1_server_handshake_write(struct tlsv1_server *conn, size_t *out_len) +{ + switch (conn->state) { + case SERVER_HELLO: + return tls_send_server_hello(conn, out_len); + case SERVER_CHANGE_CIPHER_SPEC: + return tls_send_change_cipher_spec(conn, out_len); + default: + if (conn->state == ESTABLISHED && conn->use_session_ticket) { + /* Abbreviated handshake was already completed. */ + return NULL; + } + wpa_printf(MSG_DEBUG, "TLSv1: Unexpected state %d while " + "generating reply", conn->state); + return NULL; + } +} + + +u8 * tlsv1_server_send_alert(struct tlsv1_server *conn, u8 level, + u8 description, size_t *out_len) +{ + u8 *alert, *pos, *length; + + wpa_printf(MSG_DEBUG, "TLSv1: Send Alert(%d:%d)", level, description); + *out_len = 0; + + alert = os_malloc(10); + if (alert == NULL) + return NULL; + + pos = alert; + + /* TLSPlaintext */ + /* ContentType type */ + *pos++ = TLS_CONTENT_TYPE_ALERT; + /* ProtocolVersion version */ + WPA_PUT_BE16(pos, conn->rl.tls_version ? conn->rl.tls_version : + TLS_VERSION); + pos += 2; + /* uint16 length (to be filled) */ + length = pos; + pos += 2; + /* opaque fragment[TLSPlaintext.length] */ + + /* Alert */ + /* AlertLevel level */ + *pos++ = level; + /* AlertDescription description */ + *pos++ = description; + + WPA_PUT_BE16(length, pos - length - 2); + *out_len = pos - alert; + + return alert; +} diff --git a/components/wpa_supplicant/src/wpa2/tls/x509v3.c b/components/wpa_supplicant/src/wpa2/tls/x509v3.c new file mode 100644 index 0000000000..f7962db81c --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/tls/x509v3.c @@ -0,0 +1,2013 @@ +/* + * X.509v3 certificate parsing and processing (RFC 3280 profile) + * Copyright (c) 2006-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" +#include "wpa/wpa.h" +#include "wpa/common.h" +#include "crypto/crypto.h" +#include "wpa2/tls/asn1.h" +#include "wpa2/tls/x509v3.h" + +#include "wpa2/eap_peer/eap_i.h" + +static void x509_free_name(struct x509_name *name) +{ + size_t i; + + for (i = 0; i < name->num_attr; i++) { + os_free(name->attr[i].value); + name->attr[i].value = NULL; + name->attr[i].type = X509_NAME_ATTR_NOT_USED; + } + name->num_attr = 0; + os_free(name->email); + name->email = NULL; + + os_free(name->alt_email); + os_free(name->dns); + os_free(name->uri); + os_free(name->ip); + name->alt_email = name->dns = name->uri = NULL; + name->ip = NULL; + name->ip_len = 0; + os_memset(&name->rid, 0, sizeof(name->rid)); +} + + +/** + * x509_certificate_free - Free an X.509 certificate + * @cert: Certificate to be freed + */ +void x509_certificate_free(struct x509_certificate *cert) +{ + if (cert == NULL) + return; + if (cert->next) { + wpa_printf(MSG_DEBUG, "X509: x509_certificate_free: cer=%p " + "was still on a list (next=%p)\n", + cert, cert->next); + } + x509_free_name(&cert->issuer); + x509_free_name(&cert->subject); + os_free(cert->public_key); + os_free(cert->sign_value); + os_free(cert); +} + + +/** + * x509_certificate_free - Free an X.509 certificate chain + * @cert: Pointer to the first certificate in the chain + */ +void x509_certificate_chain_free(struct x509_certificate *cert) +{ + struct x509_certificate *next; + + while (cert) { + next = cert->next; + cert->next = NULL; + x509_certificate_free(cert); + cert = next; + } +} + + +static int x509_whitespace(char c) +{ + return c == ' ' || c == '\t'; +} + + +static void x509_str_strip_whitespace(char *a) +{ + char *ipos, *opos; + int remove_whitespace = 1; + + ipos = opos = a; + + while (*ipos) { + if (remove_whitespace && x509_whitespace(*ipos)) + ipos++; + else { + remove_whitespace = x509_whitespace(*ipos); + *opos++ = *ipos++; + } + } + + *opos-- = '\0'; + if (opos > a && x509_whitespace(*opos)) + *opos = '\0'; +} + + +static int x509_str_compare(const char *a, const char *b) +{ + char *aa, *bb; + int ret; + + if (!a && b) + return -1; + if (a && !b) + return 1; + if (!a && !b) + return 0; + + aa = os_strdup(a); + bb = os_strdup(b); + + if (aa == NULL || bb == NULL) { + os_free(aa); + os_free(bb); + return strcasecmp(a, b); + } + + x509_str_strip_whitespace(aa); + x509_str_strip_whitespace(bb); + + ret = strcasecmp(aa, bb); + + os_free(aa); + os_free(bb); + + return ret; +} + + +/** + * x509_name_compare - Compare X.509 certificate names + * @a: Certificate name + * @b: Certificate name + * Returns: <0, 0, or >0 based on whether a is less than, equal to, or + * greater than b + */ +int x509_name_compare(struct x509_name *a, struct x509_name *b) +{ + int res; + size_t i; + + if (!a && b) + return -1; + if (a && !b) + return 1; + if (!a && !b) + return 0; + if (a->num_attr < b->num_attr) + return -1; + if (a->num_attr > b->num_attr) + return 1; + + for (i = 0; i < a->num_attr; i++) { + if (a->attr[i].type < b->attr[i].type) + return -1; + if (a->attr[i].type > b->attr[i].type) + return -1; + res = x509_str_compare(a->attr[i].value, b->attr[i].value); + if (res) + return res; + } + res = x509_str_compare(a->email, b->email); + if (res) + return res; + + return 0; +} + + +static int x509_parse_algorithm_identifier( + const u8 *buf, size_t len, + struct x509_algorithm_identifier *id, const u8 **next) +{ + struct asn1_hdr hdr; + const u8 *pos, *end; + + /* + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + */ + + if (asn1_get_next(buf, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " + "(AlgorithmIdentifier) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + pos = hdr.payload; + end = pos + hdr.length; + + if (end > buf + len) + return -1; + + *next = end; + + if (asn1_get_oid(pos, end - pos, &id->oid, &pos)) + return -1; + + /* TODO: optional parameters */ + + return 0; +} + + +static int x509_parse_public_key(const u8 *buf, size_t len, + struct x509_certificate *cert, + const u8 **next) +{ + struct asn1_hdr hdr; + const u8 *pos, *end; + + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + */ + + pos = buf; + end = buf + len; + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " + "(SubjectPublicKeyInfo) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + pos = hdr.payload; + + if (pos + hdr.length > end) + return -1; + end = pos + hdr.length; + *next = end; + + if (x509_parse_algorithm_identifier(pos, end - pos, + &cert->public_key_alg, &pos)) + return -1; + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_BITSTRING) { + wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING " + "(subjectPublicKey) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + if (hdr.length < 1) + return -1; + pos = hdr.payload; + if (*pos) { + wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", + *pos); + /* + * TODO: should this be rejected? X.509 certificates are + * unlikely to use such a construction. Now we would end up + * including the extra bits in the buffer which may also be + * ok. + */ + } + os_free(cert->public_key); + cert->public_key = os_malloc(hdr.length - 1); + if (cert->public_key == NULL) { + wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for " + "public key"); + return -1; + } + os_memcpy(cert->public_key, pos + 1, hdr.length - 1); + cert->public_key_len = hdr.length - 1; + wpa_hexdump(MSG_MSGDUMP, "X509: subjectPublicKey", + cert->public_key, cert->public_key_len); + + return 0; +} + + +static int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name, + const u8 **next) +{ + struct asn1_hdr hdr; + const u8 *pos, *end, *set_pos, *set_end, *seq_pos, *seq_end; + struct asn1_oid oid; + char *val; + + /* + * Name ::= CHOICE { RDNSequence } + * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue + * } + * AttributeType ::= OBJECT IDENTIFIER + * AttributeValue ::= ANY DEFINED BY AttributeType + */ + + if (asn1_get_next(buf, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " + "(Name / RDNSequencer) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + pos = hdr.payload; + + if (pos + hdr.length > buf + len) + return -1; + + end = *next = pos + hdr.length; + + while (pos < end) { + enum x509_name_attr_type type; + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SET) { + wpa_printf(MSG_DEBUG, "X509: Expected SET " + "(RelativeDistinguishedName) - found class " + "%d tag 0x%x", hdr.class, hdr.tag); + x509_free_name(name); + return -1; + } + + set_pos = hdr.payload; + pos = set_end = hdr.payload + hdr.length; + + if (asn1_get_next(set_pos, set_end - set_pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " + "(AttributeTypeAndValue) - found class %d " + "tag 0x%x", hdr.class, hdr.tag); + x509_free_name(name); + return -1; + } + + seq_pos = hdr.payload; + seq_end = hdr.payload + hdr.length; + + if (asn1_get_oid(seq_pos, seq_end - seq_pos, &oid, &seq_pos)) { + x509_free_name(name); + return -1; + } + + if (asn1_get_next(seq_pos, seq_end - seq_pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL) { + wpa_printf(MSG_DEBUG, "X509: Failed to parse " + "AttributeValue"); + x509_free_name(name); + return -1; + } + + /* RFC 3280: + * MUST: country, organization, organizational-unit, + * distinguished name qualifier, state or province name, + * common name, serial number. + * SHOULD: locality, title, surname, given name, initials, + * pseudonym, generation qualifier. + * MUST: domainComponent (RFC 2247). + */ + type = X509_NAME_ATTR_NOT_USED; + if (oid.len == 4 && + oid.oid[0] == 2 && oid.oid[1] == 5 && oid.oid[2] == 4) { + /* id-at ::= 2.5.4 */ + switch (oid.oid[3]) { + case 3: + /* commonName */ + type = X509_NAME_ATTR_CN; + break; + case 6: + /* countryName */ + type = X509_NAME_ATTR_C; + break; + case 7: + /* localityName */ + type = X509_NAME_ATTR_L; + break; + case 8: + /* stateOrProvinceName */ + type = X509_NAME_ATTR_ST; + break; + case 10: + /* organizationName */ + type = X509_NAME_ATTR_O; + break; + case 11: + /* organizationalUnitName */ + type = X509_NAME_ATTR_OU; + break; + } + } else if (oid.len == 7 && + oid.oid[0] == 1 && oid.oid[1] == 2 && + oid.oid[2] == 840 && oid.oid[3] == 113549 && + oid.oid[4] == 1 && oid.oid[5] == 9 && + oid.oid[6] == 1) { + /* 1.2.840.113549.1.9.1 - e-mailAddress */ + os_free(name->email); + name->email = os_malloc(hdr.length + 1); + if (name->email == NULL) { + x509_free_name(name); + return -1; + } + os_memcpy(name->email, hdr.payload, hdr.length); + name->email[hdr.length] = '\0'; + continue; + } else if (oid.len == 7 && + oid.oid[0] == 0 && oid.oid[1] == 9 && + oid.oid[2] == 2342 && oid.oid[3] == 19200300 && + oid.oid[4] == 100 && oid.oid[5] == 1 && + oid.oid[6] == 25) { + /* 0.9.2342.19200300.100.1.25 - domainComponent */ + type = X509_NAME_ATTR_DC; + } + + if (type == X509_NAME_ATTR_NOT_USED) { + wpa_hexdump(MSG_DEBUG, "X509: Unrecognized OID", + (u8 *) oid.oid, + oid.len * sizeof(oid.oid[0])); + wpa_hexdump_ascii(MSG_MSGDUMP, "X509: Attribute Data", + hdr.payload, hdr.length); + continue; + } + + if (name->num_attr == X509_MAX_NAME_ATTRIBUTES) { + wpa_printf(MSG_INFO, "X509: Too many Name attributes"); + x509_free_name(name); + return -1; + } + + val = (char *)dup_binstr(hdr.payload, hdr.length); + if (val == NULL) { + x509_free_name(name); + return -1; + } + if (os_strlen(val) != hdr.length) { + wpa_printf(MSG_INFO, "X509: Reject certificate with " + "embedded NUL byte in a string (%s[NUL])", + val); + os_free(val); + x509_free_name(name); + return -1; + } + + name->attr[name->num_attr].type = type; + name->attr[name->num_attr].value = val; + name->num_attr++; + } + + return 0; +} + + +static char * x509_name_attr_str(enum x509_name_attr_type type) +{ +#ifndef ESPRESSIF_USE + switch (type) { + case X509_NAME_ATTR_NOT_USED: + return "[N/A]"; + case X509_NAME_ATTR_DC: + return "DC"; + case X509_NAME_ATTR_CN: + return "CN"; + case X509_NAME_ATTR_C: + return "C"; + case X509_NAME_ATTR_L: + return "L"; + case X509_NAME_ATTR_ST: + return "ST"; + case X509_NAME_ATTR_O: + return "O"; + case X509_NAME_ATTR_OU: + return "OU"; + } + return "?"; +#else + static char name_attr[6]; + switch (type) { + case X509_NAME_ATTR_NOT_USED: + strcpy(name_attr, "[N/A]"); + case X509_NAME_ATTR_DC: + strcpy(name_attr, "DC"); + case X509_NAME_ATTR_CN: + strcpy(name_attr, "CN"); + case X509_NAME_ATTR_C: + strcpy(name_attr, "C"); + case X509_NAME_ATTR_L: + strcpy(name_attr, "L"); + case X509_NAME_ATTR_ST: + strcpy(name_attr, "ST"); + case X509_NAME_ATTR_O: + strcpy(name_attr, "O"); + case X509_NAME_ATTR_OU: + strcpy(name_attr, "OU"); + default : + strcpy(name_attr, "?"); + } + return name_attr; +#endif +} + + +/** + * x509_name_string - Convert an X.509 certificate name into a string + * @name: Name to convert + * @buf: Buffer for the string + * @len: Maximum buffer length + */ +void x509_name_string(struct x509_name *name, char *buf, size_t len) +{ + char *pos, *end; + int ret; + size_t i; + + if (len == 0) + return; + + pos = buf; + end = buf + len; + + for (i = 0; i < name->num_attr; i++) { + //ret = os_snprintf(pos, end - pos, "%s=%s, ", + ret = sprintf(pos, "%s=%s, ", + x509_name_attr_str(name->attr[i].type), + name->attr[i].value); + if (ret < 0 || ret >= end - pos) + goto done; + pos += ret; + } + + if (pos > buf + 1 && pos[-1] == ' ' && pos[-2] == ',') { + pos--; + *pos = '\0'; + pos--; + *pos = '\0'; + } + + if (name->email) { + //ret = os_snprintf(pos, end - pos, "/emailAddress=%s", + ret = sprintf(pos, "/emailAddress=%s", + name->email); + if (ret < 0 || ret >= end - pos) + goto done; + pos += ret; + } + +done: + end[-1] = '\0'; +} + + +static int x509_parse_time(const u8 *buf, size_t len, u8 asn1_tag, + os_time_t *val) +{ +#if 0 + const char *pos; + int year, month, day, hour, min, sec; + + /* + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime + * } + * + * UTCTime: YYMMDDHHMMSSZ + * GeneralizedTime: YYYYMMDDHHMMSSZ + */ + + pos = (const char *) buf; + + switch (asn1_tag) { + case ASN1_TAG_UTCTIME: + if (len != 13 || buf[12] != 'Z') { + wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized " + "UTCTime format", buf, len); + return -1; + } + if (sscanf(pos, "%02d", &year) != 1) { + wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse " + "UTCTime year", buf, len); + return -1; + } + if (year < 50) + year += 2000; + else + year += 1900; + pos += 2; + break; + case ASN1_TAG_GENERALIZEDTIME: + if (len != 15 || buf[14] != 'Z') { + wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized " + "GeneralizedTime format", buf, len); + return -1; + } + if (sscanf(pos, "%04d", &year) != 1) { + wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse " + "GeneralizedTime year", buf, len); + return -1; + } + pos += 4; + break; + default: + wpa_printf(MSG_DEBUG, "X509: Expected UTCTime or " + "GeneralizedTime - found tag 0x%x", asn1_tag); + return -1; + } + + if (sscanf(pos, "%02d", &month) != 1) { + wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " + "(month)", buf, len); + return -1; + } + pos += 2; + + if (sscanf(pos, "%02d", &day) != 1) { + wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " + "(day)", buf, len); + return -1; + } + pos += 2; + + if (sscanf(pos, "%02d", &hour) != 1) { + wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " + "(hour)", buf, len); + return -1; + } + pos += 2; + + if (sscanf(pos, "%02d", &min) != 1) { + wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " + "(min)", buf, len); + return -1; + } + pos += 2; + + if (sscanf(pos, "%02d", &sec) != 1) { + wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " + "(sec)", buf, len); + return -1; + } + + if (os_mktime(year, month, day, hour, min, sec, val) < 0) { + wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to convert Time", + buf, len); + if (year < 1970) { + /* + * At least some test certificates have been configured + * to use dates prior to 1970. Set the date to + * beginning of 1970 to handle these case. + */ + wpa_printf(MSG_DEBUG, "X509: Year=%d before epoch - " + "assume epoch as the time", year); + *val = 0; + return 0; + } + return -1; + } +#endif + return 0; +} + + +static int x509_parse_validity(const u8 *buf, size_t len, + struct x509_certificate *cert, const u8 **next) +{ + struct asn1_hdr hdr; + const u8 *pos; + size_t plen; + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time + * } + * + * RFC 3280, 4.1.2.5: + * CAs conforming to this profile MUST always encode certificate + * validity dates through the year 2049 as UTCTime; certificate + * validity dates in 2050 or later MUST be encoded as GeneralizedTime. + */ + + if (asn1_get_next(buf, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " + "(Validity) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + pos = hdr.payload; + plen = hdr.length; + + if (pos + plen > buf + len) + return -1; + + *next = pos + plen; + + if (asn1_get_next(pos, plen, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + x509_parse_time(hdr.payload, hdr.length, hdr.tag, + &cert->not_before) < 0) { + wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notBefore " + "Time", hdr.payload, hdr.length); + return -1; + } + + pos = hdr.payload + hdr.length; + plen = *next - pos; + + if (asn1_get_next(pos, plen, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + x509_parse_time(hdr.payload, hdr.length, hdr.tag, + &cert->not_after) < 0) { + wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notAfter " + "Time", hdr.payload, hdr.length); + return -1; + } + + wpa_printf(MSG_DEBUG, "X509: Validity: notBefore: %lu notAfter: %lu", + (unsigned long) cert->not_before, + (unsigned long) cert->not_after); + + return 0; +} + + +static int x509_id_ce_oid(struct asn1_oid *oid) +{ + /* id-ce arc from X.509 for standard X.509v3 extensions */ + return oid->len >= 4 && + oid->oid[0] == 2 /* joint-iso-ccitt */ && + oid->oid[1] == 5 /* ds */ && + oid->oid[2] == 29 /* id-ce */; +} + + +static int x509_parse_ext_key_usage(struct x509_certificate *cert, + const u8 *pos, size_t len) +{ + struct asn1_hdr hdr; + + /* + * KeyUsage ::= BIT STRING { + * digitalSignature (0), + * nonRepudiation (1), + * keyEncipherment (2), + * dataEncipherment (3), + * keyAgreement (4), + * keyCertSign (5), + * cRLSign (6), + * encipherOnly (7), + * decipherOnly (8) } + */ + + if (asn1_get_next(pos, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_BITSTRING || + hdr.length < 1) { + wpa_printf(MSG_DEBUG, "X509: Expected BIT STRING in " + "KeyUsage; found %d tag 0x%x len %d", + hdr.class, hdr.tag, hdr.length); + return -1; + } + + cert->extensions_present |= X509_EXT_KEY_USAGE; + cert->key_usage = asn1_bit_string_to_long(hdr.payload, hdr.length); + + wpa_printf(MSG_DEBUG, "X509: KeyUsage 0x%lx", cert->key_usage); + + return 0; +} + + +static int x509_parse_ext_basic_constraints(struct x509_certificate *cert, + const u8 *pos, size_t len) +{ + struct asn1_hdr hdr; + unsigned long value; + size_t left; + + /* + * BasicConstraints ::= SEQUENCE { + * cA BOOLEAN DEFAULT FALSE, + * pathLenConstraint INTEGER (0..MAX) OPTIONAL } + */ + + if (asn1_get_next(pos, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " + "BasicConstraints; found %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + + cert->extensions_present |= X509_EXT_BASIC_CONSTRAINTS; + + if (hdr.length == 0) + return 0; + + if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL) { + wpa_printf(MSG_DEBUG, "X509: Failed to parse " + "BasicConstraints"); + return -1; + } + + if (hdr.tag == ASN1_TAG_BOOLEAN) { + if (hdr.length != 1) { + wpa_printf(MSG_DEBUG, "X509: Unexpected " + "Boolean length (%u) in BasicConstraints", + hdr.length); + return -1; + } + cert->ca = hdr.payload[0]; + + if (hdr.payload + hdr.length == pos + len) { + wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d", + cert->ca); + return 0; + } + + if (asn1_get_next(hdr.payload + hdr.length, len - hdr.length, + &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL) { + wpa_printf(MSG_DEBUG, "X509: Failed to parse " + "BasicConstraints"); + return -1; + } + } + + if (hdr.tag != ASN1_TAG_INTEGER) { + wpa_printf(MSG_DEBUG, "X509: Expected INTEGER in " + "BasicConstraints; found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + + pos = hdr.payload; + left = hdr.length; + value = 0; + while (left) { + value <<= 8; + value |= *pos++; + left--; + } + + cert->path_len_constraint = value; + cert->extensions_present |= X509_EXT_PATH_LEN_CONSTRAINT; + + wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d " + "pathLenConstraint=%lu", + cert->ca, cert->path_len_constraint); + + return 0; +} + + +static int x509_parse_alt_name_rfc8222(struct x509_name *name, + const u8 *pos, size_t len) +{ + /* rfc822Name IA5String */ + wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - rfc822Name", pos, len); + os_free(name->alt_email); + name->alt_email = (char *)os_zalloc(len + 1); + if (name->alt_email == NULL) + return -1; + os_memcpy(name->alt_email, pos, len); + if (os_strlen(name->alt_email) != len) { + wpa_printf(MSG_INFO, "X509: Reject certificate with " + "embedded NUL byte in rfc822Name (%s[NUL])", + name->alt_email); + os_free(name->alt_email); + name->alt_email = NULL; + return -1; + } + return 0; +} + + +static int x509_parse_alt_name_dns(struct x509_name *name, + const u8 *pos, size_t len) +{ + /* dNSName IA5String */ + wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - dNSName", pos, len); + os_free(name->dns); + name->dns = (char *)os_zalloc(len + 1); + if (name->dns == NULL) + return -1; + os_memcpy(name->dns, pos, len); + if (os_strlen(name->dns) != len) { + wpa_printf(MSG_INFO, "X509: Reject certificate with " + "embedded NUL byte in dNSName (%s[NUL])", + name->dns); + os_free(name->dns); + name->dns = NULL; + return -1; + } + return 0; +} + + +static int x509_parse_alt_name_uri(struct x509_name *name, + const u8 *pos, size_t len) +{ + /* uniformResourceIdentifier IA5String */ + wpa_hexdump_ascii(MSG_MSGDUMP, + "X509: altName - uniformResourceIdentifier", + pos, len); + os_free(name->uri); + name->uri = (char *)os_zalloc(len + 1); + if (name->uri == NULL) + return -1; + os_memcpy(name->uri, pos, len); + if (os_strlen(name->uri) != len) { + wpa_printf(MSG_INFO, "X509: Reject certificate with " + "embedded NUL byte in uniformResourceIdentifier " + "(%s[NUL])", name->uri); + os_free(name->uri); + name->uri = NULL; + return -1; + } + return 0; +} + + +static int x509_parse_alt_name_ip(struct x509_name *name, + const u8 *pos, size_t len) +{ + /* iPAddress OCTET STRING */ + wpa_hexdump(MSG_MSGDUMP, "X509: altName - iPAddress", pos, len); + os_free(name->ip); + name->ip = os_malloc(len); + if (name->ip == NULL) + return -1; + os_memcpy(name->ip, pos, len); + name->ip_len = len; + return 0; +} + + +static int x509_parse_alt_name_rid(struct x509_name *name, + const u8 *pos, size_t len) +{ + char buf[80]; + + /* registeredID OBJECT IDENTIFIER */ + if (asn1_parse_oid(pos, len, &name->rid) < 0) + return -1; + + asn1_oid_to_str(&name->rid, buf, sizeof(buf)); + wpa_printf(MSG_DEBUG, "X509: altName - registeredID: %s", buf); + + return 0; +} + + +static int x509_parse_ext_alt_name(struct x509_name *name, + const u8 *pos, size_t len) +{ + struct asn1_hdr hdr; + const u8 *p, *end; + + /* + * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + * + * GeneralName ::= CHOICE { + * otherName [0] OtherName, + * rfc822Name [1] IA5String, + * dNSName [2] IA5String, + * x400Address [3] ORAddress, + * directoryName [4] Name, + * ediPartyName [5] EDIPartyName, + * uniformResourceIdentifier [6] IA5String, + * iPAddress [7] OCTET STRING, + * registeredID [8] OBJECT IDENTIFIER } + * + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * EDIPartyName ::= SEQUENCE { + * nameAssigner [0] DirectoryString OPTIONAL, + * partyName [1] DirectoryString } + */ + + for (p = pos, end = pos + len; p < end; p = hdr.payload + hdr.length) { + int res; + + if (asn1_get_next(p, end - p, &hdr) < 0) { + wpa_printf(MSG_DEBUG, "X509: Failed to parse " + "SubjectAltName item"); + return -1; + } + + if (hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) + continue; + + switch (hdr.tag) { + case 1: + res = x509_parse_alt_name_rfc8222(name, hdr.payload, + hdr.length); + break; + case 2: + res = x509_parse_alt_name_dns(name, hdr.payload, + hdr.length); + break; + case 6: + res = x509_parse_alt_name_uri(name, hdr.payload, + hdr.length); + break; + case 7: + res = x509_parse_alt_name_ip(name, hdr.payload, + hdr.length); + break; + case 8: + res = x509_parse_alt_name_rid(name, hdr.payload, + hdr.length); + break; + case 0: /* TODO: otherName */ + case 3: /* TODO: x500Address */ + case 4: /* TODO: directoryName */ + case 5: /* TODO: ediPartyName */ + default: + res = 0; + break; + } + if (res < 0) + return res; + } + + return 0; +} + + +static int x509_parse_ext_subject_alt_name(struct x509_certificate *cert, + const u8 *pos, size_t len) +{ + struct asn1_hdr hdr; + + /* SubjectAltName ::= GeneralNames */ + + if (asn1_get_next(pos, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " + "SubjectAltName; found %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + + wpa_printf(MSG_DEBUG, "X509: SubjectAltName"); + cert->extensions_present |= X509_EXT_SUBJECT_ALT_NAME; + + if (hdr.length == 0) + return 0; + + return x509_parse_ext_alt_name(&cert->subject, hdr.payload, + hdr.length); +} + + +static int x509_parse_ext_issuer_alt_name(struct x509_certificate *cert, + const u8 *pos, size_t len) +{ + struct asn1_hdr hdr; + + /* IssuerAltName ::= GeneralNames */ + + if (asn1_get_next(pos, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " + "IssuerAltName; found %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + + wpa_printf(MSG_DEBUG, "X509: IssuerAltName"); + cert->extensions_present |= X509_EXT_ISSUER_ALT_NAME; + + if (hdr.length == 0) + return 0; + + return x509_parse_ext_alt_name(&cert->issuer, hdr.payload, + hdr.length); +} + + +static int x509_parse_extension_data(struct x509_certificate *cert, + struct asn1_oid *oid, + const u8 *pos, size_t len) +{ + if (!x509_id_ce_oid(oid)) + return 1; + + /* TODO: add other extensions required by RFC 3280, Ch 4.2: + * certificate policies (section 4.2.1.5) + * name constraints (section 4.2.1.11) + * policy constraints (section 4.2.1.12) + * extended key usage (section 4.2.1.13) + * inhibit any-policy (section 4.2.1.15) + */ + switch (oid->oid[3]) { + case 15: /* id-ce-keyUsage */ + return x509_parse_ext_key_usage(cert, pos, len); + case 17: /* id-ce-subjectAltName */ + return x509_parse_ext_subject_alt_name(cert, pos, len); + case 18: /* id-ce-issuerAltName */ + return x509_parse_ext_issuer_alt_name(cert, pos, len); + case 19: /* id-ce-basicConstraints */ + return x509_parse_ext_basic_constraints(cert, pos, len); + default: + return 1; + } +} + + +static int x509_parse_extension(struct x509_certificate *cert, + const u8 *pos, size_t len, const u8 **next) +{ + const u8 *end; + struct asn1_hdr hdr; + struct asn1_oid oid; + int critical_ext = 0, res; + char buf[80]; + + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING + * } + */ + + if (asn1_get_next(pos, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in " + "Extensions: class %d tag 0x%x; expected SEQUENCE", + hdr.class, hdr.tag); + return -1; + } + pos = hdr.payload; + *next = end = pos + hdr.length; + + if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) { + wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data for " + "Extension (expected OID)"); + return -1; + } + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + (hdr.tag != ASN1_TAG_BOOLEAN && + hdr.tag != ASN1_TAG_OCTETSTRING)) { + wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in " + "Extensions: class %d tag 0x%x; expected BOOLEAN " + "or OCTET STRING", hdr.class, hdr.tag); + return -1; + } + + if (hdr.tag == ASN1_TAG_BOOLEAN) { + if (hdr.length != 1) { + wpa_printf(MSG_DEBUG, "X509: Unexpected " + "Boolean length (%u)", hdr.length); + return -1; + } + critical_ext = hdr.payload[0]; + pos = hdr.payload; + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + (hdr.class != ASN1_CLASS_UNIVERSAL && + hdr.class != ASN1_CLASS_PRIVATE) || + hdr.tag != ASN1_TAG_OCTETSTRING) { + wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header " + "in Extensions: class %d tag 0x%x; " + "expected OCTET STRING", + hdr.class, hdr.tag); + return -1; + } + } + + asn1_oid_to_str(&oid, buf, sizeof(buf)); + wpa_printf(MSG_DEBUG, "X509: Extension: extnID=%s critical=%d", + buf, critical_ext); + wpa_hexdump(MSG_MSGDUMP, "X509: extnValue", hdr.payload, hdr.length); + + res = x509_parse_extension_data(cert, &oid, hdr.payload, hdr.length); + if (res < 0) + return res; + if (res == 1 && critical_ext) { + wpa_printf(MSG_INFO, "X509: Unknown critical extension %s", + buf); + //return -1; //for wpa2 certification , commenout , ignore the error + } + + return 0; +} + + +static int x509_parse_extensions(struct x509_certificate *cert, + const u8 *pos, size_t len) +{ + const u8 *end; + struct asn1_hdr hdr; + + /* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension */ + + if (asn1_get_next(pos, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data " + "for Extensions: class %d tag 0x%x; " + "expected SEQUENCE", hdr.class, hdr.tag); + return -1; + } + + pos = hdr.payload; + end = pos + hdr.length; + + while (pos < end) { + if (x509_parse_extension(cert, pos, end - pos, &pos) + < 0) + return -1; + } + + return 0; +} + + +static int x509_parse_tbs_certificate(const u8 *buf, size_t len, + struct x509_certificate *cert, + const u8 **next) +{ + struct asn1_hdr hdr; + const u8 *pos, *end; + size_t left; + char sbuf[128]; + unsigned long value; + + /* tbsCertificate TBSCertificate ::= SEQUENCE */ + if (asn1_get_next(buf, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "X509: tbsCertificate did not start " + "with a valid SEQUENCE - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + pos = hdr.payload; + end = *next = pos + hdr.length; + + /* + * version [0] EXPLICIT Version DEFAULT v1 + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + if (asn1_get_next(pos, end - pos, &hdr) < 0) + return -1; + pos = hdr.payload; + + if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC) { + if (asn1_get_next(pos, end - pos, &hdr) < 0) + return -1; + + if (hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_INTEGER) { + wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for " + "version field - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + if (hdr.length != 1) { + wpa_printf(MSG_DEBUG, "X509: Unexpected version field " + "length %u (expected 1)", hdr.length); + return -1; + } + pos = hdr.payload; + left = hdr.length; + value = 0; + while (left) { + value <<= 8; + value |= *pos++; + left--; + } + + cert->version = value; + if (cert->version != X509_CERT_V1 && + cert->version != X509_CERT_V2 && + cert->version != X509_CERT_V3) { + wpa_printf(MSG_DEBUG, "X509: Unsupported version %d", + cert->version + 1); + return -1; + } + + if (asn1_get_next(pos, end - pos, &hdr) < 0) + return -1; + } else + cert->version = X509_CERT_V1; + wpa_printf(MSG_DEBUG, "X509: Version X.509v%d", cert->version + 1); + + /* serialNumber CertificateSerialNumber ::= INTEGER */ + if (hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_INTEGER) { + wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for " + "serialNumber; class=%d tag=0x%x", + hdr.class, hdr.tag); + return -1; + } + + pos = hdr.payload; + left = hdr.length; + while (left) { + cert->serial_number <<= 8; + cert->serial_number |= *pos++; + left--; + } + wpa_printf(MSG_DEBUG, "X509: serialNumber %lu", cert->serial_number); + + /* signature AlgorithmIdentifier */ + if (x509_parse_algorithm_identifier(pos, end - pos, &cert->signature, + &pos)) + return -1; + + /* issuer Name */ + if (x509_parse_name(pos, end - pos, &cert->issuer, &pos)) + return -1; + x509_name_string(&cert->issuer, sbuf, sizeof(sbuf)); + wpa_printf(MSG_DEBUG, "X509: issuer %s", sbuf); + + /* validity Validity */ + if (x509_parse_validity(pos, end - pos, cert, &pos)) + return -1; + + /* subject Name */ + if (x509_parse_name(pos, end - pos, &cert->subject, &pos)) + return -1; + x509_name_string(&cert->subject, sbuf, sizeof(sbuf)); + wpa_printf(MSG_DEBUG, "X509: subject %s", sbuf); + + /* subjectPublicKeyInfo SubjectPublicKeyInfo */ + if (x509_parse_public_key(pos, end - pos, cert, &pos)) + return -1; + + if (pos == end) + return 0; + + if (cert->version == X509_CERT_V1) + return 0; + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { + wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" + " tag to parse optional tbsCertificate " + "field(s); parsed class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + + if (hdr.tag == 1) { + /* issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL */ + wpa_printf(MSG_DEBUG, "X509: issuerUniqueID"); + /* TODO: parse UniqueIdentifier ::= BIT STRING */ + + if (hdr.payload + hdr.length == end) + return 0; + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { + wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" + " tag to parse optional tbsCertificate " + "field(s); parsed class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + } + + if (hdr.tag == 2) { + /* subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL */ + wpa_printf(MSG_DEBUG, "X509: subjectUniqueID"); + /* TODO: parse UniqueIdentifier ::= BIT STRING */ + + if (hdr.payload + hdr.length == end) + return 0; + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { + wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" + " tag to parse optional tbsCertificate " + "field(s); parsed class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + } + + if (hdr.tag != 3) { + wpa_printf(MSG_DEBUG, "X509: Ignored unexpected " + "Context-Specific tag %d in optional " + "tbsCertificate fields", hdr.tag); + return 0; + } + + /* extensions [3] EXPLICIT Extensions OPTIONAL */ + + if (cert->version != X509_CERT_V3) { + wpa_printf(MSG_DEBUG, "X509: X.509%d certificate and " + "Extensions data which are only allowed for " + "version 3", cert->version + 1); + return -1; + } + + if (x509_parse_extensions(cert, hdr.payload, hdr.length) < 0) + return -1; + + pos = hdr.payload + hdr.length; + if (pos < end) { + wpa_hexdump(MSG_DEBUG, + "X509: Ignored extra tbsCertificate data", + pos, end - pos); + } + + return 0; +} + + +static int x509_rsadsi_oid(struct asn1_oid *oid) +{ + return oid->len >= 4 && + oid->oid[0] == 1 /* iso */ && + oid->oid[1] == 2 /* member-body */ && + oid->oid[2] == 840 /* us */ && + oid->oid[3] == 113549 /* rsadsi */; +} + + +static int x509_pkcs_oid(struct asn1_oid *oid) +{ + return oid->len >= 5 && + x509_rsadsi_oid(oid) && + oid->oid[4] == 1 /* pkcs */; +} + + +static int x509_digest_oid(struct asn1_oid *oid) +{ + return oid->len >= 5 && + x509_rsadsi_oid(oid) && + oid->oid[4] == 2 /* digestAlgorithm */; +} + + +static int x509_sha1_oid(struct asn1_oid *oid) +{ + return oid->len == 6 && + oid->oid[0] == 1 /* iso */ && + oid->oid[1] == 3 /* identified-organization */ && + oid->oid[2] == 14 /* oiw */ && + oid->oid[3] == 3 /* secsig */ && + oid->oid[4] == 2 /* algorithms */ && + oid->oid[5] == 26 /* id-sha1 */; +} + + +static int x509_sha256_oid(struct asn1_oid *oid) +{ + return oid->len == 9 && + oid->oid[0] == 2 /* joint-iso-itu-t */ && + oid->oid[1] == 16 /* country */ && + oid->oid[2] == 840 /* us */ && + oid->oid[3] == 1 /* organization */ && + oid->oid[4] == 101 /* gov */ && + oid->oid[5] == 3 /* csor */ && + oid->oid[6] == 4 /* nistAlgorithm */ && + oid->oid[7] == 2 /* hashAlgs */ && + oid->oid[8] == 1 /* sha256 */; +} + + +/** + * x509_certificate_parse - Parse a X.509 certificate in DER format + * @buf: Pointer to the X.509 certificate in DER format + * @len: Buffer length + * Returns: Pointer to the parsed certificate or %NULL on failure + * + * Caller is responsible for freeing the returned certificate by calling + * x509_certificate_free(). + */ +struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len) +{ + struct asn1_hdr hdr; + const u8 *pos, *end, *hash_start; + struct x509_certificate *cert; + + cert = (struct x509_certificate *)os_zalloc(sizeof(*cert) + len); + if (cert == NULL) + return NULL; + os_memcpy(cert + 1, buf, len); + cert->cert_start = (u8 *) (cert + 1); + cert->cert_len = len; + + pos = buf; + end = buf + len; + + /* RFC 3280 - X.509 v3 certificate / ASN.1 DER */ + + /* Certificate ::= SEQUENCE */ + if (asn1_get_next(pos, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "X509: Certificate did not start with " + "a valid SEQUENCE - found class %d tag 0x%x", + hdr.class, hdr.tag); + x509_certificate_free(cert); + return NULL; + } + pos = hdr.payload; + + if (pos + hdr.length > end) { + x509_certificate_free(cert); + return NULL; + } + + if (pos + hdr.length < end) { + wpa_hexdump(MSG_MSGDUMP, "X509: Ignoring extra data after DER " + "encoded certificate", + pos + hdr.length, end - pos + hdr.length); + end = pos + hdr.length; + } + + hash_start = pos; + cert->tbs_cert_start = cert->cert_start + (hash_start - buf); + if (x509_parse_tbs_certificate(pos, end - pos, cert, &pos)) { + x509_certificate_free(cert); + return NULL; + } + cert->tbs_cert_len = pos - hash_start; + + /* signatureAlgorithm AlgorithmIdentifier */ + if (x509_parse_algorithm_identifier(pos, end - pos, + &cert->signature_alg, &pos)) { + x509_certificate_free(cert); + return NULL; + } + + /* signatureValue BIT STRING */ + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_BITSTRING) { + wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING " + "(signatureValue) - found class %d tag 0x%x", + hdr.class, hdr.tag); + x509_certificate_free(cert); + return NULL; + } + if (hdr.length < 1) { + x509_certificate_free(cert); + return NULL; + } + pos = hdr.payload; + if (*pos) { + wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", + *pos); + /* PKCS #1 v1.5 10.2.1: + * It is an error if the length in bits of the signature S is + * not a multiple of eight. + */ + x509_certificate_free(cert); + return NULL; + } + os_free(cert->sign_value); + cert->sign_value = os_malloc(hdr.length - 1); + if (cert->sign_value == NULL) { + wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for " + "signatureValue"); + x509_certificate_free(cert); + return NULL; + } + os_memcpy(cert->sign_value, pos + 1, hdr.length - 1); + cert->sign_value_len = hdr.length - 1; + wpa_hexdump(MSG_MSGDUMP, "X509: signature", + cert->sign_value, cert->sign_value_len); + + return cert; +} + + +/** + * x509_certificate_check_signature - Verify certificate signature + * @issuer: Issuer certificate + * @cert: Certificate to be verified + * Returns: 0 if cert has a valid signature that was signed by the issuer, + * -1 if not + */ +int x509_certificate_check_signature(struct x509_certificate *issuer, + struct x509_certificate *cert) +{ + struct crypto_public_key *pk; + u8 *data; + const u8 *pos, *end, *next, *da_end; + size_t data_len; + struct asn1_hdr hdr; + struct asn1_oid oid; + u8 hash[32]; + size_t hash_len; + + if (!x509_pkcs_oid(&cert->signature.oid) || + cert->signature.oid.len != 7 || + cert->signature.oid.oid[5] != 1 /* pkcs-1 */) { + wpa_printf(MSG_DEBUG, "X509: Unrecognized signature " + "algorithm"); + return -1; + } + + pk = crypto_public_key_import(issuer->public_key, + issuer->public_key_len); + if (pk == NULL) + return -1; + + data_len = cert->sign_value_len; + data = os_malloc(data_len); + if (data == NULL) { + crypto_public_key_free(pk); + return -1; + } + + if (crypto_public_key_decrypt_pkcs1(pk, cert->sign_value, + cert->sign_value_len, data, + &data_len) < 0) { + wpa_printf(MSG_DEBUG, "X509: Failed to decrypt signature"); + crypto_public_key_free(pk); + os_free(data); + return -1; + } + crypto_public_key_free(pk); + + wpa_hexdump(MSG_MSGDUMP, "X509: Signature data D", data, data_len); + + /* + * PKCS #1 v1.5, 10.1.2: + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest + * } + * + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * + * Digest ::= OCTET STRING + * + */ + if (asn1_get_next(data, data_len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " + "(DigestInfo) - found class %d tag 0x%x", + hdr.class, hdr.tag); + os_free(data); + return -1; + } + + pos = hdr.payload; + end = pos + hdr.length; + + /* + * X.509: + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + */ + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " + "(AlgorithmIdentifier) - found class %d tag 0x%x", + hdr.class, hdr.tag); + os_free(data); + return -1; + } + da_end = hdr.payload + hdr.length; + + if (asn1_get_oid(hdr.payload, hdr.length, &oid, &next)) { + wpa_printf(MSG_DEBUG, "X509: Failed to parse digestAlgorithm"); + os_free(data); + return -1; + } + + if (x509_sha1_oid(&oid)) { + if (cert->signature.oid.oid[6] != + 5 /* sha-1WithRSAEncryption */) { + wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA1 " + "does not match with certificate " + "signatureAlgorithm (%lu)", + cert->signature.oid.oid[6]); + os_free(data); + return -1; + } + goto skip_digest_oid; + } + + if (x509_sha256_oid(&oid)) { + if (cert->signature.oid.oid[6] != + 11 /* sha2561WithRSAEncryption */) { + wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA256 " + "does not match with certificate " + "signatureAlgorithm (%lu)", + cert->signature.oid.oid[6]); + os_free(data); + return -1; + } + goto skip_digest_oid; + } + + if (!x509_digest_oid(&oid)) { + wpa_printf(MSG_DEBUG, "X509: Unrecognized digestAlgorithm"); + os_free(data); + return -1; + } + switch (oid.oid[5]) { + case 5: /* md5 */ + if (cert->signature.oid.oid[6] != 4 /* md5WithRSAEncryption */) + { + wpa_printf(MSG_DEBUG, "X509: digestAlgorithm MD5 does " + "not match with certificate " + "signatureAlgorithm (%lu)", + cert->signature.oid.oid[6]); + os_free(data); + return -1; + } + break; + case 2: /* md2 */ + case 4: /* md4 */ + default: + wpa_printf(MSG_DEBUG, "X509: Unsupported digestAlgorithm " + "(%lu)", oid.oid[5]); + os_free(data); + return -1; + } + +skip_digest_oid: + /* Digest ::= OCTET STRING */ + pos = da_end; + end = data + data_len; + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_OCTETSTRING) { + wpa_printf(MSG_DEBUG, "X509: Expected OCTETSTRING " + "(Digest) - found class %d tag 0x%x", + hdr.class, hdr.tag); + os_free(data); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "X509: Decrypted Digest", + hdr.payload, hdr.length); + + switch (cert->signature.oid.oid[6]) { + case 4: /* md5WithRSAEncryption */ + md5_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, + hash); + hash_len = 16; + wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (MD5)", + hash, hash_len); + break; + case 5: /* sha-1WithRSAEncryption */ + sha1_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, + hash); + hash_len = 20; + wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA1)", + hash, hash_len); + break; + case 11: /* sha256WithRSAEncryption */ + if (wpa2_crypto_funcs.sha256_vector) { + wpa2_crypto_funcs.sha256_vector(1, &cert->tbs_cert_start, (int *)&cert->tbs_cert_len, + hash); + } else { + wpa_printf(MSG_ERROR, "Fail to register sha256 vector function!\r\n"); + return -1; + } + hash_len = 32; + wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA256)", + hash, hash_len); + break; + case 2: /* md2WithRSAEncryption */ + case 12: /* sha384WithRSAEncryption */ + case 13: /* sha512WithRSAEncryption */ + default: + wpa_printf(MSG_INFO, "X509: Unsupported certificate signature " + "algorithm (%lu)", cert->signature.oid.oid[6]); + os_free(data); + return -1; + } + + if (hdr.length != hash_len || + os_memcmp(hdr.payload, hash, hdr.length) != 0) { + wpa_printf(MSG_INFO, "X509: Certificate Digest does not match " + "with calculated tbsCertificate hash"); + os_free(data); + return -1; + } + + os_free(data); + + wpa_printf(MSG_DEBUG, "X509: Certificate Digest matches with " + "calculated tbsCertificate hash"); + + return 0; +} + + +static int x509_valid_issuer(const struct x509_certificate *cert) +{ + if ((cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS) && + !cert->ca) { + wpa_printf(MSG_DEBUG, "X509: Non-CA certificate used as an " + "issuer"); + return -1; + } + + if (cert->version == X509_CERT_V3 && + !(cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS)) { + wpa_printf(MSG_DEBUG, "X509: v3 CA certificate did not " + "include BasicConstraints extension"); + return -1; + } + + if ((cert->extensions_present & X509_EXT_KEY_USAGE) && + !(cert->key_usage & X509_KEY_USAGE_KEY_CERT_SIGN)) { + wpa_printf(MSG_DEBUG, "X509: Issuer certificate did not have " + "keyCertSign bit in Key Usage"); + return -1; + } + + return 0; +} + + +/** + * x509_certificate_chain_validate - Validate X.509 certificate chain + * @trusted: List of trusted certificates + * @chain: Certificate chain to be validated (first chain must be issued by + * signed by the second certificate in the chain and so on) + * @reason: Buffer for returning failure reason (X509_VALIDATE_*) + * Returns: 0 if chain is valid, -1 if not + */ +int x509_certificate_chain_validate(struct x509_certificate *trusted, + struct x509_certificate *chain, + int *reason, int disable_time_checks) +{ + long unsigned idx; + int chain_trusted = 0; + struct x509_certificate *cert, *trust; + char buf[128]; + struct os_time now; + + *reason = X509_VALIDATE_OK; + + wpa_printf(MSG_DEBUG, "X509: Validate certificate chain"); + os_get_time(&now); + + for (cert = chain, idx = 0; cert; cert = cert->next, idx++) { + x509_name_string(&cert->subject, buf, sizeof(buf)); + wpa_printf(MSG_DEBUG, "X509: %lu: %s", idx, buf); + + if (chain_trusted) + continue; + + if (!disable_time_checks && + ((unsigned long) now.sec < + (unsigned long) cert->not_before || + (unsigned long) now.sec > + (unsigned long) cert->not_after)) { + wpa_printf(MSG_INFO, "X509: Certificate not valid " + "(now=%lu not_before=%lu not_after=%lu)", + now.sec, cert->not_before, cert->not_after); + *reason = X509_VALIDATE_CERTIFICATE_EXPIRED; + return -1; + } + + if (cert->next) { + if (x509_name_compare(&cert->issuer, + &cert->next->subject) != 0) { + wpa_printf(MSG_DEBUG, "X509: Certificate " + "chain issuer name mismatch"); + x509_name_string(&cert->issuer, buf, + sizeof(buf)); + wpa_printf(MSG_DEBUG, "X509: cert issuer: %s", + buf); + x509_name_string(&cert->next->subject, buf, + sizeof(buf)); + wpa_printf(MSG_DEBUG, "X509: next cert " + "subject: %s", buf); + *reason = X509_VALIDATE_CERTIFICATE_UNKNOWN; + return -1; + } + + if (x509_valid_issuer(cert->next) < 0) { + *reason = X509_VALIDATE_BAD_CERTIFICATE; + return -1; + } + + if ((cert->next->extensions_present & + X509_EXT_PATH_LEN_CONSTRAINT) && + idx > cert->next->path_len_constraint) { + wpa_printf(MSG_DEBUG, "X509: pathLenConstraint" + " not met (idx=%lu issuer " + "pathLenConstraint=%lu)", idx, + cert->next->path_len_constraint); + *reason = X509_VALIDATE_BAD_CERTIFICATE; + return -1; + } + + if (x509_certificate_check_signature(cert->next, cert) + < 0) { + wpa_printf(MSG_DEBUG, "X509: Invalid " + "certificate signature within " + "chain"); + *reason = X509_VALIDATE_BAD_CERTIFICATE; + return -1; + } + } + + for (trust = trusted; trust; trust = trust->next) { + if (x509_name_compare(&cert->issuer, &trust->subject) + == 0) + break; + } + + if (trust) { + wpa_printf(MSG_DEBUG, "X509: Found issuer from the " + "list of trusted certificates"); + if (x509_valid_issuer(trust) < 0) { + *reason = X509_VALIDATE_BAD_CERTIFICATE; + return -1; + } + + if (x509_certificate_check_signature(trust, cert) < 0) + { + wpa_printf(MSG_DEBUG, "X509: Invalid " + "certificate signature"); + *reason = X509_VALIDATE_BAD_CERTIFICATE; + return -1; + } + + wpa_printf(MSG_DEBUG, "X509: Trusted certificate " + "found to complete the chain"); + chain_trusted = 1; + } + } + + if (!chain_trusted) { + wpa_printf(MSG_DEBUG, "X509: Did not find any of the issuers " + "from the list of trusted certificates"); + if (trusted) { + *reason = X509_VALIDATE_UNKNOWN_CA; + return -1; + } + wpa_printf(MSG_DEBUG, "X509: Certificate chain validation " + "disabled - ignore unknown CA issue"); + } + + wpa_printf(MSG_DEBUG, "X509: Certificate chain valid"); + + return 0; +} + + +/** + * x509_certificate_get_subject - Get a certificate based on Subject name + * @chain: Certificate chain to search through + * @name: Subject name to search for + * Returns: Pointer to the certificate with the given Subject name or + * %NULL on failure + */ +struct x509_certificate * +x509_certificate_get_subject(struct x509_certificate *chain, + struct x509_name *name) +{ + struct x509_certificate *cert; + + for (cert = chain; cert; cert = cert->next) { + if (x509_name_compare(&cert->subject, name) == 0) + return cert; + } + return NULL; +} + + +/** + * x509_certificate_self_signed - Is the certificate self-signed? + * @cert: Certificate + * Returns: 1 if certificate is self-signed, 0 if not + */ +int x509_certificate_self_signed(struct x509_certificate *cert) +{ + return x509_name_compare(&cert->issuer, &cert->subject) == 0; +} diff --git a/components/wpa_supplicant/src/wpa2/utils/base64.c b/components/wpa_supplicant/src/wpa2/utils/base64.c new file mode 100644 index 0000000000..0340c390e7 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/utils/base64.c @@ -0,0 +1,155 @@ +/* + * Base64 encoding/decoding (RFC1341) + * Copyright (c) 2005-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "os.h" +#include "wpa2/utils/base64.h" + +static const unsigned char base64_table[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/** + * base64_encode - Base64 encode + * @src: Data to be encoded + * @len: Length of the data to be encoded + * @out_len: Pointer to output length variable, or %NULL if not used + * Returns: Allocated buffer of out_len bytes of encoded data, + * or %NULL on failure + * + * Caller is responsible for freeing the returned buffer. Returned buffer is + * nul terminated to make it easier to use as a C string. The nul terminator is + * not included in out_len. + */ +unsigned char * base64_encode(const unsigned char *src, size_t len, + size_t *out_len) +{ + unsigned char *out, *pos; + const unsigned char *end, *in; + size_t olen; + int line_len; + + olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */ + olen += olen / 72; /* line feeds */ + olen++; /* nul termination */ + if (olen < len) + return NULL; /* integer overflow */ + out = os_malloc(olen); + if (out == NULL) + return NULL; + + end = src + len; + in = src; + pos = out; + line_len = 0; + while (end - in >= 3) { + *pos++ = base64_table[in[0] >> 2]; + *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; + *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)]; + *pos++ = base64_table[in[2] & 0x3f]; + in += 3; + line_len += 4; + if (line_len >= 72) { + *pos++ = '\n'; + line_len = 0; + } + } + + if (end - in) { + *pos++ = base64_table[in[0] >> 2]; + if (end - in == 1) { + *pos++ = base64_table[(in[0] & 0x03) << 4]; + *pos++ = '='; + } else { + *pos++ = base64_table[((in[0] & 0x03) << 4) | + (in[1] >> 4)]; + *pos++ = base64_table[(in[1] & 0x0f) << 2]; + } + *pos++ = '='; + line_len += 4; + } + + if (line_len) + *pos++ = '\n'; + + *pos = '\0'; + if (out_len) + *out_len = pos - out; + return out; +} + + +/** + * base64_decode - Base64 decode + * @src: Data to be decoded + * @len: Length of the data to be decoded + * @out_len: Pointer to output length variable + * Returns: Allocated buffer of out_len bytes of decoded data, + * or %NULL on failure + * + * Caller is responsible for freeing the returned buffer. + */ +unsigned char * base64_decode(const unsigned char *src, size_t len, + size_t *out_len) +{ + unsigned char dtable[256], *out, *pos, block[4], tmp; + size_t i, count, olen; + int pad = 0; + + os_memset(dtable, 0x80, 256); + for (i = 0; i < sizeof(base64_table) - 1; i++) + dtable[base64_table[i]] = (unsigned char) i; + dtable['='] = 0; + + count = 0; + for (i = 0; i < len; i++) { + if (dtable[src[i]] != 0x80) + count++; + } + + if (count == 0 || count % 4) + return NULL; + + olen = count / 4 * 3; + pos = out = os_malloc(olen); + if (out == NULL) + return NULL; + + count = 0; + for (i = 0; i < len; i++) { + tmp = dtable[src[i]]; + if (tmp == 0x80) + continue; + + if (src[i] == '=') + pad++; + block[count] = tmp; + count++; + if (count == 4) { + *pos++ = (block[0] << 2) | (block[1] >> 4); + *pos++ = (block[1] << 4) | (block[2] >> 2); + *pos++ = (block[2] << 6) | block[3]; + count = 0; + if (pad) { + if (pad == 1) + pos--; + else if (pad == 2) + pos -= 2; + else { + /* Invalid padding */ + os_free(out); + return NULL; + } + break; + } + } + } + + *out_len = pos - out; + return out; +} diff --git a/components/wpa_supplicant/src/wpa2/utils/ext_password.c b/components/wpa_supplicant/src/wpa2/utils/ext_password.c new file mode 100644 index 0000000000..3989f949b1 --- /dev/null +++ b/components/wpa_supplicant/src/wpa2/utils/ext_password.c @@ -0,0 +1,114 @@ +/* + * External password backend + * Copyright (c) 2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "wpa2/utils/ext_password_i.h" + +#ifdef CONFIG_EXT_PASSWORD_TEST +extern struct ext_password_backend ext_password_test; +#endif /* CONFIG_EXT_PASSWORD_TEST */ + +#ifdef CONFIG_EXT_PASSWORD +static const struct ext_password_backend *backends[] = { +#ifdef CONFIG_EXT_PASSWORD_TEST + &ext_password_test, +#endif /* CONFIG_EXT_PASSWORD_TEST */ + NULL +}; +#endif + +struct ext_password_data { + const struct ext_password_backend *backend; + void *priv; +}; + +#ifdef CONFIG_EXT_PASSWORD +struct ext_password_data * ext_password_init(const char *backend, + const char *params) +{ + struct ext_password_data *data; + int i; + + data = (struct ext_password_data *)os_zalloc(sizeof(*data)); + if (data == NULL) + return NULL; + + for (i = 0; backends[i]; i++) { + if (os_strcmp(backends[i]->name, backend) == 0) { + data->backend = backends[i]; + break; + } + } + + if (!data->backend) { + os_free(data); + return NULL; + } + + data->priv = data->backend->init(params); + if (data->priv == NULL) { + os_free(data); + return NULL; + } + + return data; +} + + +void ext_password_deinit(struct ext_password_data *data) +{ + if (data && data->backend && data->priv) + data->backend->deinit(data->priv); + os_free(data); +} + + +struct wpabuf * ext_password_get(struct ext_password_data *data, + const char *name) +{ + if (data == NULL) + return NULL; + return data->backend->get(data->priv, name); +} +#endif /* CONFIG_EXT_PASSWORD */ + +struct wpabuf * ext_password_alloc(size_t len) +{ + struct wpabuf *buf; + + buf = wpabuf_alloc(len); + if (buf == NULL) + return NULL; + +#ifdef __linux__ + if (mlock(wpabuf_head(buf), wpabuf_len(buf)) < 0) { + wpa_printf(MSG_ERROR, "EXT PW: mlock failed: %s", + strerror(errno)); + } +#endif /* __linux__ */ + + return buf; +} + +#ifdef CONFIG_EXT_PASSWORD +void ext_password_free(struct wpabuf *pw) +{ + if (pw == NULL) + return; + os_memset(wpabuf_mhead(pw), 0, wpabuf_len(pw)); +#ifdef __linux__ + if (munlock(wpabuf_head(pw), wpabuf_len(pw)) < 0) { + wpa_printf(MSG_ERROR, "EXT PW: munlock failed: %s", + strerror(errno)); + } +#endif /* __linux__ */ + wpabuf_free(pw); +} +#endif /* CONFIG_EXT_PASSWORD */ diff --git a/components/wpa_supplicant/src/wps/eap_common.c b/components/wpa_supplicant/src/wps/eap_common.c new file mode 100644 index 0000000000..640bd5a59b --- /dev/null +++ b/components/wpa_supplicant/src/wps/eap_common.c @@ -0,0 +1,205 @@ +/* + * EAP common peer/server definitions + * Copyright (c) 2004-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "wpa2/eap_peer/eap_defs.h" +#include "wpa2/eap_peer/eap_common.h" + +/** + * eap_hdr_len_valid - Validate EAP header length field + * @msg: EAP frame (starting with EAP header) + * @min_payload: Minimum payload length needed + * Returns: 1 for valid header, 0 for invalid + * + * This is a helper function that does minimal validation of EAP messages. The + * length field is verified to be large enough to include the header and not + * too large to go beyond the end of the buffer. + */ +int eap_hdr_len_valid(const struct wpabuf *msg, size_t min_payload) +{ + const struct eap_hdr *hdr; + size_t len; + + if (msg == NULL) + return 0; + + hdr = wpabuf_head(msg); + + if (wpabuf_len(msg) < sizeof(*hdr)) { + wpa_printf(MSG_INFO, "EAP: Too short EAP frame"); + return 0; + } + + len = be_to_host16(hdr->length); + if (len < sizeof(*hdr) + min_payload || len > wpabuf_len(msg)) { + wpa_printf(MSG_INFO, "EAP: Invalid EAP length"); + return 0; + } + + return 1; +} + + +/** + * eap_hdr_validate - Validate EAP header + * @vendor: Expected EAP Vendor-Id (0 = IETF) + * @eap_type: Expected EAP type number + * @msg: EAP frame (starting with EAP header) + * @plen: Pointer to variable to contain the returned payload length + * Returns: Pointer to EAP payload (after type field), or %NULL on failure + * + * This is a helper function for EAP method implementations. This is usually + * called in the beginning of struct eap_method::process() function to verify + * that the received EAP request packet has a valid header. This function is + * able to process both legacy and expanded EAP headers and in most cases, the + * caller can just use the returned payload pointer (into *plen) for processing + * the payload regardless of whether the packet used the expanded EAP header or + * not. + */ +const u8 * eap_hdr_validate(int vendor, EapType eap_type, + const struct wpabuf *msg, size_t *plen) +{ + const struct eap_hdr *hdr; + const u8 *pos; + size_t len; + + if (!eap_hdr_len_valid(msg, 1)) + return NULL; + + hdr = wpabuf_head(msg); + len = be_to_host16(hdr->length); + pos = (const u8 *) (hdr + 1); + + if (*pos == EAP_TYPE_EXPANDED) { + int exp_vendor; + u32 exp_type; + if (len < sizeof(*hdr) + 8) { + wpa_printf(MSG_INFO, "EAP: Invalid expanded EAP " + "length"); + return NULL; + } + pos++; + exp_vendor = WPA_GET_BE24(pos); + pos += 3; + exp_type = WPA_GET_BE32(pos); + pos += 4; + if (exp_vendor != vendor || exp_type != (u32) eap_type) { + wpa_printf(MSG_INFO, "EAP: Invalid expanded frame " + "type"); + return NULL; + } + + *plen = len - sizeof(*hdr) - 8; + return pos; + } else { + if (vendor != EAP_VENDOR_IETF || *pos != eap_type) { + wpa_printf(MSG_INFO, "EAP: Invalid frame type"); + return NULL; + } + *plen = len - sizeof(*hdr) - 1; + return pos + 1; + } +} + + +/** + * eap_msg_alloc - Allocate a buffer for an EAP message + * @vendor: Vendor-Id (0 = IETF) + * @type: EAP type + * @payload_len: Payload length in bytes (data after Type) + * @code: Message Code (EAP_CODE_*) + * @identifier: Identifier + * Returns: Pointer to the allocated message buffer or %NULL on error + * + * This function can be used to allocate a buffer for an EAP message and fill + * in the EAP header. This function is automatically using expanded EAP header + * if the selected Vendor-Id is not IETF. In other words, most EAP methods do + * not need to separately select which header type to use when using this + * function to allocate the message buffers. The returned buffer has room for + * payload_len bytes and has the EAP header and Type field already filled in. + */ +struct wpabuf * eap_msg_alloc(int vendor, EapType type, size_t payload_len, + u8 code, u8 identifier) +{ + struct wpabuf *buf; + struct eap_hdr *hdr; + size_t len; + + len = sizeof(struct eap_hdr) + (vendor == EAP_VENDOR_IETF ? 1 : 8) + + payload_len; + buf = wpabuf_alloc(len); + if (buf == NULL) + return NULL; + + hdr = wpabuf_put(buf, sizeof(*hdr)); + hdr->code = code; + hdr->identifier = identifier; + hdr->length = host_to_be16(len); + + if (vendor == EAP_VENDOR_IETF) { + wpabuf_put_u8(buf, type); + } else { + wpabuf_put_u8(buf, EAP_TYPE_EXPANDED); + wpabuf_put_be24(buf, vendor); + wpabuf_put_be32(buf, type); + } + + return buf; +} + + +/** + * eap_update_len - Update EAP header length + * @msg: EAP message from eap_msg_alloc + * + * This function updates the length field in the EAP header to match with the + * current length for the buffer. This allows eap_msg_alloc() to be used to + * allocate a larger buffer than the exact message length (e.g., if exact + * message length is not yet known). + */ +void eap_update_len(struct wpabuf *msg) +{ + struct eap_hdr *hdr; + hdr = wpabuf_mhead(msg); + if (wpabuf_len(msg) < sizeof(*hdr)) + return; + hdr->length = host_to_be16(wpabuf_len(msg)); +} + + +/** + * eap_get_id - Get EAP Identifier from wpabuf + * @msg: Buffer starting with an EAP header + * Returns: The Identifier field from the EAP header + */ +u8 eap_get_id(const struct wpabuf *msg) +{ + const struct eap_hdr *eap; + + if (wpabuf_len(msg) < sizeof(*eap)) + return 0; + + eap = wpabuf_head(msg); + return eap->identifier; +} + + +/** + * eap_get_id - Get EAP Type from wpabuf + * @msg: Buffer starting with an EAP header + * Returns: The EAP Type after the EAP header + */ +EapType eap_get_type(const struct wpabuf *msg) +{ + if (wpabuf_len(msg) < sizeof(struct eap_hdr) + 1) + return EAP_TYPE_NONE; + + return ((const u8 *) wpabuf_head(msg))[sizeof(struct eap_hdr)]; +} \ No newline at end of file diff --git a/components/wpa_supplicant/src/wps/uuid.c b/components/wpa_supplicant/src/wps/uuid.c new file mode 100644 index 0000000000..9f46824ee8 --- /dev/null +++ b/components/wpa_supplicant/src/wps/uuid.c @@ -0,0 +1,71 @@ +/* + * Universally Unique IDentifier (UUID) + * Copyright (c) 2008, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "wps/utils/uuid.h" + +int uuid_str2bin(const char *str, u8 *bin) +{ + const char *pos; + u8 *opos; + + pos = str; + opos = bin; + + if (hexstr2bin(pos, opos, 4)) + return -1; + pos += 8; + opos += 4; + + if (*pos++ != '-' || hexstr2bin(pos, opos, 2)) + return -1; + pos += 4; + opos += 2; + + if (*pos++ != '-' || hexstr2bin(pos, opos, 2)) + return -1; + pos += 4; + opos += 2; + + if (*pos++ != '-' || hexstr2bin(pos, opos, 2)) + return -1; + pos += 4; + opos += 2; + + if (*pos++ != '-' || hexstr2bin(pos, opos, 6)) + return -1; + + return 0; +} + + +int uuid_bin2str(const u8 *bin, char *str, size_t max_len) +{ + int len; + len = snprintf(str, max_len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-" + "%02x%02x-%02x%02x%02x%02x%02x%02x", + bin[0], bin[1], bin[2], bin[3], + bin[4], bin[5], bin[6], bin[7], + bin[8], bin[9], bin[10], bin[11], + bin[12], bin[13], bin[14], bin[15]); + if (len < 0 || (size_t) len >= max_len) + return -1; + return 0; +} + + +int is_nil_uuid(const u8 *uuid) +{ + int i; + for (i = 0; i < UUID_LEN; i++) + if (uuid[i]) + return 0; + return 1; +} \ No newline at end of file diff --git a/components/wpa_supplicant/src/wps/wps.c b/components/wpa_supplicant/src/wps/wps.c new file mode 100644 index 0000000000..2ed83bbf6f --- /dev/null +++ b/components/wpa_supplicant/src/wps/wps.c @@ -0,0 +1,641 @@ +/* + * Wi-Fi Protected Setup + * Copyright (c) 2007-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include + +#include "wpa/includes.h" +#include "wpa/wpa.h" +#include "wpa/common.h" +#include "wpa/eapol_common.h" +#include "wpa/wpa_debug.h" +#include "wpa/ieee802_11_defs.h" + +#include "crypto/dh_group5.h" + +#include "wps/wps_i.h" +#include "wps/wps_dev_attr.h" + +#include "wpa2/eap_peer/eap_defs.h" +#include "wpa2/eap_peer/eap_common.h" + + +/** + * wps_process_msg - Process a WPS message + * @wps: WPS Registration protocol data from wps_init() + * @op_code: Message OP Code + * @msg: Message data + * Returns: Processing result + * + * This function is used to process WPS messages with OP Codes WSC_ACK, + * WSC_NACK, WSC_MSG, and WSC_Done. The caller (e.g., EAP server/peer) is + * responsible for reassembling the messages before calling this function. + * Response to this message is built by calling wps_get_msg(). + */ +enum wps_process_res wps_process_msg(struct wps_data *wps, + enum wsc_op_code op_code, + const struct wpabuf *msg) +{ + if (wps->registrar) + return wps_registrar_process_msg(wps, op_code, msg); + else + return wps_enrollee_process_msg(wps, op_code, msg); +} + + +/** + * wps_get_msg - Build a WPS message + * @wps: WPS Registration protocol data from wps_init() + * @op_code: Buffer for returning message OP Code + * Returns: The generated WPS message or %NULL on failure + * + * This function is used to build a response to a message processed by calling + * wps_process_msg(). The caller is responsible for freeing the buffer. + */ +struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code) +{ + if (wps->registrar) + return wps_registrar_get_msg(wps, op_code); + else + return wps_enrollee_get_msg(wps, op_code); +} + + +/** + * wps_is_selected_pbc_registrar - Check whether WPS IE indicates active PBC + * @msg: WPS IE contents from Beacon or Probe Response frame + * Returns: 1 if PBC Registrar is active, 0 if not + */ +int wps_is_selected_pbc_registrar(const struct wpabuf *msg, u8 *bssid) +{ + struct wps_sm *sm = wps_sm_get(); + struct wps_parse_attr *attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + int i = 0; + + /* + * In theory, this could also verify that attr.sel_reg_config_methods + * includes WPS_CONFIG_PUSHBUTTON, but some deployed AP implementations + * do not set Selected Registrar Config Methods attribute properly, so + * it is safer to just use Device Password ID here. + */ + + if (wps_parse_msg(msg, attr) < 0) { + os_free(attr); + return 0; + } + + if(!attr->selected_registrar || *attr->selected_registrar == 0) { + if (sm->ignore_sel_reg == false) { + os_free(attr); + return 0; + } + else { + for (i = 0; i < WPS_MAX_DIS_AP_NUM; i++) { + if (0 == os_memcmp(sm->dis_ap_list[i].bssid, bssid, 6)) { + wpa_printf(MSG_DEBUG, "discard ap bssid[%02x:%02x:%02x:%02x:%02x:%02x]\n", \ + bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + os_free(attr); + return 0; + } + } + } + } + + if (!attr->dev_password_id || + WPA_GET_BE16(attr->dev_password_id) != DEV_PW_PUSHBUTTON) { + os_free(attr); + return 0; + } +#if 0 +#ifdef CONFIG_WPS_STRICT + if (!attr->sel_reg_config_methods || + !(WPA_GET_BE16(attr->sel_reg_config_methods) & + WPS_CONFIG_PUSHBUTTON)) { + os_free(attr); + return 0; + } +#endif /* CONFIG_WPS_STRICT */ +#endif + os_free(attr); + return 1; +} + +#ifdef CONFIG_WPS_PIN + +static int is_selected_pin_registrar(struct wps_parse_attr *attr, u8 *bssid) +{ + struct wps_sm *sm = wps_sm_get(); + int i = 0; + + if (!sm || !bssid){ + return 0; + } + /* + * In theory, this could also verify that attr.sel_reg_config_methods + * includes WPS_CONFIG_LABEL, WPS_CONFIG_DISPLAY, or WPS_CONFIG_KEYPAD, + * but some deployed AP implementations do not set Selected Registrar + * Config Methods attribute properly, so it is safer to just use + * Device Password ID here. + */ + + if (!attr->selected_registrar || *attr->selected_registrar == 0) { + if (sm->ignore_sel_reg == false) { + return 0; + } + else { + for (i = 0; i < WPS_MAX_DIS_AP_NUM; i++) { + if (0 == os_memcmp(sm->dis_ap_list[i].bssid, bssid, 6)) { + wpa_printf(MSG_DEBUG, "discard ap bssid[%02x:%02x:%02x:%02x:%02x:%02x]\n", \ + bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); + return 0; + } + } + } + } + if (attr->dev_password_id != NULL && + WPA_GET_BE16(attr->dev_password_id) == DEV_PW_PUSHBUTTON) { + return 0; + } +#ifdef CONFIG_WPS_STRICT + if (!attr->sel_reg_config_methods)// || + //!(WPA_GET_BE16(attr->sel_reg_config_methods) & + //(WPS_CONFIG_LABEL | WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD))) + return 0; +#endif /* CONFIG_WPS_STRICT */ + return 1; +} + + +/** + * wps_is_selected_pin_registrar - Check whether WPS IE indicates active PIN + * @msg: WPS IE contents from Beacon or Probe Response frame + * Returns: 1 if PIN Registrar is active, 0 if not + */ +int wps_is_selected_pin_registrar(const struct wpabuf *msg, u8 *bssid) +{ + struct wps_parse_attr *attr; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) + return -99; + + if (wps_parse_msg(msg, attr) < 0) { + os_free(attr); + return 0; + } + + ret = is_selected_pin_registrar(attr, bssid); + os_free(attr); + + return ret; +} +#endif + +/** + * wps_is_addr_authorized - Check whether WPS IE authorizes MAC address + * @msg: WPS IE contents from Beacon or Probe Response frame + * @addr: MAC address to search for + * @ver1_compat: Whether to use version 1 compatibility mode + * Returns: 2 if the specified address is explicit authorized, 1 if address is + * authorized (broadcast), 0 if not + */ +int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr, + int ver1_compat) +{ + struct wps_sm *sm = wps_sm_get(); + struct wps_parse_attr *attr; + int ret = 0; + unsigned int i; + const u8 *pos; + const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + if (!sm){ + return -10; + } + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (wps_parse_msg(msg, attr) < 0) { + ret = 0; + goto _out; + } + + if (!attr->version2 && ver1_compat) { + /* + * Version 1.0 AP - AuthorizedMACs not used, so revert back to + * old mechanism of using SelectedRegistrar. + */ +#ifdef CONFIG_WPS_PIN + + ret = is_selected_pin_registrar(attr, sm->config.bssid); + goto _out; +#endif + } + + if (!attr->authorized_macs) { + ret = 0; + goto _out; + } + + pos = attr->authorized_macs; + for (i = 0; i < attr->authorized_macs_len / ETH_ALEN; i++) { + if (os_memcmp(pos, addr, ETH_ALEN) == 0) { + ret = 2; + goto _out; + } + if (os_memcmp(pos, bcast, ETH_ALEN) == 0) { + ret = 1; + goto _out; + } + pos += ETH_ALEN; + } +_out: + if (attr) + os_free(attr); + + return ret; +} + + +/** + * wps_ap_priority_compar - Prioritize WPS IE from two APs + * @wps_a: WPS IE contents from Beacon or Probe Response frame + * @wps_b: WPS IE contents from Beacon or Probe Response frame + * Returns: 1 if wps_b is considered more likely selection for WPS + * provisioning, -1 if wps_a is considered more like, or 0 if no preference + */ +int wps_ap_priority_compar(const struct wpabuf *wps_a, + const struct wpabuf *wps_b) +{ + struct wps_parse_attr *attr_a, *attr_b; + int sel_a, sel_b; + int ret = 0; + + attr_a = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + attr_b = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + + if (attr_a == NULL || attr_b == NULL) { + ret = 0; + goto _out; + } + + if (wps_a == NULL || wps_parse_msg(wps_a, attr_a) < 0) + return 1; + if (wps_b == NULL || wps_parse_msg(wps_b, attr_b) < 0) + return -1; + + sel_a = attr_a->selected_registrar && *attr_a->selected_registrar != 0; + sel_b = attr_b->selected_registrar && *attr_b->selected_registrar != 0; + + if (sel_a && !sel_b) { + ret = -1; + goto _out; + } + if (!sel_a && sel_b) { + ret = 1; + goto _out; + } + +_out: + if (attr_a) + os_free(attr_a); + if (attr_b) + os_free(attr_b); + return ret; +} + + +/** + * wps_get_uuid_e - Get UUID-E from WPS IE + * @msg: WPS IE contents from Beacon or Probe Response frame + * Returns: Pointer to UUID-E or %NULL if not included + * + * The returned pointer is to the msg contents and it remains valid only as + * long as the msg buffer is valid. + */ +const u8 * wps_get_uuid_e(const struct wpabuf *msg) +{ + struct wps_parse_attr *attr; + const u8 *uuid_e; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) + return NULL; + + if (wps_parse_msg(msg, attr) < 0) { + uuid_e = NULL; + } else { + uuid_e = attr->uuid_e; + } + os_free(attr); + return uuid_e; +} + + +/** + * wps_is_20 - Check whether WPS attributes claim support for WPS 2.0 + */ +int wps_is_20(const struct wpabuf *msg) +{ + struct wps_parse_attr *attr; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) + return 0; + + if (msg == NULL || wps_parse_msg(msg, attr) < 0) { + ret = 0; + } else { + ret = (attr->version2 != NULL); + } + os_free(attr); + return ret; +} + + +/** + * wps_build_assoc_req_ie - Build WPS IE for (Re)Association Request + * @req_type: Value for Request Type attribute + * Returns: WPS IE or %NULL on failure + * + * The caller is responsible for freeing the buffer. + */ +struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type) +{ + struct wpabuf *ie; + u8 *len; + + wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association " + "Request"); + ie = wpabuf_alloc(100); + if (ie == NULL) + return NULL; + + wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); + len = wpabuf_put(ie, 1); + wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); + + if (wps_build_version(ie) || + wps_build_req_type(ie, req_type) || + wps_build_wfa_ext(ie, 0, NULL, 0)) { + wpabuf_free(ie); + return NULL; + } + + *len = wpabuf_len(ie) - 2; + + return ie; +} + + +/** + * wps_build_assoc_resp_ie - Build WPS IE for (Re)Association Response + * Returns: WPS IE or %NULL on failure + * + * The caller is responsible for freeing the buffer. + */ +struct wpabuf * wps_build_assoc_resp_ie(void) +{ + struct wpabuf *ie; + u8 *len; + + wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association " + "Response"); + ie = wpabuf_alloc(100); + if (ie == NULL) + return NULL; + + wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); + len = wpabuf_put(ie, 1); + wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); + + if (wps_build_version(ie) || + wps_build_resp_type(ie, WPS_RESP_AP) || + wps_build_wfa_ext(ie, 0, NULL, 0)) { + wpabuf_free(ie); + return NULL; + } + + *len = wpabuf_len(ie) - 2; + + return ie; +} + + +/** + * wps_build_probe_req_ie - Build WPS IE for Probe Request + * @pw_id: Password ID (DEV_PW_PUSHBUTTON for active PBC and DEV_PW_DEFAULT for + * most other use cases) + * @dev: Device attributes + * @uuid: Own UUID + * @req_type: Value for Request Type attribute + * @num_req_dev_types: Number of requested device types + * @req_dev_types: Requested device types (8 * num_req_dev_types octets) or + * %NULL if none + * Returns: WPS IE or %NULL on failure + * + * The caller is responsible for freeing the buffer. + */ +struct wpabuf * wps_build_probe_req_ie(u16 pw_id, struct wps_device_data *dev, + const u8 *uuid, + enum wps_request_type req_type, + unsigned int num_req_dev_types, + const u8 *req_dev_types) +{ + struct wpabuf *ie; + + wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for Probe Request\n"); + + ie = wpabuf_alloc(400); + if (ie == NULL) { + wpa_printf(MSG_ERROR, "WPS: ie alloc failed."); + return NULL; + } + + if (wps_build_version(ie) || + wps_build_req_type(ie, req_type) || + wps_build_config_methods(ie, dev->config_methods) || + wps_build_uuid_e(ie, uuid) || + wps_build_primary_dev_type(dev, ie) || + wps_build_rf_bands(dev, ie) || + wps_build_assoc_state(NULL, ie) || + wps_build_config_error(ie, WPS_CFG_NO_ERROR) || + wps_build_dev_password_id(ie, pw_id) || +#ifdef CONFIG_WPS2 + wps_build_manufacturer(dev, ie) || + wps_build_model_name(dev, ie) || + wps_build_model_number(dev, ie) || + wps_build_dev_name(dev, ie) || + wps_build_wfa_ext(ie, req_type == WPS_REQ_ENROLLEE, NULL, 0) || +#endif /* CONFIG_WPS2 */ + wps_build_req_dev_type(dev, ie, num_req_dev_types, req_dev_types) + || + wps_build_secondary_dev_type(dev, ie) + ) { + wpabuf_free(ie); + return NULL; + } + +#ifndef CONFIG_WPS2 + if (dev->p2p && wps_build_dev_name(dev, ie)) { + wpabuf_free(ie); + return NULL; + } +#endif /* CONFIG_WPS2 */ + + return wps_ie_encapsulate(ie); +} + +#ifdef CONFIG_WPS_UPNP + +void wps_free_pending_msgs(struct upnp_pending_message *msgs) +{ + struct upnp_pending_message *p, *prev; + p = msgs; + while (p) { + prev = p; + p = p->next; + wpabuf_free(prev->msg); + os_free(prev); + } +} + +#endif + +int wps_attr_text(struct wpabuf *data, char *buf, char *end) +{ + struct wps_parse_attr *attr; + char *pos = buf; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) + return -99; + + if (wps_parse_msg(data, attr) < 0) { + ret = -1; + goto _out; + } + + if (attr->wps_state) { + if (*attr->wps_state == WPS_STATE_NOT_CONFIGURED) + ret = snprintf(pos, end - pos, + "wps_state=unconfigured\n"); + else if (*attr->wps_state == WPS_STATE_CONFIGURED) + ret = snprintf(pos, end - pos, + "wps_state=configured\n"); + else + ret = 0; + if (ret < 0 || ret >= end - pos) { + ret = pos - buf; + goto _out; + } + pos += ret; + } + + if (attr->ap_setup_locked && *attr->ap_setup_locked) { + ret = snprintf(pos, end - pos, + "wps_ap_setup_locked=1\n"); + if (ret < 0 || ret >= end - pos) { + ret = pos - buf; + goto _out; + } + pos += ret; + } + + if (attr->selected_registrar && *attr->selected_registrar) { + ret = snprintf(pos, end - pos, + "wps_selected_registrar=1\n"); + if (ret < 0 || ret >= end - pos) { + ret = pos - buf; + goto _out; + } + pos += ret; + } + + if (attr->dev_password_id) { + ret = snprintf(pos, end - pos, + "wps_device_password_id=%u\n", + WPA_GET_BE16(attr->dev_password_id)); + if (ret < 0 || ret >= end - pos) { + ret = pos - buf; + goto _out; + } + pos += ret; + } + + if (attr->sel_reg_config_methods) { + ret = snprintf(pos, end - pos, + "wps_selected_registrar_config_methods=" + "0x%04x\n", + WPA_GET_BE16(attr->sel_reg_config_methods)); + if (ret < 0 || ret >= end - pos) { + ret = pos - buf; + goto _out; + } + pos += ret; + } + + if (attr->primary_dev_type) { + char devtype[WPS_DEV_TYPE_BUFSIZE]; + ret = snprintf(pos, end - pos, + "wps_primary_device_type=%s\n", + wps_dev_type_bin2str(attr->primary_dev_type, + devtype, + sizeof(devtype))); + if (ret < 0 || ret >= end - pos) { + ret = pos - buf; + goto _out; + } + pos += ret; + } + + if (attr->dev_name) { + char *str = (char *)os_malloc(attr->dev_name_len + 1); + size_t i; + if (str == NULL) { + ret = pos - buf; + goto _out; + } + for (i = 0; i < attr->dev_name_len; i++) { + if (attr->dev_name[i] < 32) + str[i] = '_'; + else + str[i] = attr->dev_name[i]; + } + str[i] = '\0'; + ret = snprintf(pos, end - pos, "wps_device_name=%s\n", str); + os_free(str); + if (ret < 0 || ret >= end - pos) { + ret = pos - buf; + goto _out; + } + pos += ret; + } + + if (attr->config_methods) { + ret = snprintf(pos, end - pos, + "wps_config_methods=0x%04x\n", + WPA_GET_BE16(attr->config_methods)); + if (ret < 0 || ret >= end - pos) { + ret = pos - buf; + goto _out; + } + pos += ret; + } + + ret = pos - buf; +_out: + if (attr) + os_free(attr); + return ret; +} diff --git a/components/wpa_supplicant/src/wps/wps_attr_build.c b/components/wpa_supplicant/src/wps/wps_attr_build.c new file mode 100644 index 0000000000..42e2d6baea --- /dev/null +++ b/components/wpa_supplicant/src/wps/wps_attr_build.c @@ -0,0 +1,438 @@ +/* + * Wi-Fi Protected Setup - attribute building + * Copyright (c) 2008, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "wpa/includes.h" +#include "wpa/common.h" +#include "wpa/wpa_debug.h" + +#include "crypto/aes_wrap.h" +#include "crypto/crypto.h" +#include "crypto/dh_group5.h" +#include "crypto/sha256.h" +#include "crypto/random.h" + +#include "wpa/ieee802_11_defs.h" +#include "wps/wps_i.h" +#include "soc/dport_reg.h" + +int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg, wps_key_mode_t mode) +{ + struct wpabuf *pubkey; + + if (mode != WPS_CALC_KEY_NO_CALC) { + + wpa_printf(MSG_DEBUG, "WPS: * Public Key"); + wpabuf_free(wps->dh_privkey); + if (wps->dev_pw_id != DEV_PW_DEFAULT && wps->wps->dh_privkey) { + wpa_printf(MSG_DEBUG, "WPS: Using pre-configured DH keys"); + wps->dh_privkey = wpabuf_dup(wps->wps->dh_privkey); + wps->dh_ctx = wps->wps->dh_ctx; + wps->wps->dh_ctx = NULL; + pubkey = wpabuf_dup(wps->wps->dh_pubkey); +#ifdef CONFIG_WPS_NFC + } else if (wps->dev_pw_id >= 0x10 && wps->wps->ap && + wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id) { + wpa_printf(MSG_DEBUG, "WPS: Using NFC password token DH keys"); + wps->dh_privkey = wpabuf_dup(wps->wps->ap_nfc_dh_privkey); + pubkey = wpabuf_dup(wps->wps->ap_nfc_dh_pubkey); + wps->dh_ctx = dh5_init_fixed(wps->dh_privkey, pubkey); +#endif /* CONFIG_WPS_NFC */ + } else { + wpa_printf(MSG_DEBUG, "WPS: Generate new DH keys"); + wps->dh_privkey = NULL; + dh5_free(wps->dh_ctx); + + wpa_printf(MSG_DEBUG, "build public key start\n"); + + wps->dh_ctx = dh5_init(&wps->dh_privkey, &pubkey); + + wpa_printf(MSG_DEBUG, "build public key finish\n"); + + pubkey = wpabuf_zeropad(pubkey, 192); + } + if (wps->dh_ctx == NULL || wps->dh_privkey == NULL || pubkey == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Failed to initialize " + "Diffie-Hellman handshake"); + wpabuf_free(pubkey); + return -1; + } + wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); + wpa_hexdump_buf(MSG_DEBUG, "WPS: DH own Public Key", pubkey); + + if (wps->registrar) { + wpabuf_free(wps->dh_pubkey_r); + wps->dh_pubkey_r = pubkey; + } else { + wpabuf_free(wps->dh_pubkey_e); + wps->dh_pubkey_e = pubkey; + } + + } + + if (mode != WPS_CALC_KEY_PRE_CALC) { + if (wps->registrar) + pubkey = wps->dh_pubkey_r; + else + pubkey = wps->dh_pubkey_e; + + wpabuf_put_be16(msg, ATTR_PUBLIC_KEY); + wpabuf_put_be16(msg, wpabuf_len(pubkey)); + wpabuf_put_buf(msg, pubkey); + } + + return 0; +} + + +int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type) +{ + wpa_printf(MSG_DEBUG, "WPS: * Request Type"); + wpabuf_put_be16(msg, ATTR_REQUEST_TYPE); + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, type); + return 0; +} + + +int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type) +{ + wpa_printf(MSG_DEBUG, "WPS: * Response Type (%d)", type); + wpabuf_put_be16(msg, ATTR_RESPONSE_TYPE); + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, type); + return 0; +} + + +int wps_build_config_methods(struct wpabuf *msg, u16 methods) +{ + wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); + wpabuf_put_be16(msg, ATTR_CONFIG_METHODS); + wpabuf_put_be16(msg, 2); + wpabuf_put_be16(msg, methods); + return 0; +} + + +int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid) +{ + wpa_printf(MSG_DEBUG, "WPS: * UUID-E"); + wpabuf_put_be16(msg, ATTR_UUID_E); + wpabuf_put_be16(msg, WPS_UUID_LEN); + wpabuf_put_data(msg, uuid, WPS_UUID_LEN); + return 0; +} + + +int wps_build_dev_password_id(struct wpabuf *msg, u16 id) +{ + wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id); + wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); + wpabuf_put_be16(msg, 2); + wpabuf_put_be16(msg, id); + return 0; +} + + +int wps_build_config_error(struct wpabuf *msg, u16 err) +{ + wpa_printf(MSG_DEBUG, "WPS: * Configuration Error (%d)", err); + wpabuf_put_be16(msg, ATTR_CONFIG_ERROR); + wpabuf_put_be16(msg, 2); + wpabuf_put_be16(msg, err); + return 0; +} + + +int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg) +{ + u8 hash[SHA256_MAC_LEN]; + const u8 *addr[2]; + size_t len[2]; + + if (wps->last_msg == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Last message not available for " + "building authenticator"); + return -1; + } + + /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*) + * (M_curr* is M_curr without the Authenticator attribute) + */ + addr[0] = wpabuf_head(wps->last_msg); + len[0] = wpabuf_len(wps->last_msg); + addr[1] = wpabuf_head(msg); + len[1] = wpabuf_len(msg); + if (wps_crypto_funcs.hmac_sha256_vector) { + wps_crypto_funcs.hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, (int *)len, hash); + } else { + wpa_printf(MSG_ERROR, "Fail to register hmac sha256 vector!\r\n"); + return -1; + } + wpa_printf(MSG_DEBUG, "WPS: * Authenticator"); + wpabuf_put_be16(msg, ATTR_AUTHENTICATOR); + wpabuf_put_be16(msg, WPS_AUTHENTICATOR_LEN); + wpabuf_put_data(msg, hash, WPS_AUTHENTICATOR_LEN); + + return 0; +} + + +int wps_build_version(struct wpabuf *msg) +{ + /* + * Note: This attribute is deprecated and set to hardcoded 0x10 for + * backwards compatibility reasons. The real version negotiation is + * done with Version2. + */ + wpa_printf(MSG_DEBUG, "WPS: * Version (hardcoded 0x10)"); + wpabuf_put_be16(msg, ATTR_VERSION); + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, 0x10); + return 0; +} + + +int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll, + const u8 *auth_macs, size_t auth_macs_count) +{ +#ifdef CONFIG_WPS2 + u8 *len; + + wpabuf_put_be16(msg, ATTR_VENDOR_EXT); + len = wpabuf_put(msg, 2); /* to be filled */ + wpabuf_put_be24(msg, WPS_VENDOR_ID_WFA); + + wpa_printf(MSG_DEBUG, "WPS: * Version2 (0x%x)", WPS_VERSION); + wpabuf_put_u8(msg, WFA_ELEM_VERSION2); + wpabuf_put_u8(msg, 1); + wpabuf_put_u8(msg, WPS_VERSION); + + if (req_to_enroll) { + wpa_printf(MSG_DEBUG, "WPS: * Request to Enroll (1)"); + wpabuf_put_u8(msg, WFA_ELEM_REQUEST_TO_ENROLL); + wpabuf_put_u8(msg, 1); + wpabuf_put_u8(msg, 1); + } + + if (auth_macs && auth_macs_count) { + size_t i; + wpa_printf(MSG_DEBUG, "WPS: * AuthorizedMACs (count=%d)", + (int) auth_macs_count); + wpabuf_put_u8(msg, WFA_ELEM_AUTHORIZEDMACS); + wpabuf_put_u8(msg, auth_macs_count * ETH_ALEN); + wpabuf_put_data(msg, auth_macs, auth_macs_count * ETH_ALEN); + for (i = 0; i < auth_macs_count; i++) + wpa_printf(MSG_DEBUG, "WPS: AuthorizedMAC: " MACSTR, + MAC2STR(&auth_macs[i * ETH_ALEN])); + } + + WPA_PUT_BE16(len, (u8 *) wpabuf_put(msg, 0) - len - 2); +#endif /* CONFIG_WPS2 */ + +#ifdef CONFIG_WPS_TESTING + if (WPS_VERSION > 0x20) { + wpa_printf(MSG_DEBUG, "WPS: * Extensibility Testing - extra " + "attribute"); + wpabuf_put_be16(msg, ATTR_EXTENSIBILITY_TEST); + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, 42); + } +#endif /* CONFIG_WPS_TESTING */ + return 0; +} + + +int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type) +{ + wpa_printf(MSG_DEBUG, "WPS: * Message Type (%d)", msg_type); + wpabuf_put_be16(msg, ATTR_MSG_TYPE); + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, msg_type); + return 0; +} + + +int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS: * Enrollee Nonce"); + wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE); + wpabuf_put_be16(msg, WPS_NONCE_LEN); + wpabuf_put_data(msg, wps->nonce_e, WPS_NONCE_LEN); + return 0; +} + + +int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS: * Registrar Nonce"); + wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE); + wpabuf_put_be16(msg, WPS_NONCE_LEN); + wpabuf_put_data(msg, wps->nonce_r, WPS_NONCE_LEN); + return 0; +} + + +int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg) +{ + u16 auth_types = WPS_AUTH_TYPES; +#ifdef CONFIG_WPS2 + auth_types &= ~WPS_AUTH_SHARED; +#endif /* CONFIG_WPS2 */ + wpa_printf(MSG_DEBUG, "WPS: * Authentication Type Flags"); + wpabuf_put_be16(msg, ATTR_AUTH_TYPE_FLAGS); + wpabuf_put_be16(msg, 2); + wpabuf_put_be16(msg, auth_types); + return 0; +} + + +int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg) +{ + u16 encr_types = WPS_ENCR_TYPES; +#ifdef CONFIG_WPS2 + encr_types &= ~WPS_ENCR_WEP; +#endif /* CONFIG_WPS2 */ + wpa_printf(MSG_DEBUG, "WPS: * Encryption Type Flags"); + wpabuf_put_be16(msg, ATTR_ENCR_TYPE_FLAGS); + wpabuf_put_be16(msg, 2); + wpabuf_put_be16(msg, encr_types); + return 0; +} + + +int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS: * Connection Type Flags"); + wpabuf_put_be16(msg, ATTR_CONN_TYPE_FLAGS); + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, WPS_CONN_ESS); + return 0; +} + + +int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS: * Association State"); + wpabuf_put_be16(msg, ATTR_ASSOC_STATE); + wpabuf_put_be16(msg, 2); + wpabuf_put_be16(msg, WPS_ASSOC_NOT_ASSOC); + return 0; +} + + +int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg) +{ + u8 hash[SHA256_MAC_LEN]; + + wpa_printf(MSG_DEBUG, "WPS: * Key Wrap Authenticator"); + if (wps_crypto_funcs.hmac_sha256) { + wps_crypto_funcs.hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, wpabuf_head(msg), + wpabuf_len(msg), hash); + } else { + wpa_printf(MSG_ERROR, "Fail to register hmac sha256 function!\r\n"); + return -1; + } + wpabuf_put_be16(msg, ATTR_KEY_WRAP_AUTH); + wpabuf_put_be16(msg, WPS_KWA_LEN); + wpabuf_put_data(msg, hash, WPS_KWA_LEN); + return 0; +} + + +int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, + struct wpabuf *plain) +{ + size_t pad_len; + const size_t block_size = 16; + u8 *iv, *data; + + wpa_printf(MSG_DEBUG, "WPS: * Encrypted Settings"); + + /* PKCS#5 v2.0 pad */ + pad_len = block_size - wpabuf_len(plain) % block_size; + os_memset(wpabuf_put(plain, pad_len), pad_len, pad_len); + + wpabuf_put_be16(msg, ATTR_ENCR_SETTINGS); + wpabuf_put_be16(msg, block_size + wpabuf_len(plain)); + + iv = wpabuf_put(msg, block_size); + if (random_get_bytes(iv, block_size) < 0) + return -1; + + data = wpabuf_put(msg, 0); + wpabuf_put_buf(msg, plain); + wpa_printf(MSG_DEBUG, "WPS: * AES 128 Encrypted Settings"); + if (wps_crypto_funcs.aes_128_encrypt) { + if (wps_crypto_funcs.aes_128_encrypt(wps->keywrapkey, iv, data, wpabuf_len(plain))) + return -1; + } else { + wpa_printf(MSG_ERROR, "Fail to register aes_128_encrypt function!\r\n"); + return -1; + } + return 0; +} + + +#ifdef CONFIG_WPS_OOB +int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id, + const struct wpabuf *pubkey, const u8 *dev_pw, + size_t dev_pw_len) +{ + size_t hash_len; + const u8 *addr[1]; + u8 pubkey_hash[WPS_HASH_LEN]; + + addr[0] = wpabuf_head(pubkey); + hash_len = wpabuf_len(pubkey); + if (wps_crypto_funcs.sha256_vector) { + wps_crypto_funcs.sha256_vector(1, addr, &hash_len, pubkey_hash); + } else { + wpa_printf(MSG_ERROR, "Fail to register sha256 vector function!\r\n"); + return -1; + } + wpabuf_put_be16(msg, ATTR_OOB_DEVICE_PASSWORD); + wpabuf_put_be16(msg, WPS_OOB_PUBKEY_HASH_LEN + 2 + dev_pw_len); + wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); + wpabuf_put_be16(msg, dev_pw_id); + wpabuf_put_data(msg, dev_pw, dev_pw_len); + + return 0; +} +#endif /* CONFIG_WPS_OOB */ + + +/* Encapsulate WPS IE data with one (or more, if needed) IE headers */ +struct wpabuf * wps_ie_encapsulate(struct wpabuf *data) +{ + struct wpabuf *ie; + const u8 *pos, *end; + + ie = wpabuf_alloc(wpabuf_len(data) + 100); + if (ie == NULL) { + wpabuf_free(data); + return NULL; + } + + pos = wpabuf_head(data); + end = pos + wpabuf_len(data); + + while (end > pos) { + size_t frag_len = end - pos; + if (frag_len > 251) + frag_len = 251; + wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); + wpabuf_put_u8(ie, 4 + frag_len); + wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); + wpabuf_put_data(ie, pos, frag_len); + pos += frag_len; + } + + wpabuf_free(data); + + return ie; +} \ No newline at end of file diff --git a/components/wpa_supplicant/src/wps/wps_attr_parse.c b/components/wpa_supplicant/src/wps/wps_attr_parse.c new file mode 100644 index 0000000000..a8cf76683d --- /dev/null +++ b/components/wpa_supplicant/src/wps/wps_attr_parse.c @@ -0,0 +1,640 @@ +/* + * Wi-Fi Protected Setup - attribute parsing + * Copyright (c) 2008, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "wps/wps_defs.h" +#include "wps/wps_attr_parse.h" + +#ifndef CONFIG_WPS_STRICT +#define WPS_WORKAROUNDS +#endif /* CONFIG_WPS_STRICT */ + + +static int wps_set_vendor_ext_wfa_subelem(struct wps_parse_attr *attr, + u8 id, u8 len, const u8 *pos) +{ + wpa_printf(MSG_DEBUG, "WPS: WFA subelement id=%u len=%u", + id, len); + switch (id) { + case WFA_ELEM_VERSION2: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Version2 length " + "%u", len); + return -1; + } + attr->version2 = pos; + break; + case WFA_ELEM_AUTHORIZEDMACS: + attr->authorized_macs = pos; + attr->authorized_macs_len = len; + break; + case WFA_ELEM_NETWORK_KEY_SHAREABLE: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key " + "Shareable length %u", len); + return -1; + } + attr->network_key_shareable = pos; + break; + case WFA_ELEM_REQUEST_TO_ENROLL: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Request to Enroll " + "length %u", len); + return -1; + } + attr->request_to_enroll = pos; + break; + case WFA_ELEM_SETTINGS_DELAY_TIME: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Settings Delay " + "Time length %u", len); + return -1; + } + attr->settings_delay_time = pos; + break; + default: + wpa_printf(MSG_DEBUG, "WPS: Skipped unknown WFA Vendor " + "Extension subelement %u", id); + break; + } + + return 0; +} + + +static int wps_parse_vendor_ext_wfa(struct wps_parse_attr *attr, const u8 *pos, + u16 len) +{ + const u8 *end = pos + len; + u8 id, elen; + + while (pos + 2 < end) { + id = *pos++; + elen = *pos++; + if (pos + elen > end) + break; + if (wps_set_vendor_ext_wfa_subelem(attr, id, elen, pos) < 0) + return -1; + pos += elen; + } + + return 0; +} + + +static int wps_parse_vendor_ext(struct wps_parse_attr *attr, const u8 *pos, + u16 len) +{ + u32 vendor_id; + + if (len < 3) { + wpa_printf(MSG_DEBUG, "WPS: Skip invalid Vendor Extension"); + return 0; + } + + vendor_id = WPA_GET_BE24(pos); + switch (vendor_id) { + case WPS_VENDOR_ID_WFA: + return wps_parse_vendor_ext_wfa(attr, pos + 3, len - 3); + } + + /* Handle unknown vendor extensions */ + + wpa_printf(MSG_DEBUG, "WPS: Unknown Vendor Extension (Vendor ID %u)", + vendor_id); + + if (len > WPS_MAX_VENDOR_EXT_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Too long Vendor Extension (%u)", + len); + return -1; + } + + if (attr->num_vendor_ext >= MAX_WPS_PARSE_VENDOR_EXT) { + wpa_printf(MSG_DEBUG, "WPS: Skipped Vendor Extension " + "attribute (max %d vendor extensions)", + MAX_WPS_PARSE_VENDOR_EXT); + return -1; + } + attr->vendor_ext[attr->num_vendor_ext] = pos; + attr->vendor_ext_len[attr->num_vendor_ext] = len; + attr->num_vendor_ext++; + + return 0; +} + + +static int wps_set_attr(struct wps_parse_attr *attr, u16 type, + const u8 *pos, u16 len) +{ + switch (type) { + case ATTR_VERSION: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Version length %u", + len); + return -1; + } + attr->version = pos; + break; + case ATTR_MSG_TYPE: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type " + "length %u", len); + return -1; + } + attr->msg_type = pos; + break; + case ATTR_ENROLLEE_NONCE: + if (len != WPS_NONCE_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce " + "length %u", len); + return -1; + } + attr->enrollee_nonce = pos; + break; + case ATTR_REGISTRAR_NONCE: + if (len != WPS_NONCE_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce " + "length %u", len); + return -1; + } + attr->registrar_nonce = pos; + break; + case ATTR_UUID_E: + if (len != WPS_UUID_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-E length %u", + len); + return -1; + } + attr->uuid_e = pos; + break; + case ATTR_UUID_R: + if (len != WPS_UUID_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid UUID-R length %u", + len); + return -1; + } + attr->uuid_r = pos; + break; + case ATTR_AUTH_TYPE_FLAGS: + if (len != 2) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " + "Type Flags length %u", len); + return -1; + } + attr->auth_type_flags = pos; + break; + case ATTR_ENCR_TYPE_FLAGS: + if (len != 2) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption Type " + "Flags length %u", len); + return -1; + } + attr->encr_type_flags = pos; + break; + case ATTR_CONN_TYPE_FLAGS: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Connection Type " + "Flags length %u", len); + return -1; + } + attr->conn_type_flags = pos; + break; + case ATTR_CONFIG_METHODS: + if (len != 2) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Config Methods " + "length %u", len); + return -1; + } + attr->config_methods = pos; + break; + case ATTR_SELECTED_REGISTRAR_CONFIG_METHODS: + if (len != 2) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Selected " + "Registrar Config Methods length %u", len); + return -1; + } + attr->sel_reg_config_methods = pos; + break; + case ATTR_PRIMARY_DEV_TYPE: + if (len != WPS_DEV_TYPE_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Primary Device " + "Type length %u", len); + return -1; + } + attr->primary_dev_type = pos; + break; + case ATTR_RF_BANDS: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid RF Bands length " + "%u", len); + return -1; + } + attr->rf_bands = pos; + break; + case ATTR_ASSOC_STATE: + if (len != 2) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Association State " + "length %u", len); + return -1; + } + attr->assoc_state = pos; + break; + case ATTR_CONFIG_ERROR: + if (len != 2) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Configuration " + "Error length %u", len); + return -1; + } + attr->config_error = pos; + break; + case ATTR_DEV_PASSWORD_ID: + if (len != 2) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Device Password " + "ID length %u", len); + return -1; + } + attr->dev_password_id = pos; + break; + case ATTR_OOB_DEVICE_PASSWORD: + if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 + + WPS_OOB_DEVICE_PASSWORD_MIN_LEN || + len > WPS_OOB_PUBKEY_HASH_LEN + 2 + + WPS_OOB_DEVICE_PASSWORD_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device " + "Password length %u", len); + return -1; + } + attr->oob_dev_password = pos; + attr->oob_dev_password_len = len; + break; + case ATTR_OS_VERSION: + if (len != 4) { + wpa_printf(MSG_DEBUG, "WPS: Invalid OS Version length " + "%u", len); + return -1; + } + attr->os_version = pos; + break; + case ATTR_WPS_STATE: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Wi-Fi Protected " + "Setup State length %u", len); + return -1; + } + attr->wps_state = pos; + break; + case ATTR_AUTHENTICATOR: + if (len != WPS_AUTHENTICATOR_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Authenticator " + "length %u", len); + return -1; + } + attr->authenticator = pos; + break; + case ATTR_R_HASH1: + if (len != WPS_HASH_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash1 length %u", + len); + return -1; + } + attr->r_hash1 = pos; + break; + case ATTR_R_HASH2: + if (len != WPS_HASH_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid R-Hash2 length %u", + len); + return -1; + } + attr->r_hash2 = pos; + break; + case ATTR_E_HASH1: + if (len != WPS_HASH_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash1 length %u", + len); + return -1; + } + attr->e_hash1 = pos; + break; + case ATTR_E_HASH2: + if (len != WPS_HASH_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid E-Hash2 length %u", + len); + return -1; + } + attr->e_hash2 = pos; + break; + case ATTR_R_SNONCE1: + if (len != WPS_SECRET_NONCE_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce1 length " + "%u", len); + return -1; + } + attr->r_snonce1 = pos; + break; + case ATTR_R_SNONCE2: + if (len != WPS_SECRET_NONCE_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid R-SNonce2 length " + "%u", len); + return -1; + } + attr->r_snonce2 = pos; + break; + case ATTR_E_SNONCE1: + if (len != WPS_SECRET_NONCE_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce1 length " + "%u", len); + return -1; + } + attr->e_snonce1 = pos; + break; + case ATTR_E_SNONCE2: + if (len != WPS_SECRET_NONCE_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid E-SNonce2 length " + "%u", len); + return -1; + } + attr->e_snonce2 = pos; + break; + case ATTR_KEY_WRAP_AUTH: + if (len != WPS_KWA_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Key Wrap " + "Authenticator length %u", len); + return -1; + } + attr->key_wrap_auth = pos; + break; + case ATTR_AUTH_TYPE: + if (len != 2) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Authentication " + "Type length %u", len); + return -1; + } + attr->auth_type = pos; + break; + case ATTR_ENCR_TYPE: + if (len != 2) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Encryption " + "Type length %u", len); + return -1; + } + attr->encr_type = pos; + break; + case ATTR_NETWORK_INDEX: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Network Index " + "length %u", len); + return -1; + } + attr->network_idx = pos; + break; + case ATTR_NETWORK_KEY_INDEX: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Network Key Index " + "length %u", len); + return -1; + } + attr->network_key_idx = pos; + break; + case ATTR_MAC_ADDR: + if (len != ETH_ALEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid MAC Address " + "length %u", len); + return -1; + } + attr->mac_addr = pos; + break; + case ATTR_KEY_PROVIDED_AUTO: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Key Provided " + "Automatically length %u", len); + return -1; + } + attr->key_prov_auto = pos; + break; + case ATTR_802_1X_ENABLED: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid 802.1X Enabled " + "length %u", len); + return -1; + } + attr->dot1x_enabled = pos; + break; + case ATTR_SELECTED_REGISTRAR: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Selected Registrar" + " length %u", len); + return -1; + } + attr->selected_registrar = pos; + break; + case ATTR_REQUEST_TYPE: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Request Type " + "length %u", len); + return -1; + } + attr->request_type = pos; + break; + case ATTR_RESPONSE_TYPE: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Response Type " + "length %u", len); + return -1; + } + attr->response_type = pos; + break; + case ATTR_MANUFACTURER: + attr->manufacturer = pos; + attr->manufacturer_len = len; + break; + case ATTR_MODEL_NAME: + attr->model_name = pos; + attr->model_name_len = len; + break; + case ATTR_MODEL_NUMBER: + attr->model_number = pos; + attr->model_number_len = len; + break; + case ATTR_SERIAL_NUMBER: + attr->serial_number = pos; + attr->serial_number_len = len; + break; + case ATTR_DEV_NAME: + attr->dev_name = pos; + attr->dev_name_len = len; + break; + case ATTR_PUBLIC_KEY: + attr->public_key = pos; + attr->public_key_len = len; + break; + case ATTR_ENCR_SETTINGS: + attr->encr_settings = pos; + attr->encr_settings_len = len; + break; + case ATTR_CRED: + if (attr->num_cred >= MAX_CRED_COUNT) { + wpa_printf(MSG_DEBUG, "WPS: Skipped Credential " + "attribute (max %d credentials)", + MAX_CRED_COUNT); + break; + } + attr->cred[attr->num_cred] = pos; + attr->cred_len[attr->num_cred] = len; + attr->num_cred++; + break; + case ATTR_SSID: + attr->ssid = pos; + attr->ssid_len = len; + break; + case ATTR_NETWORK_KEY: + attr->network_key = pos; + attr->network_key_len = len; + break; + case ATTR_EAP_TYPE: + attr->eap_type = pos; + attr->eap_type_len = len; + break; + case ATTR_EAP_IDENTITY: + attr->eap_identity = pos; + attr->eap_identity_len = len; + break; + case ATTR_AP_SETUP_LOCKED: + if (len != 1) { + wpa_printf(MSG_DEBUG, "WPS: Invalid AP Setup Locked " + "length %u", len); + return -1; + } + attr->ap_setup_locked = pos; + break; + case ATTR_REQUESTED_DEV_TYPE: + if (len != WPS_DEV_TYPE_LEN) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Requested Device " + "Type length %u", len); + return -1; + } + if (attr->num_req_dev_type >= MAX_REQ_DEV_TYPE_COUNT) { + wpa_printf(MSG_DEBUG, "WPS: Skipped Requested Device " + "Type attribute (max %u types)", + MAX_REQ_DEV_TYPE_COUNT); + break; + } + attr->req_dev_type[attr->num_req_dev_type] = pos; + attr->num_req_dev_type++; + break; + case ATTR_SECONDARY_DEV_TYPE_LIST: + if (len > WPS_SEC_DEV_TYPE_MAX_LEN || + (len % WPS_DEV_TYPE_LEN) > 0) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Secondary Device " + "Type length %u", len); + return -1; + } + attr->sec_dev_type_list = pos; + attr->sec_dev_type_list_len = len; + break; + case ATTR_VENDOR_EXT: + if (wps_parse_vendor_ext(attr, pos, len) < 0) + return -1; + break; + case ATTR_AP_CHANNEL: + if (len != 2) { + wpa_printf(MSG_DEBUG, "WPS: Invalid AP Channel " + "length %u", len); + return -1; + } + attr->ap_channel = pos; + break; + default: + wpa_printf(MSG_DEBUG, "WPS: Unsupported attribute type 0x%x " + "len=%u", type, len); + break; + } + + return 0; +} + + +int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr) +{ + const u8 *pos, *end; + u16 type, len; +#ifdef WPS_WORKAROUNDS + u16 prev_type = 0; +#endif /* WPS_WORKAROUNDS */ + + os_memset(attr, 0, sizeof(*attr)); + pos = wpabuf_head(msg); + end = pos + wpabuf_len(msg); + + while (pos < end) { + if (end - pos < 4) { + wpa_printf(MSG_DEBUG, "WPS: Invalid message - " + "%lu bytes remaining", + (unsigned long) (end - pos)); + return -1; + } + + type = WPA_GET_BE16(pos); + pos += 2; + len = WPA_GET_BE16(pos); + pos += 2; + wpa_printf(MSG_DEBUG, "WPS: attr type=0x%x len=%u", + type, len); + if (len > end - pos) { + wpa_printf(MSG_DEBUG, "WPS: Attribute overflow"); + wpa_hexdump_buf(MSG_MSGDUMP, "WPS: Message data", msg); +#ifdef WPS_WORKAROUNDS + /* + * Some deployed APs seem to have a bug in encoding of + * Network Key attribute in the Credential attribute + * where they add an extra octet after the Network Key + * attribute at least when open network is being + * provisioned. + */ + if ((type & 0xff00) != 0x1000 && + prev_type == ATTR_NETWORK_KEY) { + wpa_printf(MSG_DEBUG, "WPS: Workaround - try " + "to skip unexpected octet after " + "Network Key"); + pos -= 3; + continue; + } +#endif /* WPS_WORKAROUNDS */ + return -1; + } + +#ifdef WPS_WORKAROUNDS + if (type == 0 && len == 0) { + /* + * Mac OS X 10.6 seems to be adding 0x00 padding to the + * end of M1. Skip those to avoid interop issues. + */ + int i; + for (i = 0; i < end - pos; i++) { + if (pos[i]) + break; + } + if (i == end - pos) { + wpa_printf(MSG_DEBUG, "WPS: Workaround - skip " + "unexpected message padding"); + break; + } + } +#endif /* WPS_WORKAROUNDS */ + + if (wps_set_attr(attr, type, pos, len) < 0) + return -1; + +#ifdef WPS_WORKAROUNDS + prev_type = type; +#endif /* WPS_WORKAROUNDS */ + pos += len; + } + + return 0; +} \ No newline at end of file diff --git a/components/wpa_supplicant/src/wps/wps_attr_process.c b/components/wpa_supplicant/src/wps/wps_attr_process.c new file mode 100644 index 0000000000..cd2c6d4b40 --- /dev/null +++ b/components/wpa_supplicant/src/wps/wps_attr_process.c @@ -0,0 +1,351 @@ +/* + * Wi-Fi Protected Setup - attribute processing + * Copyright (c) 2008, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "crypto/sha256.h" +#include "wps/wps_i.h" + + +int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator, + const struct wpabuf *msg) +{ + u8 hash[SHA256_MAC_LEN]; + const u8 *addr[2]; + size_t len[2]; + + if (authenticator == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Authenticator attribute " + "included"); + return -1; + } + + if (wps->last_msg == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Last message not available for " + "validating authenticator"); + return -1; + } + + /* Authenticator = HMAC-SHA256_AuthKey(M_prev || M_curr*) + * (M_curr* is M_curr without the Authenticator attribute) + */ + addr[0] = wpabuf_head(wps->last_msg); + len[0] = wpabuf_len(wps->last_msg); + addr[1] = wpabuf_head(msg); + len[1] = wpabuf_len(msg) - 4 - WPS_AUTHENTICATOR_LEN; + if (wps_crypto_funcs.hmac_sha256_vector) { + wps_crypto_funcs.hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 2, addr, (int *)len, hash); + } else { + wpa_printf(MSG_ERROR, "Fail to register hmac_sha256_vector function!\r\n"); + return -1; + } + if (os_memcmp(hash, authenticator, WPS_AUTHENTICATOR_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: Incorrect Authenticator"); + return -1; + } + + return 0; +} + + +int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg, + const u8 *key_wrap_auth) +{ + u8 hash[SHA256_MAC_LEN]; + const u8 *head; + size_t len; + + if (key_wrap_auth == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No KWA in decrypted attribute"); + return -1; + } + + head = wpabuf_head(msg); + len = wpabuf_len(msg) - 4 - WPS_KWA_LEN; + if (head + len != key_wrap_auth - 4) { + wpa_printf(MSG_DEBUG, "WPS: KWA not in the end of the " + "decrypted attribute"); + return -1; + } + + if (wps_crypto_funcs.hmac_sha256) { + wps_crypto_funcs.hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, head, len, hash); + } else { + wpa_printf(MSG_ERROR, "Fail to register hmac sha256 function!\r\n"); + return -1; + } + if (os_memcmp(hash, key_wrap_auth, WPS_KWA_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: Invalid KWA"); + return -1; + } + + return 0; +} + + +static int wps_process_cred_network_idx(struct wps_credential *cred, + const u8 *idx) +{ + if (idx == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Credential did not include " + "Network Index"); + return -1; + } + + wpa_printf(MSG_DEBUG, "WPS: Network Index: %d", *idx); + + return 0; +} + + +static int wps_process_cred_ssid(struct wps_credential *cred, const u8 *ssid, + size_t ssid_len) +{ + if (ssid == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Credential did not include SSID"); + return -1; + } + + /* Remove zero-padding since some Registrar implementations seem to use + * hardcoded 32-octet length for this attribute */ + while (ssid_len > 0 && ssid[ssid_len - 1] == 0) + ssid_len--; + + wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", ssid, ssid_len); + if (ssid_len <= sizeof(cred->ssid)) { + os_memcpy(cred->ssid, ssid, ssid_len); + cred->ssid_len = ssid_len; + } + + return 0; +} + + +static int wps_process_cred_auth_type(struct wps_credential *cred, + const u8 *auth_type) +{ + if (auth_type == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Credential did not include " + "Authentication Type"); + return -1; + } + + cred->auth_type = WPA_GET_BE16(auth_type); + wpa_printf(MSG_DEBUG, "WPS: Authentication Type: 0x%x", + cred->auth_type); + + return 0; +} + + +static int wps_process_cred_encr_type(struct wps_credential *cred, + const u8 *encr_type) +{ + if (encr_type == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Credential did not include " + "Encryption Type"); + return -1; + } + + cred->encr_type = WPA_GET_BE16(encr_type); + wpa_printf(MSG_DEBUG, "WPS: Encryption Type: 0x%x", + cred->encr_type); + + return 0; +} + + +static int wps_process_cred_network_key_idx(struct wps_credential *cred, + const u8 *key_idx) +{ + if (key_idx == NULL) + return 0; /* optional attribute */ + + wpa_printf(MSG_DEBUG, "WPS: Network Key Index: %d", *key_idx); + cred->key_idx = *key_idx; + + return 0; +} + + +static int wps_process_cred_network_key(struct wps_credential *cred, + const u8 *key, size_t key_len) +{ + if (key == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Credential did not include " + "Network Key"); + if (cred->auth_type == WPS_WIFI_AUTH_OPEN && + cred->encr_type == WPS_ENCR_NONE) { + wpa_printf(MSG_DEBUG, "WPS: Workaround - Allow " + "missing mandatory Network Key attribute " + "for open network"); + return 0; + } + return -1; + } + + wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", key, key_len); + if (key_len <= sizeof(cred->key)) { + os_memcpy(cred->key, key, key_len); + cred->key_len = key_len; + } + + return 0; +} + + +static int wps_process_cred_mac_addr(struct wps_credential *cred, + const u8 *mac_addr) +{ + if (mac_addr == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Credential did not include " + "MAC Address"); + return -1; + } + + wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, MAC2STR(mac_addr)); + os_memcpy(cred->mac_addr, mac_addr, ETH_ALEN); + + return 0; +} + + +static int wps_process_cred_eap_type(struct wps_credential *cred, + const u8 *eap_type, size_t eap_type_len) +{ + if (eap_type == NULL) + return 0; /* optional attribute */ + + wpa_hexdump(MSG_DEBUG, "WPS: EAP Type", eap_type, eap_type_len); + + return 0; +} + + +static int wps_process_cred_eap_identity(struct wps_credential *cred, + const u8 *identity, + size_t identity_len) +{ + if (identity == NULL) + return 0; /* optional attribute */ + + wpa_hexdump_ascii(MSG_DEBUG, "WPS: EAP Identity", + identity, identity_len); + + return 0; +} + + +static int wps_process_cred_key_prov_auto(struct wps_credential *cred, + const u8 *key_prov_auto) +{ + if (key_prov_auto == NULL) + return 0; /* optional attribute */ + + wpa_printf(MSG_DEBUG, "WPS: Key Provided Automatically: %d", + *key_prov_auto); + + return 0; +} + + +static int wps_process_cred_802_1x_enabled(struct wps_credential *cred, + const u8 *dot1x_enabled) +{ + if (dot1x_enabled == NULL) + return 0; /* optional attribute */ + + wpa_printf(MSG_DEBUG, "WPS: 802.1X Enabled: %d", *dot1x_enabled); + + return 0; +} + + +static int wps_process_cred_ap_channel(struct wps_credential *cred, + const u8 *ap_channel) +{ + if (ap_channel == NULL) + return 0; /* optional attribute */ + + cred->ap_channel = WPA_GET_BE16(ap_channel); + wpa_printf(MSG_DEBUG, "WPS: AP Channel: %u", cred->ap_channel); + + return 0; +} + + +static int wps_workaround_cred_key(struct wps_credential *cred) +{ + if (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK) && + cred->key_len > 8 && cred->key_len < 64 && + cred->key[cred->key_len - 1] == 0) { +#ifdef CONFIG_WPS_STRICT + wpa_printf(MSG_INFO, "WPS: WPA/WPA2-Personal passphrase uses " + "forbidden NULL termination"); + wpa_hexdump_ascii_key(MSG_INFO, "WPS: Network Key", + cred->key, cred->key_len); + return -1; +#else /* CONFIG_WPS_STRICT */ + /* + * A deployed external registrar is known to encode ASCII + * passphrases incorrectly. Remove the extra NULL termination + * to fix the encoding. + */ + wpa_printf(MSG_DEBUG, "WPS: Workaround - remove NULL " + "termination from ASCII passphrase"); + cred->key_len--; +#endif /* CONFIG_WPS_STRICT */ + } + return 0; +} + + +int wps_process_cred(struct wps_parse_attr *attr, + struct wps_credential *cred) +{ + wpa_printf(MSG_DEBUG, "WPS: Process Credential"); + + /* TODO: support multiple Network Keys */ + if (wps_process_cred_network_idx(cred, attr->network_idx) || + wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) || + wps_process_cred_auth_type(cred, attr->auth_type) || + wps_process_cred_encr_type(cred, attr->encr_type) || + wps_process_cred_network_key_idx(cred, attr->network_key_idx) || + wps_process_cred_network_key(cred, attr->network_key, + attr->network_key_len) || + wps_process_cred_mac_addr(cred, attr->mac_addr) || + wps_process_cred_eap_type(cred, attr->eap_type, + attr->eap_type_len) || + wps_process_cred_eap_identity(cred, attr->eap_identity, + attr->eap_identity_len) || + wps_process_cred_key_prov_auto(cred, attr->key_prov_auto) || + wps_process_cred_802_1x_enabled(cred, attr->dot1x_enabled) || + wps_process_cred_ap_channel(cred, attr->ap_channel)) + return -1; + + return wps_workaround_cred_key(cred); +} + + +int wps_process_ap_settings(struct wps_parse_attr *attr, + struct wps_credential *cred) +{ + wpa_printf(MSG_DEBUG, "WPS: Processing AP Settings"); + os_memset(cred, 0, sizeof(*cred)); + /* TODO: optional attributes New Password and Device Password ID */ + if (wps_process_cred_ssid(cred, attr->ssid, attr->ssid_len) || + wps_process_cred_auth_type(cred, attr->auth_type) || + wps_process_cred_encr_type(cred, attr->encr_type) || + wps_process_cred_network_key_idx(cred, attr->network_key_idx) || + wps_process_cred_network_key(cred, attr->network_key, + attr->network_key_len) || + wps_process_cred_mac_addr(cred, attr->mac_addr)) + return -1; + + return wps_workaround_cred_key(cred); +} \ No newline at end of file diff --git a/components/wpa_supplicant/src/wps/wps_common.c b/components/wpa_supplicant/src/wps/wps_common.c new file mode 100644 index 0000000000..8a462a4983 --- /dev/null +++ b/components/wpa_supplicant/src/wps/wps_common.c @@ -0,0 +1,671 @@ +/* + * Wi-Fi Protected Setup - common functionality + * Copyright (c) 2008-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include + +#include "wpa/includes.h" +#include "wpa/common.h" + +#include "crypto/aes_wrap.h" +#include "crypto/crypto.h" +#include "crypto/dh_group5.h" +#include "crypto/sha1.h" +#include "crypto/sha256.h" +#include "crypto/random.h" + +#include "wps/wps_i.h" + +void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, + const char *label, u8 *res, size_t res_len) +{ + u8 i_buf[4], key_bits[4]; + const u8 *addr[4]; + size_t len[4]; + int i, iter; + u8 hash[SHA256_MAC_LEN], *opos; + size_t left; + + WPA_PUT_BE32(key_bits, res_len * 8); + + addr[0] = i_buf; + len[0] = sizeof(i_buf); + addr[1] = label_prefix; + len[1] = label_prefix_len; + addr[2] = (const u8 *) label; + len[2] = os_strlen(label); + addr[3] = key_bits; + len[3] = sizeof(key_bits); + + iter = (res_len + SHA256_MAC_LEN - 1) / SHA256_MAC_LEN; + opos = res; + left = res_len; + + for (i = 1; i <= iter; i++) { + WPA_PUT_BE32(i_buf, i); + if (wps_crypto_funcs.hmac_sha256_vector) { + wps_crypto_funcs.hmac_sha256_vector(key, SHA256_MAC_LEN, 4, addr, (int *)len, hash); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to reigster hmac sha256 vector function!\r\n", __FUNCTION__); + return ; + } + if (i < iter) { + os_memcpy(opos, hash, SHA256_MAC_LEN); + opos += SHA256_MAC_LEN; + left -= SHA256_MAC_LEN; + } else + os_memcpy(opos, hash, left); + } +} + + +int wps_derive_keys(struct wps_data *wps) +{ + struct wpabuf *pubkey, *dh_shared; + u8 dhkey[SHA256_MAC_LEN], kdk[SHA256_MAC_LEN]; + const u8 *addr[3]; + size_t len[3]; + u8 keys[WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN + WPS_EMSK_LEN]; + + if (wps->dh_privkey == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Own DH private key not available"); + return -1; + } + + pubkey = wps->registrar ? wps->dh_pubkey_e : wps->dh_pubkey_r; + if (pubkey == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Peer DH public key not available"); + return -1; + } + + wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH Private Key", wps->dh_privkey); + wpa_hexdump_buf(MSG_DEBUG, "WPS: DH peer Public Key", pubkey); + dh_shared = dh5_derive_shared(wps->dh_ctx, pubkey, wps->dh_privkey); + dh5_free(wps->dh_ctx); + wps->dh_ctx = NULL; + dh_shared = wpabuf_zeropad(dh_shared, 192); + if (dh_shared == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Failed to derive DH shared key"); + return -1; + } + + /* Own DH private key is not needed anymore */ +/* + * due to the public key calculated when wps start, it will not calculate anymore even when we build M1 message, also calculate the key need take a long time + * which would cause WPS fail, so we clean the key after WPS finished . + */ +#ifndef ESP32_WORKAROUND + wpabuf_free(wps->dh_privkey); + wps->dh_privkey = NULL; +#endif //ESP32_WORKAROUND + + wpa_hexdump_buf_key(MSG_DEBUG, "WPS: DH shared key", dh_shared); + + /* DHKey = SHA-256(g^AB mod p) */ + addr[0] = wpabuf_head(dh_shared); + len[0] = wpabuf_len(dh_shared); + + if (wps_crypto_funcs.sha256_vector) { + wps_crypto_funcs.sha256_vector(1, addr, (int *)len, dhkey); + } else { + wpa_printf(MSG_ERROR, "In function %s, Fail to register sha256 vector function!\r\n", __FUNCTION__); + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "WPS: DHKey", dhkey, sizeof(dhkey)); + wpabuf_free(dh_shared); + + /* KDK = HMAC-SHA-256_DHKey(N1 || EnrolleeMAC || N2) */ + addr[0] = wps->nonce_e; + len[0] = WPS_NONCE_LEN; + addr[1] = wps->mac_addr_e; + len[1] = ETH_ALEN; + addr[2] = wps->nonce_r; + len[2] = WPS_NONCE_LEN; + if (wps_crypto_funcs.hmac_sha256_vector) { + wps_crypto_funcs.hmac_sha256_vector(dhkey, sizeof(dhkey), 3, addr, (int *)len, kdk); + } else { + wpa_printf(MSG_ERROR, "In function %s, Fail to register hmac sha256 vector function!\r\n", __FUNCTION__); + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "WPS: KDK", kdk, sizeof(kdk)); + + wps_kdf(kdk, NULL, 0, "Wi-Fi Easy and Secure Key Derivation", + keys, sizeof(keys)); + os_memcpy(wps->authkey, keys, WPS_AUTHKEY_LEN); + os_memcpy(wps->keywrapkey, keys + WPS_AUTHKEY_LEN, WPS_KEYWRAPKEY_LEN); + os_memcpy(wps->emsk, keys + WPS_AUTHKEY_LEN + WPS_KEYWRAPKEY_LEN, + WPS_EMSK_LEN); + + wpa_hexdump_key(MSG_DEBUG, "WPS: AuthKey", + wps->authkey, WPS_AUTHKEY_LEN); + wpa_hexdump_key(MSG_DEBUG, "WPS: KeyWrapKey", + wps->keywrapkey, WPS_KEYWRAPKEY_LEN); + wpa_hexdump_key(MSG_DEBUG, "WPS: EMSK", wps->emsk, WPS_EMSK_LEN); + + return 0; +} + + +void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, + size_t dev_passwd_len) +{ + u8 hash[SHA256_MAC_LEN]; + + if (wps_crypto_funcs.hmac_sha256) { + wps_crypto_funcs.hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, dev_passwd, + (dev_passwd_len + 1) / 2, hash); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register hmac_sha256 function!\r\n", __FUNCTION__); + return ; + } + os_memcpy(wps->psk1, hash, WPS_PSK_LEN); + if (wps_crypto_funcs.hmac_sha256) { + wps_crypto_funcs.hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, + dev_passwd + (dev_passwd_len + 1) / 2, + dev_passwd_len / 2, hash); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register hmac_sha256 function!\r\n", __FUNCTION__); + return ; + } + os_memcpy(wps->psk2, hash, WPS_PSK_LEN); + + wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Device Password", + dev_passwd, dev_passwd_len); + wpa_hexdump_key(MSG_DEBUG, "WPS: PSK1", wps->psk1, WPS_PSK_LEN); + wpa_hexdump_key(MSG_DEBUG, "WPS: PSK2", wps->psk2, WPS_PSK_LEN); +} + + +struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, + size_t encr_len) +{ + struct wpabuf *decrypted; + const size_t block_size = 16; + size_t i; + u8 pad; + const u8 *pos; + + /* AES-128-CBC */ + if (encr == NULL || encr_len < 2 * block_size || encr_len % block_size) + { + wpa_printf(MSG_DEBUG, "WPS: No Encrypted Settings received"); + return NULL; + } + + decrypted = wpabuf_alloc(encr_len - block_size); + if (decrypted == NULL) + return NULL; + + wpa_hexdump(MSG_MSGDUMP, "WPS: Encrypted Settings", encr, encr_len); + wpabuf_put_data(decrypted, encr + block_size, encr_len - block_size); + wpa_printf(MSG_DEBUG, "WPS: AES Decrypt setting"); + if (wps_crypto_funcs.aes_128_decrypt) { + if (wps_crypto_funcs.aes_128_decrypt(wps->keywrapkey, encr, wpabuf_mhead(decrypted), + wpabuf_len(decrypted))) { + wpabuf_free(decrypted); + return NULL; + } + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register aes 128 decrypt function!\r\n", __FUNCTION__); + return NULL; + } + + wpa_hexdump_buf_key(MSG_MSGDUMP, "WPS: Decrypted Encrypted Settings", + decrypted); + + pos = wpabuf_head_u8(decrypted) + wpabuf_len(decrypted) - 1; + pad = *pos; + if (pad > wpabuf_len(decrypted)) { + wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad value"); + wpabuf_free(decrypted); + return NULL; + } + for (i = 0; i < pad; i++) { + if (*pos-- != pad) { + wpa_printf(MSG_DEBUG, "WPS: Invalid PKCS#5 v2.0 pad " + "string"); + wpabuf_free(decrypted); + return NULL; + } + } + decrypted->used -= pad; + + return decrypted; +} + +#ifdef CONFIG_WPS_PIN +/** + * wps_pin_checksum - Compute PIN checksum + * @pin: Seven digit PIN (i.e., eight digit PIN without the checksum digit) + * Returns: Checksum digit + */ +unsigned int wps_pin_checksum(unsigned int pin) +{ + unsigned int accum = 0; + while (pin) { + accum += 3 * (pin % 10); + pin /= 10; + accum += pin % 10; + pin /= 10; + } + + return (10 - accum % 10) % 10; +} + + +/** + * wps_pin_valid - Check whether a PIN has a valid checksum + * @pin: Eight digit PIN (i.e., including the checksum digit) + * Returns: 1 if checksum digit is valid, or 0 if not + */ +unsigned int wps_pin_valid(unsigned int pin) +{ + return wps_pin_checksum(pin / 10) == (pin % 10); +} + + +/** + * wps_generate_pin - Generate a random PIN + * Returns: Eight digit PIN (i.e., including the checksum digit) + */ +unsigned int wps_generate_pin(void) +{ + unsigned int val; + + /* Generate seven random digits for the PIN */ + if (random_get_bytes((unsigned char *) &val, sizeof(val)) < 0) { + return -1; + } + val %= 10000000; + + /* Append checksum digit */ + return val * 10 + wps_pin_checksum(val); +} + + +int wps_pin_str_valid(const char *pin) +{ + const char *p; + size_t len; + + p = pin; + while (*p >= '0' && *p <= '9') + p++; + if (*p != '\0') + return 0; + + len = p - pin; + return len == 4 || len == 8; +} +#endif + +void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg, + u16 config_error, u16 error_indication) +{ + union wps_event_data *data; + + data = (union wps_event_data *)os_zalloc(sizeof(union wps_event_data)); + if (data == NULL) + return; + + if (wps->event_cb == NULL) { + os_free(data); + return; + } + + os_memset(data, 0, sizeof(union wps_event_data)); + data->fail.msg = msg; + data->fail.config_error = config_error; + data->fail.error_indication = error_indication; + wps->event_cb(wps->cb_ctx, WPS_EV_FAIL, data); + os_free(data); +} + + +void wps_success_event(struct wps_context *wps) +{ + if (wps->event_cb == NULL) + return; + + wps->event_cb(wps->cb_ctx, WPS_EV_SUCCESS, NULL); +} + + +void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part) +{ + union wps_event_data *data; + + data = (union wps_event_data *)os_zalloc(sizeof(union wps_event_data)); + if (data == NULL) + return; + + if (wps->event_cb == NULL) { + os_free(data); + return; + } + + os_memset(data, 0, sizeof(union wps_event_data)); + data->pwd_auth_fail.enrollee = enrollee; + data->pwd_auth_fail.part = part; + wps->event_cb(wps->cb_ctx, WPS_EV_PWD_AUTH_FAIL, data); + os_free(data); +} + + +void wps_pbc_overlap_event(struct wps_context *wps) +{ + if (wps->event_cb == NULL) + return; + + wps->event_cb(wps->cb_ctx, WPS_EV_PBC_OVERLAP, NULL); +} + + +void wps_pbc_timeout_event(struct wps_context *wps) +{ + if (wps->event_cb == NULL) + return; + + wps->event_cb(wps->cb_ctx, WPS_EV_PBC_TIMEOUT, NULL); +} + + +#ifdef CONFIG_WPS_OOB + +struct wpabuf * wps_get_oob_cred(struct wps_context *wps) +{ + struct wps_data *data; + struct wpabuf *plain; + + data = (struct wps_data *)os_zalloc(sizeof(struct wps_data)); + if (data == NULL) + return NULL; + + plain = wpabuf_alloc(500); + if (plain == NULL) { + os_free(data); + wpa_printf(MSG_ERROR, "WPS: Failed to allocate memory for OOB " + "credential"); + return NULL; + } + + os_memset(data, 0, sizeof(struct wps_data)); + data->wps = wps; + data->auth_type = wps->auth_types; + data->encr_type = wps->encr_types; + if (wps_build_version(plain) || + wps_build_cred(data, plain) || + wps_build_wfa_ext(plain, 0, NULL, 0)) { + wpabuf_free(plain); + os_free(data); + return NULL; + } + + os_free(data); + return plain; +} + +#ifdef CONFIG_WPS_NFC + +struct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id, + const struct wpabuf *pubkey, + const struct wpabuf *dev_pw) +{ + struct wpabuf *data; + + data = wpabuf_alloc(200); + if (data == NULL) + return NULL; + + if (wps_build_version(data) || + wps_build_oob_dev_pw(data, dev_pw_id, pubkey, + wpabuf_head(dev_pw), wpabuf_len(dev_pw)) || + wps_build_wfa_ext(data, 0, NULL, 0)) { + wpa_printf(MSG_ERROR, "WPS: Failed to build NFC password " + "token"); + wpabuf_free(data); + return NULL; + } + + return data; +} + +#endif + +int wps_oob_use_cred(struct wps_context *wps, struct wps_parse_attr *attr) +{ + struct wpabuf msg; + size_t i; + + for (i = 0; i < attr->num_cred; i++) { + struct wps_credential local_cred; + struct wps_parse_attr cattr; + + os_memset(&local_cred, 0, sizeof(local_cred)); + wpabuf_set(&msg, attr->cred[i], attr->cred_len[i]); + if (wps_parse_msg(&msg, &cattr) < 0 || + wps_process_cred(&cattr, &local_cred)) { + wpa_printf(MSG_ERROR, "WPS: Failed to parse OOB " + "credential"); + return -1; + } + wps->cred_cb(wps->cb_ctx, &local_cred); + } + + return 0; +} + + +#endif /* CONFIG_WPS_OOB */ + + +int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]) +{ + const char *pos; + + /* -- */ + WPA_PUT_BE16(dev_type, atoi(str)); + pos = (char *)os_strchr(str, '-'); + if (pos == NULL) + return -1; + pos++; + if (hexstr2bin(pos, &dev_type[2], 4)) + return -1; + pos = (char *)os_strchr(pos, '-'); + if (pos == NULL) + return -1; + pos++; + WPA_PUT_BE16(&dev_type[6], atoi(pos)); + + + return 0; +} + + +char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf, + size_t buf_len) +{ + int ret; + + ret = snprintf(buf, buf_len, "%u-%08X-%u", + WPA_GET_BE16(dev_type), WPA_GET_BE32(&dev_type[2]), + WPA_GET_BE16(&dev_type[6])); + if (ret < 0 || (unsigned int) ret >= buf_len) + return NULL; + + return buf; +} + + +void uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid) +{ + const u8 *addr[2]; + size_t len[2]; + u8 hash[SHA1_MAC_LEN]; + u8 nsid[16] = { + 0x52, 0x64, 0x80, 0xf8, + 0xc9, 0x9b, + 0x4b, 0xe5, + 0xa6, 0x55, + 0x58, 0xed, 0x5f, 0x5d, 0x60, 0x84 + }; + + addr[0] = nsid; + len[0] = sizeof(nsid); + addr[1] = mac_addr; + len[1] = 6; + sha1_vector(2, addr, len, hash); + os_memcpy(uuid, hash, 16); + + /* Version: 5 = named-based version using SHA-1 */ + uuid[6] = (5 << 4) | (uuid[6] & 0x0f); + + /* Variant specified in RFC 4122 */ + uuid[8] = 0x80 | (uuid[8] & 0x3f); +} + + +u16 wps_config_methods_str2bin(const char *str) +{ + u16 methods = 0; + + if (str == NULL) { + /* Default to enabling methods based on build configuration */ + methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD; +#ifdef CONFIG_WPS2 + methods |= WPS_CONFIG_VIRT_DISPLAY; +#endif /* CONFIG_WPS2 */ +#ifdef CONFIG_WPS_NFC + methods |= WPS_CONFIG_NFC_INTERFACE; +#endif /* CONFIG_WPS_NFC */ + } else { + if (os_strstr(str, "ethernet")) + methods |= WPS_CONFIG_ETHERNET; + if (os_strstr(str, "label")) + methods |= WPS_CONFIG_LABEL; + if (os_strstr(str, "display")) + methods |= WPS_CONFIG_DISPLAY; + if (os_strstr(str, "ext_nfc_token")) + methods |= WPS_CONFIG_EXT_NFC_TOKEN; + if (os_strstr(str, "int_nfc_token")) + methods |= WPS_CONFIG_INT_NFC_TOKEN; + if (os_strstr(str, "nfc_interface")) + methods |= WPS_CONFIG_NFC_INTERFACE; + if (os_strstr(str, "push_button")) + methods |= WPS_CONFIG_PUSHBUTTON; + if (os_strstr(str, "keypad")) + methods |= WPS_CONFIG_KEYPAD; +#ifdef CONFIG_WPS2 + if (os_strstr(str, "virtual_display")) + methods |= WPS_CONFIG_VIRT_DISPLAY; + if (os_strstr(str, "physical_display")) + methods |= WPS_CONFIG_PHY_DISPLAY; + if (os_strstr(str, "virtual_push_button")) + methods |= WPS_CONFIG_VIRT_PUSHBUTTON; + if (os_strstr(str, "physical_push_button")) + methods |= WPS_CONFIG_PHY_PUSHBUTTON; +#endif /* CONFIG_WPS2 */ + } + + return methods; +} + + +struct wpabuf * wps_build_wsc_ack(struct wps_data *wps) +{ + struct wpabuf *msg; + + wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_ACK"); + + msg = wpabuf_alloc(1000); + if (msg == NULL) + return NULL; + + if (wps_build_version(msg) || + wps_build_msg_type(msg, WPS_WSC_ACK) || + wps_build_enrollee_nonce(wps, msg) || + wps_build_registrar_nonce(wps, msg) || + wps_build_wfa_ext(msg, 0, NULL, 0)) { + wpabuf_free(msg); + return NULL; + } + + return msg; +} + + +struct wpabuf * wps_build_wsc_nack(struct wps_data *wps) +{ + struct wpabuf *msg; + + wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_NACK"); + + msg = wpabuf_alloc(1000); + if (msg == NULL) + return NULL; + + if (wps_build_version(msg) || + wps_build_msg_type(msg, WPS_WSC_NACK) || + wps_build_enrollee_nonce(wps, msg) || + wps_build_registrar_nonce(wps, msg) || + wps_build_config_error(msg, wps->config_error) || + wps_build_wfa_ext(msg, 0, NULL, 0)) { + wpabuf_free(msg); + return NULL; + } + + return msg; +} + + +#ifdef CONFIG_WPS_NFC +struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey, + struct wpabuf **privkey, + struct wpabuf **dev_pw) +{ + struct wpabuf *priv = NULL, *pub = NULL, *pw, *ret; + void *dh_ctx; + u16 val; + + pw = wpabuf_alloc(WPS_OOB_DEVICE_PASSWORD_LEN); + if (pw == NULL) + return NULL; + + if (random_get_bytes(wpabuf_put(pw, WPS_OOB_DEVICE_PASSWORD_LEN), + WPS_OOB_DEVICE_PASSWORD_LEN) || + random_get_bytes((u8 *) &val, sizeof(val))) { + wpabuf_free(pw); + return NULL; + } + + dh_ctx = dh5_init(&priv, &pub); + if (dh_ctx == NULL) { + wpabuf_free(pw); + return NULL; + } + dh5_free(dh_ctx); + + *id = 0x10 + val % 0xfff0; + wpabuf_free(*pubkey); + *pubkey = pub; + wpabuf_free(*privkey); + *privkey = priv; + wpabuf_free(*dev_pw); + *dev_pw = pw; + + ret = wps_build_nfc_pw_token(*id, *pubkey, *dev_pw); + if (ndef && ret) { + struct wpabuf *tmp; + tmp = ndef_build_wifi(ret); + wpabuf_free(ret); + if (tmp == NULL) + return NULL; + ret = tmp; + } + + return ret; +} +#endif /* CONFIG_WPS_NFC */ diff --git a/components/wpa_supplicant/src/wps/wps_dev_attr.c b/components/wpa_supplicant/src/wps/wps_dev_attr.c new file mode 100644 index 0000000000..89a14c98ba --- /dev/null +++ b/components/wpa_supplicant/src/wps/wps_dev_attr.c @@ -0,0 +1,451 @@ +/* + * Wi-Fi Protected Setup - device attributes + * Copyright (c) 2008, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "wpa/includes.h" +#include "wpa/common.h" + +#include "wps/wps_i.h" +#include "wps/wps_dev_attr.h" + +int wps_build_manufacturer(struct wps_device_data *dev, struct wpabuf *msg) +{ + size_t len; + wpa_printf(MSG_DEBUG, "WPS: * Manufacturer"); + wpabuf_put_be16(msg, ATTR_MANUFACTURER); + len = dev->manufacturer ? os_strlen(dev->manufacturer) : 0; +#ifndef CONFIG_WPS_STRICT + if (len == 0) { + /* + * Some deployed WPS implementations fail to parse zero-length + * attributes. As a workaround, send a space character if the + * device attribute string is empty. + */ + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, ' '); + return 0; + } +#endif /* CONFIG_WPS_STRICT */ + wpabuf_put_be16(msg, len); + wpabuf_put_data(msg, dev->manufacturer, len); + return 0; +} + + +int wps_build_model_name(struct wps_device_data *dev, struct wpabuf *msg) +{ + size_t len; + wpa_printf(MSG_DEBUG, "WPS: * Model Name"); + wpabuf_put_be16(msg, ATTR_MODEL_NAME); + len = dev->model_name ? os_strlen(dev->model_name) : 0; +#ifndef CONFIG_WPS_STRICT + if (len == 0) { + /* + * Some deployed WPS implementations fail to parse zero-length + * attributes. As a workaround, send a space character if the + * device attribute string is empty. + */ + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, ' '); + return 0; + } +#endif /* CONFIG_WPS_STRICT */ + wpabuf_put_be16(msg, len); + wpabuf_put_data(msg, dev->model_name, len); + return 0; +} + + +int wps_build_model_number(struct wps_device_data *dev, struct wpabuf *msg) +{ + size_t len; + wpa_printf(MSG_DEBUG, "WPS: * Model Number"); + wpabuf_put_be16(msg, ATTR_MODEL_NUMBER); + len = dev->model_number ? os_strlen(dev->model_number) : 0; +#ifndef CONFIG_WPS_STRICT + if (len == 0) { + /* + * Some deployed WPS implementations fail to parse zero-length + * attributes. As a workaround, send a space character if the + * device attribute string is empty. + */ + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, ' '); + return 0; + } +#endif /* CONFIG_WPS_STRICT */ + wpabuf_put_be16(msg, len); + wpabuf_put_data(msg, dev->model_number, len); + return 0; +} + + +static int wps_build_serial_number(struct wps_device_data *dev, + struct wpabuf *msg) +{ + size_t len; + wpa_printf(MSG_DEBUG, "WPS: * Serial Number"); + wpabuf_put_be16(msg, ATTR_SERIAL_NUMBER); + len = dev->serial_number ? os_strlen(dev->serial_number) : 0; +#ifndef CONFIG_WPS_STRICT + if (len == 0) { + /* + * Some deployed WPS implementations fail to parse zero-length + * attributes. As a workaround, send a space character if the + * device attribute string is empty. + */ + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, ' '); + return 0; + } +#endif /* CONFIG_WPS_STRICT */ + wpabuf_put_be16(msg, len); + wpabuf_put_data(msg, dev->serial_number, len); + return 0; +} + + +int wps_build_primary_dev_type(struct wps_device_data *dev, struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS: * Primary Device Type"); + wpabuf_put_be16(msg, ATTR_PRIMARY_DEV_TYPE); + wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN); + wpabuf_put_data(msg, dev->pri_dev_type, WPS_DEV_TYPE_LEN); + return 0; +} + + +int wps_build_secondary_dev_type(struct wps_device_data *dev, + struct wpabuf *msg) +{ + if (!dev->num_sec_dev_types) + return 0; + + wpa_printf(MSG_DEBUG, "WPS: * Secondary Device Type"); + wpabuf_put_be16(msg, ATTR_SECONDARY_DEV_TYPE_LIST); + wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN * dev->num_sec_dev_types); + wpabuf_put_data(msg, dev->sec_dev_type, + WPS_DEV_TYPE_LEN * dev->num_sec_dev_types); + + return 0; +} + + +int wps_build_req_dev_type(struct wps_device_data *dev, struct wpabuf *msg, + unsigned int num_req_dev_types, + const u8 *req_dev_types) +{ + unsigned int i; + + for (i = 0; i < num_req_dev_types; i++) { + wpa_hexdump(MSG_DEBUG, "WPS: * Requested Device Type", + req_dev_types + i * WPS_DEV_TYPE_LEN, + WPS_DEV_TYPE_LEN); + wpabuf_put_be16(msg, ATTR_REQUESTED_DEV_TYPE); + wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN); + wpabuf_put_data(msg, req_dev_types + i * WPS_DEV_TYPE_LEN, + WPS_DEV_TYPE_LEN); + } + + return 0; +} + + +int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg) +{ + size_t len; + wpa_printf(MSG_DEBUG, "WPS: * Device Name"); + wpabuf_put_be16(msg, ATTR_DEV_NAME); + len = dev->device_name ? os_strlen(dev->device_name) : 0; +#ifndef CONFIG_WPS_STRICT + if (len == 0) { + /* + * Some deployed WPS implementations fail to parse zero-length + * attributes. As a workaround, send a space character if the + * device attribute string is empty. + */ + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, ' '); + return 0; + } +#endif /* CONFIG_WPS_STRICT */ + wpabuf_put_be16(msg, len); + wpabuf_put_data(msg, dev->device_name, len); + return 0; +} + + +int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg) +{ + if (wps_build_manufacturer(dev, msg) || + wps_build_model_name(dev, msg) || + wps_build_model_number(dev, msg) || + wps_build_serial_number(dev, msg) || + wps_build_primary_dev_type(dev, msg) || + wps_build_dev_name(dev, msg)) + return -1; + return 0; +} + + +int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS: * OS Version"); + wpabuf_put_be16(msg, ATTR_OS_VERSION); + wpabuf_put_be16(msg, 4); + wpabuf_put_be32(msg, 0x80000000 | dev->os_version); + return 0; +} + + +int wps_build_vendor_ext_m1(struct wps_device_data *dev, struct wpabuf *msg) +{ + if (dev->vendor_ext_m1 != NULL) { + wpa_hexdump(MSG_DEBUG, "WPS: * Vendor Extension M1", + wpabuf_head_u8(dev->vendor_ext_m1), + wpabuf_len(dev->vendor_ext_m1)); + wpabuf_put_be16(msg, ATTR_VENDOR_EXT); + wpabuf_put_be16(msg, wpabuf_len(dev->vendor_ext_m1)); + wpabuf_put_buf(msg, dev->vendor_ext_m1); + } + return 0; +} + + +int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS: * RF Bands (%x)", dev->rf_bands); + wpabuf_put_be16(msg, ATTR_RF_BANDS); + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, dev->rf_bands); + return 0; +} + + +int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg) +{ + int i; + + for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) { + if (dev->vendor_ext[i] == NULL) + continue; + wpa_hexdump(MSG_DEBUG, "WPS: * Vendor Extension", + wpabuf_head_u8(dev->vendor_ext[i]), + wpabuf_len(dev->vendor_ext[i])); + wpabuf_put_be16(msg, ATTR_VENDOR_EXT); + wpabuf_put_be16(msg, wpabuf_len(dev->vendor_ext[i])); + wpabuf_put_buf(msg, dev->vendor_ext[i]); + } + + return 0; +} + + +static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str, + size_t str_len) +{ + if (str == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Manufacturer received"); + return -1; + } + + wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", str, str_len); + + os_free(dev->manufacturer); + dev->manufacturer = (char *)os_malloc(str_len + 1); + if (dev->manufacturer == NULL) + return -1; + os_memcpy(dev->manufacturer, str, str_len); + dev->manufacturer[str_len] = '\0'; + + return 0; +} + + +static int wps_process_model_name(struct wps_device_data *dev, const u8 *str, + size_t str_len) +{ + if (str == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Model Name received"); + return -1; + } + + wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", str, str_len); + + os_free(dev->model_name); + dev->model_name = (char *)os_malloc(str_len + 1); + if (dev->model_name == NULL) + return -1; + os_memcpy(dev->model_name, str, str_len); + dev->model_name[str_len] = '\0'; + + return 0; +} + + +static int wps_process_model_number(struct wps_device_data *dev, const u8 *str, + size_t str_len) +{ + if (str == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Model Number received"); + return -1; + } + + wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", str, str_len); + + os_free(dev->model_number); + dev->model_number = (char *)os_malloc(str_len + 1); + if (dev->model_number == NULL) + return -1; + os_memcpy(dev->model_number, str, str_len); + dev->model_number[str_len] = '\0'; + + return 0; +} + + +static int wps_process_serial_number(struct wps_device_data *dev, + const u8 *str, size_t str_len) +{ + if (str == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Serial Number received"); + return -1; + } + + wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", str, str_len); + + os_free(dev->serial_number); + dev->serial_number = (char *)os_malloc(str_len + 1); + if (dev->serial_number == NULL) + return -1; + os_memcpy(dev->serial_number, str, str_len); + dev->serial_number[str_len] = '\0'; + + return 0; +} + + +static int wps_process_dev_name(struct wps_device_data *dev, const u8 *str, + size_t str_len) +{ + if (str == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Device Name received"); + return -1; + } + + wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", str, str_len); + + os_free(dev->device_name); + dev->device_name = (char *)os_malloc(str_len + 1); + if (dev->device_name == NULL) + return -1; + os_memcpy(dev->device_name, str, str_len); + dev->device_name[str_len] = '\0'; + + return 0; +} + + +static int wps_process_primary_dev_type(struct wps_device_data *dev, + const u8 *dev_type) +{ +#if 0 +#ifndef CONFIG_NO_STDOUT_DEBUG + char devtype[WPS_DEV_TYPE_BUFSIZE]; +#endif /* CONFIG_NO_STDOUT_DEBUG */ +#endif + if (dev_type == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Primary Device Type received"); + return -1; + } + + os_memcpy(dev->pri_dev_type, dev_type, WPS_DEV_TYPE_LEN); + //wpa_printf(MSG_DEBUG, "WPS: Primary Device Type: %s", + // wps_dev_type_bin2str(dev->pri_dev_type, devtype, + // sizeof(devtype))); + + return 0; +} + + +int wps_process_device_attrs(struct wps_device_data *dev, + struct wps_parse_attr *attr) +{ + if (wps_process_manufacturer(dev, attr->manufacturer, + attr->manufacturer_len) || + wps_process_model_name(dev, attr->model_name, + attr->model_name_len) || + wps_process_model_number(dev, attr->model_number, + attr->model_number_len) || + wps_process_serial_number(dev, attr->serial_number, + attr->serial_number_len) || + wps_process_primary_dev_type(dev, attr->primary_dev_type) || + wps_process_dev_name(dev, attr->dev_name, attr->dev_name_len)) + return -1; + return 0; +} + + +int wps_process_os_version(struct wps_device_data *dev, const u8 *ver) +{ + if (ver == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No OS Version received"); + return -1; + } + + dev->os_version = WPA_GET_BE32(ver); + wpa_printf(MSG_DEBUG, "WPS: OS Version %08x", dev->os_version); + + return 0; +} + + +int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands) +{ + if (bands == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No RF Bands received"); + return -1; + } + + dev->rf_bands = *bands; + wpa_printf(MSG_DEBUG, "WPS: Enrollee RF Bands 0x%x", dev->rf_bands); + + return 0; +} + + +void wps_device_data_dup(struct wps_device_data *dst, + const struct wps_device_data *src) +{ + if (src->device_name) + dst->device_name = os_strdup(src->device_name); + if (src->manufacturer) + dst->manufacturer = os_strdup(src->manufacturer); + if (src->model_name) + dst->model_name = os_strdup(src->model_name); + if (src->model_number) + dst->model_number = os_strdup(src->model_number); + if (src->serial_number) + dst->serial_number = os_strdup(src->serial_number); + os_memcpy(dst->pri_dev_type, src->pri_dev_type, WPS_DEV_TYPE_LEN); + dst->os_version = src->os_version; + dst->rf_bands = src->rf_bands; +} + + +void wps_device_data_free(struct wps_device_data *dev) +{ + os_free(dev->device_name); + dev->device_name = NULL; + os_free(dev->manufacturer); + dev->manufacturer = NULL; + os_free(dev->model_name); + dev->model_name = NULL; + os_free(dev->model_number); + dev->model_number = NULL; + os_free(dev->serial_number); + dev->serial_number = NULL; +} diff --git a/components/wpa_supplicant/src/wps/wps_enrollee.c b/components/wpa_supplicant/src/wps/wps_enrollee.c new file mode 100644 index 0000000000..6a4f9bdfb9 --- /dev/null +++ b/components/wpa_supplicant/src/wps/wps_enrollee.c @@ -0,0 +1,1574 @@ +/* + * Wi-Fi Protected Setup - Enrollee + * Copyright (c) 2008, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "rom/ets_sys.h" +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "crypto/crypto.h" +#include "crypto/sha256.h" +#include "crypto/random.h" +#include "wps/wps_i.h" +#include "wps/wps.h" +#include "wps/wps_dev_attr.h" + +#include "soc/dport_reg.h" + + +static int wps_build_mac_addr(struct wps_data *wps, struct wpabuf *msg) { + wpa_printf(MSG_DEBUG, "WPS: * MAC Address"); + wpabuf_put_be16(msg, ATTR_MAC_ADDR); + wpabuf_put_be16(msg, ETH_ALEN); + wpabuf_put_data(msg, wps->mac_addr_e, ETH_ALEN); + return 0; +} + + +static int wps_build_wps_state(struct wps_data *wps, struct wpabuf *msg) +{ + u8 state; + if (wps->wps->ap) + state = wps->wps->wps_state; + else + state = WPS_STATE_NOT_CONFIGURED; + wpa_printf(MSG_DEBUG, "WPS: * Wi-Fi Protected Setup State (%d)", + state); + wpabuf_put_be16(msg, ATTR_WPS_STATE); + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, state); + return 0; +} + + +static int wps_build_e_hash(struct wps_data *wps, struct wpabuf *msg) +{ + u8 *hash; + const u8 *addr[4]; + size_t len[4]; + + if (random_get_bytes(wps->snonce, 2 * WPS_SECRET_NONCE_LEN) < 0) + return -1; + wpa_hexdump(MSG_DEBUG, "WPS: E-S1", wps->snonce, WPS_SECRET_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "WPS: E-S2", + wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); + + if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) { + wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for " + "E-Hash derivation"); + return -1; + } + + wpa_printf(MSG_DEBUG, "WPS: * E-Hash1"); + wpabuf_put_be16(msg, ATTR_E_HASH1); + wpabuf_put_be16(msg, SHA256_MAC_LEN); + hash = wpabuf_put(msg, SHA256_MAC_LEN); + /* E-Hash1 = HMAC_AuthKey(E-S1 || PSK1 || PK_E || PK_R) */ + addr[0] = wps->snonce; + len[0] = WPS_SECRET_NONCE_LEN; + addr[1] = wps->psk1; + len[1] = WPS_PSK_LEN; + addr[2] = wpabuf_head(wps->dh_pubkey_e); + len[2] = wpabuf_len(wps->dh_pubkey_e); + addr[3] = wpabuf_head(wps->dh_pubkey_r); + len[3] = wpabuf_len(wps->dh_pubkey_r); + if (wps_crypto_funcs.hmac_sha256_vector) { + wps_crypto_funcs.hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, (int *)len, hash); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register hmac_sha256_vector function!\r\n", __FUNCTION__); + return -1; + } + wpa_hexdump(MSG_DEBUG, "WPS: E-Hash1", hash, SHA256_MAC_LEN); + + wpa_printf(MSG_DEBUG, "WPS: * E-Hash2"); + wpabuf_put_be16(msg, ATTR_E_HASH2); + wpabuf_put_be16(msg, SHA256_MAC_LEN); + hash = wpabuf_put(msg, SHA256_MAC_LEN); + /* E-Hash2 = HMAC_AuthKey(E-S2 || PSK2 || PK_E || PK_R) */ + addr[0] = wps->snonce + WPS_SECRET_NONCE_LEN; + addr[1] = wps->psk2; + if (wps_crypto_funcs.hmac_sha256_vector) { + wps_crypto_funcs.hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, (int *)len, hash); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register hmac_sha256_vector function!\r\n", __FUNCTION__); + return -1; + } + wpa_hexdump(MSG_DEBUG, "WPS: E-Hash2", hash, SHA256_MAC_LEN); + + return 0; +} + + +static int wps_build_e_snonce1(struct wps_data *wps, struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS: * E-SNonce1"); + wpabuf_put_be16(msg, ATTR_E_SNONCE1); + wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); + wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN); + return 0; +} + + +static int wps_build_e_snonce2(struct wps_data *wps, struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS: * E-SNonce2"); + wpabuf_put_be16(msg, ATTR_E_SNONCE2); + wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); + wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN, + WPS_SECRET_NONCE_LEN); + return 0; +} + + +static struct wpabuf * wps_build_m1(struct wps_data *wps) +{ + struct wpabuf *msg; + u16 config_methods; + + if (random_get_bytes(wps->nonce_e, WPS_NONCE_LEN) < 0) + return NULL; + wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce", + wps->nonce_e, WPS_NONCE_LEN); + + wpa_printf(MSG_DEBUG, "WPS: Building Message M1"); + msg = wpabuf_alloc(1000); + if (msg == NULL) + return NULL; + + config_methods = wps->wps->config_methods; + if (wps->wps->ap && !wps->pbc_in_m1 && + (wps->dev_password_len != 0 || + (config_methods & WPS_CONFIG_DISPLAY))) { + /* + * These are the methods that the AP supports as an Enrollee + * for adding external Registrars, so remove PushButton. + * + * As a workaround for Windows 7 mechanism for probing WPS + * capabilities from M1, leave PushButton option if no PIN + * method is available or if WPS configuration enables PBC + * workaround. + */ + config_methods &= ~WPS_CONFIG_PUSHBUTTON; +#ifdef CONFIG_WPS2 + config_methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON | + WPS_CONFIG_PHY_PUSHBUTTON); +#endif /* CONFIG_WPS2 */ + } + + if (wps_build_version(msg) || + wps_build_msg_type(msg, WPS_M1) || + wps_build_uuid_e(msg, wps->uuid_e) || + wps_build_mac_addr(wps, msg) || + wps_build_enrollee_nonce(wps, msg) || + wps_build_public_key(wps, msg, WPS_CALC_KEY_NO_CALC) || + wps_build_auth_type_flags(wps, msg) || + wps_build_encr_type_flags(wps, msg) || + wps_build_conn_type_flags(wps, msg) || + wps_build_config_methods(msg, config_methods) || + wps_build_wps_state(wps, msg) || + wps_build_device_attrs(&wps->wps->dev, msg) || + wps_build_rf_bands(&wps->wps->dev, msg) || + wps_build_assoc_state(wps, msg) || + wps_build_dev_password_id(msg, wps->dev_pw_id) || + wps_build_config_error(msg, WPS_CFG_NO_ERROR) || + wps_build_os_version(&wps->wps->dev, msg) || + wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_vendor_ext_m1(&wps->wps->dev, msg)) { + wpabuf_free(msg); + return NULL; + } + + wps->state = RECV_M2; + return msg; +} + + +static struct wpabuf * wps_build_m3(struct wps_data *wps) +{ + struct wpabuf *msg; + + wpa_printf(MSG_DEBUG, "WPS: Building Message M3"); + + if (wps->dev_password == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Device Password available"); + return NULL; + } + wps_derive_psk(wps, wps->dev_password, wps->dev_password_len); + + msg = wpabuf_alloc(1000); + if (msg == NULL) + return NULL; + + if (wps_build_version(msg) || + wps_build_msg_type(msg, WPS_M3) || + wps_build_registrar_nonce(wps, msg) || + wps_build_e_hash(wps, msg) || + wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_authenticator(wps, msg)) { + wpabuf_free(msg); + return NULL; + } + + wps->state = RECV_M4; + return msg; +} + + +static struct wpabuf * wps_build_m5(struct wps_data *wps) +{ + struct wpabuf *msg, *plain; + + wpa_printf(MSG_DEBUG, "WPS: Building Message M5"); + + plain = wpabuf_alloc(200); + if (plain == NULL) + return NULL; + + msg = wpabuf_alloc(1000); + if (msg == NULL) { + wpabuf_free(plain); + return NULL; + } + + if (wps_build_version(msg) || + wps_build_msg_type(msg, WPS_M5) || + wps_build_registrar_nonce(wps, msg) || + wps_build_e_snonce1(wps, plain) || + wps_build_key_wrap_auth(wps, plain) || + wps_build_encr_settings(wps, msg, plain) || + wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_authenticator(wps, msg)) { + wpabuf_free(plain); + wpabuf_free(msg); + return NULL; + } + wpabuf_free(plain); + + wps->state = RECV_M6; + return msg; +} + + +static int wps_build_cred_ssid(struct wps_data *wps, struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS: * SSID"); + wpabuf_put_be16(msg, ATTR_SSID); + wpabuf_put_be16(msg, wps->wps->ssid_len); + wpabuf_put_data(msg, wps->wps->ssid, wps->wps->ssid_len); + return 0; +} + + +static int wps_build_cred_auth_type(struct wps_data *wps, struct wpabuf *msg) +{ + u16 auth_type = wps->wps->auth_types; + + /* Select the best authentication type */ + if (auth_type & WPS_AUTH_WPA2PSK) + auth_type = WPS_AUTH_WPA2PSK; + else if (auth_type & WPS_AUTH_WPAPSK) + auth_type = WPS_AUTH_WPAPSK; + else if (auth_type & WPS_WIFI_AUTH_OPEN) + auth_type = WPS_WIFI_AUTH_OPEN; + else if (auth_type & WPS_AUTH_SHARED) + auth_type = WPS_AUTH_SHARED; + + wpa_printf(MSG_DEBUG, "WPS: * Authentication Type (0x%x)", auth_type); + wpabuf_put_be16(msg, ATTR_AUTH_TYPE); + wpabuf_put_be16(msg, 2); + wpabuf_put_be16(msg, auth_type); + return 0; +} + + +static int wps_build_cred_encr_type(struct wps_data *wps, struct wpabuf *msg) +{ + u16 encr_type = wps->wps->encr_types; + + /* Select the best encryption type */ + if (wps->wps->auth_types & (WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK)) { + if (encr_type & WPS_ENCR_AES) + encr_type = WPS_ENCR_AES; + else if (encr_type & WPS_ENCR_TKIP) + encr_type = WPS_ENCR_TKIP; + } else { + if (encr_type & WPS_ENCR_WEP) + encr_type = WPS_ENCR_WEP; + else if (encr_type & WPS_ENCR_NONE) + encr_type = WPS_ENCR_NONE; + } + + wpa_printf(MSG_DEBUG, "WPS: * Encryption Type (0x%x)", encr_type); + wpabuf_put_be16(msg, ATTR_ENCR_TYPE); + wpabuf_put_be16(msg, 2); + wpabuf_put_be16(msg, encr_type); + return 0; +} + + +static int wps_build_cred_network_key(struct wps_data *wps, struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS: * Network Key"); + wpabuf_put_be16(msg, ATTR_NETWORK_KEY); + wpabuf_put_be16(msg, wps->wps->network_key_len); + wpabuf_put_data(msg, wps->wps->network_key, wps->wps->network_key_len); + return 0; +} + + +static int wps_build_cred_mac_addr(struct wps_data *wps, struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS: * MAC Address (AP BSSID)"); + wpabuf_put_be16(msg, ATTR_MAC_ADDR); + wpabuf_put_be16(msg, ETH_ALEN); + wpabuf_put_data(msg, wps->wps->dev.mac_addr, ETH_ALEN); + return 0; +} + + +static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *plain) +{ + if (wps->wps->ap_settings) { + wpa_printf(MSG_DEBUG, "WPS: * AP Settings (pre-configured)"); + wpabuf_put_data(plain, wps->wps->ap_settings, + wps->wps->ap_settings_len); + return 0; + } + + return wps_build_cred_ssid(wps, plain) || + wps_build_cred_mac_addr(wps, plain) || + wps_build_cred_auth_type(wps, plain) || + wps_build_cred_encr_type(wps, plain) || + wps_build_cred_network_key(wps, plain); +} + + +static struct wpabuf * wps_build_m7(struct wps_data *wps) +{ + struct wpabuf *msg, *plain; + + wpa_printf(MSG_DEBUG, "WPS: Building Message M7"); + + plain = wpabuf_alloc(500 + wps->wps->ap_settings_len); + if (plain == NULL) + return NULL; + + msg = wpabuf_alloc(1000 + wps->wps->ap_settings_len); + if (msg == NULL) { + wpabuf_free(plain); + return NULL; + } + + if (wps_build_version(msg) || + wps_build_msg_type(msg, WPS_M7) || + wps_build_registrar_nonce(wps, msg) || + wps_build_e_snonce2(wps, plain) || + (wps->wps->ap && wps_build_ap_settings(wps, plain)) || + wps_build_key_wrap_auth(wps, plain) || + wps_build_encr_settings(wps, msg, plain) || + wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_authenticator(wps, msg)) { + wpabuf_free(plain); + wpabuf_free(msg); + return NULL; + } + wpabuf_free(plain); + + if (wps->wps->ap && wps->wps->registrar) { + /* + * If the Registrar is only learning our current configuration, + * it may not continue protocol run to successful completion. + * Store information here to make sure it remains available. + */ + wps_device_store(wps->wps->registrar, &wps->peer_dev, + wps->uuid_r); + } + + wps->state = RECV_M8; + return msg; +} + + +static struct wpabuf * wps_build_wsc_done(struct wps_data *wps) +{ + struct wpabuf *msg; + + wpa_printf(MSG_DEBUG, "WPS: Building Message WSC_Done"); + + msg = wpabuf_alloc(1000); + if (msg == NULL) + return NULL; + + if (wps_build_version(msg) || + wps_build_msg_type(msg, WPS_WSC_DONE) || + wps_build_enrollee_nonce(wps, msg) || + wps_build_registrar_nonce(wps, msg) || + wps_build_wfa_ext(msg, 0, NULL, 0)) { + wpabuf_free(msg); + return NULL; + } + + if (wps->wps->ap) + wps->state = RECV_ACK; + else { + wps_success_event(wps->wps); + wps->state = WPS_FINISHED; + } + return msg; +} + + +struct wpabuf * wps_enrollee_get_msg(struct wps_data *wps, + enum wsc_op_code *op_code) +{ + struct wpabuf *msg; + + switch (wps->state) { + case SEND_M1: + msg = wps_build_m1(wps); + *op_code = WSC_MSG; + break; + case SEND_M3: + msg = wps_build_m3(wps); + *op_code = WSC_MSG; + break; + case SEND_M5: + msg = wps_build_m5(wps); + *op_code = WSC_MSG; + break; + case SEND_M7: + msg = wps_build_m7(wps); + *op_code = WSC_MSG; + break; + case RECEIVED_M2D: + if (wps->wps->ap) { + msg = wps_build_wsc_nack(wps); + *op_code = WSC_NACK; + break; + } + msg = wps_build_wsc_ack(wps); + *op_code = WSC_ACK; + if (msg) { + /* Another M2/M2D may be received */ + wps->state = RECV_M2; + } + break; + case SEND_WSC_NACK: + msg = wps_build_wsc_nack(wps); + *op_code = WSC_NACK; + break; + case WPS_MSG_DONE: + msg = wps_build_wsc_done(wps); + *op_code = WSC_Done; + break; + default: + wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building " + "a message", wps->state); + msg = NULL; + break; + } + + if (*op_code == WSC_MSG && msg) { + /* Save a copy of the last message for Authenticator derivation + */ + wpabuf_free(wps->last_msg); + wps->last_msg = wpabuf_dup(msg); + } + + return msg; +} + + +static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce) +{ + if (r_nonce == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received"); + return -1; + } + + os_memcpy(wps->nonce_r, r_nonce, WPS_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "WPS: Registrar Nonce", + wps->nonce_r, WPS_NONCE_LEN); + + return 0; +} + + +static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce) +{ + if (e_nonce == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received"); + return -1; + } + + if (os_memcmp(wps->nonce_e, e_nonce, WPS_NONCE_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Enrollee Nonce received"); + return -1; + } + + return 0; +} + + +static int wps_process_uuid_r(struct wps_data *wps, const u8 *uuid_r) +{ + if (uuid_r == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No UUID-R received"); + return -1; + } + + os_memcpy(wps->uuid_r, uuid_r, WPS_UUID_LEN); + wpa_hexdump(MSG_DEBUG, "WPS: UUID-R", wps->uuid_r, WPS_UUID_LEN); + + return 0; +} + + +static int wps_process_pubkey(struct wps_data *wps, const u8 *pk, + size_t pk_len) +{ + if (pk == NULL || pk_len == 0) { + wpa_printf(MSG_DEBUG, "WPS: No Public Key received"); + return -1; + } + + wpabuf_free(wps->dh_pubkey_r); + wps->dh_pubkey_r = wpabuf_alloc_copy(pk, pk_len); + if (wps->dh_pubkey_r == NULL) + return -1; + + wpa_printf(MSG_DEBUG, "process pubkey start\n"); + + if (wps_derive_keys(wps) < 0) { + return -1; + } + + wpa_printf(MSG_DEBUG, "process pubkey finish\n"); + + return 0; +} + + +static int wps_process_r_hash1(struct wps_data *wps, const u8 *r_hash1) +{ + if (r_hash1 == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No R-Hash1 received"); + return -1; + } + + os_memcpy(wps->peer_hash1, r_hash1, WPS_HASH_LEN); + wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", wps->peer_hash1, WPS_HASH_LEN); + + return 0; +} + + +static int wps_process_r_hash2(struct wps_data *wps, const u8 *r_hash2) +{ + if (r_hash2 == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No R-Hash2 received"); + return -1; + } + + os_memcpy(wps->peer_hash2, r_hash2, WPS_HASH_LEN); + wpa_hexdump(MSG_DEBUG, "WPS: R-Hash2", wps->peer_hash2, WPS_HASH_LEN); + + return 0; +} + + +static int wps_process_r_snonce1(struct wps_data *wps, const u8 *r_snonce1) +{ + u8 hash[SHA256_MAC_LEN]; + const u8 *addr[4]; + size_t len[4]; + + if (r_snonce1 == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No R-SNonce1 received"); + return -1; + } + + wpa_hexdump_key(MSG_DEBUG, "WPS: R-SNonce1", r_snonce1, + WPS_SECRET_NONCE_LEN); + + /* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */ + addr[0] = r_snonce1; + len[0] = WPS_SECRET_NONCE_LEN; + addr[1] = wps->psk1; + len[1] = WPS_PSK_LEN; + addr[2] = wpabuf_head(wps->dh_pubkey_e); + len[2] = wpabuf_len(wps->dh_pubkey_e); + addr[3] = wpabuf_head(wps->dh_pubkey_r); + len[3] = wpabuf_len(wps->dh_pubkey_r); + + if (wps_crypto_funcs.hmac_sha256_vector) { + wps_crypto_funcs.hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, (int *)len, hash); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register hmac_sha256_vector function!\r\n", __FUNCTION__); + return -1; + } + if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: R-Hash1 derived from R-S1 does " + "not match with the pre-committed value"); + wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; + wps_pwd_auth_fail_event(wps->wps, 1, 1); + return -1; + } + + wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the first " + "half of the device password"); + + return 0; +} + + +static int wps_process_r_snonce2(struct wps_data *wps, const u8 *r_snonce2) +{ + u8 hash[SHA256_MAC_LEN]; + const u8 *addr[4]; + size_t len[4]; + + if (r_snonce2 == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No R-SNonce2 received"); + return -1; + } + + wpa_hexdump_key(MSG_DEBUG, "WPS: R-SNonce2", r_snonce2, + WPS_SECRET_NONCE_LEN); + + /* R-Hash2 = HMAC_AuthKey(R-S2 || PSK2 || PK_E || PK_R) */ + addr[0] = r_snonce2; + len[0] = WPS_SECRET_NONCE_LEN; + addr[1] = wps->psk2; + len[1] = WPS_PSK_LEN; + addr[2] = wpabuf_head(wps->dh_pubkey_e); + len[2] = wpabuf_len(wps->dh_pubkey_e); + addr[3] = wpabuf_head(wps->dh_pubkey_r); + len[3] = wpabuf_len(wps->dh_pubkey_r); + + if (wps_crypto_funcs.hmac_sha256_vector) { + wps_crypto_funcs.hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, (int *)len, hash); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to regiset hmac_sha256_vector function!\r\n", __FUNCTION__); + return -1; + } + + if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: R-Hash2 derived from R-S2 does " + "not match with the pre-committed value"); + wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; + wps_pwd_auth_fail_event(wps->wps, 1, 2); + return -1; + } + + wpa_printf(MSG_DEBUG, "WPS: Registrar proved knowledge of the second " + "half of the device password"); + + return 0; +} + + +static int wps_process_cred_e(struct wps_data *wps, const u8 *cred, + size_t cred_len, int wps2) +{ + struct wps_parse_attr *attr; + struct wpabuf msg; + int ret = 0; + + wpa_printf(MSG_DEBUG, "WPS: Received Credential"); + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) + return -99; + + os_memset(&wps->cred, 0, sizeof(wps->cred)); + wpabuf_set(&msg, cred, cred_len); + if (wps_parse_msg(&msg, attr) < 0 || + wps_process_cred(attr, &wps->cred)) { + ret = -1; + goto _out; + } + + if (os_memcmp(wps->cred.mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) != + 0) { + wpa_printf(MSG_DEBUG, "WPS: MAC Address in the Credential (" + MACSTR ") does not match with own address (" MACSTR + ")", MAC2STR(wps->cred.mac_addr), + MAC2STR(wps->wps->dev.mac_addr)); + /* + * In theory, this could be consider fatal error, but there are + * number of deployed implementations using other address here + * due to unclarity in the specification. For interoperability + * reasons, allow this to be processed since we do not really + * use the MAC Address information for anything. + */ +#ifdef CONFIG_WPS_STRICT + if (wps2) { + wpa_printf(MSG_INFO, "WPS: Do not accept incorrect " + "MAC Address in AP Settings"); + ret = -1; + goto _out; + } +#endif /* CONFIG_WPS_STRICT */ + } + +#ifdef CONFIG_WPS2 + if (!(wps->cred.encr_type & + (WPS_ENCR_NONE | WPS_ENCR_TKIP | WPS_ENCR_AES))) { + if (wps->cred.encr_type & WPS_ENCR_WEP) { + wpa_printf(MSG_INFO, "WPS: Reject Credential " + "due to WEP configuration"); + wps->error_indication = WPS_EI_SECURITY_WEP_PROHIBITED; + ret = -2; + goto _out; + } + + wpa_printf(MSG_INFO, "WPS: Reject Credential due to " + "invalid encr_type 0x%x", wps->cred.encr_type); + ret = -1; + goto _out; + } +#endif /* CONFIG_WPS2 */ + + wps_ssid_save(wps->cred.ssid, wps->cred.ssid_len); + wps_key_save((char *)wps->cred.key, wps->cred.key_len); + + if (wps->wps->cred_cb) { + wps->cred.cred_attr = cred - 4; + wps->cred.cred_attr_len = cred_len + 4; + ret = wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred); + wps->cred.cred_attr = NULL; + wps->cred.cred_attr_len = 0; + } + +_out: + if (attr) + os_free(attr); + + return ret; +} + + +static int wps_process_creds(struct wps_data *wps, const u8 *cred[], + size_t cred_len[], size_t num_cred, int wps2) +{ + size_t i; + int ok = 0; + + if (wps->wps->ap) + return 0; + + if (num_cred == 0) { + wpa_printf(MSG_DEBUG, "WPS: No Credential attributes " + "received"); + return -1; + } + + for (i = 0; i < num_cred; i++) { + int res; + res = wps_process_cred_e(wps, cred[i], cred_len[i], wps2); + if (res == 0) + ok++; + else if (res == -2) { + wpa_printf(MSG_DEBUG, "WPS: WEP credential skipped"); + } + else + return -1; + } + + if (ok == 0) { + wpa_printf(MSG_DEBUG, "WPS: No valid Credential attribute " + "received"); + return -1; + } + + return 0; +} + + +static int wps_process_ap_settings_e(struct wps_data *wps, + struct wps_parse_attr *attr, + struct wpabuf *attrs, int wps2) +{ + struct wps_credential *cred; + int ret = 0; + + cred = (struct wps_credential *)os_zalloc(sizeof(struct wps_credential)); + if (cred == NULL) { + ret = -99; + goto _out; + } + + if (!wps->wps->ap) { + ret = 0; + goto _out; + } + + if (wps_process_ap_settings(attr, cred) < 0) { + ret = -1; + goto _out; + } + + wpa_printf(MSG_INFO, "WPS: Received new AP configuration from " + "Registrar"); + + if (os_memcmp(cred->mac_addr, wps->wps->dev.mac_addr, ETH_ALEN) != + 0) { + wpa_printf(MSG_DEBUG, "WPS: MAC Address in the AP Settings (" + MACSTR ") does not match with own address (" MACSTR + ")", MAC2STR(cred->mac_addr), + MAC2STR(wps->wps->dev.mac_addr)); + /* + * In theory, this could be consider fatal error, but there are + * number of deployed implementations using other address here + * due to unclarity in the specification. For interoperability + * reasons, allow this to be processed since we do not really + * use the MAC Address information for anything. + */ +#ifdef CONFIG_WPS_STRICT + if (wps2) { + wpa_printf(MSG_INFO, "WPS: Do not accept incorrect " + "MAC Address in AP Settings"); + ret = -1; + goto _out; + } +#endif /* CONFIG_WPS_STRICT */ + } + +#ifdef CONFIG_WPS2 + if (!(cred->encr_type & (WPS_ENCR_NONE | WPS_ENCR_TKIP | WPS_ENCR_AES))) + { + if (cred->encr_type & WPS_ENCR_WEP) { + wpa_printf(MSG_INFO, "WPS: Reject new AP settings " + "due to WEP configuration"); + wps->error_indication = WPS_EI_SECURITY_WEP_PROHIBITED; + ret = -1; + goto _out; + } + + wpa_printf(MSG_INFO, "WPS: Reject new AP settings due to " + "invalid encr_type 0x%x", cred->encr_type); + ret = -1; + goto _out; + } +#endif /* CONFIG_WPS2 */ + +#ifdef CONFIG_WPS_STRICT + if (wps2) { + if ((cred->encr_type & (WPS_ENCR_TKIP | WPS_ENCR_AES)) == + WPS_ENCR_TKIP || + (cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) == + WPS_AUTH_WPAPSK) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid WSC 2.0 " + "AP Settings: WPA-Personal/TKIP only"); + wps->error_indication = + WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED; + ret = -1; + goto _out; + } + } +#endif /* CONFIG_WPS_STRICT */ + +#ifdef CONFIG_WPS2 + if ((cred->encr_type & (WPS_ENCR_TKIP | WPS_ENCR_AES)) == WPS_ENCR_TKIP) + { + wpa_printf(MSG_DEBUG, "WPS: Upgrade encr_type TKIP -> " + "TKIP+AES"); + cred->encr_type |= WPS_ENCR_AES; + } + + if ((cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) == + WPS_AUTH_WPAPSK) { + wpa_printf(MSG_DEBUG, "WPS: Upgrade auth_type WPAPSK -> " + "WPAPSK+WPA2PSK"); + cred->auth_type |= WPS_AUTH_WPA2PSK; + } +#endif /* CONFIG_WPS2 */ + + if (wps->wps->cred_cb) { + cred->cred_attr = wpabuf_head(attrs); + cred->cred_attr_len = wpabuf_len(attrs); + wps->wps->cred_cb(wps->wps->cb_ctx, cred); + } + +_out: + if (cred) + os_free(cred); + + return ret; +} + + +static enum wps_process_res wps_process_m2(struct wps_data *wps, + const struct wpabuf *msg, + struct wps_parse_attr *attr) +{ + wpa_printf(MSG_DEBUG, "WPS: Received M2"); + + if (wps->state != RECV_M2) { + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + "receiving M2", wps->state); + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || + wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || + wps_process_uuid_r(wps, attr->uuid_r)) { + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + /* + * Stop here on an AP as an Enrollee if AP Setup is locked unless the + * special locked mode is used to allow protocol run up to M7 in order + * to support external Registrars that only learn the current AP + * configuration without changing it. + */ + if (wps->wps->ap && + ((wps->wps->ap_setup_locked && wps->wps->ap_setup_locked != 2) || + wps->dev_password == NULL)) { + wpa_printf(MSG_DEBUG, "WPS: AP Setup is locked - refuse " + "registration of a new Registrar"); + wps->config_error = WPS_CFG_SETUP_LOCKED; + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + if (wps_process_pubkey(wps, attr->public_key, attr->public_key_len) || + wps_process_authenticator(wps, attr->authenticator, msg) || + wps_process_device_attrs(&wps->peer_dev, attr)) { + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + wps->state = SEND_M3; + return WPS_CONTINUE; +} + + +static enum wps_process_res wps_process_m2d(struct wps_data *wps, + struct wps_parse_attr *attr) +{ + wpa_printf(MSG_DEBUG, "WPS: Received M2D"); + + if (wps->state != RECV_M2) { + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + "receiving M2D", wps->state); + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", + attr->manufacturer, attr->manufacturer_len); + wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", + attr->model_name, attr->model_name_len); + wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", + attr->model_number, attr->model_number_len); + wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", + attr->serial_number, attr->serial_number_len); + wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", + attr->dev_name, attr->dev_name_len); + + if (wps->wps->event_cb) { + union wps_event_data data; + struct wps_event_m2d *m2d = &data.m2d; + os_memset(&data, 0, sizeof(data)); + if (attr->config_methods) + m2d->config_methods = + WPA_GET_BE16(attr->config_methods); + m2d->manufacturer = attr->manufacturer; + m2d->manufacturer_len = attr->manufacturer_len; + m2d->model_name = attr->model_name; + m2d->model_name_len = attr->model_name_len; + m2d->model_number = attr->model_number; + m2d->model_number_len = attr->model_number_len; + m2d->serial_number = attr->serial_number; + m2d->serial_number_len = attr->serial_number_len; + m2d->dev_name = attr->dev_name; + m2d->dev_name_len = attr->dev_name_len; + m2d->primary_dev_type = attr->primary_dev_type; + if (attr->config_error) + m2d->config_error = + WPA_GET_BE16(attr->config_error); + if (attr->dev_password_id) + m2d->dev_password_id = + WPA_GET_BE16(attr->dev_password_id); + wps->wps->event_cb(wps->wps->cb_ctx, WPS_EV_M2D, &data); + } + + wps->state = RECEIVED_M2D; + return WPS_CONTINUE; +} + + +static enum wps_process_res wps_process_m4(struct wps_data *wps, + const struct wpabuf *msg, + struct wps_parse_attr *attr) +{ + struct wpabuf *decrypted; + struct wps_parse_attr *eattr; + enum wps_process_res res; + + wpa_printf(MSG_DEBUG, "WPS: Received M4"); + + eattr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (eattr == NULL) { + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + + if (wps->state != RECV_M4) { + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + "receiving M4", wps->state); + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + + if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || + wps_process_authenticator(wps, attr->authenticator, msg) || + wps_process_r_hash1(wps, attr->r_hash1) || + wps_process_r_hash2(wps, attr->r_hash2)) { + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + + decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, + attr->encr_settings_len); + if (decrypted == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " + "Settings attribute"); + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + + if (wps_validate_m4_encr(decrypted, attr->version2 != NULL) < 0) { + wpabuf_free(decrypted); + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + + wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " + "attribute"); + if (wps_parse_msg(decrypted, eattr) < 0 || + wps_process_key_wrap_auth(wps, decrypted, eattr->key_wrap_auth) || + wps_process_r_snonce1(wps, eattr->r_snonce1)) { + wpabuf_free(decrypted); + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + wpabuf_free(decrypted); + + wps->state = SEND_M5; + res = WPS_CONTINUE; +_out: + if (eattr) + os_free(eattr); + return res; +} + + +static enum wps_process_res wps_process_m6(struct wps_data *wps, + const struct wpabuf *msg, + struct wps_parse_attr *attr) +{ + struct wpabuf *decrypted; + struct wps_parse_attr *eattr; + enum wps_process_res res; + + wpa_printf(MSG_DEBUG, "WPS: Received M6"); + + eattr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (eattr == NULL) { + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + + if (wps->state != RECV_M6) { + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + "receiving M6", wps->state); + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + + if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || + wps_process_authenticator(wps, attr->authenticator, msg)) { + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + + decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, + attr->encr_settings_len); + if (decrypted == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " + "Settings attribute"); + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + + if (wps_validate_m6_encr(decrypted, attr->version2 != NULL) < 0) { + wpabuf_free(decrypted); + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + + wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " + "attribute"); + if (wps_parse_msg(decrypted, eattr) < 0 || + wps_process_key_wrap_auth(wps, decrypted, eattr->key_wrap_auth) || + wps_process_r_snonce2(wps, eattr->r_snonce2)) { + wpabuf_free(decrypted); + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + wpabuf_free(decrypted); + + if (wps->wps->ap) + wps->wps->event_cb(wps->wps->cb_ctx, WPS_EV_AP_PIN_SUCCESS, + NULL); + + wps->state = SEND_M7; + res = WPS_CONTINUE; +_out: + if (eattr) + os_free(eattr); + return res; +} + + +static enum wps_process_res wps_process_m8(struct wps_data *wps, + const struct wpabuf *msg, + struct wps_parse_attr *attr) +{ + struct wpabuf *decrypted; + struct wps_parse_attr *eattr; + enum wps_process_res res; + + wpa_printf(MSG_DEBUG, "WPS: Received M8"); + + eattr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (eattr == NULL) { + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + + if (wps->state != RECV_M8) { + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + "receiving M8", wps->state); + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + + if (wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || + wps_process_authenticator(wps, attr->authenticator, msg)) { + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + + if (wps->wps->ap && wps->wps->ap_setup_locked) { + /* + * Stop here if special ap_setup_locked == 2 mode allowed the + * protocol to continue beyond M2. This allows ER to learn the + * current AP settings without changing them. + */ + wpa_printf(MSG_DEBUG, "WPS: AP Setup is locked - refuse " + "registration of a new Registrar"); + wps->config_error = WPS_CFG_SETUP_LOCKED; + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + + decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, + attr->encr_settings_len); + if (decrypted == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " + "Settings attribute"); + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + + if (wps_validate_m8_encr(decrypted, wps->wps->ap, + attr->version2 != NULL) < 0) { + wpabuf_free(decrypted); + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + + wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " + "attribute"); + if (wps_parse_msg(decrypted, eattr) < 0 || + wps_process_key_wrap_auth(wps, decrypted, eattr->key_wrap_auth) || + wps_process_creds(wps, eattr->cred, eattr->cred_len, + eattr->num_cred, attr->version2 != NULL) || + wps_process_ap_settings_e(wps, eattr, decrypted, + attr->version2 != NULL)) { + wpabuf_free(decrypted); + wps->state = SEND_WSC_NACK; + res = WPS_CONTINUE; + goto _out; + } + wpabuf_free(decrypted); + + wps->state = WPS_MSG_DONE; + res = WPS_CONTINUE; + +_out: + if (eattr) + os_free(eattr); + return res; +} + +extern struct wps_sm *gWpsSm; + +static enum wps_process_res wps_process_wsc_start(struct wps_data *wps, + const struct wpabuf *msg) +{ + struct wps_sm *sm = gWpsSm; + enum wps_process_res ret = WPS_CONTINUE; + + wpa_printf(MSG_DEBUG, "WPS: Received WSC_START"); + ets_timer_disarm(&sm->wps_eapol_start_timer); + wps->state = SEND_M1; + return ret; +} + +#define WPS_IGNORE_STATE(wps_st) do {\ + if (wps->state <= RECV_M8 && ((wps_st) == wps->state - 1 || (wps_st) == wps->state - 2)) { \ + return WPS_IGNORE;\ + }\ +} while (0) + +static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, + const struct wpabuf *msg) +{ + struct wps_parse_attr *attr; + enum wps_process_res ret = WPS_CONTINUE; + + wpa_printf(MSG_DEBUG, "WPS: Received WSC_MSG"); + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = WPS_FAILURE; + goto _out; + } + + if (wps_parse_msg(msg, attr) < 0) { + ret = WPS_FAILURE; + goto _out; + } + + if (attr->enrollee_nonce == NULL || + os_memcmp(wps->nonce_e, attr->enrollee_nonce, WPS_NONCE_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); + ret = WPS_FAILURE; + goto _out; + } + + if (attr->msg_type == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); + wps->state = SEND_WSC_NACK; + ret = WPS_CONTINUE; + goto _out; + } + + switch (*attr->msg_type) { + case WPS_M2: + WPS_IGNORE_STATE(RECV_M2); + if (wps_validate_m2(msg) < 0) { + ret = WPS_FAILURE; + goto _out; + } + ret = wps_process_m2(wps, msg, attr); + break; + case WPS_M2D: + if (wps_validate_m2d(msg) < 0) { + ret = WPS_FAILURE; + goto _out; + } + ret = wps_process_m2d(wps, attr); + break; + case WPS_M4: + WPS_IGNORE_STATE(RECV_M4); + if (wps_validate_m4(msg) < 0) { + ret = WPS_FAILURE; + goto _out; + } + ret = wps_process_m4(wps, msg, attr); + if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) + wps_fail_event(wps->wps, WPS_M4, wps->config_error, + wps->error_indication); + break; + case WPS_M6: + WPS_IGNORE_STATE(RECV_M6); + if (wps_validate_m6(msg) < 0) { + ret = WPS_FAILURE; + goto _out; + } + ret = wps_process_m6(wps, msg, attr); + if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) + wps_fail_event(wps->wps, WPS_M6, wps->config_error, + wps->error_indication); + break; + case WPS_M8: + WPS_IGNORE_STATE(RECV_M8); + if (wps_validate_m8(msg) < 0) { + ret = WPS_FAILURE; + goto _out; + } + ret = wps_process_m8(wps, msg, attr); + if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) + wps_fail_event(wps->wps, WPS_M8, wps->config_error, + wps->error_indication); + break; + default: + wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d", + *attr->msg_type); + ret = WPS_FAILURE; + goto _out; + } + + /* + * Save a copy of the last message for Authenticator derivation if we + * are continuing. However, skip M2D since it is not authenticated and + * neither is the ACK/NACK response frame. This allows the possibly + * following M2 to be processed correctly by using the previously sent + * M1 in Authenticator derivation. + */ + if (ret == WPS_CONTINUE && *attr->msg_type != WPS_M2D) { + /* Save a copy of the last message for Authenticator derivation + */ + wpabuf_free(wps->last_msg); + wps->last_msg = wpabuf_dup(msg); + } + +_out: + if (attr) + os_free(attr); + + return ret; +} + + +static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps, + const struct wpabuf *msg) +{ + struct wps_parse_attr *attr; + enum wps_process_res res; + + wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK"); + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + res = WPS_FAILURE; + goto _out; + } + + if (wps_parse_msg(msg, attr) < 0) { + res = WPS_FAILURE; + goto _out; + } + + if (attr->msg_type == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); + res = WPS_FAILURE; + goto _out; + } + + if (*attr->msg_type != WPS_WSC_ACK) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", + *attr->msg_type); + res = WPS_FAILURE; + goto _out; + } + + if (attr->registrar_nonce == NULL || + os_memcmp(wps->nonce_r, attr->registrar_nonce, WPS_NONCE_LEN) != 0) + { + wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); + res = WPS_FAILURE; + goto _out; + } + + if (attr->enrollee_nonce == NULL || + os_memcmp(wps->nonce_e, attr->enrollee_nonce, WPS_NONCE_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); + res = WPS_FAILURE; + goto _out; + } + + if (wps->state == RECV_ACK && wps->wps->ap) { + wpa_printf(MSG_DEBUG, "WPS: External Registrar registration " + "completed successfully"); + wps_success_event(wps->wps); + wps->state = WPS_FINISHED; + res = WPS_DONE; + goto _out; + } + + res = WPS_FAILURE; +_out: + if (attr) + os_free(attr); + + return res; +} + + +static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps, + const struct wpabuf *msg) +{ + struct wps_parse_attr *attr; + enum wps_process_res res; + u16 config_error; + + wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK"); + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + res = WPS_FAILURE; + goto _out; + } + + if (wps_parse_msg(msg, attr) < 0) { + res = WPS_FAILURE; + goto _out; + } + + if (attr->msg_type == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); + res = WPS_FAILURE; + goto _out; + } + + if (*attr->msg_type != WPS_WSC_NACK) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", + *attr->msg_type); + res = WPS_FAILURE; + goto _out; + } + + if (attr->registrar_nonce == NULL || + os_memcmp(wps->nonce_r, attr->registrar_nonce, WPS_NONCE_LEN) != 0) + { + wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); + wpa_hexdump(MSG_DEBUG, "WPS: Received Registrar Nonce", + attr->registrar_nonce, WPS_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "WPS: Expected Registrar Nonce", + wps->nonce_r, WPS_NONCE_LEN); + res = WPS_FAILURE; + goto _out; + } + + if (attr->enrollee_nonce == NULL || + os_memcmp(wps->nonce_e, attr->enrollee_nonce, WPS_NONCE_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); + wpa_hexdump(MSG_DEBUG, "WPS: Received Enrollee Nonce", + attr->enrollee_nonce, WPS_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "WPS: Expected Enrollee Nonce", + wps->nonce_e, WPS_NONCE_LEN); + res = WPS_FAILURE; + goto _out; + } + + if (attr->config_error == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Configuration Error attribute " + "in WSC_NACK"); + res = WPS_FAILURE; + goto _out; + } + + config_error = WPA_GET_BE16(attr->config_error); + wpa_printf(MSG_DEBUG, "WPS: Registrar terminated negotiation with " + "Configuration Error %d", config_error); + + switch (wps->state) { + case RECV_M4: + wps_fail_event(wps->wps, WPS_M3, config_error, + wps->error_indication); + break; + case RECV_M6: + wps_fail_event(wps->wps, WPS_M5, config_error, + wps->error_indication); + break; + case RECV_M8: + wps_fail_event(wps->wps, WPS_M7, config_error, + wps->error_indication); + break; + default: + break; + } + + /* Followed by NACK if Enrollee is Supplicant or EAP-Failure if + * Enrollee is Authenticator */ + wps->state = SEND_WSC_NACK; + + res = WPS_FAILURE; +_out: + if (attr) + os_free(attr); + + return res; +} + + +enum wps_process_res wps_enrollee_process_msg(struct wps_data *wps, + enum wsc_op_code op_code, + const struct wpabuf *msg) +{ + + wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu " + "op_code=%d)", + (unsigned long) wpabuf_len(msg), op_code); + + if (op_code == WSC_UPnP) { + /* Determine the OpCode based on message type attribute */ + struct wps_parse_attr attr; + if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type) { + if (*attr.msg_type == WPS_WSC_ACK) + op_code = WSC_ACK; + else if (*attr.msg_type == WPS_WSC_NACK) + op_code = WSC_NACK; + } + } + + switch (op_code) { + case WSC_Start: + return wps_process_wsc_start(wps, msg); + case WSC_MSG: + case WSC_UPnP: + return wps_process_wsc_msg(wps, msg); + case WSC_ACK: + if (wps_validate_wsc_ack(msg) < 0) + return WPS_FAILURE; + return wps_process_wsc_ack(wps, msg); + case WSC_NACK: + if (wps_validate_wsc_nack(msg) < 0) + return WPS_FAILURE; + return wps_process_wsc_nack(wps, msg); + default: + wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code); + return WPS_FAILURE; + } +} diff --git a/components/wpa_supplicant/src/wps/wps_registrar.c b/components/wpa_supplicant/src/wps/wps_registrar.c new file mode 100644 index 0000000000..a38a75d1fe --- /dev/null +++ b/components/wpa_supplicant/src/wps/wps_registrar.c @@ -0,0 +1,3635 @@ +/* + * Wi-Fi Protected Setup - Registrar + * Copyright (c) 2008-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "wpa/includes.h" +#include "wpa/list.h" +#include "wpa/common.h" +#include "crypto/base64.h" +//#include "utils/eloop.h" +#include "wps/utils/uuid.h" +#include "wpa/list.h" +#include "crypto/crypto.h" +#include "crypto/sha256.h" +#include "crypto/random.h" +#include "wpa/ieee802_11_defs.h" +#include "wps/wps_i.h" +#include "wps/wps_dev_attr.h" +//#include "wps/wps_upnp.h" +//#include "wps/wps_upnp_i.h" + +#ifndef CONFIG_WPS_STRICT +#define WPS_WORKAROUNDS +#endif /* CONFIG_WPS_STRICT */ + +#ifdef CONFIG_WPS_NFC + +struct wps_nfc_pw_token { + struct dl_list list; + u8 pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN]; + u16 pw_id; + u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN]; + size_t dev_pw_len; +}; + + +static void wps_remove_nfc_pw_token(struct wps_nfc_pw_token *token) +{ + dl_list_del(&token->list); + os_free(token); +} + + +static void wps_free_nfc_pw_tokens(struct dl_list *tokens, u16 pw_id) +{ + struct wps_nfc_pw_token *token, *prev; + dl_list_for_each_safe(token, prev, tokens, struct wps_nfc_pw_token, + list) { + if (pw_id == 0 || pw_id == token->pw_id) + wps_remove_nfc_pw_token(token); + } +} + + +static struct wps_nfc_pw_token * wps_get_nfc_pw_token(struct dl_list *tokens, + u16 pw_id) +{ + struct wps_nfc_pw_token *token; + dl_list_for_each(token, tokens, struct wps_nfc_pw_token, list) { + if (pw_id == token->pw_id) + return token; + } + return NULL; +} + +#else /* CONFIG_WPS_NFC */ + +#define wps_free_nfc_pw_tokens(t, p) do { } while (0) + +#endif /* CONFIG_WPS_NFC */ + +#ifdef CONFIG_WPS_PIN + +struct wps_uuid_pin { + struct dl_list list; + u8 uuid[WPS_UUID_LEN]; + int wildcard_uuid; + u8 *pin; + size_t pin_len; +#define PIN_LOCKED BIT(0) +#define PIN_EXPIRES BIT(1) + int flags; + struct os_time expiration; + u8 enrollee_addr[ETH_ALEN]; +}; + + +static void wps_free_pin(struct wps_uuid_pin *pin) +{ + os_free(pin->pin); + os_free(pin); +} + + +static void wps_remove_pin(struct wps_uuid_pin *pin) +{ + dl_list_del(&pin->list); + wps_free_pin(pin); +} + + +static void wps_free_pins(struct dl_list *pins) +{ + struct wps_uuid_pin *pin, *prev; + dl_list_for_each_safe(pin, prev, pins, struct wps_uuid_pin, list); + wps_remove_pin(pin); +} + +#endif + +struct wps_pbc_session { + struct wps_pbc_session *next; + u8 addr[ETH_ALEN]; + u8 uuid_e[WPS_UUID_LEN]; + struct os_time timestamp; +}; + + +static void wps_free_pbc_sessions(struct wps_pbc_session *pbc) +{ + struct wps_pbc_session *prev; + + while (pbc) { + prev = pbc; + pbc = pbc->next; + os_free(prev); + } +} + + +struct wps_registrar_device { + struct wps_registrar_device *next; + struct wps_device_data dev; + u8 uuid[WPS_UUID_LEN]; +}; + + +struct wps_registrar { + struct wps_context *wps; + + int pbc; + int selected_registrar; + + int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *psk, + size_t psk_len); + int (*set_ie_cb)(void *ctx, struct wpabuf *beacon_ie, + struct wpabuf *probe_resp_ie); + void (*pin_needed_cb)(void *ctx, const u8 *uuid_e, + const struct wps_device_data *dev); + void (*reg_success_cb)(void *ctx, const u8 *mac_addr, + const u8 *uuid_e, const u8 *dev_pw, + size_t dev_pw_len); + void (*set_sel_reg_cb)(void *ctx, int sel_reg, u16 dev_passwd_id, + u16 sel_reg_config_methods); + void (*enrollee_seen_cb)(void *ctx, const u8 *addr, const u8 *uuid_e, + const u8 *pri_dev_type, u16 config_methods, + u16 dev_password_id, u8 request_type, + const char *dev_name); + void *cb_ctx; + + struct dl_list pins; + struct dl_list nfc_pw_tokens; + struct wps_pbc_session *pbc_sessions; + + int skip_cred_build; + struct wpabuf *extra_cred; + int disable_auto_conf; + int sel_reg_union; + int sel_reg_dev_password_id_override; + int sel_reg_config_methods_override; + int static_wep_only; + int dualband; + + struct wps_registrar_device *devices; + + int force_pbc_overlap; + + u8 authorized_macs[WPS_MAX_AUTHORIZED_MACS][ETH_ALEN]; + u8 authorized_macs_union[WPS_MAX_AUTHORIZED_MACS][ETH_ALEN]; + + u8 p2p_dev_addr[ETH_ALEN]; + + u8 pbc_ignore_uuid[WPS_UUID_LEN]; + struct os_time pbc_ignore_start; +}; + + +static int wps_set_ie(struct wps_registrar *reg); +//static void wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx); +//static void wps_registrar_set_selected_timeout(void *eloop_ctx, +// void *timeout_ctx); +static void wps_registrar_pbc_timeout(void *eloop_ctx); +//static void wps_registrar_set_selected_timeout(void *eloop_ctx); + +#ifdef CONFIG_WPS_PIN + +static void wps_registrar_remove_pin(struct wps_registrar *reg, + struct wps_uuid_pin *pin); +#endif + +static void wps_registrar_add_authorized_mac(struct wps_registrar *reg, + const u8 *addr) +{ + int i; + wpa_printf(MSG_DEBUG, "WPS: Add authorized MAC " MACSTR, + MAC2STR(addr)); + for (i = 0; i < WPS_MAX_AUTHORIZED_MACS; i++) + if (os_memcmp(reg->authorized_macs[i], addr, ETH_ALEN) == 0) { + wpa_printf(MSG_DEBUG, "WPS: Authorized MAC was " + "already in the list"); + return; /* already in list */ + } + for (i = WPS_MAX_AUTHORIZED_MACS - 1; i > 0; i--) + os_memcpy(reg->authorized_macs[i], reg->authorized_macs[i - 1], + ETH_ALEN); + os_memcpy(reg->authorized_macs[0], addr, ETH_ALEN); + wpa_hexdump(MSG_DEBUG, "WPS: Authorized MACs", + (u8 *) reg->authorized_macs, sizeof(reg->authorized_macs)); +} + + +static void wps_registrar_remove_authorized_mac(struct wps_registrar *reg, + const u8 *addr) +{ + int i; + wpa_printf(MSG_DEBUG, "WPS: Remove authorized MAC " MACSTR, + MAC2STR(addr)); + for (i = 0; i < WPS_MAX_AUTHORIZED_MACS; i++) { + if (os_memcmp(reg->authorized_macs, addr, ETH_ALEN) == 0) + break; + } + if (i == WPS_MAX_AUTHORIZED_MACS) { + wpa_printf(MSG_DEBUG, "WPS: Authorized MAC was not in the " + "list"); + return; /* not in the list */ + } + for (; i + 1 < WPS_MAX_AUTHORIZED_MACS; i++) + os_memcpy(reg->authorized_macs[i], reg->authorized_macs[i + 1], + ETH_ALEN); + os_memset(reg->authorized_macs[WPS_MAX_AUTHORIZED_MACS - 1], 0, + ETH_ALEN); + wpa_hexdump(MSG_DEBUG, "WPS: Authorized MACs", + (u8 *) reg->authorized_macs, sizeof(reg->authorized_macs)); +} + + +static void wps_free_devices(struct wps_registrar_device *dev) +{ + struct wps_registrar_device *prev; + + while (dev) { + prev = dev; + dev = dev->next; + wps_device_data_free(&prev->dev); + os_free(prev); + } +} + + +static struct wps_registrar_device * wps_device_get(struct wps_registrar *reg, + const u8 *addr) +{ + struct wps_registrar_device *dev; + + for (dev = reg->devices; dev; dev = dev->next) { + if (os_memcmp(dev->dev.mac_addr, addr, ETH_ALEN) == 0) + return dev; + } + return NULL; +} + + +static void wps_device_clone_data(struct wps_device_data *dst, + struct wps_device_data *src) +{ + os_memcpy(dst->mac_addr, src->mac_addr, ETH_ALEN); + os_memcpy(dst->pri_dev_type, src->pri_dev_type, WPS_DEV_TYPE_LEN); + +#define WPS_STRDUP(n) \ + os_free(dst->n); \ + dst->n = src->n ? os_strdup(src->n) : NULL + + WPS_STRDUP(device_name); + WPS_STRDUP(manufacturer); + WPS_STRDUP(model_name); + WPS_STRDUP(model_number); + WPS_STRDUP(serial_number); +#undef WPS_STRDUP +} + + +int wps_device_store(struct wps_registrar *reg, + struct wps_device_data *dev, const u8 *uuid) +{ + struct wps_registrar_device *d; + + d = wps_device_get(reg, dev->mac_addr); + if (d == NULL) { + d = (struct wps_registrar_device *)os_zalloc(sizeof(*d)); + if (d == NULL) + return -1; + d->next = reg->devices; + reg->devices = d; + } + + wps_device_clone_data(&d->dev, dev); + os_memcpy(d->uuid, uuid, WPS_UUID_LEN); + + return 0; +} + + +static void wps_registrar_add_pbc_session(struct wps_registrar *reg, + const u8 *addr, const u8 *uuid_e) +{ + struct wps_pbc_session *pbc, *prev = NULL; + struct os_time now; + + os_get_time(&now); + + pbc = reg->pbc_sessions; + while (pbc) { + if (os_memcmp(pbc->addr, addr, ETH_ALEN) == 0 && + os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0) { + if (prev) + prev->next = pbc->next; + else + reg->pbc_sessions = pbc->next; + break; + } + prev = pbc; + pbc = pbc->next; + } + + if (!pbc) { + pbc = (struct wps_pbc_session *)os_zalloc(sizeof(*pbc)); + if (pbc == NULL) + return; + os_memcpy(pbc->addr, addr, ETH_ALEN); + if (uuid_e) + os_memcpy(pbc->uuid_e, uuid_e, WPS_UUID_LEN); + } + + pbc->next = reg->pbc_sessions; + reg->pbc_sessions = pbc; + pbc->timestamp = now; + + /* remove entries that have timed out */ + prev = pbc; + pbc = pbc->next; + + while (pbc) { + if (now.sec > pbc->timestamp.sec + WPS_PBC_WALK_TIME) { + prev->next = NULL; + wps_free_pbc_sessions(pbc); + break; + } + prev = pbc; + pbc = pbc->next; + } +} + + +static void wps_registrar_remove_pbc_session(struct wps_registrar *reg, + const u8 *uuid_e, + const u8 *p2p_dev_addr) +{ + struct wps_pbc_session *pbc, *prev = NULL, *tmp; + + pbc = reg->pbc_sessions; + while (pbc) { + if (os_memcmp(pbc->uuid_e, uuid_e, WPS_UUID_LEN) == 0 || + (p2p_dev_addr && !is_zero_ether_addr(reg->p2p_dev_addr) && + os_memcmp(reg->p2p_dev_addr, p2p_dev_addr, ETH_ALEN) == + 0)) { + if (prev) + prev->next = pbc->next; + else + reg->pbc_sessions = pbc->next; + tmp = pbc; + pbc = pbc->next; + wpa_printf(MSG_DEBUG, "WPS: Removing PBC session for " + "addr=" MACSTR, MAC2STR(tmp->addr)); + wpa_hexdump(MSG_DEBUG, "WPS: Removed UUID-E", + tmp->uuid_e, WPS_UUID_LEN); + os_free(tmp); + continue; + } + prev = pbc; + pbc = pbc->next; + } +} + + +int wps_registrar_pbc_overlap(struct wps_registrar *reg, + const u8 *addr, const u8 *uuid_e) +{ + int count = 0; + struct wps_pbc_session *pbc; + struct wps_pbc_session *first = NULL; + struct os_time now; + + os_get_time(&now); + + wpa_printf(MSG_DEBUG, "WPS: Checking active PBC sessions for overlap"); + + if (uuid_e) { + wpa_printf(MSG_DEBUG, "WPS: Add one for the requested UUID"); + wpa_hexdump(MSG_DEBUG, "WPS: Requested UUID", + uuid_e, WPS_UUID_LEN); + count++; + } + + for (pbc = reg->pbc_sessions; pbc; pbc = pbc->next) { + wpa_printf(MSG_DEBUG, "WPS: Consider PBC session with " MACSTR, + MAC2STR(pbc->addr)); + wpa_hexdump(MSG_DEBUG, "WPS: UUID-E", + pbc->uuid_e, WPS_UUID_LEN); + if (now.sec > pbc->timestamp.sec + WPS_PBC_WALK_TIME) { + wpa_printf(MSG_DEBUG, "WPS: PBC walk time has " + "expired"); + break; + } + if (first && + os_memcmp(pbc->uuid_e, first->uuid_e, WPS_UUID_LEN) == 0) { + wpa_printf(MSG_DEBUG, "WPS: Same Enrollee"); + continue; /* same Enrollee */ + } + if (uuid_e == NULL || + os_memcmp(uuid_e, pbc->uuid_e, WPS_UUID_LEN)) { + wpa_printf(MSG_DEBUG, "WPS: New Enrollee"); + count++; + } + if (first == NULL) + first = pbc; + } + + wpa_printf(MSG_DEBUG, "WPS: %u active PBC session(s) found", count); + + return count > 1 ? 1 : 0; +} + + +static int wps_build_wps_state(struct wps_context *wps, struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS: * Wi-Fi Protected Setup State (%d)", + wps->wps_state); + wpabuf_put_be16(msg, ATTR_WPS_STATE); + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, wps->wps_state); + return 0; +} + + +#ifdef CONFIG_WPS_UPNP +static void wps_registrar_free_pending_m2(struct wps_context *wps) +{ + struct upnp_pending_message *p, *p2, *prev = NULL; + p = wps->upnp_msgs; + while (p) { + if (p->type == WPS_M2 || p->type == WPS_M2D) { + if (prev == NULL) + wps->upnp_msgs = p->next; + else + prev->next = p->next; + wpa_printf(MSG_DEBUG, "WPS UPnP: Drop pending M2/M2D"); + p2 = p; + p = p->next; + wpabuf_free(p2->msg); + os_free(p2); + continue; + } + prev = p; + p = p->next; + } +} +#endif /* CONFIG_WPS_UPNP */ + + +static int wps_build_ap_setup_locked(struct wps_context *wps, + struct wpabuf *msg) +{ + if (wps->ap_setup_locked && wps->ap_setup_locked != 2) { + wpa_printf(MSG_DEBUG, "WPS: * AP Setup Locked"); + wpabuf_put_be16(msg, ATTR_AP_SETUP_LOCKED); + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, 1); + } + return 0; +} + + +static int wps_build_selected_registrar(struct wps_registrar *reg, + struct wpabuf *msg) +{ + if (!reg->sel_reg_union) + return 0; + wpa_printf(MSG_DEBUG, "WPS: * Selected Registrar"); + wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR); + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, 1); + return 0; +} + + +static int wps_build_sel_reg_dev_password_id(struct wps_registrar *reg, + struct wpabuf *msg) +{ + u16 id = reg->pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT; + if (!reg->sel_reg_union) + return 0; + if (reg->sel_reg_dev_password_id_override >= 0) + id = reg->sel_reg_dev_password_id_override; + wpa_printf(MSG_DEBUG, "WPS: * Device Password ID (%d)", id); + wpabuf_put_be16(msg, ATTR_DEV_PASSWORD_ID); + wpabuf_put_be16(msg, 2); + wpabuf_put_be16(msg, id); + return 0; +} + + +static int wps_build_sel_pbc_reg_uuid_e(struct wps_registrar *reg, + struct wpabuf *msg) +{ + u16 id = reg->pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT; + if (!reg->sel_reg_union) + return 0; + if (reg->sel_reg_dev_password_id_override >= 0) + id = reg->sel_reg_dev_password_id_override; + if (id != DEV_PW_PUSHBUTTON || !reg->dualband) + return 0; + return wps_build_uuid_e(msg, reg->wps->uuid); +} + + +static void wps_set_pushbutton(u16 *methods, u16 conf_methods) +{ + *methods |= WPS_CONFIG_PUSHBUTTON; +#ifdef CONFIG_WPS2 + if ((conf_methods & WPS_CONFIG_VIRT_PUSHBUTTON) == + WPS_CONFIG_VIRT_PUSHBUTTON) + *methods |= WPS_CONFIG_VIRT_PUSHBUTTON; + if ((conf_methods & WPS_CONFIG_PHY_PUSHBUTTON) == + WPS_CONFIG_PHY_PUSHBUTTON) + *methods |= WPS_CONFIG_PHY_PUSHBUTTON; + if ((*methods & WPS_CONFIG_VIRT_PUSHBUTTON) != + WPS_CONFIG_VIRT_PUSHBUTTON && + (*methods & WPS_CONFIG_PHY_PUSHBUTTON) != + WPS_CONFIG_PHY_PUSHBUTTON) { + /* + * Required to include virtual/physical flag, but we were not + * configured with push button type, so have to default to one + * of them. + */ + *methods |= WPS_CONFIG_PHY_PUSHBUTTON; + } +#endif /* CONFIG_WPS2 */ +} + + +static int wps_build_sel_reg_config_methods(struct wps_registrar *reg, + struct wpabuf *msg) +{ + u16 methods; + if (!reg->sel_reg_union) + return 0; + methods = reg->wps->config_methods; + methods &= ~WPS_CONFIG_PUSHBUTTON; +#ifdef CONFIG_WPS2 + methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON | + WPS_CONFIG_PHY_PUSHBUTTON); +#endif /* CONFIG_WPS2 */ + if (reg->pbc) + wps_set_pushbutton(&methods, reg->wps->config_methods); + if (reg->sel_reg_config_methods_override >= 0) + methods = reg->sel_reg_config_methods_override; + wpa_printf(MSG_DEBUG, "WPS: * Selected Registrar Config Methods (%x)", + methods); + wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR_CONFIG_METHODS); + wpabuf_put_be16(msg, 2); + wpabuf_put_be16(msg, methods); + return 0; +} + + +static int wps_build_probe_config_methods(struct wps_registrar *reg, + struct wpabuf *msg) +{ + u16 methods; + /* + * These are the methods that the AP supports as an Enrollee for adding + * external Registrars. + */ + methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; +#ifdef CONFIG_WPS2 + methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON | + WPS_CONFIG_PHY_PUSHBUTTON); +#endif /* CONFIG_WPS2 */ + wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); + wpabuf_put_be16(msg, ATTR_CONFIG_METHODS); + wpabuf_put_be16(msg, 2); + wpabuf_put_be16(msg, methods); + return 0; +} + + +static int wps_build_config_methods_r(struct wps_registrar *reg, + struct wpabuf *msg) +{ + return wps_build_config_methods(msg, reg->wps->config_methods); +} + + +const u8 * wps_authorized_macs(struct wps_registrar *reg, size_t *count) +{ + *count = 0; + +#ifdef CONFIG_WPS2 + while (*count < WPS_MAX_AUTHORIZED_MACS) { + if (is_zero_ether_addr(reg->authorized_macs_union[*count])) + break; + (*count)++; + } +#endif /* CONFIG_WPS2 */ + + return (const u8 *) reg->authorized_macs_union; +} + + +/** + * wps_registrar_init - Initialize WPS Registrar data + * @wps: Pointer to longterm WPS context + * @cfg: Registrar configuration + * Returns: Pointer to allocated Registrar data or %NULL on failure + * + * This function is used to initialize WPS Registrar functionality. It can be + * used for a single Registrar run (e.g., when run in a supplicant) or multiple + * runs (e.g., when run as an internal Registrar in an AP). Caller is + * responsible for freeing the returned data with wps_registrar_deinit() when + * Registrar functionality is not needed anymore. + */ +struct wps_registrar * wps_registrar_init(struct wps_context *wps, + const struct wps_registrar_config *cfg) +{ + struct wps_registrar *reg = (struct wps_registrar *)os_zalloc(sizeof(*reg)); + if (reg == NULL) + return NULL; +#ifdef CONFIG_WPS_PIN + dl_list_init(®->pins); +#endif +#ifdef CONFIG_WPS_NFC + dl_list_init(®->nfc_pw_tokens); +#endif + reg->wps = wps; + reg->new_psk_cb = cfg->new_psk_cb; + reg->set_ie_cb = cfg->set_ie_cb; +#ifdef CONFIG_WPS_PIN + reg->pin_needed_cb = cfg->pin_needed_cb; +#endif + reg->reg_success_cb = cfg->reg_success_cb; + reg->set_sel_reg_cb = cfg->set_sel_reg_cb; + reg->enrollee_seen_cb = cfg->enrollee_seen_cb; + reg->cb_ctx = cfg->cb_ctx; + reg->skip_cred_build = cfg->skip_cred_build; + if (cfg->extra_cred) { + reg->extra_cred = wpabuf_alloc_copy(cfg->extra_cred, + cfg->extra_cred_len); + if (reg->extra_cred == NULL) { + os_free(reg); + return NULL; + } + } + reg->disable_auto_conf = cfg->disable_auto_conf; + reg->sel_reg_dev_password_id_override = -1; + reg->sel_reg_config_methods_override = -1; + reg->static_wep_only = cfg->static_wep_only; + reg->dualband = cfg->dualband; + + if (wps_set_ie(reg)) { + wps_registrar_deinit(reg); + return NULL; + } + + return reg; +} + + +/** + * wps_registrar_deinit - Deinitialize WPS Registrar data + * @reg: Registrar data from wps_registrar_init() + */ +void wps_registrar_deinit(struct wps_registrar *reg) +{ + if (reg == NULL) + return; + //eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); + //eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); + + // TODO: snake to check, no sys_untimeout now, by wujg +// sys_untimeout(wps_registrar_pbc_timeout, reg); +// sys_untimeout(wps_registrar_set_selected_timeout, reg); + +#ifdef CONFIG_WPS_PIN + wps_free_pins(®->pins); +#endif +#ifdef CONFIG_WPS_NFC + wps_free_nfc_pw_tokens(®->nfc_pw_tokens, 0); +#endif + wps_free_pbc_sessions(reg->pbc_sessions); + wpabuf_free(reg->extra_cred); + wps_free_devices(reg->devices); + os_free(reg); +} + +#ifdef CONFIG_WPS_PIN + +static void wps_registrar_invalidate_unused(struct wps_registrar *reg) +{ + struct wps_uuid_pin *pin; + + dl_list_for_each(pin, ®->pins, struct wps_uuid_pin, list) { + if (pin->wildcard_uuid == 1 && !(pin->flags & PIN_LOCKED)) { + wpa_printf(MSG_DEBUG, "WPS: Invalidate previously " + "configured wildcard PIN"); + wps_registrar_remove_pin(reg, pin); + break; + } + } +} + + +/** + * wps_registrar_add_pin - Configure a new PIN for Registrar + * @reg: Registrar data from wps_registrar_init() + * @addr: Enrollee MAC address or %NULL if not known + * @uuid: UUID-E or %NULL for wildcard (any UUID) + * @pin: PIN (Device Password) + * @pin_len: Length of pin in octets + * @timeout: Time (in seconds) when the PIN will be invalidated; 0 = no timeout + * Returns: 0 on success, -1 on failure + */ +int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *addr, + const u8 *uuid, const u8 *pin, size_t pin_len, + int timeout) +{ + struct wps_uuid_pin *p; + + p = (struct wps_uuid_pin *)os_zalloc(sizeof(*p)); + if (p == NULL) + return -1; + if (addr) + os_memcpy(p->enrollee_addr, addr, ETH_ALEN); + if (uuid == NULL) + p->wildcard_uuid = 1; + else + os_memcpy(p->uuid, uuid, WPS_UUID_LEN); + p->pin = (u8 *)os_malloc(pin_len); + if (p->pin == NULL) { + os_free(p); + return -1; + } + os_memcpy(p->pin, pin, pin_len); + p->pin_len = pin_len; + + if (timeout) { + p->flags |= PIN_EXPIRES; + os_get_time(&p->expiration); + p->expiration.sec += timeout; + } + + if (p->wildcard_uuid) + wps_registrar_invalidate_unused(reg); + + dl_list_add(®->pins, &p->list); + + wpa_printf(MSG_DEBUG, "WPS: A new PIN configured (timeout=%d)", + timeout); + wpa_hexdump(MSG_DEBUG, "WPS: UUID", uuid, WPS_UUID_LEN); + wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: PIN", pin, pin_len); + reg->selected_registrar = 1; + reg->pbc = 0; + if (addr) + wps_registrar_add_authorized_mac(reg, addr); + else + wps_registrar_add_authorized_mac( + reg, (u8 *) "\xff\xff\xff\xff\xff\xff"); + wps_registrar_selected_registrar_changed(reg); + //eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); + //eloop_register_timeout(WPS_PBC_WALK_TIME, 0, + //wps_registrar_set_selected_timeout, + //reg, NULL); + + return 0; +} + + +static void wps_registrar_remove_pin(struct wps_registrar *reg, + struct wps_uuid_pin *pin) +{ + u8 *addr; + u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + if (is_zero_ether_addr(pin->enrollee_addr)) + addr = bcast; + else + addr = pin->enrollee_addr; + wps_registrar_remove_authorized_mac(reg, addr); + wps_remove_pin(pin); + wps_registrar_selected_registrar_changed(reg); +} + + +static void wps_registrar_expire_pins(struct wps_registrar *reg) +{ + struct wps_uuid_pin *pin, *prev; + struct os_time now; + + os_get_time(&now); + dl_list_for_each_safe(pin, prev, ®->pins, struct wps_uuid_pin, list) + { + if ((pin->flags & PIN_EXPIRES) && + os_time_before(&pin->expiration, &now)) { + wpa_hexdump(MSG_DEBUG, "WPS: Expired PIN for UUID", + pin->uuid, WPS_UUID_LEN); + wps_registrar_remove_pin(reg, pin); + } + } +} + + +/** + * wps_registrar_invalidate_wildcard_pin - Invalidate a wildcard PIN + * @reg: Registrar data from wps_registrar_init() + * @dev_pw: PIN to search for or %NULL to match any + * @dev_pw_len: Length of dev_pw in octets + * Returns: 0 on success, -1 if not wildcard PIN is enabled + */ +static int wps_registrar_invalidate_wildcard_pin(struct wps_registrar *reg, + const u8 *dev_pw, + size_t dev_pw_len) +{ + struct wps_uuid_pin *pin, *prev; + + dl_list_for_each_safe(pin, prev, ®->pins, struct wps_uuid_pin, list) + { + if (dev_pw && pin->pin && + (dev_pw_len != pin->pin_len || + os_memcmp(dev_pw, pin->pin, dev_pw_len) != 0)) + continue; /* different PIN */ + if (pin->wildcard_uuid) { + wpa_hexdump(MSG_DEBUG, "WPS: Invalidated PIN for UUID", + pin->uuid, WPS_UUID_LEN); + wps_registrar_remove_pin(reg, pin); + return 0; + } + } + + return -1; +} + + +/** + * wps_registrar_invalidate_pin - Invalidate a PIN for a specific UUID-E + * @reg: Registrar data from wps_registrar_init() + * @uuid: UUID-E + * Returns: 0 on success, -1 on failure (e.g., PIN not found) + */ +int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid) +{ + struct wps_uuid_pin *pin, *prev; + + dl_list_for_each_safe(pin, prev, ®->pins, struct wps_uuid_pin, list) + { + if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) { + wpa_hexdump(MSG_DEBUG, "WPS: Invalidated PIN for UUID", + pin->uuid, WPS_UUID_LEN); + wps_registrar_remove_pin(reg, pin); + return 0; + } + } + + return -1; +} + + +static const u8 * wps_registrar_get_pin(struct wps_registrar *reg, + const u8 *uuid, size_t *pin_len) +{ + struct wps_uuid_pin *pin, *found = NULL; + + wps_registrar_expire_pins(reg); + + dl_list_for_each(pin, ®->pins, struct wps_uuid_pin, list) { + if (!pin->wildcard_uuid && + os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) { + found = pin; + break; + } + } + + if (!found) { + /* Check for wildcard UUIDs since none of the UUID-specific + * PINs matched */ + dl_list_for_each(pin, ®->pins, struct wps_uuid_pin, list) { + if (pin->wildcard_uuid == 1 || + pin->wildcard_uuid == 2) { + wpa_printf(MSG_DEBUG, "WPS: Found a wildcard " + "PIN. Assigned it for this UUID-E"); + pin->wildcard_uuid++; + os_memcpy(pin->uuid, uuid, WPS_UUID_LEN); + found = pin; + break; + } + } + } + + if (!found) + return NULL; + + /* + * Lock the PIN to avoid attacks based on concurrent re-use of the PIN + * that could otherwise avoid PIN invalidations. + */ + if (found->flags & PIN_LOCKED) { + wpa_printf(MSG_DEBUG, "WPS: Selected PIN locked - do not " + "allow concurrent re-use"); + return NULL; + } + *pin_len = found->pin_len; + found->flags |= PIN_LOCKED; + return found->pin; +} + + +/** + * wps_registrar_unlock_pin - Unlock a PIN for a specific UUID-E + * @reg: Registrar data from wps_registrar_init() + * @uuid: UUID-E + * Returns: 0 on success, -1 on failure + * + * PINs are locked to enforce only one concurrent use. This function unlocks a + * PIN to allow it to be used again. If the specified PIN was configured using + * a wildcard UUID, it will be removed instead of allowing multiple uses. + */ +int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid) +{ + struct wps_uuid_pin *pin; + + dl_list_for_each(pin, ®->pins, struct wps_uuid_pin, list) { + if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) { + if (pin->wildcard_uuid == 3) { + wpa_printf(MSG_DEBUG, "WPS: Invalidating used " + "wildcard PIN"); + return wps_registrar_invalidate_pin(reg, uuid); + } + pin->flags &= ~PIN_LOCKED; + return 0; + } + } + + return -1; +} +#endif + +static void wps_registrar_stop_pbc(struct wps_registrar *reg) +{ + reg->selected_registrar = 0; + reg->pbc = 0; + os_memset(reg->p2p_dev_addr, 0, ETH_ALEN); + wps_registrar_remove_authorized_mac(reg, + (u8 *) "\xff\xff\xff\xff\xff\xff"); + wps_registrar_selected_registrar_changed(reg); +} + + +//static void ICACHE_FLASH_ATTR wps_registrar_pbc_timeout(void *eloop_ctx, void *timeout_ctx) +static void wps_registrar_pbc_timeout(void *eloop_ctx) +{ + struct wps_registrar *reg = eloop_ctx; + + wpa_printf(MSG_DEBUG, "WPS: PBC timed out - disable PBC mode"); + wps_pbc_timeout_event(reg->wps); + wps_registrar_stop_pbc(reg); +} + + +/** + * wps_registrar_button_pushed - Notify Registrar that AP button was pushed + * @reg: Registrar data from wps_registrar_init() + * @p2p_dev_addr: Limit allowed PBC devices to the specified P2P device, %NULL + * indicates no such filtering + * Returns: 0 on success, -1 on failure, -2 on session overlap + * + * This function is called on an AP when a push button is pushed to activate + * PBC mode. The PBC mode will be stopped after walk time (2 minutes) timeout + * or when a PBC registration is completed. If more than one Enrollee in active + * PBC mode has been detected during the monitor time (previous 2 minutes), the + * PBC mode is not activated and -2 is returned to indicate session overlap. + * This is skipped if a specific Enrollee is selected. + */ +int wps_registrar_button_pushed(struct wps_registrar *reg, + const u8 *p2p_dev_addr) +{ + if (p2p_dev_addr == NULL && + wps_registrar_pbc_overlap(reg, NULL, NULL)) { + wpa_printf(MSG_DEBUG, "WPS: PBC overlap - do not start PBC " + "mode"); + wps_pbc_overlap_event(reg->wps); + return -2; + } + wpa_printf(MSG_DEBUG, "WPS: Button pushed - PBC mode started"); + reg->force_pbc_overlap = 0; + reg->selected_registrar = 1; + reg->pbc = 1; + if (p2p_dev_addr) + os_memcpy(reg->p2p_dev_addr, p2p_dev_addr, ETH_ALEN); + else + os_memset(reg->p2p_dev_addr, 0, ETH_ALEN); + wps_registrar_add_authorized_mac(reg, + (u8 *) "\xff\xff\xff\xff\xff\xff"); + wps_registrar_selected_registrar_changed(reg); + + //eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); + //eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); + + // TODO: snake to check, no sys_untimeout now, by wujg +// sys_untimeout(wps_registrar_set_selected_timeout, reg); +// sys_untimeout(wps_registrar_pbc_timeout, reg); + + //eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wps_registrar_pbc_timeout, + // reg, NULL); +// sys_timeout(WPS_PBC_WALK_TIME*1000, wps_registrar_pbc_timeout, reg); + + return 0; +} + + +static void wps_registrar_pbc_completed(struct wps_registrar *reg) +{ + wpa_printf(MSG_DEBUG, "WPS: PBC completed - stopping PBC mode"); + + // TODO: snake to check, no sys_untimeout now, by wujg + //eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); +// sys_untimeout(wps_registrar_pbc_timeout, reg); + + wps_registrar_stop_pbc(reg); +} + +#ifdef CONFIG_WPS_PIN + +static void wps_registrar_pin_completed(struct wps_registrar *reg) +{ + wpa_printf(MSG_DEBUG, "WPS: PIN completed using internal Registrar"); + //eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); + reg->selected_registrar = 0; + wps_registrar_selected_registrar_changed(reg); +} +#endif + +void wps_registrar_complete(struct wps_registrar *registrar, const u8 *uuid_e, + const u8 *dev_pw, size_t dev_pw_len) +{ + if (registrar->pbc) { + wps_registrar_remove_pbc_session(registrar, + uuid_e, NULL); + wps_registrar_pbc_completed(registrar); + os_get_time(®istrar->pbc_ignore_start); + os_memcpy(registrar->pbc_ignore_uuid, uuid_e, WPS_UUID_LEN); + } else { +#ifdef CONFIG_WPS_PIN + wps_registrar_pin_completed(registrar); +#endif + } +#ifdef CONFIG_WPS_PIN + if (dev_pw && + wps_registrar_invalidate_wildcard_pin(registrar, dev_pw, + dev_pw_len) == 0) { + wpa_hexdump_key(MSG_DEBUG, "WPS: Invalidated wildcard PIN", + dev_pw, dev_pw_len); + } +#endif +} + + +int wps_registrar_wps_cancel(struct wps_registrar *reg) +{ + if (reg->pbc) { + wpa_printf(MSG_DEBUG, "WPS: PBC is set - cancelling it"); + //wps_registrar_pbc_timeout(reg, NULL); + //eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL); + wps_registrar_pbc_timeout(reg); + + // TODO: snake to check, no sys_untimeout now, by wujg +// sys_untimeout(wps_registrar_pbc_timeout, reg); + + return 1; + } else if (reg->selected_registrar) { +#ifdef CONFIG_WPS_PIN + + /* PIN Method */ + wpa_printf(MSG_DEBUG, "WPS: PIN is set - cancelling it"); + wps_registrar_pin_completed(reg); + wps_registrar_invalidate_wildcard_pin(reg, NULL, 0); + return 1; +#endif + } + return 0; +} + + +/** + * wps_registrar_probe_req_rx - Notify Registrar of Probe Request + * @reg: Registrar data from wps_registrar_init() + * @addr: MAC address of the Probe Request sender + * @wps_data: WPS IE contents + * + * This function is called on an AP when a Probe Request with WPS IE is + * received. This is used to track PBC mode use and to detect possible overlap + * situation with other WPS APs. + */ +void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr, + const struct wpabuf *wps_data, + int p2p_wildcard) +{ + struct wps_parse_attr attr; + int skip_add = 0; + + wpa_hexdump_buf(MSG_MSGDUMP, + "WPS: Probe Request with WPS data received", + wps_data); + + if (wps_parse_msg(wps_data, &attr) < 0) + return; + + if (attr.config_methods == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Config Methods attribute in " + "Probe Request"); + return; + } + + if (attr.dev_password_id == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Device Password Id attribute " + "in Probe Request"); + return; + } + + if (reg->enrollee_seen_cb && attr.uuid_e && + attr.primary_dev_type && attr.request_type && !p2p_wildcard) { + char *dev_name = NULL; + if (attr.dev_name) { + dev_name = (char *)os_zalloc(attr.dev_name_len + 1); + if (dev_name) { + os_memcpy(dev_name, attr.dev_name, + attr.dev_name_len); + } + } + reg->enrollee_seen_cb(reg->cb_ctx, addr, attr.uuid_e, + attr.primary_dev_type, + WPA_GET_BE16(attr.config_methods), + WPA_GET_BE16(attr.dev_password_id), + *attr.request_type, dev_name); + os_free(dev_name); + } + + if (WPA_GET_BE16(attr.dev_password_id) != DEV_PW_PUSHBUTTON) + return; /* Not PBC */ + + wpa_printf(MSG_DEBUG, "WPS: Probe Request for PBC received from " + MACSTR, MAC2STR(addr)); + if (attr.uuid_e == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Probe Request WPS IE: No " + "UUID-E included"); + return; + } + wpa_hexdump(MSG_DEBUG, "WPS: UUID-E from Probe Request", attr.uuid_e, + WPS_UUID_LEN); + +#ifdef WPS_WORKAROUNDS + if (reg->pbc_ignore_start.sec && + os_memcmp(attr.uuid_e, reg->pbc_ignore_uuid, WPS_UUID_LEN) == 0) { + struct os_time now, dur; + os_get_time(&now); + os_time_sub(&now, ®->pbc_ignore_start, &dur); + if (dur.sec >= 0 && dur.sec < 5) { + wpa_printf(MSG_DEBUG, "WPS: Ignore PBC activation " + "based on Probe Request from the Enrollee " + "that just completed PBC provisioning"); + skip_add = 1; + } else + reg->pbc_ignore_start.sec = 0; + } +#endif /* WPS_WORKAROUNDS */ + + if (!skip_add) + wps_registrar_add_pbc_session(reg, addr, attr.uuid_e); + if (wps_registrar_pbc_overlap(reg, addr, attr.uuid_e)) { + wpa_printf(MSG_DEBUG, "WPS: PBC session overlap detected"); + reg->force_pbc_overlap = 1; + wps_pbc_overlap_event(reg->wps); + } +} + + +static int wps_cb_new_psk(struct wps_registrar *reg, const u8 *mac_addr, + const u8 *psk, size_t psk_len) +{ + if (reg->new_psk_cb == NULL) + return 0; + + return reg->new_psk_cb(reg->cb_ctx, mac_addr, psk, psk_len); +} + +#ifdef CONFIG_WPS_PIN + +static void wps_cb_pin_needed(struct wps_registrar *reg, const u8 *uuid_e, + const struct wps_device_data *dev) +{ + if (reg->pin_needed_cb == NULL) + return; + + reg->pin_needed_cb(reg->cb_ctx, uuid_e, dev); +} +#endif + +static void wps_cb_reg_success(struct wps_registrar *reg, const u8 *mac_addr, + const u8 *uuid_e, const u8 *dev_pw, + size_t dev_pw_len) +{ + if (reg->reg_success_cb == NULL) + return; + + reg->reg_success_cb(reg->cb_ctx, mac_addr, uuid_e, dev_pw, dev_pw_len); +} + + +static int wps_cb_set_ie(struct wps_registrar *reg, struct wpabuf *beacon_ie, + struct wpabuf *probe_resp_ie) +{ + return reg->set_ie_cb(reg->cb_ctx, beacon_ie, probe_resp_ie); +} + + +static void wps_cb_set_sel_reg(struct wps_registrar *reg) +{ + u16 methods = 0; + if (reg->set_sel_reg_cb == NULL) + return; + + if (reg->selected_registrar) { + methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; +#ifdef CONFIG_WPS2 + methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON | + WPS_CONFIG_PHY_PUSHBUTTON); +#endif /* CONFIG_WPS2 */ + if (reg->pbc) + wps_set_pushbutton(&methods, reg->wps->config_methods); + } + + wpa_printf(MSG_DEBUG, "WPS: wps_cb_set_sel_reg: sel_reg=%d " + "config_methods=0x%x pbc=%d methods=0x%x", + reg->selected_registrar, reg->wps->config_methods, + reg->pbc, methods); + + reg->set_sel_reg_cb(reg->cb_ctx, reg->selected_registrar, + reg->pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT, + methods); +} + + +static int wps_set_ie(struct wps_registrar *reg) +{ + struct wpabuf *beacon; + struct wpabuf *probe; + const u8 *auth_macs; + size_t count; + size_t vendor_len = 0; + int i; + + if (reg->set_ie_cb == NULL) + return 0; + + for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) { + if (reg->wps->dev.vendor_ext[i]) { + vendor_len += 2 + 2; + vendor_len += wpabuf_len(reg->wps->dev.vendor_ext[i]); + } + } + + beacon = wpabuf_alloc(400 + vendor_len); + if (beacon == NULL) + return -1; + probe = wpabuf_alloc(500 + vendor_len); + if (probe == NULL) { + wpabuf_free(beacon); + return -1; + } + + auth_macs = wps_authorized_macs(reg, &count); + + wpa_printf(MSG_DEBUG, "WPS: Build Beacon IEs"); + + if (wps_build_version(beacon) || + wps_build_wps_state(reg->wps, beacon) || + wps_build_ap_setup_locked(reg->wps, beacon) || + wps_build_selected_registrar(reg, beacon) || + wps_build_sel_reg_dev_password_id(reg, beacon) || + wps_build_sel_reg_config_methods(reg, beacon) || + wps_build_sel_pbc_reg_uuid_e(reg, beacon) || + (reg->dualband && wps_build_rf_bands(®->wps->dev, beacon)) || + wps_build_wfa_ext(beacon, 0, auth_macs, count) || + wps_build_vendor_ext(®->wps->dev, beacon)) { + wpabuf_free(beacon); + wpabuf_free(probe); + return -1; + } + +#ifdef CONFIG_P2P + if (wps_build_dev_name(®->wps->dev, beacon) || + wps_build_primary_dev_type(®->wps->dev, beacon)) { + wpabuf_free(beacon); + wpabuf_free(probe); + return -1; + } +#endif /* CONFIG_P2P */ + + wpa_printf(MSG_DEBUG, "WPS: Build Probe Response IEs"); + + if (wps_build_version(probe) || + wps_build_wps_state(reg->wps, probe) || + wps_build_ap_setup_locked(reg->wps, probe) || + wps_build_selected_registrar(reg, probe) || + wps_build_sel_reg_dev_password_id(reg, probe) || + wps_build_sel_reg_config_methods(reg, probe) || + wps_build_resp_type(probe, reg->wps->ap ? WPS_RESP_AP : + WPS_RESP_REGISTRAR) || + wps_build_uuid_e(probe, reg->wps->uuid) || + wps_build_device_attrs(®->wps->dev, probe) || + wps_build_probe_config_methods(reg, probe) || + (reg->dualband && wps_build_rf_bands(®->wps->dev, probe)) || + wps_build_wfa_ext(probe, 0, auth_macs, count) || + wps_build_vendor_ext(®->wps->dev, probe)) { + wpabuf_free(beacon); + wpabuf_free(probe); + return -1; + } + + beacon = wps_ie_encapsulate(beacon); + probe = wps_ie_encapsulate(probe); + + if (!beacon || !probe) { + wpabuf_free(beacon); + wpabuf_free(probe); + return -1; + } + + if (reg->static_wep_only) { + /* + * Windows XP and Vista clients can get confused about + * EAP-Identity/Request when they probe the network with + * EAPOL-Start. In such a case, they may assume the network is + * using IEEE 802.1X and prompt user for a certificate while + * the correct (non-WPS) behavior would be to ask for the + * static WEP key. As a workaround, use Microsoft Provisioning + * IE to advertise that legacy 802.1X is not supported. + */ + const u8 ms_wps[7] = { + WLAN_EID_VENDOR_SPECIFIC, 5, + /* Microsoft Provisioning IE (00:50:f2:5) */ + 0x00, 0x50, 0xf2, 5, + 0x00 /* no legacy 802.1X or MS WPS */ + }; + wpa_printf(MSG_DEBUG, "WPS: Add Microsoft Provisioning IE " + "into Beacon/Probe Response frames"); + wpabuf_put_data(beacon, ms_wps, sizeof(ms_wps)); + wpabuf_put_data(probe, ms_wps, sizeof(ms_wps)); + } + + return wps_cb_set_ie(reg, beacon, probe); +} + + +static int wps_get_dev_password(struct wps_data *wps) +{ + const u8 *pin; + size_t pin_len = 0; + + os_free(wps->dev_password); + wps->dev_password = NULL; + + if (wps->pbc) { + wpa_printf(MSG_DEBUG, "WPS: Use default PIN for PBC"); + pin = (const u8 *) "00000000"; + pin_len = 8; +#ifdef CONFIG_WPS_NFC + } else if (wps->nfc_pw_token) { + wpa_printf(MSG_DEBUG, "WPS: Use OOB Device Password from NFC " + "Password Token"); + pin = wps->nfc_pw_token->dev_pw; + pin_len = wps->nfc_pw_token->dev_pw_len; +#endif /* CONFIG_WPS_NFC */ + } else { +#ifdef CONFIG_WPS_PIN + + pin = wps_registrar_get_pin(wps->wps->registrar, wps->uuid_e, + &pin_len); + } + if (pin == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Device Password available for " + "the Enrollee"); + wps_cb_pin_needed(wps->wps->registrar, wps->uuid_e, + &wps->peer_dev); + return -1; +#endif + } + + wps->dev_password = (u8 *)os_malloc(pin_len); + if (wps->dev_password == NULL) + return -1; + os_memcpy(wps->dev_password, pin, pin_len); + wps->dev_password_len = pin_len; + + return 0; +} + + +static int wps_build_uuid_r(struct wps_data *wps, struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS: * UUID-R"); + wpabuf_put_be16(msg, ATTR_UUID_R); + wpabuf_put_be16(msg, WPS_UUID_LEN); + wpabuf_put_data(msg, wps->uuid_r, WPS_UUID_LEN); + return 0; +} + + +static int wps_build_r_hash(struct wps_data *wps, struct wpabuf *msg) +{ + u8 *hash; + const u8 *addr[4]; + size_t len[4]; + + if (random_get_bytes(wps->snonce, 2 * WPS_SECRET_NONCE_LEN) < 0) + return -1; + wpa_hexdump(MSG_DEBUG, "WPS: R-S1", wps->snonce, WPS_SECRET_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "WPS: R-S2", + wps->snonce + WPS_SECRET_NONCE_LEN, WPS_SECRET_NONCE_LEN); + + if (wps->dh_pubkey_e == NULL || wps->dh_pubkey_r == NULL) { + wpa_printf(MSG_DEBUG, "WPS: DH public keys not available for " + "R-Hash derivation"); + return -1; + } + + wpa_printf(MSG_DEBUG, "WPS: * R-Hash1"); + wpabuf_put_be16(msg, ATTR_R_HASH1); + wpabuf_put_be16(msg, SHA256_MAC_LEN); + hash = wpabuf_put(msg, SHA256_MAC_LEN); + /* R-Hash1 = HMAC_AuthKey(R-S1 || PSK1 || PK_E || PK_R) */ + addr[0] = wps->snonce; + len[0] = WPS_SECRET_NONCE_LEN; + addr[1] = wps->psk1; + len[1] = WPS_PSK_LEN; + addr[2] = wpabuf_head(wps->dh_pubkey_e); + len[2] = wpabuf_len(wps->dh_pubkey_e); + addr[3] = wpabuf_head(wps->dh_pubkey_r); + len[3] = wpabuf_len(wps->dh_pubkey_r); + if (wps_crypto_funcs.hmac_sha256_vector) { + wps_crypto_funcs.hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, (int *)len, hash); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register hmac_sha256_vector function!\r\n", __FUNCTION__); + return -1; + } + wpa_hexdump(MSG_DEBUG, "WPS: R-Hash1", hash, SHA256_MAC_LEN); + + wpa_printf(MSG_DEBUG, "WPS: * R-Hash2"); + wpabuf_put_be16(msg, ATTR_R_HASH2); + wpabuf_put_be16(msg, SHA256_MAC_LEN); + hash = wpabuf_put(msg, SHA256_MAC_LEN); + /* R-Hash2 = HMAC_AuthKey(R-S2 || PSK2 || PK_E || PK_R) */ + addr[0] = wps->snonce + WPS_SECRET_NONCE_LEN; + addr[1] = wps->psk2; + if (wps_crypto_funcs.hmac_sha256_vector) { + wps_crypto_funcs.hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, (int *)len, hash); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register hmac_sha256_vector function!\r\n", __FUNCTION__); + return -1; + } + wpa_hexdump(MSG_DEBUG, "WPS: R-Hash2", hash, SHA256_MAC_LEN); + + return 0; +} + + +static int wps_build_r_snonce1(struct wps_data *wps, struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS: * R-SNonce1"); + wpabuf_put_be16(msg, ATTR_R_SNONCE1); + wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); + wpabuf_put_data(msg, wps->snonce, WPS_SECRET_NONCE_LEN); + return 0; +} + + +static int wps_build_r_snonce2(struct wps_data *wps, struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS: * R-SNonce2"); + wpabuf_put_be16(msg, ATTR_R_SNONCE2); + wpabuf_put_be16(msg, WPS_SECRET_NONCE_LEN); + wpabuf_put_data(msg, wps->snonce + WPS_SECRET_NONCE_LEN, + WPS_SECRET_NONCE_LEN); + return 0; +} + + +static int wps_build_cred_network_idx(struct wpabuf *msg, + const struct wps_credential *cred) +{ + wpa_printf(MSG_DEBUG, "WPS: * Network Index (1)"); + wpabuf_put_be16(msg, ATTR_NETWORK_INDEX); + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, 1); + return 0; +} + + +static int wps_build_cred_ssid(struct wpabuf *msg, + const struct wps_credential *cred) +{ + wpa_printf(MSG_DEBUG, "WPS: * SSID"); + wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID for Credential", + cred->ssid, cred->ssid_len); + wpabuf_put_be16(msg, ATTR_SSID); + wpabuf_put_be16(msg, cred->ssid_len); + wpabuf_put_data(msg, cred->ssid, cred->ssid_len); + return 0; +} + + +static int wps_build_cred_auth_type(struct wpabuf *msg, + const struct wps_credential *cred) +{ + wpa_printf(MSG_DEBUG, "WPS: * Authentication Type (0x%x)", + cred->auth_type); + wpabuf_put_be16(msg, ATTR_AUTH_TYPE); + wpabuf_put_be16(msg, 2); + wpabuf_put_be16(msg, cred->auth_type); + return 0; +} + + +static int wps_build_cred_encr_type(struct wpabuf *msg, + const struct wps_credential *cred) +{ + wpa_printf(MSG_DEBUG, "WPS: * Encryption Type (0x%x)", + cred->encr_type); + wpabuf_put_be16(msg, ATTR_ENCR_TYPE); + wpabuf_put_be16(msg, 2); + wpabuf_put_be16(msg, cred->encr_type); + return 0; +} + + +static int wps_build_cred_network_key(struct wpabuf *msg, + const struct wps_credential *cred) +{ + wpa_printf(MSG_DEBUG, "WPS: * Network Key (len=%d)", + (int) cred->key_len); + wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", + cred->key, cred->key_len); + wpabuf_put_be16(msg, ATTR_NETWORK_KEY); + wpabuf_put_be16(msg, cred->key_len); + wpabuf_put_data(msg, cred->key, cred->key_len); + return 0; +} + + +static int wps_build_cred_mac_addr(struct wpabuf *msg, + const struct wps_credential *cred) +{ + wpa_printf(MSG_DEBUG, "WPS: * MAC Address (" MACSTR ")", + MAC2STR(cred->mac_addr)); + wpabuf_put_be16(msg, ATTR_MAC_ADDR); + wpabuf_put_be16(msg, ETH_ALEN); + wpabuf_put_data(msg, cred->mac_addr, ETH_ALEN); + return 0; +} + + +static int wps_build_credential(struct wpabuf *msg, + const struct wps_credential *cred) +{ + if (wps_build_cred_network_idx(msg, cred) || + wps_build_cred_ssid(msg, cred) || + wps_build_cred_auth_type(msg, cred) || + wps_build_cred_encr_type(msg, cred) || + wps_build_cred_network_key(msg, cred) || + wps_build_cred_mac_addr(msg, cred)) + return -1; + return 0; +} + + +int wps_build_credential_wrap(struct wpabuf *msg, + const struct wps_credential *cred) +{ + struct wpabuf *wbuf; + wbuf = wpabuf_alloc(200); + if (wbuf == NULL) + return -1; + if (wps_build_credential(wbuf, cred)) { + wpabuf_free(wbuf); + return -1; + } + wpabuf_put_be16(msg, ATTR_CRED); + wpabuf_put_be16(msg, wpabuf_len(wbuf)); + wpabuf_put_buf(msg, wbuf); + wpabuf_free(wbuf); + return 0; +} + + +int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) +{ + struct wpabuf *cred; + + if (wps->wps->registrar->skip_cred_build) + goto skip_cred_build; + + wpa_printf(MSG_DEBUG, "WPS: * Credential"); + if (wps->use_cred) { + os_memcpy(&wps->cred, wps->use_cred, sizeof(wps->cred)); + goto use_provided; + } + os_memset(&wps->cred, 0, sizeof(wps->cred)); + + os_memcpy(wps->cred.ssid, wps->wps->ssid, wps->wps->ssid_len); + wps->cred.ssid_len = wps->wps->ssid_len; + + /* Select the best authentication and encryption type */ + if (wps->auth_type & WPS_AUTH_WPA2PSK) + wps->auth_type = WPS_AUTH_WPA2PSK; + else if (wps->auth_type & WPS_AUTH_WPAPSK) + wps->auth_type = WPS_AUTH_WPAPSK; + else if (wps->auth_type & WPS_WIFI_AUTH_OPEN) + wps->auth_type = WPS_WIFI_AUTH_OPEN; + else if (wps->auth_type & WPS_AUTH_SHARED) + wps->auth_type = WPS_AUTH_SHARED; + else { + wpa_printf(MSG_DEBUG, "WPS: Unsupported auth_type 0x%x", + wps->auth_type); + return -1; + } + wps->cred.auth_type = wps->auth_type; + + if (wps->auth_type == WPS_AUTH_WPA2PSK || + wps->auth_type == WPS_AUTH_WPAPSK) { + if (wps->encr_type & WPS_ENCR_AES) + wps->encr_type = WPS_ENCR_AES; + else if (wps->encr_type & WPS_ENCR_TKIP) + wps->encr_type = WPS_ENCR_TKIP; + else { + wpa_printf(MSG_DEBUG, "WPS: No suitable encryption " + "type for WPA/WPA2"); + return -1; + } + } else { + if (wps->encr_type & WPS_ENCR_WEP) + wps->encr_type = WPS_ENCR_WEP; + else if (wps->encr_type & WPS_ENCR_NONE) + wps->encr_type = WPS_ENCR_NONE; + else { + wpa_printf(MSG_DEBUG, "WPS: No suitable encryption " + "type for non-WPA/WPA2 mode"); + return -1; + } + } + wps->cred.encr_type = wps->encr_type; + /* + * Set MAC address in the Credential to be the Enrollee's MAC address + */ + os_memcpy(wps->cred.mac_addr, wps->mac_addr_e, ETH_ALEN); + + if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->wps->ap && + !wps->wps->registrar->disable_auto_conf) { + u8 r[16]; + /* Generate a random passphrase */ + if (random_get_bytes(r, sizeof(r)) < 0) + return -1; + os_free(wps->new_psk); + //wps->new_psk = base64_encode(r, sizeof(r), &wps->new_psk_len); + if (wps->new_psk == NULL) + return -1; + wps->new_psk_len--; /* remove newline */ + while (wps->new_psk_len && + wps->new_psk[wps->new_psk_len - 1] == '=') + wps->new_psk_len--; + wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: Generated passphrase", + wps->new_psk, wps->new_psk_len); + os_memcpy(wps->cred.key, wps->new_psk, wps->new_psk_len); + wps->cred.key_len = wps->new_psk_len; + } else if (wps->use_psk_key && wps->wps->psk_set) { + char hex[65]; + wpa_printf(MSG_DEBUG, "WPS: Use PSK format for Network Key"); + //wpa_snprintf_hex(hex, sizeof(hex), wps->wps->psk, 32); + os_memcpy(wps->cred.key, hex, 32 * 2); + wps->cred.key_len = 32 * 2; + } else if (wps->wps->network_key) { + os_memcpy(wps->cred.key, wps->wps->network_key, + wps->wps->network_key_len); + wps->cred.key_len = wps->wps->network_key_len; + } else if (wps->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) { + char hex[65]; + /* Generate a random per-device PSK */ + os_free(wps->new_psk); + wps->new_psk_len = 32; + wps->new_psk = (u8 *)os_malloc(wps->new_psk_len); + if (wps->new_psk == NULL) + return -1; + if (random_get_bytes(wps->new_psk, wps->new_psk_len) < 0) { + os_free(wps->new_psk); + wps->new_psk = NULL; + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK", + wps->new_psk, wps->new_psk_len); + //wpa_snprintf_hex(hex, sizeof(hex), wps->new_psk, + // wps->new_psk_len); + os_memcpy(wps->cred.key, hex, wps->new_psk_len * 2); + wps->cred.key_len = wps->new_psk_len * 2; + } + +use_provided: +#ifdef CONFIG_WPS_TESTING + if (wps_testing_dummy_cred) + cred = wpabuf_alloc(200); + else + cred = NULL; + if (cred) { + struct wps_credential dummy; + wpa_printf(MSG_DEBUG, "WPS: Add dummy credential"); + os_memset(&dummy, 0, sizeof(dummy)); + os_memcpy(dummy.ssid, "dummy", 5); + dummy.ssid_len = 5; + dummy.auth_type = WPS_AUTH_WPA2PSK; + dummy.encr_type = WPS_ENCR_AES; + os_memcpy(dummy.key, "dummy psk", 9); + dummy.key_len = 9; + os_memcpy(dummy.mac_addr, wps->mac_addr_e, ETH_ALEN); + wps_build_credential(cred, &dummy); + wpa_hexdump_buf(MSG_DEBUG, "WPS: Dummy Credential", cred); + + wpabuf_put_be16(msg, ATTR_CRED); + wpabuf_put_be16(msg, wpabuf_len(cred)); + wpabuf_put_buf(msg, cred); + + wpabuf_free(cred); + } +#endif /* CONFIG_WPS_TESTING */ + + cred = wpabuf_alloc(200); + if (cred == NULL) + return -1; + + if (wps_build_credential(cred, &wps->cred)) { + wpabuf_free(cred); + return -1; + } + + wpabuf_put_be16(msg, ATTR_CRED); + wpabuf_put_be16(msg, wpabuf_len(cred)); + wpabuf_put_buf(msg, cred); + wpabuf_free(cred); + +skip_cred_build: + if (wps->wps->registrar->extra_cred) { + wpa_printf(MSG_DEBUG, "WPS: * Credential (pre-configured)"); + wpabuf_put_buf(msg, wps->wps->registrar->extra_cred); + } + + return 0; +} + + +static int wps_build_ap_settings(struct wps_data *wps, struct wpabuf *msg) +{ + wpa_printf(MSG_DEBUG, "WPS: * AP Settings"); + + if (wps_build_credential(msg, &wps->cred)) + return -1; + + return 0; +} + + +static struct wpabuf * wps_build_ap_cred(struct wps_data *wps) +{ + struct wpabuf *msg, *plain; + + msg = wpabuf_alloc(1000); + if (msg == NULL) + return NULL; + + plain = wpabuf_alloc(200); + if (plain == NULL) { + wpabuf_free(msg); + return NULL; + } + + if (wps_build_ap_settings(wps, plain)) { + wpabuf_free(plain); + wpabuf_free(msg); + return NULL; + } + + wpabuf_put_be16(msg, ATTR_CRED); + wpabuf_put_be16(msg, wpabuf_len(plain)); + wpabuf_put_buf(msg, plain); + wpabuf_free(plain); + + return msg; +} + + +static struct wpabuf * wps_build_m2(struct wps_data *wps) +{ + struct wpabuf *msg; + + if (random_get_bytes(wps->nonce_r, WPS_NONCE_LEN) < 0) + return NULL; + wpa_hexdump(MSG_DEBUG, "WPS: Registrar Nonce", + wps->nonce_r, WPS_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "WPS: UUID-R", wps->uuid_r, WPS_UUID_LEN); + + wpa_printf(MSG_DEBUG, "WPS: Building Message M2"); + msg = wpabuf_alloc(1000); + if (msg == NULL) + return NULL; + + if (wps_build_version(msg) || + wps_build_msg_type(msg, WPS_M2) || + wps_build_enrollee_nonce(wps, msg) || + wps_build_registrar_nonce(wps, msg) || + wps_build_uuid_r(wps, msg) || + wps_build_public_key(wps, msg, WPS_CALC_KEY_NORMAL) || + wps_derive_keys(wps) || + wps_build_auth_type_flags(wps, msg) || + wps_build_encr_type_flags(wps, msg) || + wps_build_conn_type_flags(wps, msg) || + wps_build_config_methods_r(wps->wps->registrar, msg) || + wps_build_device_attrs(&wps->wps->dev, msg) || + wps_build_rf_bands(&wps->wps->dev, msg) || + wps_build_assoc_state(wps, msg) || + wps_build_config_error(msg, WPS_CFG_NO_ERROR) || + wps_build_dev_password_id(msg, wps->dev_pw_id) || + wps_build_os_version(&wps->wps->dev, msg) || + wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_authenticator(wps, msg)) { + wpabuf_free(msg); + return NULL; + } + + wps->int_reg = 1; + wps->state = RECV_M3; + return msg; +} + + +static struct wpabuf * wps_build_m2d(struct wps_data *wps) +{ + struct wpabuf *msg; + u16 err = wps->config_error; + + wpa_printf(MSG_DEBUG, "WPS: Building Message M2D"); + msg = wpabuf_alloc(1000); + if (msg == NULL) + return NULL; + + if (wps->wps->ap && wps->wps->ap_setup_locked && + err == WPS_CFG_NO_ERROR) + err = WPS_CFG_SETUP_LOCKED; + + if (wps_build_version(msg) || + wps_build_msg_type(msg, WPS_M2D) || + wps_build_enrollee_nonce(wps, msg) || + wps_build_registrar_nonce(wps, msg) || + wps_build_uuid_r(wps, msg) || + wps_build_auth_type_flags(wps, msg) || + wps_build_encr_type_flags(wps, msg) || + wps_build_conn_type_flags(wps, msg) || + wps_build_config_methods_r(wps->wps->registrar, msg) || + wps_build_device_attrs(&wps->wps->dev, msg) || + wps_build_rf_bands(&wps->wps->dev, msg) || + wps_build_assoc_state(wps, msg) || + wps_build_config_error(msg, err) || + wps_build_os_version(&wps->wps->dev, msg) || + wps_build_wfa_ext(msg, 0, NULL, 0)) { + wpabuf_free(msg); + return NULL; + } + + wps->state = RECV_M2D_ACK; + return msg; +} + + +static struct wpabuf * wps_build_m4(struct wps_data *wps) +{ + struct wpabuf *msg, *plain; + + wpa_printf(MSG_DEBUG, "WPS: Building Message M4"); + + wps_derive_psk(wps, wps->dev_password, wps->dev_password_len); + + plain = wpabuf_alloc(200); + if (plain == NULL) + return NULL; + + msg = wpabuf_alloc(1000); + if (msg == NULL) { + wpabuf_free(plain); + return NULL; + } + + if (wps_build_version(msg) || + wps_build_msg_type(msg, WPS_M4) || + wps_build_enrollee_nonce(wps, msg) || + wps_build_r_hash(wps, msg) || + wps_build_r_snonce1(wps, plain) || + wps_build_key_wrap_auth(wps, plain) || + wps_build_encr_settings(wps, msg, plain) || + wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_authenticator(wps, msg)) { + wpabuf_free(plain); + wpabuf_free(msg); + return NULL; + } + wpabuf_free(plain); + + wps->state = RECV_M5; + return msg; +} + + +static struct wpabuf * wps_build_m6(struct wps_data *wps) +{ + struct wpabuf *msg, *plain; + + wpa_printf(MSG_DEBUG, "WPS: Building Message M6"); + + plain = wpabuf_alloc(200); + if (plain == NULL) + return NULL; + + msg = wpabuf_alloc(1000); + if (msg == NULL) { + wpabuf_free(plain); + return NULL; + } + + if (wps_build_version(msg) || + wps_build_msg_type(msg, WPS_M6) || + wps_build_enrollee_nonce(wps, msg) || + wps_build_r_snonce2(wps, plain) || + wps_build_key_wrap_auth(wps, plain) || + wps_build_encr_settings(wps, msg, plain) || + wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_authenticator(wps, msg)) { + wpabuf_free(plain); + wpabuf_free(msg); + return NULL; + } + wpabuf_free(plain); + + wps->wps_pin_revealed = 1; + wps->state = RECV_M7; + return msg; +} + + +static struct wpabuf * wps_build_m8(struct wps_data *wps) +{ + struct wpabuf *msg, *plain; + + wpa_printf(MSG_DEBUG, "WPS: Building Message M8"); + + plain = wpabuf_alloc(500); + if (plain == NULL) + return NULL; + + msg = wpabuf_alloc(1000); + if (msg == NULL) { + wpabuf_free(plain); + return NULL; + } + + if (wps_build_version(msg) || + wps_build_msg_type(msg, WPS_M8) || + wps_build_enrollee_nonce(wps, msg) || + ((wps->wps->ap || wps->er) && wps_build_cred(wps, plain)) || + (!wps->wps->ap && !wps->er && wps_build_ap_settings(wps, plain)) || + wps_build_key_wrap_auth(wps, plain) || + wps_build_encr_settings(wps, msg, plain) || + wps_build_wfa_ext(msg, 0, NULL, 0) || + wps_build_authenticator(wps, msg)) { + wpabuf_free(plain); + wpabuf_free(msg); + return NULL; + } + wpabuf_free(plain); + + wps->state = RECV_DONE; + return msg; +} + + +struct wpabuf * wps_registrar_get_msg(struct wps_data *wps, + enum wsc_op_code *op_code) +{ + struct wpabuf *msg; + +#ifdef CONFIG_WPS_UPNP + if (!wps->int_reg && wps->wps->wps_upnp) { + struct upnp_pending_message *p, *prev = NULL; + if (wps->ext_reg > 1) + wps_registrar_free_pending_m2(wps->wps); + p = wps->wps->upnp_msgs; + /* TODO: check pending message MAC address */ + while (p && p->next) { + prev = p; + p = p->next; + } + if (p) { + wpa_printf(MSG_DEBUG, "WPS: Use pending message from " + "UPnP"); + if (prev) + prev->next = NULL; + else + wps->wps->upnp_msgs = NULL; + msg = p->msg; + switch (p->type) { + case WPS_WSC_ACK: + *op_code = WSC_ACK; + break; + case WPS_WSC_NACK: + *op_code = WSC_NACK; + break; + default: + *op_code = WSC_MSG; + break; + } + os_free(p); + if (wps->ext_reg == 0) + wps->ext_reg = 1; + return msg; + } + } + if (wps->ext_reg) { + wpa_printf(MSG_DEBUG, "WPS: Using external Registrar, but no " + "pending message available"); + return NULL; + } +#endif /* CONFIG_WPS_UPNP */ + + switch (wps->state) { + case SEND_M2: + if (wps_get_dev_password(wps) < 0) + msg = wps_build_m2d(wps); + else + msg = wps_build_m2(wps); + *op_code = WSC_MSG; + break; + case SEND_M2D: + msg = wps_build_m2d(wps); + *op_code = WSC_MSG; + break; + case SEND_M4: + msg = wps_build_m4(wps); + *op_code = WSC_MSG; + break; + case SEND_M6: + msg = wps_build_m6(wps); + *op_code = WSC_MSG; + break; + case SEND_M8: + msg = wps_build_m8(wps); + *op_code = WSC_MSG; + break; + case RECV_DONE: + msg = wps_build_wsc_ack(wps); + *op_code = WSC_ACK; + break; + case SEND_WSC_NACK: + msg = wps_build_wsc_nack(wps); + *op_code = WSC_NACK; + break; + default: + wpa_printf(MSG_DEBUG, "WPS: Unsupported state %d for building " + "a message", wps->state); + msg = NULL; + break; + } + + if (*op_code == WSC_MSG && msg) { + /* Save a copy of the last message for Authenticator derivation + */ + wpabuf_free(wps->last_msg); + wps->last_msg = wpabuf_dup(msg); + } + + return msg; +} + + +static int wps_process_enrollee_nonce(struct wps_data *wps, const u8 *e_nonce) +{ + if (e_nonce == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Enrollee Nonce received"); + return -1; + } + + os_memcpy(wps->nonce_e, e_nonce, WPS_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "WPS: Enrollee Nonce", + wps->nonce_e, WPS_NONCE_LEN); + + return 0; +} + + +static int wps_process_registrar_nonce(struct wps_data *wps, const u8 *r_nonce) +{ + if (r_nonce == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Registrar Nonce received"); + return -1; + } + + if (os_memcmp(wps->nonce_r, r_nonce, WPS_NONCE_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Registrar Nonce received"); + return -1; + } + + return 0; +} + + +static int wps_process_uuid_e(struct wps_data *wps, const u8 *uuid_e) +{ + if (uuid_e == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No UUID-E received"); + return -1; + } + + os_memcpy(wps->uuid_e, uuid_e, WPS_UUID_LEN); + wpa_hexdump(MSG_DEBUG, "WPS: UUID-E", wps->uuid_e, WPS_UUID_LEN); + + return 0; +} + + +static int wps_process_dev_password_id(struct wps_data *wps, const u8 *pw_id) +{ + if (pw_id == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Device Password ID received"); + return -1; + } + + wps->dev_pw_id = WPA_GET_BE16(pw_id); + wpa_printf(MSG_DEBUG, "WPS: Device Password ID %d", wps->dev_pw_id); + + return 0; +} + + +static int wps_process_e_hash1(struct wps_data *wps, const u8 *e_hash1) +{ + if (e_hash1 == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No E-Hash1 received"); + return -1; + } + + os_memcpy(wps->peer_hash1, e_hash1, WPS_HASH_LEN); + wpa_hexdump(MSG_DEBUG, "WPS: E-Hash1", wps->peer_hash1, WPS_HASH_LEN); + + return 0; +} + + +static int wps_process_e_hash2(struct wps_data *wps, const u8 *e_hash2) +{ + if (e_hash2 == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No E-Hash2 received"); + return -1; + } + + os_memcpy(wps->peer_hash2, e_hash2, WPS_HASH_LEN); + wpa_hexdump(MSG_DEBUG, "WPS: E-Hash2", wps->peer_hash2, WPS_HASH_LEN); + + return 0; +} + + +static int wps_process_e_snonce1(struct wps_data *wps, const u8 *e_snonce1) +{ + u8 hash[SHA256_MAC_LEN]; + const u8 *addr[4]; + size_t len[4]; + + if (e_snonce1 == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No E-SNonce1 received"); + return -1; + } + + wpa_hexdump_key(MSG_DEBUG, "WPS: E-SNonce1", e_snonce1, + WPS_SECRET_NONCE_LEN); + + /* E-Hash1 = HMAC_AuthKey(E-S1 || PSK1 || PK_E || PK_R) */ + addr[0] = e_snonce1; + len[0] = WPS_SECRET_NONCE_LEN; + addr[1] = wps->psk1; + len[1] = WPS_PSK_LEN; + addr[2] = wpabuf_head(wps->dh_pubkey_e); + len[2] = wpabuf_len(wps->dh_pubkey_e); + addr[3] = wpabuf_head(wps->dh_pubkey_r); + len[3] = wpabuf_len(wps->dh_pubkey_r); + if (wps_crypto_funcs.hmac_sha256_vector) { + wps_crypto_funcs.hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, (int *)len, hash); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register hmac_sha256_vector function!\r\n", __FUNCTION__); + return -1; + } + if (os_memcmp(wps->peer_hash1, hash, WPS_HASH_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: E-Hash1 derived from E-S1 does " + "not match with the pre-committed value"); + wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; + wps_pwd_auth_fail_event(wps->wps, 0, 1); + return -1; + } + + wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the first " + "half of the device password"); + + return 0; +} + + +static int wps_process_e_snonce2(struct wps_data *wps, const u8 *e_snonce2) +{ + u8 hash[SHA256_MAC_LEN]; + const u8 *addr[4]; + size_t len[4]; + + if (e_snonce2 == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No E-SNonce2 received"); + return -1; + } + + wpa_hexdump_key(MSG_DEBUG, "WPS: E-SNonce2", e_snonce2, + WPS_SECRET_NONCE_LEN); + + /* E-Hash2 = HMAC_AuthKey(E-S2 || PSK2 || PK_E || PK_R) */ + addr[0] = e_snonce2; + len[0] = WPS_SECRET_NONCE_LEN; + addr[1] = wps->psk2; + len[1] = WPS_PSK_LEN; + addr[2] = wpabuf_head(wps->dh_pubkey_e); + len[2] = wpabuf_len(wps->dh_pubkey_e); + addr[3] = wpabuf_head(wps->dh_pubkey_r); + len[3] = wpabuf_len(wps->dh_pubkey_r); + + if (wps_crypto_funcs.hmac_sha256_vector) { + wps_crypto_funcs.hmac_sha256_vector(wps->authkey, WPS_AUTHKEY_LEN, 4, addr, (int *)len, hash); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register hmac_sha256_vector function!\r\n", __FUNCTION__); + return -1; + } + if (os_memcmp(wps->peer_hash2, hash, WPS_HASH_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: E-Hash2 derived from E-S2 does " + "not match with the pre-committed value"); +#ifdef CONFIG_WPS_PIN + wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e); +#endif + wps->config_error = WPS_CFG_DEV_PASSWORD_AUTH_FAILURE; + wps_pwd_auth_fail_event(wps->wps, 0, 2); + return -1; + } + + wpa_printf(MSG_DEBUG, "WPS: Enrollee proved knowledge of the second " + "half of the device password"); + wps->wps_pin_revealed = 0; +#ifdef CONFIG_WPS_PIN + wps_registrar_unlock_pin(wps->wps->registrar, wps->uuid_e); + + /* + * In case wildcard PIN is used and WPS handshake succeeds in the first + * attempt, wps_registrar_unlock_pin() would not free the PIN, so make + * sure the PIN gets invalidated here. + */ + wps_registrar_invalidate_pin(wps->wps->registrar, wps->uuid_e); +#endif + return 0; +} + + +static int wps_process_mac_addr(struct wps_data *wps, const u8 *mac_addr) +{ + if (mac_addr == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No MAC Address received"); + return -1; + } + + wpa_printf(MSG_DEBUG, "WPS: Enrollee MAC Address " MACSTR, + MAC2STR(mac_addr)); + os_memcpy(wps->mac_addr_e, mac_addr, ETH_ALEN); + os_memcpy(wps->peer_dev.mac_addr, mac_addr, ETH_ALEN); + + return 0; +} + + +static int wps_process_pubkey(struct wps_data *wps, const u8 *pk, + size_t pk_len) +{ + if (pk == NULL || pk_len == 0) { + wpa_printf(MSG_DEBUG, "WPS: No Public Key received"); + return -1; + } + + wpabuf_free(wps->dh_pubkey_e); + wps->dh_pubkey_e = wpabuf_alloc_copy(pk, pk_len); + if (wps->dh_pubkey_e == NULL) + return -1; + + return 0; +} + + +static int wps_process_auth_type_flags(struct wps_data *wps, const u8 *auth) +{ + u16 auth_types; + + if (auth == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Authentication Type flags " + "received"); + return -1; + } + + auth_types = WPA_GET_BE16(auth); + + wpa_printf(MSG_DEBUG, "WPS: Enrollee Authentication Type flags 0x%x", + auth_types); + wps->auth_type = wps->wps->auth_types & auth_types; + if (wps->auth_type == 0) { + wpa_printf(MSG_DEBUG, "WPS: No match in supported " + "authentication types (own 0x%x Enrollee 0x%x)", + wps->wps->auth_types, auth_types); +#ifdef WPS_WORKAROUNDS + /* + * Some deployed implementations seem to advertise incorrect + * information in this attribute. For example, Linksys WRT350N + * seems to have a byteorder bug that breaks this negotiation. + * In order to interoperate with existing implementations, + * assume that the Enrollee supports everything we do. + */ + wpa_printf(MSG_DEBUG, "WPS: Workaround - assume Enrollee " + "does not advertise supported authentication types " + "correctly"); + wps->auth_type = wps->wps->auth_types; +#else /* WPS_WORKAROUNDS */ + return -1; +#endif /* WPS_WORKAROUNDS */ + } + + return 0; +} + + +static int wps_process_encr_type_flags(struct wps_data *wps, const u8 *encr) +{ + u16 encr_types; + + if (encr == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Encryption Type flags " + "received"); + return -1; + } + + encr_types = WPA_GET_BE16(encr); + + wpa_printf(MSG_DEBUG, "WPS: Enrollee Encryption Type flags 0x%x", + encr_types); + wps->encr_type = wps->wps->encr_types & encr_types; + if (wps->encr_type == 0) { + wpa_printf(MSG_DEBUG, "WPS: No match in supported " + "encryption types (own 0x%x Enrollee 0x%x)", + wps->wps->encr_types, encr_types); +#ifdef WPS_WORKAROUNDS + /* + * Some deployed implementations seem to advertise incorrect + * information in this attribute. For example, Linksys WRT350N + * seems to have a byteorder bug that breaks this negotiation. + * In order to interoperate with existing implementations, + * assume that the Enrollee supports everything we do. + */ + wpa_printf(MSG_DEBUG, "WPS: Workaround - assume Enrollee " + "does not advertise supported encryption types " + "correctly"); + wps->encr_type = wps->wps->encr_types; +#else /* WPS_WORKAROUNDS */ + return -1; +#endif /* WPS_WORKAROUNDS */ + } + + return 0; +} + + +static int wps_process_conn_type_flags(struct wps_data *wps, const u8 *conn) +{ + if (conn == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Connection Type flags " + "received"); + return -1; + } + + wpa_printf(MSG_DEBUG, "WPS: Enrollee Connection Type flags 0x%x", + *conn); + + return 0; +} + + +static int wps_process_config_methods(struct wps_data *wps, const u8 *methods) +{ + u16 m; + + if (methods == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Config Methods received"); + return -1; + } + + m = WPA_GET_BE16(methods); + + wpa_printf(MSG_DEBUG, "WPS: Enrollee Config Methods 0x%x" + "%s%s%s%s%s%s%s%s%s", m, + m & WPS_CONFIG_USBA ? " [USBA]" : "", + m & WPS_CONFIG_ETHERNET ? " [Ethernet]" : "", + m & WPS_CONFIG_LABEL ? " [Label]" : "", + m & WPS_CONFIG_DISPLAY ? " [Display]" : "", + m & WPS_CONFIG_EXT_NFC_TOKEN ? " [Ext NFC Token]" : "", + m & WPS_CONFIG_INT_NFC_TOKEN ? " [Int NFC Token]" : "", + m & WPS_CONFIG_NFC_INTERFACE ? " [NFC]" : "", + m & WPS_CONFIG_PUSHBUTTON ? " [PBC]" : "", + m & WPS_CONFIG_KEYPAD ? " [Keypad]" : ""); + + if (!(m & WPS_CONFIG_DISPLAY) && !wps->use_psk_key) { + /* + * The Enrollee does not have a display so it is unlikely to be + * able to show the passphrase to a user and as such, could + * benefit from receiving PSK to reduce key derivation time. + */ + wpa_printf(MSG_DEBUG, "WPS: Prefer PSK format key due to " + "Enrollee not supporting display"); + wps->use_psk_key = 1; + } + + return 0; +} + + +static int wps_process_wps_state(struct wps_data *wps, const u8 *state) +{ + if (state == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Wi-Fi Protected Setup State " + "received"); + return -1; + } + + wpa_printf(MSG_DEBUG, "WPS: Enrollee Wi-Fi Protected Setup State %d", + *state); + + return 0; +} + + +static int wps_process_assoc_state(struct wps_data *wps, const u8 *assoc) +{ + u16 a; + + if (assoc == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Association State received"); + return -1; + } + + a = WPA_GET_BE16(assoc); + wpa_printf(MSG_DEBUG, "WPS: Enrollee Association State %d", a); + + return 0; +} + + +static int wps_process_config_error(struct wps_data *wps, const u8 *err) +{ + u16 e; + + if (err == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Configuration Error received"); + return -1; + } + + e = WPA_GET_BE16(err); + wpa_printf(MSG_DEBUG, "WPS: Enrollee Configuration Error %d", e); + + return 0; +} + + +static int wps_registrar_p2p_dev_addr_match(struct wps_data *wps) +{ +#ifdef CONFIG_P2P + struct wps_registrar *reg = wps->wps->registrar; + + if (is_zero_ether_addr(reg->p2p_dev_addr)) + return 1; /* no filtering in use */ + + if (os_memcmp(reg->p2p_dev_addr, wps->p2p_dev_addr, ETH_ALEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: No match on P2P Device Address " + "filtering for PBC: expected " MACSTR " was " + MACSTR " - indicate PBC session overlap", + MAC2STR(reg->p2p_dev_addr), + MAC2STR(wps->p2p_dev_addr)); + return 0; + } +#endif /* CONFIG_P2P */ + return 1; +} + + +static int wps_registrar_skip_overlap(struct wps_data *wps) +{ +#ifdef CONFIG_P2P + struct wps_registrar *reg = wps->wps->registrar; + + if (is_zero_ether_addr(reg->p2p_dev_addr)) + return 0; /* no specific Enrollee selected */ + + if (os_memcmp(reg->p2p_dev_addr, wps->p2p_dev_addr, ETH_ALEN) == 0) { + wpa_printf(MSG_DEBUG, "WPS: Skip PBC overlap due to selected " + "Enrollee match"); + return 1; + } +#endif /* CONFIG_P2P */ + return 0; +} + + +static enum wps_process_res wps_process_m1(struct wps_data *wps, + struct wps_parse_attr *attr) +{ + wpa_printf(MSG_DEBUG, "WPS: Received M1"); + + if (wps->state != RECV_M1) { + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + "receiving M1", wps->state); + return WPS_FAILURE; + } + + if (wps_process_uuid_e(wps, attr->uuid_e) || + wps_process_mac_addr(wps, attr->mac_addr) || + wps_process_enrollee_nonce(wps, attr->enrollee_nonce) || + wps_process_pubkey(wps, attr->public_key, attr->public_key_len) || + wps_process_auth_type_flags(wps, attr->auth_type_flags) || + wps_process_encr_type_flags(wps, attr->encr_type_flags) || + wps_process_conn_type_flags(wps, attr->conn_type_flags) || + wps_process_config_methods(wps, attr->config_methods) || + wps_process_wps_state(wps, attr->wps_state) || + wps_process_device_attrs(&wps->peer_dev, attr) || + wps_process_rf_bands(&wps->peer_dev, attr->rf_bands) || + wps_process_assoc_state(wps, attr->assoc_state) || + wps_process_dev_password_id(wps, attr->dev_password_id) || + wps_process_config_error(wps, attr->config_error) || + wps_process_os_version(&wps->peer_dev, attr->os_version)) + return WPS_FAILURE; + + if (wps->dev_pw_id < 0x10 && + wps->dev_pw_id != DEV_PW_DEFAULT && + wps->dev_pw_id != DEV_PW_USER_SPECIFIED && + wps->dev_pw_id != DEV_PW_MACHINE_SPECIFIED && + wps->dev_pw_id != DEV_PW_REGISTRAR_SPECIFIED && + (wps->dev_pw_id != DEV_PW_PUSHBUTTON || + !wps->wps->registrar->pbc)) { + wpa_printf(MSG_DEBUG, "WPS: Unsupported Device Password ID %d", + wps->dev_pw_id); + wps->state = SEND_M2D; + return WPS_CONTINUE; + } + +#ifdef CONFIG_WPS_NFC + if (wps->dev_pw_id >= 0x10) { + struct wps_nfc_pw_token *token; + const u8 *addr[1]; + u8 hash[WPS_HASH_LEN]; + + token = wps_get_nfc_pw_token( + &wps->wps->registrar->nfc_pw_tokens, wps->dev_pw_id); + if (token) { + wpa_printf(MSG_DEBUG, "WPS: Found matching NFC " + "Password Token"); + dl_list_del(&token->list); + wps->nfc_pw_token = token; + + addr[0] = attr->public_key; + if (wps_crypto_funcs.sha256_vector) { + wps_crypto_funcs.sha256_vector(1, addr, &attr->public_key_len, hash); + } else { + wpa_printf(MSG_ERROR, "In function %s, fail to register sha256_vector function!\r\n", __FUNCTION__); + return WPS_FAILURE; + } + if (os_memcmp(hash, wps->nfc_pw_token->pubkey_hash, + WPS_OOB_PUBKEY_HASH_LEN) != 0) { + wpa_printf(MSG_ERROR, "WPS: Public Key hash " + "mismatch"); + return WPS_FAILURE; + } + } + } +#endif /* CONFIG_WPS_NFC */ + + if (wps->dev_pw_id == DEV_PW_PUSHBUTTON) { + if ((wps->wps->registrar->force_pbc_overlap || + wps_registrar_pbc_overlap(wps->wps->registrar, + wps->mac_addr_e, wps->uuid_e) || + !wps_registrar_p2p_dev_addr_match(wps)) && + !wps_registrar_skip_overlap(wps)) { + wpa_printf(MSG_DEBUG, "WPS: PBC overlap - deny PBC " + "negotiation"); + wps->state = SEND_M2D; + wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; + wps_pbc_overlap_event(wps->wps); + wps_fail_event(wps->wps, WPS_M1, + WPS_CFG_MULTIPLE_PBC_DETECTED, + WPS_EI_NO_ERROR); + wps->wps->registrar->force_pbc_overlap = 1; + return WPS_CONTINUE; + } + wps_registrar_add_pbc_session(wps->wps->registrar, + wps->mac_addr_e, wps->uuid_e); + wps->pbc = 1; + } + +#ifdef WPS_WORKAROUNDS + /* + * It looks like Mac OS X 10.6.3 and 10.6.4 do not like Network Key in + * passphrase format. To avoid interop issues, force PSK format to be + * used. + */ + if (!wps->use_psk_key && + wps->peer_dev.manufacturer && + os_strncmp(wps->peer_dev.manufacturer, "Apple ", 6) == 0 && + wps->peer_dev.model_name && + os_strcmp(wps->peer_dev.model_name, "AirPort") == 0) { + wpa_printf(MSG_DEBUG, "WPS: Workaround - Force Network Key in " + "PSK format"); + wps->use_psk_key = 1; + } +#endif /* WPS_WORKAROUNDS */ + + wps->state = SEND_M2; + return WPS_CONTINUE; +} + + +static enum wps_process_res wps_process_m3(struct wps_data *wps, + const struct wpabuf *msg, + struct wps_parse_attr *attr) +{ + wpa_printf(MSG_DEBUG, "WPS: Received M3"); + + if (wps->state != RECV_M3) { + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + "receiving M3", wps->state); + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + if (wps->pbc && wps->wps->registrar->force_pbc_overlap && + !wps_registrar_skip_overlap(wps)) { + wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " + "session overlap"); + wps->state = SEND_WSC_NACK; + wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; + return WPS_CONTINUE; + } + + if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || + wps_process_authenticator(wps, attr->authenticator, msg) || + wps_process_e_hash1(wps, attr->e_hash1) || + wps_process_e_hash2(wps, attr->e_hash2)) { + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + wps->state = SEND_M4; + return WPS_CONTINUE; +} + + +static enum wps_process_res wps_process_m5(struct wps_data *wps, + const struct wpabuf *msg, + struct wps_parse_attr *attr) +{ + struct wpabuf *decrypted; + struct wps_parse_attr eattr; + + wpa_printf(MSG_DEBUG, "WPS: Received M5"); + + if (wps->state != RECV_M5) { + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + "receiving M5", wps->state); + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + if (wps->pbc && wps->wps->registrar->force_pbc_overlap && + !wps_registrar_skip_overlap(wps)) { + wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " + "session overlap"); + wps->state = SEND_WSC_NACK; + wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; + return WPS_CONTINUE; + } + + if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || + wps_process_authenticator(wps, attr->authenticator, msg)) { + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, + attr->encr_settings_len); + if (decrypted == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted " + "Settings attribute"); + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + if (wps_validate_m5_encr(decrypted, attr->version2 != NULL) < 0) { + wpabuf_free(decrypted); + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " + "attribute"); + if (wps_parse_msg(decrypted, &eattr) < 0 || + wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || + wps_process_e_snonce1(wps, eattr.e_snonce1)) { + wpabuf_free(decrypted); + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + wpabuf_free(decrypted); + + wps->state = SEND_M6; + return WPS_CONTINUE; +} + + +static void wps_sta_cred_cb(struct wps_data *wps) +{ + /* + * Update credential to only include a single authentication and + * encryption type in case the AP configuration includes more than one + * option. + */ + if (wps->cred.auth_type & WPS_AUTH_WPA2PSK) + wps->cred.auth_type = WPS_AUTH_WPA2PSK; + else if (wps->cred.auth_type & WPS_AUTH_WPAPSK) + wps->cred.auth_type = WPS_AUTH_WPAPSK; + if (wps->cred.encr_type & WPS_ENCR_AES) + wps->cred.encr_type = WPS_ENCR_AES; + else if (wps->cred.encr_type & WPS_ENCR_TKIP) + wps->cred.encr_type = WPS_ENCR_TKIP; + wpa_printf(MSG_DEBUG, "WPS: Update local configuration based on the " + "AP configuration"); + if (wps->wps->cred_cb) + wps->wps->cred_cb(wps->wps->cb_ctx, &wps->cred); +} + + +static void wps_cred_update(struct wps_credential *dst, + struct wps_credential *src) +{ + os_memcpy(dst->ssid, src->ssid, sizeof(dst->ssid)); + dst->ssid_len = src->ssid_len; + dst->auth_type = src->auth_type; + dst->encr_type = src->encr_type; + dst->key_idx = src->key_idx; + os_memcpy(dst->key, src->key, sizeof(dst->key)); + dst->key_len = src->key_len; +} + + +static int wps_process_ap_settings_r(struct wps_data *wps, + struct wps_parse_attr *attr) +{ + struct wpabuf *msg; + + if (wps->wps->ap || wps->er) + return 0; + + /* AP Settings Attributes in M7 when Enrollee is an AP */ + if (wps_process_ap_settings(attr, &wps->cred) < 0) + return -1; + + wpa_printf(MSG_INFO, "WPS: Received old AP configuration from AP"); + + if (wps->new_ap_settings) { + wpa_printf(MSG_INFO, "WPS: Update AP configuration based on " + "new settings"); + wps_cred_update(&wps->cred, wps->new_ap_settings); + return 0; + } else { +#ifdef CONFIG_WPS_PIN + /* + * Use the AP PIN only to receive the current AP settings, not + * to reconfigure the AP. + */ + + /* + * Clear selected registrar here since we do not get to + * WSC_Done in this protocol run. + */ + wps_registrar_pin_completed(wps->wps->registrar); +#endif + msg = wps_build_ap_cred(wps); + if (msg == NULL) + return -1; + wps->cred.cred_attr = wpabuf_head(msg); + wps->cred.cred_attr_len = wpabuf_len(msg); + + if (wps->ap_settings_cb) { + wps->ap_settings_cb(wps->ap_settings_cb_ctx, + &wps->cred); + wpabuf_free(msg); + return 1; + } + wps_sta_cred_cb(wps); + + wps->cred.cred_attr = NULL; + wps->cred.cred_attr_len = 0; + wpabuf_free(msg); + + return 1; + } +} + + +static enum wps_process_res wps_process_m7(struct wps_data *wps, + const struct wpabuf *msg, + struct wps_parse_attr *attr) +{ + struct wpabuf *decrypted; + struct wps_parse_attr eattr; + + wpa_printf(MSG_DEBUG, "WPS: Received M7"); + + if (wps->state != RECV_M7) { + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + "receiving M7", wps->state); + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + if (wps->pbc && wps->wps->registrar->force_pbc_overlap && + !wps_registrar_skip_overlap(wps)) { + wpa_printf(MSG_DEBUG, "WPS: Reject negotiation due to PBC " + "session overlap"); + wps->state = SEND_WSC_NACK; + wps->config_error = WPS_CFG_MULTIPLE_PBC_DETECTED; + return WPS_CONTINUE; + } + + if (wps_process_registrar_nonce(wps, attr->registrar_nonce) || + wps_process_authenticator(wps, attr->authenticator, msg)) { + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings, + attr->encr_settings_len); + if (decrypted == NULL) { + wpa_printf(MSG_DEBUG, "WPS: Failed to decrypt Encrypted " + "Settings attribute"); + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + if (wps_validate_m7_encr(decrypted, wps->wps->ap || wps->er, + attr->version2 != NULL) < 0) { + wpabuf_free(decrypted); + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted Settings " + "attribute"); + if (wps_parse_msg(decrypted, &eattr) < 0 || + wps_process_key_wrap_auth(wps, decrypted, eattr.key_wrap_auth) || + wps_process_e_snonce2(wps, eattr.e_snonce2) || + wps_process_ap_settings_r(wps, &eattr)) { + wpabuf_free(decrypted); + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + wpabuf_free(decrypted); + + wps->state = SEND_M8; + return WPS_CONTINUE; +} + + +static enum wps_process_res wps_process_wsc_msg(struct wps_data *wps, + const struct wpabuf *msg) +{ + struct wps_parse_attr attr; + enum wps_process_res ret = WPS_CONTINUE; + + wpa_printf(MSG_DEBUG, "WPS: Received WSC_MSG"); + + if (wps_parse_msg(msg, &attr) < 0) + return WPS_FAILURE; + + if (attr.msg_type == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); + wps->state = SEND_WSC_NACK; + return WPS_CONTINUE; + } + + if (*attr.msg_type != WPS_M1 && + (attr.registrar_nonce == NULL || + os_memcmp(wps->nonce_r, attr.registrar_nonce, + WPS_NONCE_LEN) != 0)) { + wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); + return WPS_FAILURE; + } + + switch (*attr.msg_type) { + case WPS_M1: + if (wps_validate_m1(msg) < 0) + return WPS_FAILURE; +#ifdef CONFIG_WPS_UPNP + if (wps->wps->wps_upnp && attr.mac_addr) { + /* Remove old pending messages when starting new run */ + wps_free_pending_msgs(wps->wps->upnp_msgs); + wps->wps->upnp_msgs = NULL; + + upnp_wps_device_send_wlan_event( + wps->wps->wps_upnp, attr.mac_addr, + UPNP_WPS_WLANEVENT_TYPE_EAP, msg); + } +#endif /* CONFIG_WPS_UPNP */ + ret = wps_process_m1(wps, &attr); + break; + case WPS_M3: + if (wps_validate_m3(msg) < 0) + return WPS_FAILURE; + ret = wps_process_m3(wps, msg, &attr); + if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) + wps_fail_event(wps->wps, WPS_M3, wps->config_error, + wps->error_indication); + break; + case WPS_M5: + if (wps_validate_m5(msg) < 0) + return WPS_FAILURE; + ret = wps_process_m5(wps, msg, &attr); + if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) + wps_fail_event(wps->wps, WPS_M5, wps->config_error, + wps->error_indication); + break; + case WPS_M7: + if (wps_validate_m7(msg) < 0) + return WPS_FAILURE; + ret = wps_process_m7(wps, msg, &attr); + if (ret == WPS_FAILURE || wps->state == SEND_WSC_NACK) + wps_fail_event(wps->wps, WPS_M7, wps->config_error, + wps->error_indication); + break; + default: + wpa_printf(MSG_DEBUG, "WPS: Unsupported Message Type %d", + *attr.msg_type); + return WPS_FAILURE; + } + + if (ret == WPS_CONTINUE) { + /* Save a copy of the last message for Authenticator derivation + */ + wpabuf_free(wps->last_msg); + wps->last_msg = wpabuf_dup(msg); + } + + return ret; +} + + +static enum wps_process_res wps_process_wsc_ack(struct wps_data *wps, + const struct wpabuf *msg) +{ + struct wps_parse_attr attr; + + wpa_printf(MSG_DEBUG, "WPS: Received WSC_ACK"); + + if (wps_parse_msg(msg, &attr) < 0) + return WPS_FAILURE; + + if (attr.msg_type == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); + return WPS_FAILURE; + } + + if (*attr.msg_type != WPS_WSC_ACK) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", + *attr.msg_type); + return WPS_FAILURE; + } + +#ifdef CONFIG_WPS_UPNP + if (wps->wps->wps_upnp && wps->ext_reg && wps->state == RECV_M2D_ACK && + upnp_wps_subscribers(wps->wps->wps_upnp)) { + if (wps->wps->upnp_msgs) + return WPS_CONTINUE; + wpa_printf(MSG_DEBUG, "WPS: Wait for response from an " + "external Registrar"); + return WPS_PENDING; + } +#endif /* CONFIG_WPS_UPNP */ + + if (attr.registrar_nonce == NULL || + os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0) + { + wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); + return WPS_FAILURE; + } + + if (attr.enrollee_nonce == NULL || + os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); + return WPS_FAILURE; + } + + if (wps->state == RECV_M2D_ACK) { +#ifdef CONFIG_WPS_UPNP + if (wps->wps->wps_upnp && + upnp_wps_subscribers(wps->wps->wps_upnp)) { + if (wps->wps->upnp_msgs) + return WPS_CONTINUE; + if (wps->ext_reg == 0) + wps->ext_reg = 1; + wpa_printf(MSG_DEBUG, "WPS: Wait for response from an " + "external Registrar"); + return WPS_PENDING; + } +#endif /* CONFIG_WPS_UPNP */ + + wpa_printf(MSG_DEBUG, "WPS: No more registrars available - " + "terminate negotiation"); + } + + return WPS_FAILURE; +} + + +static enum wps_process_res wps_process_wsc_nack(struct wps_data *wps, + const struct wpabuf *msg) +{ + struct wps_parse_attr attr; + int old_state; + u16 config_error; + + wpa_printf(MSG_DEBUG, "WPS: Received WSC_NACK"); + + old_state = wps->state; + wps->state = SEND_WSC_NACK; + + if (wps_parse_msg(msg, &attr) < 0) + return WPS_FAILURE; + + if (attr.msg_type == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); + return WPS_FAILURE; + } + + if (*attr.msg_type != WPS_WSC_NACK) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", + *attr.msg_type); + return WPS_FAILURE; + } + +#ifdef CONFIG_WPS_UPNP + if (wps->wps->wps_upnp && wps->ext_reg) { + wpa_printf(MSG_DEBUG, "WPS: Negotiation using external " + "Registrar terminated by the Enrollee"); + return WPS_FAILURE; + } +#endif /* CONFIG_WPS_UPNP */ + + if (attr.registrar_nonce == NULL || + os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0) + { + wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); + return WPS_FAILURE; + } + + if (attr.enrollee_nonce == NULL || + os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); + return WPS_FAILURE; + } + + if (attr.config_error == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Configuration Error attribute " + "in WSC_NACK"); + return WPS_FAILURE; + } + + config_error = WPA_GET_BE16(attr.config_error); + wpa_printf(MSG_DEBUG, "WPS: Enrollee terminated negotiation with " + "Configuration Error %d", config_error); + + switch (old_state) { + case RECV_M3: + wps_fail_event(wps->wps, WPS_M2, config_error, + wps->error_indication); + break; + case RECV_M5: + wps_fail_event(wps->wps, WPS_M4, config_error, + wps->error_indication); + break; + case RECV_M7: + wps_fail_event(wps->wps, WPS_M6, config_error, + wps->error_indication); + break; + case RECV_DONE: + wps_fail_event(wps->wps, WPS_M8, config_error, + wps->error_indication); + break; + default: + break; + } + + return WPS_FAILURE; +} + + +static enum wps_process_res wps_process_wsc_done(struct wps_data *wps, + const struct wpabuf *msg) +{ + struct wps_parse_attr attr; + + wpa_printf(MSG_DEBUG, "WPS: Received WSC_Done"); + + //if (wps->state != RECV_DONE && + // (!wps->wps->wps_upnp || !wps->ext_reg)) + if (wps->state != RECV_DONE && (!wps->ext_reg)){ + wpa_printf(MSG_DEBUG, "WPS: Unexpected state (%d) for " + "receiving WSC_Done", wps->state); + return WPS_FAILURE; + } + + if (wps_parse_msg(msg, &attr) < 0) + return WPS_FAILURE; + + if (attr.msg_type == NULL) { + wpa_printf(MSG_DEBUG, "WPS: No Message Type attribute"); + return WPS_FAILURE; + } + + if (*attr.msg_type != WPS_WSC_DONE) { + wpa_printf(MSG_DEBUG, "WPS: Invalid Message Type %d", + *attr.msg_type); + return WPS_FAILURE; + } + +#ifdef CONFIG_WPS_UPNP + if (wps->wps->wps_upnp && wps->ext_reg) { + wpa_printf(MSG_DEBUG, "WPS: Negotiation using external " + "Registrar completed successfully"); + wps_device_store(wps->wps->registrar, &wps->peer_dev, + wps->uuid_e); + return WPS_DONE; + } +#endif /* CONFIG_WPS_UPNP */ + + if (attr.registrar_nonce == NULL || + os_memcmp(wps->nonce_r, attr.registrar_nonce, WPS_NONCE_LEN) != 0) + { + wpa_printf(MSG_DEBUG, "WPS: Mismatch in registrar nonce"); + return WPS_FAILURE; + } + + if (attr.enrollee_nonce == NULL || + os_memcmp(wps->nonce_e, attr.enrollee_nonce, WPS_NONCE_LEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: Mismatch in enrollee nonce"); + return WPS_FAILURE; + } + + wpa_printf(MSG_DEBUG, "WPS: Negotiation completed successfully"); + wps_device_store(wps->wps->registrar, &wps->peer_dev, + wps->uuid_e); + + if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->new_psk && + wps->wps->ap && !wps->wps->registrar->disable_auto_conf) { + struct wps_credential cred; + + wpa_printf(MSG_DEBUG, "WPS: Moving to Configured state based " + "on first Enrollee connection"); + + os_memset(&cred, 0, sizeof(cred)); + os_memcpy(cred.ssid, wps->wps->ssid, wps->wps->ssid_len); + cred.ssid_len = wps->wps->ssid_len; + cred.auth_type = WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK; + cred.encr_type = WPS_ENCR_TKIP | WPS_ENCR_AES; + os_memcpy(cred.key, wps->new_psk, wps->new_psk_len); + cred.key_len = wps->new_psk_len; + + wps->wps->wps_state = WPS_STATE_CONFIGURED; + wpa_hexdump_ascii_key(MSG_DEBUG, + "WPS: Generated random passphrase", + wps->new_psk, wps->new_psk_len); + if (wps->wps->cred_cb) + wps->wps->cred_cb(wps->wps->cb_ctx, &cred); + + os_free(wps->new_psk); + wps->new_psk = NULL; + } + + if (!wps->wps->ap && !wps->er) + wps_sta_cred_cb(wps); + + if (wps->new_psk) { + if (wps_cb_new_psk(wps->wps->registrar, wps->mac_addr_e, + wps->new_psk, wps->new_psk_len)) { + wpa_printf(MSG_DEBUG, "WPS: Failed to configure the " + "new PSK"); + } + os_free(wps->new_psk); + wps->new_psk = NULL; + } + + wps_cb_reg_success(wps->wps->registrar, wps->mac_addr_e, wps->uuid_e, + wps->dev_password, wps->dev_password_len); + + if (wps->pbc) { + wps_registrar_remove_pbc_session(wps->wps->registrar, + wps->uuid_e, + wps->p2p_dev_addr); + wps_registrar_pbc_completed(wps->wps->registrar); + os_get_time(&wps->wps->registrar->pbc_ignore_start); + os_memcpy(wps->wps->registrar->pbc_ignore_uuid, wps->uuid_e, + WPS_UUID_LEN); + } else { +#ifdef CONFIG_WPS_PIN + wps_registrar_pin_completed(wps->wps->registrar); +#endif + } + /* TODO: maintain AuthorizedMACs somewhere separately for each ER and + * merge them into APs own list.. */ + + wps_success_event(wps->wps); + + return WPS_DONE; +} + + +enum wps_process_res wps_registrar_process_msg(struct wps_data *wps, + enum wsc_op_code op_code, + const struct wpabuf *msg) +{ + enum wps_process_res ret; + + wpa_printf(MSG_DEBUG, "WPS: Processing received message (len=%lu " + "op_code=%d)", + (unsigned long) wpabuf_len(msg), op_code); + +#ifdef CONFIG_WPS_UPNP + if (wps->wps->wps_upnp && op_code == WSC_MSG && wps->ext_reg == 1) { + struct wps_parse_attr attr; + if (wps_parse_msg(msg, &attr) == 0 && attr.msg_type && + *attr.msg_type == WPS_M3) + wps->ext_reg = 2; /* past M2/M2D phase */ + } + if (wps->ext_reg > 1) + wps_registrar_free_pending_m2(wps->wps); + if (wps->wps->wps_upnp && wps->ext_reg && + wps->wps->upnp_msgs == NULL && + (op_code == WSC_MSG || op_code == WSC_Done || op_code == WSC_NACK)) + { + struct wps_parse_attr attr; + int type; + if (wps_parse_msg(msg, &attr) < 0 || attr.msg_type == NULL) + type = -1; + else + type = *attr.msg_type; + wpa_printf(MSG_DEBUG, "WPS: Sending received message (type %d)" + " to external Registrar for processing", type); + upnp_wps_device_send_wlan_event(wps->wps->wps_upnp, + wps->mac_addr_e, + UPNP_WPS_WLANEVENT_TYPE_EAP, + msg); + if (op_code == WSC_MSG) + return WPS_PENDING; + } else if (wps->wps->wps_upnp && wps->ext_reg && op_code == WSC_MSG) { + wpa_printf(MSG_DEBUG, "WPS: Skip internal processing - using " + "external Registrar"); + return WPS_CONTINUE; + } +#endif /* CONFIG_WPS_UPNP */ + + switch (op_code) { + case WSC_MSG: + return wps_process_wsc_msg(wps, msg); + case WSC_ACK: + if (wps_validate_wsc_ack(msg) < 0) + return WPS_FAILURE; + return wps_process_wsc_ack(wps, msg); + case WSC_NACK: + if (wps_validate_wsc_nack(msg) < 0) + return WPS_FAILURE; + return wps_process_wsc_nack(wps, msg); + case WSC_Done: + if (wps_validate_wsc_done(msg) < 0) + return WPS_FAILURE; + ret = wps_process_wsc_done(wps, msg); + if (ret == WPS_FAILURE) { + wps->state = SEND_WSC_NACK; + wps_fail_event(wps->wps, WPS_WSC_DONE, + wps->config_error, + wps->error_indication); + } + return ret; + default: + wpa_printf(MSG_DEBUG, "WPS: Unsupported op_code %d", op_code); + return WPS_FAILURE; + } +} + + +int wps_registrar_update_ie(struct wps_registrar *reg) +{ + return wps_set_ie(reg); +} + + +//static void ICACHE_FLASH_ATTR wps_registrar_set_selected_timeout(void *eloop_ctx, +// void *timeout_ctx) +#if 0 +static void wps_registrar_set_selected_timeout(void *eloop_ctx) +{ + struct wps_registrar *reg = eloop_ctx; + + wpa_printf(MSG_DEBUG, "WPS: Selected Registrar timeout - " + "unselect internal Registrar"); + reg->selected_registrar = 0; + reg->pbc = 0; + wps_registrar_selected_registrar_changed(reg); +} +#endif + +#ifdef CONFIG_WPS_UPNP +static void wps_registrar_sel_reg_add(struct wps_registrar *reg, + struct subscription *s) +{ + int i, j; + wpa_printf(MSG_DEBUG, "WPS: External Registrar selected (dev_pw_id=%d " + "config_methods=0x%x)", + s->dev_password_id, s->config_methods); + reg->sel_reg_union = 1; + if (reg->sel_reg_dev_password_id_override != DEV_PW_PUSHBUTTON) + reg->sel_reg_dev_password_id_override = s->dev_password_id; + if (reg->sel_reg_config_methods_override == -1) + reg->sel_reg_config_methods_override = 0; + reg->sel_reg_config_methods_override |= s->config_methods; + for (i = 0; i < WPS_MAX_AUTHORIZED_MACS; i++) + if (is_zero_ether_addr(reg->authorized_macs_union[i])) + break; + for (j = 0; i < WPS_MAX_AUTHORIZED_MACS && j < WPS_MAX_AUTHORIZED_MACS; + j++) { + if (is_zero_ether_addr(s->authorized_macs[j])) + break; + wpa_printf(MSG_DEBUG, "WPS: Add authorized MAC into union: " + MACSTR, MAC2STR(s->authorized_macs[j])); + os_memcpy(reg->authorized_macs_union[i], + s->authorized_macs[j], ETH_ALEN); + i++; + } + wpa_hexdump(MSG_DEBUG, "WPS: Authorized MACs union", + (u8 *) reg->authorized_macs_union, + sizeof(reg->authorized_macs_union)); +} +#endif /* CONFIG_WPS_UPNP */ + + +static void wps_registrar_sel_reg_union(struct wps_registrar *reg) +{ +#ifdef CONFIG_WPS_UPNP + struct subscription *s; + + if (reg->wps->wps_upnp == NULL) + return; + + dl_list_for_each(s, ®->wps->wps_upnp->subscriptions, + struct subscription, list) { + struct subscr_addr *sa; + sa = dl_list_first(&s->addr_list, struct subscr_addr, list); + if (sa) { + wpa_printf(MSG_DEBUG, "WPS: External Registrar %s:%d", + inet_ntoa(sa->saddr.sin_addr), + ntohs(sa->saddr.sin_port)); + } + if (s->selected_registrar) + wps_registrar_sel_reg_add(reg, s); + else + wpa_printf(MSG_DEBUG, "WPS: External Registrar not " + "selected"); + } +#endif /* CONFIG_WPS_UPNP */ +} + + +/** + * wps_registrar_selected_registrar_changed - SetSelectedRegistrar change + * @reg: Registrar data from wps_registrar_init() + * + * This function is called when selected registrar state changes, e.g., when an + * AP receives a SetSelectedRegistrar UPnP message. + */ +void wps_registrar_selected_registrar_changed(struct wps_registrar *reg) +{ + wpa_printf(MSG_DEBUG, "WPS: Selected registrar information changed"); + + reg->sel_reg_union = reg->selected_registrar; + reg->sel_reg_dev_password_id_override = -1; + reg->sel_reg_config_methods_override = -1; + os_memcpy(reg->authorized_macs_union, reg->authorized_macs, + WPS_MAX_AUTHORIZED_MACS * ETH_ALEN); + wpa_hexdump(MSG_DEBUG, "WPS: Authorized MACs union (start with own)", + (u8 *) reg->authorized_macs_union, + sizeof(reg->authorized_macs_union)); + if (reg->selected_registrar) { + u16 methods; + + methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON; +#ifdef CONFIG_WPS2 + methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON | + WPS_CONFIG_PHY_PUSHBUTTON); +#endif /* CONFIG_WPS2 */ + if (reg->pbc) { + reg->sel_reg_dev_password_id_override = + DEV_PW_PUSHBUTTON; + wps_set_pushbutton(&methods, reg->wps->config_methods); + } + wpa_printf(MSG_DEBUG, "WPS: Internal Registrar selected " + "(pbc=%d)", reg->pbc); + reg->sel_reg_config_methods_override = methods; + } else { + wpa_printf(MSG_DEBUG, "WPS: Internal Registrar not selected"); + return; + } + + wps_registrar_sel_reg_union(reg); + + wps_set_ie(reg); + wps_cb_set_sel_reg(reg); +} + + +int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr, + char *buf, size_t buflen) +{ + struct wps_registrar_device *d; + int len = 0, ret; + char uuid[40]; + char devtype[WPS_DEV_TYPE_BUFSIZE]; + + d = wps_device_get(reg, addr); + if (d == NULL) + return 0; + if (uuid_bin2str(d->uuid, uuid, sizeof(uuid))) + return 0; + + ret = snprintf(buf + len, buflen - len, + "wpsUuid=%s\n" + "wpsPrimaryDeviceType=%s\n" + "wpsDeviceName=%s\n" + "wpsManufacturer=%s\n" + "wpsModelName=%s\n" + "wpsModelNumber=%s\n" + "wpsSerialNumber=%s\n", + uuid, + wps_dev_type_bin2str(d->dev.pri_dev_type, devtype, + sizeof(devtype)), + d->dev.device_name ? d->dev.device_name : "", + d->dev.manufacturer ? d->dev.manufacturer : "", + d->dev.model_name ? d->dev.model_name : "", + d->dev.model_number ? d->dev.model_number : "", + d->dev.serial_number ? d->dev.serial_number : ""); + if (ret < 0 || (size_t) ret >= buflen - len) + return len; + len += ret; + + return len; +} + + +int wps_registrar_config_ap(struct wps_registrar *reg, + struct wps_credential *cred) +{ +#ifdef CONFIG_WPS2 + if (!(cred->encr_type & (WPS_ENCR_NONE | WPS_ENCR_TKIP | + WPS_ENCR_AES))) { + if (cred->encr_type & WPS_ENCR_WEP) { + wpa_printf(MSG_INFO, "WPS: Reject new AP settings " + "due to WEP configuration"); + return -1; + } + + wpa_printf(MSG_INFO, "WPS: Reject new AP settings due to " + "invalid encr_type 0x%x", cred->encr_type); + return -1; + } + + if ((cred->encr_type & (WPS_ENCR_TKIP | WPS_ENCR_AES)) == + WPS_ENCR_TKIP) { + wpa_printf(MSG_DEBUG, "WPS: Upgrade encr_type TKIP -> " + "TKIP+AES"); + cred->encr_type |= WPS_ENCR_AES; + } + + if ((cred->auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) == + WPS_AUTH_WPAPSK) { + wpa_printf(MSG_DEBUG, "WPS: Upgrade auth_type WPAPSK -> " + "WPAPSK+WPA2PSK"); + cred->auth_type |= WPS_AUTH_WPA2PSK; + } +#endif /* CONFIG_WPS2 */ + + if (reg->wps->cred_cb) + return reg->wps->cred_cb(reg->wps->cb_ctx, cred); + + return -1; +} + + +#ifdef CONFIG_WPS_NFC + +int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg, + const u8 *pubkey_hash, u16 pw_id, + const u8 *dev_pw, size_t dev_pw_len) +{ + struct wps_nfc_pw_token *token; + + if (dev_pw_len > WPS_OOB_DEVICE_PASSWORD_LEN) + return -1; + + wps_free_nfc_pw_tokens(®->nfc_pw_tokens, pw_id); + + token = os_zalloc(sizeof(*token)); + if (token == NULL) + return -1; + + os_memcpy(token->pubkey_hash, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); + token->pw_id = pw_id; + os_memcpy(token->dev_pw, dev_pw, dev_pw_len); + token->dev_pw_len = dev_pw_len; + + dl_list_add(®->nfc_pw_tokens, &token->list); + + reg->selected_registrar = 1; + reg->pbc = 0; + wps_registrar_add_authorized_mac(reg, + (u8 *) "\xff\xff\xff\xff\xff\xff"); + wps_registrar_selected_registrar_changed(reg); + #if 0 + eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL); + eloop_register_timeout(WPS_PBC_WALK_TIME, 0, + wps_registrar_set_selected_timeout, + reg, NULL); + #endif + return 0; +} + + +int wps_registrar_add_nfc_password_token(struct wps_registrar *reg, + const u8 *oob_dev_pw, + size_t oob_dev_pw_len) +{ + const u8 *pos, *hash, *dev_pw; + u16 id; + size_t dev_pw_len; + + if (oob_dev_pw_len < WPS_OOB_PUBKEY_HASH_LEN + 2 + + WPS_OOB_DEVICE_PASSWORD_MIN_LEN || + oob_dev_pw_len > WPS_OOB_PUBKEY_HASH_LEN + 2 + + WPS_OOB_DEVICE_PASSWORD_LEN) + return -1; + + hash = oob_dev_pw; + pos = oob_dev_pw + WPS_OOB_PUBKEY_HASH_LEN; + id = WPA_GET_BE16(pos); + dev_pw = pos + 2; + dev_pw_len = oob_dev_pw + oob_dev_pw_len - dev_pw; + + wpa_printf(MSG_DEBUG, "WPS: Add NFC Password Token for Password ID %u", + id); + + wpa_hexdump(MSG_DEBUG, "WPS: Public Key Hash", + hash, WPS_OOB_PUBKEY_HASH_LEN); + wpa_hexdump_key(MSG_DEBUG, "WPS: Device Password", dev_pw, dev_pw_len); + + return wps_registrar_add_nfc_pw_token(reg, hash, id, dev_pw, + dev_pw_len); +} + + +void wps_registrar_remove_nfc_pw_token(struct wps_registrar *reg, + struct wps_nfc_pw_token *token) +{ + wps_registrar_remove_authorized_mac(reg, + (u8 *) "\xff\xff\xff\xff\xff\xff"); + wps_registrar_selected_registrar_changed(reg); +} + +#endif /* CONFIG_WPS_NFC */ diff --git a/components/wpa_supplicant/src/wps/wps_validate.c b/components/wpa_supplicant/src/wps/wps_validate.c new file mode 100644 index 0000000000..7f2ad5eeb6 --- /dev/null +++ b/components/wpa_supplicant/src/wps/wps_validate.c @@ -0,0 +1,2375 @@ +/* + * Wi-Fi Protected Setup - Strict protocol validation routines + * Copyright (c) 2010, Atheros Communications, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "wpa/includes.h" + +#include "wpa/common.h" +#include "wps/wps_i.h" +#include "wps/wps.h" + + +#ifndef WPS_STRICT_ALL +#define WPS_STRICT_WPS2 +#endif /* WPS_STRICT_ALL */ + + +static int wps_validate_version(const u8 *version, int mandatory) +{ + if (version == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Version attribute " + "missing"); + return -1; + } + return 0; + } + if (*version != 0x10) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Version attribute " + "value 0x%x", *version); + return -1; + } + return 0; +} + + +static int wps_validate_version2(const u8 *version2, int mandatory) +{ + if (version2 == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Version2 attribute " + "missing"); + return -1; + } + return 0; + } + if (*version2 < 0x20) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Version2 attribute " + "value 0x%x", *version2); + return -1; + } + return 0; +} + + +static int wps_validate_request_type(const u8 *request_type, int mandatory) +{ + if (request_type == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Request Type " + "attribute missing"); + return -1; + } + return 0; + } + if (*request_type > 0x03) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Request Type " + "attribute value 0x%x", *request_type); + return -1; + } + return 0; +} + + +static int wps_validate_response_type(const u8 *response_type, int mandatory) +{ + if (response_type == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Response Type " + "attribute missing"); + return -1; + } + return 0; + } + if (*response_type > 0x03) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Response Type " + "attribute value 0x%x", *response_type); + return -1; + } + return 0; +} + + +static int valid_config_methods(u16 val, int wps2) +{ + if (wps2) { + if ((val & 0x6000) && !(val & WPS_CONFIG_DISPLAY)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Physical/Virtual " + "Display flag without old Display flag " + "set"); + return 0; + } + if (!(val & 0x6000) && (val & WPS_CONFIG_DISPLAY)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Display flag " + "without Physical/Virtual Display flag"); + return 0; + } + if ((val & 0x0600) && !(val & WPS_CONFIG_PUSHBUTTON)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Physical/Virtual " + "PushButton flag without old PushButton " + "flag set"); + return 0; + } + if (!(val & 0x0600) && (val & WPS_CONFIG_PUSHBUTTON)) { + wpa_printf(MSG_INFO, "WPS-STRICT: PushButton flag " + "without Physical/Virtual PushButton flag"); + return 0; + } + } + + return 1; +} + + +static int wps_validate_config_methods(const u8 *config_methods, int wps2, + int mandatory) +{ + u16 val; + + if (config_methods == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Configuration " + "Methods attribute missing"); + return -1; + } + return 0; + } + + val = WPA_GET_BE16(config_methods); + if (!valid_config_methods(val, wps2)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Configuration " + "Methods attribute value 0x%04x", val); + return -1; + } + return 0; +} + + +static int wps_validate_ap_config_methods(const u8 *config_methods, int wps2, + int mandatory) +{ + u16 val; + + if (wps_validate_config_methods(config_methods, wps2, mandatory) < 0) + return -1; + if (config_methods == NULL) + return 0; + val = WPA_GET_BE16(config_methods); + if (val & WPS_CONFIG_PUSHBUTTON) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Configuration " + "Methods attribute value 0x%04x in AP info " + "(PushButton not allowed for registering new ER)", + val); + return -1; + } + return 0; +} + + +static int wps_validate_uuid_e(const u8 *uuid_e, int mandatory) +{ + if (uuid_e == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: UUID-E " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_uuid_r(const u8 *uuid_r, int mandatory) +{ + if (uuid_r == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: UUID-R " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_primary_dev_type(const u8 *primary_dev_type, + int mandatory) +{ + if (primary_dev_type == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Primary Device Type " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_rf_bands(const u8 *rf_bands, int mandatory) +{ + if (rf_bands == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: RF Bands " + "attribute missing"); + return -1; + } + return 0; + } + if (*rf_bands != WPS_RF_24GHZ && *rf_bands != WPS_RF_50GHZ && + *rf_bands != (WPS_RF_24GHZ | WPS_RF_50GHZ)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Rf Bands " + "attribute value 0x%x", *rf_bands); + return -1; + } + return 0; +} + + +static int wps_validate_assoc_state(const u8 *assoc_state, int mandatory) +{ + u16 val; + if (assoc_state == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Association State " + "attribute missing"); + return -1; + } + return 0; + } + val = WPA_GET_BE16(assoc_state); + if (val > 4) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Association State " + "attribute value 0x%04x", val); + return -1; + } + return 0; +} + + +static int wps_validate_config_error(const u8 *config_error, int mandatory) +{ + u16 val; + + if (config_error == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Configuration Error " + "attribute missing"); + return -1; + } + return 0; + } + val = WPA_GET_BE16(config_error); + if (val > 18) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Configuration Error " + "attribute value 0x%04x", val); + return -1; + } + return 0; +} + + +static int wps_validate_dev_password_id(const u8 *dev_password_id, + int mandatory) +{ + u16 val; + + if (dev_password_id == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Device Password ID " + "attribute missing"); + return -1; + } + return 0; + } + val = WPA_GET_BE16(dev_password_id); + if (val >= 0x0006 && val <= 0x000f) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Device Password ID " + "attribute value 0x%04x", val); + return -1; + } + return 0; +} + + +static int wps_validate_manufacturer(const u8 *manufacturer, size_t len, + int mandatory) +{ + if (manufacturer == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Manufacturer " + "attribute missing"); + return -1; + } + return 0; + } + if (len > 0 && manufacturer[len - 1] == 0) { + wpa_hexdump_ascii(MSG_INFO, "WPS-STRICT: Invalid Manufacturer " + "attribute value", manufacturer, len); + return -1; + } + return 0; +} + + +static int wps_validate_model_name(const u8 *model_name, size_t len, + int mandatory) +{ + if (model_name == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Model Name " + "attribute missing"); + return -1; + } + return 0; + } + if (len > 0 && model_name[len - 1] == 0) { + wpa_hexdump_ascii(MSG_INFO, "WPS-STRICT: Invalid Model Name " + "attribute value", model_name, len); + return -1; + } + return 0; +} + + +static int wps_validate_model_number(const u8 *model_number, size_t len, + int mandatory) +{ + if (model_number == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Model Number " + "attribute missing"); + return -1; + } + return 0; + } + if (len > 0 && model_number[len - 1] == 0) { + wpa_hexdump_ascii(MSG_INFO, "WPS-STRICT: Invalid Model Number " + "attribute value", model_number, len); + return -1; + } + return 0; +} + + +static int wps_validate_serial_number(const u8 *serial_number, size_t len, + int mandatory) +{ + if (serial_number == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Serial Number " + "attribute missing"); + return -1; + } + return 0; + } + if (len > 0 && serial_number[len - 1] == 0) { + wpa_hexdump_ascii(MSG_INFO, "WPS-STRICT: Invalid Serial " + "Number attribute value", + serial_number, len); + return -1; + } + return 0; +} + + +static int wps_validate_dev_name(const u8 *dev_name, size_t len, + int mandatory) +{ + if (dev_name == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Device Name " + "attribute missing"); + return -1; + } + return 0; + } + if (len > 0 && dev_name[len - 1] == 0) { + wpa_hexdump_ascii(MSG_INFO, "WPS-STRICT: Invalid Device Name " + "attribute value", dev_name, len); + return -1; + } + return 0; +} + + +static int wps_validate_request_to_enroll(const u8 *request_to_enroll, + int mandatory) +{ + if (request_to_enroll == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Request to Enroll " + "attribute missing"); + return -1; + } + return 0; + } + if (*request_to_enroll > 0x01) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Request to Enroll " + "attribute value 0x%x", *request_to_enroll); + return -1; + } + return 0; +} + + +static int wps_validate_req_dev_type(const u8 *req_dev_type[], size_t num, + int mandatory) +{ + if (num == 0) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Requested Device " + "Type attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_wps_state(const u8 *wps_state, int mandatory) +{ + if (wps_state == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Wi-Fi Protected " + "Setup State attribute missing"); + return -1; + } + return 0; + } + if (*wps_state != WPS_STATE_NOT_CONFIGURED && + *wps_state != WPS_STATE_CONFIGURED) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Wi-Fi Protected " + "Setup State attribute value 0x%x", *wps_state); + return -1; + } + return 0; +} + + +static int wps_validate_ap_setup_locked(const u8 *ap_setup_locked, + int mandatory) +{ + if (ap_setup_locked == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: AP Setup Locked " + "attribute missing"); + return -1; + } + return 0; + } + if (*ap_setup_locked > 1) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid AP Setup Locked " + "attribute value 0x%x", *ap_setup_locked); + return -1; + } + return 0; +} + + +static int wps_validate_selected_registrar(const u8 *selected_registrar, + int mandatory) +{ + if (selected_registrar == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Selected Registrar " + "attribute missing"); + return -1; + } + return 0; + } + if (*selected_registrar > 1) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Selected Registrar " + "attribute value 0x%x", *selected_registrar); + return -1; + } + return 0; +} + + +static int wps_validate_sel_reg_config_methods(const u8 *config_methods, + int wps2, int mandatory) +{ + u16 val; + + if (config_methods == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Selected Registrar " + "Configuration Methods attribute missing"); + return -1; + } + return 0; + } + + val = WPA_GET_BE16(config_methods); + if (!valid_config_methods(val, wps2)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Selected Registrar " + "Configuration Methods attribute value 0x%04x", + val); + return -1; + } + return 0; +} + + +static int wps_validate_authorized_macs(const u8 *authorized_macs, size_t len, + int mandatory) +{ + if (authorized_macs == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Authorized MACs " + "attribute missing"); + return -1; + } + return 0; + } + if (len > 30 && (len % ETH_ALEN) != 0) { + wpa_hexdump(MSG_INFO, "WPS-STRICT: Invalid Authorized " + "MACs attribute value", authorized_macs, len); + return -1; + } + return 0; +} + + +static int wps_validate_msg_type(const u8 *msg_type, int mandatory) +{ + if (msg_type == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Message Type " + "attribute missing"); + return -1; + } + return 0; + } + if (*msg_type < WPS_Beacon || *msg_type > WPS_WSC_DONE) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Message Type " + "attribute value 0x%x", *msg_type); + return -1; + } + return 0; +} + + +static int wps_validate_mac_addr(const u8 *mac_addr, int mandatory) +{ + if (mac_addr == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: MAC Address " + "attribute missing"); + return -1; + } + return 0; + } + if (mac_addr[0] & 0x01) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid MAC Address " + "attribute value " MACSTR, MAC2STR(mac_addr)); + return -1; + } + return 0; +} + + +static int wps_validate_enrollee_nonce(const u8 *enrollee_nonce, int mandatory) +{ + if (enrollee_nonce == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Enrollee Nonce " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_registrar_nonce(const u8 *registrar_nonce, + int mandatory) +{ + if (registrar_nonce == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Registrar Nonce " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_public_key(const u8 *public_key, size_t len, + int mandatory) +{ + if (public_key == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Public Key " + "attribute missing"); + return -1; + } + return 0; + } + if (len != 192) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Public Key " + "attribute length %d", (int) len); + return -1; + } + return 0; +} + + +static int num_bits_set(u16 val) +{ + int c; + for (c = 0; val; c++) + val &= val - 1; + return c; +} + + +static int wps_validate_auth_type_flags(const u8 *flags, int mandatory) +{ + u16 val; + + if (flags == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Authentication Type " + "Flags attribute missing"); + return -1; + } + return 0; + } + val = WPA_GET_BE16(flags); + if ((val & ~WPS_AUTH_TYPES) || !(val & WPS_AUTH_WPA2PSK)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Authentication Type " + "Flags attribute value 0x%04x", val); + return -1; + } + return 0; +} + + +static int wps_validate_auth_type(const u8 *type, int mandatory) +{ + u16 val; + + if (type == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Authentication Type " + "attribute missing"); + return -1; + } + return 0; + } + val = WPA_GET_BE16(type); + if ((val & ~WPS_AUTH_TYPES) || val == 0 || + (num_bits_set(val) > 1 && + val != (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK))) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Authentication Type " + "attribute value 0x%04x", val); + return -1; + } + return 0; +} + + +static int wps_validate_encr_type_flags(const u8 *flags, int mandatory) +{ + u16 val; + + if (flags == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Encryption Type " + "Flags attribute missing"); + return -1; + } + return 0; + } + val = WPA_GET_BE16(flags); + if ((val & ~WPS_ENCR_TYPES) || !(val & WPS_ENCR_AES)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Encryption Type " + "Flags attribute value 0x%04x", val); + return -1; + } + return 0; +} + + +static int wps_validate_encr_type(const u8 *type, int mandatory) +{ + u16 val; + + if (type == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Encryption Type " + "attribute missing"); + return -1; + } + return 0; + } + val = WPA_GET_BE16(type); + if ((val & ~WPS_ENCR_TYPES) || val == 0 || + (num_bits_set(val) > 1 && val != (WPS_ENCR_TKIP | WPS_ENCR_AES))) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Encryption Type " + "attribute value 0x%04x", val); + return -1; + } + return 0; +} + + +static int wps_validate_conn_type_flags(const u8 *flags, int mandatory) +{ + if (flags == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Connection Type " + "Flags attribute missing"); + return -1; + } + return 0; + } + if ((*flags & ~(WPS_CONN_ESS | WPS_CONN_IBSS)) || + !(*flags & WPS_CONN_ESS)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Connection Type " + "Flags attribute value 0x%02x", *flags); + return -1; + } + return 0; +} + + +static int wps_validate_os_version(const u8 *os_version, int mandatory) +{ + if (os_version == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: OS Version " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_authenticator(const u8 *authenticator, int mandatory) +{ + if (authenticator == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Authenticator " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_e_hash1(const u8 *hash, int mandatory) +{ + if (hash == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: E-Hash1 " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_e_hash2(const u8 *hash, int mandatory) +{ + if (hash == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: E-Hash2 " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_r_hash1(const u8 *hash, int mandatory) +{ + if (hash == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: R-Hash1 " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_r_hash2(const u8 *hash, int mandatory) +{ + if (hash == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: R-Hash2 " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_encr_settings(const u8 *encr_settings, size_t len, + int mandatory) +{ + if (encr_settings == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Encrypted Settings " + "attribute missing"); + return -1; + } + return 0; + } + if (len < 16) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Encrypted Settings " + "attribute length %d", (int) len); + return -1; + } + return 0; +} + + +static int wps_validate_settings_delay_time(const u8 *delay, int mandatory) +{ + if (delay == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Settings Delay Time " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_r_snonce1(const u8 *nonce, int mandatory) +{ + if (nonce == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: R-SNonce1 " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_r_snonce2(const u8 *nonce, int mandatory) +{ + if (nonce == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: R-SNonce2 " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_e_snonce1(const u8 *nonce, int mandatory) +{ + if (nonce == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: E-SNonce1 " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_e_snonce2(const u8 *nonce, int mandatory) +{ + if (nonce == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: E-SNonce2 " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_key_wrap_auth(const u8 *auth, int mandatory) +{ + if (auth == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Key Wrap " + "Authenticator attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_ssid(const u8 *ssid, size_t ssid_len, int mandatory) +{ + if (ssid == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: SSID " + "attribute missing"); + return -1; + } + return 0; + } + if (ssid_len == 0 || ssid[ssid_len - 1] == 0) { + wpa_hexdump_ascii(MSG_INFO, "WPS-STRICT: Invalid SSID " + "attribute value", ssid, ssid_len); + return -1; + } + return 0; +} + + +static int wps_validate_network_key_index(const u8 *idx, int mandatory) +{ + if (idx == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Network Key Index " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_network_idx(const u8 *idx, int mandatory) +{ + if (idx == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Network Index " + "attribute missing"); + return -1; + } + return 0; + } + return 0; +} + + +static int wps_validate_network_key(const u8 *key, size_t key_len, + const u8 *encr_type, int mandatory) +{ + if (key == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Network Key " + "attribute missing"); + return -1; + } + return 0; + } + if (((encr_type == NULL || WPA_GET_BE16(encr_type) != WPS_ENCR_WEP) && + key_len > 8 && key_len < 64 && key[key_len - 1] == 0) || + key_len > 64) { + wpa_hexdump_ascii_key(MSG_INFO, "WPS-STRICT: Invalid Network " + "Key attribute value", key, key_len); + return -1; + } + return 0; +} + + +static int wps_validate_network_key_shareable(const u8 *val, int mandatory) +{ + if (val == NULL) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Network Key " + "Shareable attribute missing"); + return -1; + } + return 0; + } + if (*val > 1) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Network Key " + "Shareable attribute value 0x%x", *val); + return -1; + } + return 0; +} + + +static int wps_validate_cred(const u8 *cred, size_t len) +{ + struct wps_parse_attr *attr; + struct wpabuf buf; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (cred == NULL) { + ret = -1; + goto _out; + } + wpabuf_set(&buf, cred, len); + if (wps_parse_msg(&buf, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse Credential"); + ret = -1; + goto _out; + } + + if (wps_validate_network_idx(attr->network_idx, 1) || + wps_validate_ssid(attr->ssid, attr->ssid_len, 1) || + wps_validate_auth_type(attr->auth_type, 1) || + wps_validate_encr_type(attr->encr_type, 1) || + wps_validate_network_key_index(attr->network_key_idx, 0) || + wps_validate_network_key(attr->network_key, attr->network_key_len, + attr->encr_type, 1) || + wps_validate_mac_addr(attr->mac_addr, 1) || + wps_validate_network_key_shareable(attr->network_key_shareable, 0)) + { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Credential"); + ret = -1; + goto _out; + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +static int wps_validate_credential(const u8 *cred[], size_t len[], size_t num, + int mandatory) +{ + size_t i; + + if (num == 0) { + if (mandatory) { + wpa_printf(MSG_INFO, "WPS-STRICT: Credential " + "attribute missing"); + return -1; + } + return 0; + } + + for (i = 0; i < num; i++) { + if (wps_validate_cred(cred[i], len[i]) < 0) + return -1; + } + + return 0; +} + + +int wps_validate_beacon(const struct wpabuf *wps_ie) +{ + struct wps_parse_attr *attr; + int wps2, sel_reg; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (wps_ie == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No WPS IE in Beacon frame"); + ret = -1; + goto _out; + } + if (wps_parse_msg(wps_ie, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse WPS IE in " + "Beacon frame"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + sel_reg = attr->selected_registrar != NULL && + *attr->selected_registrar != 0; + if (wps_validate_version(attr->version, 1) || + wps_validate_wps_state(attr->wps_state, 1) || + wps_validate_ap_setup_locked(attr->ap_setup_locked, 0) || + wps_validate_selected_registrar(attr->selected_registrar, 0) || + wps_validate_dev_password_id(attr->dev_password_id, sel_reg) || + wps_validate_sel_reg_config_methods(attr->sel_reg_config_methods, + wps2, sel_reg) || + wps_validate_uuid_e(attr->uuid_e, 0) || + wps_validate_rf_bands(attr->rf_bands, 0) || + wps_validate_version2(attr->version2, wps2) || + wps_validate_authorized_macs(attr->authorized_macs, + attr->authorized_macs_len, 0)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Beacon frame"); + ret = -1; + goto _out; + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_beacon_probe_resp(const struct wpabuf *wps_ie, int probe, + const u8 *addr) +{ + struct wps_parse_attr *attr; + int wps2, sel_reg; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (wps_ie == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No WPS IE in " + "%sProbe Response frame", probe ? "" : "Beacon/"); + ret = -1; + goto _out; + } + if (wps_parse_msg(wps_ie, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse WPS IE in " + "%sProbe Response frame", probe ? "" : "Beacon/"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + sel_reg = attr->selected_registrar != NULL && + *attr->selected_registrar != 0; + if (wps_validate_version(attr->version, 1) || + wps_validate_wps_state(attr->wps_state, 1) || + wps_validate_ap_setup_locked(attr->ap_setup_locked, 0) || + wps_validate_selected_registrar(attr->selected_registrar, 0) || + wps_validate_dev_password_id(attr->dev_password_id, sel_reg) || + wps_validate_sel_reg_config_methods(attr->sel_reg_config_methods, + wps2, sel_reg) || + wps_validate_response_type(attr->response_type, probe) || + wps_validate_uuid_e(attr->uuid_e, probe) || + wps_validate_manufacturer(attr->manufacturer, attr->manufacturer_len, + probe) || + wps_validate_model_name(attr->model_name, attr->model_name_len, + probe) || + wps_validate_model_number(attr->model_number, attr->model_number_len, + probe) || + wps_validate_serial_number(attr->serial_number, + attr->serial_number_len, probe) || + wps_validate_primary_dev_type(attr->primary_dev_type, probe) || + wps_validate_dev_name(attr->dev_name, attr->dev_name_len, probe) || + wps_validate_ap_config_methods(attr->config_methods, wps2, probe) || + wps_validate_rf_bands(attr->rf_bands, 0) || + wps_validate_version2(attr->version2, wps2) || + wps_validate_authorized_macs(attr->authorized_macs, + attr->authorized_macs_len, 0)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid %sProbe Response " + "frame from " MACSTR, probe ? "" : "Beacon/", + MAC2STR(addr)); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret = -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_probe_req(const struct wpabuf *wps_ie, const u8 *addr) +{ + struct wps_parse_attr *attr; + int wps2; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (wps_ie == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No WPS IE in " + "Probe Request frame"); + ret = -1; + goto _out; + } + if (wps_parse_msg(wps_ie, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse WPS IE in " + "Probe Request frame"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + if (wps_validate_version(attr->version, 1) || + wps_validate_request_type(attr->request_type, 1) || + wps_validate_config_methods(attr->config_methods, wps2, 1) || + wps_validate_uuid_e(attr->uuid_e, attr->uuid_r == NULL) || + wps_validate_uuid_r(attr->uuid_r, attr->uuid_e == NULL) || + wps_validate_primary_dev_type(attr->primary_dev_type, 1) || + wps_validate_rf_bands(attr->rf_bands, 1) || + wps_validate_assoc_state(attr->assoc_state, 1) || + wps_validate_config_error(attr->config_error, 1) || + wps_validate_dev_password_id(attr->dev_password_id, 1) || + wps_validate_version2(attr->version2, wps2) || + wps_validate_manufacturer(attr->manufacturer, attr->manufacturer_len, + wps2) || + wps_validate_model_name(attr->model_name, attr->model_name_len, + wps2) || + wps_validate_model_number(attr->model_number, attr->model_number_len, + wps2) || + wps_validate_dev_name(attr->dev_name, attr->dev_name_len, wps2) || + wps_validate_request_to_enroll(attr->request_to_enroll, 0) || + wps_validate_req_dev_type(attr->req_dev_type, attr->num_req_dev_type, + 0)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid Probe Request " + "frame from " MACSTR, MAC2STR(addr)); + ret = -1; + goto _out; + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_assoc_req(const struct wpabuf *wps_ie) +{ + struct wps_parse_attr *attr; + int wps2; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (wps_ie == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No WPS IE in " + "(Re)Association Request frame"); + ret = -1; + goto _out; + } + if (wps_parse_msg(wps_ie, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse WPS IE in " + "(Re)Association Request frame"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + if (wps_validate_version(attr->version, 1) || + wps_validate_request_type(attr->request_type, 1) || + wps_validate_version2(attr->version2, wps2)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid (Re)Association " + "Request frame"); + ret = -1; + goto _out; + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_assoc_resp(const struct wpabuf *wps_ie) +{ + struct wps_parse_attr *attr; + int wps2; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + + if (wps_ie == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No WPS IE in " + "(Re)Association Response frame"); + ret = -1; + goto _out; + } + if (wps_parse_msg(wps_ie, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse WPS IE in " + "(Re)Association Response frame"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + if (wps_validate_version(attr->version, 1) || + wps_validate_response_type(attr->response_type, 1) || + wps_validate_version2(attr->version2, wps2)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid (Re)Association " + "Response frame"); + ret = -1; + goto _out; + } + + ret = 0; +_out: + if(attr) + os_free(attr); + + return ret; +} + + +int wps_validate_m1(const struct wpabuf *tlvs) +{ + struct wps_parse_attr *attr; + int wps2; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M1"); + ret = -1; + goto _out; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in M1"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + if (wps_validate_version(attr->version, 1) || + wps_validate_msg_type(attr->msg_type, 1) || + wps_validate_uuid_e(attr->uuid_e, 1) || + wps_validate_mac_addr(attr->mac_addr, 1) || + wps_validate_enrollee_nonce(attr->enrollee_nonce, 1) || + wps_validate_public_key(attr->public_key, attr->public_key_len, 1) || + wps_validate_auth_type_flags(attr->auth_type_flags, 1) || + wps_validate_encr_type_flags(attr->encr_type_flags, 1) || + wps_validate_conn_type_flags(attr->conn_type_flags, 1) || + wps_validate_config_methods(attr->config_methods, wps2, 1) || + wps_validate_wps_state(attr->wps_state, 1) || + wps_validate_manufacturer(attr->manufacturer, attr->manufacturer_len, + 1) || + wps_validate_model_name(attr->model_name, attr->model_name_len, 1) || + wps_validate_model_number(attr->model_number, attr->model_number_len, + 1) || + wps_validate_serial_number(attr->serial_number, + attr->serial_number_len, 1) || + wps_validate_primary_dev_type(attr->primary_dev_type, 1) || + wps_validate_dev_name(attr->dev_name, attr->dev_name_len, 1) || + wps_validate_rf_bands(attr->rf_bands, 1) || + wps_validate_assoc_state(attr->assoc_state, 1) || + wps_validate_dev_password_id(attr->dev_password_id, 1) || + wps_validate_config_error(attr->config_error, 1) || + wps_validate_os_version(attr->os_version, 1) || + wps_validate_version2(attr->version2, wps2) || + wps_validate_request_to_enroll(attr->request_to_enroll, 0)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M1"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret = -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_m2(const struct wpabuf *tlvs) +{ + struct wps_parse_attr *attr; + int wps2; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M2"); + ret = -1; + goto _out; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in M2"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + if (wps_validate_version(attr->version, 1) || + wps_validate_msg_type(attr->msg_type, 1) || + wps_validate_enrollee_nonce(attr->enrollee_nonce, 1) || + wps_validate_registrar_nonce(attr->registrar_nonce, 1) || + wps_validate_uuid_r(attr->uuid_r, 1) || + wps_validate_public_key(attr->public_key, attr->public_key_len, 1) || + wps_validate_auth_type_flags(attr->auth_type_flags, 1) || + wps_validate_encr_type_flags(attr->encr_type_flags, 1) || + wps_validate_conn_type_flags(attr->conn_type_flags, 1) || + wps_validate_config_methods(attr->config_methods, wps2, 1) || + wps_validate_manufacturer(attr->manufacturer, attr->manufacturer_len, + 1) || + wps_validate_model_name(attr->model_name, attr->model_name_len, 1) || + wps_validate_model_number(attr->model_number, attr->model_number_len, + 1) || + wps_validate_serial_number(attr->serial_number, + attr->serial_number_len, 1) || + wps_validate_primary_dev_type(attr->primary_dev_type, 1) || + wps_validate_dev_name(attr->dev_name, attr->dev_name_len, 1) || + wps_validate_rf_bands(attr->rf_bands, 1) || + wps_validate_assoc_state(attr->assoc_state, 1) || + wps_validate_config_error(attr->config_error, 1) || + wps_validate_dev_password_id(attr->dev_password_id, 1) || + wps_validate_os_version(attr->os_version, 1) || + wps_validate_version2(attr->version2, wps2) || + wps_validate_authenticator(attr->authenticator, 1)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M2"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret = -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_m2d(const struct wpabuf *tlvs) +{ + struct wps_parse_attr *attr; + int wps2; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M2D"); + ret = -1; + goto _out; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in M2D"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + if (wps_validate_version(attr->version, 1) || + wps_validate_msg_type(attr->msg_type, 1) || + wps_validate_enrollee_nonce(attr->enrollee_nonce, 1) || + wps_validate_registrar_nonce(attr->registrar_nonce, 1) || + wps_validate_uuid_r(attr->uuid_r, 1) || + wps_validate_auth_type_flags(attr->auth_type_flags, 1) || + wps_validate_encr_type_flags(attr->encr_type_flags, 1) || + wps_validate_conn_type_flags(attr->conn_type_flags, 1) || + wps_validate_config_methods(attr->config_methods, wps2, 1) || + wps_validate_manufacturer(attr->manufacturer, attr->manufacturer_len, + 1) || + wps_validate_model_name(attr->model_name, attr->model_name_len, 1) || + wps_validate_model_number(attr->model_number, attr->model_number_len, + 1) || + wps_validate_serial_number(attr->serial_number, + attr->serial_number_len, 1) || + wps_validate_primary_dev_type(attr->primary_dev_type, 1) || + wps_validate_dev_name(attr->dev_name, attr->dev_name_len, 1) || + wps_validate_rf_bands(attr->rf_bands, 1) || + wps_validate_assoc_state(attr->assoc_state, 1) || + wps_validate_config_error(attr->config_error, 1) || + wps_validate_os_version(attr->os_version, 1) || + wps_validate_version2(attr->version2, wps2)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M2D"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret = -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_m3(const struct wpabuf *tlvs) +{ + struct wps_parse_attr *attr; + int wps2; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M3"); + ret = -1; + goto _out; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in M3"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + if (wps_validate_version(attr->version, 1) || + wps_validate_msg_type(attr->msg_type, 1) || + wps_validate_registrar_nonce(attr->registrar_nonce, 1) || + wps_validate_e_hash1(attr->e_hash1, 1) || + wps_validate_e_hash2(attr->e_hash2, 1) || + wps_validate_version2(attr->version2, wps2) || + wps_validate_authenticator(attr->authenticator, 1)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M3"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret = -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_m4(const struct wpabuf *tlvs) +{ + struct wps_parse_attr *attr; + int wps2; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M4"); + ret = -1; + goto _out; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in M4"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + if (wps_validate_version(attr->version, 1) || + wps_validate_msg_type(attr->msg_type, 1) || + wps_validate_enrollee_nonce(attr->enrollee_nonce, 1) || + wps_validate_r_hash1(attr->r_hash1, 1) || + wps_validate_r_hash2(attr->r_hash2, 1) || + wps_validate_encr_settings(attr->encr_settings, + attr->encr_settings_len, 1) || + wps_validate_version2(attr->version2, wps2) || + wps_validate_authenticator(attr->authenticator, 1)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M4"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret = -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_m4_encr(const struct wpabuf *tlvs, int wps2) +{ + struct wps_parse_attr *attr; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M4 encrypted " + "settings"); + ret = -1; + goto _out; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in M4 encrypted settings"); + ret = -1; + goto _out; + } + + if (wps_validate_r_snonce1(attr->r_snonce1, 1) || + wps_validate_key_wrap_auth(attr->key_wrap_auth, 1)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M4 encrypted " + "settings"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret = -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_m5(const struct wpabuf *tlvs) +{ + struct wps_parse_attr *attr; + int wps2; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M5"); + ret = -1; + goto _out; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in M5"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + if (wps_validate_version(attr->version, 1) || + wps_validate_msg_type(attr->msg_type, 1) || + wps_validate_registrar_nonce(attr->registrar_nonce, 1) || + wps_validate_encr_settings(attr->encr_settings, + attr->encr_settings_len, 1) || + wps_validate_version2(attr->version2, wps2) || + wps_validate_authenticator(attr->authenticator, 1)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M5"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret = -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_m5_encr(const struct wpabuf *tlvs, int wps2) +{ + struct wps_parse_attr *attr; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M5 encrypted " + "settings"); + ret = -1; + goto _out; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in M5 encrypted settings"); + ret = -1; + goto _out; + } + + if (wps_validate_e_snonce1(attr->e_snonce1, 1) || + wps_validate_key_wrap_auth(attr->key_wrap_auth, 1)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M5 encrypted " + "settings"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret = -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_m6(const struct wpabuf *tlvs) +{ + struct wps_parse_attr *attr; + int wps2; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M6"); + ret = -1; + goto _out; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in M6"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + if (wps_validate_version(attr->version, 1) || + wps_validate_msg_type(attr->msg_type, 1) || + wps_validate_enrollee_nonce(attr->enrollee_nonce, 1) || + wps_validate_encr_settings(attr->encr_settings, + attr->encr_settings_len, 1) || + wps_validate_version2(attr->version2, wps2) || + wps_validate_authenticator(attr->authenticator, 1)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M6"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret = -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_m6_encr(const struct wpabuf *tlvs, int wps2) +{ + struct wps_parse_attr *attr; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M6 encrypted " + "settings"); + ret = -1; + goto _out; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in M6 encrypted settings"); + ret = -1; + goto _out; + } + + if (wps_validate_r_snonce2(attr->r_snonce2, 1) || + wps_validate_key_wrap_auth(attr->key_wrap_auth, 1)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M6 encrypted " + "settings"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret = -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_m7(const struct wpabuf *tlvs) +{ + struct wps_parse_attr *attr; + int wps2; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M7"); + ret = -1; + goto _out; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in M7"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + if (wps_validate_version(attr->version, 1) || + wps_validate_msg_type(attr->msg_type, 1) || + wps_validate_registrar_nonce(attr->registrar_nonce, 1) || + wps_validate_encr_settings(attr->encr_settings, + attr->encr_settings_len, 1) || + wps_validate_settings_delay_time(attr->settings_delay_time, 0) || + wps_validate_version2(attr->version2, wps2) || + wps_validate_authenticator(attr->authenticator, 1)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M7"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret = -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_m7_encr(const struct wpabuf *tlvs, int ap, int wps2) +{ + struct wps_parse_attr *attr; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M7 encrypted " + "settings"); + ret = -1; + goto _out; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in M7 encrypted settings"); + ret = -1; + goto _out; + } + + if (wps_validate_e_snonce2(attr->e_snonce2, 1) || + wps_validate_ssid(attr->ssid, attr->ssid_len, !ap) || + wps_validate_mac_addr(attr->mac_addr, !ap) || + wps_validate_auth_type(attr->auth_type, !ap) || + wps_validate_encr_type(attr->encr_type, !ap) || + wps_validate_network_key_index(attr->network_key_idx, 0) || + wps_validate_network_key(attr->network_key, attr->network_key_len, + attr->encr_type, !ap) || + wps_validate_key_wrap_auth(attr->key_wrap_auth, 1)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M7 encrypted " + "settings"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret = -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_m8(const struct wpabuf *tlvs) +{ + struct wps_parse_attr *attr; + int wps2; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M8"); + ret = -1; + goto _out; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in M8"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + if (wps_validate_version(attr->version, 1) || + wps_validate_msg_type(attr->msg_type, 1) || + wps_validate_enrollee_nonce(attr->enrollee_nonce, 1) || + wps_validate_encr_settings(attr->encr_settings, + attr->encr_settings_len, 1) || + wps_validate_version2(attr->version2, wps2) || + wps_validate_authenticator(attr->authenticator, 1)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M8"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret = -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_m8_encr(const struct wpabuf *tlvs, int ap, int wps2) +{ + struct wps_parse_attr *attr; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in M8 encrypted " + "settings"); + ret = -1; + goto _out; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in M8 encrypted settings"); + ret = -1; + goto _out; + } + + if (wps_validate_ssid(attr->ssid, attr->ssid_len, ap) || + wps_validate_auth_type(attr->auth_type, ap) || + wps_validate_encr_type(attr->encr_type, ap) || + wps_validate_network_key_index(attr->network_key_idx, 0) || + wps_validate_mac_addr(attr->mac_addr, ap) || + wps_validate_credential(attr->cred, attr->cred_len, attr->num_cred, + !ap) || + wps_validate_key_wrap_auth(attr->key_wrap_auth, 1)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid M8 encrypted " + "settings"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret = -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_wsc_ack(const struct wpabuf *tlvs) +{ + struct wps_parse_attr *attr; + int wps2; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in WSC_ACK"); + ret = -1; + goto _out; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in WSC_ACK"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + if (wps_validate_version(attr->version, 1) || + wps_validate_msg_type(attr->msg_type, 1) || + wps_validate_enrollee_nonce(attr->enrollee_nonce, 1) || + wps_validate_registrar_nonce(attr->registrar_nonce, 1) || + wps_validate_version2(attr->version2, wps2)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid WSC_ACK"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret = -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_wsc_nack(const struct wpabuf *tlvs) +{ + struct wps_parse_attr *attr; + int wps2; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in WSC_NACK"); + ret = -1; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in WSC_NACK"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + if (wps_validate_version(attr->version, 1) || + wps_validate_msg_type(attr->msg_type, 1) || + wps_validate_enrollee_nonce(attr->enrollee_nonce, 1) || + wps_validate_registrar_nonce(attr->registrar_nonce, 1) || + wps_validate_config_error(attr->config_error, 1) || + wps_validate_version2(attr->version2, wps2)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid WSC_NACK"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + goto _out; + ret = -1; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_wsc_done(const struct wpabuf *tlvs) +{ + struct wps_parse_attr *attr; + int wps2; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in WSC_Done"); + ret = -1; + goto _out; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in WSC_Done"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + if (wps_validate_version(attr->version, 1) || + wps_validate_msg_type(attr->msg_type, 1) || + wps_validate_enrollee_nonce(attr->enrollee_nonce, 1) || + wps_validate_registrar_nonce(attr->registrar_nonce, 1) || + wps_validate_version2(attr->version2, wps2)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid WSC_Done"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret = -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} + + +int wps_validate_upnp_set_selected_registrar(const struct wpabuf *tlvs) +{ + struct wps_parse_attr *attr; + int wps2; + int sel_reg; + int ret; + + attr = (struct wps_parse_attr *)os_zalloc(sizeof(struct wps_parse_attr)); + if (attr == NULL) { + ret = -99; + goto _out; + } + + if (tlvs == NULL) { + wpa_printf(MSG_INFO, "WPS-STRICT: No TLVs in " + "SetSelectedRegistrar"); + ret = -1; + goto _out; + } + if (wps_parse_msg(tlvs, attr) < 0) { + wpa_printf(MSG_INFO, "WPS-STRICT: Failed to parse attributes " + "in SetSelectedRegistrar"); + ret = -1; + goto _out; + } + + wps2 = attr->version2 != NULL; + sel_reg = attr->selected_registrar != NULL && + *attr->selected_registrar != 0; + if (wps_validate_version(attr->version, 1) || + wps_validate_dev_password_id(attr->dev_password_id, sel_reg) || + wps_validate_sel_reg_config_methods(attr->sel_reg_config_methods, + wps2, sel_reg) || + wps_validate_version2(attr->version2, wps2) || + wps_validate_authorized_macs(attr->authorized_macs, + attr->authorized_macs_len, wps2) || + wps_validate_uuid_r(attr->uuid_r, wps2)) { + wpa_printf(MSG_INFO, "WPS-STRICT: Invalid " + "SetSelectedRegistrar"); +#ifdef WPS_STRICT_WPS2 + if (wps2) { + ret = -1; + goto _out; + } +#else /* WPS_STRICT_WPS2 */ + ret -1; + goto _out; +#endif /* WPS_STRICT_WPS2 */ + } + + ret = 0; +_out: + if (attr) + os_free(attr); + + return ret; +} From 3b44e24db0cd61b41e9f029f96729ed81fe91550 Mon Sep 17 00:00:00 2001 From: XuanZe <119524428@qq.com> Date: Tue, 20 Mar 2018 16:52:11 +0800 Subject: [PATCH 052/187] Update index.rst. Merges https://github.com/espressif/esp-idf/pull/1747 --- docs/zh_CN/index.rst | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/zh_CN/index.rst b/docs/zh_CN/index.rst index 9aaab7c30c..7fa2d991fc 100644 --- a/docs/zh_CN/index.rst +++ b/docs/zh_CN/index.rst @@ -1,47 +1,47 @@ -ESP-IDF Programming Guide +ESP-IDF 编程指南 ========================= -This is the documentation for Espressif IoT Development Framework (`esp-idf `_). ESP-IDF is the official development framework for the `ESP32 `_ chip. +这是乐鑫 IoT 开发开发框架 (`esp-idf `_)的文档. ESP-IDF 是`ESP32 `_ 芯片的官方开发框架. ================== ================== ================== -|快速入门|_ |API Reference|_ |H/W Reference|_ +|快速入门|_ |API 参考|_ |H/W 参考|_ ------------------ ------------------ ------------------ -`快速入门`_ `API Reference`_ `H/W Reference`_ +`快速入门`_ `API 参考`_ `H/W 参考`_ ------------------ ------------------ ------------------ -|API Guides|_ |Contribute|_ |Resources|_ +|API 指南|_ |贡献代码|_ |相关资源|_ ------------------ ------------------ ------------------ -`API Guides`_ `Contribute`_ `Resources`_ +`API 指南`_ `贡献代码`_ `相关资源`_ ================== ================== ================== .. |快速入门| image:: ../_static/get-started.gif .. _快速入门: get-started/index.html -.. |API Reference| image:: ../_static/api-reference.gif -.. _API Reference: api-reference/index.html +.. |API 参考| image:: ../_static/api-reference.gif +.. _API 参考: api-reference/index.html -.. |H/W Reference| image:: ../_static/hw-reference.gif -.. _H/W Reference: hw-reference/index.html +.. |H/W 参考| image:: ../_static/hw-reference.gif +.. _H/W 参考: hw-reference/index.html -.. |Api Guides| image:: ../_static/api-guides.gif -.. _Api Guides: api-guides/index.html +.. |Api 指南| image:: ../_static/api-guides.gif +.. _API 指南: api-guides/index.html -.. |Contribute| image:: ../_static/contribute.gif -.. _Contribute: contribute/index.html +.. |贡献代码| image:: ../_static/contribute.gif +.. _贡献代码: contribute/index.html -.. |Resources| image:: ../_static/resources.gif -.. _Resources: resources.html +.. |相关资源| image:: ../_static/resources.gif +.. _相关资源: resources.html .. toctree:: :hidden: 快速入门 - API Reference - H/W Reference - API Guides - Contribute - Resources + API 参考 + H/W 参考 + API 指南 + 贡献代码 + 相关资源 Copyrights About From 58b2cb3e0c7b2c7790fdd54433b5c8439098ff56 Mon Sep 17 00:00:00 2001 From: zhiweijian Date: Thu, 26 Apr 2018 17:03:11 +0800 Subject: [PATCH 053/187] Component/bt: update con params is rejected in smp when reconnection --- components/bt/bluedroid/bta/gatt/bta_gattc_co.c | 4 +++- components/bt/bluedroid/stack/btm/btm_sec.c | 6 ++++++ components/bt/lib | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_co.c b/components/bt/bluedroid/bta/gatt/bta_gattc_co.c index e6b49cb381..6c6fc460d3 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_co.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_co.c @@ -331,7 +331,9 @@ void bta_gattc_co_cache_addr_init(void) cache_env.addr_fp = fp; // Read previously saved blob if available if ((err_code = nvs_get_blob(fp, cache_key, p_buf, &length)) != ESP_OK) { - APPL_TRACE_ERROR("%s, Line = %d, nvs flash get blob data fail, err_code = %x", __func__, __LINE__, err_code); + if(err_code != ESP_ERR_NVS_NOT_FOUND) { + APPL_TRACE_ERROR("%s, Line = %d, nvs flash get blob data fail, err_code = 0x%x", __func__, __LINE__, err_code); + } osi_free(p_buf); return; } diff --git a/components/bt/bluedroid/stack/btm/btm_sec.c b/components/bt/bluedroid/stack/btm/btm_sec.c index 00923e9f80..c238051e76 100644 --- a/components/bt/bluedroid/stack/btm/btm_sec.c +++ b/components/bt/bluedroid/stack/btm/btm_sec.c @@ -4018,6 +4018,7 @@ void btm_sec_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable) #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE tACL_CONN *p_acl = NULL; UINT8 acl_idx = btm_handle_to_acl_index(handle); + tGATT_TCB *p_tcb = NULL; #endif BTM_TRACE_EVENT ("Security Manager: encrypt_change status:%d State:%d, encr_enable = %d\n", status, (p_dev_rec) ? p_dev_rec->sec_state : 0, encr_enable); @@ -4045,6 +4046,11 @@ void btm_sec_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable) p_dev_rec->sec_flags |= BTM_SEC_16_DIGIT_PIN_AUTHED; } } else { +#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE + if ((p_tcb = gatt_find_tcb_by_addr(p_dev_rec->ble.pseudo_addr, BT_TRANSPORT_LE)) == NULL) { + //do nothing + } else +#endif p_dev_rec->sec_flags |= (BTM_SEC_LE_AUTHENTICATED | BTM_SEC_LE_ENCRYPTED); } } diff --git a/components/bt/lib b/components/bt/lib index 34b64038d0..a3e98f8314 160000 --- a/components/bt/lib +++ b/components/bt/lib @@ -1 +1 @@ -Subproject commit 34b64038d090fa172d9757e2fce293ff26e0a08c +Subproject commit a3e98f83144ee46c6ec9b53b1c838bcefdf26e97 From cb59576dd0d4bb3ba35c886a0b965b7d5e6240fb Mon Sep 17 00:00:00 2001 From: zhiweijian Date: Fri, 4 May 2018 21:11:13 +0800 Subject: [PATCH 054/187] Component/bt: fix service change write busy --- components/bt/Kconfig | 9 - .../bt/bluedroid/bta/gatt/bta_gattc_act.c | 208 +++--------------- .../bt/bluedroid/bta/gatt/bta_gattc_utils.c | 4 - .../bta/gatt/include/bta_gattc_int.h | 5 +- 4 files changed, 27 insertions(+), 199 deletions(-) diff --git a/components/bt/Kconfig b/components/bt/Kconfig index 9ede56cf09..b46f872317 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -168,15 +168,6 @@ config BLE_SMP_ENABLE help This option can be close when the app not used the ble security connect. -config BLE_ENABLE_SRVCHG_REG - bool "Enable automatic service change notify registration" - depends on BLUEDROID_ENABLED - default y - help - This option enables automatic registration of service change notification - after connect. Be careful, it can may collide with your command sequences - and lead to GATT_BUSY. - config BT_STACK_NO_LOG bool "Close the bluedroid bt stack log print" depends on BLUEDROID_ENABLED diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c index 1373ca52bc..8eace1a0a1 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c @@ -65,10 +65,7 @@ static void bta_gattc_pop_command_to_send(tBTA_GATTC_CLCB *p_clcb); static void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg); static void bta_gattc_enc_cmpl_cback(tGATT_IF gattc_if, BD_ADDR bda); static void bta_gattc_cong_cback (UINT16 conn_id, BOOLEAN congested); -static tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_id, BD_ADDR remote_bda, BOOLEAN *need_timer); -static void bta_gattc_wait4_service_change_ccc_cback (TIMER_LIST_ENT *p_tle); -static void bta_gattc_start_service_change_ccc_timer(UINT16 conn_id, BD_ADDR bda,UINT32 timeout_ms, - UINT8 timer_cnt, UINT8 last_status, TIMER_LIST_ENT *ccc_timer); +static tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_id, BD_ADDR remote_bda); static tGATT_CBACK bta_gattc_cl_cback = { bta_gattc_conn_cback, @@ -126,8 +123,6 @@ static void bta_gattc_enable(tBTA_GATTC_CB *p_cb) /* initialize control block */ memset(&bta_gattc_cb, 0, sizeof(tBTA_GATTC_CB)); p_cb->state = BTA_GATTC_STATE_ENABLED; - // Create a write ccc mutex when the gatt client enable - osi_mutex_new(&bta_gattc_cb.write_ccc_mutex); } else { APPL_TRACE_DEBUG("GATTC is already enabled"); } @@ -154,8 +149,6 @@ void bta_gattc_disable(tBTA_GATTC_CB *p_cb) APPL_TRACE_ERROR("not enabled or disable in pogress"); return; } - // Free the write ccc mutex when the gatt client disable - osi_mutex_free(&bta_gattc_cb.write_ccc_mutex); for (i = 0; i < BTA_GATTC_CL_MAX; i ++) { if (p_cb->cl_rcb[i].in_use) { @@ -1054,6 +1047,10 @@ void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) p_q_cmd = NULL; } } + + //register service change + bta_gattc_register_service_change_notify(p_clcb->bta_conn_id, p_clcb->bda); + } /******************************************************************************* ** @@ -1270,12 +1267,12 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) { tBTA_GATTC cb_data = {0}; UINT8 event; + tBTA_GATTC_CONN *p_conn = bta_gattc_conn_find(p_clcb->bda); memset(&cb_data, 0, sizeof(tBTA_GATTC)); cb_data.write.status = p_data->status; cb_data.write.handle = p_data->p_cmpl->att_value.handle; - if (p_clcb->p_q_cmd->api_write.hdr.event == BTA_GATTC_API_WRITE_EVT && p_clcb->p_q_cmd->api_write.write_type == BTA_GATTC_WRITE_PREPARE) { // Should check the value received from the peer device is correct or not. @@ -1292,6 +1289,12 @@ void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) bta_gattc_free_command_data(p_clcb); bta_gattc_pop_command_to_send(p_clcb); cb_data.write.conn_id = p_clcb->bta_conn_id; + if (p_conn && p_conn->svc_change_descr_handle == cb_data.write.handle) { + if(cb_data.write.status != BTA_GATT_OK) { + APPL_TRACE_ERROR("service change write ccc failed"); + } + return; + } /* write complete, callback */ ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data); @@ -1618,60 +1621,12 @@ static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id, tBT_TRANSPORT transport) { tBTA_GATTC_DATA *p_buf; - BOOLEAN start_ccc_timer = FALSE; - tBTA_GATTC_CONN *p_conn = NULL; - tBTA_GATTC_FIND_SERVICE_CB result; if (reason != 0) { APPL_TRACE_WARNING("%s() - cif=%d connected=%d conn_id=%d reason=0x%04x", __FUNCTION__, gattc_if, connected, conn_id, reason); } - if (connected == TRUE){ - p_conn = bta_gattc_conn_find_alloc(bda); - } - else if (connected == FALSE){ - p_conn = bta_gattc_conn_find(bda); - } - - if (p_conn == NULL){ - APPL_TRACE_ERROR("p_conn is NULL in %s\n", __func__); - } - - if ((transport == BT_TRANSPORT_LE) && (connected == TRUE) && (p_conn != NULL) \ - && (p_conn->service_change_ccc_written == FALSE) && (p_conn->ccc_timer_used == FALSE)) { -#ifdef CONFIG_BLE_ENABLE_SRVCHG_REG - result = bta_gattc_register_service_change_notify(conn_id, bda, &start_ccc_timer); -#endif - if (start_ccc_timer == TRUE) { - TIMER_LIST_ENT *ccc_timer = &(p_conn->service_change_ccc_timer); - /* start a 1000ms timer to wait for service discovery finished */ - bta_gattc_start_service_change_ccc_timer(conn_id, bda, 1000, 0, result, ccc_timer); - p_conn->ccc_timer_used = TRUE; - } - else { - /* Has written service change ccc; or service change ccc doesn't exist in remote device's gatt database */ - p_conn->service_change_ccc_written = TRUE; - p_conn->ccc_timer_used = FALSE; - } - - } - else if ((transport == BT_TRANSPORT_LE) && (connected == FALSE) && (p_conn != NULL)){ - p_conn->service_change_ccc_written = FALSE; - if (p_conn->ccc_timer_used == TRUE){ - assert(bta_gattc_cb.write_ccc_mutex != NULL); - osi_mutex_lock(&bta_gattc_cb.write_ccc_mutex, OSI_MUTEX_MAX_TIMEOUT); - - if (p_conn->service_change_ccc_timer.param != 0) { - osi_free((void *)p_conn->service_change_ccc_timer.param); - p_conn->service_change_ccc_timer.param = (TIMER_PARAM_TYPE)0; - } - bta_sys_stop_timer(&(p_conn->service_change_ccc_timer)); - p_conn->ccc_timer_used = FALSE; - osi_mutex_unlock(&bta_gattc_cb.write_ccc_mutex); - } - } - bt_bdaddr_t bdaddr; bdcpy(bdaddr.address, bda); @@ -1891,7 +1846,7 @@ BOOLEAN bta_gattc_process_srvc_chg_ind(UINT16 conn_id, UINT16 s_handle = ((UINT16)(*(p )) + (((UINT16)(*(p + 1))) << 8)); UINT16 e_handle = ((UINT16)(*(p + 2)) + (((UINT16)(*(p + 3))) << 8)); - APPL_TRACE_ERROR("%s: service changed s_handle:0x%04x e_handle:0x%04x", + APPL_TRACE_DEBUG("%s: service changed s_handle:0x%04x e_handle:0x%04x", __func__, s_handle, e_handle); processed = TRUE; @@ -2276,58 +2231,28 @@ void bta_gattc_broadcast(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg) } } -/******************************************************************************* -** -** Function bta_gattc_start_service_change_ccc_timer -** -** Description start a timer to wait for service change ccc discovered -** -** Returns void -** -*******************************************************************************/ -void bta_gattc_start_service_change_ccc_timer(UINT16 conn_id, BD_ADDR bda,UINT32 timeout_ms, - UINT8 timer_cnt, UINT8 last_status, TIMER_LIST_ENT *ccc_timer) -{ - tBTA_GATTC_WAIT_CCC_TIMER *p_timer_param = (tBTA_GATTC_WAIT_CCC_TIMER*) osi_malloc(sizeof(tBTA_GATTC_WAIT_CCC_TIMER)); - if (p_timer_param != NULL) { - p_timer_param->conn_id = conn_id; - memcpy(p_timer_param->remote_bda, bda, sizeof(BD_ADDR)); - p_timer_param->count = timer_cnt; - p_timer_param->last_status = last_status; - ccc_timer->param = (UINT32)p_timer_param; - ccc_timer->p_cback = (TIMER_CBACK *)&bta_gattc_wait4_service_change_ccc_cback; - bta_sys_start_timer(ccc_timer, 0, timeout_ms); - } - else { - APPL_TRACE_ERROR("%s, allocate p_timer_param failed\n", __func__); - } -} - /******************************************************************************* ** ** Function bta_gattc_register_service_change_notify ** ** Description Find remote device's gatt service change characteristic ccc's handle and write 2 to this -** this ccc. If not found, start a timer to wait for service discovery finished. +** this ccc. ** -** Returns Return result of service change ccc service discovery result result and written operate result +** Returns Return result of service change ccc service discovery result ** *******************************************************************************/ -tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_id, BD_ADDR remote_bda, BOOLEAN *need_timer) +tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_id, BD_ADDR remote_bda) { tBTA_GATTC_SERV *p_srcb = NULL; list_t *p_cache = NULL; tBTA_GATTC_SERVICE *p_service = NULL; tBTA_GATTC_CHARACTERISTIC *p_char = NULL; tBTA_GATTC_DESCRIPTOR *p_desc = NULL; - tGATT_STATUS write_status; - tGATT_VALUE ccc_value; tBTA_GATTC_FIND_SERVICE_CB result; BOOLEAN gatt_cache_found = FALSE; BOOLEAN gatt_service_found = FALSE; BOOLEAN gatt_service_change_found = FALSE; BOOLEAN gatt_ccc_found = FALSE; - BOOLEAN start_find_ccc_timer = FALSE; tBT_UUID gatt_service_uuid = {LEN_UUID_16, {UUID_SERVCLASS_GATT_SERVER}}; tBT_UUID gatt_service_change_uuid = {LEN_UUID_16, {GATT_UUID_GATT_SRV_CHGD}}; @@ -2339,7 +2264,6 @@ tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_ gatt_cache_found = TRUE; } else { - start_find_ccc_timer = TRUE; result = SERVICE_CHANGE_CACHE_NOT_FOUND; } /* start to find gatt service */ @@ -2354,7 +2278,6 @@ tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_ } } else { - start_find_ccc_timer = TRUE; result = SERVICE_CHANGE_CACHE_NOT_FOUND; } @@ -2373,7 +2296,6 @@ tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_ } else if (gatt_cache_found == TRUE) { /* Gatt service not found, start a timer to wait for service discovery */ - start_find_ccc_timer = TRUE; result = SERVICE_CHANGE_SERVICE_NOT_FOUND; } /* start to find gatt service change characteristic ccc */ @@ -2395,29 +2317,21 @@ tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_ * wait for service discovery * Case2: remote device exist service change char, we have found gatt service, but have not found * service change char, we need to start a timer here*/ - start_find_ccc_timer = TRUE; result = SERVICE_CHANGE_CHAR_NOT_FOUND; } if (gatt_ccc_found == TRUE){ - ccc_value.handle = p_desc->handle; - ccc_value.len = 2; - ccc_value.value[0] = GATT_CLT_CONFIG_INDICATION; - ccc_value.auth_req = GATT_AUTH_REQ_NONE; - if (gatt_is_clcb_allocated(conn_id)) { - APPL_TRACE_DEBUG("%s, GATTC_Write GATT_BUSY conn_id = %d", __func__, conn_id); - write_status = GATT_BUSY; - } else { - write_status = GATTC_Write (conn_id, GATT_WRITE, &ccc_value); - } - if (write_status != GATT_SUCCESS) { - start_find_ccc_timer = TRUE; - result = SERVICE_CHANGE_WRITE_CCC_FAILED; - } - else { - start_find_ccc_timer = FALSE; - result = SERVICE_CHANGE_CCC_WRITTEN_SUCCESS; + tBTA_GATTC_CONN *p_conn = bta_gattc_conn_find_alloc(remote_bda); + if (p_conn) { + p_conn->svc_change_descr_handle = p_desc->handle; } + result = SERVICE_CHANGE_CCC_WRITTEN_SUCCESS; + uint16_t indicate_value = GATT_CLT_CONFIG_INDICATION; + tBTA_GATT_UNFMT indicate_v; + indicate_v.len = 2; + indicate_v.p_value = (uint8_t *)&indicate_value; + BTA_GATTC_WriteCharDescr (conn_id, p_desc->handle, BTA_GATTC_TYPE_WRITE, &indicate_v, BTA_GATT_AUTH_REQ_NONE); + } else if (gatt_service_change_found == TRUE) { /* Gatt service char found, but service change char ccc not found, @@ -2425,81 +2339,11 @@ tBTA_GATTC_FIND_SERVICE_CB bta_gattc_register_service_change_notify(UINT16 conn_ * wait for service discovery * Case2: remote device exist service change char ccc, we have found gatt service change char, but have not found * service change char ccc, we need to start a timer here */ - start_find_ccc_timer = TRUE; result = SERVICE_CHANGE_CCC_NOT_FOUND; } - if (need_timer != NULL) { - *need_timer = start_find_ccc_timer; - } - return result; } -/******************************************************************************* -** -** Function bta_gattc_wait4_service_change_ccc_cback -** -** Description callback function of service_change_ccc_timer -** -** Returns None -** -*******************************************************************************/ -static void bta_gattc_wait4_service_change_ccc_cback (TIMER_LIST_ENT *p_tle) -{ - tBTA_GATTC_FIND_SERVICE_CB result; - BOOLEAN start_ccc_timer = FALSE; - UINT32 new_timeout; - - assert(bta_gattc_cb.write_ccc_mutex != NULL); - osi_mutex_lock(&bta_gattc_cb.write_ccc_mutex, OSI_MUTEX_MAX_TIMEOUT); - - tBTA_GATTC_WAIT_CCC_TIMER *p_timer_param = (tBTA_GATTC_WAIT_CCC_TIMER*) p_tle->param; - p_tle->param = (TIMER_PARAM_TYPE)0; - if (p_timer_param == NULL){ - APPL_TRACE_ERROR("p_timer_param is NULL in %s\n", __func__); - osi_mutex_unlock(&bta_gattc_cb.write_ccc_mutex); - return; - } - - tBTA_GATTC_CONN *p_conn = bta_gattc_conn_find(p_timer_param->remote_bda); - if (p_conn == NULL){ - APPL_TRACE_ERROR("p_conn is NULL in %s\n", __func__); - osi_free(p_timer_param); - osi_mutex_unlock(&bta_gattc_cb.write_ccc_mutex); - return; - } - - result = bta_gattc_register_service_change_notify(p_timer_param->conn_id, p_timer_param->remote_bda, &start_ccc_timer); - /* If return SERVICE_CHANGE_CHAR_NOT_FOUND or SERVICE_CHANGE_CCC_NOT_FOUND twice, means remote device doesn't have - * service change char or ccc, stop timer */ - if ((result == p_timer_param->last_status) \ - && ((result == SERVICE_CHANGE_CHAR_NOT_FOUND) || (result == SERVICE_CHANGE_CCC_NOT_FOUND))){ - start_ccc_timer = FALSE; - } - - if ((start_ccc_timer == TRUE) && (p_timer_param->count < 10)){ - TIMER_LIST_ENT *ccc_timer = &(p_conn->service_change_ccc_timer); - if (result == SERVICE_CHANGE_WRITE_CCC_FAILED){ - /* retry to write service change ccc, needn't to add counter */ - new_timeout = 200; - } - else { - /* retry to find service change ccc */ - new_timeout = 1000; - p_timer_param->count ++; - } - bta_gattc_start_service_change_ccc_timer(p_timer_param->conn_id, p_timer_param->remote_bda, \ - new_timeout, p_timer_param->count, result, ccc_timer); - } - else { - p_conn->ccc_timer_used = FALSE; - p_conn->service_change_ccc_written = TRUE; - } - - osi_free(p_timer_param); - osi_mutex_unlock(&bta_gattc_cb.write_ccc_mutex); -} - #endif #endif ///GATTC_INCLUDED == TRUE && BLE_INCLUDED == TRUE diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c index 35dcb0929e..9b3e5c0308 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c @@ -863,10 +863,6 @@ BOOLEAN bta_gattc_conn_dealloc(BD_ADDR remote_bda) if (p_conn != NULL) { p_conn->in_use = FALSE; memset(p_conn->remote_bda, 0, BD_ADDR_LEN); - osi_mutex_lock(&bta_gattc_cb.write_ccc_mutex, OSI_MUTEX_MAX_TIMEOUT); - bta_sys_free_timer(&p_conn->service_change_ccc_timer); - p_conn->ccc_timer_used = FALSE; - osi_mutex_unlock(&bta_gattc_cb.write_ccc_mutex); return TRUE; } return FALSE; diff --git a/components/bt/bluedroid/bta/gatt/include/bta_gattc_int.h b/components/bt/bluedroid/bta/gatt/include/bta_gattc_int.h index 26ab73bf56..89864aacea 100644 --- a/components/bt/bluedroid/bta/gatt/include/bta_gattc_int.h +++ b/components/bt/bluedroid/bta/gatt/include/bta_gattc_int.h @@ -365,9 +365,7 @@ typedef struct { typedef struct { BOOLEAN in_use; BD_ADDR remote_bda; - TIMER_LIST_ENT service_change_ccc_timer; /* wait for discovering remote device's service change ccc handle */ - BOOLEAN ccc_timer_used; /* service_change_ccc_timer started */ - BOOLEAN service_change_ccc_written; /* has written remote device's service change ccc */ + UINT16 svc_change_descr_handle; } tBTA_GATTC_CONN; enum { @@ -379,7 +377,6 @@ enum { typedef struct { UINT8 state; - osi_mutex_t write_ccc_mutex; tBTA_GATTC_CONN conn_track[BTA_GATTC_CONN_MAX]; tBTA_GATTC_BG_TCK bg_track[BTA_GATTC_KNOWN_SR_MAX]; tBTA_GATTC_RCB cl_rcb[BTA_GATTC_CL_MAX]; From 296b280801441f1f10c5660c2f4d54ada4aa0dbd Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 4 May 2018 00:57:24 +0800 Subject: [PATCH 055/187] esp_timer: fix esp_timer_impl_advance not triggering expired timers --- components/esp32/esp_timer_esp32.c | 6 ++- components/esp32/test/test_esp_timer.c | 60 ++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/components/esp32/esp_timer_esp32.c b/components/esp32/esp_timer_esp32.c index 1bc4885756..4f1200515a 100644 --- a/components/esp32/esp_timer_esp32.c +++ b/components/esp32/esp_timer_esp32.c @@ -317,9 +317,13 @@ void esp_timer_impl_advance(int64_t time_us) portENTER_CRITICAL(&s_time_update_lock); uint64_t count = REG_READ(FRC_TIMER_COUNT_REG(1)); + /* Trigger an ISR to handle past alarms and set new one. + * ISR handler will run once we exit the critical section. + */ + REG_WRITE(FRC_TIMER_ALARM_REG(1), 0); REG_WRITE(FRC_TIMER_LOAD_REG(1), 0); s_time_base_us += count / s_timer_ticks_per_us + time_us; - esp_timer_impl_set_alarm(esp_timer_get_next_alarm()); + s_overflow_happened = false; portEXIT_CRITICAL(&s_time_update_lock); } diff --git a/components/esp32/test/test_esp_timer.c b/components/esp32/test/test_esp_timer.c index 4007528bd1..da8d8951cf 100644 --- a/components/esp32/test/test_esp_timer.c +++ b/components/esp32/test/test_esp_timer.c @@ -9,6 +9,7 @@ #include "freertos/task.h" #include "freertos/semphr.h" #include "test_utils.h" +#include "../esp_timer_impl.h" #ifdef CONFIG_ESP_TIMER_PROFILING #define WITH_PROFILING 1 @@ -418,3 +419,62 @@ TEST_CASE("Can delete timer from callback", "[esp_timer]") vSemaphoreDelete(args.notify_from_timer_cb); } + +TEST_CASE("esp_timer_impl_advance moves time base correctly", "[esp_timer]") +{ + ref_clock_init(); + int64_t t0 = esp_timer_get_time(); + const int64_t diff_us = 1000000; + esp_timer_impl_advance(diff_us); + int64_t t1 = esp_timer_get_time(); + int64_t t_delta = t1 - t0; + printf("diff_us=%lld t1-t0=%lld\n", diff_us, t_delta); + TEST_ASSERT_INT_WITHIN(1000, diff_us, (int) t_delta); + ref_clock_deinit(); +} + + +TEST_CASE("after esp_timer_impl_advance, timers run when expected", "[esp_timer]") +{ + typedef struct { + int64_t cb_time; + } test_state_t; + + void timer_func(void* varg) { + test_state_t* arg = (test_state_t*) varg; + arg->cb_time = ref_clock_get(); + } + + ref_clock_init(); + + test_state_t state = { 0 }; + + esp_timer_create_args_t timer_args = { + .callback = &timer_func, + .arg = &state + }; + esp_timer_handle_t timer; + TEST_ESP_OK(esp_timer_create(&timer_args, &timer)); + + const int64_t interval = 10000; + const int64_t advance = 2000; + + printf("test 1\n"); + int64_t t_start = ref_clock_get(); + esp_timer_start_once(timer, interval); + esp_timer_impl_advance(advance); + vTaskDelay(2 * interval / 1000 / portTICK_PERIOD_MS); + + TEST_ASSERT_INT_WITHIN(portTICK_PERIOD_MS * 1000, interval - advance, state.cb_time - t_start); + + printf("test 2\n"); + state.cb_time = 0; + t_start = ref_clock_get(); + esp_timer_start_once(timer, interval); + esp_timer_impl_advance(interval); + vTaskDelay(1); + + TEST_ASSERT(state.cb_time > t_start); + + ref_clock_deinit(); +} From 8c307a5720c66bd80062199a1e9ac3699261931d Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 4 May 2018 12:50:39 +0800 Subject: [PATCH 056/187] sleep: fix deadlock in esp_timer_impl_advance after light sleep When light sleep is started, the other CPU gets halted using DPORT stall mechanism. This can happen while it is inside an esp_timer critical section, which may lead to a deadlock. This change adds functions to take and release esp_timer lock before entering DPORT critical section, preventing the deadlock. --- components/esp32/esp_timer_esp32.c | 10 ++++++++++ components/esp32/esp_timer_impl.h | 15 +++++++++++++++ components/esp32/sleep_modes.c | 6 ++++++ components/esp32/test/test_sleep.c | 29 +++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+) diff --git a/components/esp32/esp_timer_esp32.c b/components/esp32/esp_timer_esp32.c index 4f1200515a..b2c29721b2 100644 --- a/components/esp32/esp_timer_esp32.c +++ b/components/esp32/esp_timer_esp32.c @@ -165,6 +165,16 @@ static inline void IRAM_ATTR timer_count_reload(void) REG_WRITE(FRC_TIMER_LOAD_REG(1), REG_READ(FRC_TIMER_COUNT_REG(1)) - ALARM_OVERFLOW_VAL); } +void esp_timer_impl_lock() +{ + portENTER_CRITICAL(&s_time_update_lock); +} + +void esp_timer_impl_unlock() +{ + portEXIT_CRITICAL(&s_time_update_lock); +} + uint64_t IRAM_ATTR esp_timer_impl_get_time() { uint32_t timer_val; diff --git a/components/esp32/esp_timer_impl.h b/components/esp32/esp_timer_impl.h index 9c4642c474..5871428a5f 100644 --- a/components/esp32/esp_timer_impl.h +++ b/components/esp32/esp_timer_impl.h @@ -84,3 +84,18 @@ uint64_t esp_timer_impl_get_time(); * @return minimal period of periodic timer, in microseconds */ uint64_t esp_timer_impl_get_min_period_us(); + +/** + * @brief obtain internal critical section used esp_timer implementation + * This can be used when a sequence of calls to esp_timer has to be made, + * and it is necessary that the state of the timer is consistent between + * the calls. Should be treated in the same way as a spinlock. + * Call esp_timer_impl_unlock to release the lock + */ +void esp_timer_impl_lock(); + + +/** + * @brief counterpart of esp_timer_impl_lock + */ +void esp_timer_impl_unlock(); diff --git a/components/esp32/sleep_modes.c b/components/esp32/sleep_modes.c index a5f14d7f2b..65d0f05683 100644 --- a/components/esp32/sleep_modes.c +++ b/components/esp32/sleep_modes.c @@ -279,6 +279,11 @@ esp_err_t esp_light_sleep_start() { static portMUX_TYPE light_sleep_lock = portMUX_INITIALIZER_UNLOCKED; portENTER_CRITICAL(&light_sleep_lock); + /* We will be calling esp_timer_impl_advance inside DPORT access critical + * section. Make sure the code on the other CPU is not holding esp_timer + * lock, otherwise there will be deadlock. + */ + esp_timer_impl_lock(); s_config.rtc_ticks_at_sleep_start = rtc_time_get(); uint64_t frc_time_at_start = esp_timer_get_time(); DPORT_STALL_OTHER_CPU_START(); @@ -332,6 +337,7 @@ esp_err_t esp_light_sleep_start() } esp_set_time_from_rtc(); + esp_timer_impl_unlock(); DPORT_STALL_OTHER_CPU_END(); rtc_wdt_disable(); portEXIT_CRITICAL(&light_sleep_lock); diff --git a/components/esp32/test/test_sleep.c b/components/esp32/test/test_sleep.c index ac090fff98..c298d3220b 100644 --- a/components/esp32/test/test_sleep.c +++ b/components/esp32/test/test_sleep.c @@ -91,6 +91,35 @@ TEST_CASE("light sleep stress test", "[deepsleep]") vSemaphoreDelete(done); } +TEST_CASE("light sleep stress test with periodic esp_timer", "[deepsleep]") +{ + void timer_func(void* arg) + { + ets_delay_us(50); + } + + SemaphoreHandle_t done = xSemaphoreCreateCounting(2, 0); + esp_sleep_enable_timer_wakeup(1000); + esp_timer_handle_t timer; + esp_timer_create_args_t config = { + .callback = &timer_func, + }; + TEST_ESP_OK(esp_timer_create(&config, &timer)); + esp_timer_start_periodic(timer, 500); + xTaskCreatePinnedToCore(&test_light_sleep, "ls1", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 0); +#if portNUM_PROCESSORS == 2 + xTaskCreatePinnedToCore(&test_light_sleep, "ls1", 4096, done, UNITY_FREERTOS_PRIORITY + 1, NULL, 1); +#endif + xSemaphoreTake(done, portMAX_DELAY); +#if portNUM_PROCESSORS == 2 + xSemaphoreTake(done, portMAX_DELAY); +#endif + vSemaphoreDelete(done); + esp_timer_stop(timer); + esp_timer_delete(timer); +} + + #ifdef CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL #define MAX_SLEEP_TIME_ERROR_US 200 #else From e9cbf96bd1136c4e0ba72e44b70a45bae731166d Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 8 May 2018 21:45:10 +0800 Subject: [PATCH 057/187] mbedtls: re-add version 2.9.0 as a submodule --- .gitmodules | 4 + components/mbedtls/ChangeLog | 1996 ---- components/mbedtls/LICENSE | 2 - components/mbedtls/apache-2.0.txt | 202 - components/mbedtls/component.mk | 6 +- components/mbedtls/include/.gitignore | 4 - components/mbedtls/include/mbedtls/aes.h | 343 - components/mbedtls/include/mbedtls/aesni.h | 111 - components/mbedtls/include/mbedtls/arc4.h | 113 - components/mbedtls/include/mbedtls/asn1.h | 342 - .../mbedtls/include/mbedtls/asn1write.h | 239 - components/mbedtls/include/mbedtls/base64.h | 88 - components/mbedtls/include/mbedtls/bignum.h | 766 -- components/mbedtls/include/mbedtls/blowfish.h | 203 - components/mbedtls/include/mbedtls/bn_mul.h | 885 -- components/mbedtls/include/mbedtls/camellia.h | 235 - components/mbedtls/include/mbedtls/ccm.h | 141 - components/mbedtls/include/mbedtls/certs.h | 99 - .../mbedtls/include/mbedtls/check_config.h | 669 -- components/mbedtls/include/mbedtls/cipher.h | 709 -- .../mbedtls/include/mbedtls/cipher_internal.h | 109 - components/mbedtls/include/mbedtls/cmac.h | 170 - .../mbedtls/include/mbedtls/compat-1.3.h | 2523 ------ components/mbedtls/include/mbedtls/config.h | 2719 ------ components/mbedtls/include/mbedtls/ctr_drbg.h | 290 - components/mbedtls/include/mbedtls/debug.h | 228 - components/mbedtls/include/mbedtls/des.h | 306 - components/mbedtls/include/mbedtls/dhm.h | 305 - components/mbedtls/include/mbedtls/ecdh.h | 214 - components/mbedtls/include/mbedtls/ecdsa.h | 272 - components/mbedtls/include/mbedtls/ecjpake.h | 238 - components/mbedtls/include/mbedtls/ecp.h | 684 -- .../mbedtls/include/mbedtls/ecp_internal.h | 292 - components/mbedtls/include/mbedtls/entropy.h | 287 - .../mbedtls/include/mbedtls/entropy_poll.h | 109 - components/mbedtls/include/mbedtls/error.h | 107 - components/mbedtls/include/mbedtls/gcm.h | 220 - components/mbedtls/include/mbedtls/havege.h | 74 - .../mbedtls/include/mbedtls/hmac_drbg.h | 299 - components/mbedtls/include/mbedtls/md.h | 354 - components/mbedtls/include/mbedtls/md2.h | 136 - components/mbedtls/include/mbedtls/md4.h | 136 - components/mbedtls/include/mbedtls/md5.h | 136 - .../mbedtls/include/mbedtls/md_internal.h | 114 - .../include/mbedtls/memory_buffer_alloc.h | 150 - components/mbedtls/include/mbedtls/net.h | 31 - .../mbedtls/include/mbedtls/net_sockets.h | 225 - components/mbedtls/include/mbedtls/oid.h | 570 -- components/mbedtls/include/mbedtls/padlock.h | 107 - components/mbedtls/include/mbedtls/pem.h | 129 - components/mbedtls/include/mbedtls/pk.h | 616 -- .../mbedtls/include/mbedtls/pk_internal.h | 114 - components/mbedtls/include/mbedtls/pkcs11.h | 173 - components/mbedtls/include/mbedtls/pkcs12.h | 119 - components/mbedtls/include/mbedtls/pkcs5.h | 94 - components/mbedtls/include/mbedtls/platform.h | 343 - .../mbedtls/include/mbedtls/platform_time.h | 81 - .../mbedtls/include/mbedtls/ripemd160.h | 138 - components/mbedtls/include/mbedtls/rsa.h | 670 -- components/mbedtls/include/mbedtls/sha1.h | 136 - components/mbedtls/include/mbedtls/sha256.h | 141 - components/mbedtls/include/mbedtls/sha512.h | 141 - components/mbedtls/include/mbedtls/ssl.h | 2583 ------ .../mbedtls/include/mbedtls/ssl_cache.h | 143 - .../include/mbedtls/ssl_ciphersuites.h | 485 - .../mbedtls/include/mbedtls/ssl_cookie.h | 108 - .../mbedtls/include/mbedtls/ssl_internal.h | 617 -- .../mbedtls/include/mbedtls/ssl_ticket.h | 135 - .../mbedtls/include/mbedtls/threading.h | 106 - components/mbedtls/include/mbedtls/timing.h | 141 - components/mbedtls/include/mbedtls/version.h | 111 - components/mbedtls/include/mbedtls/x509.h | 332 - components/mbedtls/include/mbedtls/x509_crl.h | 173 - components/mbedtls/include/mbedtls/x509_crt.h | 661 -- components/mbedtls/include/mbedtls/x509_csr.h | 298 - components/mbedtls/include/mbedtls/xtea.h | 139 - components/mbedtls/library/.gitignore | 4 - components/mbedtls/library/aes.c | 1508 ---- components/mbedtls/library/aesni.c | 464 - components/mbedtls/library/arc4.c | 205 - components/mbedtls/library/asn1parse.c | 393 - components/mbedtls/library/asn1write.c | 390 - components/mbedtls/library/base64.c | 293 - components/mbedtls/library/bignum.c | 2460 ----- components/mbedtls/library/blowfish.c | 656 -- components/mbedtls/library/camellia.c | 1072 --- components/mbedtls/library/ccm.c | 464 - components/mbedtls/library/certs.c | 403 - components/mbedtls/library/cipher.c | 917 -- components/mbedtls/library/cipher_wrap.c | 1451 --- components/mbedtls/library/cmac.c | 1074 --- components/mbedtls/library/ctr_drbg.c | 594 -- components/mbedtls/library/debug.c | 368 - components/mbedtls/library/des.c | 1061 --- components/mbedtls/library/dhm.c | 627 -- components/mbedtls/library/ecdh.c | 264 - components/mbedtls/library/ecdsa.c | 448 - components/mbedtls/library/ecjpake.c | 1103 --- components/mbedtls/library/ecp.c | 2197 ----- components/mbedtls/library/ecp_curves.c | 1329 --- components/mbedtls/library/entropy.c | 655 -- components/mbedtls/library/entropy_poll.c | 268 - components/mbedtls/library/error.c | 709 -- components/mbedtls/library/gcm.c | 954 -- components/mbedtls/library/havege.c | 245 - components/mbedtls/library/hmac_drbg.c | 529 -- components/mbedtls/library/md.c | 471 - components/mbedtls/library/md2.c | 288 - components/mbedtls/library/md4.c | 384 - components/mbedtls/library/md5.c | 404 - components/mbedtls/library/md_wrap.c | 575 -- .../mbedtls/library/memory_buffer_alloc.c | 745 -- components/mbedtls/library/oid.c | 710 -- components/mbedtls/library/padlock.c | 170 - components/mbedtls/library/pem.c | 449 - components/mbedtls/library/pk.c | 383 - components/mbedtls/library/pk_wrap.c | 513 -- components/mbedtls/library/pkcs11.c | 240 - components/mbedtls/library/pkcs12.c | 365 - components/mbedtls/library/pkcs5.c | 406 - components/mbedtls/library/pkparse.c | 1293 --- components/mbedtls/library/pkwrite.c | 439 - components/mbedtls/library/platform.c | 327 - components/mbedtls/library/ripemd160.c | 467 - components/mbedtls/library/rsa.c | 1872 ---- components/mbedtls/library/sha1.c | 448 - components/mbedtls/library/sha256.c | 458 - components/mbedtls/library/sha512.c | 514 -- components/mbedtls/library/ssl_cache.c | 326 - components/mbedtls/library/ssl_ciphersuites.c | 1875 ---- components/mbedtls/library/ssl_cli.c | 3489 ------- components/mbedtls/library/ssl_cookie.c | 260 - components/mbedtls/library/ssl_srv.c | 4136 --------- components/mbedtls/library/ssl_ticket.c | 489 - components/mbedtls/library/ssl_tls.c | 8035 ----------------- components/mbedtls/library/threading.c | 137 - components/mbedtls/library/timing.c | 525 -- components/mbedtls/library/version.c | 50 - components/mbedtls/library/version_features.c | 683 -- components/mbedtls/library/x509.c | 1098 --- components/mbedtls/library/x509_create.c | 340 - components/mbedtls/library/x509_crl.c | 723 -- components/mbedtls/library/x509_crt.c | 2425 ----- components/mbedtls/library/x509_csr.c | 423 - components/mbedtls/library/x509write_crt.c | 459 - components/mbedtls/library/x509write_csr.c | 259 - components/mbedtls/library/xtea.c | 281 - components/mbedtls/mbedtls | 1 + tools/ci/mirror-list.txt | 1 + 149 files changed, 10 insertions(+), 88520 deletions(-) delete mode 100644 components/mbedtls/ChangeLog delete mode 100644 components/mbedtls/LICENSE delete mode 100644 components/mbedtls/apache-2.0.txt delete mode 100644 components/mbedtls/include/.gitignore delete mode 100644 components/mbedtls/include/mbedtls/aes.h delete mode 100644 components/mbedtls/include/mbedtls/aesni.h delete mode 100644 components/mbedtls/include/mbedtls/arc4.h delete mode 100644 components/mbedtls/include/mbedtls/asn1.h delete mode 100644 components/mbedtls/include/mbedtls/asn1write.h delete mode 100644 components/mbedtls/include/mbedtls/base64.h delete mode 100644 components/mbedtls/include/mbedtls/bignum.h delete mode 100644 components/mbedtls/include/mbedtls/blowfish.h delete mode 100644 components/mbedtls/include/mbedtls/bn_mul.h delete mode 100644 components/mbedtls/include/mbedtls/camellia.h delete mode 100644 components/mbedtls/include/mbedtls/ccm.h delete mode 100644 components/mbedtls/include/mbedtls/certs.h delete mode 100644 components/mbedtls/include/mbedtls/check_config.h delete mode 100644 components/mbedtls/include/mbedtls/cipher.h delete mode 100644 components/mbedtls/include/mbedtls/cipher_internal.h delete mode 100644 components/mbedtls/include/mbedtls/cmac.h delete mode 100644 components/mbedtls/include/mbedtls/compat-1.3.h delete mode 100644 components/mbedtls/include/mbedtls/config.h delete mode 100644 components/mbedtls/include/mbedtls/ctr_drbg.h delete mode 100644 components/mbedtls/include/mbedtls/debug.h delete mode 100644 components/mbedtls/include/mbedtls/des.h delete mode 100644 components/mbedtls/include/mbedtls/dhm.h delete mode 100644 components/mbedtls/include/mbedtls/ecdh.h delete mode 100644 components/mbedtls/include/mbedtls/ecdsa.h delete mode 100644 components/mbedtls/include/mbedtls/ecjpake.h delete mode 100644 components/mbedtls/include/mbedtls/ecp.h delete mode 100644 components/mbedtls/include/mbedtls/ecp_internal.h delete mode 100644 components/mbedtls/include/mbedtls/entropy.h delete mode 100644 components/mbedtls/include/mbedtls/entropy_poll.h delete mode 100644 components/mbedtls/include/mbedtls/error.h delete mode 100644 components/mbedtls/include/mbedtls/gcm.h delete mode 100644 components/mbedtls/include/mbedtls/havege.h delete mode 100644 components/mbedtls/include/mbedtls/hmac_drbg.h delete mode 100644 components/mbedtls/include/mbedtls/md.h delete mode 100644 components/mbedtls/include/mbedtls/md2.h delete mode 100644 components/mbedtls/include/mbedtls/md4.h delete mode 100644 components/mbedtls/include/mbedtls/md5.h delete mode 100644 components/mbedtls/include/mbedtls/md_internal.h delete mode 100644 components/mbedtls/include/mbedtls/memory_buffer_alloc.h delete mode 100644 components/mbedtls/include/mbedtls/net.h delete mode 100644 components/mbedtls/include/mbedtls/net_sockets.h delete mode 100644 components/mbedtls/include/mbedtls/oid.h delete mode 100644 components/mbedtls/include/mbedtls/padlock.h delete mode 100644 components/mbedtls/include/mbedtls/pem.h delete mode 100644 components/mbedtls/include/mbedtls/pk.h delete mode 100644 components/mbedtls/include/mbedtls/pk_internal.h delete mode 100644 components/mbedtls/include/mbedtls/pkcs11.h delete mode 100644 components/mbedtls/include/mbedtls/pkcs12.h delete mode 100644 components/mbedtls/include/mbedtls/pkcs5.h delete mode 100644 components/mbedtls/include/mbedtls/platform.h delete mode 100644 components/mbedtls/include/mbedtls/platform_time.h delete mode 100644 components/mbedtls/include/mbedtls/ripemd160.h delete mode 100644 components/mbedtls/include/mbedtls/rsa.h delete mode 100644 components/mbedtls/include/mbedtls/sha1.h delete mode 100644 components/mbedtls/include/mbedtls/sha256.h delete mode 100644 components/mbedtls/include/mbedtls/sha512.h delete mode 100644 components/mbedtls/include/mbedtls/ssl.h delete mode 100644 components/mbedtls/include/mbedtls/ssl_cache.h delete mode 100644 components/mbedtls/include/mbedtls/ssl_ciphersuites.h delete mode 100644 components/mbedtls/include/mbedtls/ssl_cookie.h delete mode 100644 components/mbedtls/include/mbedtls/ssl_internal.h delete mode 100644 components/mbedtls/include/mbedtls/ssl_ticket.h delete mode 100644 components/mbedtls/include/mbedtls/threading.h delete mode 100644 components/mbedtls/include/mbedtls/timing.h delete mode 100644 components/mbedtls/include/mbedtls/version.h delete mode 100644 components/mbedtls/include/mbedtls/x509.h delete mode 100644 components/mbedtls/include/mbedtls/x509_crl.h delete mode 100644 components/mbedtls/include/mbedtls/x509_crt.h delete mode 100644 components/mbedtls/include/mbedtls/x509_csr.h delete mode 100644 components/mbedtls/include/mbedtls/xtea.h delete mode 100644 components/mbedtls/library/.gitignore delete mode 100644 components/mbedtls/library/aes.c delete mode 100644 components/mbedtls/library/aesni.c delete mode 100644 components/mbedtls/library/arc4.c delete mode 100644 components/mbedtls/library/asn1parse.c delete mode 100644 components/mbedtls/library/asn1write.c delete mode 100644 components/mbedtls/library/base64.c delete mode 100644 components/mbedtls/library/bignum.c delete mode 100644 components/mbedtls/library/blowfish.c delete mode 100644 components/mbedtls/library/camellia.c delete mode 100644 components/mbedtls/library/ccm.c delete mode 100644 components/mbedtls/library/certs.c delete mode 100644 components/mbedtls/library/cipher.c delete mode 100644 components/mbedtls/library/cipher_wrap.c delete mode 100644 components/mbedtls/library/cmac.c delete mode 100644 components/mbedtls/library/ctr_drbg.c delete mode 100644 components/mbedtls/library/debug.c delete mode 100644 components/mbedtls/library/des.c delete mode 100644 components/mbedtls/library/dhm.c delete mode 100644 components/mbedtls/library/ecdh.c delete mode 100644 components/mbedtls/library/ecdsa.c delete mode 100644 components/mbedtls/library/ecjpake.c delete mode 100644 components/mbedtls/library/ecp.c delete mode 100644 components/mbedtls/library/ecp_curves.c delete mode 100644 components/mbedtls/library/entropy.c delete mode 100644 components/mbedtls/library/entropy_poll.c delete mode 100644 components/mbedtls/library/error.c delete mode 100644 components/mbedtls/library/gcm.c delete mode 100644 components/mbedtls/library/havege.c delete mode 100644 components/mbedtls/library/hmac_drbg.c delete mode 100644 components/mbedtls/library/md.c delete mode 100644 components/mbedtls/library/md2.c delete mode 100644 components/mbedtls/library/md4.c delete mode 100644 components/mbedtls/library/md5.c delete mode 100644 components/mbedtls/library/md_wrap.c delete mode 100644 components/mbedtls/library/memory_buffer_alloc.c delete mode 100644 components/mbedtls/library/oid.c delete mode 100644 components/mbedtls/library/padlock.c delete mode 100644 components/mbedtls/library/pem.c delete mode 100644 components/mbedtls/library/pk.c delete mode 100644 components/mbedtls/library/pk_wrap.c delete mode 100644 components/mbedtls/library/pkcs11.c delete mode 100644 components/mbedtls/library/pkcs12.c delete mode 100644 components/mbedtls/library/pkcs5.c delete mode 100644 components/mbedtls/library/pkparse.c delete mode 100644 components/mbedtls/library/pkwrite.c delete mode 100644 components/mbedtls/library/platform.c delete mode 100644 components/mbedtls/library/ripemd160.c delete mode 100644 components/mbedtls/library/rsa.c delete mode 100644 components/mbedtls/library/sha1.c delete mode 100644 components/mbedtls/library/sha256.c delete mode 100644 components/mbedtls/library/sha512.c delete mode 100644 components/mbedtls/library/ssl_cache.c delete mode 100644 components/mbedtls/library/ssl_ciphersuites.c delete mode 100644 components/mbedtls/library/ssl_cli.c delete mode 100644 components/mbedtls/library/ssl_cookie.c delete mode 100644 components/mbedtls/library/ssl_srv.c delete mode 100644 components/mbedtls/library/ssl_ticket.c delete mode 100644 components/mbedtls/library/ssl_tls.c delete mode 100644 components/mbedtls/library/threading.c delete mode 100644 components/mbedtls/library/timing.c delete mode 100644 components/mbedtls/library/version.c delete mode 100644 components/mbedtls/library/version_features.c delete mode 100644 components/mbedtls/library/x509.c delete mode 100644 components/mbedtls/library/x509_create.c delete mode 100644 components/mbedtls/library/x509_crl.c delete mode 100644 components/mbedtls/library/x509_crt.c delete mode 100644 components/mbedtls/library/x509_csr.c delete mode 100644 components/mbedtls/library/x509write_crt.c delete mode 100644 components/mbedtls/library/x509write_csr.c delete mode 100644 components/mbedtls/library/xtea.c create mode 160000 components/mbedtls/mbedtls diff --git a/.gitmodules b/.gitmodules index 84fa4ece2d..849ef99043 100644 --- a/.gitmodules +++ b/.gitmodules @@ -37,3 +37,7 @@ [submodule "components/json/cJSON"] path = components/json/cJSON url = https://github.com/DaveGamble/cJSON.git + +[submodule "components/mbedtls/mbedtls"] + path = components/mbedtls/mbedtls + url = https://github.com/espressif/mbedtls.git diff --git a/components/mbedtls/ChangeLog b/components/mbedtls/ChangeLog deleted file mode 100644 index 1ef952c89b..0000000000 --- a/components/mbedtls/ChangeLog +++ /dev/null @@ -1,1996 +0,0 @@ -mbed TLS ChangeLog (Sorted per branch, date) - -= mbed TLS 2.3.0 branch released 2016-06-28 - -Security - * Fix missing padding length check in mbedtls_rsa_rsaes_pkcs1_v15_decrypt - required by PKCS1 v2.2 - * Fix potential integer overflow to buffer overflow in - mbedtls_rsa_rsaes_pkcs1_v15_encrypt and mbedtls_rsa_rsaes_oaep_encrypt - (not triggerable remotely in (D)TLS). - * Fix a potential integer underflow to buffer overread in - mbedtls_rsa_rsaes_oaep_decrypt. It is not triggerable remotely in - SSL/TLS. - -Features - * Support for platform abstraction of the standard C library time() - function. - -Bugfix - * Fix bug in mbedtls_mpi_add_mpi() that caused wrong results when the three - arguments where the same (in-place doubling). Found and fixed by Janos - Follath. #309 - * Fix potential build failures related to the 'apidoc' target, introduced - in the previous patch release. Found by Robert Scheck. #390 #391 - * Fix issue in Makefile that prevented building using armar. #386 - * Fix memory leak that occured only when ECJPAKE was enabled and ECDHE and - ECDSA was disabled in config.h . The leak didn't occur by default. - * Fix an issue that caused valid certificates to be rejected whenever an - expired or not yet valid certificate was parsed before a valid certificate - in the trusted certificate list. - * Fix bug in mbedtls_x509_crt_parse that caused trailing extra data in the - buffer after DER certificates to be included in the raw representation. - * Fix issue that caused a hang when generating RSA keys of odd bitlength - * Fix bug in mbedtls_rsa_rsaes_pkcs1_v15_encrypt that made null pointer - dereference possible. - * Fix issue that caused a crash if invalid curves were passed to - mbedtls_ssl_conf_curves. #373 - * Fix issue in ssl_fork_server which was preventing it from functioning. #429 - * Fix memory leaks in test framework - * Fix test in ssl-opt.sh that does not run properly with valgrind - * Fix unchecked calls to mmbedtls_md_setup(). Fix by Brian Murray. #502 - -Changes - * On ARM platforms, when compiling with -O0 with GCC, Clang or armcc5, - don't use the optimized assembly for bignum multiplication. This removes - the need to pass -fomit-frame-pointer to avoid a build error with -O0. - * Disabled SSLv3 in the default configuration. - * Optimized mbedtls_mpi_zeroize() for MPI integer size. (Fix by Alexey - Skalozub). - * Fix non-compliance server extension handling. Extensions for SSLv3 are now - ignored, as required by RFC6101. - -= mbed TLS 2.2.1 released 2016-01-05 - -Security - * Fix potential double free when mbedtls_asn1_store_named_data() fails to - allocate memory. Only used for certificate generation, not triggerable - remotely in SSL/TLS. Found by Rafał Przywara. #367 - * Disable MD5 handshake signatures in TLS 1.2 by default to prevent the - SLOTH attack on TLS 1.2 server authentication (other attacks from the - SLOTH paper do not apply to any version of mbed TLS or PolarSSL). - https://www.mitls.org/pages/attacks/SLOTH - -Bugfix - * Fix over-restrictive length limit in GCM. Found by Andreas-N. #362 - * Fix bug in certificate validation that caused valid chains to be rejected - when the first intermediate certificate has pathLenConstraint=0. Found by - Nicholas Wilson. Introduced in mbed TLS 2.2.0. #280 - * Removed potential leak in mbedtls_rsa_rsassa_pkcs1_v15_sign(), found by - JayaraghavendranK. #372 - * Fix suboptimal handling of unexpected records that caused interop issues - with some peers over unreliable links. Avoid dropping an entire DTLS - datagram if a single record in a datagram is unexpected, instead only - drop the record and look at subsequent records (if any are present) in - the same datagram. Found by jeannotlapin. #345 - -= mbed TLS 2.2.0 released 2015-11-04 - -Security - * Fix potential double free if mbedtls_ssl_conf_psk() is called more than - once and some allocation fails. Cannot be forced remotely. Found by Guido - Vranken, Intelworks. - * Fix potential heap corruption on Windows when - mbedtls_x509_crt_parse_path() is passed a path longer than 2GB. Cannot be - triggered remotely. Found by Guido Vranken, Intelworks. - * Fix potential buffer overflow in some asn1_write_xxx() functions. - Cannot be triggered remotely unless you create X.509 certificates based - on untrusted input or write keys of untrusted origin. Found by Guido - Vranken, Intelworks. - * The X509 max_pathlen constraint was not enforced on intermediate - certificates. Found by Nicholas Wilson, fix and tests provided by - Janos Follath. #280 and #319 - -Features - * Experimental support for EC J-PAKE as defined in Thread 1.0.0. - Disabled by default as the specification might still change. - * Added a key extraction callback to accees the master secret and key - block. (Potential uses include EAP-TLS and Thread.) - -Bugfix - * Self-signed certificates were not excluded from pathlen counting, - resulting in some valid X.509 being incorrectly rejected. Found and fix - provided by Janos Follath. #319 - * Fix build error with configurations where ECDHE-PSK is the only key - exchange. Found and fix provided by Chris Hammond. #270 - * Fix build error with configurations where RSA, RSA-PSK, ECDH-RSA or - ECHD-ECDSA if the only key exchange. Multiple reports. #310 - * Fixed a bug causing some handshakes to fail due to some non-fatal alerts - not being properly ignored. Found by mancha and Kasom Koht-arsa, #308 - * mbedtls_x509_crt_verify(_with_profile)() now also checks the key type and - size/curve against the profile. Before that, there was no way to set a - minimum key size for end-entity certificates with RSA keys. Found by - Matthew Page of Scannex Electronics Ltd. - * Fix failures in MPI on Sparc(64) due to use of bad assembly code. - Found by Kurt Danielson. #292 - * Fix typo in name of the extKeyUsage OID. Found by inestlerode, #314 - * Fix bug in ASN.1 encoding of booleans that caused generated CA - certificates to be rejected by some applications, including OS X - Keychain. Found and fixed by Jonathan Leroy, Inikup. - -Changes - * Improved performance of mbedtls_ecp_muladd() when one of the scalars is 1 - or -1. - -= mbed TLS 2.1.2 released 2015-10-06 - -Security - * Added fix for CVE-2015-5291 to prevent heap corruption due to buffer - overflow of the hostname or session ticket. Found by Guido Vranken, - Intelworks. - * Fix potential double-free if mbedtls_ssl_set_hs_psk() is called more than - once in the same handhake and mbedtls_ssl_conf_psk() was used. - Found and patch provided by Guido Vranken, Intelworks. Cannot be forced - remotely. - * Fix stack buffer overflow in pkcs12 decryption (used by - mbedtls_pk_parse_key(file)() when the password is > 129 bytes. - Found by Guido Vranken, Intelworks. Not triggerable remotely. - * Fix potential buffer overflow in mbedtls_mpi_read_string(). - Found by Guido Vranken, Intelworks. Not exploitable remotely in the context - of TLS, but might be in other uses. On 32 bit machines, requires reading a - string of close to or larger than 1GB to exploit; on 64 bit machines, would - require reading a string of close to or larger than 2^62 bytes. - * Fix potential random memory allocation in mbedtls_pem_read_buffer() - on crafted PEM input data. Found and fix provided by Guido Vranken, - Intelworks. Not triggerable remotely in TLS. Triggerable remotely if you - accept PEM data from an untrusted source. - * Fix possible heap buffer overflow in base64_encoded() when the input - buffer is 512MB or larger on 32-bit platforms. Found by Guido Vranken, - Intelworks. Not trigerrable remotely in TLS. - * Fix potential double-free if mbedtls_conf_psk() is called repeatedly on - the same mbedtls_ssl_config object and memory allocation fails. Found by - Guido Vranken, Intelworks. Cannot be forced remotely. - * Fix potential heap buffer overflow in servers that perform client - authentication against a crafted CA cert. Cannot be triggered remotely - unless you allow third parties to pick trust CAs for client auth. - Found by Guido Vranken, Intelworks. - -Bugfix - * Fix compile error in net.c with musl libc. Found and patch provided by - zhasha (#278). - * Fix macroization of 'inline' keyword when building as C++. (#279) - -Changes - * Added checking of hostname length in mbedtls_ssl_set_hostname() to ensure - domain names are compliant with RFC 1035. - * Fixed paths for check_config.h in example config files. (Found by bachp) - (#291) - -= mbed TLS 2.1.1 released 2015-09-17 - -Security - * Add countermeasure against Lenstra's RSA-CRT attack for PKCS#1 v1.5 - signatures. (Found by Florian Weimer, Red Hat.) - https://securityblog.redhat.com/2015/09/02/factoring-rsa-keys-with-tls-perfect-forward-secrecy/ - * Fix possible client-side NULL pointer dereference (read) when the client - tries to continue the handshake after it failed (a misuse of the API). - (Found and patch provided by Fabian Foerg, Gotham Digital Science using - afl-fuzz.) - -Bugfix - * Fix warning when using a 64bit platform. (found by embedthis) (#275) - * Fix off-by-one error in parsing Supported Point Format extension that - caused some handshakes to fail. - -Changes - * Made X509 profile pointer const in mbedtls_ssl_conf_cert_profile() to allow - use of mbedtls_x509_crt_profile_next. (found by NWilson) - * When a client initiates a reconnect from the same port as a live - connection, if cookie verification is available - (MBEDTLS_SSL_DTLS_HELLO_VERIFY defined in config.h, and usable cookie - callbacks set with mbedtls_ssl_conf_dtls_cookies()), this will be - detected and mbedtls_ssl_read() will return - MBEDTLS_ERR_SSL_CLIENT_RECONNECT - it is then possible to start a new - handshake with the same context. (See RFC 6347 section 4.2.8.) - -= mbed TLS 2.1.0 released 2015-09-04 - -Features - * Added support for yotta as a build system. - * Primary open source license changed to Apache 2.0 license. - -Bugfix - * Fix segfault in the benchmark program when benchmarking DHM. - * Fix build error with CMake and pre-4.5 versions of GCC (found by Hugo - Leisink). - * Fix bug when parsing a ServerHello without extensions (found by David - Sears). - * Fix bug in CMake lists that caused libmbedcrypto.a not to be installed - (found by Benoit Lecocq). - * Fix bug in Makefile that caused libmbedcrypto and libmbedx509 not to be - installed (found by Rawi666). - * Fix compile error with armcc 5 with --gnu option. - * Fix bug in Makefile that caused programs not to be installed correctly - (found by robotanarchy) (#232). - * Fix bug in Makefile that prevented from installing without building the - tests (found by robotanarchy) (#232). - * Fix missing -static-libgcc when building shared libraries for Windows - with make. - * Fix link error when building shared libraries for Windows with make. - * Fix error when loading libmbedtls.so. - * Fix bug in mbedtls_ssl_conf_default() that caused the default preset to - be always used (found by dcb314) (#235) - * Fix bug in mbedtls_rsa_public() and mbedtls_rsa_private() that could - result trying to unlock an unlocked mutex on invalid input (found by - Fredrik Axelsson) (#257) - * Fix -Wshadow warnings (found by hnrkp) (#240) - * Fix memory corruption on client with overlong PSK identity, around - SSL_MAX_CONTENT_LEN or higher - not triggerrable remotely (found by - Aleksandrs Saveljevs) (#238) - * Fix unused function warning when using MBEDTLS_MDx_ALT or - MBEDTLS_SHAxxx_ALT (found by Henrik) (#239) - * Fix memory corruption in pkey programs (found by yankuncheng) (#210) - -Changes - * The PEM parser now accepts a trailing space at end of lines (#226). - * It is now possible to #include a user-provided configuration file at the - end of the default config.h by defining MBEDTLS_USER_CONFIG_FILE on the - compiler's command line. - * When verifying a certificate chain, if an intermediate certificate is - trusted, no later cert is checked. (suggested by hannes-landeholm) - (#220). - * Prepend a "thread identifier" to debug messages (issue pointed out by - Hugo Leisink) (#210). - * Add mbedtls_ssl_get_max_frag_len() to query the current maximum fragment - length. - -= mbed TLS 2.0.0 released 2015-07-13 - -Features - * Support for DTLS 1.0 and 1.2 (RFC 6347). - * Ability to override core functions from MDx, SHAx, AES and DES modules - with custom implementation (eg hardware accelerated), complementing the - ability to override the whole module. - * New server-side implementation of session tickets that rotate keys to - preserve forward secrecy, and allows sharing across multiple contexts. - * Added a concept of X.509 cerificate verification profile that controls - which algorithms and key sizes (curves for ECDSA) are acceptable. - * Expanded configurability of security parameters in the SSL module with - mbedtls_ssl_conf_dhm_min_bitlen() and mbedtls_ssl_conf_sig_hashes(). - * Introduced a concept of presets for SSL security-relevant configuration - parameters. - -API Changes - * The library has been split into libmbedcrypto, libmbedx509, libmbedtls. - You now need to link to all of them if you use TLS for example. - * All public identifiers moved to the mbedtls_* or MBEDTLS_* namespace. - Some names have been further changed to make them more consistent. - Migration helpers scripts/rename.pl and include/mbedlts/compat-1.3.h are - provided. Full list of renamings in scripts/data_files/rename-1.3-2.0.txt - * Renamings of fields inside structures, not covered by the previous list: - mbedtls_cipher_info_t.key_length -> key_bitlen - mbedtls_cipher_context_t.key_length -> key_bitlen - mbedtls_ecp_curve_info.size -> bit_size - * Headers are now found in the 'mbedtls' directory (previously 'polarssl'). - * The following _init() functions that could return errors have - been split into an _init() that returns void and another function that - should generally be the first function called on this context after init: - mbedtls_ssl_init() -> mbedtls_ssl_setup() - mbedtls_ccm_init() -> mbedtls_ccm_setkey() - mbedtls_gcm_init() -> mbedtls_gcm_setkey() - mbedtls_hmac_drbg_init() -> mbedtls_hmac_drbg_seed(_buf)() - mbedtls_ctr_drbg_init() -> mbedtls_ctr_drbg_seed() - Note that for mbedtls_ssl_setup(), you need to be done setting up the - ssl_config structure before calling it. - * Most ssl_set_xxx() functions (all except ssl_set_bio(), ssl_set_hostname(), - ssl_set_session() and ssl_set_client_transport_id(), plus - ssl_legacy_renegotiation()) have been renamed to mbedtls_ssl_conf_xxx() - (see rename.pl and compat-1.3.h above) and their first argument's type - changed from ssl_context to ssl_config. - * ssl_set_bio() changed signature (contexts merged, order switched, one - additional callback for read-with-timeout). - * The following functions have been introduced and must be used in callback - implementations (SNI, PSK) instead of their *conf counterparts: - mbedtls_ssl_set_hs_own_cert() - mbedtls_ssl_set_hs_ca_chain() - mbedtls_ssl_set_hs_psk() - * mbedtls_ssl_conf_ca_chain() lost its last argument (peer_cn), now set - using mbedtls_ssl_set_hostname(). - * mbedtls_ssl_conf_session_cache() changed prototype (only one context - pointer, parameters reordered). - * On server, mbedtls_ssl_conf_session_tickets_cb() must now be used in - place of mbedtls_ssl_conf_session_tickets() to enable session tickets. - * The SSL debug callback gained two new arguments (file name, line number). - * Debug modes were removed. - * mbedtls_ssl_conf_truncated_hmac() now returns void. - * mbedtls_memory_buffer_alloc_init() now returns void. - * X.509 verification flags are now an uint32_t. Affect the signature of: - mbedtls_ssl_get_verify_result() - mbedtls_x509_ctr_verify_info() - mbedtls_x509_crt_verify() (flags, f_vrfy -> needs to be updated) - mbedtls_ssl_conf_verify() (f_vrfy -> needs to be updated) - * The following functions changed prototype to avoid an in-out length - parameter: - mbedtls_base64_encode() - mbedtls_base64_decode() - mbedtls_mpi_write_string() - mbedtls_dhm_calc_secret() - * In the NET module, all "int" and "int *" arguments for file descriptors - changed type to "mbedtls_net_context *". - * net_accept() gained new arguments for the size of the client_ip buffer. - * In the threading layer, mbedtls_mutex_init() and mbedtls_mutex_free() now - return void. - * ecdsa_write_signature() gained an addtional md_alg argument and - ecdsa_write_signature_det() was deprecated. - * pk_sign() no longer accepts md_alg == POLARSSL_MD_NONE with ECDSA. - * Last argument of x509_crt_check_key_usage() and - mbedtls_x509write_crt_set_key_usage() changed from int to unsigned. - * test_ca_list (from certs.h) is renamed to test_cas_pem and is only - available if POLARSSL_PEM_PARSE_C is defined (it never worked without). - * Test certificates in certs.c are no longer guaranteed to be nul-terminated - strings; use the new *_len variables instead of strlen(). - * Functions mbedtls_x509_xxx_parse(), mbedtls_pk_parse_key(), - mbedtls_pk_parse_public_key() and mbedtls_dhm_parse_dhm() now expect the - length parameter to include the terminating null byte for PEM input. - * Signature of mpi_mul_mpi() changed to make the last argument unsigned - * calloc() is now used instead of malloc() everywhere. API of platform - layer and the memory_buffer_alloc module changed accordingly. - (Thanks to Mansour Moufid for helping with the replacement.) - * Change SSL_DISABLE_RENEGOTIATION config.h flag to SSL_RENEGOTIATION - (support for renegotiation now needs explicit enabling in config.h). - * Split MBEDTLS_HAVE_TIME into MBEDTLS_HAVE_TIME and MBEDTLS_HAVE_TIME_DATE - in config.h - * net_connect() and net_bind() have a new 'proto' argument to choose - between TCP and UDP, using the macros NET_PROTO_TCP or NET_PROTO_UDP. - Their 'port' argument type is changed to a string. - * Some constness fixes - -Removals - * Removed mbedtls_ecp_group_read_string(). Only named groups are supported. - * Removed mbedtls_ecp_sub() and mbedtls_ecp_add(), use - mbedtls_ecp_muladd(). - * Removed individual mdX_hmac, shaX_hmac, mdX_file and shaX_file functions - (use generic functions from md.h) - * Removed mbedtls_timing_msleep(). Use mbedtls_net_usleep() or a custom - waiting function. - * Removed test DHM parameters from the test certs module. - * Removed the PBKDF2 module (use PKCS5). - * Removed POLARSSL_ERROR_STRERROR_BC (use mbedtls_strerror()). - * Removed compat-1.2.h (helper for migrating from 1.2 to 1.3). - * Removed openssl.h (very partial OpenSSL compatibility layer). - * Configuration options POLARSSL_HAVE_LONGLONG was removed (now always on). - * Configuration options POLARSSL_HAVE_INT8 and POLARSSL_HAVE_INT16 have - been removed (compiler is required to support 32-bit operations). - * Configuration option POLARSSL_HAVE_IPV6 was removed (always enabled). - * Removed test program o_p_test, the script compat.sh does more. - * Removed test program ssl_test, superseded by ssl-opt.sh. - * Removed helper script active-config.pl - -New deprecations - * md_init_ctx() is deprecated in favour of md_setup(), that adds a third - argument (allowing memory savings if HMAC is not used) - -Semi-API changes (technically public, morally private) - * Renamed a few headers to include _internal in the name. Those headers are - not supposed to be included by users. - * Changed md_info_t into an opaque structure (use md_get_xxx() accessors). - * Changed pk_info_t into an opaque structure. - * Changed cipher_base_t into an opaque structure. - * Removed sig_oid2 and rename sig_oid1 to sig_oid in x509_crt and x509_crl. - * x509_crt.key_usage changed from unsigned char to unsigned int. - * Removed r and s from ecdsa_context - * Removed mode from des_context and des3_context - -Default behavior changes - * The default minimum TLS version is now TLS 1.0. - * RC4 is now blacklisted by default in the SSL/TLS layer, and excluded from the - default ciphersuite list returned by ssl_list_ciphersuites() - * Support for receiving SSLv2 ClientHello is now disabled by default at - compile time. - * The default authmode for SSL/TLS clients is now REQUIRED. - * Support for RSA_ALT contexts in the PK layer is now optional. Since is is - enabled in the default configuration, this is only noticeable if using a - custom config.h - * Default DHM parameters server-side upgraded from 1024 to 2048 bits. - * A minimum RSA key size of 2048 bits is now enforced during ceritificate - chain verification. - * Negotiation of truncated HMAC is now disabled by default on server too. - * The following functions are now case-sensitive: - mbedtls_cipher_info_from_string() - mbedtls_ecp_curve_info_from_name() - mbedtls_md_info_from_string() - mbedtls_ssl_ciphersuite_from_string() - mbedtls_version_check_feature() - -Requirement changes - * The minimum MSVC version required is now 2010 (better C99 support). - * The NET layer now unconditionnaly relies on getaddrinfo() and select(). - * Compiler is required to support C99 types such as long long and uint32_t. - -API changes from the 1.4 preview branch - * ssl_set_bio_timeout() was removed, split into mbedtls_ssl_set_bio() with - new prototype, and mbedtls_ssl_set_read_timeout(). - * The following functions now return void: - mbedtls_ssl_conf_transport() - mbedtls_ssl_conf_max_version() - mbedtls_ssl_conf_min_version() - * DTLS no longer hard-depends on TIMING_C, but uses a callback interface - instead, see mbedtls_ssl_set_timer_cb(), with the Timing module providing - an example implementation, see mbedtls_timing_delay_context and - mbedtls_timing_set/get_delay(). - * With UDP sockets, it is no longer necessary to call net_bind() again - after a successful net_accept(). - -Changes - * mbedtls_ctr_drbg_random() and mbedtls_hmac_drbg_random() are now - thread-safe if MBEDTLS_THREADING_C is enabled. - * Reduced ROM fooprint of SHA-256 and added an option to reduce it even - more (at the expense of performance) MBEDTLS_SHA256_SMALLER. - -= mbed TLS 1.3 branch - -Security - * With authmode set to SSL_VERIFY_OPTIONAL, verification of keyUsage and - extendedKeyUsage on the leaf certificate was lost (results not accessible - via ssl_get_verify_results()). - * Add countermeasure against "Lucky 13 strikes back" cache-based attack, - https://dl.acm.org/citation.cfm?id=2714625 - -Features - * Improve ECC performance by using more efficient doubling formulas - (contributed by Peter Dettman). - * Add x509_crt_verify_info() to display certificate verification results. - * Add support for reading DH parameters with privateValueLength included - (contributed by Daniel Kahn Gillmor). - * Add support for bit strings in X.509 names (request by Fredrik Axelsson). - * Add support for id-at-uniqueIdentifier in X.509 names. - * Add support for overriding snprintf() (except on Windows) and exit() in - the platform layer. - * Add an option to use macros instead of function pointers in the platform - layer (helps get rid of unwanted references). - * Improved Makefiles for Windows targets by fixing library targets and making - cross-compilation easier (thanks to Alon Bar-Lev). - * The benchmark program also prints heap usage for public-key primitives - if POLARSSL_MEMORY_BUFFER_ALLOC_C and POLARSSL_MEMORY_DEBUG are defined. - * New script ecc-heap.sh helps measuring the impact of ECC parameters on - speed and RAM (heap only for now) usage. - * New script memory.sh helps measuring the ROM and RAM requirements of two - reduced configurations (PSK-CCM and NSA suite B). - * Add config flag POLARSSL_DEPRECATED_WARNING (off by default) to produce - warnings on use of deprecated functions (with GCC and Clang only). - * Add config flag POLARSSL_DEPRECATED_REMOVED (off by default) to produce - errors on use of deprecated functions. - -Bugfix - * Fix compile errors with PLATFORM_NO_STD_FUNCTIONS. - * Fix compile error with PLATFORM_EXIT_ALT (thanks to Rafał Przywara). - * Fix bug in entropy.c when THREADING_C is also enabled that caused - entropy_free() to crash (thanks to Rafał Przywara). - * Fix memory leak when gcm_setkey() and ccm_setkey() are used more than - once on the same context. - * Fix bug in ssl_mail_client when password is longer that username (found - by Bruno Pape). - * Fix undefined behaviour (memcmp( NULL, NULL, 0 );) in X.509 modules - (detected by Clang's 3.6 UBSan). - * mpi_size() and mpi_msb() would segfault when called on an mpi that is - initialized but not set (found by pravic). - * Fix detection of support for getrandom() on Linux (reported by syzzer) by - doing it at runtime (using uname) rather that compile time. - * Fix handling of symlinks by "make install" (found by Gaël PORTAY). - * Fix potential NULL pointer dereference (not trigerrable remotely) when - ssl_write() is called before the handshake is finished (introduced in - 1.3.10) (first reported by Martin Blumenstingl). - * Fix bug in pk_parse_key() that caused some valid private EC keys to be - rejected. - * Fix bug in Via Padlock support (found by Nikos Mavrogiannopoulos). - * Fix thread safety bug in RSA operations (found by Fredrik Axelsson). - * Fix hardclock() (only used in the benchmarking program) with some - versions of mingw64 (found by kxjhlele). - * Fix warnings from mingw64 in timing.c (found by kxjklele). - * Fix potential unintended sign extension in asn1_get_len() on 64-bit - platforms. - * Fix potential memory leak in ssl_set_psk() (found by Mansour Moufid). - * Fix compile error when POLARSSL_SSL_DISABLE_RENEGOTATION and - POLARSSL_SSL_SSESSION_TICKETS where both enabled in config.h (introduced - in 1.3.10). - * Add missing extern "C" guard in aesni.h (reported by amir zamani). - * Add missing dependency on SHA-256 in some x509 programs (reported by - Gergely Budai). - * Fix bug related to ssl_set_curves(): the client didn't check that the - curve picked by the server was actually allowed. - -Changes - * Remove bias in mpi_gen_prime (contributed by Pascal Junod). - * Remove potential sources of timing variations (some contributed by Pascal - Junod). - * Options POLARSSL_HAVE_INT8 and POLARSSL_HAVE_INT16 are deprecated. - * Enabling POLARSSL_NET_C without POLARSSL_HAVE_IPV6 is deprecated. - * compat-1.2.h and openssl.h are deprecated. - * Adjusting/overriding CFLAGS and LDFLAGS with the make build system is now - more flexible (warning: OFLAGS is not used any more) (see the README) - (contributed by Alon Bar-Lev). - * ssl_set_own_cert() no longer calls pk_check_pair() since the - performance impact was bad for some users (this was introduced in 1.3.10). - * Move from SHA-1 to SHA-256 in example programs using signatures - (suggested by Thorsten Mühlfelder). - * Remove some unneeded inclusions of header files from the standard library - "minimize" others (eg use stddef.h if only size_t is needed). - * Change #include lines in test files to use double quotes instead of angle - brackets for uniformity with the rest of the code. - * Remove dependency on sscanf() in X.509 parsing modules. - -= mbed TLS 1.3.10 released 2015-02-09 -Security - * NULL pointer dereference in the buffer-based allocator when the buffer is - full and polarssl_free() is called (found by Mark Hasemeyer) - (only possible if POLARSSL_MEMORY_BUFFER_ALLOC_C is enabled, which it is - not by default). - * Fix remotely-triggerable uninitialised pointer dereference caused by - crafted X.509 certificate (TLS server is not affected if it doesn't ask for a - client certificate) (found using Codenomicon Defensics). - * Fix remotely-triggerable memory leak caused by crafted X.509 certificates - (TLS server is not affected if it doesn't ask for a client certificate) - (found using Codenomicon Defensics). - * Fix potential stack overflow while parsing crafted X.509 certificates - (TLS server is not affected if it doesn't ask for a client certificate) - (found using Codenomicon Defensics). - * Fix timing difference that could theoretically lead to a - Bleichenbacher-style attack in the RSA and RSA-PSK key exchanges - (reported by Sebastian Schinzel). - -Features - * Add support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv). - * Add support for Extended Master Secret (draft-ietf-tls-session-hash). - * Add support for Encrypt-then-MAC (RFC 7366). - * Add function pk_check_pair() to test if public and private keys match. - * Add x509_crl_parse_der(). - * Add compile-time option POLARSSL_X509_MAX_INTERMEDIATE_CA to limit the - length of an X.509 verification chain. - * Support for renegotiation can now be disabled at compile-time - * Support for 1/n-1 record splitting, a countermeasure against BEAST. - * Certificate selection based on signature hash, preferring SHA-1 over SHA-2 - for pre-1.2 clients when multiple certificates are available. - * Add support for getrandom() syscall on recent Linux kernels with Glibc or - a compatible enough libc (eg uClibc). - * Add ssl_set_arc4_support() to make it easier to disable RC4 at runtime - while using the default ciphersuite list. - * Added new error codes and debug messages about selection of - ciphersuite/certificate. - -Bugfix - * Stack buffer overflow if ctr_drbg_update() is called with too large - add_len (found by Jean-Philippe Aumasson) (not triggerable remotely). - * Possible buffer overflow of length at most POLARSSL_MEMORY_ALIGN_MULTIPLE - if memory_buffer_alloc_init() was called with buf not aligned and len not - a multiple of POLARSSL_MEMORY_ALIGN_MULTIPLE (not triggerable remotely). - * User set CFLAGS were ignored by Cmake with gcc (introduced in 1.3.9, found - by Julian Ospald). - * Fix potential undefined behaviour in Camellia. - * Fix potential failure in ECDSA signatures when POLARSSL_ECP_MAX_BITS is a - multiple of 8 (found by Gergely Budai). - * Fix unchecked return code in x509_crt_parse_path() on Windows (found by - Peter Vaskovic). - * Fix assembly selection for MIPS64 (thanks to James Cowgill). - * ssl_get_verify_result() now works even if the handshake was aborted due - to a failed verification (found by Fredrik Axelsson). - * Skip writing and parsing signature_algorithm extension if none of the - key exchanges enabled needs certificates. This fixes a possible interop - issue with some servers when a zero-length extension was sent. (Reported - by Peter Dettman.) - * On a 0-length input, base64_encode() did not correctly set output length - (found by Hendrik van den Boogaard). - -Changes - * Use deterministic nonces for AEAD ciphers in TLS by default (possible to - switch back to random with POLARSSL_SSL_AEAD_RANDOM_IV in config.h). - * Blind RSA private operations even when POLARSSL_RSA_NO_CRT is defined. - * ssl_set_own_cert() now returns an error on key-certificate mismatch. - * Forbid repeated extensions in X.509 certificates. - * debug_print_buf() now prints a text view in addition to hexadecimal. - * A specific error is now returned when there are ciphersuites in common - but none of them is usable due to external factors such as no certificate - with a suitable (extended)KeyUsage or curve or no PSK set. - * It is now possible to disable negotiation of truncated HMAC server-side - at runtime with ssl_set_truncated_hmac(). - * Example programs for SSL client and server now disable SSLv3 by default. - * Example programs for SSL client and server now disable RC4 by default. - * Use platform.h in all test suites and programs. - -= PolarSSL 1.3.9 released 2014-10-20 -Security - * Lowest common hash was selected from signature_algorithms extension in - TLS 1.2 (found by Darren Bane) (introduced in 1.3.8). - * Remotely-triggerable memory leak when parsing some X.509 certificates - (server is not affected if it doesn't ask for a client certificate) - (found using Codenomicon Defensics). - * Remotely-triggerable memory leak when parsing crafted ClientHello - (not affected if ECC support was compiled out) (found using Codenomicon - Defensics). - -Bugfix - * Support escaping of commas in x509_string_to_names() - * Fix compile error in ssl_pthread_server (found by Julian Ospald). - * Fix net_accept() regarding non-blocking sockets (found by Luca Pesce). - * Don't print uninitialised buffer in ssl_mail_client (found by Marc Abel). - * Fix warnings from Clang's scan-build (contributed by Alfred Klomp). - * Fix compile error in timing.c when POLARSSL_NET_C and POLARSSL_SELFTEST - are defined but not POLARSSL_HAVE_TIME (found by Stephane Di Vito). - * Remove non-existent file from VS projects (found by Peter Vaskovic). - * ssl_read() could return non-application data records on server while - renegotation was pending, and on client when a HelloRequest was received. - * Server-initiated renegotiation would fail with non-blocking I/O if the - write callback returned WANT_WRITE when requesting renegotiation. - * ssl_close_notify() could send more than one message in some circumstances - with non-blocking I/O. - * Fix compiler warnings on iOS (found by Sander Niemeijer). - * x509_crt_parse() did not increase total_failed on PEM error - * Fix compile error with armcc in mpi_is_prime() - * Fix potential bad read in parsing ServerHello (found by Adrien - Vialletelle). - -Changes - * Ciphersuites using SHA-256 or SHA-384 now require TLS 1.x (there is no - standard defining how to use SHA-2 with SSL 3.0). - * Ciphersuites using RSA-PSK key exchange new require TLS 1.x (the spec is - ambiguous on how to encode some packets with SSL 3.0). - * Made buffer size in pk_write_(pub)key_pem() more dynamic, eg smaller if - RSA is disabled, larger if POLARSSL_MPI_MAX_SIZE is larger. - * ssl_read() now returns POLARSSL_ERR_NET_WANT_READ rather than - POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE on harmless alerts. - * POLARSSL_MPI_MAX_SIZE now defaults to 1024 in order to allow 8192 bits - RSA keys. - * Accept spaces at end of line or end of buffer in base64_decode(). - * X.509 certificates with more than one AttributeTypeAndValue per - RelativeDistinguishedName are not accepted any more. - -= PolarSSL 1.3.8 released 2014-07-11 -Security - * Fix length checking for AEAD ciphersuites (found by Codenomicon). - It was possible to crash the server (and client) using crafted messages - when a GCM suite was chosen. - -Features - * Add CCM module and cipher mode to Cipher Layer - * Support for CCM and CCM_8 ciphersuites - * Support for parsing and verifying RSASSA-PSS signatures in the X.509 - modules (certificates, CRLs and CSRs). - * Blowfish in the cipher layer now supports variable length keys. - * Add example config.h for PSK with CCM, optimized for low RAM usage. - * Optimize for RAM usage in example config.h for NSA Suite B profile. - * Add POLARSSL_REMOVE_ARC4_CIPHERSUITES to allow removing RC4 ciphersuites - from the default list (inactive by default). - * Add server-side enforcement of sent renegotiation requests - (ssl_set_renegotiation_enforced()) - * Add SSL_CIPHERSUITES config.h flag to allow specifying a list of - ciphersuites to use and save some memory if the list is small. - -Changes - * Add LINK_WITH_PTHREAD option in CMake for explicit linking that is - required on some platforms (e.g. OpenBSD) - * Migrate zeroizing of data to polarssl_zeroize() instead of memset() - against unwanted compiler optimizations - * md_list() now returns hashes strongest first - * Selection of hash for signing ServerKeyExchange in TLS 1.2 now picks - strongest offered by client. - * All public contexts have _init() and _free() functions now for simpler - usage pattern - -Bugfix - * Fix in debug_print_msg() - * Enforce alignment in the buffer allocator even if buffer is not aligned - * Remove less-than-zero checks on unsigned numbers - * Stricter check on SSL ClientHello internal sizes compared to actual packet - size (found by TrustInSoft) - * Fix WSAStartup() return value check (found by Peter Vaskovic) - * Other minor issues (found by Peter Vaskovic) - * Fix symlink command for cross compiling with CMake (found by Andre - Heinecke) - * Fix DER output of gen_key app (found by Gergely Budai) - * Very small records were incorrectly rejected when truncated HMAC was in - use with some ciphersuites and versions (RC4 in all versions, CBC with - versions < TLS 1.1). - * Very large records using more than 224 bytes of padding were incorrectly - rejected with CBC-based ciphersuites and TLS >= 1.1 - * Very large records using less padding could cause a buffer overread of up - to 32 bytes with CBC-based ciphersuites and TLS >= 1.1 - * Restore ability to use a v1 cert as a CA if trusted locally. (This had - been removed in 1.3.6.) - * Restore ability to locally trust a self-signed cert that is not a proper - CA for use as an end entity certificate. (This had been removed in - 1.3.6.) - * Fix preprocessor checks for bn_mul PPC asm (found by Barry K. Nathan). - * Use \n\t rather than semicolons for bn_mul asm, since some assemblers - interpret semicolons as comment delimiters (found by Barry K. Nathan). - * Fix off-by-one error in parsing Supported Point Format extension that - caused some handshakes to fail. - * Fix possible miscomputation of the premaster secret with DHE-PSK key - exchange that caused some handshakes to fail with other implementations. - (Failure rate <= 1/255 with common DHM moduli.) - * Disable broken Sparc64 bn_mul assembly (found by Florian Obser). - * Fix base64_decode() to return and check length correctly (in case of - tight buffers) - * Fix mpi_write_string() to write "00" as hex output for empty MPI (found - by Hui Dong) - -= PolarSSL 1.3.7 released on 2014-05-02 -Features - * debug_set_log_mode() added to determine raw or full logging - * debug_set_threshold() added to ignore messages over threshold level - * version_check_feature() added to check for compile-time options at - run-time - -Changes - * POLARSSL_CONFIG_OPTIONS has been removed. All values are individually - checked and filled in the relevant module headers - * Debug module only outputs full lines instead of parts - * Better support for the different Attribute Types from IETF PKIX (RFC 5280) - * AES-NI now compiles with "old" assemblers too - * Ciphersuites based on RC4 now have the lowest priority by default - -Bugfix - * Only iterate over actual certificates in ssl_write_certificate_request() - (found by Matthew Page) - * Typos in platform.c and pkcs11.c (found by Daniel Phillips and Steffan - Karger) - * cert_write app should use subject of issuer certificate as issuer of cert - * Fix false reject in padding check in ssl_decrypt_buf() for CBC - ciphersuites, for full SSL frames of data. - * Improve interoperability by not writing extension length in ClientHello / - ServerHello when no extensions are present (found by Matthew Page) - * rsa_check_pubkey() now allows an E up to N - * On OpenBSD, use arc4random_buf() instead of rand() to prevent warnings - * mpi_fill_random() was creating numbers larger than requested on - big-endian platform when size was not an integer number of limbs - * Fix dependencies issues in X.509 test suite. - * Some parts of ssl_tls.c were compiled even when the module was disabled. - * Fix detection of DragonflyBSD in net.c (found by Markus Pfeiffer) - * Fix detection of Clang on some Apple platforms with CMake - (found by Barry K. Nathan) - -= PolarSSL 1.3.6 released on 2014-04-11 - -Features - * Support for the ALPN SSL extension - * Add option 'use_dev_random' to gen_key application - * Enable verification of the keyUsage extension for CA and leaf - certificates (POLARSSL_X509_CHECK_KEY_USAGE) - * Enable verification of the extendedKeyUsage extension - (POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE) - -Changes - * x509_crt_info() now prints information about parsed extensions as well - * pk_verify() now returns a specific error code when the signature is valid - but shorter than the supplied length. - * Use UTC time to check certificate validity. - * Reject certificates with times not in UTC, per RFC 5280. - -Security - * Avoid potential timing leak in ecdsa_sign() by blinding modular division. - (Found by Watson Ladd.) - * The notAfter date of some certificates was no longer checked since 1.3.5. - This affects certificates in the user-supplied chain except the top - certificate. If the user-supplied chain contains only one certificates, - it is not affected (ie, its notAfter date is properly checked). - * Prevent potential NULL pointer dereference in ssl_read_record() (found by - TrustInSoft) - -Bugfix - * The length of various ClientKeyExchange messages was not properly checked. - * Some example server programs were not sending the close_notify alert. - * Potential memory leak in mpi_exp_mod() when error occurs during - calculation of RR. - * Fixed malloc/free default #define in platform.c (found by Gergely Budai). - * Fixed type which made POLARSSL_ENTROPY_FORCE_SHA256 uneffective (found by - Gergely Budai). - * Fix #include path in ecdsa.h which wasn't accepted by some compilers. - (found by Gergely Budai) - * Fix compile errors when POLARSSL_ERROR_STRERROR_BC is undefined (found by - Shuo Chen). - * oid_get_numeric_string() used to truncate the output without returning an - error if the output buffer was just 1 byte too small. - * dhm_parse_dhm() (hence dhm_parse_dhmfile()) did not set dhm->len. - * Calling pk_debug() on an RSA-alt key would segfault. - * pk_get_size() and pk_get_len() were off by a factor 8 for RSA-alt keys. - * Potential buffer overwrite in pem_write_buffer() because of low length - indication (found by Thijs Alkemade) - * EC curves constants, which should be only in ROM since 1.3.3, were also - stored in RAM due to missing 'const's (found by Gergely Budai). - -= PolarSSL 1.3.5 released on 2014-03-26 -Features - * HMAC-DRBG as a separate module - * Option to set the Curve preference order (disabled by default) - * Single Platform compatilibity layer (for memory / printf / fprintf) - * Ability to provide alternate timing implementation - * Ability to force the entropy module to use SHA-256 as its basis - (POLARSSL_ENTROPY_FORCE_SHA256) - * Testing script ssl-opt.sh added for testing 'live' ssl option - interoperability against OpenSSL and PolarSSL - * Support for reading EC keys that use SpecifiedECDomain in some cases. - * Entropy module now supports seed writing and reading - -Changes - * Deprecated the Memory layer - * entropy_add_source(), entropy_update_manual() and entropy_gather() - now thread-safe if POLARSSL_THREADING_C defined - * Improvements to the CMake build system, contributed by Julian Ospald. - * Work around a bug of the version of Clang shipped by Apple with Mavericks - that prevented bignum.c from compiling. (Reported by Rafael Baptista.) - * Revamped the compat.sh interoperatibility script to include support for - testing against GnuTLS - * Deprecated ssl_set_own_cert_rsa() and ssl_set_own_cert_rsa_alt() - * Improvements to tests/Makefile, contributed by Oden Eriksson. - -Security - * Forbid change of server certificate during renegotiation to prevent - "triple handshake" attack when authentication mode is 'optional' (the - attack was already impossible when authentication is required). - * Check notBefore timestamp of certificates and CRLs from the future. - * Forbid sequence number wrapping - * Fixed possible buffer overflow with overlong PSK - * Possible remotely-triggered out-of-bounds memory access fixed (found by - TrustInSoft) - -Bugfix - * ecp_gen_keypair() does more tries to prevent failure because of - statistics - * Fixed bug in RSA PKCS#1 v1.5 "reversed" operations - * Fixed testing with out-of-source builds using cmake - * Fixed version-major intolerance in server - * Fixed CMake symlinking on out-of-source builds - * Fixed dependency issues in test suite - * Programs rsa_sign_pss and rsa_verify_pss were not using PSS since 1.3.0 - * Bignum's MIPS-32 assembly was used on MIPS-64, causing chaos. (Found by - Alex Wilson.) - * ssl_cache was creating entries when max_entries=0 if TIMING_C was enabled. - * m_sleep() was sleeping twice too long on most Unix platforms. - * Fixed bug with session tickets and non-blocking I/O in the unlikely case - send() would return an EAGAIN error when sending the ticket. - * ssl_cache was leaking memory when reusing a timed out entry containing a - client certificate. - * ssl_srv was leaking memory when client presented a timed out ticket - containing a client certificate - * ssl_init() was leaving a dirty pointer in ssl_context if malloc of - out_ctr failed - * ssl_handshake_init() was leaving dirty pointers in subcontexts if malloc - of one of them failed - * Fix typo in rsa_copy() that impacted PKCS#1 v2 contexts - * x509_get_current_time() uses localtime_r() to prevent thread issues - -= PolarSSL 1.3.4 released on 2014-01-27 -Features - * Support for the Koblitz curves: secp192k1, secp224k1, secp256k1 - * Support for RIPEMD-160 - * Support for AES CFB8 mode - * Support for deterministic ECDSA (RFC 6979) - -Bugfix - * Potential memory leak in bignum_selftest() - * Replaced expired test certificate - * ssl_mail_client now terminates lines with CRLF, instead of LF - * net module handles timeouts on blocking sockets better (found by Tilman - Sauerbeck) - * Assembly format fixes in bn_mul.h - -Security - * Missing MPI_CHK calls added around unguarded mpi calls (found by - TrustInSoft) - -= PolarSSL 1.3.3 released on 2013-12-31 -Features - * EC key generation support in gen_key app - * Support for adhering to client ciphersuite order preference - (POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE) - * Support for Curve25519 - * Support for ECDH-RSA and ECDH-ECDSA key exchanges and ciphersuites - * Support for IPv6 in the NET module - * AES-NI support for AES, AES-GCM and AES key scheduling - * SSL Pthread-based server example added (ssl_pthread_server) - -Changes - * gen_prime() speedup - * Speedup of ECP multiplication operation - * Relaxed some SHA2 ciphersuite's version requirements - * Dropped use of readdir_r() instead of readdir() with threading support - * More constant-time checks in the RSA module - * Split off curves from ecp.c into ecp_curves.c - * Curves are now stored fully in ROM - * Memory usage optimizations in ECP module - * Removed POLARSSL_THREADING_DUMMY - -Bugfix - * Fixed bug in mpi_set_bit() on platforms where t_uint is wider than int - * Fixed X.509 hostname comparison (with non-regular characters) - * SSL now gracefully handles missing RNG - * Missing defines / cases for RSA_PSK key exchange - * crypt_and_hash app checks MAC before final decryption - * Potential memory leak in ssl_ticket_keys_init() - * Memory leak in benchmark application - * Fixed x509_crt_parse_path() bug on Windows platforms - * Added missing MPI_CHK() around some statements in mpi_div_mpi() (found by - TrustInSoft) - * Fixed potential overflow in certificate size verification in - ssl_write_certificate() (found by TrustInSoft) - -Security - * Possible remotely-triggered out-of-bounds memory access fixed (found by - TrustInSoft) - -= PolarSSL 1.3.2 released on 2013-11-04 -Features - * PK tests added to test framework - * Added optional optimization for NIST MODP curves (POLARSSL_ECP_NIST_OPTIM) - * Support for Camellia-GCM mode and ciphersuites - -Changes - * Padding checks in cipher layer are now constant-time - * Value comparisons in SSL layer are now constant-time - * Support for serialNumber, postalAddress and postalCode in X509 names - * SSL Renegotiation was refactored - -Bugfix - * More stringent checks in cipher layer - * Server does not send out extensions not advertised by client - * Prevent possible alignment warnings on casting from char * to 'aligned *' - * Misc fixes and additions to dependency checks - * Const correctness - * cert_write with selfsign should use issuer_name as subject_name - * Fix ECDSA corner case: missing reduction mod N (found by DualTachyon) - * Defines to handle UEFI environment under MSVC - * Server-side initiated renegotiations send HelloRequest - -= PolarSSL 1.3.1 released on 2013-10-15 -Features - * Support for Brainpool curves and TLS ciphersuites (RFC 7027) - * Support for ECDHE-PSK key-exchange and ciphersuites - * Support for RSA-PSK key-exchange and ciphersuites - -Changes - * RSA blinding locks for a smaller amount of time - * TLS compression only allocates working buffer once - * Introduced POLARSSL_HAVE_READDIR_R for systems without it - * config.h is more script-friendly - -Bugfix - * Missing MSVC defines added - * Compile errors with POLARSSL_RSA_NO_CRT - * Header files with 'polarssl/' - * Const correctness - * Possible naming collision in dhm_context - * Better support for MSVC - * threading_set_alt() name - * Added missing x509write_crt_set_version() - -= PolarSSL 1.3.0 released on 2013-10-01 -Features - * Elliptic Curve Cryptography module added - * Elliptic Curve Diffie Hellman module added - * Ephemeral Elliptic Curve Diffie Hellman support for SSL/TLS - (ECDHE-based ciphersuites) - * Ephemeral Elliptic Curve Digital Signature Algorithm support for SSL/TLS - (ECDSA-based ciphersuites) - * Ability to specify allowed ciphersuites based on the protocol version. - * PSK and DHE-PSK based ciphersuites added - * Memory allocation abstraction layer added - * Buffer-based memory allocator added (no malloc() / free() / HEAP usage) - * Threading abstraction layer added (dummy / pthread / alternate) - * Public Key abstraction layer added - * Parsing Elliptic Curve keys - * Parsing Elliptic Curve certificates - * Support for max_fragment_length extension (RFC 6066) - * Support for truncated_hmac extension (RFC 6066) - * Support for zeros-and-length (ANSI X.923) padding, one-and-zeros - (ISO/IEC 7816-4) padding and zero padding in the cipher layer - * Support for session tickets (RFC 5077) - * Certificate Request (CSR) generation with extensions (key_usage, - ns_cert_type) - * X509 Certificate writing with extensions (basic_constraints, - issuer_key_identifier, etc) - * Optional blinding for RSA, DHM and EC - * Support for multiple active certificate / key pairs in SSL servers for - the same host (Not to be confused with SNI!) - -Changes - * Ability to enable / disable SSL v3 / TLS 1.0 / TLS 1.1 / TLS 1.2 - individually - * Introduced separate SSL Ciphersuites module that is based on - Cipher and MD information - * Internals for SSL module adapted to have separate IV pointer that is - dynamically set (Better support for hardware acceleration) - * Moved all OID functionality to a separate module. RSA function - prototypes for the RSA sign and verify functions changed as a result - * Split up the GCM module into a starts/update/finish cycle - * Client and server now filter sent and accepted ciphersuites on minimum - and maximum protocol version - * Ability to disable server_name extension (RFC 6066) - * Renamed error_strerror() to the less conflicting polarssl_strerror() - (Ability to keep old as well with POLARSSL_ERROR_STRERROR_BC) - * SHA2 renamed to SHA256, SHA4 renamed to SHA512 and functions accordingly - * All RSA operations require a random generator for blinding purposes - * X509 core refactored - * x509_crt_verify() now case insensitive for cn (RFC 6125 6.4) - * Also compiles / runs without time-based functions (!POLARSSL_HAVE_TIME) - * Support faulty X509 v1 certificates with extensions - (POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3) - -Bugfix - * Fixed parse error in ssl_parse_certificate_request() - * zlib compression/decompression skipped on empty blocks - * Support for AIX header locations in net.c module - * Fixed file descriptor leaks - -Security - * RSA blinding on CRT operations to counter timing attacks - (found by Cyril Arnaud and Pierre-Alain Fouque) - - -= Version 1.2.14 released 2015-05-?? - -Security - * Fix potential invalid memory read in the server, that allows a client to - crash it remotely (found by Caj Larsson). - * Fix potential invalid memory read in certificate parsing, that allows a - client to crash the server remotely if client authentication is enabled - (found using Codenomicon Defensics). - * Add countermeasure against "Lucky 13 strikes back" cache-based attack, - https://dl.acm.org/citation.cfm?id=2714625 - -Bugfix - * Fix bug in Via Padlock support (found by Nikos Mavrogiannopoulos). - * Fix hardclock() (only used in the benchmarking program) with some - versions of mingw64 (found by kxjhlele). - * Fix warnings from mingw64 in timing.c (found by kxjklele). - * Fix potential unintended sign extension in asn1_get_len() on 64-bit - platforms (found with Coverity Scan). - -= Version 1.2.13 released 2015-02-16 -Note: Although PolarSSL has been renamed to mbed TLS, no changes reflecting - this will be made in the 1.2 branch at this point. - -Security - * Fix remotely-triggerable uninitialised pointer dereference caused by - crafted X.509 certificate (TLS server is not affected if it doesn't ask - for a client certificate) (found using Codenomicon Defensics). - * Fix remotely-triggerable memory leak caused by crafted X.509 certificates - (TLS server is not affected if it doesn't ask for a client certificate) - (found using Codenomicon Defensics). - * Fix potential stack overflow while parsing crafted X.509 certificates - (TLS server is not affected if it doesn't ask for a client certificate) - found using Codenomicon Defensics). - * Fix buffer overread of size 1 when parsing crafted X.509 certificates - (TLS server is not affected if it doesn't ask for a client certificate). - -Bugfix - * Fix potential undefined behaviour in Camellia. - * Fix memory leaks in PKCS#5 and PKCS#12. - * Stack buffer overflow if ctr_drbg_update() is called with too large - add_len (found by Jean-Philippe Aumasson) (not triggerable remotely). - * Fix bug in MPI/bignum on s390/s390x (reported by Dan Horák) (introduced - in 1.2.12). - * Fix unchecked return code in x509_crt_parse_path() on Windows (found by - Peter Vaskovic). - * Fix assembly selection for MIPS64 (thanks to James Cowgill). - * ssl_get_verify_result() now works even if the handshake was aborted due - to a failed verification (found by Fredrik Axelsson). - * Skip writing and parsing signature_algorithm extension if none of the - key exchanges enabled needs certificates. This fixes a possible interop - issue with some servers when a zero-length extension was sent. (Reported - by Peter Dettman.) - * On a 0-length input, base64_encode() did not correctly set output length - (found by Hendrik van den Boogaard). - -Changes - * Blind RSA private operations even when POLARSSL_RSA_NO_CRT is defined. - * Forbid repeated extensions in X.509 certificates. - * Add compile-time option POLARSSL_X509_MAX_INTERMEDIATE_CA to limit the - length of an X.509 verification chain (default = 8). -= Version 1.2.12 released 2014-10-24 - -Security - * Remotely-triggerable memory leak when parsing some X.509 certificates - (server is not affected if it doesn't ask for a client certificate). - (Found using Codenomicon Defensics.) - -Bugfix - * Fix potential bad read in parsing ServerHello (found by Adrien - Vialletelle). - * ssl_close_notify() could send more than one message in some circumstances - with non-blocking I/O. - * x509_crt_parse() did not increase total_failed on PEM error - * Fix compiler warnings on iOS (found by Sander Niemeijer). - * Don't print uninitialised buffer in ssl_mail_client (found by Marc Abel). - * Fix net_accept() regarding non-blocking sockets (found by Luca Pesce). - * ssl_read() could return non-application data records on server while - renegotation was pending, and on client when a HelloRequest was received. - * Fix warnings from Clang's scan-build (contributed by Alfred Klomp). - -Changes - * X.509 certificates with more than one AttributeTypeAndValue per - RelativeDistinguishedName are not accepted any more. - * ssl_read() now returns POLARSSL_ERR_NET_WANT_READ rather than - POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE on harmless alerts. - * Accept spaces at end of line or end of buffer in base64_decode(). - -= Version 1.2.11 released 2014-07-11 -Features - * Entropy module now supports seed writing and reading - -Changes - * Introduced POLARSSL_HAVE_READDIR_R for systems without it - * Improvements to the CMake build system, contributed by Julian Ospald. - * Work around a bug of the version of Clang shipped by Apple with Mavericks - that prevented bignum.c from compiling. (Reported by Rafael Baptista.) - * Improvements to tests/Makefile, contributed by Oden Eriksson. - * Use UTC time to check certificate validity. - * Reject certificates with times not in UTC, per RFC 5280. - * Migrate zeroizing of data to polarssl_zeroize() instead of memset() - against unwanted compiler optimizations - -Security - * Forbid change of server certificate during renegotiation to prevent - "triple handshake" attack when authentication mode is optional (the - attack was already impossible when authentication is required). - * Check notBefore timestamp of certificates and CRLs from the future. - * Forbid sequence number wrapping - * Prevent potential NULL pointer dereference in ssl_read_record() (found by - TrustInSoft) - * Fix length checking for AEAD ciphersuites (found by Codenomicon). - It was possible to crash the server (and client) using crafted messages - when a GCM suite was chosen. - -Bugfix - * Fixed X.509 hostname comparison (with non-regular characters) - * SSL now gracefully handles missing RNG - * crypt_and_hash app checks MAC before final decryption - * Fixed x509_crt_parse_path() bug on Windows platforms - * Added missing MPI_CHK() around some statements in mpi_div_mpi() (found by - TrustInSoft) - * Fixed potential overflow in certificate size verification in - ssl_write_certificate() (found by TrustInSoft) - * Fix ASM format in bn_mul.h - * Potential memory leak in bignum_selftest() - * Replaced expired test certificate - * ssl_mail_client now terminates lines with CRLF, instead of LF - * Fix bug in RSA PKCS#1 v1.5 "reversed" operations - * Fixed testing with out-of-source builds using cmake - * Fixed version-major intolerance in server - * Fixed CMake symlinking on out-of-source builds - * Bignum's MIPS-32 assembly was used on MIPS-64, causing chaos. (Found by - Alex Wilson.) - * ssl_init() was leaving a dirty pointer in ssl_context if malloc of - out_ctr failed - * ssl_handshake_init() was leaving dirty pointers in subcontexts if malloc - of one of them failed - * x509_get_current_time() uses localtime_r() to prevent thread issues - * Some example server programs were not sending the close_notify alert. - * Potential memory leak in mpi_exp_mod() when error occurs during - calculation of RR. - * Improve interoperability by not writing extension length in ClientHello - when no extensions are present (found by Matthew Page) - * rsa_check_pubkey() now allows an E up to N - * On OpenBSD, use arc4random_buf() instead of rand() to prevent warnings - * mpi_fill_random() was creating numbers larger than requested on - big-endian platform when size was not an integer number of limbs - * Fix detection of DragonflyBSD in net.c (found by Markus Pfeiffer) - * Stricter check on SSL ClientHello internal sizes compared to actual packet - size (found by TrustInSoft) - * Fix preprocessor checks for bn_mul PPC asm (found by Barry K. Nathan). - * Use \n\t rather than semicolons for bn_mul asm, since some assemblers - interpret semicolons as comment delimiters (found by Barry K. Nathan). - * Disable broken Sparc64 bn_mul assembly (found by Florian Obser). - * Fix base64_decode() to return and check length correctly (in case of - tight buffers) - -= Version 1.2.10 released 2013-10-07 -Changes - * Changed RSA blinding to a slower but thread-safe version - -Bugfix - * Fixed memory leak in RSA as a result of introduction of blinding - * Fixed ssl_pkcs11_decrypt() prototype - * Fixed MSVC project files - -= Version 1.2.9 released 2013-10-01 -Changes - * x509_verify() now case insensitive for cn (RFC 6125 6.4) - -Bugfix - * Fixed potential memory leak when failing to resume a session - * Fixed potential file descriptor leaks (found by Remi Gacogne) - * Minor fixes - -Security - * Fixed potential heap buffer overflow on large hostname setting - * Fixed potential negative value misinterpretation in load_file() - * RSA blinding on CRT operations to counter timing attacks - (found by Cyril Arnaud and Pierre-Alain Fouque) - -= Version 1.2.8 released 2013-06-19 -Features - * Parsing of PKCS#8 encrypted private key files - * PKCS#12 PBE and derivation functions - * Centralized module option values in config.h to allow user-defined - settings without editing header files by using POLARSSL_CONFIG_OPTIONS - -Changes - * HAVEGE random generator disabled by default - * Internally split up x509parse_key() into a (PEM) handler function - and specific DER parser functions for the PKCS#1 and unencrypted - PKCS#8 private key formats - * Added mechanism to provide alternative implementations for all - symmetric cipher and hash algorithms (e.g. POLARSSL_AES_ALT in - config.h) - * PKCS#5 module added. Moved PBKDF2 functionality inside and deprecated - old PBKDF2 module - -Bugfix - * Secure renegotiation extension should only be sent in case client - supports secure renegotiation - * Fixed offset for cert_type list in ssl_parse_certificate_request() - * Fixed const correctness issues that have no impact on the ABI - * x509parse_crt() now better handles PEM error situations - * ssl_parse_certificate() now calls x509parse_crt_der() directly - instead of the x509parse_crt() wrapper that can also parse PEM - certificates - * x509parse_crtpath() is now reentrant and uses more portable stat() - * Fixed bignum.c and bn_mul.h to support Thumb2 and LLVM compiler - * Fixed values for 2-key Triple DES in cipher layer - * ssl_write_certificate_request() can handle empty ca_chain - -Security - * A possible DoS during the SSL Handshake, due to faulty parsing of - PEM-encoded certificates has been fixed (found by Jack Lloyd) - -= Version 1.2.7 released 2013-04-13 -Features - * Ability to specify allowed ciphersuites based on the protocol version. - -Changes - * Default Blowfish keysize is now 128-bits - * Test suites made smaller to accommodate Raspberry Pi - -Bugfix - * Fix for MPI assembly for ARM - * GCM adapted to support sizes > 2^29 - -= Version 1.2.6 released 2013-03-11 -Bugfix - * Fixed memory leak in ssl_free() and ssl_reset() for active session - * Corrected GCM counter incrementation to use only 32-bits instead of - 128-bits (found by Yawning Angel) - * Fixes for 64-bit compilation with MS Visual Studio - * Fixed net_bind() for specified IP addresses on little endian systems - * Fixed assembly code for ARM (Thumb and regular) for some compilers - -Changes - * Internally split up rsa_pkcs1_encrypt(), rsa_pkcs1_decrypt(), - rsa_pkcs1_sign() and rsa_pkcs1_verify() to separate PKCS#1 v1.5 and - PKCS#1 v2.1 functions - * Added support for custom labels when using rsa_rsaes_oaep_encrypt() - or rsa_rsaes_oaep_decrypt() - * Re-added handling for SSLv2 Client Hello when the define - POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is set - * The SSL session cache module (ssl_cache) now also retains peer_cert - information (not the entire chain) - -Security - * Removed further timing differences during SSL message decryption in - ssl_decrypt_buf() - * Removed timing differences due to bad padding from - rsa_rsaes_pkcs1_v15_decrypt() and rsa_pkcs1_decrypt() for PKCS#1 v1.5 - operations - -= Version 1.2.5 released 2013-02-02 -Changes - * Allow enabling of dummy error_strerror() to support some use-cases - * Debug messages about padding errors during SSL message decryption are - disabled by default and can be enabled with POLARSSL_SSL_DEBUG_ALL - * Sending of security-relevant alert messages that do not break - interoperability can be switched on/off with the flag - POLARSSL_SSL_ALL_ALERT_MESSAGES - -Security - * Removed timing differences during SSL message decryption in - ssl_decrypt_buf() due to badly formatted padding - -= Version 1.2.4 released 2013-01-25 -Changes - * More advanced SSL ciphersuite representation and moved to more dynamic - SSL core - * Added ssl_handshake_step() to allow single stepping the handshake process - -Bugfix - * Memory leak when using RSA_PKCS_V21 operations fixed - * Handle future version properly in ssl_write_certificate_request() - * Correctly handle CertificateRequest message in client for <= TLS 1.1 - without DN list - -= Version 1.2.3 released 2012-11-26 -Bugfix - * Server not always sending correct CertificateRequest message - -= Version 1.2.2 released 2012-11-24 -Changes - * Added p_hw_data to ssl_context for context specific hardware acceleration - data - * During verify trust-CA is only checked for expiration and CRL presence - -Bugfixes - * Fixed client authentication compatibility - * Fixed dependency on POLARSSL_SHA4_C in SSL modules - -= Version 1.2.1 released 2012-11-20 -Changes - * Depth that the certificate verify callback receives is now numbered - bottom-up (Peer cert depth is 0) - -Bugfixes - * Fixes for MSVC6 - * Moved mpi_inv_mod() outside POLARSSL_GENPRIME - * Allow R and A to point to same mpi in mpi_div_mpi (found by Manuel - Pégourié-Gonnard) - * Fixed possible segfault in mpi_shift_r() (found by Manuel - Pégourié-Gonnard) - * Added max length check for rsa_pkcs1_sign with PKCS#1 v2.1 - -= Version 1.2.0 released 2012-10-31 -Features - * Added support for NULL cipher (POLARSSL_CIPHER_NULL_CIPHER) and weak - ciphersuites (POLARSSL_ENABLE_WEAK_CIPHERSUITES). They are disabled by - default! - * Added support for wildcard certificates - * Added support for multi-domain certificates through the X509 Subject - Alternative Name extension - * Added preliminary ASN.1 buffer writing support - * Added preliminary X509 Certificate Request writing support - * Added key_app_writer example application - * Added cert_req example application - * Added base Galois Counter Mode (GCM) for AES - * Added TLS 1.2 support (RFC 5246) - * Added GCM suites to TLS 1.2 (RFC 5288) - * Added commandline error code convertor (util/strerror) - * Added support for Hardware Acceleration hooking in SSL/TLS - * Added OpenSSL / PolarSSL compatibility script (tests/compat.sh) and - example application (programs/ssl/o_p_test) (requires OpenSSL) - * Added X509 CA Path support - * Added Thumb assembly optimizations - * Added DEFLATE compression support as per RFC3749 (requires zlib) - * Added blowfish algorithm (Generic and cipher layer) - * Added PKCS#5 PBKDF2 key derivation function - * Added Secure Renegotiation (RFC 5746) - * Added predefined DHM groups from RFC 5114 - * Added simple SSL session cache implementation - * Added ServerName extension parsing (SNI) at server side - * Added option to add minimum accepted SSL/TLS protocol version - -Changes - * Removed redundant POLARSSL_DEBUG_MSG define - * AES code only check for Padlock once - * Fixed const-correctness mpi_get_bit() - * Documentation for mpi_lsb() and mpi_msb() - * Moved out_msg to out_hdr + 32 to support hardware acceleration - * Changed certificate verify behaviour to comply with RFC 6125 section 6.3 - to not match CN if subjectAltName extension is present (Closes ticket #56) - * Cipher layer cipher_mode_t POLARSSL_MODE_CFB128 is renamed to - POLARSSL_MODE_CFB, to also handle different block size CFB modes. - * Removed handling for SSLv2 Client Hello (as per RFC 5246 recommendation) - * Revamped session resumption handling - * Generalized external private key implementation handling (like PKCS#11) - in SSL/TLS - * Revamped x509_verify() and the SSL f_vrfy callback implementations - * Moved from unsigned long to fixed width uint32_t types throughout code - * Renamed ciphersuites naming scheme to IANA reserved names - -Bugfix - * Fixed handling error in mpi_cmp_mpi() on longer B values (found by - Hui Dong) - * Fixed potential heap corruption in x509_name allocation - * Fixed single RSA test that failed on Big Endian systems (Closes ticket #54) - * mpi_exp_mod() now correctly handles negative base numbers (Closes ticket - #52) - * Handle encryption with private key and decryption with public key as per - RFC 2313 - * Handle empty certificate subject names - * Prevent reading over buffer boundaries on X509 certificate parsing - * mpi_add_abs() now correctly handles adding short numbers to long numbers - with carry rollover (found by Ruslan Yushchenko) - * Handle existence of OpenSSL Trust Extensions at end of X.509 DER blob - * Fixed MPI assembly for SPARC64 platform - -Security - * Fixed potential memory zeroization on miscrafted RSA key (found by Eloi - Vanderbeken) - -= Version 1.1.8 released on 2013-10-01 -Bugfix - * Fixed potential memory leak when failing to resume a session - * Fixed potential file descriptor leaks - -Security - * Potential buffer-overflow for ssl_read_record() (independently found by - both TrustInSoft and Paul Brodeur of Leviathan Security Group) - * Potential negative value misinterpretation in load_file() - * Potential heap buffer overflow on large hostname setting - -= Version 1.1.7 released on 2013-06-19 -Changes - * HAVEGE random generator disabled by default - -Bugfix - * x509parse_crt() now better handles PEM error situations - * ssl_parse_certificate() now calls x509parse_crt_der() directly - instead of the x509parse_crt() wrapper that can also parse PEM - certificates - * Fixed values for 2-key Triple DES in cipher layer - * ssl_write_certificate_request() can handle empty ca_chain - -Security - * A possible DoS during the SSL Handshake, due to faulty parsing of - PEM-encoded certificates has been fixed (found by Jack Lloyd) - -= Version 1.1.6 released on 2013-03-11 -Bugfix - * Fixed net_bind() for specified IP addresses on little endian systems - -Changes - * Allow enabling of dummy error_strerror() to support some use-cases - * Debug messages about padding errors during SSL message decryption are - disabled by default and can be enabled with POLARSSL_SSL_DEBUG_ALL - -Security - * Removed timing differences during SSL message decryption in - ssl_decrypt_buf() - * Removed timing differences due to bad padding from - rsa_rsaes_pkcs1_v15_decrypt() and rsa_pkcs1_decrypt() for PKCS#1 v1.5 - operations - -= Version 1.1.5 released on 2013-01-16 -Bugfix - * Fixed MPI assembly for SPARC64 platform - * Handle existence of OpenSSL Trust Extensions at end of X.509 DER blob - * mpi_add_abs() now correctly handles adding short numbers to long numbers - with carry rollover - * Moved mpi_inv_mod() outside POLARSSL_GENPRIME - * Prevent reading over buffer boundaries on X509 certificate parsing - * mpi_exp_mod() now correctly handles negative base numbers (Closes ticket - #52) - * Fixed possible segfault in mpi_shift_r() (found by Manuel - Pégourié-Gonnard) - * Allow R and A to point to same mpi in mpi_div_mpi (found by Manuel - Pégourié-Gonnard) - * Added max length check for rsa_pkcs1_sign with PKCS#1 v2.1 - * Memory leak when using RSA_PKCS_V21 operations fixed - * Handle encryption with private key and decryption with public key as per - RFC 2313 - * Fixes for MSVC6 - -Security - * Fixed potential memory zeroization on miscrafted RSA key (found by Eloi - Vanderbeken) - -= Version 1.1.4 released on 2012-05-31 -Bugfix - * Correctly handle empty SSL/TLS packets (Found by James Yonan) - * Fixed potential heap corruption in x509_name allocation - * Fixed single RSA test that failed on Big Endian systems (Closes ticket #54) - -= Version 1.1.3 released on 2012-04-29 -Bugfix - * Fixed random MPI generation to not generate more size than requested. - -= Version 1.1.2 released on 2012-04-26 -Bugfix - * Fixed handling error in mpi_cmp_mpi() on longer B values (found by - Hui Dong) - -Security - * Fixed potential memory corruption on miscrafted client messages (found by - Frama-C team at CEA LIST) - * Fixed generation of DHM parameters to correct length (found by Ruslan - Yushchenko) - -= Version 1.1.1 released on 2012-01-23 -Bugfix - * Check for failed malloc() in ssl_set_hostname() and x509_get_entries() - (Closes ticket #47, found by Hugo Leisink) - * Fixed issues with Intel compiler on 64-bit systems (Closes ticket #50) - * Fixed multiple compiler warnings for VS6 and armcc - * Fixed bug in CTR_CRBG selftest - -= Version 1.1.0 released on 2011-12-22 -Features - * Added ssl_session_reset() to allow better multi-connection pools of - SSL contexts without needing to set all non-connection-specific - data and pointers again. Adapted ssl_server to use this functionality. - * Added ssl_set_max_version() to allow clients to offer a lower maximum - supported version to a server to help buggy server implementations. - (Closes ticket #36) - * Added cipher_get_cipher_mode() and cipher_get_cipher_operation() - introspection functions (Closes ticket #40) - * Added CTR_DRBG based on AES-256-CTR (NIST SP 800-90) random generator - * Added a generic entropy accumulator that provides support for adding - custom entropy sources and added some generic and platform dependent - entropy sources - -Changes - * Documentation for AES and Camellia in modes CTR and CFB128 clarified. - * Fixed rsa_encrypt and rsa_decrypt examples to use public key for - encryption and private key for decryption. (Closes ticket #34) - * Inceased maximum size of ASN1 length reads to 32-bits. - * Added an EXPLICIT tag number parameter to x509_get_ext() - * Added a separate CRL entry extension parsing function - * Separated the ASN.1 parsing code from the X.509 specific parsing code. - So now there is a module that is controlled with POLARSSL_ASN1_PARSE_C. - * Changed the defined key-length of DES ciphers in cipher.h to include the - parity bits, to prevent mistakes in copying data. (Closes ticket #33) - * Loads of minimal changes to better support WINCE as a build target - (Credits go to Marco Lizza) - * Added POLARSSL_MPI_WINDOW_SIZE definition to allow easier time to memory - trade-off - * Introduced POLARSSL_MPI_MAX_SIZE and POLARSSL_MPI_MAX_BITS for MPI size - management (Closes ticket #44) - * Changed the used random function pointer to more flexible format. Renamed - havege_rand() to havege_random() to prevent mistakes. Lots of changes as - a consequence in library code and programs - * Moved all examples programs to use the new entropy and CTR_DRBG - * Added permissive certificate parsing to x509parse_crt() and - x509parse_crtfile(). With permissive parsing the parsing does not stop on - encountering a parse-error. Beware that the meaning of return values has - changed! - * All error codes are now negative. Even on mermory failures and IO errors. - -Bugfix - * Fixed faulty HMAC-MD2 implementation. Found by dibac. (Closes - ticket #37) - * Fixed a bug where the CRL parser expected an EXPLICIT ASN.1 tag - before version numbers - * Allowed X509 key usage parsing to accept 4 byte values instead of the - standard 1 byte version sometimes used by Microsoft. (Closes ticket #38) - * Fixed incorrect behaviour in case of RSASSA-PSS with a salt length - smaller than the hash length. (Closes ticket #41) - * If certificate serial is longer than 32 octets, serial number is now - appended with '....' after first 28 octets - * Improved build support for s390x and sparc64 in bignum.h - * Fixed MS Visual C++ name clash with int64 in sha4.h - * Corrected removal of leading "00:" in printing serial numbers in - certificates and CRLs - -= Version 1.0.0 released on 2011-07-27 -Features - * Expanded cipher layer with support for CFB128 and CTR mode - * Added rsa_encrypt and rsa_decrypt simple example programs. - -Changes - * The generic cipher and message digest layer now have normal error - codes instead of integers - -Bugfix - * Undid faulty bug fix in ssl_write() when flushing old data (Ticket - #18) - -= Version 0.99-pre5 released on 2011-05-26 -Features - * Added additional Cipher Block Modes to symmetric ciphers - (AES CTR, Camellia CTR, XTEA CBC) including the option to - enable and disable individual modes when needed - * Functions requiring File System functions can now be disabled - by undefining POLARSSL_FS_IO - * A error_strerror function() has been added to translate between - error codes and their description. - * Added mpi_get_bit() and mpi_set_bit() individual bit setter/getter - functions. - * Added ssl_mail_client and ssl_fork_server as example programs. - -Changes - * Major argument / variable rewrite. Introduced use of size_t - instead of int for buffer lengths and loop variables for - better unsigned / signed use. Renamed internal bigint types - t_int and t_dbl to t_uint and t_udbl in the process - * mpi_init() and mpi_free() now only accept a single MPI - argument and do not accept variable argument lists anymore. - * The error codes have been remapped and combining error codes - is now done with a PLUS instead of an OR as error codes - used are negative. - * Changed behaviour of net_read(), ssl_fetch_input() and ssl_recv(). - net_recv() now returns 0 on EOF instead of - POLARSSL_ERR_NET_CONN_RESET. ssl_fetch_input() returns - POLARSSL_ERR_SSL_CONN_EOF on an EOF from its f_recv() function. - ssl_read() returns 0 if a POLARSSL_ERR_SSL_CONN_EOF is received - after the handshake. - * Network functions now return POLARSSL_ERR_NET_WANT_READ or - POLARSSL_ERR_NET_WANT_WRITE instead of the ambiguous - POLARSSL_ERR_NET_TRY_AGAIN - -= Version 0.99-pre4 released on 2011-04-01 -Features - * Added support for PKCS#1 v2.1 encoding and thus support - for the RSAES-OAEP and RSASSA-PSS operations. - * Reading of Public Key files incorporated into default x509 - functionality as well. - * Added mpi_fill_random() for centralized filling of big numbers - with random data (Fixed ticket #10) - -Changes - * Debug print of MPI now removes leading zero octets and - displays actual bit size of the value. - * x509parse_key() (and as a consequence x509parse_keyfile()) - does not zeroize memory in advance anymore. Use rsa_init() - before parsing a key or keyfile! - -Bugfix - * Debug output of MPI's now the same independent of underlying - platform (32-bit / 64-bit) (Fixes ticket #19, found by Mads - Kiilerich and Mihai Militaru) - * Fixed bug in ssl_write() when flushing old data (Fixed ticket - #18, found by Nikolay Epifanov) - * Fixed proper handling of RSASSA-PSS verification with variable - length salt lengths - -= Version 0.99-pre3 released on 2011-02-28 -This release replaces version 0.99-pre2 which had possible copyright issues. -Features - * Parsing PEM private keys encrypted with DES and AES - are now supported as well (Fixes ticket #5) - * Added crl_app program to allow easy reading and - printing of X509 CRLs from file - -Changes - * Parsing of PEM files moved to separate module (Fixes - ticket #13). Also possible to remove PEM support for - systems only using DER encoding - -Bugfixes - * Corrected parsing of UTCTime dates before 1990 and - after 1950 - * Support more exotic OID's when parsing certificates - (found by Mads Kiilerich) - * Support more exotic name representations when parsing - certificates (found by Mads Kiilerich) - * Replaced the expired test certificates - * Do not bail out if no client certificate specified. Try - to negotiate anonymous connection (Fixes ticket #12, - found by Boris Krasnovskiy) - -Security fixes - * Fixed a possible Man-in-the-Middle attack on the - Diffie Hellman key exchange (thanks to Larry Highsmith, - Subreption LLC) - -= Version 0.99-pre1 released on 2011-01-30 -Features -Note: Most of these features have been donated by Fox-IT - * Added Doxygen source code documentation parts - * Added reading of DHM context from memory and file - * Improved X509 certificate parsing to include extended - certificate fields, including Key Usage - * Improved certificate verification and verification - against the available CRLs - * Detection for DES weak keys and parity bits added - * Improvements to support integration in other - applications: - + Added generic message digest and cipher wrapper - + Improved information about current capabilities, - status, objects and configuration - + Added verification callback on certificate chain - verification to allow external blacklisting - + Additional example programs to show usage - * Added support for PKCS#11 through the use of the - libpkcs11-helper library - -Changes - * x509parse_time_expired() checks time in addition to - the existing date check - * The ciphers member of ssl_context and the cipher member - of ssl_session have been renamed to ciphersuites and - ciphersuite respectively. This clarifies the difference - with the generic cipher layer and is better naming - altogether - -= Version 0.14.0 released on 2010-08-16 -Features - * Added support for SSL_EDH_RSA_AES_128_SHA and - SSL_EDH_RSA_CAMELLIA_128_SHA ciphersuites - * Added compile-time and run-time version information - * Expanded ssl_client2 arguments for more flexibility - * Added support for TLS v1.1 - -Changes - * Made Makefile cleaner - * Removed dependency on rand() in rsa_pkcs1_encrypt(). - Now using random fuction provided to function and - changed the prototype of rsa_pkcs1_encrypt(), - rsa_init() and rsa_gen_key(). - * Some SSL defines were renamed in order to avoid - future confusion - -Bug fixes - * Fixed CMake out of source build for tests (found by - kkert) - * rsa_check_private() now supports PKCS1v2 keys as well - * Fixed deadlock in rsa_pkcs1_encrypt() on failing random - generator - -= Version 0.13.1 released on 2010-03-24 -Bug fixes - * Fixed Makefile in library that was mistakenly merged - * Added missing const string fixes - -= Version 0.13.0 released on 2010-03-21 -Features - * Added option parsing for host and port selection to - ssl_client2 - * Added support for GeneralizedTime in X509 parsing - * Added cert_app program to allow easy reading and - printing of X509 certificates from file or SSL - connection. - -Changes - * Added const correctness for main code base - * X509 signature algorithm determination is now - in a function to allow easy future expansion - * Changed symmetric cipher functions to - identical interface (returning int result values) - * Changed ARC4 to use separate input/output buffer - * Added reset function for HMAC context as speed-up - for specific use-cases - -Bug fixes - * Fixed bug resulting in failure to send the last - certificate in the chain in ssl_write_certificate() and - ssl_write_certificate_request() (found by fatbob) - * Added small fixes for compiler warnings on a Mac - (found by Frank de Brabander) - * Fixed algorithmic bug in mpi_is_prime() (found by - Smbat Tonoyan) - -= Version 0.12.1 released on 2009-10-04 -Changes - * Coverage test definitions now support 'depends_on' - tagging system. - * Tests requiring specific hashing algorithms now honor - the defines. - -Bug fixes - * Changed typo in #ifdef in x509parse.c (found - by Eduardo) - -= Version 0.12.0 released on 2009-07-28 -Features - * Added CMake makefiles as alternative to regular Makefiles. - * Added preliminary Code Coverage tests for AES, ARC4, - Base64, MPI, SHA-family, MD-family, HMAC-SHA-family, - Camellia, DES, 3-DES, RSA PKCS#1, XTEA, Diffie-Hellman - and X509parse. - -Changes - * Error codes are not (necessarily) negative. Keep - this is mind when checking for errors. - * RSA_RAW renamed to SIG_RSA_RAW for consistency. - * Fixed typo in name of POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE. - * Changed interface for AES and Camellia setkey functions - to indicate invalid key lengths. - -Bug fixes - * Fixed include location of endian.h on FreeBSD (found by - Gabriel) - * Fixed include location of endian.h and name clash on - Apples (found by Martin van Hensbergen) - * Fixed HMAC-MD2 by modifying md2_starts(), so that the - required HMAC ipad and opad variables are not cleared. - (found by code coverage tests) - * Prevented use of long long in bignum if - POLARSSL_HAVE_LONGLONG not defined (found by Giles - Bathgate). - * Fixed incorrect handling of negative strings in - mpi_read_string() (found by code coverage tests). - * Fixed segfault on handling empty rsa_context in - rsa_check_pubkey() and rsa_check_privkey() (found by - code coverage tests). - * Fixed incorrect handling of one single negative input - value in mpi_add_abs() (found by code coverage tests). - * Fixed incorrect handling of negative first input - value in mpi_sub_abs() (found by code coverage tests). - * Fixed incorrect handling of negative first input - value in mpi_mod_mpi() and mpi_mod_int(). Resulting - change also affects mpi_write_string() (found by code - coverage tests). - * Corrected is_prime() results for 0, 1 and 2 (found by - code coverage tests). - * Fixed Camellia and XTEA for 64-bit Windows systems. - -= Version 0.11.1 released on 2009-05-17 - * Fixed missing functionality for SHA-224, SHA-256, SHA384, - SHA-512 in rsa_pkcs1_sign() - -= Version 0.11.0 released on 2009-05-03 - * Fixed a bug in mpi_gcd() so that it also works when both - input numbers are even and added testcases to check - (found by Pierre Habouzit). - * Added support for SHA-224, SHA-256, SHA-384 and SHA-512 - one way hash functions with the PKCS#1 v1.5 signing and - verification. - * Fixed minor bug regarding mpi_gcd located within the - POLARSSL_GENPRIME block. - * Fixed minor memory leak in x509parse_crt() and added better - handling of 'full' certificate chains (found by Mathias - Olsson). - * Centralized file opening and reading for x509 files into - load_file() - * Made definition of net_htons() endian-clean for big endian - systems (Found by Gernot). - * Undefining POLARSSL_HAVE_ASM now also handles prevents asm in - padlock and timing code. - * Fixed an off-by-one buffer allocation in ssl_set_hostname() - responsible for crashes and unwanted behaviour. - * Added support for Certificate Revocation List (CRL) parsing. - * Added support for CRL revocation to x509parse_verify() and - SSL/TLS code. - * Fixed compatibility of XTEA and Camellia on a 64-bit system - (found by Felix von Leitner). - -= Version 0.10.0 released on 2009-01-12 - * Migrated XySSL to PolarSSL - * Added XTEA symmetric cipher - * Added Camellia symmetric cipher - * Added support for ciphersuites: SSL_RSA_CAMELLIA_128_SHA, - SSL_RSA_CAMELLIA_256_SHA and SSL_EDH_RSA_CAMELLIA_256_SHA - * Fixed dangerous bug that can cause a heap overflow in - rsa_pkcs1_decrypt (found by Christophe Devine) - -================================================================ -XySSL ChangeLog - -= Version 0.9 released on 2008-03-16 - - * Added support for ciphersuite: SSL_RSA_AES_128_SHA - * Enabled support for large files by default in aescrypt2.c - * Preliminary openssl wrapper contributed by David Barrett - * Fixed a bug in ssl_write() that caused the same payload to - be sent twice in non-blocking mode when send returns EAGAIN - * Fixed ssl_parse_client_hello(): session id and challenge must - not be swapped in the SSLv2 ClientHello (found by Greg Robson) - * Added user-defined callback debug function (Krystian Kolodziej) - * Before freeing a certificate, properly zero out all cert. data - * Fixed the "mode" parameter so that encryption/decryption are - not swapped on PadLock; also fixed compilation on older versions - of gcc (bug reported by David Barrett) - * Correctly handle the case in padlock_xcryptcbc() when input or - ouput data is non-aligned by falling back to the software - implementation, as VIA Nehemiah cannot handle non-aligned buffers - * Fixed a memory leak in x509parse_crt() which was reported by Greg - Robson-Garth; some x509write.c fixes by Pascal Vizeli, thanks to - Matthew Page who reported several bugs - * Fixed x509_get_ext() to accept some rare certificates which have - an INTEGER instead of a BOOLEAN for BasicConstraints::cA. - * Added support on the client side for the TLS "hostname" extension - (patch contributed by David Patino) - * Make x509parse_verify() return BADCERT_CN_MISMATCH when an empty - string is passed as the CN (bug reported by spoofy) - * Added an option to enable/disable the BN assembly code - * Updated rsa_check_privkey() to verify that (D*E) = 1 % (P-1)*(Q-1) - * Disabled obsolete hash functions by default (MD2, MD4); updated - selftest and benchmark to not test ciphers that have been disabled - * Updated x509parse_cert_info() to correctly display byte 0 of the - serial number, setup correct server port in the ssl client example - * Fixed a critical denial-of-service with X.509 cert. verification: - peer may cause xyssl to loop indefinitely by sending a certificate - for which the RSA signature check fails (bug reported by Benoit) - * Added test vectors for: AES-CBC, AES-CFB, DES-CBC and 3DES-CBC, - HMAC-MD5, HMAC-SHA1, HMAC-SHA-256, HMAC-SHA-384, and HMAC-SHA-512 - * Fixed HMAC-SHA-384 and HMAC-SHA-512 (thanks to Josh Sinykin) - * Modified ssl_parse_client_key_exchange() to protect against - Daniel Bleichenbacher attack on PKCS#1 v1.5 padding, as well - as the Klima-Pokorny-Rosa extension of Bleichenbacher's attack - * Updated rsa_gen_key() so that ctx->N is always nbits in size - * Fixed assembly PPC compilation errors on Mac OS X, thanks to - David Barrett and Dusan Semen - -= Version 0.8 released on 2007-10-20 - - * Modified the HMAC functions to handle keys larger - than 64 bytes, thanks to Stephane Desneux and gary ng - * Fixed ssl_read_record() to properly update the handshake - message digests, which fixes IE6/IE7 client authentication - * Cleaned up the XYSSL* #defines, suggested by Azriel Fasten - * Fixed net_recv(), thanks to Lorenz Schori and Egon Kocjan - * Added user-defined callbacks for handling I/O and sessions - * Added lots of debugging output in the SSL/TLS functions - * Added preliminary X.509 cert. writing by Pascal Vizeli - * Added preliminary support for the VIA PadLock routines - * Added AES-CFB mode of operation, contributed by chmike - * Added an SSL/TLS stress testing program (ssl_test.c) - * Updated the RSA PKCS#1 code to allow choosing between - RSA_PUBLIC and RSA_PRIVATE, as suggested by David Barrett - * Updated ssl_read() to skip 0-length records from OpenSSL - * Fixed the make install target to comply with *BSD make - * Fixed a bug in mpi_read_binary() on 64-bit platforms - * mpi_is_prime() speedups, thanks to Kevin McLaughlin - * Fixed a long standing memory leak in mpi_is_prime() - * Replaced realloc with malloc in mpi_grow(), and set - the sign of zero as positive in mpi_init() (reported - by Jonathan M. McCune) - -= Version 0.7 released on 2007-07-07 - - * Added support for the MicroBlaze soft-core processor - * Fixed a bug in ssl_tls.c which sometimes prevented SSL - connections from being established with non-blocking I/O - * Fixed a couple bugs in the VS6 and UNIX Makefiles - * Fixed the "PIC register ebx clobbered in asm" bug - * Added HMAC starts/update/finish support functions - * Added the SHA-224, SHA-384 and SHA-512 hash functions - * Fixed the net_set_*block routines, thanks to Andreas - * Added a few demonstration programs: md5sum, sha1sum, - dh_client, dh_server, rsa_genkey, rsa_sign, rsa_verify - * Added new bignum import and export helper functions - * Rewrote README.txt in program/ssl/ca to better explain - how to create a test PKI - -= Version 0.6 released on 2007-04-01 - - * Ciphers used in SSL/TLS can now be disabled at compile - time, to reduce the memory footprint on embedded systems - * Added multiply assembly code for the TriCore and modified - havege_struct for this processor, thanks to David Patiño - * Added multiply assembly code for 64-bit PowerPCs, - thanks to Peking University and the OSU Open Source Lab - * Added experimental support of Quantum Cryptography - * Added support for autoconf, contributed by Arnaud Cornet - * Fixed "long long" compilation issues on IA-64 and PPC64 - * Fixed a bug introduced in xyssl-0.5/timing.c: hardclock - was not being correctly defined on ARM and MIPS - -= Version 0.5 released on 2007-03-01 - - * Added multiply assembly code for SPARC and Alpha - * Added (beta) support for non-blocking I/O operations - * Implemented session resuming and client authentication - * Fixed some portability issues on WinCE, MINIX 3, Plan9 - (thanks to Benjamin Newman), HP-UX, FreeBSD and Solaris - * Improved the performance of the EDH key exchange - * Fixed a bug that caused valid packets with a payload - size of 16384 bytes to be rejected - -= Version 0.4 released on 2007-02-01 - - * Added support for Ephemeral Diffie-Hellman key exchange - * Added multiply asm code for SSE2, ARM, PPC, MIPS and M68K - * Various improvement to the modular exponentiation code - * Rewrote the headers to generate the API docs with doxygen - * Fixed a bug in ssl_encrypt_buf (incorrect padding was - generated) and in ssl_parse_client_hello (max. client - version was not properly set), thanks to Didier Rebeix - * Fixed another bug in ssl_parse_client_hello: clients with - cipherlists larger than 96 bytes were incorrectly rejected - * Fixed a couple memory leak in x509_read.c - -= Version 0.3 released on 2007-01-01 - - * Added server-side SSLv3 and TLSv1.0 support - * Multiple fixes to enhance the compatibility with g++, - thanks to Xosé Antón Otero Ferreira - * Fixed a bug in the CBC code, thanks to dowst; also, - the bignum code is no longer dependent on long long - * Updated rsa_pkcs1_sign to handle arbitrary large inputs - * Updated timing.c for improved compatibility with i386 - and 486 processors, thanks to Arnaud Cornet - -= Version 0.2 released on 2006-12-01 - - * Updated timing.c to support ARM and MIPS arch - * Updated the MPI code to support 8086 on MSVC 1.5 - * Added the copyright notice at the top of havege.h - * Fixed a bug in sha2_hmac, thanks to newsoft/Wenfang Zhang - * Fixed a bug reported by Adrian Rüegsegger in x509_read_key - * Fixed a bug reported by Torsten Lauter in ssl_read_record - * Fixed a bug in rsa_check_privkey that would wrongly cause - valid RSA keys to be dismissed (thanks to oldwolf) - * Fixed a bug in mpi_is_prime that caused some primes to fail - the Miller-Rabin primality test - - I'd also like to thank Younès Hafri for the CRUX linux port, - Khalil Petit who added XySSL into pkgsrc and Arnaud Cornet - who maintains the Debian package :-) - -= Version 0.1 released on 2006-11-01 - diff --git a/components/mbedtls/LICENSE b/components/mbedtls/LICENSE deleted file mode 100644 index 546a8e631f..0000000000 --- a/components/mbedtls/LICENSE +++ /dev/null @@ -1,2 +0,0 @@ -Unless specifically indicated otherwise in a file, files are licensed -under the Apache 2.0 license, as can be found in: apache-2.0.txt diff --git a/components/mbedtls/apache-2.0.txt b/components/mbedtls/apache-2.0.txt deleted file mode 100644 index d645695673..0000000000 --- a/components/mbedtls/apache-2.0.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/components/mbedtls/component.mk b/components/mbedtls/component.mk index d2cd0455f5..af0b8b6ea7 100644 --- a/components/mbedtls/component.mk +++ b/components/mbedtls/component.mk @@ -2,6 +2,8 @@ # Component Makefile # -COMPONENT_ADD_INCLUDEDIRS := port/include include +COMPONENT_ADD_INCLUDEDIRS := port/include mbedtls/include -COMPONENT_SRCDIRS := library port +COMPONENT_SRCDIRS := mbedtls/library port + +COMPONENT_OBJEXCLUDE := mbedtls/library/net_sockets.o diff --git a/components/mbedtls/include/.gitignore b/components/mbedtls/include/.gitignore deleted file mode 100644 index bf67d02ed8..0000000000 --- a/components/mbedtls/include/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -Makefile -*.sln -*.vcxproj -mbedtls/check_config diff --git a/components/mbedtls/include/mbedtls/aes.h b/components/mbedtls/include/mbedtls/aes.h deleted file mode 100644 index 1829f72402..0000000000 --- a/components/mbedtls/include/mbedtls/aes.h +++ /dev/null @@ -1,343 +0,0 @@ -/** - * \file aes.h - * - * \brief AES block cipher - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_AES_H -#define MBEDTLS_AES_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -/* padlock.c and aesni.c rely on these values! */ -#define MBEDTLS_AES_ENCRYPT 1 -#define MBEDTLS_AES_DECRYPT 0 - -#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ -#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ - -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -#if !defined(MBEDTLS_AES_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief AES context structure - * - * \note buf is able to hold 32 extra bytes, which can be used: - * - for alignment purposes if VIA padlock is used, and/or - * - to simplify key expansion in the 256-bit case by - * generating an extra round key - */ -typedef struct -{ - int nr; /*!< number of rounds */ - uint32_t *rk; /*!< AES round keys */ - uint32_t buf[68]; /*!< unaligned data */ -} -mbedtls_aes_context; - -/** - * \brief Initialize AES context - * - * \param ctx AES context to be initialized - */ -void mbedtls_aes_init( mbedtls_aes_context *ctx ); - -/** - * \brief Clear AES context - * - * \param ctx AES context to be cleared - */ -void mbedtls_aes_free( mbedtls_aes_context *ctx ); - -/** - * \brief AES key schedule (encryption) - * - * \param ctx AES context to be initialized - * \param key encryption key - * \param keybits must be 128, 192 or 256 - * - * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH - */ -int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, - unsigned int keybits ); - -/** - * \brief AES key schedule (decryption) - * - * \param ctx AES context to be initialized - * \param key decryption key - * \param keybits must be 128, 192 or 256 - * - * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH - */ -int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, - unsigned int keybits ); - -/** - * \brief AES-ECB block encryption/decryption - * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param input 16-byte input block - * \param output 16-byte output block - * - * \return 0 if successful - */ -int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/** - * \brief AES-CBC buffer encryption/decryption - * Length should be a multiple of the block - * size (16 bytes) - * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. - * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH - */ -int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -/** - * \brief AES-CFB128 buffer encryption/decryption. - * - * Note: Due to the nature of CFB you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT. - * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. - * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param length length of the input data - * \param iv_off offset in IV (updated after use) - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful - */ -int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); - -/** - * \brief AES-CFB8 buffer encryption/decryption. - * - * Note: Due to the nature of CFB you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT. - * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. - * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful - */ -int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); -#endif /*MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -/** - * \brief AES-CTR buffer encryption/decryption - * - * Warning: You have to keep the maximum use of your counter in mind! - * - * Note: Due to the nature of CTR you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT. - * - * \param ctx AES context - * \param length The length of the data - * \param nc_off The offset in the current stream_block (for resuming - * within current cipher stream). The offset pointer to - * should be 0 at the start of a stream. - * \param nonce_counter The 128-bit nonce and counter. - * \param stream_block The saved stream-block for resuming. Is overwritten - * by the function. - * \param input The input data stream - * \param output The output data stream - * - * \return 0 if successful - */ -int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[16], - unsigned char stream_block[16], - const unsigned char *input, - unsigned char *output ); -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -/** - * \brief Internal AES block encryption function - * (Only exposed to allow overriding it, - * see MBEDTLS_AES_ENCRYPT_ALT) - * - * \param ctx AES context - * \param input Plaintext block - * \param output Output (ciphertext) block - * - * \return 0 if successful - */ -int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ); - -/** - * \brief Internal AES block decryption function - * (Only exposed to allow overriding it, - * see MBEDTLS_AES_DECRYPT_ALT) - * - * \param ctx AES context - * \param input Ciphertext block - * \param output Output (plaintext) block - * - * \return 0 if successful - */ -int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ); - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief Deprecated internal AES block encryption function - * without return value. - * - * \deprecated Superseded by mbedtls_aes_encrypt_ext() in 2.5.0 - * - * \param ctx AES context - * \param input Plaintext block - * \param output Output (ciphertext) block - */ -MBEDTLS_DEPRECATED void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ); - -/** - * \brief Deprecated internal AES block decryption function - * without return value. - * - * \deprecated Superseded by mbedtls_aes_decrypt_ext() in 2.5.0 - * - * \param ctx AES context - * \param input Ciphertext block - * \param output Output (plaintext) block - */ -MBEDTLS_DEPRECATED void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_AES_ALT */ -#include "aes_alt.h" -#endif /* MBEDTLS_AES_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_aes_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* aes.h */ diff --git a/components/mbedtls/include/mbedtls/aesni.h b/components/mbedtls/include/mbedtls/aesni.h deleted file mode 100644 index b1b7f1cdec..0000000000 --- a/components/mbedtls/include/mbedtls/aesni.h +++ /dev/null @@ -1,111 +0,0 @@ -/** - * \file aesni.h - * - * \brief AES-NI for hardware AES acceleration on some Intel processors - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_AESNI_H -#define MBEDTLS_AESNI_H - -#include "aes.h" - -#define MBEDTLS_AESNI_AES 0x02000000u -#define MBEDTLS_AESNI_CLMUL 0x00000002u - -#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \ - ( defined(__amd64__) || defined(__x86_64__) ) && \ - ! defined(MBEDTLS_HAVE_X86_64) -#define MBEDTLS_HAVE_X86_64 -#endif - -#if defined(MBEDTLS_HAVE_X86_64) - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief AES-NI features detection routine - * - * \param what The feature to detect - * (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL) - * - * \return 1 if CPU has support for the feature, 0 otherwise - */ -int mbedtls_aesni_has_support( unsigned int what ); - -/** - * \brief AES-NI AES-ECB block en(de)cryption - * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param input 16-byte input block - * \param output 16-byte output block - * - * \return 0 on success (cannot fail) - */ -int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); - -/** - * \brief GCM multiplication: c = a * b in GF(2^128) - * - * \param c Result - * \param a First operand - * \param b Second operand - * - * \note Both operands and result are bit strings interpreted as - * elements of GF(2^128) as per the GCM spec. - */ -void mbedtls_aesni_gcm_mult( unsigned char c[16], - const unsigned char a[16], - const unsigned char b[16] ); - -/** - * \brief Compute decryption round keys from encryption round keys - * - * \param invkey Round keys for the equivalent inverse cipher - * \param fwdkey Original round keys (for encryption) - * \param nr Number of rounds (that is, number of round keys minus one) - */ -void mbedtls_aesni_inverse_key( unsigned char *invkey, - const unsigned char *fwdkey, int nr ); - -/** - * \brief Perform key expansion (for encryption) - * - * \param rk Destination buffer where the round keys are written - * \param key Encryption key - * \param bits Key size in bits (must be 128, 192 or 256) - * - * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH - */ -int mbedtls_aesni_setkey_enc( unsigned char *rk, - const unsigned char *key, - size_t bits ); - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_HAVE_X86_64 */ - -#endif /* MBEDTLS_AESNI_H */ diff --git a/components/mbedtls/include/mbedtls/arc4.h b/components/mbedtls/include/mbedtls/arc4.h deleted file mode 100644 index 5fc5395a8c..0000000000 --- a/components/mbedtls/include/mbedtls/arc4.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * \file arc4.h - * - * \brief The ARCFOUR stream cipher - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_ARC4_H -#define MBEDTLS_ARC4_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -#if !defined(MBEDTLS_ARC4_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief ARC4 context structure - */ -typedef struct -{ - int x; /*!< permutation index */ - int y; /*!< permutation index */ - unsigned char m[256]; /*!< permutation table */ -} -mbedtls_arc4_context; - -/** - * \brief Initialize ARC4 context - * - * \param ctx ARC4 context to be initialized - */ -void mbedtls_arc4_init( mbedtls_arc4_context *ctx ); - -/** - * \brief Clear ARC4 context - * - * \param ctx ARC4 context to be cleared - */ -void mbedtls_arc4_free( mbedtls_arc4_context *ctx ); - -/** - * \brief ARC4 key schedule - * - * \param ctx ARC4 context to be setup - * \param key the secret key - * \param keylen length of the key, in bytes - */ -void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, - unsigned int keylen ); - -/** - * \brief ARC4 cipher function - * - * \param ctx ARC4 context - * \param length length of the input data - * \param input buffer holding the input data - * \param output buffer for the output data - * - * \return 0 if successful - */ -int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, - unsigned char *output ); - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_ARC4_ALT */ -#include "arc4_alt.h" -#endif /* MBEDTLS_ARC4_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_arc4_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* arc4.h */ diff --git a/components/mbedtls/include/mbedtls/asn1.h b/components/mbedtls/include/mbedtls/asn1.h deleted file mode 100644 index 082832c87f..0000000000 --- a/components/mbedtls/include/mbedtls/asn1.h +++ /dev/null @@ -1,342 +0,0 @@ -/** - * \file asn1.h - * - * \brief Generic ASN.1 parsing - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_ASN1_H -#define MBEDTLS_ASN1_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -#if defined(MBEDTLS_BIGNUM_C) -#include "bignum.h" -#endif - -/** - * \addtogroup asn1_module - * \{ - */ - -/** - * \name ASN1 Error codes - * These error codes are OR'ed to X509 error codes for - * higher error granularity. - * ASN1 is a standard to specify data structures. - * \{ - */ -#define MBEDTLS_ERR_ASN1_OUT_OF_DATA -0x0060 /**< Out of data when parsing an ASN1 data structure. */ -#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */ -#define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */ -#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */ -#define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. (not used) */ -#define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A /**< Memory allocation failed */ -#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */ - -/* \} name */ - -/** - * \name DER constants - * These constants comply with DER encoded the ANS1 type tags. - * DER encoding uses hexadecimal representation. - * An example DER sequence is:\n - * - 0x02 -- tag indicating INTEGER - * - 0x01 -- length in octets - * - 0x05 -- value - * Such sequences are typically read into \c ::mbedtls_x509_buf. - * \{ - */ -#define MBEDTLS_ASN1_BOOLEAN 0x01 -#define MBEDTLS_ASN1_INTEGER 0x02 -#define MBEDTLS_ASN1_BIT_STRING 0x03 -#define MBEDTLS_ASN1_OCTET_STRING 0x04 -#define MBEDTLS_ASN1_NULL 0x05 -#define MBEDTLS_ASN1_OID 0x06 -#define MBEDTLS_ASN1_UTF8_STRING 0x0C -#define MBEDTLS_ASN1_SEQUENCE 0x10 -#define MBEDTLS_ASN1_SET 0x11 -#define MBEDTLS_ASN1_PRINTABLE_STRING 0x13 -#define MBEDTLS_ASN1_T61_STRING 0x14 -#define MBEDTLS_ASN1_IA5_STRING 0x16 -#define MBEDTLS_ASN1_UTC_TIME 0x17 -#define MBEDTLS_ASN1_GENERALIZED_TIME 0x18 -#define MBEDTLS_ASN1_UNIVERSAL_STRING 0x1C -#define MBEDTLS_ASN1_BMP_STRING 0x1E -#define MBEDTLS_ASN1_PRIMITIVE 0x00 -#define MBEDTLS_ASN1_CONSTRUCTED 0x20 -#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 -/* \} name */ -/* \} addtogroup asn1_module */ - -/** Returns the size of the binary string, without the trailing \\0 */ -#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1) - -/** - * Compares an mbedtls_asn1_buf structure to a reference OID. - * - * Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a - * 'unsigned char *oid' here! - */ -#define MBEDTLS_OID_CMP(oid_str, oid_buf) \ - ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \ - memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 ) - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \name Functions to parse ASN.1 data structures - * \{ - */ - -/** - * Type-length-value structure that allows for ASN1 using DER. - */ -typedef struct mbedtls_asn1_buf -{ - int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */ - size_t len; /**< ASN1 length, in octets. */ - unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ -} -mbedtls_asn1_buf; - -/** - * Container for ASN1 bit strings. - */ -typedef struct mbedtls_asn1_bitstring -{ - size_t len; /**< ASN1 length, in octets. */ - unsigned char unused_bits; /**< Number of unused bits at the end of the string */ - unsigned char *p; /**< Raw ASN1 data for the bit string */ -} -mbedtls_asn1_bitstring; - -/** - * Container for a sequence of ASN.1 items - */ -typedef struct mbedtls_asn1_sequence -{ - mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ - struct mbedtls_asn1_sequence *next; /**< The next entry in the sequence. */ -} -mbedtls_asn1_sequence; - -/** - * Container for a sequence or list of 'named' ASN.1 data items - */ -typedef struct mbedtls_asn1_named_data -{ - mbedtls_asn1_buf oid; /**< The object identifier. */ - mbedtls_asn1_buf val; /**< The named value. */ - struct mbedtls_asn1_named_data *next; /**< The next entry in the sequence. */ - unsigned char next_merged; /**< Merge next item into the current one? */ -} -mbedtls_asn1_named_data; - -/** - * \brief Get the length of an ASN.1 element. - * Updates the pointer to immediately behind the length. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param len The variable that will receive the value - * - * \return 0 if successful, MBEDTLS_ERR_ASN1_OUT_OF_DATA on reaching - * end of data, MBEDTLS_ERR_ASN1_INVALID_LENGTH if length is - * unparseable. - */ -int mbedtls_asn1_get_len( unsigned char **p, - const unsigned char *end, - size_t *len ); - -/** - * \brief Get the tag and length of the tag. Check for the requested tag. - * Updates the pointer to immediately behind the tag and length. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param len The variable that will receive the length - * \param tag The expected tag - * - * \return 0 if successful, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if tag did - * not match requested tag, or another specific ASN.1 error code. - */ -int mbedtls_asn1_get_tag( unsigned char **p, - const unsigned char *end, - size_t *len, int tag ); - -/** - * \brief Retrieve a boolean ASN.1 tag and its value. - * Updates the pointer to immediately behind the full tag. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param val The variable that will receive the value - * - * \return 0 if successful or a specific ASN.1 error code. - */ -int mbedtls_asn1_get_bool( unsigned char **p, - const unsigned char *end, - int *val ); - -/** - * \brief Retrieve an integer ASN.1 tag and its value. - * Updates the pointer to immediately behind the full tag. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param val The variable that will receive the value - * - * \return 0 if successful or a specific ASN.1 error code. - */ -int mbedtls_asn1_get_int( unsigned char **p, - const unsigned char *end, - int *val ); - -/** - * \brief Retrieve a bitstring ASN.1 tag and its value. - * Updates the pointer to immediately behind the full tag. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param bs The variable that will receive the value - * - * \return 0 if successful or a specific ASN.1 error code. - */ -int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, - mbedtls_asn1_bitstring *bs); - -/** - * \brief Retrieve a bitstring ASN.1 tag without unused bits and its - * value. - * Updates the pointer to the beginning of the bit/octet string. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param len Length of the actual bit/octect string in bytes - * - * \return 0 if successful or a specific ASN.1 error code. - */ -int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, - size_t *len ); - -/** - * \brief Parses and splits an ASN.1 "SEQUENCE OF " - * Updated the pointer to immediately behind the full sequence tag. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param cur First variable in the chain to fill - * \param tag Type of sequence - * - * \return 0 if successful or a specific ASN.1 error code. - */ -int mbedtls_asn1_get_sequence_of( unsigned char **p, - const unsigned char *end, - mbedtls_asn1_sequence *cur, - int tag); - -#if defined(MBEDTLS_BIGNUM_C) -/** - * \brief Retrieve a MPI value from an integer ASN.1 tag. - * Updates the pointer to immediately behind the full tag. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param X The MPI that will receive the value - * - * \return 0 if successful or a specific ASN.1 or MPI error code. - */ -int mbedtls_asn1_get_mpi( unsigned char **p, - const unsigned char *end, - mbedtls_mpi *X ); -#endif /* MBEDTLS_BIGNUM_C */ - -/** - * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. - * Updates the pointer to immediately behind the full - * AlgorithmIdentifier. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param alg The buffer to receive the OID - * \param params The buffer to receive the params (if any) - * - * \return 0 if successful or a specific ASN.1 or MPI error code. - */ -int mbedtls_asn1_get_alg( unsigned char **p, - const unsigned char *end, - mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ); - -/** - * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no - * params. - * Updates the pointer to immediately behind the full - * AlgorithmIdentifier. - * - * \param p The position in the ASN.1 data - * \param end End of data - * \param alg The buffer to receive the OID - * - * \return 0 if successful or a specific ASN.1 or MPI error code. - */ -int mbedtls_asn1_get_alg_null( unsigned char **p, - const unsigned char *end, - mbedtls_asn1_buf *alg ); - -/** - * \brief Find a specific named_data entry in a sequence or list based on - * the OID. - * - * \param list The list to seek through - * \param oid The OID to look for - * \param len Size of the OID - * - * \return NULL if not found, or a pointer to the existing entry. - */ -mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, - const char *oid, size_t len ); - -/** - * \brief Free a mbedtls_asn1_named_data entry - * - * \param entry The named data entry to free - */ -void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry ); - -/** - * \brief Free all entries in a mbedtls_asn1_named_data list - * Head will be set to NULL - * - * \param head Pointer to the head of the list of named data entries to free - */ -void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ); - -#ifdef __cplusplus -} -#endif - -#endif /* asn1.h */ diff --git a/components/mbedtls/include/mbedtls/asn1write.h b/components/mbedtls/include/mbedtls/asn1write.h deleted file mode 100644 index 73ff32b669..0000000000 --- a/components/mbedtls/include/mbedtls/asn1write.h +++ /dev/null @@ -1,239 +0,0 @@ -/** - * \file asn1write.h - * - * \brief ASN.1 buffer writing functionality - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_ASN1_WRITE_H -#define MBEDTLS_ASN1_WRITE_H - -#include "asn1.h" - -#define MBEDTLS_ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else \ - g += ret; } while( 0 ) - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Write a length field in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param len the length to write - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ); - -/** - * \brief Write a ASN.1 tag in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param tag the tag to write - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, - unsigned char tag ); - -/** - * \brief Write raw buffer data - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param buf data buffer to write - * \param size length of the data buffer - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t size ); - -#if defined(MBEDTLS_BIGNUM_C) -/** - * \brief Write a big number (MBEDTLS_ASN1_INTEGER) in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param X the MPI to write - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ); -#endif /* MBEDTLS_BIGNUM_C */ - -/** - * \brief Write a NULL tag (MBEDTLS_ASN1_NULL) with zero data in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ); - -/** - * \brief Write an OID tag (MBEDTLS_ASN1_OID) and data in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param oid the OID to write - * \param oid_len length of the OID - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len ); - -/** - * \brief Write an AlgorithmIdentifier sequence in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param oid the OID of the algorithm - * \param oid_len length of the OID - * \param par_len length of parameters, which must be already written. - * If 0, NULL parameters are added - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len, - size_t par_len ); - -/** - * \brief Write a boolean tag (MBEDTLS_ASN1_BOOLEAN) and value in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param boolean 0 or 1 - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ); - -/** - * \brief Write an int tag (MBEDTLS_ASN1_INTEGER) and value in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param val the integer value - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ); - -/** - * \brief Write a printable string tag (MBEDTLS_ASN1_PRINTABLE_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param text the text to write - * \param text_len length of the text - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, - const char *text, size_t text_len ); - -/** - * \brief Write an IA5 string tag (MBEDTLS_ASN1_IA5_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param text the text to write - * \param text_len length of the text - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, - const char *text, size_t text_len ); - -/** - * \brief Write a bitstring tag (MBEDTLS_ASN1_BIT_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param buf the bitstring - * \param bits the total number of bits in the bitstring - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t bits ); - -/** - * \brief Write an octet string tag (MBEDTLS_ASN1_OCTET_STRING) and - * value in ASN.1 format - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param buf data buffer to write - * \param size length of the data buffer - * - * \return the length written or a negative error code - */ -int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t size ); - -/** - * \brief Create or find a specific named_data entry for writing in a - * sequence or list based on the OID. If not already in there, - * a new entry is added to the head of the list. - * Warning: Destructive behaviour for the val data! - * - * \param list Pointer to the location of the head of the list to seek - * through (will be updated in case of a new entry) - * \param oid The OID to look for - * \param oid_len Size of the OID - * \param val Data to store (can be NULL if you want to fill it by hand) - * \param val_len Minimum length of the data buffer needed - * - * \return NULL if if there was a memory allocation error, or a pointer - * to the new / existing entry. - */ -mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list, - const char *oid, size_t oid_len, - const unsigned char *val, - size_t val_len ); - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_ASN1_WRITE_H */ diff --git a/components/mbedtls/include/mbedtls/base64.h b/components/mbedtls/include/mbedtls/base64.h deleted file mode 100644 index 352c652db9..0000000000 --- a/components/mbedtls/include/mbedtls/base64.h +++ /dev/null @@ -1,88 +0,0 @@ -/** - * \file base64.h - * - * \brief RFC 1521 base64 encoding/decoding - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_BASE64_H -#define MBEDTLS_BASE64_H - -#include - -#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ -#define MBEDTLS_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Encode a buffer into base64 format - * - * \param dst destination buffer - * \param dlen size of the destination buffer - * \param olen number of bytes written - * \param src source buffer - * \param slen amount of data to be encoded - * - * \return 0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL. - * *olen is always updated to reflect the amount - * of data that has (or would have) been written. - * If that length cannot be represented, then no data is - * written to the buffer and *olen is set to the maximum - * length representable as a size_t. - * - * \note Call this function with dlen = 0 to obtain the - * required buffer size in *olen - */ -int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, - const unsigned char *src, size_t slen ); - -/** - * \brief Decode a base64-formatted buffer - * - * \param dst destination buffer (can be NULL for checking size) - * \param dlen size of the destination buffer - * \param olen number of bytes written - * \param src source buffer - * \param slen amount of data to be decoded - * - * \return 0 if successful, MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL, or - * MBEDTLS_ERR_BASE64_INVALID_CHARACTER if the input data is - * not correct. *olen is always updated to reflect the amount - * of data that has (or would have) been written. - * - * \note Call this function with *dst = NULL or dlen = 0 to obtain - * the required buffer size in *olen - */ -int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, - const unsigned char *src, size_t slen ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_base64_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* base64.h */ diff --git a/components/mbedtls/include/mbedtls/bignum.h b/components/mbedtls/include/mbedtls/bignum.h deleted file mode 100644 index 2e021c9ba1..0000000000 --- a/components/mbedtls/include/mbedtls/bignum.h +++ /dev/null @@ -1,766 +0,0 @@ -/** - * \file bignum.h - * - * \brief Multi-precision integer library - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_BIGNUM_H -#define MBEDTLS_BIGNUM_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#if defined(MBEDTLS_FS_IO) -#include -#endif - -#define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ -#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ -#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ -#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ -#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ -#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ -#define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 /**< Memory allocation failed. */ - -#define MBEDTLS_MPI_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 ) - -/* - * Maximum size MPIs are allowed to grow to in number of limbs. - */ -#define MBEDTLS_MPI_MAX_LIMBS 10000 - -#if !defined(MBEDTLS_MPI_WINDOW_SIZE) -/* - * Maximum window size used for modular exponentiation. Default: 6 - * Minimum value: 1. Maximum value: 6. - * - * Result is an array of ( 2 << MBEDTLS_MPI_WINDOW_SIZE ) MPIs used - * for the sliding window calculation. (So 64 by default) - * - * Reduction in size, reduces speed. - */ -#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ -#endif /* !MBEDTLS_MPI_WINDOW_SIZE */ - -#if !defined(MBEDTLS_MPI_MAX_SIZE) -/* - * Maximum size of MPIs allowed in bits and bytes for user-MPIs. - * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) - * - * Note: Calculations can results temporarily in larger MPIs. So the number - * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. - */ -#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ -#endif /* !MBEDTLS_MPI_MAX_SIZE */ - -#define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ - -/* - * When reading from files with mbedtls_mpi_read_file() and writing to files with - * mbedtls_mpi_write_file() the buffer should have space - * for a (short) label, the MPI (in the provided radix), the newline - * characters and the '\0'. - * - * By default we assume at least a 10 char label, a minimum radix of 10 - * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). - * Autosized at compile time for at least a 10 char label, a minimum radix - * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size. - * - * This used to be statically sized to 1250 for a maximum of 4096 bit - * numbers (1234 decimal chars). - * - * Calculate using the formula: - * MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) + - * LabelSize + 6 - */ -#define MBEDTLS_MPI_MAX_BITS_SCALE100 ( 100 * MBEDTLS_MPI_MAX_BITS ) -#define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 -#define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) - -#if !defined(MBEDTLS_BIGNUM_ALT) - -/* - * Define the base integer type, architecture-wise. - * - * 32 or 64-bit integer types can be forced regardless of the underlying - * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 - * respectively and undefining MBEDTLS_HAVE_ASM. - * - * Double-width integers (e.g. 128-bit in 64-bit architectures) can be - * disabled by defining MBEDTLS_NO_UDBL_DIVISION. - */ -#if !defined(MBEDTLS_HAVE_INT32) - #if defined(_MSC_VER) && defined(_M_AMD64) - /* Always choose 64-bit when using MSC */ - #if !defined(MBEDTLS_HAVE_INT64) - #define MBEDTLS_HAVE_INT64 - #endif /* !MBEDTLS_HAVE_INT64 */ - typedef int64_t mbedtls_mpi_sint; - typedef uint64_t mbedtls_mpi_uint; - #elif defined(__GNUC__) && ( \ - defined(__amd64__) || defined(__x86_64__) || \ - defined(__ppc64__) || defined(__powerpc64__) || \ - defined(__ia64__) || defined(__alpha__) || \ - ( defined(__sparc__) && defined(__arch64__) ) || \ - defined(__s390x__) || defined(__mips64) ) - #if !defined(MBEDTLS_HAVE_INT64) - #define MBEDTLS_HAVE_INT64 - #endif /* MBEDTLS_HAVE_INT64 */ - typedef int64_t mbedtls_mpi_sint; - typedef uint64_t mbedtls_mpi_uint; - #if !defined(MBEDTLS_NO_UDBL_DIVISION) - /* mbedtls_t_udbl defined as 128-bit unsigned int */ - typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); - #define MBEDTLS_HAVE_UDBL - #endif /* !MBEDTLS_NO_UDBL_DIVISION */ - #elif defined(__ARMCC_VERSION) && defined(__aarch64__) - /* - * __ARMCC_VERSION is defined for both armcc and armclang and - * __aarch64__ is only defined by armclang when compiling 64-bit code - */ - #if !defined(MBEDTLS_HAVE_INT64) - #define MBEDTLS_HAVE_INT64 - #endif /* !MBEDTLS_HAVE_INT64 */ - typedef int64_t mbedtls_mpi_sint; - typedef uint64_t mbedtls_mpi_uint; - #if !defined(MBEDTLS_NO_UDBL_DIVISION) - /* mbedtls_t_udbl defined as 128-bit unsigned int */ - typedef __uint128_t mbedtls_t_udbl; - #define MBEDTLS_HAVE_UDBL - #endif /* !MBEDTLS_NO_UDBL_DIVISION */ - #elif defined(MBEDTLS_HAVE_INT64) - /* Force 64-bit integers with unknown compiler */ - typedef int64_t mbedtls_mpi_sint; - typedef uint64_t mbedtls_mpi_uint; - #endif -#endif /* !MBEDTLS_HAVE_INT32 */ - -#if !defined(MBEDTLS_HAVE_INT64) - /* Default to 32-bit compilation */ - #if !defined(MBEDTLS_HAVE_INT32) - #define MBEDTLS_HAVE_INT32 - #endif /* !MBEDTLS_HAVE_INT32 */ - typedef int32_t mbedtls_mpi_sint; - typedef uint32_t mbedtls_mpi_uint; - #if !defined(MBEDTLS_NO_UDBL_DIVISION) - typedef uint64_t mbedtls_t_udbl; - #define MBEDTLS_HAVE_UDBL - #endif /* !MBEDTLS_NO_UDBL_DIVISION */ -#endif /* !MBEDTLS_HAVE_INT64 */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief MPI structure - */ -typedef struct -{ - int s; /*!< integer sign */ - size_t n; /*!< total # of limbs */ - mbedtls_mpi_uint *p; /*!< pointer to limbs */ -} -mbedtls_mpi; - -/** - * \brief Initialize one MPI (make internal references valid) - * This just makes it ready to be set or freed, - * but does not define a value for the MPI. - * - * \param X One MPI to initialize. - */ -void mbedtls_mpi_init( mbedtls_mpi *X ); - -/** - * \brief Unallocate one MPI - * - * \param X One MPI to unallocate. - */ -void mbedtls_mpi_free( mbedtls_mpi *X ); - -/** - * \brief Enlarge to the specified number of limbs - * - * \param X MPI to grow - * \param nblimbs The target number of limbs - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); - -/** - * \brief Resize down, keeping at least the specified number of limbs - * - * \param X MPI to shrink - * \param nblimbs The minimum number of limbs to keep - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); - -/** - * \brief Copy the contents of Y into X - * - * \param X Destination MPI - * \param Y Source MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); - -/** - * \brief Swap the contents of X and Y - * - * \param X First MPI value - * \param Y Second MPI value - */ -void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); - -/** - * \brief Safe conditional assignement X = Y if assign is 1 - * - * \param X MPI to conditionally assign to - * \param Y Value to be assigned - * \param assign 1: perform the assignment, 0: keep X's original value - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * - * \note This function is equivalent to - * if( assign ) mbedtls_mpi_copy( X, Y ); - * except that it avoids leaking any information about whether - * the assignment was done or not (the above code may leak - * information through branch prediction and/or memory access - * patterns analysis). - */ -int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); - -/** - * \brief Safe conditional swap X <-> Y if swap is 1 - * - * \param X First mbedtls_mpi value - * \param Y Second mbedtls_mpi value - * \param assign 1: perform the swap, 0: keep X and Y's original values - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * - * \note This function is equivalent to - * if( assign ) mbedtls_mpi_swap( X, Y ); - * except that it avoids leaking any information about whether - * the assignment was done or not (the above code may leak - * information through branch prediction and/or memory access - * patterns analysis). - */ -int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); - -/** - * \brief Set value from integer - * - * \param X MPI to set - * \param z Value to use - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); - -/** - * \brief Get a specific bit from X - * - * \param X MPI to use - * \param pos Zero-based index of the bit in X - * - * \return Either a 0 or a 1 - */ -int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); - -/** - * \brief Set a bit of X to a specific value of 0 or 1 - * - * \note Will grow X if necessary to set a bit to 1 in a not yet - * existing limb. Will not grow if bit should be set to 0 - * - * \param X MPI to use - * \param pos Zero-based index of the bit in X - * \param val The value to set the bit to (0 or 1) - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 - */ -int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); - -/** - * \brief Return the number of zero-bits before the least significant - * '1' bit - * - * Note: Thus also the zero-based index of the least significant '1' bit - * - * \param X MPI to use - */ -size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); - -/** - * \brief Return the number of bits up to and including the most - * significant '1' bit' - * - * Note: Thus also the one-based index of the most significant '1' bit - * - * \param X MPI to use - */ -size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ); - -/** - * \brief Return the total size in bytes - * - * \param X MPI to use - */ -size_t mbedtls_mpi_size( const mbedtls_mpi *X ); - -/** - * \brief Import from an ASCII string - * - * \param X Destination MPI - * \param radix Input numeric base - * \param s Null-terminated string buffer - * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code - */ -int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); - -/** - * \brief Export into an ASCII string - * - * \param X Source MPI - * \param radix Output numeric base - * \param buf Buffer to write the string to - * \param buflen Length of buf - * \param olen Length of the string written, including final NUL byte - * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code. - * *olen is always updated to reflect the amount - * of data that has (or would have) been written. - * - * \note Call this function with buflen = 0 to obtain the - * minimum required buffer size in *olen. - */ -int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, - char *buf, size_t buflen, size_t *olen ); - -#if defined(MBEDTLS_FS_IO) -/** - * \brief Read MPI from a line in an opened file - * - * \param X Destination MPI - * \param radix Input numeric base - * \param fin Input file handle - * - * \return 0 if successful, MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if - * the file read buffer is too small or a - * MBEDTLS_ERR_MPI_XXX error code - * - * \note On success, this function advances the file stream - * to the end of the current line or to EOF. - * - * The function returns 0 on an empty line. - * - * Leading whitespaces are ignored, as is a - * '0x' prefix for radix 16. - * - */ -int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); - -/** - * \brief Write X into an opened file, or stdout if fout is NULL - * - * \param p Prefix, can be NULL - * \param X Source MPI - * \param radix Output numeric base - * \param fout Output file handle (can be NULL) - * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code - * - * \note Set fout == NULL to print X on the console. - */ -int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ); -#endif /* MBEDTLS_FS_IO */ - -/** - * \brief Import X from unsigned binary data, big endian - * - * \param X Destination MPI - * \param buf Input buffer - * \param buflen Input buffer size - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ); - -/** - * \brief Export X into unsigned binary data, big endian. - * Always fills the whole buffer, which will start with zeros - * if the number is smaller. - * - * \param X Source MPI - * \param buf Output buffer - * \param buflen Output buffer size - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough - */ -int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ); - -/** - * \brief Left-shift: X <<= count - * - * \param X MPI to shift - * \param count Amount to shift - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); - -/** - * \brief Right-shift: X >>= count - * - * \param X MPI to shift - * \param count Amount to shift - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); - -/** - * \brief Compare unsigned values - * - * \param X Left-hand MPI - * \param Y Right-hand MPI - * - * \return 1 if |X| is greater than |Y|, - * -1 if |X| is lesser than |Y| or - * 0 if |X| is equal to |Y| - */ -int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); - -/** - * \brief Compare signed values - * - * \param X Left-hand MPI - * \param Y Right-hand MPI - * - * \return 1 if X is greater than Y, - * -1 if X is lesser than Y or - * 0 if X is equal to Y - */ -int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); - -/** - * \brief Compare signed values - * - * \param X Left-hand MPI - * \param z The integer value to compare to - * - * \return 1 if X is greater than z, - * -1 if X is lesser than z or - * 0 if X is equal to z - */ -int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); - -/** - * \brief Unsigned addition: X = |A| + |B| - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Unsigned subtraction: X = |A| - |B| - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B is greater than A - */ -int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Signed addition: X = A + B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Signed subtraction: X = A - B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Signed addition: X = A + b - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to add - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); - -/** - * \brief Signed subtraction: X = A - b - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to subtract - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); - -/** - * \brief Baseline multiplication: X = A * B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Baseline multiplication: X = A * b - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The unsigned integer value to multiply with - * - * \note b is unsigned - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ); - -/** - * \brief Division by mbedtls_mpi: A = Q * B + R - * - * \param Q Destination MPI for the quotient - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0 - * - * \note Either Q or R can be NULL. - */ -int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Division by int: A = Q * b + R - * - * \param Q Destination MPI for the quotient - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param b Integer to divide by - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0 - * - * \note Either Q or R can be NULL. - */ -int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ); - -/** - * \brief Modulo: R = A mod B - * - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0, - * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B < 0 - */ -int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Modulo: r = A mod b - * - * \param r Destination mbedtls_mpi_uint - * \param A Left-hand MPI - * \param b Integer to divide by - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0, - * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if b < 0 - */ -int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ); - -/** - * \brief Sliding-window exponentiation: X = A^E mod N - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param E Exponent MPI - * \param N Modular MPI - * \param _RR Speed-up MPI used for recalculations - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or even or - * if E is negative - * - * \note _RR is used to avoid re-computing R*R mod N across - * multiple calls, which speeds up things a bit. It can - * be set to NULL if the extra performance is unneeded. - */ -int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ); - -/** - * \brief Fill an MPI X with size bytes of random - * - * \param X Destination MPI - * \param size Size in bytes - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Greatest common divisor: G = gcd(A, B) - * - * \param G Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ); - -/** - * \brief Modular inverse: X = A^-1 mod N - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param N Right-hand MPI - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is <= 1, - MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N. - */ -int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ); - -/** - * \brief Miller-Rabin primality test - * - * \param X MPI to check - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful (probably prime), - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime - */ -int mbedtls_mpi_is_prime( const mbedtls_mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Prime number generation - * - * \param X Destination MPI - * \param nbits Required size of X in bits - * ( 3 <= nbits <= MBEDTLS_MPI_MAX_BITS ) - * \param dh_flag If 1, then (X-1)/2 will be prime too - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful (probably prime), - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 - */ -int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); -#else /* MBEDTLS_BIGNUM_ALT */ -#include "bignum_alt.h" -#endif /* MBEDTLS_BIGNUM_ALT */ - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_mpi_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* bignum.h */ diff --git a/components/mbedtls/include/mbedtls/blowfish.h b/components/mbedtls/include/mbedtls/blowfish.h deleted file mode 100644 index 34626eef48..0000000000 --- a/components/mbedtls/include/mbedtls/blowfish.h +++ /dev/null @@ -1,203 +0,0 @@ -/** - * \file blowfish.h - * - * \brief Blowfish block cipher - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_BLOWFISH_H -#define MBEDTLS_BLOWFISH_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#define MBEDTLS_BLOWFISH_ENCRYPT 1 -#define MBEDTLS_BLOWFISH_DECRYPT 0 -#define MBEDTLS_BLOWFISH_MAX_KEY_BITS 448 -#define MBEDTLS_BLOWFISH_MIN_KEY_BITS 32 -#define MBEDTLS_BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */ -#define MBEDTLS_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */ - -#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH -0x0016 /**< Invalid key length. */ -#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */ - -#if !defined(MBEDTLS_BLOWFISH_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Blowfish context structure - */ -typedef struct -{ - uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */ - uint32_t S[4][256]; /*!< key dependent S-boxes */ -} -mbedtls_blowfish_context; - -/** - * \brief Initialize Blowfish context - * - * \param ctx Blowfish context to be initialized - */ -void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ); - -/** - * \brief Clear Blowfish context - * - * \param ctx Blowfish context to be cleared - */ -void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ); - -/** - * \brief Blowfish key schedule - * - * \param ctx Blowfish context to be initialized - * \param key encryption key - * \param keybits must be between 32 and 448 bits - * - * \return 0 if successful, or MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH - */ -int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, - unsigned int keybits ); - -/** - * \brief Blowfish-ECB block encryption/decryption - * - * \param ctx Blowfish context - * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT - * \param input 8-byte input block - * \param output 8-byte output block - * - * \return 0 if successful - */ -int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, - int mode, - const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], - unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/** - * \brief Blowfish-CBC buffer encryption/decryption - * Length should be a multiple of the block - * size (8 bytes) - * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. - * - * \param ctx Blowfish context - * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful, or - * MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH - */ -int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, - int mode, - size_t length, - unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], - const unsigned char *input, - unsigned char *output ); -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -/** - * \brief Blowfish CFB buffer encryption/decryption. - * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. - * - * \param ctx Blowfish context - * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT - * \param length length of the input data - * \param iv_off offset in IV (updated after use) - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful - */ -int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], - const unsigned char *input, - unsigned char *output ); -#endif /*MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -/** - * \brief Blowfish-CTR buffer encryption/decryption - * - * Warning: You have to keep the maximum use of your counter in mind! - * - * \param ctx Blowfish context - * \param length The length of the data - * \param nc_off The offset in the current stream_block (for resuming - * within current cipher stream). The offset pointer to - * should be 0 at the start of a stream. - * \param nonce_counter The 64-bit nonce and counter. - * \param stream_block The saved stream-block for resuming. Is overwritten - * by the function. - * \param input The input data stream - * \param output The output data stream - * - * \return 0 if successful - */ -int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], - unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], - const unsigned char *input, - unsigned char *output ); -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_BLOWFISH_ALT */ -#include "blowfish_alt.h" -#endif /* MBEDTLS_BLOWFISH_ALT */ - -#endif /* blowfish.h */ diff --git a/components/mbedtls/include/mbedtls/bn_mul.h b/components/mbedtls/include/mbedtls/bn_mul.h deleted file mode 100644 index cac3f14577..0000000000 --- a/components/mbedtls/include/mbedtls/bn_mul.h +++ /dev/null @@ -1,885 +0,0 @@ -/** - * \file bn_mul.h - * - * \brief Multi-precision integer library - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * Multiply source vector [s] with b, add result - * to destination vector [d] and set carry c. - * - * Currently supports: - * - * . IA-32 (386+) . AMD64 / EM64T - * . IA-32 (SSE2) . Motorola 68000 - * . PowerPC, 32-bit . MicroBlaze - * . PowerPC, 64-bit . TriCore - * . SPARC v8 . ARM v3+ - * . Alpha . MIPS32 - * . C, longlong . C, generic - */ -#ifndef MBEDTLS_BN_MUL_H -#define MBEDTLS_BN_MUL_H - -#include "bignum.h" - -#if defined(MBEDTLS_HAVE_ASM) - -#ifndef asm -#define asm __asm -#endif - -/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ -#if defined(__GNUC__) && \ - ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) -#if defined(__i386__) - -#define MULADDC_INIT \ - asm( \ - "movl %%ebx, %0 \n\t" \ - "movl %5, %%esi \n\t" \ - "movl %6, %%edi \n\t" \ - "movl %7, %%ecx \n\t" \ - "movl %8, %%ebx \n\t" - -#define MULADDC_CORE \ - "lodsl \n\t" \ - "mull %%ebx \n\t" \ - "addl %%ecx, %%eax \n\t" \ - "adcl $0, %%edx \n\t" \ - "addl (%%edi), %%eax \n\t" \ - "adcl $0, %%edx \n\t" \ - "movl %%edx, %%ecx \n\t" \ - "stosl \n\t" - -#if defined(MBEDTLS_HAVE_SSE2) - -#define MULADDC_HUIT \ - "movd %%ecx, %%mm1 \n\t" \ - "movd %%ebx, %%mm0 \n\t" \ - "movd (%%edi), %%mm3 \n\t" \ - "paddq %%mm3, %%mm1 \n\t" \ - "movd (%%esi), %%mm2 \n\t" \ - "pmuludq %%mm0, %%mm2 \n\t" \ - "movd 4(%%esi), %%mm4 \n\t" \ - "pmuludq %%mm0, %%mm4 \n\t" \ - "movd 8(%%esi), %%mm6 \n\t" \ - "pmuludq %%mm0, %%mm6 \n\t" \ - "movd 12(%%esi), %%mm7 \n\t" \ - "pmuludq %%mm0, %%mm7 \n\t" \ - "paddq %%mm2, %%mm1 \n\t" \ - "movd 4(%%edi), %%mm3 \n\t" \ - "paddq %%mm4, %%mm3 \n\t" \ - "movd 8(%%edi), %%mm5 \n\t" \ - "paddq %%mm6, %%mm5 \n\t" \ - "movd 12(%%edi), %%mm4 \n\t" \ - "paddq %%mm4, %%mm7 \n\t" \ - "movd %%mm1, (%%edi) \n\t" \ - "movd 16(%%esi), %%mm2 \n\t" \ - "pmuludq %%mm0, %%mm2 \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "movd 20(%%esi), %%mm4 \n\t" \ - "pmuludq %%mm0, %%mm4 \n\t" \ - "paddq %%mm3, %%mm1 \n\t" \ - "movd 24(%%esi), %%mm6 \n\t" \ - "pmuludq %%mm0, %%mm6 \n\t" \ - "movd %%mm1, 4(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "movd 28(%%esi), %%mm3 \n\t" \ - "pmuludq %%mm0, %%mm3 \n\t" \ - "paddq %%mm5, %%mm1 \n\t" \ - "movd 16(%%edi), %%mm5 \n\t" \ - "paddq %%mm5, %%mm2 \n\t" \ - "movd %%mm1, 8(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "paddq %%mm7, %%mm1 \n\t" \ - "movd 20(%%edi), %%mm5 \n\t" \ - "paddq %%mm5, %%mm4 \n\t" \ - "movd %%mm1, 12(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "paddq %%mm2, %%mm1 \n\t" \ - "movd 24(%%edi), %%mm5 \n\t" \ - "paddq %%mm5, %%mm6 \n\t" \ - "movd %%mm1, 16(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "paddq %%mm4, %%mm1 \n\t" \ - "movd 28(%%edi), %%mm5 \n\t" \ - "paddq %%mm5, %%mm3 \n\t" \ - "movd %%mm1, 20(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "paddq %%mm6, %%mm1 \n\t" \ - "movd %%mm1, 24(%%edi) \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "paddq %%mm3, %%mm1 \n\t" \ - "movd %%mm1, 28(%%edi) \n\t" \ - "addl $32, %%edi \n\t" \ - "addl $32, %%esi \n\t" \ - "psrlq $32, %%mm1 \n\t" \ - "movd %%mm1, %%ecx \n\t" - -#define MULADDC_STOP \ - "emms \n\t" \ - "movl %4, %%ebx \n\t" \ - "movl %%ecx, %1 \n\t" \ - "movl %%edi, %2 \n\t" \ - "movl %%esi, %3 \n\t" \ - : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ - : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ - ); - -#else - -#define MULADDC_STOP \ - "movl %4, %%ebx \n\t" \ - "movl %%ecx, %1 \n\t" \ - "movl %%edi, %2 \n\t" \ - "movl %%esi, %3 \n\t" \ - : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ - : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ - ); -#endif /* SSE2 */ -#endif /* i386 */ - -#if defined(__amd64__) || defined (__x86_64__) - -#define MULADDC_INIT \ - asm( \ - "xorq %%r8, %%r8 \n\t" - -#define MULADDC_CORE \ - "movq (%%rsi), %%rax \n\t" \ - "mulq %%rbx \n\t" \ - "addq $8, %%rsi \n\t" \ - "addq %%rcx, %%rax \n\t" \ - "movq %%r8, %%rcx \n\t" \ - "adcq $0, %%rdx \n\t" \ - "nop \n\t" \ - "addq %%rax, (%%rdi) \n\t" \ - "adcq %%rdx, %%rcx \n\t" \ - "addq $8, %%rdi \n\t" - -#define MULADDC_STOP \ - : "+c" (c), "+D" (d), "+S" (s) \ - : "b" (b) \ - : "rax", "rdx", "r8" \ - ); - -#endif /* AMD64 */ - -#if defined(__mc68020__) || defined(__mcpu32__) - -#define MULADDC_INIT \ - asm( \ - "movl %3, %%a2 \n\t" \ - "movl %4, %%a3 \n\t" \ - "movl %5, %%d3 \n\t" \ - "movl %6, %%d2 \n\t" \ - "moveq #0, %%d0 \n\t" - -#define MULADDC_CORE \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d4:%%d1 \n\t" \ - "addl %%d3, %%d1 \n\t" \ - "addxl %%d0, %%d4 \n\t" \ - "moveq #0, %%d3 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "addxl %%d4, %%d3 \n\t" - -#define MULADDC_STOP \ - "movl %%d3, %0 \n\t" \ - "movl %%a3, %1 \n\t" \ - "movl %%a2, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ - ); - -#define MULADDC_HUIT \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d4:%%d1 \n\t" \ - "addxl %%d3, %%d1 \n\t" \ - "addxl %%d0, %%d4 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d3:%%d1 \n\t" \ - "addxl %%d4, %%d1 \n\t" \ - "addxl %%d0, %%d3 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d4:%%d1 \n\t" \ - "addxl %%d3, %%d1 \n\t" \ - "addxl %%d0, %%d4 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d3:%%d1 \n\t" \ - "addxl %%d4, %%d1 \n\t" \ - "addxl %%d0, %%d3 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d4:%%d1 \n\t" \ - "addxl %%d3, %%d1 \n\t" \ - "addxl %%d0, %%d4 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d3:%%d1 \n\t" \ - "addxl %%d4, %%d1 \n\t" \ - "addxl %%d0, %%d3 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d4:%%d1 \n\t" \ - "addxl %%d3, %%d1 \n\t" \ - "addxl %%d0, %%d4 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "movel %%a2@+, %%d1 \n\t" \ - "mulul %%d2, %%d3:%%d1 \n\t" \ - "addxl %%d4, %%d1 \n\t" \ - "addxl %%d0, %%d3 \n\t" \ - "addl %%d1, %%a3@+ \n\t" \ - "addxl %%d0, %%d3 \n\t" - -#endif /* MC68000 */ - -#if defined(__powerpc64__) || defined(__ppc64__) - -#if defined(__MACH__) && defined(__APPLE__) - -#define MULADDC_INIT \ - asm( \ - "ld r3, %3 \n\t" \ - "ld r4, %4 \n\t" \ - "ld r5, %5 \n\t" \ - "ld r6, %6 \n\t" \ - "addi r3, r3, -8 \n\t" \ - "addi r4, r4, -8 \n\t" \ - "addic r5, r5, 0 \n\t" - -#define MULADDC_CORE \ - "ldu r7, 8(r3) \n\t" \ - "mulld r8, r7, r6 \n\t" \ - "mulhdu r9, r7, r6 \n\t" \ - "adde r8, r8, r5 \n\t" \ - "ld r7, 8(r4) \n\t" \ - "addze r5, r9 \n\t" \ - "addc r8, r8, r7 \n\t" \ - "stdu r8, 8(r4) \n\t" - -#define MULADDC_STOP \ - "addze r5, r5 \n\t" \ - "addi r4, r4, 8 \n\t" \ - "addi r3, r3, 8 \n\t" \ - "std r5, %0 \n\t" \ - "std r4, %1 \n\t" \ - "std r3, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ - ); - - -#else /* __MACH__ && __APPLE__ */ - -#define MULADDC_INIT \ - asm( \ - "ld %%r3, %3 \n\t" \ - "ld %%r4, %4 \n\t" \ - "ld %%r5, %5 \n\t" \ - "ld %%r6, %6 \n\t" \ - "addi %%r3, %%r3, -8 \n\t" \ - "addi %%r4, %%r4, -8 \n\t" \ - "addic %%r5, %%r5, 0 \n\t" - -#define MULADDC_CORE \ - "ldu %%r7, 8(%%r3) \n\t" \ - "mulld %%r8, %%r7, %%r6 \n\t" \ - "mulhdu %%r9, %%r7, %%r6 \n\t" \ - "adde %%r8, %%r8, %%r5 \n\t" \ - "ld %%r7, 8(%%r4) \n\t" \ - "addze %%r5, %%r9 \n\t" \ - "addc %%r8, %%r8, %%r7 \n\t" \ - "stdu %%r8, 8(%%r4) \n\t" - -#define MULADDC_STOP \ - "addze %%r5, %%r5 \n\t" \ - "addi %%r4, %%r4, 8 \n\t" \ - "addi %%r3, %%r3, 8 \n\t" \ - "std %%r5, %0 \n\t" \ - "std %%r4, %1 \n\t" \ - "std %%r3, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ - ); - -#endif /* __MACH__ && __APPLE__ */ - -#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ - -#if defined(__MACH__) && defined(__APPLE__) - -#define MULADDC_INIT \ - asm( \ - "lwz r3, %3 \n\t" \ - "lwz r4, %4 \n\t" \ - "lwz r5, %5 \n\t" \ - "lwz r6, %6 \n\t" \ - "addi r3, r3, -4 \n\t" \ - "addi r4, r4, -4 \n\t" \ - "addic r5, r5, 0 \n\t" - -#define MULADDC_CORE \ - "lwzu r7, 4(r3) \n\t" \ - "mullw r8, r7, r6 \n\t" \ - "mulhwu r9, r7, r6 \n\t" \ - "adde r8, r8, r5 \n\t" \ - "lwz r7, 4(r4) \n\t" \ - "addze r5, r9 \n\t" \ - "addc r8, r8, r7 \n\t" \ - "stwu r8, 4(r4) \n\t" - -#define MULADDC_STOP \ - "addze r5, r5 \n\t" \ - "addi r4, r4, 4 \n\t" \ - "addi r3, r3, 4 \n\t" \ - "stw r5, %0 \n\t" \ - "stw r4, %1 \n\t" \ - "stw r3, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ - ); - -#else /* __MACH__ && __APPLE__ */ - -#define MULADDC_INIT \ - asm( \ - "lwz %%r3, %3 \n\t" \ - "lwz %%r4, %4 \n\t" \ - "lwz %%r5, %5 \n\t" \ - "lwz %%r6, %6 \n\t" \ - "addi %%r3, %%r3, -4 \n\t" \ - "addi %%r4, %%r4, -4 \n\t" \ - "addic %%r5, %%r5, 0 \n\t" - -#define MULADDC_CORE \ - "lwzu %%r7, 4(%%r3) \n\t" \ - "mullw %%r8, %%r7, %%r6 \n\t" \ - "mulhwu %%r9, %%r7, %%r6 \n\t" \ - "adde %%r8, %%r8, %%r5 \n\t" \ - "lwz %%r7, 4(%%r4) \n\t" \ - "addze %%r5, %%r9 \n\t" \ - "addc %%r8, %%r8, %%r7 \n\t" \ - "stwu %%r8, 4(%%r4) \n\t" - -#define MULADDC_STOP \ - "addze %%r5, %%r5 \n\t" \ - "addi %%r4, %%r4, 4 \n\t" \ - "addi %%r3, %%r3, 4 \n\t" \ - "stw %%r5, %0 \n\t" \ - "stw %%r4, %1 \n\t" \ - "stw %%r3, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ - ); - -#endif /* __MACH__ && __APPLE__ */ - -#endif /* PPC32 */ - -/* - * The Sparc(64) assembly is reported to be broken. - * Disable it for now, until we're able to fix it. - */ -#if 0 && defined(__sparc__) -#if defined(__sparc64__) - -#define MULADDC_INIT \ - asm( \ - "ldx %3, %%o0 \n\t" \ - "ldx %4, %%o1 \n\t" \ - "ld %5, %%o2 \n\t" \ - "ld %6, %%o3 \n\t" - -#define MULADDC_CORE \ - "ld [%%o0], %%o4 \n\t" \ - "inc 4, %%o0 \n\t" \ - "ld [%%o1], %%o5 \n\t" \ - "umul %%o3, %%o4, %%o4 \n\t" \ - "addcc %%o4, %%o2, %%o4 \n\t" \ - "rd %%y, %%g1 \n\t" \ - "addx %%g1, 0, %%g1 \n\t" \ - "addcc %%o4, %%o5, %%o4 \n\t" \ - "st %%o4, [%%o1] \n\t" \ - "addx %%g1, 0, %%o2 \n\t" \ - "inc 4, %%o1 \n\t" - - #define MULADDC_STOP \ - "st %%o2, %0 \n\t" \ - "stx %%o1, %1 \n\t" \ - "stx %%o0, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "g1", "o0", "o1", "o2", "o3", "o4", \ - "o5" \ - ); - -#else /* __sparc64__ */ - -#define MULADDC_INIT \ - asm( \ - "ld %3, %%o0 \n\t" \ - "ld %4, %%o1 \n\t" \ - "ld %5, %%o2 \n\t" \ - "ld %6, %%o3 \n\t" - -#define MULADDC_CORE \ - "ld [%%o0], %%o4 \n\t" \ - "inc 4, %%o0 \n\t" \ - "ld [%%o1], %%o5 \n\t" \ - "umul %%o3, %%o4, %%o4 \n\t" \ - "addcc %%o4, %%o2, %%o4 \n\t" \ - "rd %%y, %%g1 \n\t" \ - "addx %%g1, 0, %%g1 \n\t" \ - "addcc %%o4, %%o5, %%o4 \n\t" \ - "st %%o4, [%%o1] \n\t" \ - "addx %%g1, 0, %%o2 \n\t" \ - "inc 4, %%o1 \n\t" - -#define MULADDC_STOP \ - "st %%o2, %0 \n\t" \ - "st %%o1, %1 \n\t" \ - "st %%o0, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "g1", "o0", "o1", "o2", "o3", "o4", \ - "o5" \ - ); - -#endif /* __sparc64__ */ -#endif /* __sparc__ */ - -#if defined(__microblaze__) || defined(microblaze) - -#define MULADDC_INIT \ - asm( \ - "lwi r3, %3 \n\t" \ - "lwi r4, %4 \n\t" \ - "lwi r5, %5 \n\t" \ - "lwi r6, %6 \n\t" \ - "andi r7, r6, 0xffff \n\t" \ - "bsrli r6, r6, 16 \n\t" - -#define MULADDC_CORE \ - "lhui r8, r3, 0 \n\t" \ - "addi r3, r3, 2 \n\t" \ - "lhui r9, r3, 0 \n\t" \ - "addi r3, r3, 2 \n\t" \ - "mul r10, r9, r6 \n\t" \ - "mul r11, r8, r7 \n\t" \ - "mul r12, r9, r7 \n\t" \ - "mul r13, r8, r6 \n\t" \ - "bsrli r8, r10, 16 \n\t" \ - "bsrli r9, r11, 16 \n\t" \ - "add r13, r13, r8 \n\t" \ - "add r13, r13, r9 \n\t" \ - "bslli r10, r10, 16 \n\t" \ - "bslli r11, r11, 16 \n\t" \ - "add r12, r12, r10 \n\t" \ - "addc r13, r13, r0 \n\t" \ - "add r12, r12, r11 \n\t" \ - "addc r13, r13, r0 \n\t" \ - "lwi r10, r4, 0 \n\t" \ - "add r12, r12, r10 \n\t" \ - "addc r13, r13, r0 \n\t" \ - "add r12, r12, r5 \n\t" \ - "addc r5, r13, r0 \n\t" \ - "swi r12, r4, 0 \n\t" \ - "addi r4, r4, 4 \n\t" - -#define MULADDC_STOP \ - "swi r5, %0 \n\t" \ - "swi r4, %1 \n\t" \ - "swi r3, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r3", "r4" "r5", "r6", "r7", "r8", \ - "r9", "r10", "r11", "r12", "r13" \ - ); - -#endif /* MicroBlaze */ - -#if defined(__tricore__) - -#define MULADDC_INIT \ - asm( \ - "ld.a %%a2, %3 \n\t" \ - "ld.a %%a3, %4 \n\t" \ - "ld.w %%d4, %5 \n\t" \ - "ld.w %%d1, %6 \n\t" \ - "xor %%d5, %%d5 \n\t" - -#define MULADDC_CORE \ - "ld.w %%d0, [%%a2+] \n\t" \ - "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ - "ld.w %%d0, [%%a3] \n\t" \ - "addx %%d2, %%d2, %%d0 \n\t" \ - "addc %%d3, %%d3, 0 \n\t" \ - "mov %%d4, %%d3 \n\t" \ - "st.w [%%a3+], %%d2 \n\t" - -#define MULADDC_STOP \ - "st.w %0, %%d4 \n\t" \ - "st.a %1, %%a3 \n\t" \ - "st.a %2, %%a2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "d0", "d1", "e2", "d4", "a2", "a3" \ - ); - -#endif /* TriCore */ - -/* - * gcc -O0 by default uses r7 for the frame pointer, so it complains about our - * use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately, - * passing that option is not easy when building with yotta. - * - * On the other hand, -fomit-frame-pointer is implied by any -Ox options with - * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by - * clang and armcc5 under the same conditions). - * - * So, only use the optimized assembly below for optimized build, which avoids - * the build error and is pretty reasonable anyway. - */ -#if defined(__GNUC__) && !defined(__OPTIMIZE__) -#define MULADDC_CANNOT_USE_R7 -#endif - -#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7) - -#if defined(__thumb__) && !defined(__thumb2__) - -#define MULADDC_INIT \ - asm( \ - "ldr r0, %3 \n\t" \ - "ldr r1, %4 \n\t" \ - "ldr r2, %5 \n\t" \ - "ldr r3, %6 \n\t" \ - "lsr r7, r3, #16 \n\t" \ - "mov r9, r7 \n\t" \ - "lsl r7, r3, #16 \n\t" \ - "lsr r7, r7, #16 \n\t" \ - "mov r8, r7 \n\t" - -#define MULADDC_CORE \ - "ldmia r0!, {r6} \n\t" \ - "lsr r7, r6, #16 \n\t" \ - "lsl r6, r6, #16 \n\t" \ - "lsr r6, r6, #16 \n\t" \ - "mov r4, r8 \n\t" \ - "mul r4, r6 \n\t" \ - "mov r3, r9 \n\t" \ - "mul r6, r3 \n\t" \ - "mov r5, r9 \n\t" \ - "mul r5, r7 \n\t" \ - "mov r3, r8 \n\t" \ - "mul r7, r3 \n\t" \ - "lsr r3, r6, #16 \n\t" \ - "add r5, r5, r3 \n\t" \ - "lsr r3, r7, #16 \n\t" \ - "add r5, r5, r3 \n\t" \ - "add r4, r4, r2 \n\t" \ - "mov r2, #0 \n\t" \ - "adc r5, r2 \n\t" \ - "lsl r3, r6, #16 \n\t" \ - "add r4, r4, r3 \n\t" \ - "adc r5, r2 \n\t" \ - "lsl r3, r7, #16 \n\t" \ - "add r4, r4, r3 \n\t" \ - "adc r5, r2 \n\t" \ - "ldr r3, [r1] \n\t" \ - "add r4, r4, r3 \n\t" \ - "adc r2, r5 \n\t" \ - "stmia r1!, {r4} \n\t" - -#define MULADDC_STOP \ - "str r2, %0 \n\t" \ - "str r1, %1 \n\t" \ - "str r0, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r0", "r1", "r2", "r3", "r4", "r5", \ - "r6", "r7", "r8", "r9", "cc" \ - ); - -#else - -#define MULADDC_INIT \ - asm( \ - "ldr r0, %3 \n\t" \ - "ldr r1, %4 \n\t" \ - "ldr r2, %5 \n\t" \ - "ldr r3, %6 \n\t" - -#define MULADDC_CORE \ - "ldr r4, [r0], #4 \n\t" \ - "mov r5, #0 \n\t" \ - "ldr r6, [r1] \n\t" \ - "umlal r2, r5, r3, r4 \n\t" \ - "adds r7, r6, r2 \n\t" \ - "adc r2, r5, #0 \n\t" \ - "str r7, [r1], #4 \n\t" - -#define MULADDC_STOP \ - "str r2, %0 \n\t" \ - "str r1, %1 \n\t" \ - "str r0, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r0", "r1", "r2", "r3", "r4", "r5", \ - "r6", "r7", "cc" \ - ); - -#endif /* Thumb */ - -#endif /* ARMv3 */ - -#if defined(__alpha__) - -#define MULADDC_INIT \ - asm( \ - "ldq $1, %3 \n\t" \ - "ldq $2, %4 \n\t" \ - "ldq $3, %5 \n\t" \ - "ldq $4, %6 \n\t" - -#define MULADDC_CORE \ - "ldq $6, 0($1) \n\t" \ - "addq $1, 8, $1 \n\t" \ - "mulq $6, $4, $7 \n\t" \ - "umulh $6, $4, $6 \n\t" \ - "addq $7, $3, $7 \n\t" \ - "cmpult $7, $3, $3 \n\t" \ - "ldq $5, 0($2) \n\t" \ - "addq $7, $5, $7 \n\t" \ - "cmpult $7, $5, $5 \n\t" \ - "stq $7, 0($2) \n\t" \ - "addq $2, 8, $2 \n\t" \ - "addq $6, $3, $3 \n\t" \ - "addq $5, $3, $3 \n\t" - -#define MULADDC_STOP \ - "stq $3, %0 \n\t" \ - "stq $2, %1 \n\t" \ - "stq $1, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ - ); -#endif /* Alpha */ - -#if defined(__mips__) && !defined(__mips64) - -#define MULADDC_INIT \ - asm( \ - "lw $10, %3 \n\t" \ - "lw $11, %4 \n\t" \ - "lw $12, %5 \n\t" \ - "lw $13, %6 \n\t" - -#define MULADDC_CORE \ - "lw $14, 0($10) \n\t" \ - "multu $13, $14 \n\t" \ - "addi $10, $10, 4 \n\t" \ - "mflo $14 \n\t" \ - "mfhi $9 \n\t" \ - "addu $14, $12, $14 \n\t" \ - "lw $15, 0($11) \n\t" \ - "sltu $12, $14, $12 \n\t" \ - "addu $15, $14, $15 \n\t" \ - "sltu $14, $15, $14 \n\t" \ - "addu $12, $12, $9 \n\t" \ - "sw $15, 0($11) \n\t" \ - "addu $12, $12, $14 \n\t" \ - "addi $11, $11, 4 \n\t" - -#define MULADDC_STOP \ - "sw $12, %0 \n\t" \ - "sw $11, %1 \n\t" \ - "sw $10, %2 \n\t" \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "$9", "$10", "$11", "$12", "$13", "$14", "$15" \ - ); - -#endif /* MIPS */ -#endif /* GNUC */ - -#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) - -#define MULADDC_INIT \ - __asm mov esi, s \ - __asm mov edi, d \ - __asm mov ecx, c \ - __asm mov ebx, b - -#define MULADDC_CORE \ - __asm lodsd \ - __asm mul ebx \ - __asm add eax, ecx \ - __asm adc edx, 0 \ - __asm add eax, [edi] \ - __asm adc edx, 0 \ - __asm mov ecx, edx \ - __asm stosd - -#if defined(MBEDTLS_HAVE_SSE2) - -#define EMIT __asm _emit - -#define MULADDC_HUIT \ - EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ - EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ - EMIT 0x0F EMIT 0x6E EMIT 0x1F \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x6E EMIT 0x16 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ - EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ - EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ - EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ - EMIT 0x0F EMIT 0x7E EMIT 0x0F \ - EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ - EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ - EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ - EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x7E EMIT 0xC9 - -#define MULADDC_STOP \ - EMIT 0x0F EMIT 0x77 \ - __asm mov c, ecx \ - __asm mov d, edi \ - __asm mov s, esi \ - -#else - -#define MULADDC_STOP \ - __asm mov c, ecx \ - __asm mov d, edi \ - __asm mov s, esi \ - -#endif /* SSE2 */ -#endif /* MSVC */ - -#endif /* MBEDTLS_HAVE_ASM */ - -#if !defined(MULADDC_CORE) -#if defined(MBEDTLS_HAVE_UDBL) - -#define MULADDC_INIT \ -{ \ - mbedtls_t_udbl r; \ - mbedtls_mpi_uint r0, r1; - -#define MULADDC_CORE \ - r = *(s++) * (mbedtls_t_udbl) b; \ - r0 = (mbedtls_mpi_uint) r; \ - r1 = (mbedtls_mpi_uint)( r >> biL ); \ - r0 += c; r1 += (r0 < c); \ - r0 += *d; r1 += (r0 < *d); \ - c = r1; *(d++) = r0; - -#define MULADDC_STOP \ -} - -#else -#define MULADDC_INIT \ -{ \ - mbedtls_mpi_uint s0, s1, b0, b1; \ - mbedtls_mpi_uint r0, r1, rx, ry; \ - b0 = ( b << biH ) >> biH; \ - b1 = ( b >> biH ); - -#define MULADDC_CORE \ - s0 = ( *s << biH ) >> biH; \ - s1 = ( *s >> biH ); s++; \ - rx = s0 * b1; r0 = s0 * b0; \ - ry = s1 * b0; r1 = s1 * b1; \ - r1 += ( rx >> biH ); \ - r1 += ( ry >> biH ); \ - rx <<= biH; ry <<= biH; \ - r0 += rx; r1 += (r0 < rx); \ - r0 += ry; r1 += (r0 < ry); \ - r0 += c; r1 += (r0 < c); \ - r0 += *d; r1 += (r0 < *d); \ - c = r1; *(d++) = r0; - -#define MULADDC_STOP \ -} - -#endif /* C (generic) */ -#endif /* C (longlong) */ - -#endif /* bn_mul.h */ diff --git a/components/mbedtls/include/mbedtls/camellia.h b/components/mbedtls/include/mbedtls/camellia.h deleted file mode 100644 index 0424d623fb..0000000000 --- a/components/mbedtls/include/mbedtls/camellia.h +++ /dev/null @@ -1,235 +0,0 @@ -/** - * \file camellia.h - * - * \brief Camellia block cipher - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_CAMELLIA_H -#define MBEDTLS_CAMELLIA_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#define MBEDTLS_CAMELLIA_ENCRYPT 1 -#define MBEDTLS_CAMELLIA_DECRYPT 0 - -#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */ -#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ - -#if !defined(MBEDTLS_CAMELLIA_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief CAMELLIA context structure - */ -typedef struct -{ - int nr; /*!< number of rounds */ - uint32_t rk[68]; /*!< CAMELLIA round keys */ -} -mbedtls_camellia_context; - -/** - * \brief Initialize CAMELLIA context - * - * \param ctx CAMELLIA context to be initialized - */ -void mbedtls_camellia_init( mbedtls_camellia_context *ctx ); - -/** - * \brief Clear CAMELLIA context - * - * \param ctx CAMELLIA context to be cleared - */ -void mbedtls_camellia_free( mbedtls_camellia_context *ctx ); - -/** - * \brief CAMELLIA key schedule (encryption) - * - * \param ctx CAMELLIA context to be initialized - * \param key encryption key - * \param keybits must be 128, 192 or 256 - * - * \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH - */ -int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned char *key, - unsigned int keybits ); - -/** - * \brief CAMELLIA key schedule (decryption) - * - * \param ctx CAMELLIA context to be initialized - * \param key decryption key - * \param keybits must be 128, 192 or 256 - * - * \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH - */ -int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, const unsigned char *key, - unsigned int keybits ); - -/** - * \brief CAMELLIA-ECB block encryption/decryption - * - * \param ctx CAMELLIA context - * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT - * \param input 16-byte input block - * \param output 16-byte output block - * - * \return 0 if successful - */ -int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/** - * \brief CAMELLIA-CBC buffer encryption/decryption - * Length should be a multiple of the block - * size (16 bytes) - * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. - * - * \param ctx CAMELLIA context - * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful, or - * MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH - */ -int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -/** - * \brief CAMELLIA-CFB128 buffer encryption/decryption - * - * Note: Due to the nature of CFB you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT. - * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. - * - * \param ctx CAMELLIA context - * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT - * \param length length of the input data - * \param iv_off offset in IV (updated after use) - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful, or - * MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH - */ -int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -/** - * \brief CAMELLIA-CTR buffer encryption/decryption - * - * Warning: You have to keep the maximum use of your counter in mind! - * - * Note: Due to the nature of CTR you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and MBEDTLS_CAMELLIA_DECRYPT. - * - * \param ctx CAMELLIA context - * \param length The length of the data - * \param nc_off The offset in the current stream_block (for resuming - * within current cipher stream). The offset pointer to - * should be 0 at the start of a stream. - * \param nonce_counter The 128-bit nonce and counter. - * \param stream_block The saved stream-block for resuming. Is overwritten - * by the function. - * \param input The input data stream - * \param output The output data stream - * - * \return 0 if successful - */ -int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[16], - unsigned char stream_block[16], - const unsigned char *input, - unsigned char *output ); -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_CAMELLIA_ALT */ -#include "camellia_alt.h" -#endif /* MBEDTLS_CAMELLIA_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_camellia_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* camellia.h */ diff --git a/components/mbedtls/include/mbedtls/ccm.h b/components/mbedtls/include/mbedtls/ccm.h deleted file mode 100644 index ef75839baa..0000000000 --- a/components/mbedtls/include/mbedtls/ccm.h +++ /dev/null @@ -1,141 +0,0 @@ -/** - * \file ccm.h - * - * \brief Counter with CBC-MAC (CCM) for 128-bit block ciphers - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_CCM_H -#define MBEDTLS_CCM_H - -#include "cipher.h" - -#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief CCM context structure - */ -typedef struct { - mbedtls_cipher_context_t cipher_ctx; /*!< cipher context used */ -} -mbedtls_ccm_context; - -/** - * \brief Initialize CCM context (just makes references valid) - * Makes the context ready for mbedtls_ccm_setkey() or - * mbedtls_ccm_free(). - * - * \param ctx CCM context to initialize - */ -void mbedtls_ccm_init( mbedtls_ccm_context *ctx ); - -/** - * \brief CCM initialization (encryption and decryption) - * - * \param ctx CCM context to be initialized - * \param cipher cipher to use (a 128-bit block cipher) - * \param key encryption key - * \param keybits key size in bits (must be acceptable by the cipher) - * - * \return 0 if successful, or a cipher specific error code - */ -int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, - mbedtls_cipher_id_t cipher, - const unsigned char *key, - unsigned int keybits ); - -/** - * \brief Free a CCM context and underlying cipher sub-context - * - * \param ctx CCM context to free - */ -void mbedtls_ccm_free( mbedtls_ccm_context *ctx ); - -/** - * \brief CCM buffer encryption - * - * \param ctx CCM context - * \param length length of the input data in bytes - * \param iv nonce (initialization vector) - * \param iv_len length of IV in bytes - * must be 2, 3, 4, 5, 6, 7 or 8 - * \param add additional data - * \param add_len length of additional data in bytes - * must be less than 2^16 - 2^8 - * \param input buffer holding the input data - * \param output buffer for holding the output data - * must be at least 'length' bytes wide - * \param tag buffer for holding the tag - * \param tag_len length of the tag to generate in bytes - * must be 4, 6, 8, 10, 14 or 16 - * - * \note The tag is written to a separate buffer. To get the tag - * concatenated with the output as in the CCM spec, use - * tag = output + length and make sure the output buffer is - * at least length + tag_len wide. - * - * \return 0 if successful - */ -int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, - const unsigned char *iv, size_t iv_len, - const unsigned char *add, size_t add_len, - const unsigned char *input, unsigned char *output, - unsigned char *tag, size_t tag_len ); - -/** - * \brief CCM buffer authenticated decryption - * - * \param ctx CCM context - * \param length length of the input data - * \param iv initialization vector - * \param iv_len length of IV - * \param add additional data - * \param add_len length of additional data - * \param input buffer holding the input data - * \param output buffer for holding the output data - * \param tag buffer holding the tag - * \param tag_len length of the tag - * - * \return 0 if successful and authenticated, - * MBEDTLS_ERR_CCM_AUTH_FAILED if tag does not match - */ -int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, - const unsigned char *iv, size_t iv_len, - const unsigned char *add, size_t add_len, - const unsigned char *input, unsigned char *output, - const unsigned char *tag, size_t tag_len ); - -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_ccm_self_test( int verbose ); -#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_CCM_H */ diff --git a/components/mbedtls/include/mbedtls/certs.h b/components/mbedtls/include/mbedtls/certs.h deleted file mode 100644 index ca49086e4f..0000000000 --- a/components/mbedtls/include/mbedtls/certs.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * \file certs.h - * - * \brief Sample certificates and DHM parameters for testing - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_CERTS_H -#define MBEDTLS_CERTS_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(MBEDTLS_PEM_PARSE_C) -/* Concatenation of all CA certificates in PEM format if available */ -extern const char mbedtls_test_cas_pem[]; -extern const size_t mbedtls_test_cas_pem_len; -#endif - -/* List of all CA certificates, terminated by NULL */ -extern const char * mbedtls_test_cas[]; -extern const size_t mbedtls_test_cas_len[]; - -/* - * Convenience for users who just want a certificate: - * RSA by default, or ECDSA if RSA is not available - */ -extern const char * mbedtls_test_ca_crt; -extern const size_t mbedtls_test_ca_crt_len; -extern const char * mbedtls_test_ca_key; -extern const size_t mbedtls_test_ca_key_len; -extern const char * mbedtls_test_ca_pwd; -extern const size_t mbedtls_test_ca_pwd_len; -extern const char * mbedtls_test_srv_crt; -extern const size_t mbedtls_test_srv_crt_len; -extern const char * mbedtls_test_srv_key; -extern const size_t mbedtls_test_srv_key_len; -extern const char * mbedtls_test_cli_crt; -extern const size_t mbedtls_test_cli_crt_len; -extern const char * mbedtls_test_cli_key; -extern const size_t mbedtls_test_cli_key_len; - -#if defined(MBEDTLS_ECDSA_C) -extern const char mbedtls_test_ca_crt_ec[]; -extern const size_t mbedtls_test_ca_crt_ec_len; -extern const char mbedtls_test_ca_key_ec[]; -extern const size_t mbedtls_test_ca_key_ec_len; -extern const char mbedtls_test_ca_pwd_ec[]; -extern const size_t mbedtls_test_ca_pwd_ec_len; -extern const char mbedtls_test_srv_crt_ec[]; -extern const size_t mbedtls_test_srv_crt_ec_len; -extern const char mbedtls_test_srv_key_ec[]; -extern const size_t mbedtls_test_srv_key_ec_len; -extern const char mbedtls_test_cli_crt_ec[]; -extern const size_t mbedtls_test_cli_crt_ec_len; -extern const char mbedtls_test_cli_key_ec[]; -extern const size_t mbedtls_test_cli_key_ec_len; -#endif - -#if defined(MBEDTLS_RSA_C) -extern const char mbedtls_test_ca_crt_rsa[]; -extern const size_t mbedtls_test_ca_crt_rsa_len; -extern const char mbedtls_test_ca_key_rsa[]; -extern const size_t mbedtls_test_ca_key_rsa_len; -extern const char mbedtls_test_ca_pwd_rsa[]; -extern const size_t mbedtls_test_ca_pwd_rsa_len; -extern const char mbedtls_test_srv_crt_rsa[]; -extern const size_t mbedtls_test_srv_crt_rsa_len; -extern const char mbedtls_test_srv_key_rsa[]; -extern const size_t mbedtls_test_srv_key_rsa_len; -extern const char mbedtls_test_cli_crt_rsa[]; -extern const size_t mbedtls_test_cli_crt_rsa_len; -extern const char mbedtls_test_cli_key_rsa[]; -extern const size_t mbedtls_test_cli_key_rsa_len; -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* certs.h */ diff --git a/components/mbedtls/include/mbedtls/check_config.h b/components/mbedtls/include/mbedtls/check_config.h deleted file mode 100644 index fa72454e53..0000000000 --- a/components/mbedtls/include/mbedtls/check_config.h +++ /dev/null @@ -1,669 +0,0 @@ -/** - * \file check_config.h - * - * \brief Consistency checks for configuration options - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -/* - * It is recommended to include this file from your config.h - * in order to catch dependency issues early. - */ - -#ifndef MBEDTLS_CHECK_CONFIG_H -#define MBEDTLS_CHECK_CONFIG_H - -/* - * We assume CHAR_BIT is 8 in many places. In practice, this is true on our - * target platforms, so not an issue, but let's just be extra sure. - */ -#include -#if CHAR_BIT != 8 -#error "mbed TLS requires a platform with 8-bit chars" -#endif - -#if defined(_WIN32) -#if !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_C is required on Windows" -#endif - -/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as - * it would confuse config.pl. */ -#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ - !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) -#define MBEDTLS_PLATFORM_SNPRINTF_ALT -#endif -#endif /* _WIN32 */ - -#if defined(TARGET_LIKE_MBED) && \ - ( defined(MBEDTLS_NET_C) || defined(MBEDTLS_TIMING_C) ) -#error "The NET and TIMING modules are not available for mbed OS - please use the network and timing functions provided by mbed OS" -#endif - -#if defined(MBEDTLS_DEPRECATED_WARNING) && \ - !defined(__GNUC__) && !defined(__clang__) -#error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang" -#endif - -#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME) -#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" -#endif - -#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM) -#error "MBEDTLS_AESNI_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) -#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C) -#error "MBEDTLS_DHM_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_CMAC_C) && \ - !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) -#error "MBEDTLS_CMAC_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) -#error "MBEDTLS_ECDH_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECDSA_C) && \ - ( !defined(MBEDTLS_ECP_C) || \ - !defined(MBEDTLS_ASN1_PARSE_C) || \ - !defined(MBEDTLS_ASN1_WRITE_C) ) -#error "MBEDTLS_ECDSA_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECJPAKE_C) && \ - ( !defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C) ) -#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) -#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ - !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ - !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) ) ) -#error "MBEDTLS_ECP_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ - !defined(MBEDTLS_SHA256_C)) -#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" -#endif -#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \ - defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) -#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" -#endif -#if defined(MBEDTLS_ENTROPY_C) && \ - ( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \ - && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) -#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" -#endif -#if defined(MBEDTLS_ENTROPY_C) && \ - defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C) -#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ - ( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) ) -#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" -#endif -#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ - ( defined(MBEDTLS_ENTROPY_NV_SEED) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || \ - defined(MBEDTLS_HAVEGE_C) ) -#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too" -#endif - -#if defined(MBEDTLS_GCM_C) && ( \ - !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) ) -#error "MBEDTLS_GCM_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) -#error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C) -#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) -#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ - ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) -#error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ - ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) -#error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C) -#error "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ - !defined(MBEDTLS_ECDH_C) -#error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ - ( !defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) || \ - !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) -#error "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ - ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ - !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) -#error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ - ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ - !defined(MBEDTLS_X509_CRT_PARSE_C) ) -#error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ - ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ - !defined(MBEDTLS_PKCS1_V15) ) -#error "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ - ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ - !defined(MBEDTLS_PKCS1_V15) ) -#error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ - ( !defined(MBEDTLS_ECJPAKE_C) || !defined(MBEDTLS_SHA256_C) || \ - !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ) -#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ - ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) -#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM) -#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C) -#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C) -#error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PK_C) && \ - ( !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C) ) -#error "MBEDTLS_PK_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C) -#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C) -#error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PKCS11_C) && !defined(MBEDTLS_PK_C) -#error "MBEDTLS_PKCS11_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\ - ( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\ - defined(MBEDTLS_PLATFORM_EXIT_ALT) ) -#error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\ - ( !defined(MBEDTLS_PLATFORM_C) ||\ - !defined(MBEDTLS_HAVE_TIME) ) -#error "MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ - ( !defined(MBEDTLS_PLATFORM_C) ||\ - !defined(MBEDTLS_HAVE_TIME) ) -#error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ - ( !defined(MBEDTLS_PLATFORM_C) ||\ - !defined(MBEDTLS_HAVE_TIME) ) -#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ - ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ - defined(MBEDTLS_PLATFORM_TIME_ALT) ) -#error "MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ - ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ - defined(MBEDTLS_PLATFORM_TIME_ALT) ) -#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\ - ( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\ - defined(MBEDTLS_PLATFORM_FPRINTF_ALT) ) -#error "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ - ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) -#error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ - defined(MBEDTLS_PLATFORM_STD_FREE) -#error "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO) -#error "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is" -#endif - -#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ - ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) -#error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ - defined(MBEDTLS_PLATFORM_STD_CALLOC) -#error "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO) -#error "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is" -#endif - -#if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\ - ( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\ - defined(MBEDTLS_PLATFORM_PRINTF_ALT) ) -#error "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) -#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\ - ( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\ - defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) ) -#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\ - !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) -#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) -#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) -#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY) -#error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\ - !defined(MBEDTLS_PLATFORM_EXIT_ALT) -#error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_TIME) &&\ - ( !defined(MBEDTLS_PLATFORM_TIME_ALT) ||\ - !defined(MBEDTLS_HAVE_TIME) ) -#error "MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\ - !defined(MBEDTLS_PLATFORM_FPRINTF_ALT) -#error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\ - !defined(MBEDTLS_PLATFORM_PRINTF_ALT) -#error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\ - !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) -#error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_ENTROPY_NV_SEED) &&\ - ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) ) -#error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\ - !defined(MBEDTLS_ENTROPY_NV_SEED) -#error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\ - !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) -#error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\ - !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) -#error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\ - ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\ - defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) -#error "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\ - ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\ - defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) -#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" -#endif - -#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ - !defined(MBEDTLS_OID_C) ) -#error "MBEDTLS_RSA_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_PKCS1_V21) && \ - !defined(MBEDTLS_PKCS1_V15) ) -#error "MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled" -#endif - -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ - ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21) ) -#error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_PROTO_SSL3) && ( !defined(MBEDTLS_MD5_C) || \ - !defined(MBEDTLS_SHA1_C) ) -#error "MBEDTLS_SSL_PROTO_SSL3 defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1) && ( !defined(MBEDTLS_MD5_C) || \ - !defined(MBEDTLS_SHA1_C) ) -#error "MBEDTLS_SSL_PROTO_TLS1 defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) && ( !defined(MBEDTLS_MD5_C) || \ - !defined(MBEDTLS_SHA1_C) ) -#error "MBEDTLS_SSL_PROTO_TLS1_1 defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && ( !defined(MBEDTLS_SHA1_C) && \ - !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) ) -#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_PROTO_DTLS) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_2) -#error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C) -#error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) || \ - !defined(MBEDTLS_MD_C) ) -#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C) -#error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) && (!defined(MBEDTLS_SSL_PROTO_SSL3) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1) && !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_2)) -#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) && !defined(MBEDTLS_SSL_PROTO_TLS1)) -#error "Illegal protocol selection" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_TLS1) && \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) && !defined(MBEDTLS_SSL_PROTO_TLS1_1)) -#error "Illegal protocol selection" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) && (!defined(MBEDTLS_SSL_PROTO_TLS1) || \ - !defined(MBEDTLS_SSL_PROTO_TLS1_1))) -#error "Illegal protocol selection" -#endif - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS) -#error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \ - !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) -#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \ - ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) -#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \ - ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) -#error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_2) -#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites" -#endif - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ - !defined(MBEDTLS_SSL_PROTO_TLS1_2) -#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites" -#endif - -#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C) -#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) && \ - !defined(MBEDTLS_SSL_PROTO_SSL3) && !defined(MBEDTLS_SSL_PROTO_TLS1) -#error "MBEDTLS_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ - !defined(MBEDTLS_X509_CRT_PARSE_C) -#error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_THREADING_PTHREAD) -#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) -#error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites" -#endif -#define MBEDTLS_THREADING_IMPL -#endif - -#if defined(MBEDTLS_THREADING_ALT) -#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) -#error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" -#endif -#define MBEDTLS_THREADING_IMPL -#endif - -#if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL) -#error "MBEDTLS_THREADING_C defined, single threading implementation required" -#endif -#undef MBEDTLS_THREADING_IMPL - -#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) -#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_USE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ - !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \ - !defined(MBEDTLS_PK_PARSE_C) ) -#error "MBEDTLS_X509_USE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CREATE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ - !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \ - !defined(MBEDTLS_PK_WRITE_C) ) -#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) -#error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CRL_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) -#error "MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CSR_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) -#error "MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CRT_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) -#error "MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_X509_CSR_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) -#error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites" -#endif - -#if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64) -#error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously" -#endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */ - -#if ( defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64) ) && \ - defined(MBEDTLS_HAVE_ASM) -#error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" -#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ - -/* - * Avoid warning from -pedantic. This is a convenient place for this - * workaround since this is included by every single file before the - * #if defined(MBEDTLS_xxx_C) that results in emtpy translation units. - */ -typedef int mbedtls_iso_c_forbids_empty_translation_units; - -#endif /* MBEDTLS_CHECK_CONFIG_H */ diff --git a/components/mbedtls/include/mbedtls/cipher.h b/components/mbedtls/include/mbedtls/cipher.h deleted file mode 100644 index b12e38843a..0000000000 --- a/components/mbedtls/include/mbedtls/cipher.h +++ /dev/null @@ -1,709 +0,0 @@ -/** - * \file cipher.h - * - * \brief Generic cipher wrapper. - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef MBEDTLS_CIPHER_H -#define MBEDTLS_CIPHER_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) -#define MBEDTLS_CIPHER_MODE_AEAD -#endif - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#define MBEDTLS_CIPHER_MODE_WITH_PADDING -#endif - -#if defined(MBEDTLS_ARC4_C) -#define MBEDTLS_CIPHER_MODE_STREAM -#endif - -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */ -#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */ -#define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */ -#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ -#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ -#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid, eg because it was free()ed. */ - -#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length */ -#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - MBEDTLS_CIPHER_ID_NONE = 0, - MBEDTLS_CIPHER_ID_NULL, - MBEDTLS_CIPHER_ID_AES, - MBEDTLS_CIPHER_ID_DES, - MBEDTLS_CIPHER_ID_3DES, - MBEDTLS_CIPHER_ID_CAMELLIA, - MBEDTLS_CIPHER_ID_BLOWFISH, - MBEDTLS_CIPHER_ID_ARC4, -} mbedtls_cipher_id_t; - -typedef enum { - MBEDTLS_CIPHER_NONE = 0, - MBEDTLS_CIPHER_NULL, - MBEDTLS_CIPHER_AES_128_ECB, - MBEDTLS_CIPHER_AES_192_ECB, - MBEDTLS_CIPHER_AES_256_ECB, - MBEDTLS_CIPHER_AES_128_CBC, - MBEDTLS_CIPHER_AES_192_CBC, - MBEDTLS_CIPHER_AES_256_CBC, - MBEDTLS_CIPHER_AES_128_CFB128, - MBEDTLS_CIPHER_AES_192_CFB128, - MBEDTLS_CIPHER_AES_256_CFB128, - MBEDTLS_CIPHER_AES_128_CTR, - MBEDTLS_CIPHER_AES_192_CTR, - MBEDTLS_CIPHER_AES_256_CTR, - MBEDTLS_CIPHER_AES_128_GCM, - MBEDTLS_CIPHER_AES_192_GCM, - MBEDTLS_CIPHER_AES_256_GCM, - MBEDTLS_CIPHER_CAMELLIA_128_ECB, - MBEDTLS_CIPHER_CAMELLIA_192_ECB, - MBEDTLS_CIPHER_CAMELLIA_256_ECB, - MBEDTLS_CIPHER_CAMELLIA_128_CBC, - MBEDTLS_CIPHER_CAMELLIA_192_CBC, - MBEDTLS_CIPHER_CAMELLIA_256_CBC, - MBEDTLS_CIPHER_CAMELLIA_128_CFB128, - MBEDTLS_CIPHER_CAMELLIA_192_CFB128, - MBEDTLS_CIPHER_CAMELLIA_256_CFB128, - MBEDTLS_CIPHER_CAMELLIA_128_CTR, - MBEDTLS_CIPHER_CAMELLIA_192_CTR, - MBEDTLS_CIPHER_CAMELLIA_256_CTR, - MBEDTLS_CIPHER_CAMELLIA_128_GCM, - MBEDTLS_CIPHER_CAMELLIA_192_GCM, - MBEDTLS_CIPHER_CAMELLIA_256_GCM, - MBEDTLS_CIPHER_DES_ECB, - MBEDTLS_CIPHER_DES_CBC, - MBEDTLS_CIPHER_DES_EDE_ECB, - MBEDTLS_CIPHER_DES_EDE_CBC, - MBEDTLS_CIPHER_DES_EDE3_ECB, - MBEDTLS_CIPHER_DES_EDE3_CBC, - MBEDTLS_CIPHER_BLOWFISH_ECB, - MBEDTLS_CIPHER_BLOWFISH_CBC, - MBEDTLS_CIPHER_BLOWFISH_CFB64, - MBEDTLS_CIPHER_BLOWFISH_CTR, - MBEDTLS_CIPHER_ARC4_128, - MBEDTLS_CIPHER_AES_128_CCM, - MBEDTLS_CIPHER_AES_192_CCM, - MBEDTLS_CIPHER_AES_256_CCM, - MBEDTLS_CIPHER_CAMELLIA_128_CCM, - MBEDTLS_CIPHER_CAMELLIA_192_CCM, - MBEDTLS_CIPHER_CAMELLIA_256_CCM, -} mbedtls_cipher_type_t; - -typedef enum { - MBEDTLS_MODE_NONE = 0, - MBEDTLS_MODE_ECB, - MBEDTLS_MODE_CBC, - MBEDTLS_MODE_CFB, - MBEDTLS_MODE_OFB, /* Unused! */ - MBEDTLS_MODE_CTR, - MBEDTLS_MODE_GCM, - MBEDTLS_MODE_STREAM, - MBEDTLS_MODE_CCM, -} mbedtls_cipher_mode_t; - -typedef enum { - MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default) */ - MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding */ - MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding */ - MBEDTLS_PADDING_ZEROS, /**< zero padding (not reversible!) */ - MBEDTLS_PADDING_NONE, /**< never pad (full blocks only) */ -} mbedtls_cipher_padding_t; - -typedef enum { - MBEDTLS_OPERATION_NONE = -1, - MBEDTLS_DECRYPT = 0, - MBEDTLS_ENCRYPT, -} mbedtls_operation_t; - -enum { - /** Undefined key length */ - MBEDTLS_KEY_LENGTH_NONE = 0, - /** Key length, in bits (including parity), for DES keys */ - MBEDTLS_KEY_LENGTH_DES = 64, - /** Key length, in bits (including parity), for DES in two key EDE */ - MBEDTLS_KEY_LENGTH_DES_EDE = 128, - /** Key length, in bits (including parity), for DES in three-key EDE */ - MBEDTLS_KEY_LENGTH_DES_EDE3 = 192, -}; - -/** Maximum length of any IV, in bytes */ -#define MBEDTLS_MAX_IV_LENGTH 16 -/** Maximum block size of any cipher, in bytes */ -#define MBEDTLS_MAX_BLOCK_LENGTH 16 - -/** - * Base cipher information (opaque struct). - */ -typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t; - -/** - * CMAC context (opaque struct). - */ -typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; - -/** - * Cipher information. Allows cipher functions to be called in a generic way. - */ -typedef struct { - /** Full cipher identifier (e.g. MBEDTLS_CIPHER_AES_256_CBC) */ - mbedtls_cipher_type_t type; - - /** Cipher mode (e.g. MBEDTLS_MODE_CBC) */ - mbedtls_cipher_mode_t mode; - - /** Cipher key length, in bits (default length for variable sized ciphers) - * (Includes parity bits for ciphers like DES) */ - unsigned int key_bitlen; - - /** Name of the cipher */ - const char * name; - - /** IV/NONCE size, in bytes. - * For cipher that accept many sizes: recommended size */ - unsigned int iv_size; - - /** Flags for variable IV size, variable key size, etc. */ - int flags; - - /** block size, in bytes */ - unsigned int block_size; - - /** Base cipher information and functions */ - const mbedtls_cipher_base_t *base; - -} mbedtls_cipher_info_t; - -/** - * Generic cipher context. - */ -typedef struct { - /** Information about the associated cipher */ - const mbedtls_cipher_info_t *cipher_info; - - /** Key length to use */ - int key_bitlen; - - /** Operation that the context's key has been initialised for */ - mbedtls_operation_t operation; - -#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) - /** Padding functions to use, if relevant for cipher mode */ - void (*add_padding)( unsigned char *output, size_t olen, size_t data_len ); - int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len ); -#endif - - /** Buffer for data that hasn't been encrypted yet */ - unsigned char unprocessed_data[MBEDTLS_MAX_BLOCK_LENGTH]; - - /** Number of bytes that still need processing */ - size_t unprocessed_len; - - /** Current IV or NONCE_COUNTER for CTR-mode */ - unsigned char iv[MBEDTLS_MAX_IV_LENGTH]; - - /** IV size in bytes (for ciphers with variable-length IVs) */ - size_t iv_size; - - /** Cipher-specific context */ - void *cipher_ctx; - -#if defined(MBEDTLS_CMAC_C) - /** CMAC Specific context */ - mbedtls_cmac_context_t *cmac_ctx; -#endif -} mbedtls_cipher_context_t; - -/** - * \brief Returns the list of ciphers supported by the generic cipher module. - * - * \return a statically allocated array of ciphers, the last entry - * is 0. - */ -const int *mbedtls_cipher_list( void ); - -/** - * \brief Returns the cipher information structure associated - * with the given cipher name. - * - * \param cipher_name Name of the cipher to search for. - * - * \return the cipher information structure associated with the - * given cipher_name, or NULL if not found. - */ -const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ); - -/** - * \brief Returns the cipher information structure associated - * with the given cipher type. - * - * \param cipher_type Type of the cipher to search for. - * - * \return the cipher information structure associated with the - * given cipher_type, or NULL if not found. - */ -const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ); - -/** - * \brief Returns the cipher information structure associated - * with the given cipher id, key size and mode. - * - * \param cipher_id Id of the cipher to search for - * (e.g. MBEDTLS_CIPHER_ID_AES) - * \param key_bitlen Length of the key in bits - * \param mode Cipher mode (e.g. MBEDTLS_MODE_CBC) - * - * \return the cipher information structure associated with the - * given cipher_type, or NULL if not found. - */ -const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, - int key_bitlen, - const mbedtls_cipher_mode_t mode ); - -/** - * \brief Initialize a cipher_context (as NONE) - */ -void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ); - -/** - * \brief Free and clear the cipher-specific context of ctx. - * Freeing ctx itself remains the responsibility of the - * caller. - */ -void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); - -/** - * \brief Initialises and fills the cipher context structure with - * the appropriate values. - * - * \note Currently also clears structure. In future versions you - * will be required to call mbedtls_cipher_init() on the structure - * first. - * - * \param ctx context to initialise. May not be NULL. - * \param cipher_info cipher to use. - * - * \return 0 on success, - * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on parameter failure, - * MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the - * cipher-specific context failed. - */ -int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ); - -/** - * \brief Returns the block size of the given cipher. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return size of the cipher's blocks, or 0 if ctx has not been - * initialised. - */ -static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return 0; - - return ctx->cipher_info->block_size; -} - -/** - * \brief Returns the mode of operation for the cipher. - * (e.g. MBEDTLS_MODE_CBC) - * - * \param ctx cipher's context. Must have been initialised. - * - * \return mode of operation, or MBEDTLS_MODE_NONE if ctx - * has not been initialised. - */ -static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtls_cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return MBEDTLS_MODE_NONE; - - return ctx->cipher_info->mode; -} - -/** - * \brief Returns the size of the cipher's IV/NONCE in bytes. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return If IV has not been set yet: (recommended) IV size - * (0 for ciphers not using IV/NONCE). - * If IV has already been set: actual size. - */ -static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return 0; - - if( ctx->iv_size != 0 ) - return (int) ctx->iv_size; - - return (int) ctx->cipher_info->iv_size; -} - -/** - * \brief Returns the type of the given cipher. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return type of the cipher, or MBEDTLS_CIPHER_NONE if ctx has - * not been initialised. - */ -static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return MBEDTLS_CIPHER_NONE; - - return ctx->cipher_info->type; -} - -/** - * \brief Returns the name of the given cipher, as a string. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return name of the cipher, or NULL if ctx was not initialised. - */ -static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return 0; - - return ctx->cipher_info->name; -} - -/** - * \brief Returns the key length of the cipher. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return cipher's key length, in bits, or - * MBEDTLS_KEY_LENGTH_NONE if ctx has not been - * initialised. - */ -static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return MBEDTLS_KEY_LENGTH_NONE; - - return (int) ctx->cipher_info->key_bitlen; -} - -/** - * \brief Returns the operation of the given cipher. - * - * \param ctx cipher's context. Must have been initialised. - * - * \return operation (MBEDTLS_ENCRYPT or MBEDTLS_DECRYPT), - * or MBEDTLS_OPERATION_NONE if ctx has not been - * initialised. - */ -static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return MBEDTLS_OPERATION_NONE; - - return ctx->operation; -} - -/** - * \brief Set the key to use with the given context. - * - * \param ctx generic cipher context. May not be NULL. Must have been - * initialised using cipher_context_from_type or - * cipher_context_from_string. - * \param key The key to use. - * \param key_bitlen key length to use, in bits. - * \param operation Operation that the key will be used for, either - * MBEDTLS_ENCRYPT or MBEDTLS_DECRYPT. - * - * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if - * parameter verification fails or a cipher specific - * error code. - */ -int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, - int key_bitlen, const mbedtls_operation_t operation ); - -#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) -/** - * \brief Set padding mode, for cipher modes that use padding. - * (Default: PKCS7 padding.) - * - * \param ctx generic cipher context - * \param mode padding mode - * - * \returns 0 on success, MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE - * if selected padding mode is not supported, or - * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode - * does not support padding. - */ -int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ); -#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ - -/** - * \brief Set the initialization vector (IV) or nonce - * - * \param ctx generic cipher context - * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) - * \param iv_len IV length for ciphers with variable-size IV; - * discarded by ciphers with fixed-size IV. - * - * \returns 0 on success, or MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA - * - * \note Some ciphers don't use IVs nor NONCE. For these - * ciphers, this function has no effect. - */ -int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len ); - -/** - * \brief Finish preparation of the given context - * - * \param ctx generic cipher context - * - * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA - * if parameter verification fails. - */ -int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); - -#if defined(MBEDTLS_GCM_C) -/** - * \brief Add additional data (for AEAD ciphers). - * Currently only supported with GCM. - * Must be called exactly once, after mbedtls_cipher_reset(). - * - * \param ctx generic cipher context - * \param ad Additional data to use. - * \param ad_len Length of ad. - * - * \return 0 on success, or a specific error code. - */ -int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, - const unsigned char *ad, size_t ad_len ); -#endif /* MBEDTLS_GCM_C */ - -/** - * \brief Generic cipher update function. Encrypts/decrypts - * using the given cipher context. Writes as many block - * size'd blocks of data as possible to output. Any data - * that cannot be written immediately will either be added - * to the next block, or flushed when cipher_final is - * called. - * Exception: for MBEDTLS_MODE_ECB, expects single block - * in size (e.g. 16 bytes for AES) - * - * \param ctx generic cipher context - * \param input buffer holding the input data - * \param ilen length of the input data - * \param output buffer for the output data. Should be able to hold at - * least ilen + block_size. Cannot be the same buffer as - * input! - * \param olen length of the output data, will be filled with the - * actual number of bytes written. - * - * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if - * parameter verification fails, - * MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an - * unsupported mode for a cipher or a cipher specific - * error code. - * - * \note If the underlying cipher is GCM, all calls to this - * function, except the last one before mbedtls_cipher_finish(), - * must have ilen a multiple of the block size. - */ -int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, - size_t ilen, unsigned char *output, size_t *olen ); - -/** - * \brief Generic cipher finalisation function. If data still - * needs to be flushed from an incomplete block, data - * contained within it will be padded with the size of - * the last block, and written to the output buffer. - * - * \param ctx Generic cipher context - * \param output buffer to write data to. Needs block_size available. - * \param olen length of the data written to the output buffer. - * - * \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if - * parameter verification fails, - * MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption - * expected a full block but was not provided one, - * MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding - * while decrypting or a cipher specific error code. - */ -int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, - unsigned char *output, size_t *olen ); - -#if defined(MBEDTLS_GCM_C) -/** - * \brief Write tag for AEAD ciphers. - * Currently only supported with GCM. - * Must be called after mbedtls_cipher_finish(). - * - * \param ctx Generic cipher context - * \param tag buffer to write the tag - * \param tag_len Length of the tag to write - * - * \return 0 on success, or a specific error code. - */ -int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, - unsigned char *tag, size_t tag_len ); - -/** - * \brief Check tag for AEAD ciphers. - * Currently only supported with GCM. - * Must be called after mbedtls_cipher_finish(). - * - * \param ctx Generic cipher context - * \param tag Buffer holding the tag - * \param tag_len Length of the tag to check - * - * \return 0 on success, or a specific error code. - */ -int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, - const unsigned char *tag, size_t tag_len ); -#endif /* MBEDTLS_GCM_C */ - -/** - * \brief Generic all-in-one encryption/decryption - * (for all ciphers except AEAD constructs). - * - * \param ctx generic cipher context - * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) - * \param iv_len IV length for ciphers with variable-size IV; - * discarded by ciphers with fixed-size IV. - * \param input buffer holding the input data - * \param ilen length of the input data - * \param output buffer for the output data. Should be able to hold at - * least ilen + block_size. Cannot be the same buffer as - * input! - * \param olen length of the output data, will be filled with the - * actual number of bytes written. - * - * \note Some ciphers don't use IVs nor NONCE. For these - * ciphers, use iv = NULL and iv_len = 0. - * - * \returns 0 on success, or - * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or - * MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption - * expected a full block but was not provided one, or - * MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding - * while decrypting, or - * a cipher specific error code. - */ -int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen ); - -#if defined(MBEDTLS_CIPHER_MODE_AEAD) -/** - * \brief Generic autenticated encryption (AEAD ciphers). - * - * \param ctx generic cipher context - * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) - * \param iv_len IV length for ciphers with variable-size IV; - * discarded by ciphers with fixed-size IV. - * \param ad Additional data to authenticate. - * \param ad_len Length of ad. - * \param input buffer holding the input data - * \param ilen length of the input data - * \param output buffer for the output data. - * Should be able to hold at least ilen. - * \param olen length of the output data, will be filled with the - * actual number of bytes written. - * \param tag buffer for the authentication tag - * \param tag_len desired tag length - * - * \returns 0 on success, or - * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or - * a cipher specific error code. - */ -int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *ad, size_t ad_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, - unsigned char *tag, size_t tag_len ); - -/** - * \brief Generic autenticated decryption (AEAD ciphers). - * - * \param ctx generic cipher context - * \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers) - * \param iv_len IV length for ciphers with variable-size IV; - * discarded by ciphers with fixed-size IV. - * \param ad Additional data to be authenticated. - * \param ad_len Length of ad. - * \param input buffer holding the input data - * \param ilen length of the input data - * \param output buffer for the output data. - * Should be able to hold at least ilen. - * \param olen length of the output data, will be filled with the - * actual number of bytes written. - * \param tag buffer holding the authentication tag - * \param tag_len length of the authentication tag - * - * \returns 0 on success, or - * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or - * MBEDTLS_ERR_CIPHER_AUTH_FAILED if data isn't authentic, - * or a cipher specific error code. - * - * \note If the data is not authentic, then the output buffer - * is zeroed out to prevent the unauthentic plaintext to - * be used by mistake, making this interface safer. - */ -int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *ad, size_t ad_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, - const unsigned char *tag, size_t tag_len ); -#endif /* MBEDTLS_CIPHER_MODE_AEAD */ - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_CIPHER_H */ diff --git a/components/mbedtls/include/mbedtls/cipher_internal.h b/components/mbedtls/include/mbedtls/cipher_internal.h deleted file mode 100644 index 6c58bcc525..0000000000 --- a/components/mbedtls/include/mbedtls/cipher_internal.h +++ /dev/null @@ -1,109 +0,0 @@ -/** - * \file cipher_internal.h - * - * \brief Cipher wrappers. - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_CIPHER_WRAP_H -#define MBEDTLS_CIPHER_WRAP_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "cipher.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Base cipher information. The non-mode specific functions and values. - */ -struct mbedtls_cipher_base_t -{ - /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */ - mbedtls_cipher_id_t cipher; - - /** Encrypt using ECB */ - int (*ecb_func)( void *ctx, mbedtls_operation_t mode, - const unsigned char *input, unsigned char *output ); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - /** Encrypt using CBC */ - int (*cbc_func)( void *ctx, mbedtls_operation_t mode, size_t length, - unsigned char *iv, const unsigned char *input, - unsigned char *output ); -#endif - -#if defined(MBEDTLS_CIPHER_MODE_CFB) - /** Encrypt using CFB (Full length) */ - int (*cfb_func)( void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off, - unsigned char *iv, const unsigned char *input, - unsigned char *output ); -#endif - -#if defined(MBEDTLS_CIPHER_MODE_CTR) - /** Encrypt using CTR */ - int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, - unsigned char *nonce_counter, unsigned char *stream_block, - const unsigned char *input, unsigned char *output ); -#endif - -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - /** Encrypt using STREAM */ - int (*stream_func)( void *ctx, size_t length, - const unsigned char *input, unsigned char *output ); -#endif - - /** Set key for encryption purposes */ - int (*setkey_enc_func)( void *ctx, const unsigned char *key, - unsigned int key_bitlen ); - - /** Set key for decryption purposes */ - int (*setkey_dec_func)( void *ctx, const unsigned char *key, - unsigned int key_bitlen); - - /** Allocate a new context */ - void * (*ctx_alloc_func)( void ); - - /** Free the given context */ - void (*ctx_free_func)( void *ctx ); - -}; - -typedef struct -{ - mbedtls_cipher_type_t type; - const mbedtls_cipher_info_t *info; -} mbedtls_cipher_definition_t; - -extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[]; - -extern int mbedtls_cipher_supported[]; - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_CIPHER_WRAP_H */ diff --git a/components/mbedtls/include/mbedtls/cmac.h b/components/mbedtls/include/mbedtls/cmac.h deleted file mode 100644 index 9a2b96bc92..0000000000 --- a/components/mbedtls/include/mbedtls/cmac.h +++ /dev/null @@ -1,170 +0,0 @@ -/** - * \file cmac.h - * - * \brief Cipher-based Message Authentication Code (CMAC) Mode for - * Authentication - * - * Copyright (C) 2015-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_CMAC_H -#define MBEDTLS_CMAC_H - -#include "mbedtls/cipher.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define MBEDTLS_AES_BLOCK_SIZE 16 -#define MBEDTLS_DES3_BLOCK_SIZE 8 - -#if defined(MBEDTLS_AES_C) -#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /* longest used by CMAC is AES */ -#else -#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /* longest used by CMAC is 3DES */ -#endif - -/** - * CMAC context structure - Contains internal state information only - */ -struct mbedtls_cmac_context_t -{ - /** Internal state of the CMAC algorithm */ - unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX]; - - /** Unprocessed data - either data that was not block aligned and is still - * pending to be processed, or the final block */ - unsigned char unprocessed_block[MBEDTLS_CIPHER_BLKSIZE_MAX]; - - /** Length of data pending to be processed */ - size_t unprocessed_len; -}; - -/** - * \brief Set the CMAC key and prepare to authenticate the input - * data. - * Should be called with an initialized cipher context. - * - * \param ctx Cipher context. This should be a cipher context, - * initialized to be one of the following types: - * MBEDTLS_CIPHER_AES_128_ECB, MBEDTLS_CIPHER_AES_192_ECB, - * MBEDTLS_CIPHER_AES_256_ECB or - * MBEDTLS_CIPHER_DES_EDE3_ECB. - * \param key CMAC key - * \param keybits length of the CMAC key in bits - * (must be acceptable by the cipher) - * - * \return 0 if successful, or a cipher specific error code - */ -int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, - const unsigned char *key, size_t keybits ); - -/** - * \brief Generic CMAC process buffer. - * Called between mbedtls_cipher_cmac_starts() or - * mbedtls_cipher_cmac_reset() and - * mbedtls_cipher_cmac_finish(). - * May be called repeatedly. - * - * \param ctx CMAC context - * \param input buffer holding the data - * \param ilen length of the input data - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, - const unsigned char *input, size_t ilen ); - -/** - * \brief Output CMAC. - * Called after mbedtls_cipher_cmac_update(). - * Usually followed by mbedtls_cipher_cmac_reset(), then - * mbedtls_cipher_cmac_starts(), or mbedtls_cipher_free(). - * - * \param ctx CMAC context - * \param output Generic CMAC checksum result - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, - unsigned char *output ); - -/** - * \brief Prepare to authenticate a new message with the same key. - * Called after mbedtls_cipher_cmac_finish() and before - * mbedtls_cipher_cmac_update(). - * - * \param ctx CMAC context to be reset - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ); - -/** - * \brief Output = Generic_CMAC( cmac key, input buffer ) - * - * \param cipher_info message digest info - * \param key CMAC key - * \param keylen length of the CMAC key in bits - * \param input buffer holding the data - * \param ilen length of the input data - * \param output Generic CMAC-result - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, - const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char *output ); - -#if defined(MBEDTLS_AES_C) -/** - * \brief AES-CMAC-128-PRF - * Implementation of (AES-CMAC-PRF-128), as defined in RFC 4615 - * - * \param key PRF key - * \param key_len PRF key length in bytes - * \param input buffer holding the input data - * \param in_len length of the input data in bytes - * \param output buffer holding the generated pseudorandom output (16 bytes) - * - * \return 0 if successful - */ -int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len, - const unsigned char *input, size_t in_len, - unsigned char output[16] ); -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_cmac_self_test( int verbose ); -#endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_CMAC_H */ diff --git a/components/mbedtls/include/mbedtls/compat-1.3.h b/components/mbedtls/include/mbedtls/compat-1.3.h deleted file mode 100644 index bba1d2c247..0000000000 --- a/components/mbedtls/include/mbedtls/compat-1.3.h +++ /dev/null @@ -1,2523 +0,0 @@ -/** - * \file compat-1.3.h - * - * \brief Compatibility definitions for using mbed TLS with client code written - * for the PolarSSL naming conventions. - * - * \deprecated Use the new names directly instead - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if ! defined(MBEDTLS_DEPRECATED_REMOVED) - -#if defined(MBEDTLS_DEPRECATED_WARNING) -#warning "Including compat-1.3.h is deprecated" -#endif - -#ifndef MBEDTLS_COMPAT13_H -#define MBEDTLS_COMPAT13_H - -/* - * config.h options - */ -#if defined MBEDTLS_AESNI_C -#define POLARSSL_AESNI_C MBEDTLS_AESNI_C -#endif -#if defined MBEDTLS_AES_ALT -#define POLARSSL_AES_ALT MBEDTLS_AES_ALT -#endif -#if defined MBEDTLS_AES_C -#define POLARSSL_AES_C MBEDTLS_AES_C -#endif -#if defined MBEDTLS_AES_ROM_TABLES -#define POLARSSL_AES_ROM_TABLES MBEDTLS_AES_ROM_TABLES -#endif -#if defined MBEDTLS_ARC4_ALT -#define POLARSSL_ARC4_ALT MBEDTLS_ARC4_ALT -#endif -#if defined MBEDTLS_ARC4_C -#define POLARSSL_ARC4_C MBEDTLS_ARC4_C -#endif -#if defined MBEDTLS_ASN1_PARSE_C -#define POLARSSL_ASN1_PARSE_C MBEDTLS_ASN1_PARSE_C -#endif -#if defined MBEDTLS_ASN1_WRITE_C -#define POLARSSL_ASN1_WRITE_C MBEDTLS_ASN1_WRITE_C -#endif -#if defined MBEDTLS_BASE64_C -#define POLARSSL_BASE64_C MBEDTLS_BASE64_C -#endif -#if defined MBEDTLS_BIGNUM_C -#define POLARSSL_BIGNUM_C MBEDTLS_BIGNUM_C -#endif -#if defined MBEDTLS_BLOWFISH_ALT -#define POLARSSL_BLOWFISH_ALT MBEDTLS_BLOWFISH_ALT -#endif -#if defined MBEDTLS_BLOWFISH_C -#define POLARSSL_BLOWFISH_C MBEDTLS_BLOWFISH_C -#endif -#if defined MBEDTLS_CAMELLIA_ALT -#define POLARSSL_CAMELLIA_ALT MBEDTLS_CAMELLIA_ALT -#endif -#if defined MBEDTLS_CAMELLIA_C -#define POLARSSL_CAMELLIA_C MBEDTLS_CAMELLIA_C -#endif -#if defined MBEDTLS_CAMELLIA_SMALL_MEMORY -#define POLARSSL_CAMELLIA_SMALL_MEMORY MBEDTLS_CAMELLIA_SMALL_MEMORY -#endif -#if defined MBEDTLS_CCM_C -#define POLARSSL_CCM_C MBEDTLS_CCM_C -#endif -#if defined MBEDTLS_CERTS_C -#define POLARSSL_CERTS_C MBEDTLS_CERTS_C -#endif -#if defined MBEDTLS_CIPHER_C -#define POLARSSL_CIPHER_C MBEDTLS_CIPHER_C -#endif -#if defined MBEDTLS_CIPHER_MODE_CBC -#define POLARSSL_CIPHER_MODE_CBC MBEDTLS_CIPHER_MODE_CBC -#endif -#if defined MBEDTLS_CIPHER_MODE_CFB -#define POLARSSL_CIPHER_MODE_CFB MBEDTLS_CIPHER_MODE_CFB -#endif -#if defined MBEDTLS_CIPHER_MODE_CTR -#define POLARSSL_CIPHER_MODE_CTR MBEDTLS_CIPHER_MODE_CTR -#endif -#if defined MBEDTLS_CIPHER_NULL_CIPHER -#define POLARSSL_CIPHER_NULL_CIPHER MBEDTLS_CIPHER_NULL_CIPHER -#endif -#if defined MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS -#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS -#endif -#if defined MBEDTLS_CIPHER_PADDING_PKCS7 -#define POLARSSL_CIPHER_PADDING_PKCS7 MBEDTLS_CIPHER_PADDING_PKCS7 -#endif -#if defined MBEDTLS_CIPHER_PADDING_ZEROS -#define POLARSSL_CIPHER_PADDING_ZEROS MBEDTLS_CIPHER_PADDING_ZEROS -#endif -#if defined MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN -#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN -#endif -#if defined MBEDTLS_CTR_DRBG_C -#define POLARSSL_CTR_DRBG_C MBEDTLS_CTR_DRBG_C -#endif -#if defined MBEDTLS_DEBUG_C -#define POLARSSL_DEBUG_C MBEDTLS_DEBUG_C -#endif -#if defined MBEDTLS_DEPRECATED_REMOVED -#define POLARSSL_DEPRECATED_REMOVED MBEDTLS_DEPRECATED_REMOVED -#endif -#if defined MBEDTLS_DEPRECATED_WARNING -#define POLARSSL_DEPRECATED_WARNING MBEDTLS_DEPRECATED_WARNING -#endif -#if defined MBEDTLS_DES_ALT -#define POLARSSL_DES_ALT MBEDTLS_DES_ALT -#endif -#if defined MBEDTLS_DES_C -#define POLARSSL_DES_C MBEDTLS_DES_C -#endif -#if defined MBEDTLS_DHM_C -#define POLARSSL_DHM_C MBEDTLS_DHM_C -#endif -#if defined MBEDTLS_ECDH_C -#define POLARSSL_ECDH_C MBEDTLS_ECDH_C -#endif -#if defined MBEDTLS_ECDSA_C -#define POLARSSL_ECDSA_C MBEDTLS_ECDSA_C -#endif -#if defined MBEDTLS_ECDSA_DETERMINISTIC -#define POLARSSL_ECDSA_DETERMINISTIC MBEDTLS_ECDSA_DETERMINISTIC -#endif -#if defined MBEDTLS_ECP_C -#define POLARSSL_ECP_C MBEDTLS_ECP_C -#endif -#if defined MBEDTLS_ECP_DP_BP256R1_ENABLED -#define POLARSSL_ECP_DP_BP256R1_ENABLED MBEDTLS_ECP_DP_BP256R1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_BP384R1_ENABLED -#define POLARSSL_ECP_DP_BP384R1_ENABLED MBEDTLS_ECP_DP_BP384R1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_BP512R1_ENABLED -#define POLARSSL_ECP_DP_BP512R1_ENABLED MBEDTLS_ECP_DP_BP512R1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_CURVE25519_ENABLED -#define POLARSSL_ECP_DP_M255_ENABLED MBEDTLS_ECP_DP_CURVE25519_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_SECP192K1_ENABLED -#define POLARSSL_ECP_DP_SECP192K1_ENABLED MBEDTLS_ECP_DP_SECP192K1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_SECP192R1_ENABLED -#define POLARSSL_ECP_DP_SECP192R1_ENABLED MBEDTLS_ECP_DP_SECP192R1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_SECP224K1_ENABLED -#define POLARSSL_ECP_DP_SECP224K1_ENABLED MBEDTLS_ECP_DP_SECP224K1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_SECP224R1_ENABLED -#define POLARSSL_ECP_DP_SECP224R1_ENABLED MBEDTLS_ECP_DP_SECP224R1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_SECP256K1_ENABLED -#define POLARSSL_ECP_DP_SECP256K1_ENABLED MBEDTLS_ECP_DP_SECP256K1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_SECP256R1_ENABLED -#define POLARSSL_ECP_DP_SECP256R1_ENABLED MBEDTLS_ECP_DP_SECP256R1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_SECP384R1_ENABLED -#define POLARSSL_ECP_DP_SECP384R1_ENABLED MBEDTLS_ECP_DP_SECP384R1_ENABLED -#endif -#if defined MBEDTLS_ECP_DP_SECP521R1_ENABLED -#define POLARSSL_ECP_DP_SECP521R1_ENABLED MBEDTLS_ECP_DP_SECP521R1_ENABLED -#endif -#if defined MBEDTLS_ECP_FIXED_POINT_OPTIM -#define POLARSSL_ECP_FIXED_POINT_OPTIM MBEDTLS_ECP_FIXED_POINT_OPTIM -#endif -#if defined MBEDTLS_ECP_MAX_BITS -#define POLARSSL_ECP_MAX_BITS MBEDTLS_ECP_MAX_BITS -#endif -#if defined MBEDTLS_ECP_NIST_OPTIM -#define POLARSSL_ECP_NIST_OPTIM MBEDTLS_ECP_NIST_OPTIM -#endif -#if defined MBEDTLS_ECP_WINDOW_SIZE -#define POLARSSL_ECP_WINDOW_SIZE MBEDTLS_ECP_WINDOW_SIZE -#endif -#if defined MBEDTLS_ENABLE_WEAK_CIPHERSUITES -#define POLARSSL_ENABLE_WEAK_CIPHERSUITES MBEDTLS_ENABLE_WEAK_CIPHERSUITES -#endif -#if defined MBEDTLS_ENTROPY_C -#define POLARSSL_ENTROPY_C MBEDTLS_ENTROPY_C -#endif -#if defined MBEDTLS_ENTROPY_FORCE_SHA256 -#define POLARSSL_ENTROPY_FORCE_SHA256 MBEDTLS_ENTROPY_FORCE_SHA256 -#endif -#if defined MBEDTLS_ERROR_C -#define POLARSSL_ERROR_C MBEDTLS_ERROR_C -#endif -#if defined MBEDTLS_ERROR_STRERROR_DUMMY -#define POLARSSL_ERROR_STRERROR_DUMMY MBEDTLS_ERROR_STRERROR_DUMMY -#endif -#if defined MBEDTLS_FS_IO -#define POLARSSL_FS_IO MBEDTLS_FS_IO -#endif -#if defined MBEDTLS_GCM_C -#define POLARSSL_GCM_C MBEDTLS_GCM_C -#endif -#if defined MBEDTLS_GENPRIME -#define POLARSSL_GENPRIME MBEDTLS_GENPRIME -#endif -#if defined MBEDTLS_HAVEGE_C -#define POLARSSL_HAVEGE_C MBEDTLS_HAVEGE_C -#endif -#if defined MBEDTLS_HAVE_ASM -#define POLARSSL_HAVE_ASM MBEDTLS_HAVE_ASM -#endif -#if defined MBEDTLS_HAVE_SSE2 -#define POLARSSL_HAVE_SSE2 MBEDTLS_HAVE_SSE2 -#endif -#if defined MBEDTLS_HAVE_TIME -#define POLARSSL_HAVE_TIME MBEDTLS_HAVE_TIME -#endif -#if defined MBEDTLS_HMAC_DRBG_C -#define POLARSSL_HMAC_DRBG_C MBEDTLS_HMAC_DRBG_C -#endif -#if defined MBEDTLS_HMAC_DRBG_MAX_INPUT -#define POLARSSL_HMAC_DRBG_MAX_INPUT MBEDTLS_HMAC_DRBG_MAX_INPUT -#endif -#if defined MBEDTLS_HMAC_DRBG_MAX_REQUEST -#define POLARSSL_HMAC_DRBG_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST -#endif -#if defined MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT -#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT -#endif -#if defined MBEDTLS_HMAC_DRBG_RESEED_INTERVAL -#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL MBEDTLS_HMAC_DRBG_RESEED_INTERVAL -#endif -#if defined MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED -#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED -#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED -#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED -#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED -#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED -#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED -#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_PSK_ENABLED -#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_PSK_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_RSA_ENABLED -#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_ENABLED -#endif -#if defined MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED -#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED -#endif -#if defined MBEDTLS_MD2_ALT -#define POLARSSL_MD2_ALT MBEDTLS_MD2_ALT -#endif -#if defined MBEDTLS_MD2_C -#define POLARSSL_MD2_C MBEDTLS_MD2_C -#endif -#if defined MBEDTLS_MD2_PROCESS_ALT -#define POLARSSL_MD2_PROCESS_ALT MBEDTLS_MD2_PROCESS_ALT -#endif -#if defined MBEDTLS_MD4_ALT -#define POLARSSL_MD4_ALT MBEDTLS_MD4_ALT -#endif -#if defined MBEDTLS_MD4_C -#define POLARSSL_MD4_C MBEDTLS_MD4_C -#endif -#if defined MBEDTLS_MD4_PROCESS_ALT -#define POLARSSL_MD4_PROCESS_ALT MBEDTLS_MD4_PROCESS_ALT -#endif -#if defined MBEDTLS_MD5_ALT -#define POLARSSL_MD5_ALT MBEDTLS_MD5_ALT -#endif -#if defined MBEDTLS_MD5_C -#define POLARSSL_MD5_C MBEDTLS_MD5_C -#endif -#if defined MBEDTLS_MD5_PROCESS_ALT -#define POLARSSL_MD5_PROCESS_ALT MBEDTLS_MD5_PROCESS_ALT -#endif -#if defined MBEDTLS_MD_C -#define POLARSSL_MD_C MBEDTLS_MD_C -#endif -#if defined MBEDTLS_MEMORY_ALIGN_MULTIPLE -#define POLARSSL_MEMORY_ALIGN_MULTIPLE MBEDTLS_MEMORY_ALIGN_MULTIPLE -#endif -#if defined MBEDTLS_MEMORY_BACKTRACE -#define POLARSSL_MEMORY_BACKTRACE MBEDTLS_MEMORY_BACKTRACE -#endif -#if defined MBEDTLS_MEMORY_BUFFER_ALLOC_C -#define POLARSSL_MEMORY_BUFFER_ALLOC_C MBEDTLS_MEMORY_BUFFER_ALLOC_C -#endif -#if defined MBEDTLS_MEMORY_DEBUG -#define POLARSSL_MEMORY_DEBUG MBEDTLS_MEMORY_DEBUG -#endif -#if defined MBEDTLS_MPI_MAX_SIZE -#define POLARSSL_MPI_MAX_SIZE MBEDTLS_MPI_MAX_SIZE -#endif -#if defined MBEDTLS_MPI_WINDOW_SIZE -#define POLARSSL_MPI_WINDOW_SIZE MBEDTLS_MPI_WINDOW_SIZE -#endif -#if defined MBEDTLS_NET_C -#define POLARSSL_NET_C MBEDTLS_NET_C -#endif -#if defined MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES -#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES -#endif -#if defined MBEDTLS_NO_PLATFORM_ENTROPY -#define POLARSSL_NO_PLATFORM_ENTROPY MBEDTLS_NO_PLATFORM_ENTROPY -#endif -#if defined MBEDTLS_OID_C -#define POLARSSL_OID_C MBEDTLS_OID_C -#endif -#if defined MBEDTLS_PADLOCK_C -#define POLARSSL_PADLOCK_C MBEDTLS_PADLOCK_C -#endif -#if defined MBEDTLS_PEM_PARSE_C -#define POLARSSL_PEM_PARSE_C MBEDTLS_PEM_PARSE_C -#endif -#if defined MBEDTLS_PEM_WRITE_C -#define POLARSSL_PEM_WRITE_C MBEDTLS_PEM_WRITE_C -#endif -#if defined MBEDTLS_PKCS11_C -#define POLARSSL_PKCS11_C MBEDTLS_PKCS11_C -#endif -#if defined MBEDTLS_PKCS12_C -#define POLARSSL_PKCS12_C MBEDTLS_PKCS12_C -#endif -#if defined MBEDTLS_PKCS1_V15 -#define POLARSSL_PKCS1_V15 MBEDTLS_PKCS1_V15 -#endif -#if defined MBEDTLS_PKCS1_V21 -#define POLARSSL_PKCS1_V21 MBEDTLS_PKCS1_V21 -#endif -#if defined MBEDTLS_PKCS5_C -#define POLARSSL_PKCS5_C MBEDTLS_PKCS5_C -#endif -#if defined MBEDTLS_PK_C -#define POLARSSL_PK_C MBEDTLS_PK_C -#endif -#if defined MBEDTLS_PK_PARSE_C -#define POLARSSL_PK_PARSE_C MBEDTLS_PK_PARSE_C -#endif -#if defined MBEDTLS_PK_PARSE_EC_EXTENDED -#define POLARSSL_PK_PARSE_EC_EXTENDED MBEDTLS_PK_PARSE_EC_EXTENDED -#endif -#if defined MBEDTLS_PK_RSA_ALT_SUPPORT -#define POLARSSL_PK_RSA_ALT_SUPPORT MBEDTLS_PK_RSA_ALT_SUPPORT -#endif -#if defined MBEDTLS_PK_WRITE_C -#define POLARSSL_PK_WRITE_C MBEDTLS_PK_WRITE_C -#endif -#if defined MBEDTLS_PLATFORM_C -#define POLARSSL_PLATFORM_C MBEDTLS_PLATFORM_C -#endif -#if defined MBEDTLS_PLATFORM_EXIT_ALT -#define POLARSSL_PLATFORM_EXIT_ALT MBEDTLS_PLATFORM_EXIT_ALT -#endif -#if defined MBEDTLS_PLATFORM_EXIT_MACRO -#define POLARSSL_PLATFORM_EXIT_MACRO MBEDTLS_PLATFORM_EXIT_MACRO -#endif -#if defined MBEDTLS_PLATFORM_FPRINTF_ALT -#define POLARSSL_PLATFORM_FPRINTF_ALT MBEDTLS_PLATFORM_FPRINTF_ALT -#endif -#if defined MBEDTLS_PLATFORM_FPRINTF_MACRO -#define POLARSSL_PLATFORM_FPRINTF_MACRO MBEDTLS_PLATFORM_FPRINTF_MACRO -#endif -#if defined MBEDTLS_PLATFORM_FREE_MACRO -#define POLARSSL_PLATFORM_FREE_MACRO MBEDTLS_PLATFORM_FREE_MACRO -#endif -#if defined MBEDTLS_PLATFORM_MEMORY -#define POLARSSL_PLATFORM_MEMORY MBEDTLS_PLATFORM_MEMORY -#endif -#if defined MBEDTLS_PLATFORM_NO_STD_FUNCTIONS -#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS MBEDTLS_PLATFORM_NO_STD_FUNCTIONS -#endif -#if defined MBEDTLS_PLATFORM_PRINTF_ALT -#define POLARSSL_PLATFORM_PRINTF_ALT MBEDTLS_PLATFORM_PRINTF_ALT -#endif -#if defined MBEDTLS_PLATFORM_PRINTF_MACRO -#define POLARSSL_PLATFORM_PRINTF_MACRO MBEDTLS_PLATFORM_PRINTF_MACRO -#endif -#if defined MBEDTLS_PLATFORM_SNPRINTF_ALT -#define POLARSSL_PLATFORM_SNPRINTF_ALT MBEDTLS_PLATFORM_SNPRINTF_ALT -#endif -#if defined MBEDTLS_PLATFORM_SNPRINTF_MACRO -#define POLARSSL_PLATFORM_SNPRINTF_MACRO MBEDTLS_PLATFORM_SNPRINTF_MACRO -#endif -#if defined MBEDTLS_PLATFORM_STD_EXIT -#define POLARSSL_PLATFORM_STD_EXIT MBEDTLS_PLATFORM_STD_EXIT -#endif -#if defined MBEDTLS_PLATFORM_STD_FPRINTF -#define POLARSSL_PLATFORM_STD_FPRINTF MBEDTLS_PLATFORM_STD_FPRINTF -#endif -#if defined MBEDTLS_PLATFORM_STD_FREE -#define POLARSSL_PLATFORM_STD_FREE MBEDTLS_PLATFORM_STD_FREE -#endif -#if defined MBEDTLS_PLATFORM_STD_MEM_HDR -#define POLARSSL_PLATFORM_STD_MEM_HDR MBEDTLS_PLATFORM_STD_MEM_HDR -#endif -#if defined MBEDTLS_PLATFORM_STD_PRINTF -#define POLARSSL_PLATFORM_STD_PRINTF MBEDTLS_PLATFORM_STD_PRINTF -#endif -#if defined MBEDTLS_PLATFORM_STD_SNPRINTF -#define POLARSSL_PLATFORM_STD_SNPRINTF MBEDTLS_PLATFORM_STD_SNPRINTF -#endif -#if defined MBEDTLS_PSK_MAX_LEN -#define POLARSSL_PSK_MAX_LEN MBEDTLS_PSK_MAX_LEN -#endif -#if defined MBEDTLS_REMOVE_ARC4_CIPHERSUITES -#define POLARSSL_REMOVE_ARC4_CIPHERSUITES MBEDTLS_REMOVE_ARC4_CIPHERSUITES -#endif -#if defined MBEDTLS_RIPEMD160_ALT -#define POLARSSL_RIPEMD160_ALT MBEDTLS_RIPEMD160_ALT -#endif -#if defined MBEDTLS_RIPEMD160_C -#define POLARSSL_RIPEMD160_C MBEDTLS_RIPEMD160_C -#endif -#if defined MBEDTLS_RIPEMD160_PROCESS_ALT -#define POLARSSL_RIPEMD160_PROCESS_ALT MBEDTLS_RIPEMD160_PROCESS_ALT -#endif -#if defined MBEDTLS_RSA_C -#define POLARSSL_RSA_C MBEDTLS_RSA_C -#endif -#if defined MBEDTLS_RSA_NO_CRT -#define POLARSSL_RSA_NO_CRT MBEDTLS_RSA_NO_CRT -#endif -#if defined MBEDTLS_SELF_TEST -#define POLARSSL_SELF_TEST MBEDTLS_SELF_TEST -#endif -#if defined MBEDTLS_SHA1_ALT -#define POLARSSL_SHA1_ALT MBEDTLS_SHA1_ALT -#endif -#if defined MBEDTLS_SHA1_C -#define POLARSSL_SHA1_C MBEDTLS_SHA1_C -#endif -#if defined MBEDTLS_SHA1_PROCESS_ALT -#define POLARSSL_SHA1_PROCESS_ALT MBEDTLS_SHA1_PROCESS_ALT -#endif -#if defined MBEDTLS_SHA256_ALT -#define POLARSSL_SHA256_ALT MBEDTLS_SHA256_ALT -#endif -#if defined MBEDTLS_SHA256_C -#define POLARSSL_SHA256_C MBEDTLS_SHA256_C -#endif -#if defined MBEDTLS_SHA256_PROCESS_ALT -#define POLARSSL_SHA256_PROCESS_ALT MBEDTLS_SHA256_PROCESS_ALT -#endif -#if defined MBEDTLS_SHA512_ALT -#define POLARSSL_SHA512_ALT MBEDTLS_SHA512_ALT -#endif -#if defined MBEDTLS_SHA512_C -#define POLARSSL_SHA512_C MBEDTLS_SHA512_C -#endif -#if defined MBEDTLS_SHA512_PROCESS_ALT -#define POLARSSL_SHA512_PROCESS_ALT MBEDTLS_SHA512_PROCESS_ALT -#endif -#if defined MBEDTLS_SSL_ALL_ALERT_MESSAGES -#define POLARSSL_SSL_ALL_ALERT_MESSAGES MBEDTLS_SSL_ALL_ALERT_MESSAGES -#endif -#if defined MBEDTLS_SSL_ALPN -#define POLARSSL_SSL_ALPN MBEDTLS_SSL_ALPN -#endif -#if defined MBEDTLS_SSL_CACHE_C -#define POLARSSL_SSL_CACHE_C MBEDTLS_SSL_CACHE_C -#endif -#if defined MBEDTLS_SSL_CBC_RECORD_SPLITTING -#define POLARSSL_SSL_CBC_RECORD_SPLITTING MBEDTLS_SSL_CBC_RECORD_SPLITTING -#endif -#if defined MBEDTLS_SSL_CLI_C -#define POLARSSL_SSL_CLI_C MBEDTLS_SSL_CLI_C -#endif -#if defined MBEDTLS_SSL_COOKIE_C -#define POLARSSL_SSL_COOKIE_C MBEDTLS_SSL_COOKIE_C -#endif -#if defined MBEDTLS_SSL_COOKIE_TIMEOUT -#define POLARSSL_SSL_COOKIE_TIMEOUT MBEDTLS_SSL_COOKIE_TIMEOUT -#endif -#if defined MBEDTLS_SSL_DEBUG_ALL -#define POLARSSL_SSL_DEBUG_ALL MBEDTLS_SSL_DEBUG_ALL -#endif -#if defined MBEDTLS_SSL_DTLS_ANTI_REPLAY -#define POLARSSL_SSL_DTLS_ANTI_REPLAY MBEDTLS_SSL_DTLS_ANTI_REPLAY -#endif -#if defined MBEDTLS_SSL_DTLS_BADMAC_LIMIT -#define POLARSSL_SSL_DTLS_BADMAC_LIMIT MBEDTLS_SSL_DTLS_BADMAC_LIMIT -#endif -#if defined MBEDTLS_SSL_DTLS_HELLO_VERIFY -#define POLARSSL_SSL_DTLS_HELLO_VERIFY MBEDTLS_SSL_DTLS_HELLO_VERIFY -#endif -#if defined MBEDTLS_SSL_ENCRYPT_THEN_MAC -#define POLARSSL_SSL_ENCRYPT_THEN_MAC MBEDTLS_SSL_ENCRYPT_THEN_MAC -#endif -#if defined MBEDTLS_SSL_EXTENDED_MASTER_SECRET -#define POLARSSL_SSL_EXTENDED_MASTER_SECRET MBEDTLS_SSL_EXTENDED_MASTER_SECRET -#endif -#if defined MBEDTLS_SSL_FALLBACK_SCSV -#define POLARSSL_SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV -#endif -#if defined MBEDTLS_SSL_HW_RECORD_ACCEL -#define POLARSSL_SSL_HW_RECORD_ACCEL MBEDTLS_SSL_HW_RECORD_ACCEL -#endif -#if defined MBEDTLS_SSL_MAX_FRAGMENT_LENGTH -#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH MBEDTLS_SSL_MAX_FRAGMENT_LENGTH -#endif -#if defined MBEDTLS_SSL_PROTO_DTLS -#define POLARSSL_SSL_PROTO_DTLS MBEDTLS_SSL_PROTO_DTLS -#endif -#if defined MBEDTLS_SSL_PROTO_SSL3 -#define POLARSSL_SSL_PROTO_SSL3 MBEDTLS_SSL_PROTO_SSL3 -#endif -#if defined MBEDTLS_SSL_PROTO_TLS1 -#define POLARSSL_SSL_PROTO_TLS1 MBEDTLS_SSL_PROTO_TLS1 -#endif -#if defined MBEDTLS_SSL_PROTO_TLS1_1 -#define POLARSSL_SSL_PROTO_TLS1_1 MBEDTLS_SSL_PROTO_TLS1_1 -#endif -#if defined MBEDTLS_SSL_PROTO_TLS1_2 -#define POLARSSL_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_2 -#endif -#if defined MBEDTLS_SSL_RENEGOTIATION -#define POLARSSL_SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION -#endif -#if defined MBEDTLS_SSL_SERVER_NAME_INDICATION -#define POLARSSL_SSL_SERVER_NAME_INDICATION MBEDTLS_SSL_SERVER_NAME_INDICATION -#endif -#if defined MBEDTLS_SSL_SESSION_TICKETS -#define POLARSSL_SSL_SESSION_TICKETS MBEDTLS_SSL_SESSION_TICKETS -#endif -#if defined MBEDTLS_SSL_SRV_C -#define POLARSSL_SSL_SRV_C MBEDTLS_SSL_SRV_C -#endif -#if defined MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE -#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE -#endif -#if defined MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO -#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO -#endif -#if defined MBEDTLS_SSL_TLS_C -#define POLARSSL_SSL_TLS_C MBEDTLS_SSL_TLS_C -#endif -#if defined MBEDTLS_SSL_TRUNCATED_HMAC -#define POLARSSL_SSL_TRUNCATED_HMAC MBEDTLS_SSL_TRUNCATED_HMAC -#endif -#if defined MBEDTLS_THREADING_ALT -#define POLARSSL_THREADING_ALT MBEDTLS_THREADING_ALT -#endif -#if defined MBEDTLS_THREADING_C -#define POLARSSL_THREADING_C MBEDTLS_THREADING_C -#endif -#if defined MBEDTLS_THREADING_PTHREAD -#define POLARSSL_THREADING_PTHREAD MBEDTLS_THREADING_PTHREAD -#endif -#if defined MBEDTLS_TIMING_ALT -#define POLARSSL_TIMING_ALT MBEDTLS_TIMING_ALT -#endif -#if defined MBEDTLS_TIMING_C -#define POLARSSL_TIMING_C MBEDTLS_TIMING_C -#endif -#if defined MBEDTLS_VERSION_C -#define POLARSSL_VERSION_C MBEDTLS_VERSION_C -#endif -#if defined MBEDTLS_VERSION_FEATURES -#define POLARSSL_VERSION_FEATURES MBEDTLS_VERSION_FEATURES -#endif -#if defined MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 -#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 -#endif -#if defined MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION -#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION -#endif -#if defined MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE -#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE -#endif -#if defined MBEDTLS_X509_CHECK_KEY_USAGE -#define POLARSSL_X509_CHECK_KEY_USAGE MBEDTLS_X509_CHECK_KEY_USAGE -#endif -#if defined MBEDTLS_X509_CREATE_C -#define POLARSSL_X509_CREATE_C MBEDTLS_X509_CREATE_C -#endif -#if defined MBEDTLS_X509_CRL_PARSE_C -#define POLARSSL_X509_CRL_PARSE_C MBEDTLS_X509_CRL_PARSE_C -#endif -#if defined MBEDTLS_X509_CRT_PARSE_C -#define POLARSSL_X509_CRT_PARSE_C MBEDTLS_X509_CRT_PARSE_C -#endif -#if defined MBEDTLS_X509_CRT_WRITE_C -#define POLARSSL_X509_CRT_WRITE_C MBEDTLS_X509_CRT_WRITE_C -#endif -#if defined MBEDTLS_X509_CSR_PARSE_C -#define POLARSSL_X509_CSR_PARSE_C MBEDTLS_X509_CSR_PARSE_C -#endif -#if defined MBEDTLS_X509_CSR_WRITE_C -#define POLARSSL_X509_CSR_WRITE_C MBEDTLS_X509_CSR_WRITE_C -#endif -#if defined MBEDTLS_X509_MAX_INTERMEDIATE_CA -#define POLARSSL_X509_MAX_INTERMEDIATE_CA MBEDTLS_X509_MAX_INTERMEDIATE_CA -#endif -#if defined MBEDTLS_X509_RSASSA_PSS_SUPPORT -#define POLARSSL_X509_RSASSA_PSS_SUPPORT MBEDTLS_X509_RSASSA_PSS_SUPPORT -#endif -#if defined MBEDTLS_X509_USE_C -#define POLARSSL_X509_USE_C MBEDTLS_X509_USE_C -#endif -#if defined MBEDTLS_XTEA_ALT -#define POLARSSL_XTEA_ALT MBEDTLS_XTEA_ALT -#endif -#if defined MBEDTLS_XTEA_C -#define POLARSSL_XTEA_C MBEDTLS_XTEA_C -#endif -#if defined MBEDTLS_ZLIB_SUPPORT -#define POLARSSL_ZLIB_SUPPORT MBEDTLS_ZLIB_SUPPORT -#endif - -/* - * Misc names (macros, types, functions, enum constants...) - */ -#define AES_DECRYPT MBEDTLS_AES_DECRYPT -#define AES_ENCRYPT MBEDTLS_AES_ENCRYPT -#define ASN1_BIT_STRING MBEDTLS_ASN1_BIT_STRING -#define ASN1_BMP_STRING MBEDTLS_ASN1_BMP_STRING -#define ASN1_BOOLEAN MBEDTLS_ASN1_BOOLEAN -#define ASN1_CHK_ADD MBEDTLS_ASN1_CHK_ADD -#define ASN1_CONSTRUCTED MBEDTLS_ASN1_CONSTRUCTED -#define ASN1_CONTEXT_SPECIFIC MBEDTLS_ASN1_CONTEXT_SPECIFIC -#define ASN1_GENERALIZED_TIME MBEDTLS_ASN1_GENERALIZED_TIME -#define ASN1_IA5_STRING MBEDTLS_ASN1_IA5_STRING -#define ASN1_INTEGER MBEDTLS_ASN1_INTEGER -#define ASN1_NULL MBEDTLS_ASN1_NULL -#define ASN1_OCTET_STRING MBEDTLS_ASN1_OCTET_STRING -#define ASN1_OID MBEDTLS_ASN1_OID -#define ASN1_PRIMITIVE MBEDTLS_ASN1_PRIMITIVE -#define ASN1_PRINTABLE_STRING MBEDTLS_ASN1_PRINTABLE_STRING -#define ASN1_SEQUENCE MBEDTLS_ASN1_SEQUENCE -#define ASN1_SET MBEDTLS_ASN1_SET -#define ASN1_T61_STRING MBEDTLS_ASN1_T61_STRING -#define ASN1_UNIVERSAL_STRING MBEDTLS_ASN1_UNIVERSAL_STRING -#define ASN1_UTC_TIME MBEDTLS_ASN1_UTC_TIME -#define ASN1_UTF8_STRING MBEDTLS_ASN1_UTF8_STRING -#define BADCERT_CN_MISMATCH MBEDTLS_X509_BADCERT_CN_MISMATCH -#define BADCERT_EXPIRED MBEDTLS_X509_BADCERT_EXPIRED -#define BADCERT_FUTURE MBEDTLS_X509_BADCERT_FUTURE -#define BADCERT_MISSING MBEDTLS_X509_BADCERT_MISSING -#define BADCERT_NOT_TRUSTED MBEDTLS_X509_BADCERT_NOT_TRUSTED -#define BADCERT_OTHER MBEDTLS_X509_BADCERT_OTHER -#define BADCERT_REVOKED MBEDTLS_X509_BADCERT_REVOKED -#define BADCERT_SKIP_VERIFY MBEDTLS_X509_BADCERT_SKIP_VERIFY -#define BADCRL_EXPIRED MBEDTLS_X509_BADCRL_EXPIRED -#define BADCRL_FUTURE MBEDTLS_X509_BADCRL_FUTURE -#define BADCRL_NOT_TRUSTED MBEDTLS_X509_BADCRL_NOT_TRUSTED -#define BLOWFISH_BLOCKSIZE MBEDTLS_BLOWFISH_BLOCKSIZE -#define BLOWFISH_DECRYPT MBEDTLS_BLOWFISH_DECRYPT -#define BLOWFISH_ENCRYPT MBEDTLS_BLOWFISH_ENCRYPT -#define BLOWFISH_MAX_KEY MBEDTLS_BLOWFISH_MAX_KEY_BITS -#define BLOWFISH_MIN_KEY MBEDTLS_BLOWFISH_MIN_KEY_BITS -#define BLOWFISH_ROUNDS MBEDTLS_BLOWFISH_ROUNDS -#define CAMELLIA_DECRYPT MBEDTLS_CAMELLIA_DECRYPT -#define CAMELLIA_ENCRYPT MBEDTLS_CAMELLIA_ENCRYPT -#define COLLECT_SIZE MBEDTLS_HAVEGE_COLLECT_SIZE -#define CTR_DRBG_BLOCKSIZE MBEDTLS_CTR_DRBG_BLOCKSIZE -#define CTR_DRBG_ENTROPY_LEN MBEDTLS_CTR_DRBG_ENTROPY_LEN -#define CTR_DRBG_KEYBITS MBEDTLS_CTR_DRBG_KEYBITS -#define CTR_DRBG_KEYSIZE MBEDTLS_CTR_DRBG_KEYSIZE -#define CTR_DRBG_MAX_INPUT MBEDTLS_CTR_DRBG_MAX_INPUT -#define CTR_DRBG_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST -#define CTR_DRBG_MAX_SEED_INPUT MBEDTLS_CTR_DRBG_MAX_SEED_INPUT -#define CTR_DRBG_PR_OFF MBEDTLS_CTR_DRBG_PR_OFF -#define CTR_DRBG_PR_ON MBEDTLS_CTR_DRBG_PR_ON -#define CTR_DRBG_RESEED_INTERVAL MBEDTLS_CTR_DRBG_RESEED_INTERVAL -#define CTR_DRBG_SEEDLEN MBEDTLS_CTR_DRBG_SEEDLEN -#define DEPRECATED MBEDTLS_DEPRECATED -#define DES_DECRYPT MBEDTLS_DES_DECRYPT -#define DES_ENCRYPT MBEDTLS_DES_ENCRYPT -#define DES_KEY_SIZE MBEDTLS_DES_KEY_SIZE -#define ENTROPY_BLOCK_SIZE MBEDTLS_ENTROPY_BLOCK_SIZE -#define ENTROPY_MAX_GATHER MBEDTLS_ENTROPY_MAX_GATHER -#define ENTROPY_MAX_SEED_SIZE MBEDTLS_ENTROPY_MAX_SEED_SIZE -#define ENTROPY_MAX_SOURCES MBEDTLS_ENTROPY_MAX_SOURCES -#define ENTROPY_MIN_HARDCLOCK MBEDTLS_ENTROPY_MIN_HARDCLOCK -#define ENTROPY_MIN_HAVEGE MBEDTLS_ENTROPY_MIN_HAVEGE -#define ENTROPY_MIN_PLATFORM MBEDTLS_ENTROPY_MIN_PLATFORM -#define ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_SOURCE_MANUAL -#define EXT_AUTHORITY_KEY_IDENTIFIER MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER -#define EXT_BASIC_CONSTRAINTS MBEDTLS_X509_EXT_BASIC_CONSTRAINTS -#define EXT_CERTIFICATE_POLICIES MBEDTLS_X509_EXT_CERTIFICATE_POLICIES -#define EXT_CRL_DISTRIBUTION_POINTS MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS -#define EXT_EXTENDED_KEY_USAGE MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE -#define EXT_FRESHEST_CRL MBEDTLS_X509_EXT_FRESHEST_CRL -#define EXT_INIHIBIT_ANYPOLICY MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY -#define EXT_ISSUER_ALT_NAME MBEDTLS_X509_EXT_ISSUER_ALT_NAME -#define EXT_KEY_USAGE MBEDTLS_X509_EXT_KEY_USAGE -#define EXT_NAME_CONSTRAINTS MBEDTLS_X509_EXT_NAME_CONSTRAINTS -#define EXT_NS_CERT_TYPE MBEDTLS_X509_EXT_NS_CERT_TYPE -#define EXT_POLICY_CONSTRAINTS MBEDTLS_X509_EXT_POLICY_CONSTRAINTS -#define EXT_POLICY_MAPPINGS MBEDTLS_X509_EXT_POLICY_MAPPINGS -#define EXT_SUBJECT_ALT_NAME MBEDTLS_X509_EXT_SUBJECT_ALT_NAME -#define EXT_SUBJECT_DIRECTORY_ATTRS MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS -#define EXT_SUBJECT_KEY_IDENTIFIER MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER -#define GCM_DECRYPT MBEDTLS_GCM_DECRYPT -#define GCM_ENCRYPT MBEDTLS_GCM_ENCRYPT -#define KU_CRL_SIGN MBEDTLS_X509_KU_CRL_SIGN -#define KU_DATA_ENCIPHERMENT MBEDTLS_X509_KU_DATA_ENCIPHERMENT -#define KU_DIGITAL_SIGNATURE MBEDTLS_X509_KU_DIGITAL_SIGNATURE -#define KU_KEY_AGREEMENT MBEDTLS_X509_KU_KEY_AGREEMENT -#define KU_KEY_CERT_SIGN MBEDTLS_X509_KU_KEY_CERT_SIGN -#define KU_KEY_ENCIPHERMENT MBEDTLS_X509_KU_KEY_ENCIPHERMENT -#define KU_NON_REPUDIATION MBEDTLS_X509_KU_NON_REPUDIATION -#define LN_2_DIV_LN_10_SCALE100 MBEDTLS_LN_2_DIV_LN_10_SCALE100 -#define MEMORY_VERIFY_ALLOC MBEDTLS_MEMORY_VERIFY_ALLOC -#define MEMORY_VERIFY_ALWAYS MBEDTLS_MEMORY_VERIFY_ALWAYS -#define MEMORY_VERIFY_FREE MBEDTLS_MEMORY_VERIFY_FREE -#define MEMORY_VERIFY_NONE MBEDTLS_MEMORY_VERIFY_NONE -#define MPI_CHK MBEDTLS_MPI_CHK -#define NET_PROTO_TCP MBEDTLS_NET_PROTO_TCP -#define NET_PROTO_UDP MBEDTLS_NET_PROTO_UDP -#define NS_CERT_TYPE_EMAIL MBEDTLS_X509_NS_CERT_TYPE_EMAIL -#define NS_CERT_TYPE_EMAIL_CA MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA -#define NS_CERT_TYPE_OBJECT_SIGNING MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING -#define NS_CERT_TYPE_OBJECT_SIGNING_CA MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA -#define NS_CERT_TYPE_RESERVED MBEDTLS_X509_NS_CERT_TYPE_RESERVED -#define NS_CERT_TYPE_SSL_CA MBEDTLS_X509_NS_CERT_TYPE_SSL_CA -#define NS_CERT_TYPE_SSL_CLIENT MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT -#define NS_CERT_TYPE_SSL_SERVER MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER -#define OID_ANSI_X9_62 MBEDTLS_OID_ANSI_X9_62 -#define OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE -#define OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD -#define OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62_SIG -#define OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 -#define OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE -#define OID_AT MBEDTLS_OID_AT -#define OID_AT_CN MBEDTLS_OID_AT_CN -#define OID_AT_COUNTRY MBEDTLS_OID_AT_COUNTRY -#define OID_AT_DN_QUALIFIER MBEDTLS_OID_AT_DN_QUALIFIER -#define OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT_GENERATION_QUALIFIER -#define OID_AT_GIVEN_NAME MBEDTLS_OID_AT_GIVEN_NAME -#define OID_AT_INITIALS MBEDTLS_OID_AT_INITIALS -#define OID_AT_LOCALITY MBEDTLS_OID_AT_LOCALITY -#define OID_AT_ORGANIZATION MBEDTLS_OID_AT_ORGANIZATION -#define OID_AT_ORG_UNIT MBEDTLS_OID_AT_ORG_UNIT -#define OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT_POSTAL_ADDRESS -#define OID_AT_POSTAL_CODE MBEDTLS_OID_AT_POSTAL_CODE -#define OID_AT_PSEUDONYM MBEDTLS_OID_AT_PSEUDONYM -#define OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT_SERIAL_NUMBER -#define OID_AT_STATE MBEDTLS_OID_AT_STATE -#define OID_AT_SUR_NAME MBEDTLS_OID_AT_SUR_NAME -#define OID_AT_TITLE MBEDTLS_OID_AT_TITLE -#define OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT_UNIQUE_IDENTIFIER -#define OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER -#define OID_BASIC_CONSTRAINTS MBEDTLS_OID_BASIC_CONSTRAINTS -#define OID_CERTICOM MBEDTLS_OID_CERTICOM -#define OID_CERTIFICATE_POLICIES MBEDTLS_OID_CERTIFICATE_POLICIES -#define OID_CLIENT_AUTH MBEDTLS_OID_CLIENT_AUTH -#define OID_CMP MBEDTLS_OID_CMP -#define OID_CODE_SIGNING MBEDTLS_OID_CODE_SIGNING -#define OID_COUNTRY_US MBEDTLS_OID_COUNTRY_US -#define OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_CRL_DISTRIBUTION_POINTS -#define OID_CRL_NUMBER MBEDTLS_OID_CRL_NUMBER -#define OID_DES_CBC MBEDTLS_OID_DES_CBC -#define OID_DES_EDE3_CBC MBEDTLS_OID_DES_EDE3_CBC -#define OID_DIGEST_ALG_MD2 MBEDTLS_OID_DIGEST_ALG_MD2 -#define OID_DIGEST_ALG_MD4 MBEDTLS_OID_DIGEST_ALG_MD4 -#define OID_DIGEST_ALG_MD5 MBEDTLS_OID_DIGEST_ALG_MD5 -#define OID_DIGEST_ALG_SHA1 MBEDTLS_OID_DIGEST_ALG_SHA1 -#define OID_DIGEST_ALG_SHA224 MBEDTLS_OID_DIGEST_ALG_SHA224 -#define OID_DIGEST_ALG_SHA256 MBEDTLS_OID_DIGEST_ALG_SHA256 -#define OID_DIGEST_ALG_SHA384 MBEDTLS_OID_DIGEST_ALG_SHA384 -#define OID_DIGEST_ALG_SHA512 MBEDTLS_OID_DIGEST_ALG_SHA512 -#define OID_DOMAIN_COMPONENT MBEDTLS_OID_DOMAIN_COMPONENT -#define OID_ECDSA_SHA1 MBEDTLS_OID_ECDSA_SHA1 -#define OID_ECDSA_SHA224 MBEDTLS_OID_ECDSA_SHA224 -#define OID_ECDSA_SHA256 MBEDTLS_OID_ECDSA_SHA256 -#define OID_ECDSA_SHA384 MBEDTLS_OID_ECDSA_SHA384 -#define OID_ECDSA_SHA512 MBEDTLS_OID_ECDSA_SHA512 -#define OID_EC_ALG_ECDH MBEDTLS_OID_EC_ALG_ECDH -#define OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_EC_ALG_UNRESTRICTED -#define OID_EC_BRAINPOOL_V1 MBEDTLS_OID_EC_BRAINPOOL_V1 -#define OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_GRP_BP256R1 -#define OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_GRP_BP384R1 -#define OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_GRP_BP512R1 -#define OID_EC_GRP_SECP192K1 MBEDTLS_OID_EC_GRP_SECP192K1 -#define OID_EC_GRP_SECP192R1 MBEDTLS_OID_EC_GRP_SECP192R1 -#define OID_EC_GRP_SECP224K1 MBEDTLS_OID_EC_GRP_SECP224K1 -#define OID_EC_GRP_SECP224R1 MBEDTLS_OID_EC_GRP_SECP224R1 -#define OID_EC_GRP_SECP256K1 MBEDTLS_OID_EC_GRP_SECP256K1 -#define OID_EC_GRP_SECP256R1 MBEDTLS_OID_EC_GRP_SECP256R1 -#define OID_EC_GRP_SECP384R1 MBEDTLS_OID_EC_GRP_SECP384R1 -#define OID_EC_GRP_SECP521R1 MBEDTLS_OID_EC_GRP_SECP521R1 -#define OID_EMAIL_PROTECTION MBEDTLS_OID_EMAIL_PROTECTION -#define OID_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE -#define OID_FRESHEST_CRL MBEDTLS_OID_FRESHEST_CRL -#define OID_GOV MBEDTLS_OID_GOV -#define OID_HMAC_SHA1 MBEDTLS_OID_HMAC_SHA1 -#define OID_ID_CE MBEDTLS_OID_ID_CE -#define OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_INIHIBIT_ANYPOLICY -#define OID_ISO_CCITT_DS MBEDTLS_OID_ISO_CCITT_DS -#define OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ISO_IDENTIFIED_ORG -#define OID_ISO_ITU_COUNTRY MBEDTLS_OID_ISO_ITU_COUNTRY -#define OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_US_ORG -#define OID_ISO_MEMBER_BODIES MBEDTLS_OID_ISO_MEMBER_BODIES -#define OID_ISSUER_ALT_NAME MBEDTLS_OID_ISSUER_ALT_NAME -#define OID_KEY_USAGE MBEDTLS_OID_KEY_USAGE -#define OID_KP MBEDTLS_OID_KP -#define OID_MGF1 MBEDTLS_OID_MGF1 -#define OID_NAME_CONSTRAINTS MBEDTLS_OID_NAME_CONSTRAINTS -#define OID_NETSCAPE MBEDTLS_OID_NETSCAPE -#define OID_NS_BASE_URL MBEDTLS_OID_NS_BASE_URL -#define OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CA_POLICY_URL -#define OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CA_REVOCATION_URL -#define OID_NS_CERT MBEDTLS_OID_NS_CERT -#define OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_CERT_SEQUENCE -#define OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT_TYPE -#define OID_NS_COMMENT MBEDTLS_OID_NS_COMMENT -#define OID_NS_DATA_TYPE MBEDTLS_OID_NS_DATA_TYPE -#define OID_NS_RENEWAL_URL MBEDTLS_OID_NS_RENEWAL_URL -#define OID_NS_REVOCATION_URL MBEDTLS_OID_NS_REVOCATION_URL -#define OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_SSL_SERVER_NAME -#define OID_OCSP_SIGNING MBEDTLS_OID_OCSP_SIGNING -#define OID_OIW_SECSIG MBEDTLS_OID_OIW_SECSIG -#define OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG_ALG -#define OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_SHA1 -#define OID_ORGANIZATION MBEDTLS_OID_ORGANIZATION -#define OID_ORG_ANSI_X9_62 MBEDTLS_OID_ORG_ANSI_X9_62 -#define OID_ORG_CERTICOM MBEDTLS_OID_ORG_CERTICOM -#define OID_ORG_DOD MBEDTLS_OID_ORG_DOD -#define OID_ORG_GOV MBEDTLS_OID_ORG_GOV -#define OID_ORG_NETSCAPE MBEDTLS_OID_ORG_NETSCAPE -#define OID_ORG_OIW MBEDTLS_OID_ORG_OIW -#define OID_ORG_RSA_DATA_SECURITY MBEDTLS_OID_ORG_RSA_DATA_SECURITY -#define OID_ORG_TELETRUST MBEDTLS_OID_ORG_TELETRUST -#define OID_PKCS MBEDTLS_OID_PKCS -#define OID_PKCS1 MBEDTLS_OID_PKCS1 -#define OID_PKCS12 MBEDTLS_OID_PKCS12 -#define OID_PKCS12_PBE MBEDTLS_OID_PKCS12_PBE -#define OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC -#define OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC -#define OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC -#define OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC -#define OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 -#define OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 -#define OID_PKCS1_MD2 MBEDTLS_OID_PKCS1_MD2 -#define OID_PKCS1_MD4 MBEDTLS_OID_PKCS1_MD4 -#define OID_PKCS1_MD5 MBEDTLS_OID_PKCS1_MD5 -#define OID_PKCS1_RSA MBEDTLS_OID_PKCS1_RSA -#define OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1_SHA1 -#define OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1_SHA224 -#define OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1_SHA256 -#define OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1_SHA384 -#define OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1_SHA512 -#define OID_PKCS5 MBEDTLS_OID_PKCS5 -#define OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5_PBES2 -#define OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC -#define OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC -#define OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC -#define OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC -#define OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC -#define OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC -#define OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5_PBKDF2 -#define OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5_PBMAC1 -#define OID_PKCS9 MBEDTLS_OID_PKCS9 -#define OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9_CSR_EXT_REQ -#define OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9_EMAIL -#define OID_PKIX MBEDTLS_OID_PKIX -#define OID_POLICY_CONSTRAINTS MBEDTLS_OID_POLICY_CONSTRAINTS -#define OID_POLICY_MAPPINGS MBEDTLS_OID_POLICY_MAPPINGS -#define OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD -#define OID_RSASSA_PSS MBEDTLS_OID_RSASSA_PSS -#define OID_RSA_COMPANY MBEDTLS_OID_RSA_COMPANY -#define OID_RSA_SHA_OBS MBEDTLS_OID_RSA_SHA_OBS -#define OID_SERVER_AUTH MBEDTLS_OID_SERVER_AUTH -#define OID_SIZE MBEDTLS_OID_SIZE -#define OID_SUBJECT_ALT_NAME MBEDTLS_OID_SUBJECT_ALT_NAME -#define OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS -#define OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER -#define OID_TELETRUST MBEDTLS_OID_TELETRUST -#define OID_TIME_STAMPING MBEDTLS_OID_TIME_STAMPING -#define PADLOCK_ACE MBEDTLS_PADLOCK_ACE -#define PADLOCK_ALIGN16 MBEDTLS_PADLOCK_ALIGN16 -#define PADLOCK_PHE MBEDTLS_PADLOCK_PHE -#define PADLOCK_PMM MBEDTLS_PADLOCK_PMM -#define PADLOCK_RNG MBEDTLS_PADLOCK_RNG -#define PKCS12_DERIVE_IV MBEDTLS_PKCS12_DERIVE_IV -#define PKCS12_DERIVE_KEY MBEDTLS_PKCS12_DERIVE_KEY -#define PKCS12_DERIVE_MAC_KEY MBEDTLS_PKCS12_DERIVE_MAC_KEY -#define PKCS12_PBE_DECRYPT MBEDTLS_PKCS12_PBE_DECRYPT -#define PKCS12_PBE_ENCRYPT MBEDTLS_PKCS12_PBE_ENCRYPT -#define PKCS5_DECRYPT MBEDTLS_PKCS5_DECRYPT -#define PKCS5_ENCRYPT MBEDTLS_PKCS5_ENCRYPT -#define POLARSSL_AESNI_AES MBEDTLS_AESNI_AES -#define POLARSSL_AESNI_CLMUL MBEDTLS_AESNI_CLMUL -#define POLARSSL_AESNI_H MBEDTLS_AESNI_H -#define POLARSSL_AES_H MBEDTLS_AES_H -#define POLARSSL_ARC4_H MBEDTLS_ARC4_H -#define POLARSSL_ASN1_H MBEDTLS_ASN1_H -#define POLARSSL_ASN1_WRITE_H MBEDTLS_ASN1_WRITE_H -#define POLARSSL_BASE64_H MBEDTLS_BASE64_H -#define POLARSSL_BIGNUM_H MBEDTLS_BIGNUM_H -#define POLARSSL_BLOWFISH_H MBEDTLS_BLOWFISH_H -#define POLARSSL_BN_MUL_H MBEDTLS_BN_MUL_H -#define POLARSSL_CAMELLIA_H MBEDTLS_CAMELLIA_H -#define POLARSSL_CCM_H MBEDTLS_CCM_H -#define POLARSSL_CERTS_H MBEDTLS_CERTS_H -#define POLARSSL_CHECK_CONFIG_H MBEDTLS_CHECK_CONFIG_H -#define POLARSSL_CIPHERSUITE_NODTLS MBEDTLS_CIPHERSUITE_NODTLS -#define POLARSSL_CIPHERSUITE_SHORT_TAG MBEDTLS_CIPHERSUITE_SHORT_TAG -#define POLARSSL_CIPHERSUITE_WEAK MBEDTLS_CIPHERSUITE_WEAK -#define POLARSSL_CIPHER_AES_128_CBC MBEDTLS_CIPHER_AES_128_CBC -#define POLARSSL_CIPHER_AES_128_CCM MBEDTLS_CIPHER_AES_128_CCM -#define POLARSSL_CIPHER_AES_128_CFB128 MBEDTLS_CIPHER_AES_128_CFB128 -#define POLARSSL_CIPHER_AES_128_CTR MBEDTLS_CIPHER_AES_128_CTR -#define POLARSSL_CIPHER_AES_128_ECB MBEDTLS_CIPHER_AES_128_ECB -#define POLARSSL_CIPHER_AES_128_GCM MBEDTLS_CIPHER_AES_128_GCM -#define POLARSSL_CIPHER_AES_192_CBC MBEDTLS_CIPHER_AES_192_CBC -#define POLARSSL_CIPHER_AES_192_CCM MBEDTLS_CIPHER_AES_192_CCM -#define POLARSSL_CIPHER_AES_192_CFB128 MBEDTLS_CIPHER_AES_192_CFB128 -#define POLARSSL_CIPHER_AES_192_CTR MBEDTLS_CIPHER_AES_192_CTR -#define POLARSSL_CIPHER_AES_192_ECB MBEDTLS_CIPHER_AES_192_ECB -#define POLARSSL_CIPHER_AES_192_GCM MBEDTLS_CIPHER_AES_192_GCM -#define POLARSSL_CIPHER_AES_256_CBC MBEDTLS_CIPHER_AES_256_CBC -#define POLARSSL_CIPHER_AES_256_CCM MBEDTLS_CIPHER_AES_256_CCM -#define POLARSSL_CIPHER_AES_256_CFB128 MBEDTLS_CIPHER_AES_256_CFB128 -#define POLARSSL_CIPHER_AES_256_CTR MBEDTLS_CIPHER_AES_256_CTR -#define POLARSSL_CIPHER_AES_256_ECB MBEDTLS_CIPHER_AES_256_ECB -#define POLARSSL_CIPHER_AES_256_GCM MBEDTLS_CIPHER_AES_256_GCM -#define POLARSSL_CIPHER_ARC4_128 MBEDTLS_CIPHER_ARC4_128 -#define POLARSSL_CIPHER_BLOWFISH_CBC MBEDTLS_CIPHER_BLOWFISH_CBC -#define POLARSSL_CIPHER_BLOWFISH_CFB64 MBEDTLS_CIPHER_BLOWFISH_CFB64 -#define POLARSSL_CIPHER_BLOWFISH_CTR MBEDTLS_CIPHER_BLOWFISH_CTR -#define POLARSSL_CIPHER_BLOWFISH_ECB MBEDTLS_CIPHER_BLOWFISH_ECB -#define POLARSSL_CIPHER_CAMELLIA_128_CBC MBEDTLS_CIPHER_CAMELLIA_128_CBC -#define POLARSSL_CIPHER_CAMELLIA_128_CCM MBEDTLS_CIPHER_CAMELLIA_128_CCM -#define POLARSSL_CIPHER_CAMELLIA_128_CFB128 MBEDTLS_CIPHER_CAMELLIA_128_CFB128 -#define POLARSSL_CIPHER_CAMELLIA_128_CTR MBEDTLS_CIPHER_CAMELLIA_128_CTR -#define POLARSSL_CIPHER_CAMELLIA_128_ECB MBEDTLS_CIPHER_CAMELLIA_128_ECB -#define POLARSSL_CIPHER_CAMELLIA_128_GCM MBEDTLS_CIPHER_CAMELLIA_128_GCM -#define POLARSSL_CIPHER_CAMELLIA_192_CBC MBEDTLS_CIPHER_CAMELLIA_192_CBC -#define POLARSSL_CIPHER_CAMELLIA_192_CCM MBEDTLS_CIPHER_CAMELLIA_192_CCM -#define POLARSSL_CIPHER_CAMELLIA_192_CFB128 MBEDTLS_CIPHER_CAMELLIA_192_CFB128 -#define POLARSSL_CIPHER_CAMELLIA_192_CTR MBEDTLS_CIPHER_CAMELLIA_192_CTR -#define POLARSSL_CIPHER_CAMELLIA_192_ECB MBEDTLS_CIPHER_CAMELLIA_192_ECB -#define POLARSSL_CIPHER_CAMELLIA_192_GCM MBEDTLS_CIPHER_CAMELLIA_192_GCM -#define POLARSSL_CIPHER_CAMELLIA_256_CBC MBEDTLS_CIPHER_CAMELLIA_256_CBC -#define POLARSSL_CIPHER_CAMELLIA_256_CCM MBEDTLS_CIPHER_CAMELLIA_256_CCM -#define POLARSSL_CIPHER_CAMELLIA_256_CFB128 MBEDTLS_CIPHER_CAMELLIA_256_CFB128 -#define POLARSSL_CIPHER_CAMELLIA_256_CTR MBEDTLS_CIPHER_CAMELLIA_256_CTR -#define POLARSSL_CIPHER_CAMELLIA_256_ECB MBEDTLS_CIPHER_CAMELLIA_256_ECB -#define POLARSSL_CIPHER_CAMELLIA_256_GCM MBEDTLS_CIPHER_CAMELLIA_256_GCM -#define POLARSSL_CIPHER_DES_CBC MBEDTLS_CIPHER_DES_CBC -#define POLARSSL_CIPHER_DES_ECB MBEDTLS_CIPHER_DES_ECB -#define POLARSSL_CIPHER_DES_EDE3_CBC MBEDTLS_CIPHER_DES_EDE3_CBC -#define POLARSSL_CIPHER_DES_EDE3_ECB MBEDTLS_CIPHER_DES_EDE3_ECB -#define POLARSSL_CIPHER_DES_EDE_CBC MBEDTLS_CIPHER_DES_EDE_CBC -#define POLARSSL_CIPHER_DES_EDE_ECB MBEDTLS_CIPHER_DES_EDE_ECB -#define POLARSSL_CIPHER_H MBEDTLS_CIPHER_H -#define POLARSSL_CIPHER_ID_3DES MBEDTLS_CIPHER_ID_3DES -#define POLARSSL_CIPHER_ID_AES MBEDTLS_CIPHER_ID_AES -#define POLARSSL_CIPHER_ID_ARC4 MBEDTLS_CIPHER_ID_ARC4 -#define POLARSSL_CIPHER_ID_BLOWFISH MBEDTLS_CIPHER_ID_BLOWFISH -#define POLARSSL_CIPHER_ID_CAMELLIA MBEDTLS_CIPHER_ID_CAMELLIA -#define POLARSSL_CIPHER_ID_DES MBEDTLS_CIPHER_ID_DES -#define POLARSSL_CIPHER_ID_NONE MBEDTLS_CIPHER_ID_NONE -#define POLARSSL_CIPHER_ID_NULL MBEDTLS_CIPHER_ID_NULL -#define POLARSSL_CIPHER_MODE_AEAD MBEDTLS_CIPHER_MODE_AEAD -#define POLARSSL_CIPHER_MODE_STREAM MBEDTLS_CIPHER_MODE_STREAM -#define POLARSSL_CIPHER_MODE_WITH_PADDING MBEDTLS_CIPHER_MODE_WITH_PADDING -#define POLARSSL_CIPHER_NONE MBEDTLS_CIPHER_NONE -#define POLARSSL_CIPHER_NULL MBEDTLS_CIPHER_NULL -#define POLARSSL_CIPHER_VARIABLE_IV_LEN MBEDTLS_CIPHER_VARIABLE_IV_LEN -#define POLARSSL_CIPHER_VARIABLE_KEY_LEN MBEDTLS_CIPHER_VARIABLE_KEY_LEN -#define POLARSSL_CIPHER_WRAP_H MBEDTLS_CIPHER_WRAP_H -#define POLARSSL_CONFIG_H MBEDTLS_CONFIG_H -#define POLARSSL_CTR_DRBG_H MBEDTLS_CTR_DRBG_H -#define POLARSSL_DEBUG_H MBEDTLS_DEBUG_H -#define POLARSSL_DECRYPT MBEDTLS_DECRYPT -#define POLARSSL_DES_H MBEDTLS_DES_H -#define POLARSSL_DHM_H MBEDTLS_DHM_H -#define POLARSSL_DHM_RFC3526_MODP_2048_G MBEDTLS_DHM_RFC3526_MODP_2048_G -#define POLARSSL_DHM_RFC3526_MODP_2048_P MBEDTLS_DHM_RFC3526_MODP_2048_P -#define POLARSSL_DHM_RFC3526_MODP_3072_G MBEDTLS_DHM_RFC3526_MODP_3072_G -#define POLARSSL_DHM_RFC3526_MODP_3072_P MBEDTLS_DHM_RFC3526_MODP_3072_P -#define POLARSSL_DHM_RFC5114_MODP_2048_G MBEDTLS_DHM_RFC5114_MODP_2048_G -#define POLARSSL_DHM_RFC5114_MODP_2048_P MBEDTLS_DHM_RFC5114_MODP_2048_P -#define POLARSSL_ECDH_H MBEDTLS_ECDH_H -#define POLARSSL_ECDH_OURS MBEDTLS_ECDH_OURS -#define POLARSSL_ECDH_THEIRS MBEDTLS_ECDH_THEIRS -#define POLARSSL_ECDSA_H MBEDTLS_ECDSA_H -#define POLARSSL_ECP_DP_BP256R1 MBEDTLS_ECP_DP_BP256R1 -#define POLARSSL_ECP_DP_BP384R1 MBEDTLS_ECP_DP_BP384R1 -#define POLARSSL_ECP_DP_BP512R1 MBEDTLS_ECP_DP_BP512R1 -#define POLARSSL_ECP_DP_M255 MBEDTLS_ECP_DP_CURVE25519 -#define POLARSSL_ECP_DP_MAX MBEDTLS_ECP_DP_MAX -#define POLARSSL_ECP_DP_NONE MBEDTLS_ECP_DP_NONE -#define POLARSSL_ECP_DP_SECP192K1 MBEDTLS_ECP_DP_SECP192K1 -#define POLARSSL_ECP_DP_SECP192R1 MBEDTLS_ECP_DP_SECP192R1 -#define POLARSSL_ECP_DP_SECP224K1 MBEDTLS_ECP_DP_SECP224K1 -#define POLARSSL_ECP_DP_SECP224R1 MBEDTLS_ECP_DP_SECP224R1 -#define POLARSSL_ECP_DP_SECP256K1 MBEDTLS_ECP_DP_SECP256K1 -#define POLARSSL_ECP_DP_SECP256R1 MBEDTLS_ECP_DP_SECP256R1 -#define POLARSSL_ECP_DP_SECP384R1 MBEDTLS_ECP_DP_SECP384R1 -#define POLARSSL_ECP_DP_SECP521R1 MBEDTLS_ECP_DP_SECP521R1 -#define POLARSSL_ECP_H MBEDTLS_ECP_H -#define POLARSSL_ECP_MAX_BYTES MBEDTLS_ECP_MAX_BYTES -#define POLARSSL_ECP_MAX_PT_LEN MBEDTLS_ECP_MAX_PT_LEN -#define POLARSSL_ECP_PF_COMPRESSED MBEDTLS_ECP_PF_COMPRESSED -#define POLARSSL_ECP_PF_UNCOMPRESSED MBEDTLS_ECP_PF_UNCOMPRESSED -#define POLARSSL_ECP_TLS_NAMED_CURVE MBEDTLS_ECP_TLS_NAMED_CURVE -#define POLARSSL_ENCRYPT MBEDTLS_ENCRYPT -#define POLARSSL_ENTROPY_H MBEDTLS_ENTROPY_H -#define POLARSSL_ENTROPY_POLL_H MBEDTLS_ENTROPY_POLL_H -#define POLARSSL_ENTROPY_SHA256_ACCUMULATOR MBEDTLS_ENTROPY_SHA256_ACCUMULATOR -#define POLARSSL_ENTROPY_SHA512_ACCUMULATOR MBEDTLS_ENTROPY_SHA512_ACCUMULATOR -#define POLARSSL_ERROR_H MBEDTLS_ERROR_H -#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -#define POLARSSL_ERR_ASN1_BUF_TOO_SMALL MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -#define POLARSSL_ERR_ASN1_INVALID_DATA MBEDTLS_ERR_ASN1_INVALID_DATA -#define POLARSSL_ERR_ASN1_INVALID_LENGTH MBEDTLS_ERR_ASN1_INVALID_LENGTH -#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -#define POLARSSL_ERR_ASN1_MALLOC_FAILED MBEDTLS_ERR_ASN1_ALLOC_FAILED -#define POLARSSL_ERR_ASN1_OUT_OF_DATA MBEDTLS_ERR_ASN1_OUT_OF_DATA -#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -#define POLARSSL_ERR_BASE64_INVALID_CHARACTER MBEDTLS_ERR_BASE64_INVALID_CHARACTER -#define POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -#define POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH -#define POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -#define POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH -#define POLARSSL_ERR_CCM_AUTH_FAILED MBEDTLS_ERR_CCM_AUTH_FAILED -#define POLARSSL_ERR_CCM_BAD_INPUT MBEDTLS_ERR_CCM_BAD_INPUT -#define POLARSSL_ERR_CIPHER_ALLOC_FAILED MBEDTLS_ERR_CIPHER_ALLOC_FAILED -#define POLARSSL_ERR_CIPHER_AUTH_FAILED MBEDTLS_ERR_CIPHER_AUTH_FAILED -#define POLARSSL_ERR_CIPHER_BAD_INPUT_DATA MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -#define POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -#define POLARSSL_ERR_CIPHER_INVALID_PADDING MBEDTLS_ERR_CIPHER_INVALID_PADDING -#define POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -#define POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -#define POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -#define POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -#define POLARSSL_ERR_DHM_BAD_INPUT_DATA MBEDTLS_ERR_DHM_BAD_INPUT_DATA -#define POLARSSL_ERR_DHM_CALC_SECRET_FAILED MBEDTLS_ERR_DHM_CALC_SECRET_FAILED -#define POLARSSL_ERR_DHM_FILE_IO_ERROR MBEDTLS_ERR_DHM_FILE_IO_ERROR -#define POLARSSL_ERR_DHM_INVALID_FORMAT MBEDTLS_ERR_DHM_INVALID_FORMAT -#define POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED -#define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED -#define POLARSSL_ERR_DHM_MALLOC_FAILED MBEDTLS_ERR_DHM_ALLOC_FAILED -#define POLARSSL_ERR_DHM_READ_PARAMS_FAILED MBEDTLS_ERR_DHM_READ_PARAMS_FAILED -#define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED -#define POLARSSL_ERR_ECP_BAD_INPUT_DATA MBEDTLS_ERR_ECP_BAD_INPUT_DATA -#define POLARSSL_ERR_ECP_BUFFER_TOO_SMALL MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -#define POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_ECP_INVALID_KEY MBEDTLS_ERR_ECP_INVALID_KEY -#define POLARSSL_ERR_ECP_MALLOC_FAILED MBEDTLS_ERR_ECP_ALLOC_FAILED -#define POLARSSL_ERR_ECP_RANDOM_FAILED MBEDTLS_ERR_ECP_RANDOM_FAILED -#define POLARSSL_ERR_ECP_SIG_LEN_MISMATCH MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -#define POLARSSL_ERR_ECP_VERIFY_FAILED MBEDTLS_ERR_ECP_VERIFY_FAILED -#define POLARSSL_ERR_ENTROPY_FILE_IO_ERROR MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR -#define POLARSSL_ERR_ENTROPY_MAX_SOURCES MBEDTLS_ERR_ENTROPY_MAX_SOURCES -#define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED -#define POLARSSL_ERR_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -#define POLARSSL_ERR_GCM_AUTH_FAILED MBEDTLS_ERR_GCM_AUTH_FAILED -#define POLARSSL_ERR_GCM_BAD_INPUT MBEDTLS_ERR_GCM_BAD_INPUT -#define POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -#define POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR -#define POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG -#define POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -#define POLARSSL_ERR_MD_ALLOC_FAILED MBEDTLS_ERR_MD_ALLOC_FAILED -#define POLARSSL_ERR_MD_BAD_INPUT_DATA MBEDTLS_ERR_MD_BAD_INPUT_DATA -#define POLARSSL_ERR_MD_FEATURE_UNAVAILABLE MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_MD_FILE_IO_ERROR MBEDTLS_ERR_MD_FILE_IO_ERROR -#define POLARSSL_ERR_MPI_BAD_INPUT_DATA MBEDTLS_ERR_MPI_BAD_INPUT_DATA -#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -#define POLARSSL_ERR_MPI_FILE_IO_ERROR MBEDTLS_ERR_MPI_FILE_IO_ERROR -#define POLARSSL_ERR_MPI_INVALID_CHARACTER MBEDTLS_ERR_MPI_INVALID_CHARACTER -#define POLARSSL_ERR_MPI_MALLOC_FAILED MBEDTLS_ERR_MPI_ALLOC_FAILED -#define POLARSSL_ERR_MPI_NEGATIVE_VALUE MBEDTLS_ERR_MPI_NEGATIVE_VALUE -#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -#define POLARSSL_ERR_NET_ACCEPT_FAILED MBEDTLS_ERR_NET_ACCEPT_FAILED -#define POLARSSL_ERR_NET_BIND_FAILED MBEDTLS_ERR_NET_BIND_FAILED -#define POLARSSL_ERR_NET_CONNECT_FAILED MBEDTLS_ERR_NET_CONNECT_FAILED -#define POLARSSL_ERR_NET_CONN_RESET MBEDTLS_ERR_NET_CONN_RESET -#define POLARSSL_ERR_NET_LISTEN_FAILED MBEDTLS_ERR_NET_LISTEN_FAILED -#define POLARSSL_ERR_NET_RECV_FAILED MBEDTLS_ERR_NET_RECV_FAILED -#define POLARSSL_ERR_NET_SEND_FAILED MBEDTLS_ERR_NET_SEND_FAILED -#define POLARSSL_ERR_NET_SOCKET_FAILED MBEDTLS_ERR_NET_SOCKET_FAILED -#define POLARSSL_ERR_NET_TIMEOUT MBEDTLS_ERR_SSL_TIMEOUT -#define POLARSSL_ERR_NET_UNKNOWN_HOST MBEDTLS_ERR_NET_UNKNOWN_HOST -#define POLARSSL_ERR_NET_WANT_READ MBEDTLS_ERR_SSL_WANT_READ -#define POLARSSL_ERR_NET_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE -#define POLARSSL_ERR_OID_BUF_TOO_SMALL MBEDTLS_ERR_OID_BUF_TOO_SMALL -#define POLARSSL_ERR_OID_NOT_FOUND MBEDTLS_ERR_OID_NOT_FOUND -#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -#define POLARSSL_ERR_PEM_BAD_INPUT_DATA MBEDTLS_ERR_PEM_BAD_INPUT_DATA -#define POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_PEM_INVALID_DATA MBEDTLS_ERR_PEM_INVALID_DATA -#define POLARSSL_ERR_PEM_INVALID_ENC_IV MBEDTLS_ERR_PEM_INVALID_ENC_IV -#define POLARSSL_ERR_PEM_MALLOC_FAILED MBEDTLS_ERR_PEM_ALLOC_FAILED -#define POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT -#define POLARSSL_ERR_PEM_PASSWORD_MISMATCH MBEDTLS_ERR_PEM_PASSWORD_MISMATCH -#define POLARSSL_ERR_PEM_PASSWORD_REQUIRED MBEDTLS_ERR_PEM_PASSWORD_REQUIRED -#define POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG -#define POLARSSL_ERR_PKCS12_BAD_INPUT_DATA MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA -#define POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH -#define POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT -#define POLARSSL_ERR_PKCS5_BAD_INPUT_DATA MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA -#define POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_PKCS5_INVALID_FORMAT MBEDTLS_ERR_PKCS5_INVALID_FORMAT -#define POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH -#define POLARSSL_ERR_PK_BAD_INPUT_DATA MBEDTLS_ERR_PK_BAD_INPUT_DATA -#define POLARSSL_ERR_PK_FEATURE_UNAVAILABLE MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_PK_FILE_IO_ERROR MBEDTLS_ERR_PK_FILE_IO_ERROR -#define POLARSSL_ERR_PK_INVALID_ALG MBEDTLS_ERR_PK_INVALID_ALG -#define POLARSSL_ERR_PK_INVALID_PUBKEY MBEDTLS_ERR_PK_INVALID_PUBKEY -#define POLARSSL_ERR_PK_KEY_INVALID_FORMAT MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -#define POLARSSL_ERR_PK_KEY_INVALID_VERSION MBEDTLS_ERR_PK_KEY_INVALID_VERSION -#define POLARSSL_ERR_PK_MALLOC_FAILED MBEDTLS_ERR_PK_ALLOC_FAILED -#define POLARSSL_ERR_PK_PASSWORD_MISMATCH MBEDTLS_ERR_PK_PASSWORD_MISMATCH -#define POLARSSL_ERR_PK_PASSWORD_REQUIRED MBEDTLS_ERR_PK_PASSWORD_REQUIRED -#define POLARSSL_ERR_PK_SIG_LEN_MISMATCH MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -#define POLARSSL_ERR_PK_TYPE_MISMATCH MBEDTLS_ERR_PK_TYPE_MISMATCH -#define POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -#define POLARSSL_ERR_PK_UNKNOWN_PK_ALG MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -#define POLARSSL_ERR_RSA_BAD_INPUT_DATA MBEDTLS_ERR_RSA_BAD_INPUT_DATA -#define POLARSSL_ERR_RSA_INVALID_PADDING MBEDTLS_ERR_RSA_INVALID_PADDING -#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -#define POLARSSL_ERR_RSA_KEY_GEN_FAILED MBEDTLS_ERR_RSA_KEY_GEN_FAILED -#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -#define POLARSSL_ERR_RSA_PRIVATE_FAILED MBEDTLS_ERR_RSA_PRIVATE_FAILED -#define POLARSSL_ERR_RSA_PUBLIC_FAILED MBEDTLS_ERR_RSA_PUBLIC_FAILED -#define POLARSSL_ERR_RSA_RNG_FAILED MBEDTLS_ERR_RSA_RNG_FAILED -#define POLARSSL_ERR_RSA_VERIFY_FAILED MBEDTLS_ERR_RSA_VERIFY_FAILED -#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE -#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -#define POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO -#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -#define POLARSSL_ERR_SSL_BAD_HS_FINISHED MBEDTLS_ERR_SSL_BAD_HS_FINISHED -#define POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -#define POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION -#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO -#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -#define POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -#define POLARSSL_ERR_SSL_BAD_INPUT_DATA MBEDTLS_ERR_SSL_BAD_INPUT_DATA -#define POLARSSL_ERR_SSL_BUFFER_TOO_SMALL MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -#define POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED -#define POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED -#define POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE -#define POLARSSL_ERR_SSL_COMPRESSION_FAILED MBEDTLS_ERR_SSL_COMPRESSION_FAILED -#define POLARSSL_ERR_SSL_CONN_EOF MBEDTLS_ERR_SSL_CONN_EOF -#define POLARSSL_ERR_SSL_COUNTER_WRAPPING MBEDTLS_ERR_SSL_COUNTER_WRAPPING -#define POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -#define POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_SSL_HELLO_VERIFY_REQUIRED MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -#define POLARSSL_ERR_SSL_HW_ACCEL_FAILED MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -#define POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -#define POLARSSL_ERR_SSL_INTERNAL_ERROR MBEDTLS_ERR_SSL_INTERNAL_ERROR -#define POLARSSL_ERR_SSL_INVALID_MAC MBEDTLS_ERR_SSL_INVALID_MAC -#define POLARSSL_ERR_SSL_INVALID_RECORD MBEDTLS_ERR_SSL_INVALID_RECORD -#define POLARSSL_ERR_SSL_MALLOC_FAILED MBEDTLS_ERR_SSL_ALLOC_FAILED -#define POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN -#define POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -#define POLARSSL_ERR_SSL_NO_RNG MBEDTLS_ERR_SSL_NO_RNG -#define POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -#define POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -#define POLARSSL_ERR_SSL_PEER_VERIFY_FAILED MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED -#define POLARSSL_ERR_SSL_PK_TYPE_MISMATCH MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH -#define POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -#define POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -#define POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -#define POLARSSL_ERR_SSL_UNKNOWN_CIPHER MBEDTLS_ERR_SSL_UNKNOWN_CIPHER -#define POLARSSL_ERR_SSL_UNKNOWN_IDENTITY MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY -#define POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -#define POLARSSL_ERR_THREADING_BAD_INPUT_DATA MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -#define POLARSSL_ERR_THREADING_FEATURE_UNAVAILABLE MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_THREADING_MUTEX_ERROR MBEDTLS_ERR_THREADING_MUTEX_ERROR -#define POLARSSL_ERR_X509_BAD_INPUT_DATA MBEDTLS_ERR_X509_BAD_INPUT_DATA -#define POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT -#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED MBEDTLS_ERR_X509_CERT_VERIFY_FAILED -#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE -#define POLARSSL_ERR_X509_FILE_IO_ERROR MBEDTLS_ERR_X509_FILE_IO_ERROR -#define POLARSSL_ERR_X509_INVALID_ALG MBEDTLS_ERR_X509_INVALID_ALG -#define POLARSSL_ERR_X509_INVALID_DATE MBEDTLS_ERR_X509_INVALID_DATE -#define POLARSSL_ERR_X509_INVALID_EXTENSIONS MBEDTLS_ERR_X509_INVALID_EXTENSIONS -#define POLARSSL_ERR_X509_INVALID_FORMAT MBEDTLS_ERR_X509_INVALID_FORMAT -#define POLARSSL_ERR_X509_INVALID_NAME MBEDTLS_ERR_X509_INVALID_NAME -#define POLARSSL_ERR_X509_INVALID_SERIAL MBEDTLS_ERR_X509_INVALID_SERIAL -#define POLARSSL_ERR_X509_INVALID_SIGNATURE MBEDTLS_ERR_X509_INVALID_SIGNATURE -#define POLARSSL_ERR_X509_INVALID_VERSION MBEDTLS_ERR_X509_INVALID_VERSION -#define POLARSSL_ERR_X509_MALLOC_FAILED MBEDTLS_ERR_X509_ALLOC_FAILED -#define POLARSSL_ERR_X509_SIG_MISMATCH MBEDTLS_ERR_X509_SIG_MISMATCH -#define POLARSSL_ERR_X509_UNKNOWN_OID MBEDTLS_ERR_X509_UNKNOWN_OID -#define POLARSSL_ERR_X509_UNKNOWN_SIG_ALG MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG -#define POLARSSL_ERR_X509_UNKNOWN_VERSION MBEDTLS_ERR_X509_UNKNOWN_VERSION -#define POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH -#define POLARSSL_GCM_H MBEDTLS_GCM_H -#define POLARSSL_HAVEGE_H MBEDTLS_HAVEGE_H -#define POLARSSL_HAVE_INT32 MBEDTLS_HAVE_INT32 -#define POLARSSL_HAVE_INT64 MBEDTLS_HAVE_INT64 -#define POLARSSL_HAVE_UDBL MBEDTLS_HAVE_UDBL -#define POLARSSL_HAVE_X86 MBEDTLS_HAVE_X86 -#define POLARSSL_HAVE_X86_64 MBEDTLS_HAVE_X86_64 -#define POLARSSL_HMAC_DRBG_H MBEDTLS_HMAC_DRBG_H -#define POLARSSL_HMAC_DRBG_PR_OFF MBEDTLS_HMAC_DRBG_PR_OFF -#define POLARSSL_HMAC_DRBG_PR_ON MBEDTLS_HMAC_DRBG_PR_ON -#define POLARSSL_KEY_EXCHANGE_DHE_PSK MBEDTLS_KEY_EXCHANGE_DHE_PSK -#define POLARSSL_KEY_EXCHANGE_DHE_RSA MBEDTLS_KEY_EXCHANGE_DHE_RSA -#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA -#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK MBEDTLS_KEY_EXCHANGE_ECDHE_PSK -#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA MBEDTLS_KEY_EXCHANGE_ECDHE_RSA -#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA -#define POLARSSL_KEY_EXCHANGE_ECDH_RSA MBEDTLS_KEY_EXCHANGE_ECDH_RSA -#define POLARSSL_KEY_EXCHANGE_NONE MBEDTLS_KEY_EXCHANGE_NONE -#define POLARSSL_KEY_EXCHANGE_PSK MBEDTLS_KEY_EXCHANGE_PSK -#define POLARSSL_KEY_EXCHANGE_RSA MBEDTLS_KEY_EXCHANGE_RSA -#define POLARSSL_KEY_EXCHANGE_RSA_PSK MBEDTLS_KEY_EXCHANGE_RSA_PSK -#define POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED -#define POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED -#define POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED -#define POLARSSL_KEY_LENGTH_DES MBEDTLS_KEY_LENGTH_DES -#define POLARSSL_KEY_LENGTH_DES_EDE MBEDTLS_KEY_LENGTH_DES_EDE -#define POLARSSL_KEY_LENGTH_DES_EDE3 MBEDTLS_KEY_LENGTH_DES_EDE3 -#define POLARSSL_KEY_LENGTH_NONE MBEDTLS_KEY_LENGTH_NONE -#define POLARSSL_MAX_BLOCK_LENGTH MBEDTLS_MAX_BLOCK_LENGTH -#define POLARSSL_MAX_IV_LENGTH MBEDTLS_MAX_IV_LENGTH -#define POLARSSL_MD2_H MBEDTLS_MD2_H -#define POLARSSL_MD4_H MBEDTLS_MD4_H -#define POLARSSL_MD5_H MBEDTLS_MD5_H -#define POLARSSL_MD_H MBEDTLS_MD_H -#define POLARSSL_MD_MAX_SIZE MBEDTLS_MD_MAX_SIZE -#define POLARSSL_MD_MD2 MBEDTLS_MD_MD2 -#define POLARSSL_MD_MD4 MBEDTLS_MD_MD4 -#define POLARSSL_MD_MD5 MBEDTLS_MD_MD5 -#define POLARSSL_MD_NONE MBEDTLS_MD_NONE -#define POLARSSL_MD_RIPEMD160 MBEDTLS_MD_RIPEMD160 -#define POLARSSL_MD_SHA1 MBEDTLS_MD_SHA1 -#define POLARSSL_MD_SHA224 MBEDTLS_MD_SHA224 -#define POLARSSL_MD_SHA256 MBEDTLS_MD_SHA256 -#define POLARSSL_MD_SHA384 MBEDTLS_MD_SHA384 -#define POLARSSL_MD_SHA512 MBEDTLS_MD_SHA512 -#define POLARSSL_MD_WRAP_H MBEDTLS_MD_WRAP_H -#define POLARSSL_MEMORY_BUFFER_ALLOC_H MBEDTLS_MEMORY_BUFFER_ALLOC_H -#define POLARSSL_MODE_CBC MBEDTLS_MODE_CBC -#define POLARSSL_MODE_CCM MBEDTLS_MODE_CCM -#define POLARSSL_MODE_CFB MBEDTLS_MODE_CFB -#define POLARSSL_MODE_CTR MBEDTLS_MODE_CTR -#define POLARSSL_MODE_ECB MBEDTLS_MODE_ECB -#define POLARSSL_MODE_GCM MBEDTLS_MODE_GCM -#define POLARSSL_MODE_NONE MBEDTLS_MODE_NONE -#define POLARSSL_MODE_OFB MBEDTLS_MODE_OFB -#define POLARSSL_MODE_STREAM MBEDTLS_MODE_STREAM -#define POLARSSL_MPI_MAX_BITS MBEDTLS_MPI_MAX_BITS -#define POLARSSL_MPI_MAX_BITS_SCALE100 MBEDTLS_MPI_MAX_BITS_SCALE100 -#define POLARSSL_MPI_MAX_LIMBS MBEDTLS_MPI_MAX_LIMBS -#define POLARSSL_MPI_RW_BUFFER_SIZE MBEDTLS_MPI_RW_BUFFER_SIZE -#define POLARSSL_NET_H MBEDTLS_NET_SOCKETS_H -#define POLARSSL_NET_LISTEN_BACKLOG MBEDTLS_NET_LISTEN_BACKLOG -#define POLARSSL_OID_H MBEDTLS_OID_H -#define POLARSSL_OPERATION_NONE MBEDTLS_OPERATION_NONE -#define POLARSSL_PADDING_NONE MBEDTLS_PADDING_NONE -#define POLARSSL_PADDING_ONE_AND_ZEROS MBEDTLS_PADDING_ONE_AND_ZEROS -#define POLARSSL_PADDING_PKCS7 MBEDTLS_PADDING_PKCS7 -#define POLARSSL_PADDING_ZEROS MBEDTLS_PADDING_ZEROS -#define POLARSSL_PADDING_ZEROS_AND_LEN MBEDTLS_PADDING_ZEROS_AND_LEN -#define POLARSSL_PADLOCK_H MBEDTLS_PADLOCK_H -#define POLARSSL_PEM_H MBEDTLS_PEM_H -#define POLARSSL_PKCS11_H MBEDTLS_PKCS11_H -#define POLARSSL_PKCS12_H MBEDTLS_PKCS12_H -#define POLARSSL_PKCS5_H MBEDTLS_PKCS5_H -#define POLARSSL_PK_DEBUG_ECP MBEDTLS_PK_DEBUG_ECP -#define POLARSSL_PK_DEBUG_MAX_ITEMS MBEDTLS_PK_DEBUG_MAX_ITEMS -#define POLARSSL_PK_DEBUG_MPI MBEDTLS_PK_DEBUG_MPI -#define POLARSSL_PK_DEBUG_NONE MBEDTLS_PK_DEBUG_NONE -#define POLARSSL_PK_ECDSA MBEDTLS_PK_ECDSA -#define POLARSSL_PK_ECKEY MBEDTLS_PK_ECKEY -#define POLARSSL_PK_ECKEY_DH MBEDTLS_PK_ECKEY_DH -#define POLARSSL_PK_H MBEDTLS_PK_H -#define POLARSSL_PK_NONE MBEDTLS_PK_NONE -#define POLARSSL_PK_RSA MBEDTLS_PK_RSA -#define POLARSSL_PK_RSASSA_PSS MBEDTLS_PK_RSASSA_PSS -#define POLARSSL_PK_RSA_ALT MBEDTLS_PK_RSA_ALT -#define POLARSSL_PK_WRAP_H MBEDTLS_PK_WRAP_H -#define POLARSSL_PLATFORM_H MBEDTLS_PLATFORM_H -#define POLARSSL_PREMASTER_SIZE MBEDTLS_PREMASTER_SIZE -#define POLARSSL_RIPEMD160_H MBEDTLS_RIPEMD160_H -#define POLARSSL_RSA_H MBEDTLS_RSA_H -#define POLARSSL_SHA1_H MBEDTLS_SHA1_H -#define POLARSSL_SHA256_H MBEDTLS_SHA256_H -#define POLARSSL_SHA512_H MBEDTLS_SHA512_H -#define POLARSSL_SSL_CACHE_H MBEDTLS_SSL_CACHE_H -#define POLARSSL_SSL_CIPHERSUITES_H MBEDTLS_SSL_CIPHERSUITES_H -#define POLARSSL_SSL_COOKIE_H MBEDTLS_SSL_COOKIE_H -#define POLARSSL_SSL_H MBEDTLS_SSL_H -#define POLARSSL_THREADING_H MBEDTLS_THREADING_H -#define POLARSSL_THREADING_IMPL MBEDTLS_THREADING_IMPL -#define POLARSSL_TIMING_H MBEDTLS_TIMING_H -#define POLARSSL_VERSION_H MBEDTLS_VERSION_H -#define POLARSSL_VERSION_MAJOR MBEDTLS_VERSION_MAJOR -#define POLARSSL_VERSION_MINOR MBEDTLS_VERSION_MINOR -#define POLARSSL_VERSION_NUMBER MBEDTLS_VERSION_NUMBER -#define POLARSSL_VERSION_PATCH MBEDTLS_VERSION_PATCH -#define POLARSSL_VERSION_STRING MBEDTLS_VERSION_STRING -#define POLARSSL_VERSION_STRING_FULL MBEDTLS_VERSION_STRING_FULL -#define POLARSSL_X509_CRL_H MBEDTLS_X509_CRL_H -#define POLARSSL_X509_CRT_H MBEDTLS_X509_CRT_H -#define POLARSSL_X509_CSR_H MBEDTLS_X509_CSR_H -#define POLARSSL_X509_H MBEDTLS_X509_H -#define POLARSSL_XTEA_H MBEDTLS_XTEA_H -#define RSA_CRYPT MBEDTLS_RSA_CRYPT -#define RSA_PKCS_V15 MBEDTLS_RSA_PKCS_V15 -#define RSA_PKCS_V21 MBEDTLS_RSA_PKCS_V21 -#define RSA_PRIVATE MBEDTLS_RSA_PRIVATE -#define RSA_PUBLIC MBEDTLS_RSA_PUBLIC -#define RSA_SALT_LEN_ANY MBEDTLS_RSA_SALT_LEN_ANY -#define RSA_SIGN MBEDTLS_RSA_SIGN -#define SSL_ALERT_LEVEL_FATAL MBEDTLS_SSL_ALERT_LEVEL_FATAL -#define SSL_ALERT_LEVEL_WARNING MBEDTLS_SSL_ALERT_LEVEL_WARNING -#define SSL_ALERT_MSG_ACCESS_DENIED MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED -#define SSL_ALERT_MSG_BAD_CERT MBEDTLS_SSL_ALERT_MSG_BAD_CERT -#define SSL_ALERT_MSG_BAD_RECORD_MAC MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC -#define SSL_ALERT_MSG_CERT_EXPIRED MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED -#define SSL_ALERT_MSG_CERT_REVOKED MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED -#define SSL_ALERT_MSG_CERT_UNKNOWN MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN -#define SSL_ALERT_MSG_CLOSE_NOTIFY MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY -#define SSL_ALERT_MSG_DECODE_ERROR MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR -#define SSL_ALERT_MSG_DECOMPRESSION_FAILURE MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE -#define SSL_ALERT_MSG_DECRYPTION_FAILED MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED -#define SSL_ALERT_MSG_DECRYPT_ERROR MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR -#define SSL_ALERT_MSG_EXPORT_RESTRICTION MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION -#define SSL_ALERT_MSG_HANDSHAKE_FAILURE MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE -#define SSL_ALERT_MSG_ILLEGAL_PARAMETER MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER -#define SSL_ALERT_MSG_INAPROPRIATE_FALLBACK MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK -#define SSL_ALERT_MSG_INSUFFICIENT_SECURITY MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY -#define SSL_ALERT_MSG_INTERNAL_ERROR MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR -#define SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL -#define SSL_ALERT_MSG_NO_CERT MBEDTLS_SSL_ALERT_MSG_NO_CERT -#define SSL_ALERT_MSG_NO_RENEGOTIATION MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION -#define SSL_ALERT_MSG_PROTOCOL_VERSION MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION -#define SSL_ALERT_MSG_RECORD_OVERFLOW MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW -#define SSL_ALERT_MSG_UNEXPECTED_MESSAGE MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE -#define SSL_ALERT_MSG_UNKNOWN_CA MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA -#define SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY -#define SSL_ALERT_MSG_UNRECOGNIZED_NAME MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME -#define SSL_ALERT_MSG_UNSUPPORTED_CERT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT -#define SSL_ALERT_MSG_UNSUPPORTED_EXT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT -#define SSL_ALERT_MSG_USER_CANCELED MBEDTLS_SSL_ALERT_MSG_USER_CANCELED -#define SSL_ANTI_REPLAY_DISABLED MBEDTLS_SSL_ANTI_REPLAY_DISABLED -#define SSL_ANTI_REPLAY_ENABLED MBEDTLS_SSL_ANTI_REPLAY_ENABLED -#define SSL_ARC4_DISABLED MBEDTLS_SSL_ARC4_DISABLED -#define SSL_ARC4_ENABLED MBEDTLS_SSL_ARC4_ENABLED -#define SSL_BUFFER_LEN MBEDTLS_SSL_BUFFER_LEN -#define SSL_CACHE_DEFAULT_MAX_ENTRIES MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES -#define SSL_CACHE_DEFAULT_TIMEOUT MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT -#define SSL_CBC_RECORD_SPLITTING_DISABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED -#define SSL_CBC_RECORD_SPLITTING_ENABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED -#define SSL_CERTIFICATE_REQUEST MBEDTLS_SSL_CERTIFICATE_REQUEST -#define SSL_CERTIFICATE_VERIFY MBEDTLS_SSL_CERTIFICATE_VERIFY -#define SSL_CERT_TYPE_ECDSA_SIGN MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN -#define SSL_CERT_TYPE_RSA_SIGN MBEDTLS_SSL_CERT_TYPE_RSA_SIGN -#define SSL_CHANNEL_INBOUND MBEDTLS_SSL_CHANNEL_INBOUND -#define SSL_CHANNEL_OUTBOUND MBEDTLS_SSL_CHANNEL_OUTBOUND -#define SSL_CIPHERSUITES MBEDTLS_SSL_CIPHERSUITES -#define SSL_CLIENT_CERTIFICATE MBEDTLS_SSL_CLIENT_CERTIFICATE -#define SSL_CLIENT_CHANGE_CIPHER_SPEC MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC -#define SSL_CLIENT_FINISHED MBEDTLS_SSL_CLIENT_FINISHED -#define SSL_CLIENT_HELLO MBEDTLS_SSL_CLIENT_HELLO -#define SSL_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_CLIENT_KEY_EXCHANGE -#define SSL_COMPRESSION_ADD MBEDTLS_SSL_COMPRESSION_ADD -#define SSL_COMPRESS_DEFLATE MBEDTLS_SSL_COMPRESS_DEFLATE -#define SSL_COMPRESS_NULL MBEDTLS_SSL_COMPRESS_NULL -#define SSL_DEBUG_BUF MBEDTLS_SSL_DEBUG_BUF -#define SSL_DEBUG_CRT MBEDTLS_SSL_DEBUG_CRT -#define SSL_DEBUG_ECP MBEDTLS_SSL_DEBUG_ECP -#define SSL_DEBUG_MPI MBEDTLS_SSL_DEBUG_MPI -#define SSL_DEBUG_MSG MBEDTLS_SSL_DEBUG_MSG -#define SSL_DEBUG_RET MBEDTLS_SSL_DEBUG_RET -#define SSL_DEFAULT_TICKET_LIFETIME MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME -#define SSL_DTLS_TIMEOUT_DFL_MAX MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX -#define SSL_DTLS_TIMEOUT_DFL_MIN MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN -#define SSL_EMPTY_RENEGOTIATION_INFO MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO -#define SSL_ETM_DISABLED MBEDTLS_SSL_ETM_DISABLED -#define SSL_ETM_ENABLED MBEDTLS_SSL_ETM_ENABLED -#define SSL_EXTENDED_MS_DISABLED MBEDTLS_SSL_EXTENDED_MS_DISABLED -#define SSL_EXTENDED_MS_ENABLED MBEDTLS_SSL_EXTENDED_MS_ENABLED -#define SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV -#define SSL_FLUSH_BUFFERS MBEDTLS_SSL_FLUSH_BUFFERS -#define SSL_HANDSHAKE_OVER MBEDTLS_SSL_HANDSHAKE_OVER -#define SSL_HANDSHAKE_WRAPUP MBEDTLS_SSL_HANDSHAKE_WRAPUP -#define SSL_HASH_MD5 MBEDTLS_SSL_HASH_MD5 -#define SSL_HASH_NONE MBEDTLS_SSL_HASH_NONE -#define SSL_HASH_SHA1 MBEDTLS_SSL_HASH_SHA1 -#define SSL_HASH_SHA224 MBEDTLS_SSL_HASH_SHA224 -#define SSL_HASH_SHA256 MBEDTLS_SSL_HASH_SHA256 -#define SSL_HASH_SHA384 MBEDTLS_SSL_HASH_SHA384 -#define SSL_HASH_SHA512 MBEDTLS_SSL_HASH_SHA512 -#define SSL_HELLO_REQUEST MBEDTLS_SSL_HELLO_REQUEST -#define SSL_HS_CERTIFICATE MBEDTLS_SSL_HS_CERTIFICATE -#define SSL_HS_CERTIFICATE_REQUEST MBEDTLS_SSL_HS_CERTIFICATE_REQUEST -#define SSL_HS_CERTIFICATE_VERIFY MBEDTLS_SSL_HS_CERTIFICATE_VERIFY -#define SSL_HS_CLIENT_HELLO MBEDTLS_SSL_HS_CLIENT_HELLO -#define SSL_HS_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE -#define SSL_HS_FINISHED MBEDTLS_SSL_HS_FINISHED -#define SSL_HS_HELLO_REQUEST MBEDTLS_SSL_HS_HELLO_REQUEST -#define SSL_HS_HELLO_VERIFY_REQUEST MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST -#define SSL_HS_NEW_SESSION_TICKET MBEDTLS_SSL_HS_NEW_SESSION_TICKET -#define SSL_HS_SERVER_HELLO MBEDTLS_SSL_HS_SERVER_HELLO -#define SSL_HS_SERVER_HELLO_DONE MBEDTLS_SSL_HS_SERVER_HELLO_DONE -#define SSL_HS_SERVER_KEY_EXCHANGE MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE -#define SSL_INITIAL_HANDSHAKE MBEDTLS_SSL_INITIAL_HANDSHAKE -#define SSL_IS_CLIENT MBEDTLS_SSL_IS_CLIENT -#define SSL_IS_FALLBACK MBEDTLS_SSL_IS_FALLBACK -#define SSL_IS_NOT_FALLBACK MBEDTLS_SSL_IS_NOT_FALLBACK -#define SSL_IS_SERVER MBEDTLS_SSL_IS_SERVER -#define SSL_LEGACY_ALLOW_RENEGOTIATION MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION -#define SSL_LEGACY_BREAK_HANDSHAKE MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE -#define SSL_LEGACY_NO_RENEGOTIATION MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION -#define SSL_LEGACY_RENEGOTIATION MBEDTLS_SSL_LEGACY_RENEGOTIATION -#define SSL_MAC_ADD MBEDTLS_SSL_MAC_ADD -#define SSL_MAJOR_VERSION_3 MBEDTLS_SSL_MAJOR_VERSION_3 -#define SSL_MAX_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN -#define SSL_MAX_FRAG_LEN_1024 MBEDTLS_SSL_MAX_FRAG_LEN_1024 -#define SSL_MAX_FRAG_LEN_2048 MBEDTLS_SSL_MAX_FRAG_LEN_2048 -#define SSL_MAX_FRAG_LEN_4096 MBEDTLS_SSL_MAX_FRAG_LEN_4096 -#define SSL_MAX_FRAG_LEN_512 MBEDTLS_SSL_MAX_FRAG_LEN_512 -#define SSL_MAX_FRAG_LEN_INVALID MBEDTLS_SSL_MAX_FRAG_LEN_INVALID -#define SSL_MAX_FRAG_LEN_NONE MBEDTLS_SSL_MAX_FRAG_LEN_NONE -#define SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAX_MAJOR_VERSION -#define SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MAX_MINOR_VERSION -#define SSL_MINOR_VERSION_0 MBEDTLS_SSL_MINOR_VERSION_0 -#define SSL_MINOR_VERSION_1 MBEDTLS_SSL_MINOR_VERSION_1 -#define SSL_MINOR_VERSION_2 MBEDTLS_SSL_MINOR_VERSION_2 -#define SSL_MINOR_VERSION_3 MBEDTLS_SSL_MINOR_VERSION_3 -#define SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MIN_MAJOR_VERSION -#define SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MIN_MINOR_VERSION -#define SSL_MSG_ALERT MBEDTLS_SSL_MSG_ALERT -#define SSL_MSG_APPLICATION_DATA MBEDTLS_SSL_MSG_APPLICATION_DATA -#define SSL_MSG_CHANGE_CIPHER_SPEC MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC -#define SSL_MSG_HANDSHAKE MBEDTLS_SSL_MSG_HANDSHAKE -#define SSL_PADDING_ADD MBEDTLS_SSL_PADDING_ADD -#define SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION -#define SSL_RENEGOTIATION_DISABLED MBEDTLS_SSL_RENEGOTIATION_DISABLED -#define SSL_RENEGOTIATION_DONE MBEDTLS_SSL_RENEGOTIATION_DONE -#define SSL_RENEGOTIATION_ENABLED MBEDTLS_SSL_RENEGOTIATION_ENABLED -#define SSL_RENEGOTIATION_NOT_ENFORCED MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED -#define SSL_RENEGOTIATION_PENDING MBEDTLS_SSL_RENEGOTIATION_PENDING -#define SSL_RENEGO_MAX_RECORDS_DEFAULT MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT -#define SSL_RETRANS_FINISHED MBEDTLS_SSL_RETRANS_FINISHED -#define SSL_RETRANS_PREPARING MBEDTLS_SSL_RETRANS_PREPARING -#define SSL_RETRANS_SENDING MBEDTLS_SSL_RETRANS_SENDING -#define SSL_RETRANS_WAITING MBEDTLS_SSL_RETRANS_WAITING -#define SSL_SECURE_RENEGOTIATION MBEDTLS_SSL_SECURE_RENEGOTIATION -#define SSL_SERVER_CERTIFICATE MBEDTLS_SSL_SERVER_CERTIFICATE -#define SSL_SERVER_CHANGE_CIPHER_SPEC MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC -#define SSL_SERVER_FINISHED MBEDTLS_SSL_SERVER_FINISHED -#define SSL_SERVER_HELLO MBEDTLS_SSL_SERVER_HELLO -#define SSL_SERVER_HELLO_DONE MBEDTLS_SSL_SERVER_HELLO_DONE -#define SSL_SERVER_HELLO_VERIFY_REQUEST_SENT MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT -#define SSL_SERVER_KEY_EXCHANGE MBEDTLS_SSL_SERVER_KEY_EXCHANGE -#define SSL_SERVER_NEW_SESSION_TICKET MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET -#define SSL_SESSION_TICKETS_DISABLED MBEDTLS_SSL_SESSION_TICKETS_DISABLED -#define SSL_SESSION_TICKETS_ENABLED MBEDTLS_SSL_SESSION_TICKETS_ENABLED -#define SSL_SIG_ANON MBEDTLS_SSL_SIG_ANON -#define SSL_SIG_ECDSA MBEDTLS_SSL_SIG_ECDSA -#define SSL_SIG_RSA MBEDTLS_SSL_SIG_RSA -#define SSL_TRANSPORT_DATAGRAM MBEDTLS_SSL_TRANSPORT_DATAGRAM -#define SSL_TRANSPORT_STREAM MBEDTLS_SSL_TRANSPORT_STREAM -#define SSL_TRUNCATED_HMAC_LEN MBEDTLS_SSL_TRUNCATED_HMAC_LEN -#define SSL_TRUNC_HMAC_DISABLED MBEDTLS_SSL_TRUNC_HMAC_DISABLED -#define SSL_TRUNC_HMAC_ENABLED MBEDTLS_SSL_TRUNC_HMAC_ENABLED -#define SSL_VERIFY_DATA_MAX_LEN MBEDTLS_SSL_VERIFY_DATA_MAX_LEN -#define SSL_VERIFY_NONE MBEDTLS_SSL_VERIFY_NONE -#define SSL_VERIFY_OPTIONAL MBEDTLS_SSL_VERIFY_OPTIONAL -#define SSL_VERIFY_REQUIRED MBEDTLS_SSL_VERIFY_REQUIRED -#define TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA -#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA -#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 -#define TLS_DHE_PSK_WITH_AES_128_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM -#define TLS_DHE_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 -#define TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 -#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA -#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 -#define TLS_DHE_PSK_WITH_AES_256_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM -#define TLS_DHE_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 -#define TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 -#define TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 -#define TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_DHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA -#define TLS_DHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 -#define TLS_DHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 -#define TLS_DHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA -#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA -#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA -#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 -#define TLS_DHE_RSA_WITH_AES_128_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM -#define TLS_DHE_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 -#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 -#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA -#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 -#define TLS_DHE_RSA_WITH_AES_256_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM -#define TLS_DHE_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 -#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 -#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA -#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA -#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 -#define TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_DHE_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA -#define TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA -#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA -#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 -#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM -#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 -#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 -#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA -#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 -#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM -#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 -#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 -#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 -#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_ECDHE_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA -#define TLS_ECDHE_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA -#define TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA -#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA -#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 -#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA -#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 -#define TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 -#define TLS_ECDHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA -#define TLS_ECDHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 -#define TLS_ECDHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 -#define TLS_ECDHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA -#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA -#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA -#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 -#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 -#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA -#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 -#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 -#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 -#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_ECDHE_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA -#define TLS_ECDHE_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA -#define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA -#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA -#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 -#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 -#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA -#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 -#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 -#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 -#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_ECDH_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA -#define TLS_ECDH_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA -#define TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA -#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA -#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 -#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 -#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA -#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 -#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 -#define TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 -#define TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_ECDH_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA -#define TLS_ECDH_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA -#define TLS_EXT_ALPN MBEDTLS_TLS_EXT_ALPN -#define TLS_EXT_ENCRYPT_THEN_MAC MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC -#define TLS_EXT_EXTENDED_MASTER_SECRET MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET -#define TLS_EXT_MAX_FRAGMENT_LENGTH MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH -#define TLS_EXT_RENEGOTIATION_INFO MBEDTLS_TLS_EXT_RENEGOTIATION_INFO -#define TLS_EXT_SERVERNAME MBEDTLS_TLS_EXT_SERVERNAME -#define TLS_EXT_SERVERNAME_HOSTNAME MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME -#define TLS_EXT_SESSION_TICKET MBEDTLS_TLS_EXT_SESSION_TICKET -#define TLS_EXT_SIG_ALG MBEDTLS_TLS_EXT_SIG_ALG -#define TLS_EXT_SUPPORTED_ELLIPTIC_CURVES MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES -#define TLS_EXT_SUPPORTED_POINT_FORMATS MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS -#define TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT -#define TLS_EXT_TRUNCATED_HMAC MBEDTLS_TLS_EXT_TRUNCATED_HMAC -#define TLS_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA -#define TLS_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA -#define TLS_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 -#define TLS_PSK_WITH_AES_128_CCM MBEDTLS_TLS_PSK_WITH_AES_128_CCM -#define TLS_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 -#define TLS_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 -#define TLS_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA -#define TLS_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 -#define TLS_PSK_WITH_AES_256_CCM MBEDTLS_TLS_PSK_WITH_AES_256_CCM -#define TLS_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 -#define TLS_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 -#define TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 -#define TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_PSK_WITH_NULL_SHA MBEDTLS_TLS_PSK_WITH_NULL_SHA -#define TLS_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_PSK_WITH_NULL_SHA256 -#define TLS_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_PSK_WITH_NULL_SHA384 -#define TLS_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_PSK_WITH_RC4_128_SHA -#define TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA -#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA -#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 -#define TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 -#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA -#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 -#define TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 -#define TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 -#define TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_RSA_PSK_WITH_NULL_SHA MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA -#define TLS_RSA_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 -#define TLS_RSA_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 -#define TLS_RSA_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA -#define TLS_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA -#define TLS_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA -#define TLS_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 -#define TLS_RSA_WITH_AES_128_CCM MBEDTLS_TLS_RSA_WITH_AES_128_CCM -#define TLS_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 -#define TLS_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 -#define TLS_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA -#define TLS_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 -#define TLS_RSA_WITH_AES_256_CCM MBEDTLS_TLS_RSA_WITH_AES_256_CCM -#define TLS_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 -#define TLS_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 -#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA -#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 -#define TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 -#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA -#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 -#define TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 -#define TLS_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA -#define TLS_RSA_WITH_NULL_MD5 MBEDTLS_TLS_RSA_WITH_NULL_MD5 -#define TLS_RSA_WITH_NULL_SHA MBEDTLS_TLS_RSA_WITH_NULL_SHA -#define TLS_RSA_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_WITH_NULL_SHA256 -#define TLS_RSA_WITH_RC4_128_MD5 MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 -#define TLS_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_WITH_RC4_128_SHA -#define X509_CRT_VERSION_1 MBEDTLS_X509_CRT_VERSION_1 -#define X509_CRT_VERSION_2 MBEDTLS_X509_CRT_VERSION_2 -#define X509_CRT_VERSION_3 MBEDTLS_X509_CRT_VERSION_3 -#define X509_FORMAT_DER MBEDTLS_X509_FORMAT_DER -#define X509_FORMAT_PEM MBEDTLS_X509_FORMAT_PEM -#define X509_MAX_DN_NAME_SIZE MBEDTLS_X509_MAX_DN_NAME_SIZE -#define X509_RFC5280_MAX_SERIAL_LEN MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN -#define X509_RFC5280_UTC_TIME_LEN MBEDTLS_X509_RFC5280_UTC_TIME_LEN -#define XTEA_DECRYPT MBEDTLS_XTEA_DECRYPT -#define XTEA_ENCRYPT MBEDTLS_XTEA_ENCRYPT -#define _asn1_bitstring mbedtls_asn1_bitstring -#define _asn1_buf mbedtls_asn1_buf -#define _asn1_named_data mbedtls_asn1_named_data -#define _asn1_sequence mbedtls_asn1_sequence -#define _ssl_cache_context mbedtls_ssl_cache_context -#define _ssl_cache_entry mbedtls_ssl_cache_entry -#define _ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t -#define _ssl_context mbedtls_ssl_context -#define _ssl_flight_item mbedtls_ssl_flight_item -#define _ssl_handshake_params mbedtls_ssl_handshake_params -#define _ssl_key_cert mbedtls_ssl_key_cert -#define _ssl_premaster_secret mbedtls_ssl_premaster_secret -#define _ssl_session mbedtls_ssl_session -#define _ssl_transform mbedtls_ssl_transform -#define _x509_crl mbedtls_x509_crl -#define _x509_crl_entry mbedtls_x509_crl_entry -#define _x509_crt mbedtls_x509_crt -#define _x509_csr mbedtls_x509_csr -#define _x509_time mbedtls_x509_time -#define _x509write_cert mbedtls_x509write_cert -#define _x509write_csr mbedtls_x509write_csr -#define aes_context mbedtls_aes_context -#define aes_crypt_cbc mbedtls_aes_crypt_cbc -#define aes_crypt_cfb128 mbedtls_aes_crypt_cfb128 -#define aes_crypt_cfb8 mbedtls_aes_crypt_cfb8 -#define aes_crypt_ctr mbedtls_aes_crypt_ctr -#define aes_crypt_ecb mbedtls_aes_crypt_ecb -#define aes_free mbedtls_aes_free -#define aes_init mbedtls_aes_init -#define aes_self_test mbedtls_aes_self_test -#define aes_setkey_dec mbedtls_aes_setkey_dec -#define aes_setkey_enc mbedtls_aes_setkey_enc -#define aesni_crypt_ecb mbedtls_aesni_crypt_ecb -#define aesni_gcm_mult mbedtls_aesni_gcm_mult -#define aesni_inverse_key mbedtls_aesni_inverse_key -#define aesni_setkey_enc mbedtls_aesni_setkey_enc -#define aesni_supports mbedtls_aesni_has_support -#define alarmed mbedtls_timing_alarmed -#define arc4_context mbedtls_arc4_context -#define arc4_crypt mbedtls_arc4_crypt -#define arc4_free mbedtls_arc4_free -#define arc4_init mbedtls_arc4_init -#define arc4_self_test mbedtls_arc4_self_test -#define arc4_setup mbedtls_arc4_setup -#define asn1_bitstring mbedtls_asn1_bitstring -#define asn1_buf mbedtls_asn1_buf -#define asn1_find_named_data mbedtls_asn1_find_named_data -#define asn1_free_named_data mbedtls_asn1_free_named_data -#define asn1_free_named_data_list mbedtls_asn1_free_named_data_list -#define asn1_get_alg mbedtls_asn1_get_alg -#define asn1_get_alg_null mbedtls_asn1_get_alg_null -#define asn1_get_bitstring mbedtls_asn1_get_bitstring -#define asn1_get_bitstring_null mbedtls_asn1_get_bitstring_null -#define asn1_get_bool mbedtls_asn1_get_bool -#define asn1_get_int mbedtls_asn1_get_int -#define asn1_get_len mbedtls_asn1_get_len -#define asn1_get_mpi mbedtls_asn1_get_mpi -#define asn1_get_sequence_of mbedtls_asn1_get_sequence_of -#define asn1_get_tag mbedtls_asn1_get_tag -#define asn1_named_data mbedtls_asn1_named_data -#define asn1_sequence mbedtls_asn1_sequence -#define asn1_store_named_data mbedtls_asn1_store_named_data -#define asn1_write_algorithm_identifier mbedtls_asn1_write_algorithm_identifier -#define asn1_write_bitstring mbedtls_asn1_write_bitstring -#define asn1_write_bool mbedtls_asn1_write_bool -#define asn1_write_ia5_string mbedtls_asn1_write_ia5_string -#define asn1_write_int mbedtls_asn1_write_int -#define asn1_write_len mbedtls_asn1_write_len -#define asn1_write_mpi mbedtls_asn1_write_mpi -#define asn1_write_null mbedtls_asn1_write_null -#define asn1_write_octet_string mbedtls_asn1_write_octet_string -#define asn1_write_oid mbedtls_asn1_write_oid -#define asn1_write_printable_string mbedtls_asn1_write_printable_string -#define asn1_write_raw_buffer mbedtls_asn1_write_raw_buffer -#define asn1_write_tag mbedtls_asn1_write_tag -#define base64_decode mbedtls_base64_decode -#define base64_encode mbedtls_base64_encode -#define base64_self_test mbedtls_base64_self_test -#define blowfish_context mbedtls_blowfish_context -#define blowfish_crypt_cbc mbedtls_blowfish_crypt_cbc -#define blowfish_crypt_cfb64 mbedtls_blowfish_crypt_cfb64 -#define blowfish_crypt_ctr mbedtls_blowfish_crypt_ctr -#define blowfish_crypt_ecb mbedtls_blowfish_crypt_ecb -#define blowfish_free mbedtls_blowfish_free -#define blowfish_init mbedtls_blowfish_init -#define blowfish_setkey mbedtls_blowfish_setkey -#define camellia_context mbedtls_camellia_context -#define camellia_crypt_cbc mbedtls_camellia_crypt_cbc -#define camellia_crypt_cfb128 mbedtls_camellia_crypt_cfb128 -#define camellia_crypt_ctr mbedtls_camellia_crypt_ctr -#define camellia_crypt_ecb mbedtls_camellia_crypt_ecb -#define camellia_free mbedtls_camellia_free -#define camellia_init mbedtls_camellia_init -#define camellia_self_test mbedtls_camellia_self_test -#define camellia_setkey_dec mbedtls_camellia_setkey_dec -#define camellia_setkey_enc mbedtls_camellia_setkey_enc -#define ccm_auth_decrypt mbedtls_ccm_auth_decrypt -#define ccm_context mbedtls_ccm_context -#define ccm_encrypt_and_tag mbedtls_ccm_encrypt_and_tag -#define ccm_free mbedtls_ccm_free -#define ccm_init mbedtls_ccm_init -#define ccm_self_test mbedtls_ccm_self_test -#define cipher_auth_decrypt mbedtls_cipher_auth_decrypt -#define cipher_auth_encrypt mbedtls_cipher_auth_encrypt -#define cipher_base_t mbedtls_cipher_base_t -#define cipher_check_tag mbedtls_cipher_check_tag -#define cipher_context_t mbedtls_cipher_context_t -#define cipher_crypt mbedtls_cipher_crypt -#define cipher_definition_t mbedtls_cipher_definition_t -#define cipher_definitions mbedtls_cipher_definitions -#define cipher_finish mbedtls_cipher_finish -#define cipher_free mbedtls_cipher_free -#define cipher_get_block_size mbedtls_cipher_get_block_size -#define cipher_get_cipher_mode mbedtls_cipher_get_cipher_mode -#define cipher_get_iv_size mbedtls_cipher_get_iv_size -#define cipher_get_key_size mbedtls_cipher_get_key_bitlen -#define cipher_get_name mbedtls_cipher_get_name -#define cipher_get_operation mbedtls_cipher_get_operation -#define cipher_get_type mbedtls_cipher_get_type -#define cipher_id_t mbedtls_cipher_id_t -#define cipher_info_from_string mbedtls_cipher_info_from_string -#define cipher_info_from_type mbedtls_cipher_info_from_type -#define cipher_info_from_values mbedtls_cipher_info_from_values -#define cipher_info_t mbedtls_cipher_info_t -#define cipher_init mbedtls_cipher_init -#define cipher_init_ctx mbedtls_cipher_setup -#define cipher_list mbedtls_cipher_list -#define cipher_mode_t mbedtls_cipher_mode_t -#define cipher_padding_t mbedtls_cipher_padding_t -#define cipher_reset mbedtls_cipher_reset -#define cipher_set_iv mbedtls_cipher_set_iv -#define cipher_set_padding_mode mbedtls_cipher_set_padding_mode -#define cipher_setkey mbedtls_cipher_setkey -#define cipher_type_t mbedtls_cipher_type_t -#define cipher_update mbedtls_cipher_update -#define cipher_update_ad mbedtls_cipher_update_ad -#define cipher_write_tag mbedtls_cipher_write_tag -#define ctr_drbg_context mbedtls_ctr_drbg_context -#define ctr_drbg_free mbedtls_ctr_drbg_free -#define ctr_drbg_init mbedtls_ctr_drbg_init -#define ctr_drbg_random mbedtls_ctr_drbg_random -#define ctr_drbg_random_with_add mbedtls_ctr_drbg_random_with_add -#define ctr_drbg_reseed mbedtls_ctr_drbg_reseed -#define ctr_drbg_self_test mbedtls_ctr_drbg_self_test -#define ctr_drbg_set_entropy_len mbedtls_ctr_drbg_set_entropy_len -#define ctr_drbg_set_prediction_resistance mbedtls_ctr_drbg_set_prediction_resistance -#define ctr_drbg_set_reseed_interval mbedtls_ctr_drbg_set_reseed_interval -#define ctr_drbg_update mbedtls_ctr_drbg_update -#define ctr_drbg_update_seed_file mbedtls_ctr_drbg_update_seed_file -#define ctr_drbg_write_seed_file mbedtls_ctr_drbg_write_seed_file -#define debug_print_buf mbedtls_debug_print_buf -#define debug_print_crt mbedtls_debug_print_crt -#define debug_print_ecp mbedtls_debug_print_ecp -#define debug_print_mpi mbedtls_debug_print_mpi -#define debug_print_msg mbedtls_debug_print_msg -#define debug_print_ret mbedtls_debug_print_ret -#define debug_set_threshold mbedtls_debug_set_threshold -#define des3_context mbedtls_des3_context -#define des3_crypt_cbc mbedtls_des3_crypt_cbc -#define des3_crypt_ecb mbedtls_des3_crypt_ecb -#define des3_free mbedtls_des3_free -#define des3_init mbedtls_des3_init -#define des3_set2key_dec mbedtls_des3_set2key_dec -#define des3_set2key_enc mbedtls_des3_set2key_enc -#define des3_set3key_dec mbedtls_des3_set3key_dec -#define des3_set3key_enc mbedtls_des3_set3key_enc -#define des_context mbedtls_des_context -#define des_crypt_cbc mbedtls_des_crypt_cbc -#define des_crypt_ecb mbedtls_des_crypt_ecb -#define des_free mbedtls_des_free -#define des_init mbedtls_des_init -#define des_key_check_key_parity mbedtls_des_key_check_key_parity -#define des_key_check_weak mbedtls_des_key_check_weak -#define des_key_set_parity mbedtls_des_key_set_parity -#define des_self_test mbedtls_des_self_test -#define des_setkey_dec mbedtls_des_setkey_dec -#define des_setkey_enc mbedtls_des_setkey_enc -#define dhm_calc_secret mbedtls_dhm_calc_secret -#define dhm_context mbedtls_dhm_context -#define dhm_free mbedtls_dhm_free -#define dhm_init mbedtls_dhm_init -#define dhm_make_params mbedtls_dhm_make_params -#define dhm_make_public mbedtls_dhm_make_public -#define dhm_parse_dhm mbedtls_dhm_parse_dhm -#define dhm_parse_dhmfile mbedtls_dhm_parse_dhmfile -#define dhm_read_params mbedtls_dhm_read_params -#define dhm_read_public mbedtls_dhm_read_public -#define dhm_self_test mbedtls_dhm_self_test -#define ecdh_calc_secret mbedtls_ecdh_calc_secret -#define ecdh_compute_shared mbedtls_ecdh_compute_shared -#define ecdh_context mbedtls_ecdh_context -#define ecdh_free mbedtls_ecdh_free -#define ecdh_gen_public mbedtls_ecdh_gen_public -#define ecdh_get_params mbedtls_ecdh_get_params -#define ecdh_init mbedtls_ecdh_init -#define ecdh_make_params mbedtls_ecdh_make_params -#define ecdh_make_public mbedtls_ecdh_make_public -#define ecdh_read_params mbedtls_ecdh_read_params -#define ecdh_read_public mbedtls_ecdh_read_public -#define ecdh_side mbedtls_ecdh_side -#define ecdsa_context mbedtls_ecdsa_context -#define ecdsa_free mbedtls_ecdsa_free -#define ecdsa_from_keypair mbedtls_ecdsa_from_keypair -#define ecdsa_genkey mbedtls_ecdsa_genkey -#define ecdsa_info mbedtls_ecdsa_info -#define ecdsa_init mbedtls_ecdsa_init -#define ecdsa_read_signature mbedtls_ecdsa_read_signature -#define ecdsa_sign mbedtls_ecdsa_sign -#define ecdsa_sign_det mbedtls_ecdsa_sign_det -#define ecdsa_verify mbedtls_ecdsa_verify -#define ecdsa_write_signature mbedtls_ecdsa_write_signature -#define ecdsa_write_signature_det mbedtls_ecdsa_write_signature_det -#define eckey_info mbedtls_eckey_info -#define eckeydh_info mbedtls_eckeydh_info -#define ecp_check_privkey mbedtls_ecp_check_privkey -#define ecp_check_pub_priv mbedtls_ecp_check_pub_priv -#define ecp_check_pubkey mbedtls_ecp_check_pubkey -#define ecp_copy mbedtls_ecp_copy -#define ecp_curve_info mbedtls_ecp_curve_info -#define ecp_curve_info_from_grp_id mbedtls_ecp_curve_info_from_grp_id -#define ecp_curve_info_from_name mbedtls_ecp_curve_info_from_name -#define ecp_curve_info_from_tls_id mbedtls_ecp_curve_info_from_tls_id -#define ecp_curve_list mbedtls_ecp_curve_list -#define ecp_gen_key mbedtls_ecp_gen_key -#define ecp_gen_keypair mbedtls_ecp_gen_keypair -#define ecp_group mbedtls_ecp_group -#define ecp_group_copy mbedtls_ecp_group_copy -#define ecp_group_free mbedtls_ecp_group_free -#define ecp_group_id mbedtls_ecp_group_id -#define ecp_group_init mbedtls_ecp_group_init -#define ecp_grp_id_list mbedtls_ecp_grp_id_list -#define ecp_is_zero mbedtls_ecp_is_zero -#define ecp_keypair mbedtls_ecp_keypair -#define ecp_keypair_free mbedtls_ecp_keypair_free -#define ecp_keypair_init mbedtls_ecp_keypair_init -#define ecp_mul mbedtls_ecp_mul -#define ecp_point mbedtls_ecp_point -#define ecp_point_free mbedtls_ecp_point_free -#define ecp_point_init mbedtls_ecp_point_init -#define ecp_point_read_binary mbedtls_ecp_point_read_binary -#define ecp_point_read_string mbedtls_ecp_point_read_string -#define ecp_point_write_binary mbedtls_ecp_point_write_binary -#define ecp_self_test mbedtls_ecp_self_test -#define ecp_set_zero mbedtls_ecp_set_zero -#define ecp_tls_read_group mbedtls_ecp_tls_read_group -#define ecp_tls_read_point mbedtls_ecp_tls_read_point -#define ecp_tls_write_group mbedtls_ecp_tls_write_group -#define ecp_tls_write_point mbedtls_ecp_tls_write_point -#define ecp_use_known_dp mbedtls_ecp_group_load -#define entropy_add_source mbedtls_entropy_add_source -#define entropy_context mbedtls_entropy_context -#define entropy_free mbedtls_entropy_free -#define entropy_func mbedtls_entropy_func -#define entropy_gather mbedtls_entropy_gather -#define entropy_init mbedtls_entropy_init -#define entropy_self_test mbedtls_entropy_self_test -#define entropy_update_manual mbedtls_entropy_update_manual -#define entropy_update_seed_file mbedtls_entropy_update_seed_file -#define entropy_write_seed_file mbedtls_entropy_write_seed_file -#define error_strerror mbedtls_strerror -#define f_source_ptr mbedtls_entropy_f_source_ptr -#define gcm_auth_decrypt mbedtls_gcm_auth_decrypt -#define gcm_context mbedtls_gcm_context -#define gcm_crypt_and_tag mbedtls_gcm_crypt_and_tag -#define gcm_finish mbedtls_gcm_finish -#define gcm_free mbedtls_gcm_free -#define gcm_init mbedtls_gcm_init -#define gcm_self_test mbedtls_gcm_self_test -#define gcm_starts mbedtls_gcm_starts -#define gcm_update mbedtls_gcm_update -#define get_timer mbedtls_timing_get_timer -#define hardclock mbedtls_timing_hardclock -#define hardclock_poll mbedtls_hardclock_poll -#define havege_free mbedtls_havege_free -#define havege_init mbedtls_havege_init -#define havege_poll mbedtls_havege_poll -#define havege_random mbedtls_havege_random -#define havege_state mbedtls_havege_state -#define hmac_drbg_context mbedtls_hmac_drbg_context -#define hmac_drbg_free mbedtls_hmac_drbg_free -#define hmac_drbg_init mbedtls_hmac_drbg_init -#define hmac_drbg_random mbedtls_hmac_drbg_random -#define hmac_drbg_random_with_add mbedtls_hmac_drbg_random_with_add -#define hmac_drbg_reseed mbedtls_hmac_drbg_reseed -#define hmac_drbg_self_test mbedtls_hmac_drbg_self_test -#define hmac_drbg_set_entropy_len mbedtls_hmac_drbg_set_entropy_len -#define hmac_drbg_set_prediction_resistance mbedtls_hmac_drbg_set_prediction_resistance -#define hmac_drbg_set_reseed_interval mbedtls_hmac_drbg_set_reseed_interval -#define hmac_drbg_update mbedtls_hmac_drbg_update -#define hmac_drbg_update_seed_file mbedtls_hmac_drbg_update_seed_file -#define hmac_drbg_write_seed_file mbedtls_hmac_drbg_write_seed_file -#define hr_time mbedtls_timing_hr_time -#define key_exchange_type_t mbedtls_key_exchange_type_t -#define md mbedtls_md -#define md2 mbedtls_md2 -#define md2_context mbedtls_md2_context -#define md2_finish mbedtls_md2_finish -#define md2_free mbedtls_md2_free -#define md2_info mbedtls_md2_info -#define md2_init mbedtls_md2_init -#define md2_process mbedtls_md2_process -#define md2_self_test mbedtls_md2_self_test -#define md2_starts mbedtls_md2_starts -#define md2_update mbedtls_md2_update -#define md4 mbedtls_md4 -#define md4_context mbedtls_md4_context -#define md4_finish mbedtls_md4_finish -#define md4_free mbedtls_md4_free -#define md4_info mbedtls_md4_info -#define md4_init mbedtls_md4_init -#define md4_process mbedtls_md4_process -#define md4_self_test mbedtls_md4_self_test -#define md4_starts mbedtls_md4_starts -#define md4_update mbedtls_md4_update -#define md5 mbedtls_md5 -#define md5_context mbedtls_md5_context -#define md5_finish mbedtls_md5_finish -#define md5_free mbedtls_md5_free -#define md5_info mbedtls_md5_info -#define md5_init mbedtls_md5_init -#define md5_process mbedtls_md5_process -#define md5_self_test mbedtls_md5_self_test -#define md5_starts mbedtls_md5_starts -#define md5_update mbedtls_md5_update -#define md_context_t mbedtls_md_context_t -#define md_file mbedtls_md_file -#define md_finish mbedtls_md_finish -#define md_free mbedtls_md_free -#define md_get_name mbedtls_md_get_name -#define md_get_size mbedtls_md_get_size -#define md_get_type mbedtls_md_get_type -#define md_hmac mbedtls_md_hmac -#define md_hmac_finish mbedtls_md_hmac_finish -#define md_hmac_reset mbedtls_md_hmac_reset -#define md_hmac_starts mbedtls_md_hmac_starts -#define md_hmac_update mbedtls_md_hmac_update -#define md_info_from_string mbedtls_md_info_from_string -#define md_info_from_type mbedtls_md_info_from_type -#define md_info_t mbedtls_md_info_t -#define md_init mbedtls_md_init -#define md_init_ctx mbedtls_md_init_ctx -#define md_list mbedtls_md_list -#define md_process mbedtls_md_process -#define md_starts mbedtls_md_starts -#define md_type_t mbedtls_md_type_t -#define md_update mbedtls_md_update -#define memory_buffer_alloc_cur_get mbedtls_memory_buffer_alloc_cur_get -#define memory_buffer_alloc_free mbedtls_memory_buffer_alloc_free -#define memory_buffer_alloc_init mbedtls_memory_buffer_alloc_init -#define memory_buffer_alloc_max_get mbedtls_memory_buffer_alloc_max_get -#define memory_buffer_alloc_max_reset mbedtls_memory_buffer_alloc_max_reset -#define memory_buffer_alloc_self_test mbedtls_memory_buffer_alloc_self_test -#define memory_buffer_alloc_status mbedtls_memory_buffer_alloc_status -#define memory_buffer_alloc_verify mbedtls_memory_buffer_alloc_verify -#define memory_buffer_set_verify mbedtls_memory_buffer_set_verify -#define mpi mbedtls_mpi -#define mpi_add_abs mbedtls_mpi_add_abs -#define mpi_add_int mbedtls_mpi_add_int -#define mpi_add_mpi mbedtls_mpi_add_mpi -#define mpi_cmp_abs mbedtls_mpi_cmp_abs -#define mpi_cmp_int mbedtls_mpi_cmp_int -#define mpi_cmp_mpi mbedtls_mpi_cmp_mpi -#define mpi_copy mbedtls_mpi_copy -#define mpi_div_int mbedtls_mpi_div_int -#define mpi_div_mpi mbedtls_mpi_div_mpi -#define mpi_exp_mod mbedtls_mpi_exp_mod -#define mpi_fill_random mbedtls_mpi_fill_random -#define mpi_free mbedtls_mpi_free -#define mpi_gcd mbedtls_mpi_gcd -#define mpi_gen_prime mbedtls_mpi_gen_prime -#define mpi_get_bit mbedtls_mpi_get_bit -#define mpi_grow mbedtls_mpi_grow -#define mpi_init mbedtls_mpi_init -#define mpi_inv_mod mbedtls_mpi_inv_mod -#define mpi_is_prime mbedtls_mpi_is_prime -#define mpi_lsb mbedtls_mpi_lsb -#define mpi_lset mbedtls_mpi_lset -#define mpi_mod_int mbedtls_mpi_mod_int -#define mpi_mod_mpi mbedtls_mpi_mod_mpi -#define mpi_msb mbedtls_mpi_bitlen -#define mpi_mul_int mbedtls_mpi_mul_int -#define mpi_mul_mpi mbedtls_mpi_mul_mpi -#define mpi_read_binary mbedtls_mpi_read_binary -#define mpi_read_file mbedtls_mpi_read_file -#define mpi_read_string mbedtls_mpi_read_string -#define mpi_safe_cond_assign mbedtls_mpi_safe_cond_assign -#define mpi_safe_cond_swap mbedtls_mpi_safe_cond_swap -#define mpi_self_test mbedtls_mpi_self_test -#define mpi_set_bit mbedtls_mpi_set_bit -#define mpi_shift_l mbedtls_mpi_shift_l -#define mpi_shift_r mbedtls_mpi_shift_r -#define mpi_shrink mbedtls_mpi_shrink -#define mpi_size mbedtls_mpi_size -#define mpi_sub_abs mbedtls_mpi_sub_abs -#define mpi_sub_int mbedtls_mpi_sub_int -#define mpi_sub_mpi mbedtls_mpi_sub_mpi -#define mpi_swap mbedtls_mpi_swap -#define mpi_write_binary mbedtls_mpi_write_binary -#define mpi_write_file mbedtls_mpi_write_file -#define mpi_write_string mbedtls_mpi_write_string -#define net_accept mbedtls_net_accept -#define net_bind mbedtls_net_bind -#define net_close mbedtls_net_free -#define net_connect mbedtls_net_connect -#define net_recv mbedtls_net_recv -#define net_recv_timeout mbedtls_net_recv_timeout -#define net_send mbedtls_net_send -#define net_set_block mbedtls_net_set_block -#define net_set_nonblock mbedtls_net_set_nonblock -#define net_usleep mbedtls_net_usleep -#define oid_descriptor_t mbedtls_oid_descriptor_t -#define oid_get_attr_short_name mbedtls_oid_get_attr_short_name -#define oid_get_cipher_alg mbedtls_oid_get_cipher_alg -#define oid_get_ec_grp mbedtls_oid_get_ec_grp -#define oid_get_extended_key_usage mbedtls_oid_get_extended_key_usage -#define oid_get_md_alg mbedtls_oid_get_md_alg -#define oid_get_numeric_string mbedtls_oid_get_numeric_string -#define oid_get_oid_by_ec_grp mbedtls_oid_get_oid_by_ec_grp -#define oid_get_oid_by_md mbedtls_oid_get_oid_by_md -#define oid_get_oid_by_pk_alg mbedtls_oid_get_oid_by_pk_alg -#define oid_get_oid_by_sig_alg mbedtls_oid_get_oid_by_sig_alg -#define oid_get_pk_alg mbedtls_oid_get_pk_alg -#define oid_get_pkcs12_pbe_alg mbedtls_oid_get_pkcs12_pbe_alg -#define oid_get_sig_alg mbedtls_oid_get_sig_alg -#define oid_get_sig_alg_desc mbedtls_oid_get_sig_alg_desc -#define oid_get_x509_ext_type mbedtls_oid_get_x509_ext_type -#define operation_t mbedtls_operation_t -#define padlock_supports mbedtls_padlock_has_support -#define padlock_xcryptcbc mbedtls_padlock_xcryptcbc -#define padlock_xcryptecb mbedtls_padlock_xcryptecb -#define pem_context mbedtls_pem_context -#define pem_free mbedtls_pem_free -#define pem_init mbedtls_pem_init -#define pem_read_buffer mbedtls_pem_read_buffer -#define pem_write_buffer mbedtls_pem_write_buffer -#define pk_can_do mbedtls_pk_can_do -#define pk_check_pair mbedtls_pk_check_pair -#define pk_context mbedtls_pk_context -#define pk_debug mbedtls_pk_debug -#define pk_debug_item mbedtls_pk_debug_item -#define pk_debug_type mbedtls_pk_debug_type -#define pk_decrypt mbedtls_pk_decrypt -#define pk_ec mbedtls_pk_ec -#define pk_encrypt mbedtls_pk_encrypt -#define pk_free mbedtls_pk_free -#define pk_get_len mbedtls_pk_get_len -#define pk_get_name mbedtls_pk_get_name -#define pk_get_size mbedtls_pk_get_bitlen -#define pk_get_type mbedtls_pk_get_type -#define pk_info_from_type mbedtls_pk_info_from_type -#define pk_info_t mbedtls_pk_info_t -#define pk_init mbedtls_pk_init -#define pk_init_ctx mbedtls_pk_setup -#define pk_init_ctx_rsa_alt mbedtls_pk_setup_rsa_alt -#define pk_load_file mbedtls_pk_load_file -#define pk_parse_key mbedtls_pk_parse_key -#define pk_parse_keyfile mbedtls_pk_parse_keyfile -#define pk_parse_public_key mbedtls_pk_parse_public_key -#define pk_parse_public_keyfile mbedtls_pk_parse_public_keyfile -#define pk_parse_subpubkey mbedtls_pk_parse_subpubkey -#define pk_rsa mbedtls_pk_rsa -#define pk_rsa_alt_decrypt_func mbedtls_pk_rsa_alt_decrypt_func -#define pk_rsa_alt_key_len_func mbedtls_pk_rsa_alt_key_len_func -#define pk_rsa_alt_sign_func mbedtls_pk_rsa_alt_sign_func -#define pk_rsassa_pss_options mbedtls_pk_rsassa_pss_options -#define pk_sign mbedtls_pk_sign -#define pk_type_t mbedtls_pk_type_t -#define pk_verify mbedtls_pk_verify -#define pk_verify_ext mbedtls_pk_verify_ext -#define pk_write_key_der mbedtls_pk_write_key_der -#define pk_write_key_pem mbedtls_pk_write_key_pem -#define pk_write_pubkey mbedtls_pk_write_pubkey -#define pk_write_pubkey_der mbedtls_pk_write_pubkey_der -#define pk_write_pubkey_pem mbedtls_pk_write_pubkey_pem -#define pkcs11_context mbedtls_pkcs11_context -#define pkcs11_decrypt mbedtls_pkcs11_decrypt -#define pkcs11_priv_key_free mbedtls_pkcs11_priv_key_free -#define pkcs11_priv_key_init mbedtls_pkcs11_priv_key_bind -#define pkcs11_sign mbedtls_pkcs11_sign -#define pkcs11_x509_cert_init mbedtls_pkcs11_x509_cert_bind -#define pkcs12_derivation mbedtls_pkcs12_derivation -#define pkcs12_pbe mbedtls_pkcs12_pbe -#define pkcs12_pbe_sha1_rc4_128 mbedtls_pkcs12_pbe_sha1_rc4_128 -#define pkcs5_pbes2 mbedtls_pkcs5_pbes2 -#define pkcs5_pbkdf2_hmac mbedtls_pkcs5_pbkdf2_hmac -#define pkcs5_self_test mbedtls_pkcs5_self_test -#define platform_entropy_poll mbedtls_platform_entropy_poll -#define platform_set_exit mbedtls_platform_set_exit -#define platform_set_fprintf mbedtls_platform_set_fprintf -#define platform_set_printf mbedtls_platform_set_printf -#define platform_set_snprintf mbedtls_platform_set_snprintf -#define polarssl_exit mbedtls_exit -#define polarssl_fprintf mbedtls_fprintf -#define polarssl_free mbedtls_free -#define polarssl_mutex_free mbedtls_mutex_free -#define polarssl_mutex_init mbedtls_mutex_init -#define polarssl_mutex_lock mbedtls_mutex_lock -#define polarssl_mutex_unlock mbedtls_mutex_unlock -#define polarssl_printf mbedtls_printf -#define polarssl_snprintf mbedtls_snprintf -#define polarssl_strerror mbedtls_strerror -#define ripemd160 mbedtls_ripemd160 -#define ripemd160_context mbedtls_ripemd160_context -#define ripemd160_finish mbedtls_ripemd160_finish -#define ripemd160_free mbedtls_ripemd160_free -#define ripemd160_info mbedtls_ripemd160_info -#define ripemd160_init mbedtls_ripemd160_init -#define ripemd160_process mbedtls_ripemd160_process -#define ripemd160_self_test mbedtls_ripemd160_self_test -#define ripemd160_starts mbedtls_ripemd160_starts -#define ripemd160_update mbedtls_ripemd160_update -#define rsa_alt_context mbedtls_rsa_alt_context -#define rsa_alt_info mbedtls_rsa_alt_info -#define rsa_check_privkey mbedtls_rsa_check_privkey -#define rsa_check_pub_priv mbedtls_rsa_check_pub_priv -#define rsa_check_pubkey mbedtls_rsa_check_pubkey -#define rsa_context mbedtls_rsa_context -#define rsa_copy mbedtls_rsa_copy -#define rsa_free mbedtls_rsa_free -#define rsa_gen_key mbedtls_rsa_gen_key -#define rsa_info mbedtls_rsa_info -#define rsa_init mbedtls_rsa_init -#define rsa_pkcs1_decrypt mbedtls_rsa_pkcs1_decrypt -#define rsa_pkcs1_encrypt mbedtls_rsa_pkcs1_encrypt -#define rsa_pkcs1_sign mbedtls_rsa_pkcs1_sign -#define rsa_pkcs1_verify mbedtls_rsa_pkcs1_verify -#define rsa_private mbedtls_rsa_private -#define rsa_public mbedtls_rsa_public -#define rsa_rsaes_oaep_decrypt mbedtls_rsa_rsaes_oaep_decrypt -#define rsa_rsaes_oaep_encrypt mbedtls_rsa_rsaes_oaep_encrypt -#define rsa_rsaes_pkcs1_v15_decrypt mbedtls_rsa_rsaes_pkcs1_v15_decrypt -#define rsa_rsaes_pkcs1_v15_encrypt mbedtls_rsa_rsaes_pkcs1_v15_encrypt -#define rsa_rsassa_pkcs1_v15_sign mbedtls_rsa_rsassa_pkcs1_v15_sign -#define rsa_rsassa_pkcs1_v15_verify mbedtls_rsa_rsassa_pkcs1_v15_verify -#define rsa_rsassa_pss_sign mbedtls_rsa_rsassa_pss_sign -#define rsa_rsassa_pss_verify mbedtls_rsa_rsassa_pss_verify -#define rsa_rsassa_pss_verify_ext mbedtls_rsa_rsassa_pss_verify_ext -#define rsa_self_test mbedtls_rsa_self_test -#define rsa_set_padding mbedtls_rsa_set_padding -#define safer_memcmp mbedtls_ssl_safer_memcmp -#define set_alarm mbedtls_set_alarm -#define sha1 mbedtls_sha1 -#define sha1_context mbedtls_sha1_context -#define sha1_finish mbedtls_sha1_finish -#define sha1_free mbedtls_sha1_free -#define sha1_info mbedtls_sha1_info -#define sha1_init mbedtls_sha1_init -#define sha1_process mbedtls_sha1_process -#define sha1_self_test mbedtls_sha1_self_test -#define sha1_starts mbedtls_sha1_starts -#define sha1_update mbedtls_sha1_update -#define sha224_info mbedtls_sha224_info -#define sha256 mbedtls_sha256 -#define sha256_context mbedtls_sha256_context -#define sha256_finish mbedtls_sha256_finish -#define sha256_free mbedtls_sha256_free -#define sha256_info mbedtls_sha256_info -#define sha256_init mbedtls_sha256_init -#define sha256_process mbedtls_sha256_process -#define sha256_self_test mbedtls_sha256_self_test -#define sha256_starts mbedtls_sha256_starts -#define sha256_update mbedtls_sha256_update -#define sha384_info mbedtls_sha384_info -#define sha512 mbedtls_sha512 -#define sha512_context mbedtls_sha512_context -#define sha512_finish mbedtls_sha512_finish -#define sha512_free mbedtls_sha512_free -#define sha512_info mbedtls_sha512_info -#define sha512_init mbedtls_sha512_init -#define sha512_process mbedtls_sha512_process -#define sha512_self_test mbedtls_sha512_self_test -#define sha512_starts mbedtls_sha512_starts -#define sha512_update mbedtls_sha512_update -#define source_state mbedtls_entropy_source_state -#define ssl_cache_context mbedtls_ssl_cache_context -#define ssl_cache_entry mbedtls_ssl_cache_entry -#define ssl_cache_free mbedtls_ssl_cache_free -#define ssl_cache_get mbedtls_ssl_cache_get -#define ssl_cache_init mbedtls_ssl_cache_init -#define ssl_cache_set mbedtls_ssl_cache_set -#define ssl_cache_set_max_entries mbedtls_ssl_cache_set_max_entries -#define ssl_cache_set_timeout mbedtls_ssl_cache_set_timeout -#define ssl_check_cert_usage mbedtls_ssl_check_cert_usage -#define ssl_ciphersuite_from_id mbedtls_ssl_ciphersuite_from_id -#define ssl_ciphersuite_from_string mbedtls_ssl_ciphersuite_from_string -#define ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t -#define ssl_ciphersuite_uses_ec mbedtls_ssl_ciphersuite_uses_ec -#define ssl_ciphersuite_uses_psk mbedtls_ssl_ciphersuite_uses_psk -#define ssl_close_notify mbedtls_ssl_close_notify -#define ssl_context mbedtls_ssl_context -#define ssl_cookie_check mbedtls_ssl_cookie_check -#define ssl_cookie_check_t mbedtls_ssl_cookie_check_t -#define ssl_cookie_ctx mbedtls_ssl_cookie_ctx -#define ssl_cookie_free mbedtls_ssl_cookie_free -#define ssl_cookie_init mbedtls_ssl_cookie_init -#define ssl_cookie_set_timeout mbedtls_ssl_cookie_set_timeout -#define ssl_cookie_setup mbedtls_ssl_cookie_setup -#define ssl_cookie_write mbedtls_ssl_cookie_write -#define ssl_cookie_write_t mbedtls_ssl_cookie_write_t -#define ssl_derive_keys mbedtls_ssl_derive_keys -#define ssl_dtls_replay_check mbedtls_ssl_dtls_replay_check -#define ssl_dtls_replay_update mbedtls_ssl_dtls_replay_update -#define ssl_fetch_input mbedtls_ssl_fetch_input -#define ssl_flight_item mbedtls_ssl_flight_item -#define ssl_flush_output mbedtls_ssl_flush_output -#define ssl_free mbedtls_ssl_free -#define ssl_get_alpn_protocol mbedtls_ssl_get_alpn_protocol -#define ssl_get_bytes_avail mbedtls_ssl_get_bytes_avail -#define ssl_get_ciphersuite mbedtls_ssl_get_ciphersuite -#define ssl_get_ciphersuite_id mbedtls_ssl_get_ciphersuite_id -#define ssl_get_ciphersuite_name mbedtls_ssl_get_ciphersuite_name -#define ssl_get_ciphersuite_sig_pk_alg mbedtls_ssl_get_ciphersuite_sig_pk_alg -#define ssl_get_peer_cert mbedtls_ssl_get_peer_cert -#define ssl_get_record_expansion mbedtls_ssl_get_record_expansion -#define ssl_get_session mbedtls_ssl_get_session -#define ssl_get_verify_result mbedtls_ssl_get_verify_result -#define ssl_get_version mbedtls_ssl_get_version -#define ssl_handshake mbedtls_ssl_handshake -#define ssl_handshake_client_step mbedtls_ssl_handshake_client_step -#define ssl_handshake_free mbedtls_ssl_handshake_free -#define ssl_handshake_params mbedtls_ssl_handshake_params -#define ssl_handshake_server_step mbedtls_ssl_handshake_server_step -#define ssl_handshake_step mbedtls_ssl_handshake_step -#define ssl_handshake_wrapup mbedtls_ssl_handshake_wrapup -#define ssl_hdr_len mbedtls_ssl_hdr_len -#define ssl_hs_hdr_len mbedtls_ssl_hs_hdr_len -#define ssl_hw_record_activate mbedtls_ssl_hw_record_activate -#define ssl_hw_record_finish mbedtls_ssl_hw_record_finish -#define ssl_hw_record_init mbedtls_ssl_hw_record_init -#define ssl_hw_record_read mbedtls_ssl_hw_record_read -#define ssl_hw_record_reset mbedtls_ssl_hw_record_reset -#define ssl_hw_record_write mbedtls_ssl_hw_record_write -#define ssl_init mbedtls_ssl_init -#define ssl_key_cert mbedtls_ssl_key_cert -#define ssl_legacy_renegotiation mbedtls_ssl_conf_legacy_renegotiation -#define ssl_list_ciphersuites mbedtls_ssl_list_ciphersuites -#define ssl_md_alg_from_hash mbedtls_ssl_md_alg_from_hash -#define ssl_optimize_checksum mbedtls_ssl_optimize_checksum -#define ssl_own_cert mbedtls_ssl_own_cert -#define ssl_own_key mbedtls_ssl_own_key -#define ssl_parse_certificate mbedtls_ssl_parse_certificate -#define ssl_parse_change_cipher_spec mbedtls_ssl_parse_change_cipher_spec -#define ssl_parse_finished mbedtls_ssl_parse_finished -#define ssl_pk_alg_from_sig mbedtls_ssl_pk_alg_from_sig -#define ssl_pkcs11_decrypt mbedtls_ssl_pkcs11_decrypt -#define ssl_pkcs11_key_len mbedtls_ssl_pkcs11_key_len -#define ssl_pkcs11_sign mbedtls_ssl_pkcs11_sign -#define ssl_psk_derive_premaster mbedtls_ssl_psk_derive_premaster -#define ssl_read mbedtls_ssl_read -#define ssl_read_record mbedtls_ssl_read_record -#define ssl_read_version mbedtls_ssl_read_version -#define ssl_recv_flight_completed mbedtls_ssl_recv_flight_completed -#define ssl_renegotiate mbedtls_ssl_renegotiate -#define ssl_resend mbedtls_ssl_resend -#define ssl_reset_checksum mbedtls_ssl_reset_checksum -#define ssl_send_alert_message mbedtls_ssl_send_alert_message -#define ssl_send_fatal_handshake_failure mbedtls_ssl_send_fatal_handshake_failure -#define ssl_send_flight_completed mbedtls_ssl_send_flight_completed -#define ssl_session mbedtls_ssl_session -#define ssl_session_free mbedtls_ssl_session_free -#define ssl_session_init mbedtls_ssl_session_init -#define ssl_session_reset mbedtls_ssl_session_reset -#define ssl_set_alpn_protocols mbedtls_ssl_conf_alpn_protocols -#define ssl_set_arc4_support mbedtls_ssl_conf_arc4_support -#define ssl_set_authmode mbedtls_ssl_conf_authmode -#define ssl_set_bio mbedtls_ssl_set_bio -#define ssl_set_ca_chain mbedtls_ssl_conf_ca_chain -#define ssl_set_cbc_record_splitting mbedtls_ssl_conf_cbc_record_splitting -#define ssl_set_ciphersuites mbedtls_ssl_conf_ciphersuites -#define ssl_set_ciphersuites_for_version mbedtls_ssl_conf_ciphersuites_for_version -#define ssl_set_client_transport_id mbedtls_ssl_set_client_transport_id -#define ssl_set_curves mbedtls_ssl_conf_curves -#define ssl_set_dbg mbedtls_ssl_conf_dbg -#define ssl_set_dh_param mbedtls_ssl_conf_dh_param -#define ssl_set_dh_param_ctx mbedtls_ssl_conf_dh_param_ctx -#define ssl_set_dtls_anti_replay mbedtls_ssl_conf_dtls_anti_replay -#define ssl_set_dtls_badmac_limit mbedtls_ssl_conf_dtls_badmac_limit -#define ssl_set_dtls_cookies mbedtls_ssl_conf_dtls_cookies -#define ssl_set_encrypt_then_mac mbedtls_ssl_conf_encrypt_then_mac -#define ssl_set_endpoint mbedtls_ssl_conf_endpoint -#define ssl_set_extended_master_secret mbedtls_ssl_conf_extended_master_secret -#define ssl_set_fallback mbedtls_ssl_conf_fallback -#define ssl_set_handshake_timeout mbedtls_ssl_conf_handshake_timeout -#define ssl_set_hostname mbedtls_ssl_set_hostname -#define ssl_set_max_frag_len mbedtls_ssl_conf_max_frag_len -#define ssl_set_max_version mbedtls_ssl_conf_max_version -#define ssl_set_min_version mbedtls_ssl_conf_min_version -#define ssl_set_own_cert mbedtls_ssl_conf_own_cert -#define ssl_set_psk mbedtls_ssl_conf_psk -#define ssl_set_psk_cb mbedtls_ssl_conf_psk_cb -#define ssl_set_renegotiation mbedtls_ssl_conf_renegotiation -#define ssl_set_renegotiation_enforced mbedtls_ssl_conf_renegotiation_enforced -#define ssl_set_renegotiation_period mbedtls_ssl_conf_renegotiation_period -#define ssl_set_rng mbedtls_ssl_conf_rng -#define ssl_set_session mbedtls_ssl_set_session -#define ssl_set_session_cache mbedtls_ssl_conf_session_cache -#define ssl_set_session_tickets mbedtls_ssl_conf_session_tickets -#define ssl_set_sni mbedtls_ssl_conf_sni -#define ssl_set_transport mbedtls_ssl_conf_transport -#define ssl_set_truncated_hmac mbedtls_ssl_conf_truncated_hmac -#define ssl_set_verify mbedtls_ssl_conf_verify -#define ssl_sig_from_pk mbedtls_ssl_sig_from_pk -#define ssl_states mbedtls_ssl_states -#define ssl_transform mbedtls_ssl_transform -#define ssl_transform_free mbedtls_ssl_transform_free -#define ssl_write mbedtls_ssl_write -#define ssl_write_certificate mbedtls_ssl_write_certificate -#define ssl_write_change_cipher_spec mbedtls_ssl_write_change_cipher_spec -#define ssl_write_finished mbedtls_ssl_write_finished -#define ssl_write_record mbedtls_ssl_write_record -#define ssl_write_version mbedtls_ssl_write_version -#define supported_ciphers mbedtls_cipher_supported -#define t_sint mbedtls_mpi_sint -#define t_udbl mbedtls_t_udbl -#define t_uint mbedtls_mpi_uint -#define test_ca_crt mbedtls_test_ca_crt -#define test_ca_crt_ec mbedtls_test_ca_crt_ec -#define test_ca_crt_rsa mbedtls_test_ca_crt_rsa -#define test_ca_key mbedtls_test_ca_key -#define test_ca_key_ec mbedtls_test_ca_key_ec -#define test_ca_key_rsa mbedtls_test_ca_key_rsa -#define test_ca_list mbedtls_test_cas_pem -#define test_ca_pwd mbedtls_test_ca_pwd -#define test_ca_pwd_ec mbedtls_test_ca_pwd_ec -#define test_ca_pwd_rsa mbedtls_test_ca_pwd_rsa -#define test_cli_crt mbedtls_test_cli_crt -#define test_cli_crt_ec mbedtls_test_cli_crt_ec -#define test_cli_crt_rsa mbedtls_test_cli_crt_rsa -#define test_cli_key mbedtls_test_cli_key -#define test_cli_key_ec mbedtls_test_cli_key_ec -#define test_cli_key_rsa mbedtls_test_cli_key_rsa -#define test_srv_crt mbedtls_test_srv_crt -#define test_srv_crt_ec mbedtls_test_srv_crt_ec -#define test_srv_crt_rsa mbedtls_test_srv_crt_rsa -#define test_srv_key mbedtls_test_srv_key -#define test_srv_key_ec mbedtls_test_srv_key_ec -#define test_srv_key_rsa mbedtls_test_srv_key_rsa -#define threading_mutex_t mbedtls_threading_mutex_t -#define threading_set_alt mbedtls_threading_set_alt -#define timing_self_test mbedtls_timing_self_test -#define version_check_feature mbedtls_version_check_feature -#define version_get_number mbedtls_version_get_number -#define version_get_string mbedtls_version_get_string -#define version_get_string_full mbedtls_version_get_string_full -#define x509_bitstring mbedtls_x509_bitstring -#define x509_buf mbedtls_x509_buf -#define x509_crl mbedtls_x509_crl -#define x509_crl_entry mbedtls_x509_crl_entry -#define x509_crl_free mbedtls_x509_crl_free -#define x509_crl_info mbedtls_x509_crl_info -#define x509_crl_init mbedtls_x509_crl_init -#define x509_crl_parse mbedtls_x509_crl_parse -#define x509_crl_parse_der mbedtls_x509_crl_parse_der -#define x509_crl_parse_file mbedtls_x509_crl_parse_file -#define x509_crt mbedtls_x509_crt -#define x509_crt_check_extended_key_usage mbedtls_x509_crt_check_extended_key_usage -#define x509_crt_check_key_usage mbedtls_x509_crt_check_key_usage -#define x509_crt_free mbedtls_x509_crt_free -#define x509_crt_info mbedtls_x509_crt_info -#define x509_crt_init mbedtls_x509_crt_init -#define x509_crt_parse mbedtls_x509_crt_parse -#define x509_crt_parse_der mbedtls_x509_crt_parse_der -#define x509_crt_parse_file mbedtls_x509_crt_parse_file -#define x509_crt_parse_path mbedtls_x509_crt_parse_path -#define x509_crt_revoked mbedtls_x509_crt_is_revoked -#define x509_crt_verify mbedtls_x509_crt_verify -#define x509_csr mbedtls_x509_csr -#define x509_csr_free mbedtls_x509_csr_free -#define x509_csr_info mbedtls_x509_csr_info -#define x509_csr_init mbedtls_x509_csr_init -#define x509_csr_parse mbedtls_x509_csr_parse -#define x509_csr_parse_der mbedtls_x509_csr_parse_der -#define x509_csr_parse_file mbedtls_x509_csr_parse_file -#define x509_dn_gets mbedtls_x509_dn_gets -#define x509_get_alg mbedtls_x509_get_alg -#define x509_get_alg_null mbedtls_x509_get_alg_null -#define x509_get_ext mbedtls_x509_get_ext -#define x509_get_name mbedtls_x509_get_name -#define x509_get_rsassa_pss_params mbedtls_x509_get_rsassa_pss_params -#define x509_get_serial mbedtls_x509_get_serial -#define x509_get_sig mbedtls_x509_get_sig -#define x509_get_sig_alg mbedtls_x509_get_sig_alg -#define x509_get_time mbedtls_x509_get_time -#define x509_key_size_helper mbedtls_x509_key_size_helper -#define x509_name mbedtls_x509_name -#define x509_self_test mbedtls_x509_self_test -#define x509_sequence mbedtls_x509_sequence -#define x509_serial_gets mbedtls_x509_serial_gets -#define x509_set_extension mbedtls_x509_set_extension -#define x509_sig_alg_gets mbedtls_x509_sig_alg_gets -#define x509_string_to_names mbedtls_x509_string_to_names -#define x509_time mbedtls_x509_time -#define x509_time_expired mbedtls_x509_time_is_past -#define x509_time_future mbedtls_x509_time_is_future -#define x509_write_extensions mbedtls_x509_write_extensions -#define x509_write_names mbedtls_x509_write_names -#define x509_write_sig mbedtls_x509_write_sig -#define x509write_cert mbedtls_x509write_cert -#define x509write_crt_der mbedtls_x509write_crt_der -#define x509write_crt_free mbedtls_x509write_crt_free -#define x509write_crt_init mbedtls_x509write_crt_init -#define x509write_crt_pem mbedtls_x509write_crt_pem -#define x509write_crt_set_authority_key_identifier mbedtls_x509write_crt_set_authority_key_identifier -#define x509write_crt_set_basic_constraints mbedtls_x509write_crt_set_basic_constraints -#define x509write_crt_set_extension mbedtls_x509write_crt_set_extension -#define x509write_crt_set_issuer_key mbedtls_x509write_crt_set_issuer_key -#define x509write_crt_set_issuer_name mbedtls_x509write_crt_set_issuer_name -#define x509write_crt_set_key_usage mbedtls_x509write_crt_set_key_usage -#define x509write_crt_set_md_alg mbedtls_x509write_crt_set_md_alg -#define x509write_crt_set_ns_cert_type mbedtls_x509write_crt_set_ns_cert_type -#define x509write_crt_set_serial mbedtls_x509write_crt_set_serial -#define x509write_crt_set_subject_key mbedtls_x509write_crt_set_subject_key -#define x509write_crt_set_subject_key_identifier mbedtls_x509write_crt_set_subject_key_identifier -#define x509write_crt_set_subject_name mbedtls_x509write_crt_set_subject_name -#define x509write_crt_set_validity mbedtls_x509write_crt_set_validity -#define x509write_crt_set_version mbedtls_x509write_crt_set_version -#define x509write_csr mbedtls_x509write_csr -#define x509write_csr_der mbedtls_x509write_csr_der -#define x509write_csr_free mbedtls_x509write_csr_free -#define x509write_csr_init mbedtls_x509write_csr_init -#define x509write_csr_pem mbedtls_x509write_csr_pem -#define x509write_csr_set_extension mbedtls_x509write_csr_set_extension -#define x509write_csr_set_key mbedtls_x509write_csr_set_key -#define x509write_csr_set_key_usage mbedtls_x509write_csr_set_key_usage -#define x509write_csr_set_md_alg mbedtls_x509write_csr_set_md_alg -#define x509write_csr_set_ns_cert_type mbedtls_x509write_csr_set_ns_cert_type -#define x509write_csr_set_subject_name mbedtls_x509write_csr_set_subject_name -#define xtea_context mbedtls_xtea_context -#define xtea_crypt_cbc mbedtls_xtea_crypt_cbc -#define xtea_crypt_ecb mbedtls_xtea_crypt_ecb -#define xtea_free mbedtls_xtea_free -#define xtea_init mbedtls_xtea_init -#define xtea_self_test mbedtls_xtea_self_test -#define xtea_setup mbedtls_xtea_setup - -#endif /* compat-1.3.h */ -#endif /* MBEDTLS_DEPRECATED_REMOVED */ diff --git a/components/mbedtls/include/mbedtls/config.h b/components/mbedtls/include/mbedtls/config.h deleted file mode 100644 index 47c7196402..0000000000 --- a/components/mbedtls/include/mbedtls/config.h +++ /dev/null @@ -1,2719 +0,0 @@ -/** - * \file config.h - * - * \brief Configuration options (set of defines) - * - * This set of compile-time options may be used to enable - * or disable features selectively, and reduce the global - * memory footprint. - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef MBEDTLS_CONFIG_H -#define MBEDTLS_CONFIG_H - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) -#define _CRT_SECURE_NO_DEPRECATE 1 -#endif - -/** - * \name SECTION: System support - * - * This section sets system specific settings. - * \{ - */ - -/** - * \def MBEDTLS_HAVE_ASM - * - * The compiler has support for asm(). - * - * Requires support for asm() in compiler. - * - * Used in: - * library/timing.c - * library/padlock.c - * include/mbedtls/bn_mul.h - * - * Comment to disable the use of assembly code. - */ -#define MBEDTLS_HAVE_ASM - -/** - * \def MBEDTLS_NO_UDBL_DIVISION - * - * The platform lacks support for double-width integer division (64-bit - * division on a 32-bit platform, 128-bit division on a 64-bit platform). - * - * Used in: - * include/mbedtls/bignum.h - * library/bignum.c - * - * The bignum code uses double-width division to speed up some operations. - * Double-width division is often implemented in software that needs to - * be linked with the program. The presence of a double-width integer - * type is usually detected automatically through preprocessor macros, - * but the automatic detection cannot know whether the code needs to - * and can be linked with an implementation of division for that type. - * By default division is assumed to be usable if the type is present. - * Uncomment this option to prevent the use of double-width division. - * - * Note that division for the native integer type is always required. - * Furthermore, a 64-bit type is always required even on a 32-bit - * platform, but it need not support multiplication or division. In some - * cases it is also desirable to disable some double-width operations. For - * example, if double-width division is implemented in software, disabling - * it can reduce code size in some embedded targets. - */ -//#define MBEDTLS_NO_UDBL_DIVISION - -/** - * \def MBEDTLS_HAVE_SSE2 - * - * CPU supports SSE2 instruction set. - * - * Uncomment if the CPU supports SSE2 (IA-32 specific). - */ -//#define MBEDTLS_HAVE_SSE2 - -/** - * \def MBEDTLS_HAVE_TIME - * - * System has time.h and time(). - * The time does not need to be correct, only time differences are used, - * by contrast with MBEDTLS_HAVE_TIME_DATE - * - * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT, - * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and - * MBEDTLS_PLATFORM_STD_TIME. - * - * Comment if your system does not support time functions - */ -#define MBEDTLS_HAVE_TIME - -/** - * \def MBEDTLS_HAVE_TIME_DATE - * - * System has time.h and time(), gmtime() and the clock is correct. - * The time needs to be correct (not necesarily very accurate, but at least - * the date should be correct). This is used to verify the validity period of - * X.509 certificates. - * - * Comment if your system does not have a correct clock. - */ -#define MBEDTLS_HAVE_TIME_DATE - -/** - * \def MBEDTLS_PLATFORM_MEMORY - * - * Enable the memory allocation layer. - * - * By default mbed TLS uses the system-provided calloc() and free(). - * This allows different allocators (self-implemented or provided) to be - * provided to the platform abstraction layer. - * - * Enabling MBEDTLS_PLATFORM_MEMORY without the - * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide - * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and - * free() function pointer at runtime. - * - * Enabling MBEDTLS_PLATFORM_MEMORY and specifying - * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the - * alternate function at compile time. - * - * Requires: MBEDTLS_PLATFORM_C - * - * Enable this layer to allow use of alternative memory allocators. - */ -//#define MBEDTLS_PLATFORM_MEMORY - -/** - * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS - * - * Do not assign standard functions in the platform layer (e.g. calloc() to - * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF) - * - * This makes sure there are no linking errors on platforms that do not support - * these functions. You will HAVE to provide alternatives, either at runtime - * via the platform_set_xxx() functions or at compile time by setting - * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a - * MBEDTLS_PLATFORM_XXX_MACRO. - * - * Requires: MBEDTLS_PLATFORM_C - * - * Uncomment to prevent default assignment of standard functions in the - * platform layer. - */ -//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS - -/** - * \def MBEDTLS_PLATFORM_EXIT_ALT - * - * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the - * function in the platform abstraction layer. - * - * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will - * provide a function "mbedtls_platform_set_printf()" that allows you to set an - * alternative printf function pointer. - * - * All these define require MBEDTLS_PLATFORM_C to be defined! - * - * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows; - * it will be enabled automatically by check_config.h - * - * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as - * MBEDTLS_PLATFORM_XXX_MACRO! - * - * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME - * - * Uncomment a macro to enable alternate implementation of specific base - * platform function - */ -//#define MBEDTLS_PLATFORM_EXIT_ALT -//#define MBEDTLS_PLATFORM_TIME_ALT -//#define MBEDTLS_PLATFORM_FPRINTF_ALT -//#define MBEDTLS_PLATFORM_PRINTF_ALT -//#define MBEDTLS_PLATFORM_SNPRINTF_ALT -//#define MBEDTLS_PLATFORM_NV_SEED_ALT -//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT - -/** - * \def MBEDTLS_DEPRECATED_WARNING - * - * Mark deprecated functions so that they generate a warning if used. - * Functions deprecated in one version will usually be removed in the next - * version. You can enable this to help you prepare the transition to a new - * major version by making sure your code is not using these functions. - * - * This only works with GCC and Clang. With other compilers, you may want to - * use MBEDTLS_DEPRECATED_REMOVED - * - * Uncomment to get warnings on using deprecated functions. - */ -//#define MBEDTLS_DEPRECATED_WARNING - -/** - * \def MBEDTLS_DEPRECATED_REMOVED - * - * Remove deprecated functions so that they generate an error if used. - * Functions deprecated in one version will usually be removed in the next - * version. You can enable this to help you prepare the transition to a new - * major version by making sure your code is not using these functions. - * - * Uncomment to get errors on using deprecated functions. - */ -//#define MBEDTLS_DEPRECATED_REMOVED - -/* \} name SECTION: System support */ - -/** - * \name SECTION: mbed TLS feature support - * - * This section sets support for features that are or are not needed - * within the modules that are enabled. - * \{ - */ - -/** - * \def MBEDTLS_TIMING_ALT - * - * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(), - * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() - * - * Only works if you have MBEDTLS_TIMING_C enabled. - * - * You will need to provide a header "timing_alt.h" and an implementation at - * compile time. - */ -//#define MBEDTLS_TIMING_ALT - -/** - * \def MBEDTLS_AES_ALT - * - * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your - * alternate core implementation of a symmetric crypto, an arithmetic or hash - * module (e.g. platform specific assembly optimized implementations). Keep - * in mind that the function prototypes should remain the same. - * - * This replaces the whole module. If you only want to replace one of the - * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags. - * - * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer - * provide the "struct mbedtls_aes_context" definition and omit the base - * function declarations and implementations. "aes_alt.h" will be included from - * "aes.h" to include the new function definitions. - * - * Uncomment a macro to enable alternate implementation of the corresponding - * module. - */ -//#define MBEDTLS_AES_ALT -//#define MBEDTLS_ARC4_ALT -//#define MBEDTLS_BLOWFISH_ALT -//#define MBEDTLS_CAMELLIA_ALT -//#define MBEDTLS_DES_ALT -//#define MBEDTLS_XTEA_ALT -//#define MBEDTLS_MD2_ALT -//#define MBEDTLS_MD4_ALT -//#define MBEDTLS_MD5_ALT -//#define MBEDTLS_RIPEMD160_ALT -//#define MBEDTLS_SHA1_ALT -//#define MBEDTLS_SHA256_ALT -//#define MBEDTLS_SHA512_ALT -/* - * When replacing the elliptic curve module, pleace consider, that it is - * implemented with two .c files: - * - ecp.c - * - ecp_curves.c - * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT - * macros as described above. The only difference is that you have to make sure - * that you provide functionality for both .c files. - */ -//#define MBEDTLS_ECP_ALT - -/** - * \def MBEDTLS_MD2_PROCESS_ALT - * - * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you - * alternate core implementation of symmetric crypto or hash function. Keep in - * mind that function prototypes should remain the same. - * - * This replaces only one function. The header file from mbed TLS is still - * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags. - * - * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will - * no longer provide the mbedtls_sha1_process() function, but it will still provide - * the other function (using your mbedtls_sha1_process() function) and the definition - * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible - * with this definition. - * - * \note Because of a signature change, the core AES encryption and decryption routines are - * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt, - * respectively. When setting up alternative implementations, these functions should - * be overriden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt - * must stay untouched. - * - * \note If you use the AES_xxx_ALT macros, then is is recommended to also set - * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES - * tables. - * - * Uncomment a macro to enable alternate implementation of the corresponding - * function. - */ -//#define MBEDTLS_MD2_PROCESS_ALT -//#define MBEDTLS_MD4_PROCESS_ALT -//#define MBEDTLS_MD5_PROCESS_ALT -//#define MBEDTLS_RIPEMD160_PROCESS_ALT -//#define MBEDTLS_SHA1_PROCESS_ALT -//#define MBEDTLS_SHA256_PROCESS_ALT -//#define MBEDTLS_SHA512_PROCESS_ALT -//#define MBEDTLS_DES_SETKEY_ALT -//#define MBEDTLS_DES_CRYPT_ECB_ALT -//#define MBEDTLS_DES3_CRYPT_ECB_ALT -//#define MBEDTLS_AES_SETKEY_ENC_ALT -//#define MBEDTLS_AES_SETKEY_DEC_ALT -//#define MBEDTLS_AES_ENCRYPT_ALT -//#define MBEDTLS_AES_DECRYPT_ALT - -/** - * \def MBEDTLS_ECP_INTERNAL_ALT - * - * Expose a part of the internal interface of the Elliptic Curve Point module. - * - * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your - * alternative core implementation of elliptic curve arithmetic. Keep in mind - * that function prototypes should remain the same. - * - * This partially replaces one function. The header file from mbed TLS is still - * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation - * is still present and it is used for group structures not supported by the - * alternative. - * - * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT - * and implementing the following functions: - * unsigned char mbedtls_internal_ecp_grp_capable( - * const mbedtls_ecp_group *grp ) - * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) - * void mbedtls_internal_ecp_deinit( const mbedtls_ecp_group *grp ) - * The mbedtls_internal_ecp_grp_capable function should return 1 if the - * replacement functions implement arithmetic for the given group and 0 - * otherwise. - * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_deinit are - * called before and after each point operation and provide an opportunity to - * implement optimized set up and tear down instructions. - * - * Example: In case you uncomment MBEDTLS_ECP_INTERNAL_ALT and - * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac - * function, but will use your mbedtls_internal_ecp_double_jac if the group is - * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when - * receives it as an argument). If the group is not supported then the original - * implementation is used. The other functions and the definition of - * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your - * implementation of mbedtls_internal_ecp_double_jac and - * mbedtls_internal_ecp_grp_capable must be compatible with this definition. - * - * Uncomment a macro to enable alternate implementation of the corresponding - * function. - */ -/* Required for all the functions in this section */ -//#define MBEDTLS_ECP_INTERNAL_ALT -/* Support for Weierstrass curves with Jacobi representation */ -//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT -//#define MBEDTLS_ECP_ADD_MIXED_ALT -//#define MBEDTLS_ECP_DOUBLE_JAC_ALT -//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT -//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT -/* Support for curves with Montgomery arithmetic */ -//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT -//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT -//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT - -/** - * \def MBEDTLS_TEST_NULL_ENTROPY - * - * Enables testing and use of mbed TLS without any configured entropy sources. - * This permits use of the library on platforms before an entropy source has - * been integrated (see for example the MBEDTLS_ENTROPY_HARDWARE_ALT or the - * MBEDTLS_ENTROPY_NV_SEED switches). - * - * WARNING! This switch MUST be disabled in production builds, and is suitable - * only for development. - * Enabling the switch negates any security provided by the library. - * - * Requires MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES - * - */ -//#define MBEDTLS_TEST_NULL_ENTROPY - -/** - * \def MBEDTLS_ENTROPY_HARDWARE_ALT - * - * Uncomment this macro to let mbed TLS use your own implementation of a - * hardware entropy collector. - * - * Your function must be called \c mbedtls_hardware_poll(), have the same - * prototype as declared in entropy_poll.h, and accept NULL as first argument. - * - * Uncomment to use your own hardware entropy collector. - */ -//#define MBEDTLS_ENTROPY_HARDWARE_ALT - -/** - * \def MBEDTLS_AES_ROM_TABLES - * - * Store the AES tables in ROM. - * - * Uncomment this macro to store the AES tables in ROM. - */ -//#define MBEDTLS_AES_ROM_TABLES - -/** - * \def MBEDTLS_CAMELLIA_SMALL_MEMORY - * - * Use less ROM for the Camellia implementation (saves about 768 bytes). - * - * Uncomment this macro to use less memory for Camellia. - */ -//#define MBEDTLS_CAMELLIA_SMALL_MEMORY - -/** - * \def MBEDTLS_CIPHER_MODE_CBC - * - * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. - */ -#define MBEDTLS_CIPHER_MODE_CBC - -/** - * \def MBEDTLS_CIPHER_MODE_CFB - * - * Enable Cipher Feedback mode (CFB) for symmetric ciphers. - */ -#define MBEDTLS_CIPHER_MODE_CFB - -/** - * \def MBEDTLS_CIPHER_MODE_CTR - * - * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. - */ -#define MBEDTLS_CIPHER_MODE_CTR - -/** - * \def MBEDTLS_CIPHER_NULL_CIPHER - * - * Enable NULL cipher. - * Warning: Only do so when you know what you are doing. This allows for - * encryption or channels without any security! - * - * Requires MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable - * the following ciphersuites: - * MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA - * MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA - * MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA - * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 - * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 - * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA - * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 - * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 - * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA - * MBEDTLS_TLS_RSA_WITH_NULL_SHA256 - * MBEDTLS_TLS_RSA_WITH_NULL_SHA - * MBEDTLS_TLS_RSA_WITH_NULL_MD5 - * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 - * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 - * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA - * MBEDTLS_TLS_PSK_WITH_NULL_SHA384 - * MBEDTLS_TLS_PSK_WITH_NULL_SHA256 - * MBEDTLS_TLS_PSK_WITH_NULL_SHA - * - * Uncomment this macro to enable the NULL cipher and ciphersuites - */ -//#define MBEDTLS_CIPHER_NULL_CIPHER - -/** - * \def MBEDTLS_CIPHER_PADDING_PKCS7 - * - * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for - * specific padding modes in the cipher layer with cipher modes that support - * padding (e.g. CBC) - * - * If you disable all padding modes, only full blocks can be used with CBC. - * - * Enable padding modes in the cipher layer. - */ -#define MBEDTLS_CIPHER_PADDING_PKCS7 -#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS -#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN -#define MBEDTLS_CIPHER_PADDING_ZEROS - -/** - * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES - * - * Enable weak ciphersuites in SSL / TLS. - * Warning: Only do so when you know what you are doing. This allows for - * channels with virtually no security at all! - * - * This enables the following ciphersuites: - * MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA - * MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA - * - * Uncomment this macro to enable weak ciphersuites - */ -//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES - -/** - * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES - * - * Remove RC4 ciphersuites by default in SSL / TLS. - * This flag removes the ciphersuites based on RC4 from the default list as - * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to - * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them - * explicitly. - * - * Uncomment this macro to remove RC4 ciphersuites by default. - */ -#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES - -/** - * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED - * - * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve - * module. By default all supported curves are enabled. - * - * Comment macros to disable the curve and functions for it - */ -#define MBEDTLS_ECP_DP_SECP192R1_ENABLED -#define MBEDTLS_ECP_DP_SECP224R1_ENABLED -#define MBEDTLS_ECP_DP_SECP256R1_ENABLED -#define MBEDTLS_ECP_DP_SECP384R1_ENABLED -#define MBEDTLS_ECP_DP_SECP521R1_ENABLED -#define MBEDTLS_ECP_DP_SECP192K1_ENABLED -#define MBEDTLS_ECP_DP_SECP224K1_ENABLED -#define MBEDTLS_ECP_DP_SECP256K1_ENABLED -#define MBEDTLS_ECP_DP_BP256R1_ENABLED -#define MBEDTLS_ECP_DP_BP384R1_ENABLED -#define MBEDTLS_ECP_DP_BP512R1_ENABLED -#define MBEDTLS_ECP_DP_CURVE25519_ENABLED - -/** - * \def MBEDTLS_ECP_NIST_OPTIM - * - * Enable specific 'modulo p' routines for each NIST prime. - * Depending on the prime and architecture, makes operations 4 to 8 times - * faster on the corresponding curve. - * - * Comment this macro to disable NIST curves optimisation. - */ -#define MBEDTLS_ECP_NIST_OPTIM - -/** - * \def MBEDTLS_ECDSA_DETERMINISTIC - * - * Enable deterministic ECDSA (RFC 6979). - * Standard ECDSA is "fragile" in the sense that lack of entropy when signing - * may result in a compromise of the long-term signing key. This is avoided by - * the deterministic variant. - * - * Requires: MBEDTLS_HMAC_DRBG_C - * - * Comment this macro to disable deterministic ECDSA. - */ -#define MBEDTLS_ECDSA_DETERMINISTIC - -/** - * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED - * - * Enable the PSK based ciphersuite modes in SSL / TLS. - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 - * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA - */ -#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED - -/** - * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED - * - * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. - * - * Requires: MBEDTLS_DHM_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 - * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA - */ -#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED - -/** - * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED - * - * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. - * - * Requires: MBEDTLS_ECDH_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA - */ -#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED - -/** - * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED - * - * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. - * - * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, - * MBEDTLS_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 - * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA - */ -#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED - -/** - * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED - * - * Enable the RSA-only based ciphersuite modes in SSL / TLS. - * - * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, - * MBEDTLS_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 - * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA - * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA - * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA - * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 - */ -#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED - -/** - * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED - * - * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. - * - * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, - * MBEDTLS_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA - */ -#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED - -/** - * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED - * - * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. - * - * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, - * MBEDTLS_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 - * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA - */ -#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED - -/** - * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - * - * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. - * - * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C, - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA - */ -#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - -/** - * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED - * - * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. - * - * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA - * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 - * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 - * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 - */ -#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED - -/** - * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED - * - * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. - * - * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA - * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 - * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 - * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 - */ -#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED - -/** - * \def MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED - * - * Enable the ECJPAKE based ciphersuite modes in SSL / TLS. - * - * \warning This is currently experimental. EC J-PAKE support is based on the - * Thread v1.0.0 specification; incompatible changes to the specification - * might still happen. For this reason, this is disabled by default. - * - * Requires: MBEDTLS_ECJPAKE_C - * MBEDTLS_SHA256_C - * MBEDTLS_ECP_DP_SECP256R1_ENABLED - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 - */ -//#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED - -/** - * \def MBEDTLS_PK_PARSE_EC_EXTENDED - * - * Enhance support for reading EC keys using variants of SEC1 not allowed by - * RFC 5915 and RFC 5480. - * - * Currently this means parsing the SpecifiedECDomain choice of EC - * parameters (only known groups are supported, not arbitrary domains, to - * avoid validation issues). - * - * Disable if you only need to support RFC 5915 + 5480 key formats. - */ -#define MBEDTLS_PK_PARSE_EC_EXTENDED - -/** - * \def MBEDTLS_ERROR_STRERROR_DUMMY - * - * Enable a dummy error function to make use of mbedtls_strerror() in - * third party libraries easier when MBEDTLS_ERROR_C is disabled - * (no effect when MBEDTLS_ERROR_C is enabled). - * - * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're - * not using mbedtls_strerror() or error_strerror() in your application. - * - * Disable if you run into name conflicts and want to really remove the - * mbedtls_strerror() - */ -#define MBEDTLS_ERROR_STRERROR_DUMMY - -/** - * \def MBEDTLS_GENPRIME - * - * Enable the prime-number generation code. - * - * Requires: MBEDTLS_BIGNUM_C - */ -#define MBEDTLS_GENPRIME - -/** - * \def MBEDTLS_FS_IO - * - * Enable functions that use the filesystem. - */ -#define MBEDTLS_FS_IO - -/** - * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES - * - * Do not add default entropy sources. These are the platform specific, - * mbedtls_timing_hardclock and HAVEGE based poll functions. - * - * This is useful to have more control over the added entropy sources in an - * application. - * - * Uncomment this macro to prevent loading of default entropy functions. - */ -//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES - -/** - * \def MBEDTLS_NO_PLATFORM_ENTROPY - * - * Do not use built-in platform entropy functions. - * This is useful if your platform does not support - * standards like the /dev/urandom or Windows CryptoAPI. - * - * Uncomment this macro to disable the built-in platform entropy functions. - */ -//#define MBEDTLS_NO_PLATFORM_ENTROPY - -/** - * \def MBEDTLS_ENTROPY_FORCE_SHA256 - * - * Force the entropy accumulator to use a SHA-256 accumulator instead of the - * default SHA-512 based one (if both are available). - * - * Requires: MBEDTLS_SHA256_C - * - * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option - * if you have performance concerns. - * - * This option is only useful if both MBEDTLS_SHA256_C and - * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used. - */ -//#define MBEDTLS_ENTROPY_FORCE_SHA256 - -/** - * \def MBEDTLS_ENTROPY_NV_SEED - * - * Enable the non-volatile (NV) seed file-based entropy source. - * (Also enables the NV seed read/write functions in the platform layer) - * - * This is crucial (if not required) on systems that do not have a - * cryptographic entropy source (in hardware or kernel) available. - * - * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C - * - * \note The read/write functions that are used by the entropy source are - * determined in the platform layer, and can be modified at runtime and/or - * compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used. - * - * \note If you use the default implementation functions that read a seedfile - * with regular fopen(), please make sure you make a seedfile with the - * proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at - * least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from - * and written to or you will get an entropy source error! The default - * implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE - * bytes from the file. - * - * \note The entropy collector will write to the seed file before entropy is - * given to an external source, to update it. - */ -//#define MBEDTLS_ENTROPY_NV_SEED - -/** - * \def MBEDTLS_MEMORY_DEBUG - * - * Enable debugging of buffer allocator memory issues. Automatically prints - * (to stderr) all (fatal) messages on memory allocation issues. Enables - * function for 'debug output' of allocated memory. - * - * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C - * - * Uncomment this macro to let the buffer allocator print out error messages. - */ -//#define MBEDTLS_MEMORY_DEBUG - -/** - * \def MBEDTLS_MEMORY_BACKTRACE - * - * Include backtrace information with each allocated block. - * - * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C - * GLIBC-compatible backtrace() an backtrace_symbols() support - * - * Uncomment this macro to include backtrace information - */ -//#define MBEDTLS_MEMORY_BACKTRACE - -/** - * \def MBEDTLS_PK_RSA_ALT_SUPPORT - * - * Support external private RSA keys (eg from a HSM) in the PK layer. - * - * Comment this macro to disable support for external private RSA keys. - */ -#define MBEDTLS_PK_RSA_ALT_SUPPORT - -/** - * \def MBEDTLS_PKCS1_V15 - * - * Enable support for PKCS#1 v1.5 encoding. - * - * Requires: MBEDTLS_RSA_C - * - * This enables support for PKCS#1 v1.5 operations. - */ -#define MBEDTLS_PKCS1_V15 - -/** - * \def MBEDTLS_PKCS1_V21 - * - * Enable support for PKCS#1 v2.1 encoding. - * - * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C - * - * This enables support for RSAES-OAEP and RSASSA-PSS operations. - */ -#define MBEDTLS_PKCS1_V21 - -/** - * \def MBEDTLS_RSA_NO_CRT - * - * Do not use the Chinese Remainder Theorem for the RSA private operation. - * - * Uncomment this macro to disable the use of CRT in RSA. - * - */ -//#define MBEDTLS_RSA_NO_CRT - -/** - * \def MBEDTLS_SELF_TEST - * - * Enable the checkup functions (*_self_test). - */ -#define MBEDTLS_SELF_TEST - -/** - * \def MBEDTLS_SHA256_SMALLER - * - * Enable an implementation of SHA-256 that has lower ROM footprint but also - * lower performance. - * - * The default implementation is meant to be a reasonnable compromise between - * performance and size. This version optimizes more aggressively for size at - * the expense of performance. Eg on Cortex-M4 it reduces the size of - * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about - * 30%. - * - * Uncomment to enable the smaller implementation of SHA256. - */ -//#define MBEDTLS_SHA256_SMALLER - -/** - * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES - * - * Enable sending of alert messages in case of encountered errors as per RFC. - * If you choose not to send the alert messages, mbed TLS can still communicate - * with other servers, only debugging of failures is harder. - * - * The advantage of not sending alert messages, is that no information is given - * about reasons for failures thus preventing adversaries of gaining intel. - * - * Enable sending of all alert messages - */ -#define MBEDTLS_SSL_ALL_ALERT_MESSAGES - -/** - * \def MBEDTLS_SSL_DEBUG_ALL - * - * Enable the debug messages in SSL module for all issues. - * Debug messages have been disabled in some places to prevent timing - * attacks due to (unbalanced) debugging function calls. - * - * If you need all error reporting you should enable this during debugging, - * but remove this for production servers that should log as well. - * - * Uncomment this macro to report all debug messages on errors introducing - * a timing side-channel. - * - */ -//#define MBEDTLS_SSL_DEBUG_ALL - -/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC - * - * Enable support for Encrypt-then-MAC, RFC 7366. - * - * This allows peers that both support it to use a more robust protection for - * ciphersuites using CBC, providing deep resistance against timing attacks - * on the padding or underlying cipher. - * - * This only affects CBC ciphersuites, and is useless if none is defined. - * - * Requires: MBEDTLS_SSL_PROTO_TLS1 or - * MBEDTLS_SSL_PROTO_TLS1_1 or - * MBEDTLS_SSL_PROTO_TLS1_2 - * - * Comment this macro to disable support for Encrypt-then-MAC - */ -#define MBEDTLS_SSL_ENCRYPT_THEN_MAC - -/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET - * - * Enable support for Extended Master Secret, aka Session Hash - * (draft-ietf-tls-session-hash-02). - * - * This was introduced as "the proper fix" to the Triple Handshake familiy of - * attacks, but it is recommended to always use it (even if you disable - * renegotiation), since it actually fixes a more fundamental issue in the - * original SSL/TLS design, and has implications beyond Triple Handshake. - * - * Requires: MBEDTLS_SSL_PROTO_TLS1 or - * MBEDTLS_SSL_PROTO_TLS1_1 or - * MBEDTLS_SSL_PROTO_TLS1_2 - * - * Comment this macro to disable support for Extended Master Secret. - */ -#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET - -/** - * \def MBEDTLS_SSL_FALLBACK_SCSV - * - * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00). - * - * For servers, it is recommended to always enable this, unless you support - * only one version of TLS, or know for sure that none of your clients - * implements a fallback strategy. - * - * For clients, you only need this if you're using a fallback strategy, which - * is not recommended in the first place, unless you absolutely need it to - * interoperate with buggy (version-intolerant) servers. - * - * Comment this macro to disable support for FALLBACK_SCSV - */ -#define MBEDTLS_SSL_FALLBACK_SCSV - -/** - * \def MBEDTLS_SSL_HW_RECORD_ACCEL - * - * Enable hooking functions in SSL module for hardware acceleration of - * individual records. - * - * Uncomment this macro to enable hooking functions. - */ -//#define MBEDTLS_SSL_HW_RECORD_ACCEL - -/** - * \def MBEDTLS_SSL_CBC_RECORD_SPLITTING - * - * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0. - * - * This is a countermeasure to the BEAST attack, which also minimizes the risk - * of interoperability issues compared to sending 0-length records. - * - * Comment this macro to disable 1/n-1 record splitting. - */ -#define MBEDTLS_SSL_CBC_RECORD_SPLITTING - -/** - * \def MBEDTLS_SSL_RENEGOTIATION - * - * Disable support for TLS renegotiation. - * - * The two main uses of renegotiation are (1) refresh keys on long-lived - * connections and (2) client authentication after the initial handshake. - * If you don't need renegotiation, it's probably better to disable it, since - * it has been associated with security issues in the past and is easy to - * misuse/misunderstand. - * - * Comment this to disable support for renegotiation. - */ -#define MBEDTLS_SSL_RENEGOTIATION - -/** - * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO - * - * Enable support for receiving and parsing SSLv2 Client Hello messages for the - * SSL Server module (MBEDTLS_SSL_SRV_C). - * - * Uncomment this macro to enable support for SSLv2 Client Hello messages. - */ -//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO - -/** - * \def MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE - * - * Pick the ciphersuite according to the client's preferences rather than ours - * in the SSL Server module (MBEDTLS_SSL_SRV_C). - * - * Uncomment this macro to respect client's ciphersuite order - */ -//#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE - -/** - * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH - * - * Enable support for RFC 6066 max_fragment_length extension in SSL. - * - * Comment this macro to disable support for the max_fragment_length extension - */ -#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH - -/** - * \def MBEDTLS_SSL_PROTO_SSL3 - * - * Enable support for SSL 3.0. - * - * Requires: MBEDTLS_MD5_C - * MBEDTLS_SHA1_C - * - * Comment this macro to disable support for SSL 3.0 - */ -//#define MBEDTLS_SSL_PROTO_SSL3 - -/** - * \def MBEDTLS_SSL_PROTO_TLS1 - * - * Enable support for TLS 1.0. - * - * Requires: MBEDTLS_MD5_C - * MBEDTLS_SHA1_C - * - * Comment this macro to disable support for TLS 1.0 - */ -#define MBEDTLS_SSL_PROTO_TLS1 - -/** - * \def MBEDTLS_SSL_PROTO_TLS1_1 - * - * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled). - * - * Requires: MBEDTLS_MD5_C - * MBEDTLS_SHA1_C - * - * Comment this macro to disable support for TLS 1.1 / DTLS 1.0 - */ -#define MBEDTLS_SSL_PROTO_TLS1_1 - -/** - * \def MBEDTLS_SSL_PROTO_TLS1_2 - * - * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). - * - * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C - * (Depends on ciphersuites) - * - * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 - */ -#define MBEDTLS_SSL_PROTO_TLS1_2 - -/** - * \def MBEDTLS_SSL_PROTO_DTLS - * - * Enable support for DTLS (all available versions). - * - * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0, - * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. - * - * Requires: MBEDTLS_SSL_PROTO_TLS1_1 - * or MBEDTLS_SSL_PROTO_TLS1_2 - * - * Comment this macro to disable support for DTLS - */ -#define MBEDTLS_SSL_PROTO_DTLS - -/** - * \def MBEDTLS_SSL_ALPN - * - * Enable support for RFC 7301 Application Layer Protocol Negotiation. - * - * Comment this macro to disable support for ALPN. - */ -#define MBEDTLS_SSL_ALPN - -/** - * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY - * - * Enable support for the anti-replay mechanism in DTLS. - * - * Requires: MBEDTLS_SSL_TLS_C - * MBEDTLS_SSL_PROTO_DTLS - * - * \warning Disabling this is often a security risk! - * See mbedtls_ssl_conf_dtls_anti_replay() for details. - * - * Comment this to disable anti-replay in DTLS. - */ -#define MBEDTLS_SSL_DTLS_ANTI_REPLAY - -/** - * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY - * - * Enable support for HelloVerifyRequest on DTLS servers. - * - * This feature is highly recommended to prevent DTLS servers being used as - * amplifiers in DoS attacks against other hosts. It should always be enabled - * unless you know for sure amplification cannot be a problem in the - * environment in which your server operates. - * - * \warning Disabling this can ba a security risk! (see above) - * - * Requires: MBEDTLS_SSL_PROTO_DTLS - * - * Comment this to disable support for HelloVerifyRequest. - */ -#define MBEDTLS_SSL_DTLS_HELLO_VERIFY - -/** - * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE - * - * Enable server-side support for clients that reconnect from the same port. - * - * Some clients unexpectedly close the connection and try to reconnect using the - * same source port. This needs special support from the server to handle the - * new connection securely, as described in section 4.2.8 of RFC 6347. This - * flag enables that support. - * - * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY - * - * Comment this to disable support for clients reusing the source port. - */ -#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE - -/** - * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT - * - * Enable support for a limit of records with bad MAC. - * - * See mbedtls_ssl_conf_dtls_badmac_limit(). - * - * Requires: MBEDTLS_SSL_PROTO_DTLS - */ -#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT - -/** - * \def MBEDTLS_SSL_SESSION_TICKETS - * - * Enable support for RFC 5077 session tickets in SSL. - * Client-side, provides full support for session tickets (maintainance of a - * session store remains the responsibility of the application, though). - * Server-side, you also need to provide callbacks for writing and parsing - * tickets, including authenticated encryption and key management. Example - * callbacks are provided by MBEDTLS_SSL_TICKET_C. - * - * Comment this macro to disable support for SSL session tickets - */ -#define MBEDTLS_SSL_SESSION_TICKETS - -/** - * \def MBEDTLS_SSL_EXPORT_KEYS - * - * Enable support for exporting key block and master secret. - * This is required for certain users of TLS, e.g. EAP-TLS. - * - * Comment this macro to disable support for key export - */ -#define MBEDTLS_SSL_EXPORT_KEYS - -/** - * \def MBEDTLS_SSL_SERVER_NAME_INDICATION - * - * Enable support for RFC 6066 server name indication (SNI) in SSL. - * - * Requires: MBEDTLS_X509_CRT_PARSE_C - * - * Comment this macro to disable support for server name indication in SSL - */ -#define MBEDTLS_SSL_SERVER_NAME_INDICATION - -/** - * \def MBEDTLS_SSL_TRUNCATED_HMAC - * - * Enable support for RFC 6066 truncated HMAC in SSL. - * - * Comment this macro to disable support for truncated HMAC in SSL - */ -#define MBEDTLS_SSL_TRUNCATED_HMAC - -/** - * \def MBEDTLS_THREADING_ALT - * - * Provide your own alternate threading implementation. - * - * Requires: MBEDTLS_THREADING_C - * - * Uncomment this to allow your own alternate threading implementation. - */ -//#define MBEDTLS_THREADING_ALT - -/** - * \def MBEDTLS_THREADING_PTHREAD - * - * Enable the pthread wrapper layer for the threading layer. - * - * Requires: MBEDTLS_THREADING_C - * - * Uncomment this to enable pthread mutexes. - */ -//#define MBEDTLS_THREADING_PTHREAD - -/** - * \def MBEDTLS_VERSION_FEATURES - * - * Allow run-time checking of compile-time enabled features. Thus allowing users - * to check at run-time if the library is for instance compiled with threading - * support via mbedtls_version_check_feature(). - * - * Requires: MBEDTLS_VERSION_C - * - * Comment this to disable run-time checking and save ROM space - */ -#define MBEDTLS_VERSION_FEATURES - -/** - * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 - * - * If set, the X509 parser will not break-off when parsing an X509 certificate - * and encountering an extension in a v1 or v2 certificate. - * - * Uncomment to prevent an error. - */ -//#define MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 - -/** - * \def MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION - * - * If set, the X509 parser will not break-off when parsing an X509 certificate - * and encountering an unknown critical extension. - * - * \warning Depending on your PKI use, enabling this can be a security risk! - * - * Uncomment to prevent an error. - */ -//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION - -/** - * \def MBEDTLS_X509_CHECK_KEY_USAGE - * - * Enable verification of the keyUsage extension (CA and leaf certificates). - * - * Disabling this avoids problems with mis-issued and/or misused - * (intermediate) CA and leaf certificates. - * - * \warning Depending on your PKI use, disabling this can be a security risk! - * - * Comment to skip keyUsage checking for both CA and leaf certificates. - */ -#define MBEDTLS_X509_CHECK_KEY_USAGE - -/** - * \def MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE - * - * Enable verification of the extendedKeyUsage extension (leaf certificates). - * - * Disabling this avoids problems with mis-issued and/or misused certificates. - * - * \warning Depending on your PKI use, disabling this can be a security risk! - * - * Comment to skip extendedKeyUsage checking for certificates. - */ -#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE - -/** - * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT - * - * Enable parsing and verification of X.509 certificates, CRLs and CSRS - * signed with RSASSA-PSS (aka PKCS#1 v2.1). - * - * Comment this macro to disallow using RSASSA-PSS in certificates. - */ -#define MBEDTLS_X509_RSASSA_PSS_SUPPORT - -/** - * \def MBEDTLS_ZLIB_SUPPORT - * - * If set, the SSL/TLS module uses ZLIB to support compression and - * decompression of packet data. - * - * \warning TLS-level compression MAY REDUCE SECURITY! See for example the - * CRIME attack. Before enabling this option, you should examine with care if - * CRIME or similar exploits may be a applicable to your use case. - * - * \note Currently compression can't be used with DTLS. - * - * Used in: library/ssl_tls.c - * library/ssl_cli.c - * library/ssl_srv.c - * - * This feature requires zlib library and headers to be present. - * - * Uncomment to enable use of ZLIB - */ -//#define MBEDTLS_ZLIB_SUPPORT -/* \} name SECTION: mbed TLS feature support */ - -/** - * \name SECTION: mbed TLS modules - * - * This section enables or disables entire modules in mbed TLS - * \{ - */ - -/** - * \def MBEDTLS_AESNI_C - * - * Enable AES-NI support on x86-64. - * - * Module: library/aesni.c - * Caller: library/aes.c - * - * Requires: MBEDTLS_HAVE_ASM - * - * This modules adds support for the AES-NI instructions on x86-64 - */ -#define MBEDTLS_AESNI_C - -/** - * \def MBEDTLS_AES_C - * - * Enable the AES block cipher. - * - * Module: library/aes.c - * Caller: library/ssl_tls.c - * library/pem.c - * library/ctr_drbg.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 - * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 - * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 - * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 - * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 - * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA - * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 - * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 - * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA - * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 - * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 - * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA - * - * PEM_PARSE uses AES for decrypting encrypted keys. - */ -#define MBEDTLS_AES_C - -/** - * \def MBEDTLS_ARC4_C - * - * Enable the ARCFOUR stream cipher. - * - * Module: library/arc4.c - * Caller: library/ssl_tls.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA - * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA - * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA - * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA - * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA - * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA - * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 - * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA - * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA - */ -#define MBEDTLS_ARC4_C - -/** - * \def MBEDTLS_ASN1_PARSE_C - * - * Enable the generic ASN1 parser. - * - * Module: library/asn1.c - * Caller: library/x509.c - * library/dhm.c - * library/pkcs12.c - * library/pkcs5.c - * library/pkparse.c - */ -#define MBEDTLS_ASN1_PARSE_C - -/** - * \def MBEDTLS_ASN1_WRITE_C - * - * Enable the generic ASN1 writer. - * - * Module: library/asn1write.c - * Caller: library/ecdsa.c - * library/pkwrite.c - * library/x509_create.c - * library/x509write_crt.c - * library/x509write_csr.c - */ -#define MBEDTLS_ASN1_WRITE_C - -/** - * \def MBEDTLS_BASE64_C - * - * Enable the Base64 module. - * - * Module: library/base64.c - * Caller: library/pem.c - * - * This module is required for PEM support (required by X.509). - */ -#define MBEDTLS_BASE64_C - -/** - * \def MBEDTLS_BIGNUM_C - * - * Enable the multi-precision integer library. - * - * Module: library/bignum.c - * Caller: library/dhm.c - * library/ecp.c - * library/ecdsa.c - * library/rsa.c - * library/ssl_tls.c - * - * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. - */ -#define MBEDTLS_BIGNUM_C - -/** - * \def MBEDTLS_BLOWFISH_C - * - * Enable the Blowfish block cipher. - * - * Module: library/blowfish.c - */ -#define MBEDTLS_BLOWFISH_C - -/** - * \def MBEDTLS_CAMELLIA_C - * - * Enable the Camellia block cipher. - * - * Module: library/camellia.c - * Caller: library/ssl_tls.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 - * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 - * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 - * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 - * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 - * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 - * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA - * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA - * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 - */ -#define MBEDTLS_CAMELLIA_C - -/** - * \def MBEDTLS_CCM_C - * - * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. - * - * Module: library/ccm.c - * - * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C - * - * This module enables the AES-CCM ciphersuites, if other requisites are - * enabled as well. - */ -#define MBEDTLS_CCM_C - -/** - * \def MBEDTLS_CERTS_C - * - * Enable the test certificates. - * - * Module: library/certs.c - * Caller: - * - * This module is used for testing (ssl_client/server). - */ -#define MBEDTLS_CERTS_C - -/** - * \def MBEDTLS_CIPHER_C - * - * Enable the generic cipher layer. - * - * Module: library/cipher.c - * Caller: library/ssl_tls.c - * - * Uncomment to enable generic cipher wrappers. - */ -#define MBEDTLS_CIPHER_C - -/** - * \def MBEDTLS_CMAC_C - * - * Enable the CMAC (Cipher-based Message Authentication Code) mode for block - * ciphers. - * - * Module: library/cmac.c - * - * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C - * - */ -//#define MBEDTLS_CMAC_C - -/** - * \def MBEDTLS_CTR_DRBG_C - * - * Enable the CTR_DRBG AES-256-based random generator. - * - * Module: library/ctr_drbg.c - * Caller: - * - * Requires: MBEDTLS_AES_C - * - * This module provides the CTR_DRBG AES-256 random number generator. - */ -#define MBEDTLS_CTR_DRBG_C - -/** - * \def MBEDTLS_DEBUG_C - * - * Enable the debug functions. - * - * Module: library/debug.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * This module provides debugging functions. - */ -#define MBEDTLS_DEBUG_C - -/** - * \def MBEDTLS_DES_C - * - * Enable the DES block cipher. - * - * Module: library/des.c - * Caller: library/pem.c - * library/ssl_tls.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA - * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA - * - * PEM_PARSE uses DES/3DES for decrypting encrypted keys. - */ -#define MBEDTLS_DES_C - -/** - * \def MBEDTLS_DHM_C - * - * Enable the Diffie-Hellman-Merkle module. - * - * Module: library/dhm.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * This module is used by the following key exchanges: - * DHE-RSA, DHE-PSK - */ -#define MBEDTLS_DHM_C - -/** - * \def MBEDTLS_ECDH_C - * - * Enable the elliptic curve Diffie-Hellman library. - * - * Module: library/ecdh.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * This module is used by the following key exchanges: - * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK - * - * Requires: MBEDTLS_ECP_C - */ -#define MBEDTLS_ECDH_C - -/** - * \def MBEDTLS_ECDSA_C - * - * Enable the elliptic curve DSA library. - * - * Module: library/ecdsa.c - * Caller: - * - * This module is used by the following key exchanges: - * ECDHE-ECDSA - * - * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C - */ -#define MBEDTLS_ECDSA_C - -/** - * \def MBEDTLS_ECJPAKE_C - * - * Enable the elliptic curve J-PAKE library. - * - * \warning This is currently experimental. EC J-PAKE support is based on the - * Thread v1.0.0 specification; incompatible changes to the specification - * might still happen. For this reason, this is disabled by default. - * - * Module: library/ecjpake.c - * Caller: - * - * This module is used by the following key exchanges: - * ECJPAKE - * - * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C - */ -//#define MBEDTLS_ECJPAKE_C - -/** - * \def MBEDTLS_ECP_C - * - * Enable the elliptic curve over GF(p) library. - * - * Module: library/ecp.c - * Caller: library/ecdh.c - * library/ecdsa.c - * library/ecjpake.c - * - * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED - */ -#define MBEDTLS_ECP_C - -/** - * \def MBEDTLS_ENTROPY_C - * - * Enable the platform-specific entropy code. - * - * Module: library/entropy.c - * Caller: - * - * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C - * - * This module provides a generic entropy pool - */ -#define MBEDTLS_ENTROPY_C - -/** - * \def MBEDTLS_ERROR_C - * - * Enable error code to error string conversion. - * - * Module: library/error.c - * Caller: - * - * This module enables mbedtls_strerror(). - */ -#define MBEDTLS_ERROR_C - -/** - * \def MBEDTLS_GCM_C - * - * Enable the Galois/Counter Mode (GCM) for AES. - * - * Module: library/gcm.c - * - * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C - * - * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other - * requisites are enabled as well. - */ -#define MBEDTLS_GCM_C - -/** - * \def MBEDTLS_HAVEGE_C - * - * Enable the HAVEGE random generator. - * - * Warning: the HAVEGE random generator is not suitable for virtualized - * environments - * - * Warning: the HAVEGE random generator is dependent on timing and specific - * processor traits. It is therefore not advised to use HAVEGE as - * your applications primary random generator or primary entropy pool - * input. As a secondary input to your entropy pool, it IS able add - * the (limited) extra entropy it provides. - * - * Module: library/havege.c - * Caller: - * - * Requires: MBEDTLS_TIMING_C - * - * Uncomment to enable the HAVEGE random generator. - */ -//#define MBEDTLS_HAVEGE_C - -/** - * \def MBEDTLS_HMAC_DRBG_C - * - * Enable the HMAC_DRBG random generator. - * - * Module: library/hmac_drbg.c - * Caller: - * - * Requires: MBEDTLS_MD_C - * - * Uncomment to enable the HMAC_DRBG random number geerator. - */ -#define MBEDTLS_HMAC_DRBG_C - -/** - * \def MBEDTLS_MD_C - * - * Enable the generic message digest layer. - * - * Module: library/md.c - * Caller: - * - * Uncomment to enable generic message digest wrappers. - */ -#define MBEDTLS_MD_C - -/** - * \def MBEDTLS_MD2_C - * - * Enable the MD2 hash algorithm. - * - * Module: library/md2.c - * Caller: - * - * Uncomment to enable support for (rare) MD2-signed X.509 certs. - */ -//#define MBEDTLS_MD2_C - -/** - * \def MBEDTLS_MD4_C - * - * Enable the MD4 hash algorithm. - * - * Module: library/md4.c - * Caller: - * - * Uncomment to enable support for (rare) MD4-signed X.509 certs. - */ -//#define MBEDTLS_MD4_C - -/** - * \def MBEDTLS_MD5_C - * - * Enable the MD5 hash algorithm. - * - * Module: library/md5.c - * Caller: library/md.c - * library/pem.c - * library/ssl_tls.c - * - * This module is required for SSL/TLS and X.509. - * PEM_PARSE uses MD5 for decrypting encrypted keys. - */ -#define MBEDTLS_MD5_C - -/** - * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C - * - * Enable the buffer allocator implementation that makes use of a (stack) - * based buffer to 'allocate' dynamic memory. (replaces calloc() and free() - * calls) - * - * Module: library/memory_buffer_alloc.c - * - * Requires: MBEDTLS_PLATFORM_C - * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS) - * - * Enable this module to enable the buffer memory allocator. - */ -//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C - -/** - * \def MBEDTLS_NET_C - * - * Enable the TCP and UDP over IPv6/IPv4 networking routines. - * - * \note This module only works on POSIX/Unix (including Linux, BSD and OS X) - * and Windows. For other platforms, you'll want to disable it, and write your - * own networking callbacks to be passed to \c mbedtls_ssl_set_bio(). - * - * \note See also our Knowledge Base article about porting to a new - * environment: - * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS - * - * Module: library/net_sockets.c - * - * This module provides networking routines. - */ -#define MBEDTLS_NET_C - -/** - * \def MBEDTLS_OID_C - * - * Enable the OID database. - * - * Module: library/oid.c - * Caller: library/asn1write.c - * library/pkcs5.c - * library/pkparse.c - * library/pkwrite.c - * library/rsa.c - * library/x509.c - * library/x509_create.c - * library/x509_crl.c - * library/x509_crt.c - * library/x509_csr.c - * library/x509write_crt.c - * library/x509write_csr.c - * - * This modules translates between OIDs and internal values. - */ -#define MBEDTLS_OID_C - -/** - * \def MBEDTLS_PADLOCK_C - * - * Enable VIA Padlock support on x86. - * - * Module: library/padlock.c - * Caller: library/aes.c - * - * Requires: MBEDTLS_HAVE_ASM - * - * This modules adds support for the VIA PadLock on x86. - */ -#define MBEDTLS_PADLOCK_C - -/** - * \def MBEDTLS_PEM_PARSE_C - * - * Enable PEM decoding / parsing. - * - * Module: library/pem.c - * Caller: library/dhm.c - * library/pkparse.c - * library/x509_crl.c - * library/x509_crt.c - * library/x509_csr.c - * - * Requires: MBEDTLS_BASE64_C - * - * This modules adds support for decoding / parsing PEM files. - */ -#define MBEDTLS_PEM_PARSE_C - -/** - * \def MBEDTLS_PEM_WRITE_C - * - * Enable PEM encoding / writing. - * - * Module: library/pem.c - * Caller: library/pkwrite.c - * library/x509write_crt.c - * library/x509write_csr.c - * - * Requires: MBEDTLS_BASE64_C - * - * This modules adds support for encoding / writing PEM files. - */ -#define MBEDTLS_PEM_WRITE_C - -/** - * \def MBEDTLS_PK_C - * - * Enable the generic public (asymetric) key layer. - * - * Module: library/pk.c - * Caller: library/ssl_tls.c - * library/ssl_cli.c - * library/ssl_srv.c - * - * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C - * - * Uncomment to enable generic public key wrappers. - */ -#define MBEDTLS_PK_C - -/** - * \def MBEDTLS_PK_PARSE_C - * - * Enable the generic public (asymetric) key parser. - * - * Module: library/pkparse.c - * Caller: library/x509_crt.c - * library/x509_csr.c - * - * Requires: MBEDTLS_PK_C - * - * Uncomment to enable generic public key parse functions. - */ -#define MBEDTLS_PK_PARSE_C - -/** - * \def MBEDTLS_PK_WRITE_C - * - * Enable the generic public (asymetric) key writer. - * - * Module: library/pkwrite.c - * Caller: library/x509write.c - * - * Requires: MBEDTLS_PK_C - * - * Uncomment to enable generic public key write functions. - */ -#define MBEDTLS_PK_WRITE_C - -/** - * \def MBEDTLS_PKCS5_C - * - * Enable PKCS#5 functions. - * - * Module: library/pkcs5.c - * - * Requires: MBEDTLS_MD_C - * - * This module adds support for the PKCS#5 functions. - */ -#define MBEDTLS_PKCS5_C - -/** - * \def MBEDTLS_PKCS11_C - * - * Enable wrapper for PKCS#11 smartcard support. - * - * Module: library/pkcs11.c - * Caller: library/pk.c - * - * Requires: MBEDTLS_PK_C - * - * This module enables SSL/TLS PKCS #11 smartcard support. - * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) - */ -//#define MBEDTLS_PKCS11_C - -/** - * \def MBEDTLS_PKCS12_C - * - * Enable PKCS#12 PBE functions. - * Adds algorithms for parsing PKCS#8 encrypted private keys - * - * Module: library/pkcs12.c - * Caller: library/pkparse.c - * - * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C - * Can use: MBEDTLS_ARC4_C - * - * This module enables PKCS#12 functions. - */ -#define MBEDTLS_PKCS12_C - -/** - * \def MBEDTLS_PLATFORM_C - * - * Enable the platform abstraction layer that allows you to re-assign - * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). - * - * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT - * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned - * above to be specified at runtime or compile time respectively. - * - * \note This abstraction layer must be enabled on Windows (including MSYS2) - * as other module rely on it for a fixed snprintf implementation. - * - * Module: library/platform.c - * Caller: Most other .c files - * - * This module enables abstraction of common (libc) functions. - */ -#define MBEDTLS_PLATFORM_C - -/** - * \def MBEDTLS_RIPEMD160_C - * - * Enable the RIPEMD-160 hash algorithm. - * - * Module: library/ripemd160.c - * Caller: library/md.c - * - */ -#define MBEDTLS_RIPEMD160_C - -/** - * \def MBEDTLS_RSA_C - * - * Enable the RSA public-key cryptosystem. - * - * Module: library/rsa.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509.c - * - * This module is used by the following key exchanges: - * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK - * - * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C - */ -#define MBEDTLS_RSA_C - -/** - * \def MBEDTLS_SHA1_C - * - * Enable the SHA1 cryptographic hash algorithm. - * - * Module: library/sha1.c - * Caller: library/md.c - * library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509write_crt.c - * - * This module is required for SSL/TLS up to version 1.1, for TLS 1.2 - * depending on the handshake parameters, and for SHA1-signed certificates. - */ -#define MBEDTLS_SHA1_C - -/** - * \def MBEDTLS_SHA256_C - * - * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. - * - * Module: library/sha256.c - * Caller: library/entropy.c - * library/md.c - * library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * This module adds support for SHA-224 and SHA-256. - * This module is required for the SSL/TLS 1.2 PRF function. - */ -#define MBEDTLS_SHA256_C - -/** - * \def MBEDTLS_SHA512_C - * - * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. - * - * Module: library/sha512.c - * Caller: library/entropy.c - * library/md.c - * library/ssl_cli.c - * library/ssl_srv.c - * - * This module adds support for SHA-384 and SHA-512. - */ -#define MBEDTLS_SHA512_C - -/** - * \def MBEDTLS_SSL_CACHE_C - * - * Enable simple SSL cache implementation. - * - * Module: library/ssl_cache.c - * Caller: - * - * Requires: MBEDTLS_SSL_CACHE_C - */ -#define MBEDTLS_SSL_CACHE_C - -/** - * \def MBEDTLS_SSL_COOKIE_C - * - * Enable basic implementation of DTLS cookies for hello verification. - * - * Module: library/ssl_cookie.c - * Caller: - */ -#define MBEDTLS_SSL_COOKIE_C - -/** - * \def MBEDTLS_SSL_TICKET_C - * - * Enable an implementation of TLS server-side callbacks for session tickets. - * - * Module: library/ssl_ticket.c - * Caller: - * - * Requires: MBEDTLS_CIPHER_C - */ -#define MBEDTLS_SSL_TICKET_C - -/** - * \def MBEDTLS_SSL_CLI_C - * - * Enable the SSL/TLS client code. - * - * Module: library/ssl_cli.c - * Caller: - * - * Requires: MBEDTLS_SSL_TLS_C - * - * This module is required for SSL/TLS client support. - */ -#define MBEDTLS_SSL_CLI_C - -/** - * \def MBEDTLS_SSL_SRV_C - * - * Enable the SSL/TLS server code. - * - * Module: library/ssl_srv.c - * Caller: - * - * Requires: MBEDTLS_SSL_TLS_C - * - * This module is required for SSL/TLS server support. - */ -#define MBEDTLS_SSL_SRV_C - -/** - * \def MBEDTLS_SSL_TLS_C - * - * Enable the generic SSL/TLS code. - * - * Module: library/ssl_tls.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C - * and at least one of the MBEDTLS_SSL_PROTO_XXX defines - * - * This module is required for SSL/TLS. - */ -#define MBEDTLS_SSL_TLS_C - -/** - * \def MBEDTLS_THREADING_C - * - * Enable the threading abstraction layer. - * By default mbed TLS assumes it is used in a non-threaded environment or that - * contexts are not shared between threads. If you do intend to use contexts - * between threads, you will need to enable this layer to prevent race - * conditions. See also our Knowledge Base article about threading: - * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading - * - * Module: library/threading.c - * - * This allows different threading implementations (self-implemented or - * provided). - * - * You will have to enable either MBEDTLS_THREADING_ALT or - * MBEDTLS_THREADING_PTHREAD. - * - * Enable this layer to allow use of mutexes within mbed TLS - */ -//#define MBEDTLS_THREADING_C - -/** - * \def MBEDTLS_TIMING_C - * - * Enable the semi-portable timing interface. - * - * \note The provided implementation only works on POSIX/Unix (including Linux, - * BSD and OS X) and Windows. On other platforms, you can either disable that - * module and provide your own implementations of the callbacks needed by - * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide - * your own implementation of the whole module by setting - * \c MBEDTLS_TIMING_ALT in the current file. - * - * \note See also our Knowledge Base article about porting to a new - * environment: - * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS - * - * Module: library/timing.c - * Caller: library/havege.c - * - * This module is used by the HAVEGE random number generator. - */ -#define MBEDTLS_TIMING_C - -/** - * \def MBEDTLS_VERSION_C - * - * Enable run-time version information. - * - * Module: library/version.c - * - * This module provides run-time version information. - */ -#define MBEDTLS_VERSION_C - -/** - * \def MBEDTLS_X509_USE_C - * - * Enable X.509 core for using certificates. - * - * Module: library/x509.c - * Caller: library/x509_crl.c - * library/x509_crt.c - * library/x509_csr.c - * - * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, - * MBEDTLS_PK_PARSE_C - * - * This module is required for the X.509 parsing modules. - */ -#define MBEDTLS_X509_USE_C - -/** - * \def MBEDTLS_X509_CRT_PARSE_C - * - * Enable X.509 certificate parsing. - * - * Module: library/x509_crt.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * Requires: MBEDTLS_X509_USE_C - * - * This module is required for X.509 certificate parsing. - */ -#define MBEDTLS_X509_CRT_PARSE_C - -/** - * \def MBEDTLS_X509_CRL_PARSE_C - * - * Enable X.509 CRL parsing. - * - * Module: library/x509_crl.c - * Caller: library/x509_crt.c - * - * Requires: MBEDTLS_X509_USE_C - * - * This module is required for X.509 CRL parsing. - */ -#define MBEDTLS_X509_CRL_PARSE_C - -/** - * \def MBEDTLS_X509_CSR_PARSE_C - * - * Enable X.509 Certificate Signing Request (CSR) parsing. - * - * Module: library/x509_csr.c - * Caller: library/x509_crt_write.c - * - * Requires: MBEDTLS_X509_USE_C - * - * This module is used for reading X.509 certificate request. - */ -#define MBEDTLS_X509_CSR_PARSE_C - -/** - * \def MBEDTLS_X509_CREATE_C - * - * Enable X.509 core for creating certificates. - * - * Module: library/x509_create.c - * - * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C - * - * This module is the basis for creating X.509 certificates and CSRs. - */ -#define MBEDTLS_X509_CREATE_C - -/** - * \def MBEDTLS_X509_CRT_WRITE_C - * - * Enable creating X.509 certificates. - * - * Module: library/x509_crt_write.c - * - * Requires: MBEDTLS_X509_CREATE_C - * - * This module is required for X.509 certificate creation. - */ -#define MBEDTLS_X509_CRT_WRITE_C - -/** - * \def MBEDTLS_X509_CSR_WRITE_C - * - * Enable creating X.509 Certificate Signing Requests (CSR). - * - * Module: library/x509_csr_write.c - * - * Requires: MBEDTLS_X509_CREATE_C - * - * This module is required for X.509 certificate request writing. - */ -#define MBEDTLS_X509_CSR_WRITE_C - -/** - * \def MBEDTLS_XTEA_C - * - * Enable the XTEA block cipher. - * - * Module: library/xtea.c - * Caller: - */ -#define MBEDTLS_XTEA_C - -/* \} name SECTION: mbed TLS modules */ - -/** - * \name SECTION: Module configuration options - * - * This section allows for the setting of module specific sizes and - * configuration options. The default values are already present in the - * relevant header files and should suffice for the regular use cases. - * - * Our advice is to enable options and change their values here - * only if you have a good reason and know the consequences. - * - * Please check the respective header file for documentation on these - * parameters (to prevent duplicate documentation). - * \{ - */ - -/* MPI / BIGNUM options */ -//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ -//#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ - -/* CTR_DRBG options */ -//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ -//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ -//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ -//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ -//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ - -/* HMAC_DRBG options */ -//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ -//#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ -//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ -//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ - -/* ECP options */ -//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ -//#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ -//#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ - -/* Entropy options */ -//#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ -//#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ -//#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */ - -/* Memory buffer allocator options */ -//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ - -/* Platform options */ -//#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ -//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */ -//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ -//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ -//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ -//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ -//#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ -/* Note: your snprintf must correclty zero-terminate the buffer! */ -//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ -//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */ -//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */ -//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ -//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ -//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */ - -/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ -/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ -//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */ -//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */ -//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ -//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ -//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ -//#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ -//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ -/* Note: your snprintf must correclty zero-terminate the buffer! */ -//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ -//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ -//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ - -/* SSL Cache options */ -//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ -//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ - -/* SSL options */ -//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */ -//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ -//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ -//#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ - -/** - * Complete list of ciphersuites to use, in order of preference. - * - * \warning No dependency checking is done on that field! This option can only - * be used to restrict the set of available ciphersuites. It is your - * responsibility to make sure the needed modules are active. - * - * Use this to save a few hundred bytes of ROM (default ordering of all - * available ciphersuites) and a few to a few hundred bytes of RAM. - * - * The value below is only an example, not the default. - */ -//#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - -/* X509 options */ -//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ -//#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */ - -/** - * Allow SHA-1 in the default TLS configuration for certificate signing. - * Without this build-time option, SHA-1 support must be activated explicitly - * through mbedtls_ssl_conf_cert_profile. Turning on this option is not - * recommended because of it is possible to generte SHA-1 collisions, however - * this may be safe for legacy infrastructure where additional controls apply. - */ -// #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES - -/** - * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake - * signature and ciphersuite selection. Without this build-time option, SHA-1 - * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes. - * The use of SHA-1 in TLS <= 1.1 and in HMAC-SHA-1 is always allowed by - * default. At the time of writing, there is no practical attack on the use - * of SHA-1 in handshake signatures, hence this option is turned on by default - * for compatibility with existing peers. - */ -#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE - -/* \} name SECTION: Customisation configuration options */ - -/* Target and application specific configurations */ -//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "mbedtls/target_config.h" - -#if defined(TARGET_LIKE_MBED) && defined(YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE) -#include YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE -#endif - -/* - * Allow user to override any previous default. - * - * Use two macro names for that, as: - * - with yotta the prefix YOTTA_CFG_ is forced - * - without yotta is looks weird to have a YOTTA prefix. - */ -#if defined(YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE) -#include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE -#elif defined(MBEDTLS_USER_CONFIG_FILE) -#include MBEDTLS_USER_CONFIG_FILE -#endif - -#include "check_config.h" - -#endif /* MBEDTLS_CONFIG_H */ diff --git a/components/mbedtls/include/mbedtls/ctr_drbg.h b/components/mbedtls/include/mbedtls/ctr_drbg.h deleted file mode 100644 index 059d3c5c9a..0000000000 --- a/components/mbedtls/include/mbedtls/ctr_drbg.h +++ /dev/null @@ -1,290 +0,0 @@ -/** - * \file ctr_drbg.h - * - * \brief CTR_DRBG based on AES-256 (NIST SP 800-90) - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_CTR_DRBG_H -#define MBEDTLS_CTR_DRBG_H - -#include "aes.h" - -#if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" -#endif - -#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ -#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< Too many random requested in single call. */ -#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< Input too large (Entropy + additional). */ -#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read/write error in file. */ - -#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< Block size used by the cipher */ -#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< Key size used by the cipher */ -#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) -#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) - /**< The seed length (counter + AES key) */ - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -#if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) -#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ -#else -#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ -#endif -#endif - -#if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) -#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ -#endif - -#if !defined(MBEDTLS_CTR_DRBG_MAX_INPUT) -#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ -#endif - -#if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) -#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ -#endif - -#if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) -#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ -#endif - -/* \} name SECTION: Module settings */ - -#define MBEDTLS_CTR_DRBG_PR_OFF 0 /**< No prediction resistance */ -#define MBEDTLS_CTR_DRBG_PR_ON 1 /**< Prediction resistance enabled */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief CTR_DRBG context structure - */ -typedef struct -{ - unsigned char counter[16]; /*!< counter (V) */ - int reseed_counter; /*!< reseed counter */ - int prediction_resistance; /*!< enable prediction resistance (Automatic - reseed before every random generation) */ - size_t entropy_len; /*!< amount of entropy grabbed on each - (re)seed */ - int reseed_interval; /*!< reseed interval */ - - mbedtls_aes_context aes_ctx; /*!< AES context */ - - /* - * Callbacks (Entropy) - */ - int (*f_entropy)(void *, unsigned char *, size_t); - - void *p_entropy; /*!< context for the entropy function */ - -#if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; -#endif -} -mbedtls_ctr_drbg_context; - -/** - * \brief CTR_DRBG context initialization - * Makes the context ready for mbedtls_ctr_drbg_seed() or - * mbedtls_ctr_drbg_free(). - * - * \param ctx CTR_DRBG context to be initialized - */ -void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); - -/** - * \brief CTR_DRBG initial seeding - * Seed and setup entropy source for future reseeds. - * - * Note: Personalization data can be provided in addition to the more generic - * entropy source to make this instantiation as unique as possible. - * - * \param ctx CTR_DRBG context to be seeded - * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer - * length) - * \param p_entropy Entropy context - * \param custom Personalization data (Device specific identifiers) - * (Can be NULL) - * \param len Length of personalization data - * - * \return 0 if successful, or - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED - */ -int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len ); - -/** - * \brief Clear CTR_CRBG context data - * - * \param ctx CTR_DRBG context to clear - */ -void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ); - -/** - * \brief Enable / disable prediction resistance (Default: Off) - * - * Note: If enabled, entropy is used for ctx->entropy_len before each call! - * Only use this if you have ample supply of good entropy! - * - * \param ctx CTR_DRBG context - * \param resistance MBEDTLS_CTR_DRBG_PR_ON or MBEDTLS_CTR_DRBG_PR_OFF - */ -void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, - int resistance ); - -/** - * \brief Set the amount of entropy grabbed on each (re)seed - * (Default: MBEDTLS_CTR_DRBG_ENTROPY_LEN) - * - * \param ctx CTR_DRBG context - * \param len Amount of entropy to grab - */ -void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, - size_t len ); - -/** - * \brief Set the reseed interval - * (Default: MBEDTLS_CTR_DRBG_RESEED_INTERVAL) - * - * \param ctx CTR_DRBG context - * \param interval Reseed interval - */ -void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, - int interval ); - -/** - * \brief CTR_DRBG reseeding (extracts data from entropy source) - * - * \param ctx CTR_DRBG context - * \param additional Additional data to add to state (Can be NULL) - * \param len Length of additional data - * - * \return 0 if successful, or - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED - */ -int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, size_t len ); - -/** - * \brief CTR_DRBG update state - * - * \param ctx CTR_DRBG context - * \param additional Additional data to update state with - * \param add_len Length of additional data - * - * \note If add_len is greater than MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, - * only the first MBEDTLS_CTR_DRBG_MAX_SEED_INPUT bytes are used, - * the remaining ones are silently discarded. - */ -void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, size_t add_len ); - -/** - * \brief CTR_DRBG generate random with additional update input - * - * Note: Automatically reseeds if reseed_counter is reached. - * - * \param p_rng CTR_DRBG context - * \param output Buffer to fill - * \param output_len Length of the buffer - * \param additional Additional data to update with (Can be NULL) - * \param add_len Length of additional data - * - * \return 0 if successful, or - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or - * MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG - */ -int mbedtls_ctr_drbg_random_with_add( void *p_rng, - unsigned char *output, size_t output_len, - const unsigned char *additional, size_t add_len ); - -/** - * \brief CTR_DRBG generate random - * - * Note: Automatically reseeds if reseed_counter is reached. - * - * \param p_rng CTR_DRBG context - * \param output Buffer to fill - * \param output_len Length of the buffer - * - * \return 0 if successful, or - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED, or - * MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG - */ -int mbedtls_ctr_drbg_random( void *p_rng, - unsigned char *output, size_t output_len ); - -#if defined(MBEDTLS_FS_IO) -/** - * \brief Write a seed file - * - * \param ctx CTR_DRBG context - * \param path Name of the file - * - * \return 0 if successful, - * MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error, or - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED - */ -int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); - -/** - * \brief Read and update a seed file. Seed is added to this - * instance - * - * \param ctx CTR_DRBG context - * \param path Name of the file - * - * \return 0 if successful, - * MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error, - * MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or - * MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG - */ -int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); -#endif /* MBEDTLS_FS_IO */ - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_ctr_drbg_self_test( int verbose ); - -/* Internal functions (do not call directly) */ -int mbedtls_ctr_drbg_seed_entropy_len( mbedtls_ctr_drbg_context *, - int (*)(void *, unsigned char *, size_t), void *, - const unsigned char *, size_t, size_t ); - -#ifdef __cplusplus -} -#endif - -#endif /* ctr_drbg.h */ diff --git a/components/mbedtls/include/mbedtls/debug.h b/components/mbedtls/include/mbedtls/debug.h deleted file mode 100644 index 2957996407..0000000000 --- a/components/mbedtls/include/mbedtls/debug.h +++ /dev/null @@ -1,228 +0,0 @@ -/** - * \file debug.h - * - * \brief Functions for controlling and providing debug output from the library. - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_DEBUG_H -#define MBEDTLS_DEBUG_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "ssl.h" - -#if defined(MBEDTLS_ECP_C) -#include "ecp.h" -#endif - -#if defined(MBEDTLS_DEBUG_C) - -#define MBEDTLS_DEBUG_STRIP_PARENS( ... ) __VA_ARGS__ - -#define MBEDTLS_SSL_DEBUG_MSG( level, args ) \ - mbedtls_debug_print_msg( ssl, level, __FILE__, __LINE__, \ - MBEDTLS_DEBUG_STRIP_PARENS args ) - -#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) \ - mbedtls_debug_print_ret( ssl, level, __FILE__, __LINE__, text, ret ) - -#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) \ - mbedtls_debug_print_buf( ssl, level, __FILE__, __LINE__, text, buf, len ) - -#if defined(MBEDTLS_BIGNUM_C) -#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) \ - mbedtls_debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X ) -#endif - -#if defined(MBEDTLS_ECP_C) -#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) \ - mbedtls_debug_print_ecp( ssl, level, __FILE__, __LINE__, text, X ) -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) \ - mbedtls_debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt ) -#endif - -#else /* MBEDTLS_DEBUG_C */ - -#define MBEDTLS_SSL_DEBUG_MSG( level, args ) do { } while( 0 ) -#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) do { } while( 0 ) -#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 ) -#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) do { } while( 0 ) -#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) do { } while( 0 ) -#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) - -#endif /* MBEDTLS_DEBUG_C */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Set the threshold error level to handle globally all debug output. - * Debug messages that have a level over the threshold value are - * discarded. - * (Default value: 0 = No debug ) - * - * \param threshold theshold level of messages to filter on. Messages at a - * higher level will be discarded. - * - Debug levels - * - 0 No debug - * - 1 Error - * - 2 State change - * - 3 Informational - * - 4 Verbose - */ -void mbedtls_debug_set_threshold( int threshold ); - -/** - * \brief Print a message to the debug output. This function is always used - * through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl - * context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the message has occurred in - * \param line line number the message has occurred at - * \param format format specifier, in printf format - * \param ... variables used by the format specifier - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *format, ... ); - -/** - * \brief Print the return value of a function to the debug output. This - * function is always used through the MBEDTLS_SSL_DEBUG_RET() macro, - * which supplies the ssl context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the error has occurred in - * \param line line number the error has occurred in - * \param text the name of the function that returned the error - * \param ret the return code value - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, int ret ); - -/** - * \brief Output a buffer of size len bytes to the debug output. This function - * is always used through the MBEDTLS_SSL_DEBUG_BUF() macro, - * which supplies the ssl context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the error has occurred in - * \param line line number the error has occurred in - * \param text a name or label for the buffer being dumped. Normally the - * variable or buffer name - * \param buf the buffer to be outputted - * \param len length of the buffer - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, const char *text, - const unsigned char *buf, size_t len ); - -#if defined(MBEDTLS_BIGNUM_C) -/** - * \brief Print a MPI variable to the debug output. This function is always - * used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the - * ssl context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the error has occurred in - * \param line line number the error has occurred in - * \param text a name or label for the MPI being output. Normally the - * variable name - * \param X the MPI variable - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_mpi *X ); -#endif - -#if defined(MBEDTLS_ECP_C) -/** - * \brief Print an ECP point to the debug output. This function is always - * used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the - * ssl context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the error has occurred in - * \param line line number the error has occurred in - * \param text a name or label for the ECP point being output. Normally the - * variable name - * \param X the ECP point - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_ecp_point *X ); -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/** - * \brief Print a X.509 certificate structure to the debug output. This - * function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro, - * which supplies the ssl context, file and line number parameters. - * - * \param ssl SSL context - * \param level error level of the debug message - * \param file file the error has occurred in - * \param line line number the error has occurred in - * \param text a name or label for the certificate being output - * \param crt X.509 certificate structure - * - * \attention This function is intended for INTERNAL usage within the - * library only. - */ -void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_x509_crt *crt ); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* debug.h */ - diff --git a/components/mbedtls/include/mbedtls/des.h b/components/mbedtls/include/mbedtls/des.h deleted file mode 100644 index 5ca2ecf2e0..0000000000 --- a/components/mbedtls/include/mbedtls/des.h +++ /dev/null @@ -1,306 +0,0 @@ -/** - * \file des.h - * - * \brief DES block cipher - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_DES_H -#define MBEDTLS_DES_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#define MBEDTLS_DES_ENCRYPT 1 -#define MBEDTLS_DES_DECRYPT 0 - -#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ - -#define MBEDTLS_DES_KEY_SIZE 8 - -#if !defined(MBEDTLS_DES_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief DES context structure - */ -typedef struct -{ - uint32_t sk[32]; /*!< DES subkeys */ -} -mbedtls_des_context; - -/** - * \brief Triple-DES context structure - */ -typedef struct -{ - uint32_t sk[96]; /*!< 3DES subkeys */ -} -mbedtls_des3_context; - -/** - * \brief Initialize DES context - * - * \param ctx DES context to be initialized - */ -void mbedtls_des_init( mbedtls_des_context *ctx ); - -/** - * \brief Clear DES context - * - * \param ctx DES context to be cleared - */ -void mbedtls_des_free( mbedtls_des_context *ctx ); - -/** - * \brief Initialize Triple-DES context - * - * \param ctx DES3 context to be initialized - */ -void mbedtls_des3_init( mbedtls_des3_context *ctx ); - -/** - * \brief Clear Triple-DES context - * - * \param ctx DES3 context to be cleared - */ -void mbedtls_des3_free( mbedtls_des3_context *ctx ); - -/** - * \brief Set key parity on the given key to odd. - * - * DES keys are 56 bits long, but each byte is padded with - * a parity bit to allow verification. - * - * \param key 8-byte secret key - */ -void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ); - -/** - * \brief Check that key parity on the given key is odd. - * - * DES keys are 56 bits long, but each byte is padded with - * a parity bit to allow verification. - * - * \param key 8-byte secret key - * - * \return 0 is parity was ok, 1 if parity was not correct. - */ -int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); - -/** - * \brief Check that key is not a weak or semi-weak DES key - * - * \param key 8-byte secret key - * - * \return 0 if no weak key was found, 1 if a weak key was identified. - */ -int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); - -/** - * \brief DES key schedule (56-bit, encryption) - * - * \param ctx DES context to be initialized - * \param key 8-byte secret key - * - * \return 0 - */ -int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); - -/** - * \brief DES key schedule (56-bit, decryption) - * - * \param ctx DES context to be initialized - * \param key 8-byte secret key - * - * \return 0 - */ -int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); - -/** - * \brief Triple-DES key schedule (112-bit, encryption) - * - * \param ctx 3DES context to be initialized - * \param key 16-byte secret key - * - * \return 0 - */ -int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); - -/** - * \brief Triple-DES key schedule (112-bit, decryption) - * - * \param ctx 3DES context to be initialized - * \param key 16-byte secret key - * - * \return 0 - */ -int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); - -/** - * \brief Triple-DES key schedule (168-bit, encryption) - * - * \param ctx 3DES context to be initialized - * \param key 24-byte secret key - * - * \return 0 - */ -int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); - -/** - * \brief Triple-DES key schedule (168-bit, decryption) - * - * \param ctx 3DES context to be initialized - * \param key 24-byte secret key - * - * \return 0 - */ -int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); - -/** - * \brief DES-ECB block encryption/decryption - * - * \param ctx DES context - * \param input 64-bit input block - * \param output 64-bit output block - * - * \return 0 if successful - */ -int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, - const unsigned char input[8], - unsigned char output[8] ); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/** - * \brief DES-CBC buffer encryption/decryption - * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. - * - * \param ctx DES context - * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - */ -int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ); -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -/** - * \brief 3DES-ECB block encryption/decryption - * - * \param ctx 3DES context - * \param input 64-bit input block - * \param output 64-bit output block - * - * \return 0 if successful - */ -int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, - const unsigned char input[8], - unsigned char output[8] ); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/** - * \brief 3DES-CBC buffer encryption/decryption - * - * \note Upon exit, the content of the IV is updated so that you can - * call the function same function again on the following - * block(s) of data and get the same result as if it was - * encrypted in one call. This allows a "streaming" usage. - * If on the other hand you need to retain the contents of the - * IV, you should either save it manually or use the cipher - * module instead. - * - * \param ctx 3DES context - * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH - */ -int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ); -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -/** - * \brief Internal function for key expansion. - * (Only exposed to allow overriding it, - * see MBEDTLS_DES_SETKEY_ALT) - * - * \param SK Round keys - * \param key Base key - */ -void mbedtls_des_setkey( uint32_t SK[32], - const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_DES_ALT */ -#include "des_alt.h" -#endif /* MBEDTLS_DES_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_des_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* des.h */ diff --git a/components/mbedtls/include/mbedtls/dhm.h b/components/mbedtls/include/mbedtls/dhm.h deleted file mode 100644 index d7ab1522ec..0000000000 --- a/components/mbedtls/include/mbedtls/dhm.h +++ /dev/null @@ -1,305 +0,0 @@ -/** - * \file dhm.h - * - * \brief Diffie-Hellman-Merkle key exchange - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_DHM_H -#define MBEDTLS_DHM_H - -#include "bignum.h" - -/* - * DHM Error codes - */ -#define MBEDTLS_ERR_DHM_BAD_INPUT_DATA -0x3080 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_DHM_READ_PARAMS_FAILED -0x3100 /**< Reading of the DHM parameters failed. */ -#define MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 /**< Making of the DHM parameters failed. */ -#define MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED -0x3200 /**< Reading of the public values failed. */ -#define MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED -0x3280 /**< Making of the public value failed. */ -#define MBEDTLS_ERR_DHM_CALC_SECRET_FAILED -0x3300 /**< Calculation of the DHM secret failed. */ -#define MBEDTLS_ERR_DHM_INVALID_FORMAT -0x3380 /**< The ASN.1 data is not formatted correctly. */ -#define MBEDTLS_ERR_DHM_ALLOC_FAILED -0x3400 /**< Allocation of memory failed. */ -#define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 /**< Read/write of file failed. */ - -/** - * RFC 3526 defines a number of standardized Diffie-Hellman groups - * for IKE. - * RFC 5114 defines a number of standardized Diffie-Hellman groups - * that can be used. - * - * Some are included here for convenience. - * - * Included are: - * RFC 3526 3. 2048-bit MODP Group - * RFC 3526 4. 3072-bit MODP Group - * RFC 3526 5. 4096-bit MODP Group - * RFC 5114 2.2. 2048-bit MODP Group with 224-bit Prime Order Subgroup - */ -#define MBEDTLS_DHM_RFC3526_MODP_2048_P \ - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ - "15728E5A8AACAA68FFFFFFFFFFFFFFFF" - -#define MBEDTLS_DHM_RFC3526_MODP_2048_G "02" - -#define MBEDTLS_DHM_RFC3526_MODP_3072_P \ - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ - "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ - "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ - "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ - "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ - "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF" - -#define MBEDTLS_DHM_RFC3526_MODP_3072_G "02" - -#define MBEDTLS_DHM_RFC3526_MODP_4096_P \ - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \ - "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \ - "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \ - "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \ - "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \ - "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \ - "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" \ - "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" \ - "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" \ - "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" \ - "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" \ - "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" \ - "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" \ - "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" \ - "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" \ - "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" \ - "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" \ - "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" \ - "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" \ - "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" \ - "FFFFFFFFFFFFFFFF" - -#define MBEDTLS_DHM_RFC3526_MODP_4096_G "02" - -#define MBEDTLS_DHM_RFC5114_MODP_2048_P \ - "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1" \ - "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" \ - "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212" \ - "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" \ - "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708" \ - "B3BF8A317091883681286130BC8985DB1602E714415D9330" \ - "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D" \ - "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" \ - "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763" \ - "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" \ - "CF9DE5384E71B81C0AC4DFFE0C10E64F" - -#define MBEDTLS_DHM_RFC5114_MODP_2048_G \ - "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF"\ - "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA"\ - "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7"\ - "C17669101999024AF4D027275AC1348BB8A762D0521BC98A"\ - "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE"\ - "F180EB34118E98D119529A45D6F834566E3025E316A330EF"\ - "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB"\ - "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381"\ - "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269"\ - "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179"\ - "81BC087F2A7065B384B890D3191F2BFA" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief DHM context structure - */ -typedef struct -{ - size_t len; /*!< size(P) in chars */ - mbedtls_mpi P; /*!< prime modulus */ - mbedtls_mpi G; /*!< generator */ - mbedtls_mpi X; /*!< secret value */ - mbedtls_mpi GX; /*!< self = G^X mod P */ - mbedtls_mpi GY; /*!< peer = G^Y mod P */ - mbedtls_mpi K; /*!< key = GY^X mod P */ - mbedtls_mpi RP; /*!< cached R^2 mod P */ - mbedtls_mpi Vi; /*!< blinding value */ - mbedtls_mpi Vf; /*!< un-blinding value */ - mbedtls_mpi pX; /*!< previous X */ -} -mbedtls_dhm_context; - -/** - * \brief Initialize DHM context - * - * \param ctx DHM context to be initialized - */ -void mbedtls_dhm_init( mbedtls_dhm_context *ctx ); - -/** - * \brief Parse the ServerKeyExchange parameters - * - * \param ctx DHM context - * \param p &(start of input buffer) - * \param end end of buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_DHM_XXX error code - */ -int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, - unsigned char **p, - const unsigned char *end ); - -/** - * \brief Setup and write the ServerKeyExchange parameters - * - * \param ctx DHM context - * \param x_size private value size in bytes - * \param output destination buffer - * \param olen number of chars written - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \note This function assumes that ctx->P and ctx->G - * have already been properly set (for example - * using mbedtls_mpi_read_string or mbedtls_mpi_read_binary). - * - * \return 0 if successful, or an MBEDTLS_ERR_DHM_XXX error code - */ -int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, - unsigned char *output, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Import the peer's public value G^Y - * - * \param ctx DHM context - * \param input input buffer - * \param ilen size of buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_DHM_XXX error code - */ -int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, - const unsigned char *input, size_t ilen ); - -/** - * \brief Create own private value X and export G^X - * - * \param ctx DHM context - * \param x_size private value size in bytes - * \param output destination buffer - * \param olen must be at least equal to the size of P, ctx->len - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, or an MBEDTLS_ERR_DHM_XXX error code - */ -int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, - unsigned char *output, size_t olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Derive and export the shared secret (G^Y)^X mod P - * - * \param ctx DHM context - * \param output destination buffer - * \param output_size size of the destination buffer - * \param olen on exit, holds the actual number of bytes written - * \param f_rng RNG function, for blinding purposes - * \param p_rng RNG parameter - * - * \return 0 if successful, or an MBEDTLS_ERR_DHM_XXX error code - * - * \note If non-NULL, f_rng is used to blind the input as - * countermeasure against timing attacks. Blinding is - * automatically used if and only if our secret value X is - * re-used and costs nothing otherwise, so it is recommended - * to always pass a non-NULL f_rng argument. - */ -int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, - unsigned char *output, size_t output_size, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Free and clear the components of a DHM key - * - * \param ctx DHM context to free and clear - */ -void mbedtls_dhm_free( mbedtls_dhm_context *ctx ); - -#if defined(MBEDTLS_ASN1_PARSE_C) -/** \ingroup x509_module */ -/** - * \brief Parse DHM parameters in PEM or DER format - * - * \param dhm DHM context to be initialized - * \param dhmin input buffer - * \param dhminlen size of the buffer - * (including the terminating null byte for PEM data) - * - * \return 0 if successful, or a specific DHM or PEM error code - */ -int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, - size_t dhminlen ); - -#if defined(MBEDTLS_FS_IO) -/** \ingroup x509_module */ -/** - * \brief Load and parse DHM parameters - * - * \param dhm DHM context to be initialized - * \param path filename to read the DHM Parameters from - * - * \return 0 if successful, or a specific DHM or PEM error code - */ -int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ); -#endif /* MBEDTLS_FS_IO */ -#endif /* MBEDTLS_ASN1_PARSE_C */ - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_dhm_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* dhm.h */ diff --git a/components/mbedtls/include/mbedtls/ecdh.h b/components/mbedtls/include/mbedtls/ecdh.h deleted file mode 100644 index 625a281923..0000000000 --- a/components/mbedtls/include/mbedtls/ecdh.h +++ /dev/null @@ -1,214 +0,0 @@ -/** - * \file ecdh.h - * - * \brief Elliptic curve Diffie-Hellman - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_ECDH_H -#define MBEDTLS_ECDH_H - -#include "ecp.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * When importing from an EC key, select if it is our key or the peer's key - */ -typedef enum -{ - MBEDTLS_ECDH_OURS, - MBEDTLS_ECDH_THEIRS, -} mbedtls_ecdh_side; - -/** - * \brief ECDH context structure - */ -typedef struct -{ - mbedtls_ecp_group grp; /*!< elliptic curve used */ - mbedtls_mpi d; /*!< our secret value (private key) */ - mbedtls_ecp_point Q; /*!< our public value (public key) */ - mbedtls_ecp_point Qp; /*!< peer's public value (public key) */ - mbedtls_mpi z; /*!< shared secret */ - int point_format; /*!< format for point export in TLS messages */ - mbedtls_ecp_point Vi; /*!< blinding value (for later) */ - mbedtls_ecp_point Vf; /*!< un-blinding value (for later) */ - mbedtls_mpi _d; /*!< previous d (for later) */ -} -mbedtls_ecdh_context; - -/** - * \brief Generate a public key. - * Raw function that only does the core computation. - * - * \param grp ECP group - * \param d Destination MPI (secret exponent, aka private key) - * \param Q Destination point (public key) - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code - */ -int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Compute shared secret - * Raw function that only does the core computation. - * - * \param grp ECP group - * \param z Destination MPI (shared secret) - * \param Q Public key from other party - * \param d Our secret exponent (private key) - * \param f_rng RNG function (see notes) - * \param p_rng RNG parameter - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code - * - * \note If f_rng is not NULL, it is used to implement - * countermeasures against potential elaborate timing - * attacks, see \c mbedtls_ecp_mul() for details. - */ -int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, - const mbedtls_ecp_point *Q, const mbedtls_mpi *d, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Initialize context - * - * \param ctx Context to initialize - */ -void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ); - -/** - * \brief Free context - * - * \param ctx Context to free - */ -void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ); - -/** - * \brief Generate a public key and a TLS ServerKeyExchange payload. - * (First function used by a TLS server for ECDHE.) - * - * \param ctx ECDH context - * \param olen number of chars written - * \param buf destination buffer - * \param blen length of buffer - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \note This function assumes that ctx->grp has already been - * properly set (for example using mbedtls_ecp_group_load). - * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code - */ -int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Parse and procress a TLS ServerKeyExhange payload. - * (First function used by a TLS client for ECDHE.) - * - * \param ctx ECDH context - * \param buf pointer to start of input buffer - * \param end one past end of buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code - */ -int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, - const unsigned char **buf, const unsigned char *end ); - -/** - * \brief Setup an ECDH context from an EC key. - * (Used by clients and servers in place of the - * ServerKeyEchange for static ECDH: import ECDH parameters - * from a certificate's EC key information.) - * - * \param ctx ECDH constext to set - * \param key EC key to use - * \param side Is it our key (1) or the peer's key (0) ? - * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code - */ -int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, - mbedtls_ecdh_side side ); - -/** - * \brief Generate a public key and a TLS ClientKeyExchange payload. - * (Second function used by a TLS client for ECDH(E).) - * - * \param ctx ECDH context - * \param olen number of bytes actually written - * \param buf destination buffer - * \param blen size of destination buffer - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code - */ -int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Parse and process a TLS ClientKeyExchange payload. - * (Second function used by a TLS server for ECDH(E).) - * - * \param ctx ECDH context - * \param buf start of input buffer - * \param blen length of input buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code - */ -int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, - const unsigned char *buf, size_t blen ); - -/** - * \brief Derive and export the shared secret. - * (Last function used by both TLS client en servers.) - * - * \param ctx ECDH context - * \param olen number of bytes written - * \param buf destination buffer - * \param blen buffer length - * \param f_rng RNG function, see notes for \c mbedtls_ecdh_compute_shared() - * \param p_rng RNG parameter - * - * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code - */ -int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -#ifdef __cplusplus -} -#endif - -#endif /* ecdh.h */ diff --git a/components/mbedtls/include/mbedtls/ecdsa.h b/components/mbedtls/include/mbedtls/ecdsa.h deleted file mode 100644 index a277715b3d..0000000000 --- a/components/mbedtls/include/mbedtls/ecdsa.h +++ /dev/null @@ -1,272 +0,0 @@ -/** - * \file ecdsa.h - * - * \brief Elliptic curve DSA - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_ECDSA_H -#define MBEDTLS_ECDSA_H - -#include "ecp.h" -#include "md.h" - -/* - * RFC 4492 page 20: - * - * Ecdsa-Sig-Value ::= SEQUENCE { - * r INTEGER, - * s INTEGER - * } - * - * Size is at most - * 1 (tag) + 1 (len) + 1 (initial 0) + ECP_MAX_BYTES for each of r and s, - * twice that + 1 (tag) + 2 (len) for the sequence - * (assuming ECP_MAX_BYTES is less than 126 for r and s, - * and less than 124 (total len <= 255) for the sequence) - */ -#if MBEDTLS_ECP_MAX_BYTES > 124 -#error "MBEDTLS_ECP_MAX_BYTES bigger than expected, please fix MBEDTLS_ECDSA_MAX_LEN" -#endif -/** Maximum size of an ECDSA signature in bytes */ -#define MBEDTLS_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + MBEDTLS_ECP_MAX_BYTES ) ) - -/** - * \brief ECDSA context structure - */ -typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Compute ECDSA signature of a previously hashed message - * - * \note The deterministic version is usually prefered. - * - * \param grp ECP group - * \param r First output integer - * \param s Second output integer - * \param d Private signing key - * \param buf Message hash - * \param blen Length of buf - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \note If the bitlength of the message hash is larger than the - * bitlength of the group order, then the hash is truncated as - * prescribed by SEC1 4.1.3 step 5. - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code - */ -int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); - -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) -/** - * \brief Compute ECDSA signature of a previously hashed message, - * deterministic version (RFC 6979). - * - * \param grp ECP group - * \param r First output integer - * \param s Second output integer - * \param d Private signing key - * \param buf Message hash - * \param blen Length of buf - * \param md_alg MD algorithm used to hash the message - * - * \note If the bitlength of the message hash is larger than the - * bitlength of the group order, then the hash is truncated as - * prescribed by SEC1 4.1.3 step 5. - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code - */ -int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - mbedtls_md_type_t md_alg ); -#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ - -/** - * \brief Verify ECDSA signature of a previously hashed message - * - * \param grp ECP group - * \param buf Message hash - * \param blen Length of buf - * \param Q Public key to use for verification - * \param r First integer of the signature - * \param s Second integer of the signature - * - * \note If the bitlength of the message hash is larger than the - * bitlength of the group order, then the hash is truncated as - * prescribed by SEC1 4.1.4 step 3. - * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code - */ -int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s); - -/** - * \brief Compute ECDSA signature and write it to buffer, - * serialized as defined in RFC 4492 page 20. - * (Not thread-safe to use same context in multiple threads) - * - * \note The deterministic version (RFC 6979) is used if - * MBEDTLS_ECDSA_DETERMINISTIC is defined. - * - * \param ctx ECDSA context - * \param md_alg Algorithm that was used to hash the message - * \param hash Message hash - * \param hlen Length of hash - * \param sig Buffer that will hold the signature - * \param slen Length of the signature written - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \note The "sig" buffer must be at least as large as twice the - * size of the curve used, plus 9 (eg. 73 bytes if a 256-bit - * curve is used). MBEDTLS_ECDSA_MAX_LEN is always safe. - * - * \note If the bitlength of the message hash is larger than the - * bitlength of the group order, then the hash is truncated as - * prescribed by SEC1 4.1.3 step 5. - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX, MBEDTLS_ERR_MPI_XXX or - * MBEDTLS_ERR_ASN1_XXX error code - */ -int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t *slen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) -#if ! defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief Compute ECDSA signature and write it to buffer, - * serialized as defined in RFC 4492 page 20. - * Deterministic version, RFC 6979. - * (Not thread-safe to use same context in multiple threads) - * - * \deprecated Superseded by mbedtls_ecdsa_write_signature() in 2.0.0 - * - * \param ctx ECDSA context - * \param hash Message hash - * \param hlen Length of hash - * \param sig Buffer that will hold the signature - * \param slen Length of the signature written - * \param md_alg MD algorithm used to hash the message - * - * \note The "sig" buffer must be at least as large as twice the - * size of the curve used, plus 9 (eg. 73 bytes if a 256-bit - * curve is used). MBEDTLS_ECDSA_MAX_LEN is always safe. - * - * \note If the bitlength of the message hash is larger than the - * bitlength of the group order, then the hash is truncated as - * prescribed by SEC1 4.1.3 step 5. - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX, MBEDTLS_ERR_MPI_XXX or - * MBEDTLS_ERR_ASN1_XXX error code - */ -int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, - const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t *slen, - mbedtls_md_type_t md_alg ) MBEDTLS_DEPRECATED; -#undef MBEDTLS_DEPRECATED -#endif /* MBEDTLS_DEPRECATED_REMOVED */ -#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ - -/** - * \brief Read and verify an ECDSA signature - * - * \param ctx ECDSA context - * \param hash Message hash - * \param hlen Size of hash - * \param sig Signature to read and verify - * \param slen Size of sig - * - * \note If the bitlength of the message hash is larger than the - * bitlength of the group order, then the hash is truncated as - * prescribed by SEC1 4.1.4 step 3. - * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid, - * MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if the signature is - * valid but its actual length is less than siglen, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_ERR_MPI_XXX error code - */ -int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, - const unsigned char *hash, size_t hlen, - const unsigned char *sig, size_t slen ); - -/** - * \brief Generate an ECDSA keypair on the given curve - * - * \param ctx ECDSA context in which the keypair should be stored - * \param gid Group (elliptic curve) to use. One of the various - * MBEDTLS_ECP_DP_XXX macros depending on configuration. - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 on success, or a MBEDTLS_ERR_ECP_XXX code. - */ -int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); - -/** - * \brief Set an ECDSA context from an EC key pair - * - * \param ctx ECDSA context to set - * \param key EC key to use - * - * \return 0 on success, or a MBEDTLS_ERR_ECP_XXX code. - */ -int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ); - -/** - * \brief Initialize context - * - * \param ctx Context to initialize - */ -void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ); - -/** - * \brief Free context - * - * \param ctx Context to free - */ -void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ); - -#ifdef __cplusplus -} -#endif - -#endif /* ecdsa.h */ diff --git a/components/mbedtls/include/mbedtls/ecjpake.h b/components/mbedtls/include/mbedtls/ecjpake.h deleted file mode 100644 index 161a5b213f..0000000000 --- a/components/mbedtls/include/mbedtls/ecjpake.h +++ /dev/null @@ -1,238 +0,0 @@ -/** - * \file ecjpake.h - * - * \brief Elliptic curve J-PAKE - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_ECJPAKE_H -#define MBEDTLS_ECJPAKE_H - -/* - * J-PAKE is a password-authenticated key exchange that allows deriving a - * strong shared secret from a (potentially low entropy) pre-shared - * passphrase, with forward secrecy and mutual authentication. - * https://en.wikipedia.org/wiki/Password_Authenticated_Key_Exchange_by_Juggling - * - * This file implements the Elliptic Curve variant of J-PAKE, - * as defined in Chapter 7.4 of the Thread v1.0 Specification, - * available to members of the Thread Group http://threadgroup.org/ - * - * As the J-PAKE algorithm is inherently symmetric, so is our API. - * Each party needs to send its first round message, in any order, to the - * other party, then each sends its second round message, in any order. - * The payloads are serialized in a way suitable for use in TLS, but could - * also be use outside TLS. - */ - -#include "ecp.h" -#include "md.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Roles in the EC J-PAKE exchange - */ -typedef enum { - MBEDTLS_ECJPAKE_CLIENT = 0, /**< Client */ - MBEDTLS_ECJPAKE_SERVER, /**< Server */ -} mbedtls_ecjpake_role; - -/** - * EC J-PAKE context structure. - * - * J-PAKE is a symmetric protocol, except for the identifiers used in - * Zero-Knowledge Proofs, and the serialization of the second message - * (KeyExchange) as defined by the Thread spec. - * - * In order to benefit from this symmetry, we choose a different naming - * convetion from the Thread v1.0 spec. Correspondance is indicated in the - * description as a pair C: client name, S: server name - */ -typedef struct -{ - const mbedtls_md_info_t *md_info; /**< Hash to use */ - mbedtls_ecp_group grp; /**< Elliptic curve */ - mbedtls_ecjpake_role role; /**< Are we client or server? */ - int point_format; /**< Format for point export */ - - mbedtls_ecp_point Xm1; /**< My public key 1 C: X1, S: X3 */ - mbedtls_ecp_point Xm2; /**< My public key 2 C: X2, S: X4 */ - mbedtls_ecp_point Xp1; /**< Peer public key 1 C: X3, S: X1 */ - mbedtls_ecp_point Xp2; /**< Peer public key 2 C: X4, S: X2 */ - mbedtls_ecp_point Xp; /**< Peer public key C: Xs, S: Xc */ - - mbedtls_mpi xm1; /**< My private key 1 C: x1, S: x3 */ - mbedtls_mpi xm2; /**< My private key 2 C: x2, S: x4 */ - - mbedtls_mpi s; /**< Pre-shared secret (passphrase) */ -} mbedtls_ecjpake_context; - -/** - * \brief Initialize a context - * (just makes it ready for setup() or free()). - * - * \param ctx context to initialize - */ -void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ); - -/** - * \brief Set up a context for use - * - * \note Currently the only values for hash/curve allowed by the - * standard are MBEDTLS_MD_SHA256/MBEDTLS_ECP_DP_SECP256R1. - * - * \param ctx context to set up - * \param role Our role: client or server - * \param hash hash function to use (MBEDTLS_MD_XXX) - * \param curve elliptic curve identifier (MBEDTLS_ECP_DP_XXX) - * \param secret pre-shared secret (passphrase) - * \param len length of the shared secret - * - * \return 0 if successfull, - * a negative error code otherwise - */ -int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, - mbedtls_ecjpake_role role, - mbedtls_md_type_t hash, - mbedtls_ecp_group_id curve, - const unsigned char *secret, - size_t len ); - -/** - * \brief Check if a context is ready for use - * - * \param ctx Context to check - * - * \return 0 if the context is ready for use, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise - */ -int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ); - -/** - * \brief Generate and write the first round message - * (TLS: contents of the Client/ServerHello extension, - * excluding extension type and length bytes) - * - * \param ctx Context to use - * \param buf Buffer to write the contents to - * \param len Buffer size - * \param olen Will be updated with the number of bytes written - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successfull, - * a negative error code otherwise - */ -int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, - unsigned char *buf, size_t len, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Read and process the first round message - * (TLS: contents of the Client/ServerHello extension, - * excluding extension type and length bytes) - * - * \param ctx Context to use - * \param buf Pointer to extension contents - * \param len Extension length - * - * \return 0 if successfull, - * a negative error code otherwise - */ -int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, - const unsigned char *buf, - size_t len ); - -/** - * \brief Generate and write the second round message - * (TLS: contents of the Client/ServerKeyExchange) - * - * \param ctx Context to use - * \param buf Buffer to write the contents to - * \param len Buffer size - * \param olen Will be updated with the number of bytes written - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successfull, - * a negative error code otherwise - */ -int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, - unsigned char *buf, size_t len, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Read and process the second round message - * (TLS: contents of the Client/ServerKeyExchange) - * - * \param ctx Context to use - * \param buf Pointer to the message - * \param len Message length - * - * \return 0 if successfull, - * a negative error code otherwise - */ -int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, - const unsigned char *buf, - size_t len ); - -/** - * \brief Derive the shared secret - * (TLS: Pre-Master Secret) - * - * \param ctx Context to use - * \param buf Buffer to write the contents to - * \param len Buffer size - * \param olen Will be updated with the number of bytes written - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successfull, - * a negative error code otherwise - */ -int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, - unsigned char *buf, size_t len, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Free a context's content - * - * \param ctx context to free - */ -void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ); - -#if defined(MBEDTLS_SELF_TEST) -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if a test failed - */ -int mbedtls_ecjpake_self_test( int verbose ); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* ecjpake.h */ diff --git a/components/mbedtls/include/mbedtls/ecp.h b/components/mbedtls/include/mbedtls/ecp.h deleted file mode 100644 index dad9aef002..0000000000 --- a/components/mbedtls/include/mbedtls/ecp.h +++ /dev/null @@ -1,684 +0,0 @@ -/** - * \file ecp.h - * - * \brief Elliptic curves over GF(p) - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_ECP_H -#define MBEDTLS_ECP_H - -#include "bignum.h" - -/* - * ECP error codes - */ -#define MBEDTLS_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /**< The buffer is too small to write to. */ -#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< Requested curve not available. */ -#define MBEDTLS_ERR_ECP_VERIFY_FAILED -0x4E00 /**< The signature is not valid. */ -#define MBEDTLS_ERR_ECP_ALLOC_FAILED -0x4D80 /**< Memory allocation failed. */ -#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as (ephemeral) key, failed. */ -#define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ -#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< Signature is valid but shorter than the user-supplied length. */ - -#if !defined(MBEDTLS_ECP_ALT) -/* - * default mbed TLS elliptic curve arithmetic implementation - * - * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an - * alternative implementation for the whole module and it will replace this - * one.) - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Domain parameters (curve, subgroup and generator) identifiers. - * - * Only curves over prime fields are supported. - * - * \warning This library does not support validation of arbitrary domain - * parameters. Therefore, only well-known domain parameters from trusted - * sources should be used. See mbedtls_ecp_group_load(). - */ -typedef enum -{ - MBEDTLS_ECP_DP_NONE = 0, - MBEDTLS_ECP_DP_SECP192R1, /*!< 192-bits NIST curve */ - MBEDTLS_ECP_DP_SECP224R1, /*!< 224-bits NIST curve */ - MBEDTLS_ECP_DP_SECP256R1, /*!< 256-bits NIST curve */ - MBEDTLS_ECP_DP_SECP384R1, /*!< 384-bits NIST curve */ - MBEDTLS_ECP_DP_SECP521R1, /*!< 521-bits NIST curve */ - MBEDTLS_ECP_DP_BP256R1, /*!< 256-bits Brainpool curve */ - MBEDTLS_ECP_DP_BP384R1, /*!< 384-bits Brainpool curve */ - MBEDTLS_ECP_DP_BP512R1, /*!< 512-bits Brainpool curve */ - MBEDTLS_ECP_DP_CURVE25519, /*!< Curve25519 */ - MBEDTLS_ECP_DP_SECP192K1, /*!< 192-bits "Koblitz" curve */ - MBEDTLS_ECP_DP_SECP224K1, /*!< 224-bits "Koblitz" curve */ - MBEDTLS_ECP_DP_SECP256K1, /*!< 256-bits "Koblitz" curve */ -} mbedtls_ecp_group_id; - -/** - * Number of supported curves (plus one for NONE). - * - * (Montgomery curves excluded for now.) - */ -#define MBEDTLS_ECP_DP_MAX 12 - -/** - * Curve information for use by other modules - */ -typedef struct -{ - mbedtls_ecp_group_id grp_id; /*!< Internal identifier */ - uint16_t tls_id; /*!< TLS NamedCurve identifier */ - uint16_t bit_size; /*!< Curve size in bits */ - const char *name; /*!< Human-friendly name */ -} mbedtls_ecp_curve_info; - -/** - * \brief ECP point structure (jacobian coordinates) - * - * \note All functions expect and return points satisfying - * the following condition: Z == 0 or Z == 1. (Other - * values of Z are used by internal functions only.) - * The point is zero, or "at infinity", if Z == 0. - * Otherwise, X and Y are its standard (affine) coordinates. - */ -typedef struct -{ - mbedtls_mpi X; /*!< the point's X coordinate */ - mbedtls_mpi Y; /*!< the point's Y coordinate */ - mbedtls_mpi Z; /*!< the point's Z coordinate */ -} -mbedtls_ecp_point; - -/** - * \brief ECP group structure - * - * We consider two types of curves equations: - * 1. Short Weierstrass y^2 = x^3 + A x + B mod P (SEC1 + RFC 4492) - * 2. Montgomery, y^2 = x^3 + A x^2 + x mod P (Curve25519 + draft) - * In both cases, a generator G for a prime-order subgroup is fixed. In the - * short weierstrass, this subgroup is actually the whole curve, and its - * cardinal is denoted by N. - * - * In the case of Short Weierstrass curves, our code requires that N is an odd - * prime. (Use odd in mbedtls_ecp_mul() and prime in mbedtls_ecdsa_sign() for blinding.) - * - * In the case of Montgomery curves, we don't store A but (A + 2) / 4 which is - * the quantity actually used in the formulas. Also, nbits is not the size of N - * but the required size for private keys. - * - * If modp is NULL, reduction modulo P is done using a generic algorithm. - * Otherwise, it must point to a function that takes an mbedtls_mpi in the range - * 0..2^(2*pbits)-1 and transforms it in-place in an integer of little more - * than pbits, so that the integer may be efficiently brought in the 0..P-1 - * range by a few additions or substractions. It must return 0 on success and - * non-zero on failure. - */ -typedef struct -{ - mbedtls_ecp_group_id id; /*!< internal group identifier */ - mbedtls_mpi P; /*!< prime modulus of the base field */ - mbedtls_mpi A; /*!< 1. A in the equation, or 2. (A + 2) / 4 */ - mbedtls_mpi B; /*!< 1. B in the equation, or 2. unused */ - mbedtls_ecp_point G; /*!< generator of the (sub)group used */ - mbedtls_mpi N; /*!< 1. the order of G, or 2. unused */ - size_t pbits; /*!< number of bits in P */ - size_t nbits; /*!< number of bits in 1. P, or 2. private keys */ - unsigned int h; /*!< internal: 1 if the constants are static */ - int (*modp)(mbedtls_mpi *); /*!< function for fast reduction mod P */ - int (*t_pre)(mbedtls_ecp_point *, void *); /*!< unused */ - int (*t_post)(mbedtls_ecp_point *, void *); /*!< unused */ - void *t_data; /*!< unused */ - mbedtls_ecp_point *T; /*!< pre-computed points for ecp_mul_comb() */ - size_t T_size; /*!< number for pre-computed points */ -} -mbedtls_ecp_group; - -/** - * \brief ECP key pair structure - * - * A generic key pair that could be used for ECDSA, fixed ECDH, etc. - * - * \note Members purposefully in the same order as struc mbedtls_ecdsa_context. - */ -typedef struct -{ - mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ - mbedtls_mpi d; /*!< our secret value */ - mbedtls_ecp_point Q; /*!< our public value */ -} -mbedtls_ecp_keypair; - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -#if !defined(MBEDTLS_ECP_MAX_BITS) -/** - * Maximum size of the groups (that is, of N and P) - */ -#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ -#endif - -#define MBEDTLS_ECP_MAX_BYTES ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 ) -#define MBEDTLS_ECP_MAX_PT_LEN ( 2 * MBEDTLS_ECP_MAX_BYTES + 1 ) - -#if !defined(MBEDTLS_ECP_WINDOW_SIZE) -/* - * Maximum "window" size used for point multiplication. - * Default: 6. - * Minimum value: 2. Maximum value: 7. - * - * Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) - * points used for point multiplication. This value is directly tied to EC - * peak memory usage, so decreasing it by one should roughly cut memory usage - * by two (if large curves are in use). - * - * Reduction in size may reduce speed, but larger curves are impacted first. - * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1): - * w-size: 6 5 4 3 2 - * 521 145 141 135 120 97 - * 384 214 209 198 177 146 - * 256 320 320 303 262 226 - - * 224 475 475 453 398 342 - * 192 640 640 633 587 476 - */ -#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ -#endif /* MBEDTLS_ECP_WINDOW_SIZE */ - -#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) -/* - * Trade memory for speed on fixed-point multiplication. - * - * This speeds up repeated multiplication of the generator (that is, the - * multiplication in ECDSA signatures, and half of the multiplications in - * ECDSA verification and ECDHE) by a factor roughly 3 to 4. - * - * The cost is increasing EC peak memory usage by a factor roughly 2. - * - * Change this value to 0 to reduce peak memory usage. - */ -#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ -#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ - -/* \} name SECTION: Module settings */ - -/* - * Point formats, from RFC 4492's enum ECPointFormat - */ -#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format */ -#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format */ - -/* - * Some other constants from RFC 4492 - */ -#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType's named_curve */ - -/** - * \brief Get the list of supported curves in order of preferrence - * (full information) - * - * \return A statically allocated array, the last entry is 0. - */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ); - -/** - * \brief Get the list of supported curves in order of preferrence - * (grp_id only) - * - * \return A statically allocated array, - * terminated with MBEDTLS_ECP_DP_NONE. - */ -const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ); - -/** - * \brief Get curve information from an internal group identifier - * - * \param grp_id A MBEDTLS_ECP_DP_XXX value - * - * \return The associated curve information or NULL - */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ); - -/** - * \brief Get curve information from a TLS NamedCurve value - * - * \param tls_id A MBEDTLS_ECP_DP_XXX value - * - * \return The associated curve information or NULL - */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ); - -/** - * \brief Get curve information from a human-readable name - * - * \param name The name - * - * \return The associated curve information or NULL - */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ); - -/** - * \brief Initialize a point (as zero) - */ -void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ); - -/** - * \brief Initialize a group (to something meaningless) - */ -void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ); - -/** - * \brief Initialize a key pair (as an invalid one) - */ -void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ); - -/** - * \brief Free the components of a point - */ -void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ); - -/** - * \brief Free the components of an ECP group - */ -void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ); - -/** - * \brief Free the components of a key pair - */ -void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); - -/** - * \brief Copy the contents of point Q into P - * - * \param P Destination point - * \param Q Source point - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); - -/** - * \brief Copy the contents of a group object - * - * \param dst Destination group - * \param src Source group - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ); - -/** - * \brief Set a point to zero - * - * \param pt Destination point - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ); - -/** - * \brief Tell if a point is zero - * - * \param pt Point to test - * - * \return 1 if point is zero, 0 otherwise - */ -int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ); - -/** - * \brief Compare two points - * - * \note This assumes the points are normalized. Otherwise, - * they may compare as "not equal" even if they are. - * - * \param P First point to compare - * \param Q Second point to compare - * - * \return 0 if the points are equal, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise - */ -int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, - const mbedtls_ecp_point *Q ); - -/** - * \brief Import a non-zero point from two ASCII strings - * - * \param P Destination point - * \param radix Input numeric base - * \param x First affine coordinate as a null-terminated string - * \param y Second affine coordinate as a null-terminated string - * - * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code - */ -int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, - const char *x, const char *y ); - -/** - * \brief Export a point into unsigned binary data - * - * \param grp Group to which the point should belong - * \param P Point to export - * \param format Point format, should be a MBEDTLS_ECP_PF_XXX macro - * \param olen Length of the actual output - * \param buf Output buffer - * \param buflen Length of the output buffer - * - * \return 0 if successful, - * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA - * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL - */ -int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, - int format, size_t *olen, - unsigned char *buf, size_t buflen ); - -/** - * \brief Import a point from unsigned binary data - * - * \param grp Group to which the point should belong - * \param P Point to import - * \param buf Input buffer - * \param ilen Actual length of input - * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format - * is not implemented. - * - * \note This function does NOT check that the point actually - * belongs to the given group, see mbedtls_ecp_check_pubkey() for - * that. - */ -int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, - const unsigned char *buf, size_t ilen ); - -/** - * \brief Import a point from a TLS ECPoint record - * - * \param grp ECP group used - * \param pt Destination point - * \param buf $(Start of input buffer) - * \param len Buffer length - * - * \note buf is updated to point right after the ECPoint on exit - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_XXX if initialization failed - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid - */ -int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, - const unsigned char **buf, size_t len ); - -/** - * \brief Export a point as a TLS ECPoint record - * - * \param grp ECP group used - * \param pt Point to export - * \param format Export format - * \param olen length of data written - * \param buf Buffer to write to - * \param blen Buffer length - * - * \return 0 if successful, - * or MBEDTLS_ERR_ECP_BAD_INPUT_DATA - * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL - */ -int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, - int format, size_t *olen, - unsigned char *buf, size_t blen ); - -/** - * \brief Set a group using well-known domain parameters - * - * \param grp Destination group - * \param id Index in the list of well-known domain parameters - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_XXX if initialization failed - * MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups - * - * \note Index should be a value of RFC 4492's enum NamedCurve, - * usually in the form of a MBEDTLS_ECP_DP_XXX macro. - */ -int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ); - -/** - * \brief Set a group from a TLS ECParameters record - * - * \param grp Destination group - * \param buf &(Start of input buffer) - * \param len Buffer length - * - * \note buf is updated to point right after ECParameters on exit - * - * \return 0 if successful, - * MBEDTLS_ERR_MPI_XXX if initialization failed - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid - */ -int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ); - -/** - * \brief Write the TLS ECParameters record for a group - * - * \param grp ECP group used - * \param olen Number of bytes actually written - * \param buf Buffer to write to - * \param blen Buffer length - * - * \return 0 if successful, - * or MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL - */ -int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, - unsigned char *buf, size_t blen ); - -/** - * \brief Multiplication by an integer: R = m * P - * (Not thread-safe to use same group in multiple threads) - * - * \note In order to prevent timing attacks, this function - * executes the exact same sequence of (base field) - * operations for any valid m. It avoids any if-branch or - * array index depending on the value of m. - * - * \note If f_rng is not NULL, it is used to randomize intermediate - * results in order to prevent potential timing attacks - * targeting these results. It is recommended to always - * provide a non-NULL f_rng (the overhead is negligible). - * - * \param grp ECP group - * \param R Destination point - * \param m Integer by which to multiply - * \param P Point to multiply - * \param f_rng RNG function (see notes) - * \param p_rng RNG parameter - * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_INVALID_KEY if m is not a valid privkey - * or P is not a valid pubkey, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_mpi *m, const mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); - -/** - * \brief Multiplication and addition of two points by integers: - * R = m * P + n * Q - * (Not thread-safe to use same group in multiple threads) - * - * \note In contrast to mbedtls_ecp_mul(), this function does not guarantee - * a constant execution flow and timing. - * - * \param grp ECP group - * \param R Destination point - * \param m Integer by which to multiply P - * \param P Point to multiply by m - * \param n Integer by which to multiply Q - * \param Q Point to be multiplied by n - * - * \return 0 if successful, - * MBEDTLS_ERR_ECP_INVALID_KEY if m or n is not a valid privkey - * or P or Q is not a valid pubkey, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed - */ -int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_mpi *m, const mbedtls_ecp_point *P, - const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); - -/** - * \brief Check that a point is a valid public key on this curve - * - * \param grp Curve/group the point should belong to - * \param pt Point to check - * - * \return 0 if point is a valid public key, - * MBEDTLS_ERR_ECP_INVALID_KEY otherwise. - * - * \note This function only checks the point is non-zero, has valid - * coordinates and lies on the curve, but not that it is - * indeed a multiple of G. This is additional check is more - * expensive, isn't required by standards, and shouldn't be - * necessary if the group used has a small cofactor. In - * particular, it is useless for the NIST groups which all - * have a cofactor of 1. - * - * \note Uses bare components rather than an mbedtls_ecp_keypair structure - * in order to ease use with other structures such as - * mbedtls_ecdh_context of mbedtls_ecdsa_context. - */ -int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ); - -/** - * \brief Check that an mbedtls_mpi is a valid private key for this curve - * - * \param grp Group used - * \param d Integer to check - * - * \return 0 if point is a valid private key, - * MBEDTLS_ERR_ECP_INVALID_KEY otherwise. - * - * \note Uses bare components rather than an mbedtls_ecp_keypair structure - * in order to ease use with other structures such as - * mbedtls_ecdh_context of mbedtls_ecdsa_context. - */ -int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ); - -/** - * \brief Generate a keypair with configurable base point - * - * \param grp ECP group - * \param G Chosen base point - * \param d Destination MPI (secret part) - * \param Q Destination point (public part) - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code - * - * \note Uses bare components rather than an mbedtls_ecp_keypair structure - * in order to ease use with other structures such as - * mbedtls_ecdh_context of mbedtls_ecdsa_context. - */ -int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, - const mbedtls_ecp_point *G, - mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Generate a keypair - * - * \param grp ECP group - * \param d Destination MPI (secret part) - * \param Q Destination point (public part) - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code - * - * \note Uses bare components rather than an mbedtls_ecp_keypair structure - * in order to ease use with other structures such as - * mbedtls_ecdh_context of mbedtls_ecdsa_context. - */ -int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Generate a keypair - * - * \param grp_id ECP group identifier - * \param key Destination keypair - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, - * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code - */ -int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); - -/** - * \brief Check a public-private key pair - * - * \param pub Keypair structure holding a public key - * \param prv Keypair structure holding a private (plus public) key - * - * \return 0 if successful (keys are valid and match), or - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA, or - * a MBEDTLS_ERR_ECP_XXX or MBEDTLS_ERR_MPI_XXX code. - */ -int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ); - -#if defined(MBEDTLS_SELF_TEST) - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if a test failed - */ -int mbedtls_ecp_self_test( int verbose ); - -#endif /* MBEDTLS_SELF_TEST */ - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_ECP_ALT */ -#include "ecp_alt.h" -#endif /* MBEDTLS_ECP_ALT */ - -#endif /* ecp.h */ diff --git a/components/mbedtls/include/mbedtls/ecp_internal.h b/components/mbedtls/include/mbedtls/ecp_internal.h deleted file mode 100644 index 2991e26dd9..0000000000 --- a/components/mbedtls/include/mbedtls/ecp_internal.h +++ /dev/null @@ -1,292 +0,0 @@ -/** - * \file ecp_internal.h - * - * \brief Function declarations for alternative implementation of elliptic curve - * point arithmetic. - * - * Copyright (C) 2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -/* - * References: - * - * [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records. - * - * - * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis - * for elliptic curve cryptosystems. In : Cryptographic Hardware and - * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. - * - * - * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to - * render ECC resistant against Side Channel Attacks. IACR Cryptology - * ePrint Archive, 2004, vol. 2004, p. 342. - * - * - * [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters. - * - * - * [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic - * Curve Cryptography. - * - * [6] Digital Signature Standard (DSS), FIPS 186-4. - * - * - * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer - * Security (TLS), RFC 4492. - * - * - * [8] - * - * [9] COHEN, Henri. A Course in Computational Algebraic Number Theory. - * Springer Science & Business Media, 1 Aug 2000 - */ - -#ifndef MBEDTLS_ECP_INTERNAL_H -#define MBEDTLS_ECP_INTERNAL_H - -#if defined(MBEDTLS_ECP_INTERNAL_ALT) - -/** - * \brief Indicate if the Elliptic Curve Point module extension can - * handle the group. - * - * \param grp The pointer to the elliptic curve group that will be the - * basis of the cryptographic computations. - * - * \return Non-zero if successful. - */ -unsigned char mbedtls_internal_ecp_grp_capable( const mbedtls_ecp_group *grp ); - -/** - * \brief Initialise the Elliptic Curve Point module extension. - * - * If mbedtls_internal_ecp_grp_capable returns true for a - * group, this function has to be able to initialise the - * module for it. - * - * This module can be a driver to a crypto hardware - * accelerator, for which this could be an initialise function. - * - * \param grp The pointer to the group the module needs to be - * initialised for. - * - * \return 0 if successful. - */ -int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ); - -/** - * \brief Frees and deallocates the Elliptic Curve Point module - * extension. - * - * \param grp The pointer to the group the module was initialised for. - */ -void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ); - -#if defined(ECP_SHORTWEIERSTRASS) - -#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) -/** - * \brief Randomize jacobian coordinates: - * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l. - * - * \param grp Pointer to the group representing the curve. - * - * \param pt The point on the curve to be randomised, given with Jacobian - * coordinates. - * - * \param f_rng A function pointer to the random number generator. - * - * \param p_rng A pointer to the random number generator state. - * - * \return 0 if successful. - */ -int mbedtls_internal_ecp_randomize_jac( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); -#endif - -#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) -/** - * \brief Addition: R = P + Q, mixed affine-Jacobian coordinates. - * - * The coordinates of Q must be normalized (= affine), - * but those of P don't need to. R is not normalized. - * - * This function is used only as a subrutine of - * ecp_mul_comb(). - * - * Special cases: (1) P or Q is zero, (2) R is zero, - * (3) P == Q. - * None of these cases can happen as intermediate step in - * ecp_mul_comb(): - * - at each step, P, Q and R are multiples of the base - * point, the factor being less than its order, so none of - * them is zero; - * - Q is an odd multiple of the base point, P an even - * multiple, due to the choice of precomputed points in the - * modified comb method. - * So branches for these cases do not leak secret information. - * - * We accept Q->Z being unset (saving memory in tables) as - * meaning 1. - * - * Cost in field operations if done by [5] 3.22: - * 1A := 8M + 3S - * - * \param grp Pointer to the group representing the curve. - * - * \param R Pointer to a point structure to hold the result. - * - * \param P Pointer to the first summand, given with Jacobian - * coordinates - * - * \param Q Pointer to the second summand, given with affine - * coordinates. - * - * \return 0 if successful. - */ -int mbedtls_internal_ecp_add_mixed( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *R, const mbedtls_ecp_point *P, - const mbedtls_ecp_point *Q ); -#endif - -/** - * \brief Point doubling R = 2 P, Jacobian coordinates. - * - * Cost: 1D := 3M + 4S (A == 0) - * 4M + 4S (A == -3) - * 3M + 6S + 1a otherwise - * when the implementation is based on the "dbl-1998-cmo-2" - * doubling formulas in [8] and standard optimizations are - * applied when curve parameter A is one of { 0, -3 }. - * - * \param grp Pointer to the group representing the curve. - * - * \param R Pointer to a point structure to hold the result. - * - * \param P Pointer to the point that has to be doubled, given with - * Jacobian coordinates. - * - * \return 0 if successful. - */ -#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) -int mbedtls_internal_ecp_double_jac( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *R, const mbedtls_ecp_point *P ); -#endif - -/** - * \brief Normalize jacobian coordinates of an array of (pointers to) - * points. - * - * Using Montgomery's trick to perform only one inversion mod P - * the cost is: - * 1N(t) := 1I + (6t - 3)M + 1S - * (See for example Algorithm 10.3.4. in [9]) - * - * This function is used only as a subrutine of - * ecp_mul_comb(). - * - * Warning: fails (returning an error) if one of the points is - * zero! - * This should never happen, see choice of w in ecp_mul_comb(). - * - * \param grp Pointer to the group representing the curve. - * - * \param T Array of pointers to the points to normalise. - * - * \param t_len Number of elements in the array. - * - * \return 0 if successful, - * an error if one of the points is zero. - */ -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) -int mbedtls_internal_ecp_normalize_jac_many( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *T[], size_t t_len ); -#endif - -/** - * \brief Normalize jacobian coordinates so that Z == 0 || Z == 1. - * - * Cost in field operations if done by [5] 3.2.1: - * 1N := 1I + 3M + 1S - * - * \param grp Pointer to the group representing the curve. - * - * \param pt pointer to the point to be normalised. This is an - * input/output parameter. - * - * \return 0 if successful. - */ -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) -int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *pt ); -#endif - -#endif /* ECP_SHORTWEIERSTRASS */ - -#if defined(ECP_MONTGOMERY) - -#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) -int mbedtls_internal_ecp_double_add_mxz( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *R, mbedtls_ecp_point *S, const mbedtls_ecp_point *P, - const mbedtls_ecp_point *Q, const mbedtls_mpi *d ); -#endif - -/** - * \brief Randomize projective x/z coordinates: - * (X, Z) -> (l X, l Z) for random l - * - * \param grp pointer to the group representing the curve - * - * \param P the point on the curve to be randomised given with - * projective coordinates. This is an input/output parameter. - * - * \param f_rng a function pointer to the random number generator - * - * \param p_rng a pointer to the random number generator state - * - * \return 0 if successful - */ -#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) -int mbedtls_internal_ecp_randomize_mxz( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); -#endif - -/** - * \brief Normalize Montgomery x/z coordinates: X = X/Z, Z = 1. - * - * \param grp pointer to the group representing the curve - * - * \param P pointer to the point to be normalised. This is an - * input/output parameter. - * - * \return 0 if successful - */ -#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) -int mbedtls_internal_ecp_normalize_mxz( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *P ); -#endif - -#endif /* ECP_MONTGOMERY */ - -#endif /* MBEDTLS_ECP_INTERNAL_ALT */ - -#endif /* ecp_internal.h */ - diff --git a/components/mbedtls/include/mbedtls/entropy.h b/components/mbedtls/include/mbedtls/entropy.h deleted file mode 100644 index 747aca4dfa..0000000000 --- a/components/mbedtls/include/mbedtls/entropy.h +++ /dev/null @@ -1,287 +0,0 @@ -/** - * \file entropy.h - * - * \brief Entropy accumulator implementation - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_ENTROPY_H -#define MBEDTLS_ENTROPY_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) -#include "sha512.h" -#define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR -#else -#if defined(MBEDTLS_SHA256_C) -#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR -#include "sha256.h" -#endif -#endif - -#if defined(MBEDTLS_THREADING_C) -#include "threading.h" -#endif - -#if defined(MBEDTLS_HAVEGE_C) -#include "havege.h" -#endif - -#define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */ -#define MBEDTLS_ERR_ENTROPY_MAX_SOURCES -0x003E /**< No more sources can be added. */ -#define MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /**< No sources have been added to poll. */ -#define MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE -0x003D /**< No strong sources have been added to poll. */ -#define MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR -0x003F /**< Read/write error in file. */ - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -#if !defined(MBEDTLS_ENTROPY_MAX_SOURCES) -#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ -#endif - -#if !defined(MBEDTLS_ENTROPY_MAX_GATHER) -#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ -#endif - -/* \} name SECTION: Module settings */ - -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) -#define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ -#else -#define MBEDTLS_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ -#endif - -#define MBEDTLS_ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ -#define MBEDTLS_ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_MAX_SOURCES - -#define MBEDTLS_ENTROPY_SOURCE_STRONG 1 /**< Entropy source is strong */ -#define MBEDTLS_ENTROPY_SOURCE_WEAK 0 /**< Entropy source is weak */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Entropy poll callback pointer - * - * \param data Callback-specific data pointer - * \param output Data to fill - * \param len Maximum size to provide - * \param olen The actual amount of bytes put into the buffer (Can be 0) - * - * \return 0 if no critical failures occurred, - * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise - */ -typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len, - size_t *olen); - -/** - * \brief Entropy source state - */ -typedef struct -{ - mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */ - void * p_source; /**< The callback data pointer */ - size_t size; /**< Amount received in bytes */ - size_t threshold; /**< Minimum bytes required before release */ - int strong; /**< Is the source strong? */ -} -mbedtls_entropy_source_state; - -/** - * \brief Entropy context structure - */ -typedef struct -{ -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - mbedtls_sha512_context accumulator; -#else - mbedtls_sha256_context accumulator; -#endif - int source_count; - mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES]; -#if defined(MBEDTLS_HAVEGE_C) - mbedtls_havege_state havege_data; -#endif -#if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; /*!< mutex */ -#endif -#if defined(MBEDTLS_ENTROPY_NV_SEED) - int initial_entropy_run; -#endif -} -mbedtls_entropy_context; - -/** - * \brief Initialize the context - * - * \param ctx Entropy context to initialize - */ -void mbedtls_entropy_init( mbedtls_entropy_context *ctx ); - -/** - * \brief Free the data in the context - * - * \param ctx Entropy context to free - */ -void mbedtls_entropy_free( mbedtls_entropy_context *ctx ); - -/** - * \brief Adds an entropy source to poll - * (Thread-safe if MBEDTLS_THREADING_C is enabled) - * - * \param ctx Entropy context - * \param f_source Entropy function - * \param p_source Function data - * \param threshold Minimum required from source before entropy is released - * ( with mbedtls_entropy_func() ) (in bytes) - * \param strong MBEDTLS_ENTROPY_SOURCE_STRONG or - * MBEDTSL_ENTROPY_SOURCE_WEAK. - * At least one strong source needs to be added. - * Weaker sources (such as the cycle counter) can be used as - * a complement. - * - * \return 0 if successful or MBEDTLS_ERR_ENTROPY_MAX_SOURCES - */ -int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, - mbedtls_entropy_f_source_ptr f_source, void *p_source, - size_t threshold, int strong ); - -/** - * \brief Trigger an extra gather poll for the accumulator - * (Thread-safe if MBEDTLS_THREADING_C is enabled) - * - * \param ctx Entropy context - * - * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED - */ -int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ); - -/** - * \brief Retrieve entropy from the accumulator - * (Maximum length: MBEDTLS_ENTROPY_BLOCK_SIZE) - * (Thread-safe if MBEDTLS_THREADING_C is enabled) - * - * \param data Entropy context - * \param output Buffer to fill - * \param len Number of bytes desired, must be at most MBEDTLS_ENTROPY_BLOCK_SIZE - * - * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED - */ -int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ); - -/** - * \brief Add data to the accumulator manually - * (Thread-safe if MBEDTLS_THREADING_C is enabled) - * - * \param ctx Entropy context - * \param data Data to add - * \param len Length of data - * - * \return 0 if successful - */ -int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, - const unsigned char *data, size_t len ); - -#if defined(MBEDTLS_ENTROPY_NV_SEED) -/** - * \brief Trigger an update of the seed file in NV by using the - * current entropy pool. - * - * \param ctx Entropy context - * - * \return 0 if successful - */ -int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ); -#endif /* MBEDTLS_ENTROPY_NV_SEED */ - -#if defined(MBEDTLS_FS_IO) -/** - * \brief Write a seed file - * - * \param ctx Entropy context - * \param path Name of the file - * - * \return 0 if successful, - * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, or - * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED - */ -int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ); - -/** - * \brief Read and update a seed file. Seed is added to this - * instance. No more than MBEDTLS_ENTROPY_MAX_SEED_SIZE bytes are - * read from the seed file. The rest is ignored. - * - * \param ctx Entropy context - * \param path Name of the file - * - * \return 0 if successful, - * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, - * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED - */ -int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ); -#endif /* MBEDTLS_FS_IO */ - -#if defined(MBEDTLS_SELF_TEST) -/** - * \brief Checkup routine - * - * This module self-test also calls the entropy self-test, - * mbedtls_entropy_source_self_test(); - * - * \return 0 if successful, or 1 if a test failed - */ -int mbedtls_entropy_self_test( int verbose ); - -#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) -/** - * \brief Checkup routine - * - * Verifies the integrity of the hardware entropy source - * provided by the function 'mbedtls_hardware_poll()'. - * - * Note this is the only hardware entropy source that is known - * at link time, and other entropy sources configured - * dynamically at runtime by the function - * mbedtls_entropy_add_source() will not be tested. - * - * \return 0 if successful, or 1 if a test failed - */ -int mbedtls_entropy_source_self_test( int verbose ); -#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ -#endif /* MBEDTLS_SELF_TEST */ - -#ifdef __cplusplus -} -#endif - -#endif /* entropy.h */ diff --git a/components/mbedtls/include/mbedtls/entropy_poll.h b/components/mbedtls/include/mbedtls/entropy_poll.h deleted file mode 100644 index 81258d5f39..0000000000 --- a/components/mbedtls/include/mbedtls/entropy_poll.h +++ /dev/null @@ -1,109 +0,0 @@ -/** - * \file entropy_poll.h - * - * \brief Platform-specific and custom entropy polling functions - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_ENTROPY_POLL_H -#define MBEDTLS_ENTROPY_POLL_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Default thresholds for built-in sources, in bytes - */ -#define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ -#define MBEDTLS_ENTROPY_MIN_HAVEGE 32 /**< Minimum for HAVEGE */ -#define MBEDTLS_ENTROPY_MIN_HARDCLOCK 4 /**< Minimum for mbedtls_timing_hardclock() */ -#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) -#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ -#endif - -/** - * \brief Entropy poll callback that provides 0 entropy. - */ -#if defined(MBEDTLS_TEST_NULL_ENTROPY) - int mbedtls_null_entropy_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); -#endif - -#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) -/** - * \brief Platform-specific entropy poll callback - */ -int mbedtls_platform_entropy_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); -#endif - -#if defined(MBEDTLS_HAVEGE_C) -/** - * \brief HAVEGE based entropy poll callback - * - * Requires an HAVEGE state as its data pointer. - */ -int mbedtls_havege_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); -#endif - -#if defined(MBEDTLS_TIMING_C) -/** - * \brief mbedtls_timing_hardclock-based entropy poll callback - */ -int mbedtls_hardclock_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); -#endif - -#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) -/** - * \brief Entropy poll callback for a hardware source - * - * \warning This is not provided by mbed TLS! - * See \c MBEDTLS_ENTROPY_HARDWARE_ALT in config.h. - * - * \note This must accept NULL as its first argument. - */ -int mbedtls_hardware_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); -#endif - -#if defined(MBEDTLS_ENTROPY_NV_SEED) -/** - * \brief Entropy poll callback for a non-volatile seed file - * - * \note This must accept NULL as its first argument. - */ -int mbedtls_nv_seed_poll( void *data, - unsigned char *output, size_t len, size_t *olen ); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* entropy_poll.h */ diff --git a/components/mbedtls/include/mbedtls/error.h b/components/mbedtls/include/mbedtls/error.h deleted file mode 100644 index 31591e2d64..0000000000 --- a/components/mbedtls/include/mbedtls/error.h +++ /dev/null @@ -1,107 +0,0 @@ -/** - * \file error.h - * - * \brief Error to string translation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_ERROR_H -#define MBEDTLS_ERROR_H - -#include - -/** - * Error code layout. - * - * Currently we try to keep all error codes within the negative space of 16 - * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In - * addition we'd like to give two layers of information on the error if - * possible. - * - * For that purpose the error codes are segmented in the following manner: - * - * 16 bit error code bit-segmentation - * - * 1 bit - Unused (sign bit) - * 3 bits - High level module ID - * 5 bits - Module-dependent error code - * 7 bits - Low level module errors - * - * For historical reasons, low-level error codes are divided in even and odd, - * even codes were assigned first, and -1 is reserved for other errors. - * - * Low-level module errors (0x0002-0x007E, 0x0003-0x007F) - * - * Module Nr Codes assigned - * MPI 7 0x0002-0x0010 - * GCM 2 0x0012-0x0014 - * BLOWFISH 2 0x0016-0x0018 - * THREADING 3 0x001A-0x001E - * AES 2 0x0020-0x0022 - * CAMELLIA 2 0x0024-0x0026 - * XTEA 1 0x0028-0x0028 - * BASE64 2 0x002A-0x002C - * OID 1 0x002E-0x002E 0x000B-0x000B - * PADLOCK 1 0x0030-0x0030 - * DES 1 0x0032-0x0032 - * CTR_DBRG 4 0x0034-0x003A - * ENTROPY 3 0x003C-0x0040 0x003D-0x003F - * NET 11 0x0042-0x0052 0x0043-0x0045 - * ASN1 7 0x0060-0x006C - * PBKDF2 1 0x007C-0x007C - * HMAC_DRBG 4 0x0003-0x0009 - * CCM 2 0x000D-0x000F - * - * High-level module nr (3 bits - 0x0...-0x7...) - * Name ID Nr of Errors - * PEM 1 9 - * PKCS#12 1 4 (Started from top) - * X509 2 20 - * PKCS5 2 4 (Started from top) - * DHM 3 9 - * PK 3 14 (Started from top) - * RSA 4 9 - * ECP 4 8 (Started from top) - * MD 5 4 - * CIPHER 6 6 - * SSL 6 17 (Started from top) - * SSL 7 31 - * - * Module dependent error code (5 bits 0x.00.-0x.F8.) - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Translate a mbed TLS error code into a string representation, - * Result is truncated if necessary and always includes a terminating - * null byte. - * - * \param errnum error code - * \param buffer buffer to place representation in - * \param buflen length of the buffer - */ -void mbedtls_strerror( int errnum, char *buffer, size_t buflen ); - -#ifdef __cplusplus -} -#endif - -#endif /* error.h */ diff --git a/components/mbedtls/include/mbedtls/gcm.h b/components/mbedtls/include/mbedtls/gcm.h deleted file mode 100644 index 1b77aaedd4..0000000000 --- a/components/mbedtls/include/mbedtls/gcm.h +++ /dev/null @@ -1,220 +0,0 @@ -/** - * \file gcm.h - * - * \brief Galois/Counter mode for 128-bit block ciphers - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_GCM_H -#define MBEDTLS_GCM_H - -#include "cipher.h" - -#include - -#define MBEDTLS_GCM_ENCRYPT 1 -#define MBEDTLS_GCM_DECRYPT 0 - -#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ -#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief GCM context structure - */ -typedef struct { - mbedtls_cipher_context_t cipher_ctx;/*!< cipher context used */ - uint64_t HL[16]; /*!< Precalculated HTable */ - uint64_t HH[16]; /*!< Precalculated HTable */ - uint64_t len; /*!< Total data length */ - uint64_t add_len; /*!< Total add length */ - unsigned char base_ectr[16];/*!< First ECTR for tag */ - unsigned char y[16]; /*!< Y working value */ - unsigned char buf[16]; /*!< buf working value */ - int mode; /*!< Encrypt or Decrypt */ -} -mbedtls_gcm_context; - -/** - * \brief Initialize GCM context (just makes references valid) - * Makes the context ready for mbedtls_gcm_setkey() or - * mbedtls_gcm_free(). - * - * \param ctx GCM context to initialize - */ -void mbedtls_gcm_init( mbedtls_gcm_context *ctx ); - -/** - * \brief GCM initialization (encryption) - * - * \param ctx GCM context to be initialized - * \param cipher cipher to use (a 128-bit block cipher) - * \param key encryption key - * \param keybits must be 128, 192 or 256 - * - * \return 0 if successful, or a cipher specific error code - */ -int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, - mbedtls_cipher_id_t cipher, - const unsigned char *key, - unsigned int keybits ); - -/** - * \brief GCM buffer encryption/decryption using a block cipher - * - * \note On encryption, the output buffer can be the same as the input buffer. - * On decryption, the output buffer cannot be the same as input buffer. - * If buffers overlap, the output buffer must trail at least 8 bytes - * behind the input buffer. - * - * \param ctx GCM context - * \param mode MBEDTLS_GCM_ENCRYPT or MBEDTLS_GCM_DECRYPT - * \param length length of the input data - * \param iv initialization vector - * \param iv_len length of IV - * \param add additional data - * \param add_len length of additional data - * \param input buffer holding the input data - * \param output buffer for holding the output data - * \param tag_len length of the tag to generate - * \param tag buffer for holding the tag - * - * \return 0 if successful - */ -int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, - int mode, - size_t length, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len, - const unsigned char *input, - unsigned char *output, - size_t tag_len, - unsigned char *tag ); - -/** - * \brief GCM buffer authenticated decryption using a block cipher - * - * \note On decryption, the output buffer cannot be the same as input buffer. - * If buffers overlap, the output buffer must trail at least 8 bytes - * behind the input buffer. - * - * \param ctx GCM context - * \param length length of the input data - * \param iv initialization vector - * \param iv_len length of IV - * \param add additional data - * \param add_len length of additional data - * \param tag buffer holding the tag - * \param tag_len length of the tag - * \param input buffer holding the input data - * \param output buffer for holding the output data - * - * \return 0 if successful and authenticated, - * MBEDTLS_ERR_GCM_AUTH_FAILED if tag does not match - */ -int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, - size_t length, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len, - const unsigned char *tag, - size_t tag_len, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Generic GCM stream start function - * - * \param ctx GCM context - * \param mode MBEDTLS_GCM_ENCRYPT or MBEDTLS_GCM_DECRYPT - * \param iv initialization vector - * \param iv_len length of IV - * \param add additional data (or NULL if length is 0) - * \param add_len length of additional data - * - * \return 0 if successful - */ -int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, - int mode, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len ); - -/** - * \brief Generic GCM update function. Encrypts/decrypts using the - * given GCM context. Expects input to be a multiple of 16 - * bytes! Only the last call before mbedtls_gcm_finish() can be less - * than 16 bytes! - * - * \note On decryption, the output buffer cannot be the same as input buffer. - * If buffers overlap, the output buffer must trail at least 8 bytes - * behind the input buffer. - * - * \param ctx GCM context - * \param length length of the input data - * \param input buffer holding the input data - * \param output buffer for holding the output data - * - * \return 0 if successful or MBEDTLS_ERR_GCM_BAD_INPUT - */ -int mbedtls_gcm_update( mbedtls_gcm_context *ctx, - size_t length, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Generic GCM finalisation function. Wraps up the GCM stream - * and generates the tag. The tag can have a maximum length of - * 16 bytes. - * - * \param ctx GCM context - * \param tag buffer for holding the tag - * \param tag_len length of the tag to generate (must be at least 4) - * - * \return 0 if successful or MBEDTLS_ERR_GCM_BAD_INPUT - */ -int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, - unsigned char *tag, - size_t tag_len ); - -/** - * \brief Free a GCM context and underlying cipher sub-context - * - * \param ctx GCM context to free - */ -void mbedtls_gcm_free( mbedtls_gcm_context *ctx ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_gcm_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* gcm.h */ diff --git a/components/mbedtls/include/mbedtls/havege.h b/components/mbedtls/include/mbedtls/havege.h deleted file mode 100644 index dac5d31138..0000000000 --- a/components/mbedtls/include/mbedtls/havege.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * \file havege.h - * - * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_HAVEGE_H -#define MBEDTLS_HAVEGE_H - -#include - -#define MBEDTLS_HAVEGE_COLLECT_SIZE 1024 - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief HAVEGE state structure - */ -typedef struct -{ - int PT1, PT2, offset[2]; - int pool[MBEDTLS_HAVEGE_COLLECT_SIZE]; - int WALK[8192]; -} -mbedtls_havege_state; - -/** - * \brief HAVEGE initialization - * - * \param hs HAVEGE state to be initialized - */ -void mbedtls_havege_init( mbedtls_havege_state *hs ); - -/** - * \brief Clear HAVEGE state - * - * \param hs HAVEGE state to be cleared - */ -void mbedtls_havege_free( mbedtls_havege_state *hs ); - -/** - * \brief HAVEGE rand function - * - * \param p_rng A HAVEGE state - * \param output Buffer to fill - * \param len Length of buffer - * - * \return 0 - */ -int mbedtls_havege_random( void *p_rng, unsigned char *output, size_t len ); - -#ifdef __cplusplus -} -#endif - -#endif /* havege.h */ diff --git a/components/mbedtls/include/mbedtls/hmac_drbg.h b/components/mbedtls/include/mbedtls/hmac_drbg.h deleted file mode 100644 index e010558028..0000000000 --- a/components/mbedtls/include/mbedtls/hmac_drbg.h +++ /dev/null @@ -1,299 +0,0 @@ -/** - * \file hmac_drbg.h - * - * \brief HMAC_DRBG (NIST SP 800-90A) - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_HMAC_DRBG_H -#define MBEDTLS_HMAC_DRBG_H - -#include "md.h" - -#if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" -#endif - -/* - * Error codes - */ -#define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 /**< Too many random requested in single call. */ -#define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 /**< Input too large (Entropy + additional). */ -#define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 /**< Read/write error in file. */ -#define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 /**< The entropy source failed. */ - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -#if !defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) -#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ -#endif - -#if !defined(MBEDTLS_HMAC_DRBG_MAX_INPUT) -#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ -#endif - -#if !defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST) -#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ -#endif - -#if !defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) -#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ -#endif - -/* \} name SECTION: Module settings */ - -#define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */ -#define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * HMAC_DRBG context. - */ -typedef struct -{ - /* Working state: the key K is not stored explicitely, - * but is implied by the HMAC context */ - mbedtls_md_context_t md_ctx; /*!< HMAC context (inc. K) */ - unsigned char V[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */ - int reseed_counter; /*!< reseed counter */ - - /* Administrative state */ - size_t entropy_len; /*!< entropy bytes grabbed on each (re)seed */ - int prediction_resistance; /*!< enable prediction resistance (Automatic - reseed before every random generation) */ - int reseed_interval; /*!< reseed interval */ - - /* Callbacks */ - int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */ - void *p_entropy; /*!< context for the entropy function */ - -#if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; -#endif -} mbedtls_hmac_drbg_context; - -/** - * \brief HMAC_DRBG context initialization - * Makes the context ready for mbedtls_hmac_drbg_seed(), - * mbedtls_hmac_drbg_seed_buf() or - * mbedtls_hmac_drbg_free(). - * - * \param ctx HMAC_DRBG context to be initialized - */ -void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ); - -/** - * \brief HMAC_DRBG initial seeding - * Seed and setup entropy source for future reseeds. - * - * \param ctx HMAC_DRBG context to be seeded - * \param md_info MD algorithm to use for HMAC_DRBG - * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer - * length) - * \param p_entropy Entropy context - * \param custom Personalization data (Device specific identifiers) - * (Can be NULL) - * \param len Length of personalization data - * - * \note The "security strength" as defined by NIST is set to: - * 128 bits if md_alg is SHA-1, - * 192 bits if md_alg is SHA-224, - * 256 bits if md_alg is SHA-256 or higher. - * Note that SHA-256 is just as efficient as SHA-224. - * - * \return 0 if successful, or - * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or - * MBEDTLS_ERR_MD_ALLOC_FAILED, or - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED. - */ -int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, - const mbedtls_md_info_t * md_info, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len ); - -/** - * \brief Initilisation of simpified HMAC_DRBG (never reseeds). - * (For use with deterministic ECDSA.) - * - * \param ctx HMAC_DRBG context to be initialised - * \param md_info MD algorithm to use for HMAC_DRBG - * \param data Concatenation of entropy string and additional data - * \param data_len Length of data in bytes - * - * \return 0 if successful, or - * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or - * MBEDTLS_ERR_MD_ALLOC_FAILED. - */ -int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, - const mbedtls_md_info_t * md_info, - const unsigned char *data, size_t data_len ); - -/** - * \brief Enable / disable prediction resistance (Default: Off) - * - * Note: If enabled, entropy is used for ctx->entropy_len before each call! - * Only use this if you have ample supply of good entropy! - * - * \param ctx HMAC_DRBG context - * \param resistance MBEDTLS_HMAC_DRBG_PR_ON or MBEDTLS_HMAC_DRBG_PR_OFF - */ -void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, - int resistance ); - -/** - * \brief Set the amount of entropy grabbed on each reseed - * (Default: given by the security strength, which - * depends on the hash used, see \c mbedtls_hmac_drbg_init() ) - * - * \param ctx HMAC_DRBG context - * \param len Amount of entropy to grab, in bytes - */ -void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, - size_t len ); - -/** - * \brief Set the reseed interval - * (Default: MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) - * - * \param ctx HMAC_DRBG context - * \param interval Reseed interval - */ -void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, - int interval ); - -/** - * \brief HMAC_DRBG update state - * - * \param ctx HMAC_DRBG context - * \param additional Additional data to update state with, or NULL - * \param add_len Length of additional data, or 0 - * - * \note Additional data is optional, pass NULL and 0 as second - * third argument if no additional data is being used. - */ -void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, - const unsigned char *additional, size_t add_len ); - -/** - * \brief HMAC_DRBG reseeding (extracts data from entropy source) - * - * \param ctx HMAC_DRBG context - * \param additional Additional data to add to state (Can be NULL) - * \param len Length of additional data - * - * \return 0 if successful, or - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED - */ -int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, - const unsigned char *additional, size_t len ); - -/** - * \brief HMAC_DRBG generate random with additional update input - * - * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. - * - * \param p_rng HMAC_DRBG context - * \param output Buffer to fill - * \param output_len Length of the buffer - * \param additional Additional data to update with (can be NULL) - * \param add_len Length of additional data (can be 0) - * - * \return 0 if successful, or - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or - * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or - * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG. - */ -int mbedtls_hmac_drbg_random_with_add( void *p_rng, - unsigned char *output, size_t output_len, - const unsigned char *additional, - size_t add_len ); - -/** - * \brief HMAC_DRBG generate random - * - * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. - * - * \param p_rng HMAC_DRBG context - * \param output Buffer to fill - * \param out_len Length of the buffer - * - * \return 0 if successful, or - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or - * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG - */ -int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ); - -/** - * \brief Free an HMAC_DRBG context - * - * \param ctx HMAC_DRBG context to free. - */ -void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ); - -#if defined(MBEDTLS_FS_IO) -/** - * \brief Write a seed file - * - * \param ctx HMAC_DRBG context - * \param path Name of the file - * - * \return 0 if successful, 1 on file error, or - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED - */ -int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); - -/** - * \brief Read and update a seed file. Seed is added to this - * instance - * - * \param ctx HMAC_DRBG context - * \param path Name of the file - * - * \return 0 if successful, 1 on file error, - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or - * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG - */ -int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); -#endif /* MBEDTLS_FS_IO */ - - -#if defined(MBEDTLS_SELF_TEST) -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_hmac_drbg_self_test( int verbose ); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* hmac_drbg.h */ diff --git a/components/mbedtls/include/mbedtls/md.h b/components/mbedtls/include/mbedtls/md.h deleted file mode 100644 index 9b996a951b..0000000000 --- a/components/mbedtls/include/mbedtls/md.h +++ /dev/null @@ -1,354 +0,0 @@ -/** - * \file md.h - * - * \brief Generic message digest wrapper - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_MD_H -#define MBEDTLS_MD_H - -#include - -#define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */ -#define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ -#define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - MBEDTLS_MD_NONE=0, - MBEDTLS_MD_MD2, - MBEDTLS_MD_MD4, - MBEDTLS_MD_MD5, - MBEDTLS_MD_SHA1, - MBEDTLS_MD_SHA224, - MBEDTLS_MD_SHA256, - MBEDTLS_MD_SHA384, - MBEDTLS_MD_SHA512, - MBEDTLS_MD_RIPEMD160, -} mbedtls_md_type_t; - -#if defined(MBEDTLS_SHA512_C) -#define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ -#else -#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ -#endif - -/** - * Opaque struct defined in md_internal.h - */ -typedef struct mbedtls_md_info_t mbedtls_md_info_t; - -/** - * Generic message digest context. - */ -typedef struct { - /** Information about the associated message digest */ - const mbedtls_md_info_t *md_info; - - /** Digest-specific context */ - void *md_ctx; - - /** HMAC part of the context */ - void *hmac_ctx; -} mbedtls_md_context_t; - -/** - * \brief Returns the list of digests supported by the generic digest module. - * - * \return a statically allocated array of digests, the last entry - * is 0. - */ -const int *mbedtls_md_list( void ); - -/** - * \brief Returns the message digest information associated with the - * given digest name. - * - * \param md_name Name of the digest to search for. - * - * \return The message digest information associated with md_name or - * NULL if not found. - */ -const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); - -/** - * \brief Returns the message digest information associated with the - * given digest type. - * - * \param md_type type of digest to search for. - * - * \return The message digest information associated with md_type or - * NULL if not found. - */ -const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ); - -/** - * \brief Initialize a md_context (as NONE) - * This should always be called first. - * Prepares the context for mbedtls_md_setup() or mbedtls_md_free(). - */ -void mbedtls_md_init( mbedtls_md_context_t *ctx ); - -/** - * \brief Free and clear the internal structures of ctx. - * Can be called at any time after mbedtls_md_init(). - * Mandatory once mbedtls_md_setup() has been called. - */ -void mbedtls_md_free( mbedtls_md_context_t *ctx ); - -#if ! defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief Select MD to use and allocate internal structures. - * Should be called after mbedtls_md_init() or mbedtls_md_free(). - * Makes it necessary to call mbedtls_md_free() later. - * - * \deprecated Superseded by mbedtls_md_setup() in 2.0.0 - * - * \param ctx Context to set up. - * \param md_info Message digest to use. - * - * \returns \c 0 on success, - * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, - * \c MBEDTLS_ERR_MD_ALLOC_FAILED memory allocation failure. - */ -int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) MBEDTLS_DEPRECATED; -#undef MBEDTLS_DEPRECATED -#endif /* MBEDTLS_DEPRECATED_REMOVED */ - -/** - * \brief Select MD to use and allocate internal structures. - * Should be called after mbedtls_md_init() or mbedtls_md_free(). - * Makes it necessary to call mbedtls_md_free() later. - * - * \param ctx Context to set up. - * \param md_info Message digest to use. - * \param hmac 0 to save some memory if HMAC will not be used, - * non-zero is HMAC is going to be used with this context. - * - * \returns \c 0 on success, - * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure, - * \c MBEDTLS_ERR_MD_ALLOC_FAILED memory allocation failure. - */ -int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); - -/** - * \brief Clone the state of an MD context - * - * \note The two contexts must have been setup to the same type - * (cloning from SHA-256 to SHA-512 make no sense). - * - * \warning Only clones the MD state, not the HMAC state! (for now) - * - * \param dst The destination context - * \param src The context to be cloned - * - * \return \c 0 on success, - * \c MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter failure. - */ -int mbedtls_md_clone( mbedtls_md_context_t *dst, - const mbedtls_md_context_t *src ); - -/** - * \brief Returns the size of the message digest output. - * - * \param md_info message digest info - * - * \return size of the message digest output in bytes. - */ -unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ); - -/** - * \brief Returns the type of the message digest output. - * - * \param md_info message digest info - * - * \return type of the message digest output. - */ -mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ); - -/** - * \brief Returns the name of the message digest output. - * - * \param md_info message digest info - * - * \return name of the message digest output. - */ -const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); - -/** - * \brief Prepare the context to digest a new message. - * Generally called after mbedtls_md_setup() or mbedtls_md_finish(). - * Followed by mbedtls_md_update(). - * - * \param ctx generic message digest context. - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md_starts( mbedtls_md_context_t *ctx ); - -/** - * \brief Generic message digest process buffer - * Called between mbedtls_md_starts() and mbedtls_md_finish(). - * May be called repeatedly. - * - * \param ctx Generic message digest context - * \param input buffer holding the datal - * \param ilen length of the input data - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief Generic message digest final digest - * Called after mbedtls_md_update(). - * Usually followed by mbedtls_md_free() or mbedtls_md_starts(). - * - * \param ctx Generic message digest context - * \param output Generic message digest checksum result - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); - -/** - * \brief Output = message_digest( input buffer ) - * - * \param md_info message digest info - * \param input buffer holding the data - * \param ilen length of the input data - * \param output Generic message digest checksum result - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, - unsigned char *output ); - -#if defined(MBEDTLS_FS_IO) -/** - * \brief Output = message_digest( file contents ) - * - * \param md_info message digest info - * \param path input file name - * \param output generic message digest checksum result - * - * \return 0 if successful, - * MBEDTLS_ERR_MD_FILE_IO_ERROR if file input failed, - * MBEDTLS_ERR_MD_BAD_INPUT_DATA if md_info was NULL. - */ -int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, - unsigned char *output ); -#endif /* MBEDTLS_FS_IO */ - -/** - * \brief Set HMAC key and prepare to authenticate a new message. - * Usually called after mbedtls_md_setup() or mbedtls_md_hmac_finish(). - * - * \param ctx HMAC context - * \param key HMAC secret key - * \param keylen length of the HMAC key in bytes - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, - size_t keylen ); - -/** - * \brief Generic HMAC process buffer. - * Called between mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() - * and mbedtls_md_hmac_finish(). - * May be called repeatedly. - * - * \param ctx HMAC context - * \param input buffer holding the data - * \param ilen length of the input data - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, - size_t ilen ); - -/** - * \brief Output HMAC. - * Called after mbedtls_md_hmac_update(). - * Usually followed by mbedtls_md_hmac_reset(), - * mbedtls_md_hmac_starts(), or mbedtls_md_free(). - * - * \param ctx HMAC context - * \param output Generic HMAC checksum result - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); - -/** - * \brief Prepare to authenticate a new message with the same key. - * Called after mbedtls_md_hmac_finish() and before - * mbedtls_md_hmac_update(). - * - * \param ctx HMAC context to be reset - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); - -/** - * \brief Output = Generic_HMAC( hmac key, input buffer ) - * - * \param md_info message digest info - * \param key HMAC secret key - * \param keylen length of the HMAC key in bytes - * \param input buffer holding the data - * \param ilen length of the input data - * \param output Generic HMAC-result - * - * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter - * verification fails. - */ -int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char *output ); - -/* Internal use */ -int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ); - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_MD_H */ diff --git a/components/mbedtls/include/mbedtls/md2.h b/components/mbedtls/include/mbedtls/md2.h deleted file mode 100644 index 0f93fbf427..0000000000 --- a/components/mbedtls/include/mbedtls/md2.h +++ /dev/null @@ -1,136 +0,0 @@ -/** - * \file md2.h - * - * \brief MD2 message digest algorithm (hash function) - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_MD2_H -#define MBEDTLS_MD2_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -#if !defined(MBEDTLS_MD2_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief MD2 context structure - */ -typedef struct -{ - unsigned char cksum[16]; /*!< checksum of the data block */ - unsigned char state[48]; /*!< intermediate digest state */ - unsigned char buffer[16]; /*!< data block being processed */ - size_t left; /*!< amount of data in buffer */ -} -mbedtls_md2_context; - -/** - * \brief Initialize MD2 context - * - * \param ctx MD2 context to be initialized - */ -void mbedtls_md2_init( mbedtls_md2_context *ctx ); - -/** - * \brief Clear MD2 context - * - * \param ctx MD2 context to be cleared - */ -void mbedtls_md2_free( mbedtls_md2_context *ctx ); - -/** - * \brief Clone (the state of) an MD2 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_md2_clone( mbedtls_md2_context *dst, - const mbedtls_md2_context *src ); - -/** - * \brief MD2 context setup - * - * \param ctx context to be initialized - */ -void mbedtls_md2_starts( mbedtls_md2_context *ctx ); - -/** - * \brief MD2 process buffer - * - * \param ctx MD2 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_md2_update( mbedtls_md2_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief MD2 final digest - * - * \param ctx MD2 context - * \param output MD2 checksum result - */ -void mbedtls_md2_finish( mbedtls_md2_context *ctx, unsigned char output[16] ); - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_MD2_ALT */ -#include "md2_alt.h" -#endif /* MBEDTLS_MD2_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Output = MD2( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output MD2 checksum result - */ -void mbedtls_md2( const unsigned char *input, size_t ilen, unsigned char output[16] ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_md2_self_test( int verbose ); - -/* Internal use */ -void mbedtls_md2_process( mbedtls_md2_context *ctx ); - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_md2.h */ diff --git a/components/mbedtls/include/mbedtls/md4.h b/components/mbedtls/include/mbedtls/md4.h deleted file mode 100644 index 45214d41d9..0000000000 --- a/components/mbedtls/include/mbedtls/md4.h +++ /dev/null @@ -1,136 +0,0 @@ -/** - * \file md4.h - * - * \brief MD4 message digest algorithm (hash function) - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_MD4_H -#define MBEDTLS_MD4_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#if !defined(MBEDTLS_MD4_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief MD4 context structure - */ -typedef struct -{ - uint32_t total[2]; /*!< number of bytes processed */ - uint32_t state[4]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ -} -mbedtls_md4_context; - -/** - * \brief Initialize MD4 context - * - * \param ctx MD4 context to be initialized - */ -void mbedtls_md4_init( mbedtls_md4_context *ctx ); - -/** - * \brief Clear MD4 context - * - * \param ctx MD4 context to be cleared - */ -void mbedtls_md4_free( mbedtls_md4_context *ctx ); - -/** - * \brief Clone (the state of) an MD4 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_md4_clone( mbedtls_md4_context *dst, - const mbedtls_md4_context *src ); - -/** - * \brief MD4 context setup - * - * \param ctx context to be initialized - */ -void mbedtls_md4_starts( mbedtls_md4_context *ctx ); - -/** - * \brief MD4 process buffer - * - * \param ctx MD4 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief MD4 final digest - * - * \param ctx MD4 context - * \param output MD4 checksum result - */ -void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] ); - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_MD4_ALT */ -#include "md4_alt.h" -#endif /* MBEDTLS_MD4_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Output = MD4( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output MD4 checksum result - */ -void mbedtls_md4( const unsigned char *input, size_t ilen, unsigned char output[16] ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_md4_self_test( int verbose ); - -/* Internal use */ -void mbedtls_md4_process( mbedtls_md4_context *ctx, const unsigned char data[64] ); - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_md4.h */ diff --git a/components/mbedtls/include/mbedtls/md5.h b/components/mbedtls/include/mbedtls/md5.h deleted file mode 100644 index 5a64061aa0..0000000000 --- a/components/mbedtls/include/mbedtls/md5.h +++ /dev/null @@ -1,136 +0,0 @@ -/** - * \file md5.h - * - * \brief MD5 message digest algorithm (hash function) - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_MD5_H -#define MBEDTLS_MD5_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#if !defined(MBEDTLS_MD5_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief MD5 context structure - */ -typedef struct -{ - uint32_t total[2]; /*!< number of bytes processed */ - uint32_t state[4]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ -} -mbedtls_md5_context; - -/** - * \brief Initialize MD5 context - * - * \param ctx MD5 context to be initialized - */ -void mbedtls_md5_init( mbedtls_md5_context *ctx ); - -/** - * \brief Clear MD5 context - * - * \param ctx MD5 context to be cleared - */ -void mbedtls_md5_free( mbedtls_md5_context *ctx ); - -/** - * \brief Clone (the state of) an MD5 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_md5_clone( mbedtls_md5_context *dst, - const mbedtls_md5_context *src ); - -/** - * \brief MD5 context setup - * - * \param ctx context to be initialized - */ -void mbedtls_md5_starts( mbedtls_md5_context *ctx ); - -/** - * \brief MD5 process buffer - * - * \param ctx MD5 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief MD5 final digest - * - * \param ctx MD5 context - * \param output MD5 checksum result - */ -void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ); - -/* Internal use */ -void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] ); - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_MD5_ALT */ -#include "md5_alt.h" -#endif /* MBEDTLS_MD5_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Output = MD5( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output MD5 checksum result - */ -void mbedtls_md5( const unsigned char *input, size_t ilen, unsigned char output[16] ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_md5_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_md5.h */ diff --git a/components/mbedtls/include/mbedtls/md_internal.h b/components/mbedtls/include/mbedtls/md_internal.h deleted file mode 100644 index e2441bbc49..0000000000 --- a/components/mbedtls/include/mbedtls/md_internal.h +++ /dev/null @@ -1,114 +0,0 @@ -/** - * \file md_internal.h - * - * \brief Message digest wrappers. - * - * \warning This in an internal header. Do not include directly. - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_MD_WRAP_H -#define MBEDTLS_MD_WRAP_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "md.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Message digest information. - * Allows message digest functions to be called in a generic way. - */ -struct mbedtls_md_info_t -{ - /** Digest identifier */ - mbedtls_md_type_t type; - - /** Name of the message digest */ - const char * name; - - /** Output length of the digest function in bytes */ - int size; - - /** Block length of the digest function in bytes */ - int block_size; - - /** Digest initialisation function */ - void (*starts_func)( void *ctx ); - - /** Digest update function */ - void (*update_func)( void *ctx, const unsigned char *input, size_t ilen ); - - /** Digest finalisation function */ - void (*finish_func)( void *ctx, unsigned char *output ); - - /** Generic digest function */ - void (*digest_func)( const unsigned char *input, size_t ilen, - unsigned char *output ); - - /** Allocate a new context */ - void * (*ctx_alloc_func)( void ); - - /** Free the given context */ - void (*ctx_free_func)( void *ctx ); - - /** Clone state from a context */ - void (*clone_func)( void *dst, const void *src ); - - /** Internal use only */ - void (*process_func)( void *ctx, const unsigned char *input ); -}; - -#if defined(MBEDTLS_MD2_C) -extern const mbedtls_md_info_t mbedtls_md2_info; -#endif -#if defined(MBEDTLS_MD4_C) -extern const mbedtls_md_info_t mbedtls_md4_info; -#endif -#if defined(MBEDTLS_MD5_C) -extern const mbedtls_md_info_t mbedtls_md5_info; -#endif -#if defined(MBEDTLS_RIPEMD160_C) -extern const mbedtls_md_info_t mbedtls_ripemd160_info; -#endif -#if defined(MBEDTLS_SHA1_C) -extern const mbedtls_md_info_t mbedtls_sha1_info; -#endif -#if defined(MBEDTLS_SHA256_C) -extern const mbedtls_md_info_t mbedtls_sha224_info; -extern const mbedtls_md_info_t mbedtls_sha256_info; -#endif -#if defined(MBEDTLS_SHA512_C) -extern const mbedtls_md_info_t mbedtls_sha384_info; -extern const mbedtls_md_info_t mbedtls_sha512_info; -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_MD_WRAP_H */ diff --git a/components/mbedtls/include/mbedtls/memory_buffer_alloc.h b/components/mbedtls/include/mbedtls/memory_buffer_alloc.h deleted file mode 100644 index d5df316fdd..0000000000 --- a/components/mbedtls/include/mbedtls/memory_buffer_alloc.h +++ /dev/null @@ -1,150 +0,0 @@ -/** - * \file memory_buffer_alloc.h - * - * \brief Buffer-based memory allocator - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_MEMORY_BUFFER_ALLOC_H -#define MBEDTLS_MEMORY_BUFFER_ALLOC_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -#if !defined(MBEDTLS_MEMORY_ALIGN_MULTIPLE) -#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ -#endif - -/* \} name SECTION: Module settings */ - -#define MBEDTLS_MEMORY_VERIFY_NONE 0 -#define MBEDTLS_MEMORY_VERIFY_ALLOC (1 << 0) -#define MBEDTLS_MEMORY_VERIFY_FREE (1 << 1) -#define MBEDTLS_MEMORY_VERIFY_ALWAYS (MBEDTLS_MEMORY_VERIFY_ALLOC | MBEDTLS_MEMORY_VERIFY_FREE) - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Initialize use of stack-based memory allocator. - * The stack-based allocator does memory management inside the - * presented buffer and does not call calloc() and free(). - * It sets the global mbedtls_calloc() and mbedtls_free() pointers - * to its own functions. - * (Provided mbedtls_calloc() and mbedtls_free() are thread-safe if - * MBEDTLS_THREADING_C is defined) - * - * \note This code is not optimized and provides a straight-forward - * implementation of a stack-based memory allocator. - * - * \param buf buffer to use as heap - * \param len size of the buffer - */ -void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ); - -/** - * \brief Free the mutex for thread-safety and clear remaining memory - */ -void mbedtls_memory_buffer_alloc_free( void ); - -/** - * \brief Determine when the allocator should automatically verify the state - * of the entire chain of headers / meta-data. - * (Default: MBEDTLS_MEMORY_VERIFY_NONE) - * - * \param verify One of MBEDTLS_MEMORY_VERIFY_NONE, MBEDTLS_MEMORY_VERIFY_ALLOC, - * MBEDTLS_MEMORY_VERIFY_FREE or MBEDTLS_MEMORY_VERIFY_ALWAYS - */ -void mbedtls_memory_buffer_set_verify( int verify ); - -#if defined(MBEDTLS_MEMORY_DEBUG) -/** - * \brief Print out the status of the allocated memory (primarily for use - * after a program should have de-allocated all memory) - * Prints out a list of 'still allocated' blocks and their stack - * trace if MBEDTLS_MEMORY_BACKTRACE is defined. - */ -void mbedtls_memory_buffer_alloc_status( void ); - -/** - * \brief Get the peak heap usage so far - * - * \param max_used Peak number of bytes in use or committed. This - * includes bytes in allocated blocks too small to split - * into smaller blocks but larger than the requested size. - * \param max_blocks Peak number of blocks in use, including free and used - */ -void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ); - -/** - * \brief Reset peak statistics - */ -void mbedtls_memory_buffer_alloc_max_reset( void ); - -/** - * \brief Get the current heap usage - * - * \param cur_used Current number of bytes in use or committed. This - * includes bytes in allocated blocks too small to split - * into smaller blocks but larger than the requested size. - * \param cur_blocks Current number of blocks in use, including free and used - */ -void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ); -#endif /* MBEDTLS_MEMORY_DEBUG */ - -/** - * \brief Verifies that all headers in the memory buffer are correct - * and contain sane values. Helps debug buffer-overflow errors. - * - * Prints out first failure if MBEDTLS_MEMORY_DEBUG is defined. - * Prints out full header information if MBEDTLS_MEMORY_DEBUG - * is defined. (Includes stack trace information for each block if - * MBEDTLS_MEMORY_BACKTRACE is defined as well). - * - * \return 0 if verified, 1 otherwise - */ -int mbedtls_memory_buffer_alloc_verify( void ); - -#if defined(MBEDTLS_SELF_TEST) -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if a test failed - */ -int mbedtls_memory_buffer_alloc_self_test( int verbose ); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* memory_buffer_alloc.h */ diff --git a/components/mbedtls/include/mbedtls/net.h b/components/mbedtls/include/mbedtls/net.h deleted file mode 100644 index 774559b3cf..0000000000 --- a/components/mbedtls/include/mbedtls/net.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * \file net.h - * - * \brief Deprecated header file that includes mbedtls/net_sockets.h - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - * - * \deprecated Superseded by mbedtls/net_sockets.h - */ - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#include "mbedtls/net_sockets.h" -#if defined(MBEDTLS_DEPRECATED_WARNING) -#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h" -#endif /* MBEDTLS_DEPRECATED_WARNING */ -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ diff --git a/components/mbedtls/include/mbedtls/net_sockets.h b/components/mbedtls/include/mbedtls/net_sockets.h deleted file mode 100644 index de335526fe..0000000000 --- a/components/mbedtls/include/mbedtls/net_sockets.h +++ /dev/null @@ -1,225 +0,0 @@ -/** - * \file net_sockets.h - * - * \brief Network communication functions - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_NET_SOCKETS_H -#define MBEDTLS_NET_SOCKETS_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "ssl.h" - -#include -#include - -#define MBEDTLS_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */ -#define MBEDTLS_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */ -#define MBEDTLS_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */ -#define MBEDTLS_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */ -#define MBEDTLS_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */ -#define MBEDTLS_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */ -#define MBEDTLS_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */ -#define MBEDTLS_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */ -#define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /**< Failed to get an IP address for the given hostname. */ -#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /**< Buffer is too small to hold the data. */ -#define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /**< The context is invalid, eg because it was free()ed. */ - -#define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ - -#define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */ -#define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Wrapper type for sockets. - * - * Currently backed by just a file descriptor, but might be more in the future - * (eg two file descriptors for combined IPv4 + IPv6 support, or additional - * structures for hand-made UDP demultiplexing). - */ -typedef struct -{ - int fd; /**< The underlying file descriptor */ -} -mbedtls_net_context; - -/** - * \brief Initialize a context - * Just makes the context ready to be used or freed safely. - * - * \param ctx Context to initialize - */ -void mbedtls_net_init( mbedtls_net_context *ctx ); - -/** - * \brief Initiate a connection with host:port in the given protocol - * - * \param ctx Socket to use - * \param host Host to connect to - * \param port Port to connect to - * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP - * - * \return 0 if successful, or one of: - * MBEDTLS_ERR_NET_SOCKET_FAILED, - * MBEDTLS_ERR_NET_UNKNOWN_HOST, - * MBEDTLS_ERR_NET_CONNECT_FAILED - * - * \note Sets the socket in connected mode even with UDP. - */ -int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto ); - -/** - * \brief Create a receiving socket on bind_ip:port in the chosen - * protocol. If bind_ip == NULL, all interfaces are bound. - * - * \param ctx Socket to use - * \param bind_ip IP to bind to, can be NULL - * \param port Port number to use - * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP - * - * \return 0 if successful, or one of: - * MBEDTLS_ERR_NET_SOCKET_FAILED, - * MBEDTLS_ERR_NET_BIND_FAILED, - * MBEDTLS_ERR_NET_LISTEN_FAILED - * - * \note Regardless of the protocol, opens the sockets and binds it. - * In addition, make the socket listening if protocol is TCP. - */ -int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ); - -/** - * \brief Accept a connection from a remote client - * - * \param bind_ctx Relevant socket - * \param client_ctx Will contain the connected client socket - * \param client_ip Will contain the client IP address - * \param buf_size Size of the client_ip buffer - * \param ip_len Will receive the size of the client IP written - * - * \return 0 if successful, or - * MBEDTLS_ERR_NET_ACCEPT_FAILED, or - * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, - * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to - * non-blocking and accept() would block. - */ -int mbedtls_net_accept( mbedtls_net_context *bind_ctx, - mbedtls_net_context *client_ctx, - void *client_ip, size_t buf_size, size_t *ip_len ); - -/** - * \brief Set the socket blocking - * - * \param ctx Socket to set - * - * \return 0 if successful, or a non-zero error code - */ -int mbedtls_net_set_block( mbedtls_net_context *ctx ); - -/** - * \brief Set the socket non-blocking - * - * \param ctx Socket to set - * - * \return 0 if successful, or a non-zero error code - */ -int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ); - -/** - * \brief Portable usleep helper - * - * \param usec Amount of microseconds to sleep - * - * \note Real amount of time slept will not be less than - * select()'s timeout granularity (typically, 10ms). - */ -void mbedtls_net_usleep( unsigned long usec ); - -/** - * \brief Read at most 'len' characters. If no error occurs, - * the actual amount read is returned. - * - * \param ctx Socket - * \param buf The buffer to write to - * \param len Maximum length of the buffer - * - * \return the number of bytes received, - * or a non-zero error code; with a non-blocking socket, - * MBEDTLS_ERR_SSL_WANT_READ indicates read() would block. - */ -int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ); - -/** - * \brief Write at most 'len' characters. If no error occurs, - * the actual amount read is returned. - * - * \param ctx Socket - * \param buf The buffer to read from - * \param len The length of the buffer - * - * \return the number of bytes sent, - * or a non-zero error code; with a non-blocking socket, - * MBEDTLS_ERR_SSL_WANT_WRITE indicates write() would block. - */ -int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ); - -/** - * \brief Read at most 'len' characters, blocking for at most - * 'timeout' seconds. If no error occurs, the actual amount - * read is returned. - * - * \param ctx Socket - * \param buf The buffer to write to - * \param len Maximum length of the buffer - * \param timeout Maximum number of milliseconds to wait for data - * 0 means no timeout (wait forever) - * - * \return the number of bytes received, - * or a non-zero error code: - * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, - * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. - * - * \note This function will block (until data becomes available or - * timeout is reached) even if the socket is set to - * non-blocking. Handling timeouts with non-blocking reads - * requires a different strategy. - */ -int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, - uint32_t timeout ); - -/** - * \brief Gracefully shutdown the connection and free associated data - * - * \param ctx The context to free - */ -void mbedtls_net_free( mbedtls_net_context *ctx ); - -#ifdef __cplusplus -} -#endif - -#endif /* net_sockets.h */ diff --git a/components/mbedtls/include/mbedtls/oid.h b/components/mbedtls/include/mbedtls/oid.h deleted file mode 100644 index fcecdafdca..0000000000 --- a/components/mbedtls/include/mbedtls/oid.h +++ /dev/null @@ -1,570 +0,0 @@ -/** - * \file oid.h - * - * \brief Object Identifier (OID) database - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_OID_H -#define MBEDTLS_OID_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "asn1.h" -#include "pk.h" - -#include - -#if defined(MBEDTLS_CIPHER_C) -#include "cipher.h" -#endif - -#if defined(MBEDTLS_MD_C) -#include "md.h" -#endif - -#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) -#include "x509.h" -#endif - -#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E /**< OID is not found. */ -#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B /**< output buffer is too small */ - -/* - * Top level OID tuples - */ -#define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ -#define MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ -#define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ -#define MBEDTLS_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ - -/* - * ISO Member bodies OID parts - */ -#define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ -#define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ -#define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ - MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ -#define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ -#define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ - MBEDTLS_OID_ORG_ANSI_X9_62 - -/* - * ISO Identified organization OID parts - */ -#define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ -#define MBEDTLS_OID_ORG_OIW "\x0e" -#define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" -#define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" -#define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" -#define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ -#define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_CERTICOM -#define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ -#define MBEDTLS_OID_TELETRUST MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_TELETRUST - -/* - * ISO ITU OID parts - */ -#define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ -#define MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ - -#define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ -#define MBEDTLS_OID_GOV MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ - -#define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ -#define MBEDTLS_OID_NETSCAPE MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ - -/* ISO arc for standard certificate and CRL extensions */ -#define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ - -/** - * Private Internet Extensions - * { iso(1) identified-organization(3) dod(6) internet(1) - * security(5) mechanisms(5) pkix(7) } - */ -#define MBEDTLS_OID_PKIX MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01\x05\x05\x07" - -/* - * Arc for standard naming attributes - */ -#define MBEDTLS_OID_AT MBEDTLS_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ -#define MBEDTLS_OID_AT_CN MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ -#define MBEDTLS_OID_AT_SUR_NAME MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ -#define MBEDTLS_OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ -#define MBEDTLS_OID_AT_COUNTRY MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ -#define MBEDTLS_OID_AT_LOCALITY MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ -#define MBEDTLS_OID_AT_STATE MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ -#define MBEDTLS_OID_AT_ORGANIZATION MBEDTLS_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ -#define MBEDTLS_OID_AT_ORG_UNIT MBEDTLS_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ -#define MBEDTLS_OID_AT_TITLE MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ -#define MBEDTLS_OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ -#define MBEDTLS_OID_AT_POSTAL_CODE MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ -#define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ -#define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ -#define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ -#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */ -#define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ -#define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ - -#define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ - -/* - * OIDs for standard certificate extensions - */ -#define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ -#define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ -#define MBEDTLS_OID_KEY_USAGE MBEDTLS_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ -#define MBEDTLS_OID_CERTIFICATE_POLICIES MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ -#define MBEDTLS_OID_POLICY_MAPPINGS MBEDTLS_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ -#define MBEDTLS_OID_SUBJECT_ALT_NAME MBEDTLS_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ -#define MBEDTLS_OID_ISSUER_ALT_NAME MBEDTLS_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ -#define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ -#define MBEDTLS_OID_BASIC_CONSTRAINTS MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ -#define MBEDTLS_OID_NAME_CONSTRAINTS MBEDTLS_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ -#define MBEDTLS_OID_POLICY_CONSTRAINTS MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ -#define MBEDTLS_OID_EXTENDED_KEY_USAGE MBEDTLS_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ -#define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ -#define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ -#define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ - -/* - * Netscape certificate extensions - */ -#define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" -#define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" -#define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" -#define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" -#define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" -#define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" -#define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" -#define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" -#define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" -#define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" -#define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" - -/* - * OIDs for CRL extensions - */ -#define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" -#define MBEDTLS_OID_CRL_NUMBER MBEDTLS_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ - -/* - * X.509 v3 Extended key usage OIDs - */ -#define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ - -#define MBEDTLS_OID_KP MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ -#define MBEDTLS_OID_SERVER_AUTH MBEDTLS_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ -#define MBEDTLS_OID_CLIENT_AUTH MBEDTLS_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ -#define MBEDTLS_OID_CODE_SIGNING MBEDTLS_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ -#define MBEDTLS_OID_EMAIL_PROTECTION MBEDTLS_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ -#define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ -#define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ - -/* - * PKCS definition OIDs - */ - -#define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ -#define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ -#define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ -#define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ -#define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ - -/* - * PKCS#1 OIDs - */ -#define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ -#define MBEDTLS_OID_PKCS1_MD2 MBEDTLS_OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */ -#define MBEDTLS_OID_PKCS1_MD4 MBEDTLS_OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */ -#define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ -#define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ -#define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ -#define MBEDTLS_OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ -#define MBEDTLS_OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ -#define MBEDTLS_OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ - -#define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" - -#define MBEDTLS_OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ - -/* RFC 4055 */ -#define MBEDTLS_OID_RSASSA_PSS MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ -#define MBEDTLS_OID_MGF1 MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ - -/* - * Digest algorithms - */ -#define MBEDTLS_OID_DIGEST_ALG_MD2 MBEDTLS_OID_RSA_COMPANY "\x02\x02" /**< id-mbedtls_md2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 } */ -#define MBEDTLS_OID_DIGEST_ALG_MD4 MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */ -#define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_GOV "\x03\x04\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ -#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_GOV "\x03\x04\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ - -#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_GOV "\x03\x04\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ - -#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_GOV "\x03\x04\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ - -#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ - -/* - * Encryption algorithms - */ -#define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ -#define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ - -/* - * PKCS#5 OIDs - */ -#define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ -#define MBEDTLS_OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ -#define MBEDTLS_OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ - -/* - * PKCS#5 PBES1 algorithms - */ -#define MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */ -#define MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5 "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */ -#define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ -#define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ -#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ -#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ - -/* - * PKCS#8 OIDs - */ -#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ - -/* - * PKCS#12 PBE OIDs - */ -#define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ - -#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 1} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 2} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ -#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ - -/* - * EC key algorithms from RFC 5480 - */ - -/* id-ecPublicKey OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ -#define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" - -/* id-ecDH OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) - * schemes(1) ecdh(12) } */ -#define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" - -/* - * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 - */ - -/* secp192r1 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ -#define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" - -/* secp224r1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ -#define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" - -/* secp256r1 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ -#define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" - -/* secp384r1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ -#define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" - -/* secp521r1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ -#define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" - -/* secp192k1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ -#define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" - -/* secp224k1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ -#define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" - -/* secp256k1 OBJECT IDENTIFIER ::= { - * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ -#define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" - -/* RFC 5639 4.1 - * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) - * identified-organization(3) teletrust(36) algorithm(3) signature- - * algorithm(3) ecSign(2) 8} - * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} - * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ -#define MBEDTLS_OID_EC_BRAINPOOL_V1 MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" - -/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ -#define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" - -/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ -#define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" - -/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ -#define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" - -/* - * SEC1 C.1 - * - * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } - * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} - */ -#define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" -#define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" - -/* - * ECDSA signature identifiers, from RFC 5480 - */ -#define MBEDTLS_OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ -#define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ - -/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ -#define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" - -/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) - * ecdsa-with-SHA2(3) 1 } */ -#define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" - -/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) - * ecdsa-with-SHA2(3) 2 } */ -#define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" - -/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) - * ecdsa-with-SHA2(3) 3 } */ -#define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" - -/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) - * ecdsa-with-SHA2(3) 4 } */ -#define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Base OID descriptor structure - */ -typedef struct { - const char *asn1; /*!< OID ASN.1 representation */ - size_t asn1_len; /*!< length of asn1 */ - const char *name; /*!< official name (e.g. from RFC) */ - const char *description; /*!< human friendly description */ -} mbedtls_oid_descriptor_t; - -/** - * \brief Translate an ASN.1 OID into its numeric representation - * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") - * - * \param buf buffer to put representation in - * \param size size of the buffer - * \param oid OID to translate - * - * \return Length of the string written (excluding final NULL) or - * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error - */ -int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_buf *oid ); - -#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) -/** - * \brief Translate an X.509 extension OID into local values - * - * \param oid OID to use - * \param ext_type place to store the extension type - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type ); -#endif - -/** - * \brief Translate an X.509 attribute type OID into the short name - * (e.g. the OID for an X520 Common Name into "CN") - * - * \param oid OID to use - * \param short_name place to store the string pointer - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_attr_short_name( const mbedtls_asn1_buf *oid, const char **short_name ); - -/** - * \brief Translate PublicKeyAlgorithm OID into pk_type - * - * \param oid OID to use - * \param pk_alg place to store public key algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_pk_alg( const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg ); - -/** - * \brief Translate pk_type into PublicKeyAlgorithm OID - * - * \param pk_alg Public key type to look for - * \param oid place to store ASN.1 OID string pointer - * \param olen length of the OID - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_type_t pk_alg, - const char **oid, size_t *olen ); - -#if defined(MBEDTLS_ECP_C) -/** - * \brief Translate NamedCurve OID into an EC group identifier - * - * \param oid OID to use - * \param grp_id place to store group id - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_ec_grp( const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id ); - -/** - * \brief Translate EC group identifier into NamedCurve OID - * - * \param grp_id EC group identifier - * \param oid place to store ASN.1 OID string pointer - * \param olen length of the OID - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_oid_by_ec_grp( mbedtls_ecp_group_id grp_id, - const char **oid, size_t *olen ); -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_MD_C) -/** - * \brief Translate SignatureAlgorithm OID into md_type and pk_type - * - * \param oid OID to use - * \param md_alg place to store message digest algorithm - * \param pk_alg place to store public key algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_sig_alg( const mbedtls_asn1_buf *oid, - mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg ); - -/** - * \brief Translate SignatureAlgorithm OID into description - * - * \param oid OID to use - * \param desc place to store string pointer - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_sig_alg_desc( const mbedtls_asn1_buf *oid, const char **desc ); - -/** - * \brief Translate md_type and pk_type into SignatureAlgorithm OID - * - * \param md_alg message digest algorithm - * \param pk_alg public key algorithm - * \param oid place to store ASN.1 OID string pointer - * \param olen length of the OID - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_oid_by_sig_alg( mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, - const char **oid, size_t *olen ); - -/** - * \brief Translate hash algorithm OID into md_type - * - * \param oid OID to use - * \param md_alg place to store message digest algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_md_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg ); -#endif /* MBEDTLS_MD_C */ - -/** - * \brief Translate Extended Key Usage OID into description - * - * \param oid OID to use - * \param desc place to store string pointer - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_extended_key_usage( const mbedtls_asn1_buf *oid, const char **desc ); - -/** - * \brief Translate md_type into hash algorithm OID - * - * \param md_alg message digest algorithm - * \param oid place to store ASN.1 OID string pointer - * \param olen length of the OID - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_oid_by_md( mbedtls_md_type_t md_alg, const char **oid, size_t *olen ); - -#if defined(MBEDTLS_CIPHER_C) -/** - * \brief Translate encryption algorithm OID into cipher_type - * - * \param oid OID to use - * \param cipher_alg place to store cipher algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_cipher_alg( const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg ); -#endif /* MBEDTLS_CIPHER_C */ - -#if defined(MBEDTLS_PKCS12_C) -/** - * \brief Translate PKCS#12 PBE algorithm OID into md_type and - * cipher_type - * - * \param oid OID to use - * \param md_alg place to store message digest algorithm - * \param cipher_alg place to store cipher algorithm - * - * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND - */ -int mbedtls_oid_get_pkcs12_pbe_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, - mbedtls_cipher_type_t *cipher_alg ); -#endif /* MBEDTLS_PKCS12_C */ - -#ifdef __cplusplus -} -#endif - -#endif /* oid.h */ diff --git a/components/mbedtls/include/mbedtls/padlock.h b/components/mbedtls/include/mbedtls/padlock.h deleted file mode 100644 index 2045a5ab64..0000000000 --- a/components/mbedtls/include/mbedtls/padlock.h +++ /dev/null @@ -1,107 +0,0 @@ -/** - * \file padlock.h - * - * \brief VIA PadLock ACE for HW encryption/decryption supported by some - * processors - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_PADLOCK_H -#define MBEDTLS_PADLOCK_H - -#include "aes.h" - -#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ - -#if defined(__has_feature) -#if __has_feature(address_sanitizer) -#define MBEDTLS_HAVE_ASAN -#endif -#endif - -/* Some versions of ASan result in errors about not enough registers */ -#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) && \ - !defined(MBEDTLS_HAVE_ASAN) - -#ifndef MBEDTLS_HAVE_X86 -#define MBEDTLS_HAVE_X86 -#endif - -#include - -#define MBEDTLS_PADLOCK_RNG 0x000C -#define MBEDTLS_PADLOCK_ACE 0x00C0 -#define MBEDTLS_PADLOCK_PHE 0x0C00 -#define MBEDTLS_PADLOCK_PMM 0x3000 - -#define MBEDTLS_PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) x & ~15)) - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief PadLock detection routine - * - * \param feature The feature to detect - * - * \return 1 if CPU has support for the feature, 0 otherwise - */ -int mbedtls_padlock_has_support( int feature ); - -/** - * \brief PadLock AES-ECB block en(de)cryption - * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param input 16-byte input block - * \param output 16-byte output block - * - * \return 0 if success, 1 if operation failed - */ -int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); - -/** - * \brief PadLock AES-CBC buffer en(de)cryption - * - * \param ctx AES context - * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if success, 1 if operation failed - */ -int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); - -#ifdef __cplusplus -} -#endif - -#endif /* HAVE_X86 */ - -#endif /* padlock.h */ diff --git a/components/mbedtls/include/mbedtls/pem.h b/components/mbedtls/include/mbedtls/pem.h deleted file mode 100644 index 54dc02d7cd..0000000000 --- a/components/mbedtls/include/mbedtls/pem.h +++ /dev/null @@ -1,129 +0,0 @@ -/** - * \file pem.h - * - * \brief Privacy Enhanced Mail (PEM) decoding - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_PEM_H -#define MBEDTLS_PEM_H - -#include - -/** - * \name PEM Error codes - * These error codes are returned in case of errors reading the - * PEM data. - * \{ - */ -#define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 /**< No PEM header or footer found. */ -#define MBEDTLS_ERR_PEM_INVALID_DATA -0x1100 /**< PEM string is not as expected. */ -#define MBEDTLS_ERR_PEM_ALLOC_FAILED -0x1180 /**< Failed to allocate memory. */ -#define MBEDTLS_ERR_PEM_INVALID_ENC_IV -0x1200 /**< RSA IV is not in hex-format. */ -#define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /**< Unsupported key encryption algorithm. */ -#define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED -0x1300 /**< Private key password can't be empty. */ -#define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH -0x1380 /**< Given private key password does not allow for correct decryption. */ -#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /**< Unavailable feature, e.g. hashing/encryption combination. */ -#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480 /**< Bad input parameters to function. */ -/* \} name */ - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(MBEDTLS_PEM_PARSE_C) -/** - * \brief PEM context structure - */ -typedef struct -{ - unsigned char *buf; /*!< buffer for decoded data */ - size_t buflen; /*!< length of the buffer */ - unsigned char *info; /*!< buffer for extra header information */ -} -mbedtls_pem_context; - -/** - * \brief PEM context setup - * - * \param ctx context to be initialized - */ -void mbedtls_pem_init( mbedtls_pem_context *ctx ); - -/** - * \brief Read a buffer for PEM information and store the resulting - * data into the specified context buffers. - * - * \param ctx context to use - * \param header header string to seek and expect - * \param footer footer string to seek and expect - * \param data source data to look in (must be nul-terminated) - * \param pwd password for decryption (can be NULL) - * \param pwdlen length of password - * \param use_len destination for total length used (set after header is - * correctly read, so unless you get - * MBEDTLS_ERR_PEM_BAD_INPUT_DATA or - * MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is - * the length to skip) - * - * \note Attempts to check password correctness by verifying if - * the decrypted text starts with an ASN.1 sequence of - * appropriate length - * - * \return 0 on success, or a specific PEM error code - */ -int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, - const unsigned char *data, - const unsigned char *pwd, - size_t pwdlen, size_t *use_len ); - -/** - * \brief PEM context memory freeing - * - * \param ctx context to be freed - */ -void mbedtls_pem_free( mbedtls_pem_context *ctx ); -#endif /* MBEDTLS_PEM_PARSE_C */ - -#if defined(MBEDTLS_PEM_WRITE_C) -/** - * \brief Write a buffer of PEM information from a DER encoded - * buffer. - * - * \param header header string to write - * \param footer footer string to write - * \param der_data DER data to write - * \param der_len length of the DER data - * \param buf buffer to write to - * \param buf_len length of output buffer - * \param olen total length written / required (if buf_len is not enough) - * - * \return 0 on success, or a specific PEM or BASE64 error code. On - * MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL olen is the required - * size. - */ -int mbedtls_pem_write_buffer( const char *header, const char *footer, - const unsigned char *der_data, size_t der_len, - unsigned char *buf, size_t buf_len, size_t *olen ); -#endif /* MBEDTLS_PEM_WRITE_C */ - -#ifdef __cplusplus -} -#endif - -#endif /* pem.h */ diff --git a/components/mbedtls/include/mbedtls/pk.h b/components/mbedtls/include/mbedtls/pk.h deleted file mode 100644 index f9f9b9bb09..0000000000 --- a/components/mbedtls/include/mbedtls/pk.h +++ /dev/null @@ -1,616 +0,0 @@ -/** - * \file pk.h - * - * \brief Public Key abstraction layer - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef MBEDTLS_PK_H -#define MBEDTLS_PK_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "md.h" - -#if defined(MBEDTLS_RSA_C) -#include "rsa.h" -#endif - -#if defined(MBEDTLS_ECP_C) -#include "ecp.h" -#endif - -#if defined(MBEDTLS_ECDSA_C) -#include "ecdsa.h" -#endif - -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -#define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 /**< Memory allocation failed. */ -#define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 /**< Type mismatch, eg attempt to encrypt with an ECDSA key */ -#define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 /**< Read/write of file failed. */ -#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 /**< Unsupported key version */ -#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 /**< Invalid key tag or value. */ -#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 /**< Key algorithm is unsupported (only RSA and EC are supported). */ -#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 /**< Private key password can't be empty. */ -#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 /**< Given private key password does not allow for correct decryption. */ -#define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 /**< The pubkey tag or value is invalid (only RSA and EC are supported). */ -#define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 /**< The algorithm tag or value is invalid. */ -#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */ -#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */ -#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The signature is valid but its length is less than expected. */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Public key types - */ -typedef enum { - MBEDTLS_PK_NONE=0, - MBEDTLS_PK_RSA, - MBEDTLS_PK_ECKEY, - MBEDTLS_PK_ECKEY_DH, - MBEDTLS_PK_ECDSA, - MBEDTLS_PK_RSA_ALT, - MBEDTLS_PK_RSASSA_PSS, -} mbedtls_pk_type_t; - -/** - * \brief Options for RSASSA-PSS signature verification. - * See \c mbedtls_rsa_rsassa_pss_verify_ext() - */ -typedef struct -{ - mbedtls_md_type_t mgf1_hash_id; - int expected_salt_len; - -} mbedtls_pk_rsassa_pss_options; - -/** - * \brief Types for interfacing with the debug module - */ -typedef enum -{ - MBEDTLS_PK_DEBUG_NONE = 0, - MBEDTLS_PK_DEBUG_MPI, - MBEDTLS_PK_DEBUG_ECP, -} mbedtls_pk_debug_type; - -/** - * \brief Item to send to the debug module - */ -typedef struct -{ - mbedtls_pk_debug_type type; - const char *name; - void *value; -} mbedtls_pk_debug_item; - -/** Maximum number of item send for debugging, plus 1 */ -#define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 - -/** - * \brief Public key information and operations - */ -typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; - -/** - * \brief Public key container - */ -typedef struct -{ - const mbedtls_pk_info_t * pk_info; /**< Public key informations */ - void * pk_ctx; /**< Underlying public key context */ -} mbedtls_pk_context; - -#if defined(MBEDTLS_RSA_C) -/** - * Quick access to an RSA context inside a PK context. - * - * \warning You must make sure the PK context actually holds an RSA context - * before using this function! - */ -static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk ) -{ - return( (mbedtls_rsa_context *) (pk).pk_ctx ); -} -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) -/** - * Quick access to an EC context inside a PK context. - * - * \warning You must make sure the PK context actually holds an EC context - * before using this function! - */ -static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk ) -{ - return( (mbedtls_ecp_keypair *) (pk).pk_ctx ); -} -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/** - * \brief Types for RSA-alt abstraction - */ -typedef int (*mbedtls_pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen, - const unsigned char *input, unsigned char *output, - size_t output_max_len ); -typedef int (*mbedtls_pk_rsa_alt_sign_func)( void *ctx, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, - const unsigned char *hash, unsigned char *sig ); -typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx ); -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - -/** - * \brief Return information associated with the given PK type - * - * \param pk_type PK type to search for. - * - * \return The PK info associated with the type or NULL if not found. - */ -const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ); - -/** - * \brief Initialize a mbedtls_pk_context (as NONE) - */ -void mbedtls_pk_init( mbedtls_pk_context *ctx ); - -/** - * \brief Free a mbedtls_pk_context - */ -void mbedtls_pk_free( mbedtls_pk_context *ctx ); - -/** - * \brief Initialize a PK context with the information given - * and allocates the type-specific PK subcontext. - * - * \param ctx Context to initialize. Must be empty (type NONE). - * \param info Information to use - * - * \return 0 on success, - * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, - * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. - * - * \note For contexts holding an RSA-alt key, use - * \c mbedtls_pk_setup_rsa_alt() instead. - */ -int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/** - * \brief Initialize an RSA-alt context - * - * \param ctx Context to initialize. Must be empty (type NONE). - * \param key RSA key pointer - * \param decrypt_func Decryption function - * \param sign_func Signing function - * \param key_len_func Function returning key length in bytes - * - * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the - * context wasn't already initialized as RSA_ALT. - * - * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. - */ -int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, - mbedtls_pk_rsa_alt_decrypt_func decrypt_func, - mbedtls_pk_rsa_alt_sign_func sign_func, - mbedtls_pk_rsa_alt_key_len_func key_len_func ); -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - -/** - * \brief Get the size in bits of the underlying key - * - * \param ctx Context to use - * - * \return Key size in bits, or 0 on error - */ -size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ); - -/** - * \brief Get the length in bytes of the underlying key - * \param ctx Context to use - * - * \return Key length in bytes, or 0 on error - */ -static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx ) -{ - return( ( mbedtls_pk_get_bitlen( ctx ) + 7 ) / 8 ); -} - -/** - * \brief Tell if a context can do the operation given by type - * - * \param ctx Context to test - * \param type Target type - * - * \return 0 if context can't do the operations, - * 1 otherwise. - */ -int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); - -/** - * \brief Verify signature (including padding if relevant). - * - * \param ctx PK context to use - * \param md_alg Hash algorithm used (see notes) - * \param hash Hash of the message to sign - * \param hash_len Hash length or 0 (see notes) - * \param sig Signature to verify - * \param sig_len Signature length - * - * \return 0 on success (signature is valid), - * MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if the signature is - * valid but its actual length is less than sig_len, - * or a specific error code. - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) - * to verify RSASSA_PSS signatures. - * - * \note If hash_len is 0, then the length associated with md_alg - * is used instead, or an error returned if it is invalid. - * - * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 - */ -int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ); - -/** - * \brief Verify signature, with options. - * (Includes verification of the padding depending on type.) - * - * \param type Signature type (inc. possible padding type) to verify - * \param options Pointer to type-specific options, or NULL - * \param ctx PK context to use - * \param md_alg Hash algorithm used (see notes) - * \param hash Hash of the message to sign - * \param hash_len Hash length or 0 (see notes) - * \param sig Signature to verify - * \param sig_len Signature length - * - * \return 0 on success (signature is valid), - * MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be - * used for this type of signatures, - * MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if the signature is - * valid but its actual length is less than sig_len, - * or a specific error code. - * - * \note If hash_len is 0, then the length associated with md_alg - * is used instead, or an error returned if it is invalid. - * - * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 - * - * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point - * to a mbedtls_pk_rsassa_pss_options structure, - * otherwise it must be NULL. - */ -int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, - mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ); - -/** - * \brief Make signature, including padding if relevant. - * - * \param ctx PK context to use - must hold a private key - * \param md_alg Hash algorithm used (see notes) - * \param hash Hash of the message to sign - * \param hash_len Hash length or 0 (see notes) - * \param sig Place to write the signature - * \param sig_len Number of bytes written - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 on success, or a specific error code. - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * There is no interface in the PK module to make RSASSA-PSS - * signatures yet. - * - * \note If hash_len is 0, then the length associated with md_alg - * is used instead, or an error returned if it is invalid. - * - * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. - * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. - */ -int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); - -/** - * \brief Decrypt message (including padding if relevant). - * - * \param ctx PK context to use - must hold a private key - * \param input Input to decrypt - * \param ilen Input size - * \param output Decrypted output - * \param olen Decrypted message length - * \param osize Size of the output buffer - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * - * \return 0 on success, or a specific error code. - */ -int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); - -/** - * \brief Encrypt message (including padding if relevant). - * - * \param ctx PK context to use - * \param input Message to encrypt - * \param ilen Message size - * \param output Encrypted output - * \param olen Encrypted output length - * \param osize Size of the output buffer - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \note For RSA keys, the default padding type is PKCS#1 v1.5. - * - * \return 0 on success, or a specific error code. - */ -int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); - -/** - * \brief Check if a public-private pair of keys matches. - * - * \param pub Context holding a public key. - * \param prv Context holding a private (and public) key. - * - * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA - */ -int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ); - -/** - * \brief Export debug information - * - * \param ctx Context to use - * \param items Place to write debug items - * - * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA - */ -int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ); - -/** - * \brief Access the type name - * - * \param ctx Context to use - * - * \return Type name on success, or "invalid PK" - */ -const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx ); - -/** - * \brief Get the key type - * - * \param ctx Context to use - * - * \return Type on success, or MBEDTLS_PK_NONE - */ -mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); - -#if defined(MBEDTLS_PK_PARSE_C) -/** \ingroup pk_module */ -/** - * \brief Parse a private key in PEM or DER format - * - * \param ctx key to be initialized - * \param key input buffer - * \param keylen size of the buffer - * (including the terminating null byte for PEM data) - * \param pwd password for decryption (optional) - * \param pwdlen size of the password - * - * \note On entry, ctx must be empty, either freshly initialised - * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a - * specific key type, check the result with mbedtls_pk_can_do(). - * - * \note The key is also checked for correctness. - * - * \return 0 if successful, or a specific PK or PEM error code - */ -int mbedtls_pk_parse_key( mbedtls_pk_context *ctx, - const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen ); - -/** \ingroup pk_module */ -/** - * \brief Parse a public key in PEM or DER format - * - * \param ctx key to be initialized - * \param key input buffer - * \param keylen size of the buffer - * (including the terminating null byte for PEM data) - * - * \note On entry, ctx must be empty, either freshly initialised - * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a - * specific key type, check the result with mbedtls_pk_can_do(). - * - * \note The key is also checked for correctness. - * - * \return 0 if successful, or a specific PK or PEM error code - */ -int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, - const unsigned char *key, size_t keylen ); - -#if defined(MBEDTLS_FS_IO) -/** \ingroup pk_module */ -/** - * \brief Load and parse a private key - * - * \param ctx key to be initialized - * \param path filename to read the private key from - * \param password password to decrypt the file (can be NULL) - * - * \note On entry, ctx must be empty, either freshly initialised - * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a - * specific key type, check the result with mbedtls_pk_can_do(). - * - * \note The key is also checked for correctness. - * - * \return 0 if successful, or a specific PK or PEM error code - */ -int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, - const char *path, const char *password ); - -/** \ingroup pk_module */ -/** - * \brief Load and parse a public key - * - * \param ctx key to be initialized - * \param path filename to read the public key from - * - * \note On entry, ctx must be empty, either freshly initialised - * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If - * you need a specific key type, check the result with - * mbedtls_pk_can_do(). - * - * \note The key is also checked for correctness. - * - * \return 0 if successful, or a specific PK or PEM error code - */ -int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ); -#endif /* MBEDTLS_FS_IO */ -#endif /* MBEDTLS_PK_PARSE_C */ - -#if defined(MBEDTLS_PK_WRITE_C) -/** - * \brief Write a private key to a PKCS#1 or SEC1 DER structure - * Note: data is written at the end of the buffer! Use the - * return value to determine where you should start - * using the buffer - * - * \param ctx private to write away - * \param buf buffer to write to - * \param size size of the buffer - * - * \return length of data written if successful, or a specific - * error code - */ -int mbedtls_pk_write_key_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); - -/** - * \brief Write a public key to a SubjectPublicKeyInfo DER structure - * Note: data is written at the end of the buffer! Use the - * return value to determine where you should start - * using the buffer - * - * \param ctx public key to write away - * \param buf buffer to write to - * \param size size of the buffer - * - * \return length of data written if successful, or a specific - * error code - */ -int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); - -#if defined(MBEDTLS_PEM_WRITE_C) -/** - * \brief Write a public key to a PEM string - * - * \param ctx public key to write away - * \param buf buffer to write to - * \param size size of the buffer - * - * \return 0 if successful, or a specific error code - */ -int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); - -/** - * \brief Write a private key to a PKCS#1 or SEC1 PEM string - * - * \param ctx private to write away - * \param buf buffer to write to - * \param size size of the buffer - * - * \return 0 if successful, or a specific error code - */ -int mbedtls_pk_write_key_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); -#endif /* MBEDTLS_PEM_WRITE_C */ -#endif /* MBEDTLS_PK_WRITE_C */ - -/* - * WARNING: Low-level functions. You probably do not want to use these unless - * you are certain you do ;) - */ - -#if defined(MBEDTLS_PK_PARSE_C) -/** - * \brief Parse a SubjectPublicKeyInfo DER structure - * - * \param p the position in the ASN.1 data - * \param end end of the buffer - * \param pk the key to fill - * - * \return 0 if successful, or a specific PK error code - */ -int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, - mbedtls_pk_context *pk ); -#endif /* MBEDTLS_PK_PARSE_C */ - -#if defined(MBEDTLS_PK_WRITE_C) -/** - * \brief Write a subjectPublicKey to ASN.1 data - * Note: function works backwards in data buffer - * - * \param p reference to current position pointer - * \param start start of the buffer (for bounds-checking) - * \param key public key to write away - * - * \return the length written or a negative error code - */ -int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, - const mbedtls_pk_context *key ); -#endif /* MBEDTLS_PK_WRITE_C */ - -/* - * Internal module functions. You probably do not want to use these unless you - * know you do. - */ -#if defined(MBEDTLS_FS_IO) -int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_PK_H */ diff --git a/components/mbedtls/include/mbedtls/pk_internal.h b/components/mbedtls/include/mbedtls/pk_internal.h deleted file mode 100644 index 01d0f214bc..0000000000 --- a/components/mbedtls/include/mbedtls/pk_internal.h +++ /dev/null @@ -1,114 +0,0 @@ -/** - * \file pk.h - * - * \brief Public Key abstraction layer: wrapper functions - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#ifndef MBEDTLS_PK_WRAP_H -#define MBEDTLS_PK_WRAP_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "pk.h" - -struct mbedtls_pk_info_t -{ - /** Public key type */ - mbedtls_pk_type_t type; - - /** Type name */ - const char *name; - - /** Get key size in bits */ - size_t (*get_bitlen)( const void * ); - - /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ - int (*can_do)( mbedtls_pk_type_t type ); - - /** Verify signature */ - int (*verify_func)( void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ); - - /** Make signature */ - int (*sign_func)( void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - - /** Decrypt message */ - int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - - /** Encrypt message */ - int (*encrypt_func)( void *ctx, const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - - /** Check public-private key pair */ - int (*check_pair_func)( const void *pub, const void *prv ); - - /** Allocate a new context */ - void * (*ctx_alloc_func)( void ); - - /** Free the given context */ - void (*ctx_free_func)( void *ctx ); - - /** Interface with the debug module */ - void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); - -}; -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/* Container for RSA-alt */ -typedef struct -{ - void *key; - mbedtls_pk_rsa_alt_decrypt_func decrypt_func; - mbedtls_pk_rsa_alt_sign_func sign_func; - mbedtls_pk_rsa_alt_key_len_func key_len_func; -} mbedtls_rsa_alt_context; -#endif - -#if defined(MBEDTLS_RSA_C) -extern const mbedtls_pk_info_t mbedtls_rsa_info; -#endif - -#if defined(MBEDTLS_ECP_C) -extern const mbedtls_pk_info_t mbedtls_eckey_info; -extern const mbedtls_pk_info_t mbedtls_eckeydh_info; -#endif - -#if defined(MBEDTLS_ECDSA_C) -extern const mbedtls_pk_info_t mbedtls_ecdsa_info; -#endif - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; -#endif - -#endif /* MBEDTLS_PK_WRAP_H */ diff --git a/components/mbedtls/include/mbedtls/pkcs11.h b/components/mbedtls/include/mbedtls/pkcs11.h deleted file mode 100644 index 2e88928137..0000000000 --- a/components/mbedtls/include/mbedtls/pkcs11.h +++ /dev/null @@ -1,173 +0,0 @@ -/** - * \file pkcs11.h - * - * \brief Wrapper for PKCS#11 library libpkcs11-helper - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_PKCS11_H -#define MBEDTLS_PKCS11_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PKCS11_C) - -#include "x509_crt.h" - -#include - -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Context for PKCS #11 private keys. - */ -typedef struct { - pkcs11h_certificate_t pkcs11h_cert; - int len; -} mbedtls_pkcs11_context; - -/** - * Initialize a mbedtls_pkcs11_context. - * (Just making memory references valid.) - */ -void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ); - -/** - * Fill in a mbed TLS certificate, based on the given PKCS11 helper certificate. - * - * \param cert X.509 certificate to fill - * \param pkcs11h_cert PKCS #11 helper certificate - * - * \return 0 on success. - */ -int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11h_cert ); - -/** - * Set up a mbedtls_pkcs11_context storing the given certificate. Note that the - * mbedtls_pkcs11_context will take over control of the certificate, freeing it when - * done. - * - * \param priv_key Private key structure to fill. - * \param pkcs11_cert PKCS #11 helper certificate - * - * \return 0 on success - */ -int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key, - pkcs11h_certificate_t pkcs11_cert ); - -/** - * Free the contents of the given private key context. Note that the structure - * itself is not freed. - * - * \param priv_key Private key structure to cleanup - */ -void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key ); - -/** - * \brief Do an RSA private key decrypt, then remove the message - * padding - * - * \param ctx PKCS #11 context - * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param olen will contain the plaintext length - * \param output_max_len maximum length of the output buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise - * an error is thrown. - */ -int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ); - -/** - * \brief Do a private RSA to sign a message digest - * - * \param ctx PKCS #11 context - * \param mode must be MBEDTLS_RSA_PRIVATE, for compatibility with rsa.c's signature - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext - * - * \return 0 if the signing operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * SSL/TLS wrappers for PKCS#11 functions - */ -static inline int mbedtls_ssl_pkcs11_decrypt( void *ctx, int mode, size_t *olen, - const unsigned char *input, unsigned char *output, - size_t output_max_len ) -{ - return mbedtls_pkcs11_decrypt( (mbedtls_pkcs11_context *) ctx, mode, olen, input, output, - output_max_len ); -} - -static inline int mbedtls_ssl_pkcs11_sign( void *ctx, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, - const unsigned char *hash, unsigned char *sig ) -{ - ((void) f_rng); - ((void) p_rng); - return mbedtls_pkcs11_sign( (mbedtls_pkcs11_context *) ctx, mode, md_alg, - hashlen, hash, sig ); -} - -static inline size_t mbedtls_ssl_pkcs11_key_len( void *ctx ) -{ - return ( (mbedtls_pkcs11_context *) ctx )->len; -} - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_PKCS11_C */ - -#endif /* MBEDTLS_PKCS11_H */ diff --git a/components/mbedtls/include/mbedtls/pkcs12.h b/components/mbedtls/include/mbedtls/pkcs12.h deleted file mode 100644 index 9b2d904591..0000000000 --- a/components/mbedtls/include/mbedtls/pkcs12.h +++ /dev/null @@ -1,119 +0,0 @@ -/** - * \file pkcs12.h - * - * \brief PKCS#12 Personal Information Exchange Syntax - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_PKCS12_H -#define MBEDTLS_PKCS12_H - -#include "md.h" -#include "cipher.h" -#include "asn1.h" - -#include - -#define MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA -0x1F80 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE -0x1F00 /**< Feature not available, e.g. unsupported encryption scheme. */ -#define MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT -0x1E80 /**< PBE ASN.1 data not as expected. */ -#define MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH -0x1E00 /**< Given private key password does not allow for correct decryption. */ - -#define MBEDTLS_PKCS12_DERIVE_KEY 1 /**< encryption/decryption key */ -#define MBEDTLS_PKCS12_DERIVE_IV 2 /**< initialization vector */ -#define MBEDTLS_PKCS12_DERIVE_MAC_KEY 3 /**< integrity / MAC key */ - -#define MBEDTLS_PKCS12_PBE_DECRYPT 0 -#define MBEDTLS_PKCS12_PBE_ENCRYPT 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief PKCS12 Password Based function (encryption / decryption) - * for pbeWithSHAAnd128BitRC4 - * - * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure - * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT - * \param pwd the password used (may be NULL if no password is used) - * \param pwdlen length of the password (may be 0) - * \param input the input data - * \param len data length - * \param output the output buffer - * - * \return 0 if successful, or a MBEDTLS_ERR_XXX code - */ -int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *input, size_t len, - unsigned char *output ); - -/** - * \brief PKCS12 Password Based function (encryption / decryption) - * for cipher-based and mbedtls_md-based PBE's - * - * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure - * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT - * \param cipher_type the cipher used - * \param md_type the mbedtls_md used - * \param pwd the password used (may be NULL if no password is used) - * \param pwdlen length of the password (may be 0) - * \param input the input data - * \param len data length - * \param output the output buffer - * - * \return 0 if successful, or a MBEDTLS_ERR_XXX code - */ -int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, - mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *input, size_t len, - unsigned char *output ); - -/** - * \brief The PKCS#12 derivation function uses a password and a salt - * to produce pseudo-random bits for a particular "purpose". - * - * Depending on the given id, this function can produce an - * encryption/decryption key, an nitialization vector or an - * integrity key. - * - * \param data buffer to store the derived data in - * \param datalen length to fill - * \param pwd password to use (may be NULL if no password is used) - * \param pwdlen length of the password (may be 0) - * \param salt salt buffer to use - * \param saltlen length of the salt - * \param mbedtls_md mbedtls_md type to use during the derivation - * \param id id that describes the purpose (can be MBEDTLS_PKCS12_DERIVE_KEY, - * MBEDTLS_PKCS12_DERIVE_IV or MBEDTLS_PKCS12_DERIVE_MAC_KEY) - * \param iterations number of iterations - * - * \return 0 if successful, or a MD, BIGNUM type error. - */ -int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *salt, size_t saltlen, - mbedtls_md_type_t mbedtls_md, int id, int iterations ); - -#ifdef __cplusplus -} -#endif - -#endif /* pkcs12.h */ diff --git a/components/mbedtls/include/mbedtls/pkcs5.h b/components/mbedtls/include/mbedtls/pkcs5.h deleted file mode 100644 index ec5cb9e744..0000000000 --- a/components/mbedtls/include/mbedtls/pkcs5.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * \file pkcs5.h - * - * \brief PKCS#5 functions - * - * \author Mathias Olsson - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_PKCS5_H -#define MBEDTLS_PKCS5_H - -#include "asn1.h" -#include "md.h" - -#include -#include - -#define MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA -0x2f80 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_PKCS5_INVALID_FORMAT -0x2f00 /**< Unexpected ASN.1 data. */ -#define MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE -0x2e80 /**< Requested encryption or digest alg not available. */ -#define MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH -0x2e00 /**< Given private key password does not allow for correct decryption. */ - -#define MBEDTLS_PKCS5_DECRYPT 0 -#define MBEDTLS_PKCS5_ENCRYPT 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief PKCS#5 PBES2 function - * - * \param pbe_params the ASN.1 algorithm parameters - * \param mode either MBEDTLS_PKCS5_DECRYPT or MBEDTLS_PKCS5_ENCRYPT - * \param pwd password to use when generating key - * \param pwdlen length of password - * \param data data to process - * \param datalen length of data - * \param output output buffer - * - * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. - */ -int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *data, size_t datalen, - unsigned char *output ); - -/** - * \brief PKCS#5 PBKDF2 using HMAC - * - * \param ctx Generic HMAC context - * \param password Password to use when generating key - * \param plen Length of password - * \param salt Salt to use when generating key - * \param slen Length of salt - * \param iteration_count Iteration count - * \param key_length Length of generated key in bytes - * \param output Generated key. Must be at least as big as key_length - * - * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. - */ -int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, - size_t plen, const unsigned char *salt, size_t slen, - unsigned int iteration_count, - uint32_t key_length, unsigned char *output ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_pkcs5_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* pkcs5.h */ diff --git a/components/mbedtls/include/mbedtls/platform.h b/components/mbedtls/include/mbedtls/platform.h deleted file mode 100644 index 35010f8852..0000000000 --- a/components/mbedtls/include/mbedtls/platform.h +++ /dev/null @@ -1,343 +0,0 @@ -/** - * \file platform.h - * - * \brief mbed TLS Platform abstraction layer - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_PLATFORM_H -#define MBEDTLS_PLATFORM_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) -#include -#include -#include -#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) -#if defined(_WIN32) -#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< Default snprintf to use */ -#else -#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use */ -#endif -#endif -#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) -#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) -#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) -#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_FREE) -#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_EXIT) -#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_TIME) -#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) -#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< Default exit value to use */ -#endif -#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) -#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< Default exit value to use */ -#endif -#if defined(MBEDTLS_FS_IO) -#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) -#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read -#endif -#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) -#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write -#endif -#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE) -#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" -#endif -#endif /* MBEDTLS_FS_IO */ -#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ -#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) -#include MBEDTLS_PLATFORM_STD_MEM_HDR -#endif -#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ - - -/* \} name SECTION: Module settings */ - -/* - * The function pointers for calloc and free - */ -#if defined(MBEDTLS_PLATFORM_MEMORY) -#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ - defined(MBEDTLS_PLATFORM_CALLOC_MACRO) -#define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO -#define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO -#else -/* For size_t */ -#include -extern void * (*mbedtls_calloc)( size_t n, size_t size ); -extern void (*mbedtls_free)( void *ptr ); - -/** - * \brief Set your own memory implementation function pointers - * - * \param calloc_func the calloc function implementation - * \param free_func the free function implementation - * - * \return 0 if successful - */ -int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), - void (*free_func)( void * ) ); -#endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */ -#else /* !MBEDTLS_PLATFORM_MEMORY */ -#define mbedtls_free free -#define mbedtls_calloc calloc -#endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */ - -/* - * The function pointers for fprintf - */ -#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) -/* We need FILE * */ -#include -extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... ); - -/** - * \brief Set your own fprintf function pointer - * - * \param fprintf_func the fprintf function implementation - * - * \return 0 - */ -int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *, - ... ) ); -#else -#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) -#define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO -#else -#define mbedtls_fprintf fprintf -#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */ -#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ - -/* - * The function pointers for printf - */ -#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) -extern int (*mbedtls_printf)( const char *format, ... ); - -/** - * \brief Set your own printf function pointer - * - * \param printf_func the printf function implementation - * - * \return 0 - */ -int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ); -#else /* !MBEDTLS_PLATFORM_PRINTF_ALT */ -#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) -#define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO -#else -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */ -#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ - -/* - * The function pointers for snprintf - * - * The snprintf implementation should conform to C99: - * - it *must* always correctly zero-terminate the buffer - * (except when n == 0, then it must leave the buffer untouched) - * - however it is acceptable to return -1 instead of the required length when - * the destination buffer is too short. - */ -#if defined(_WIN32) -/* For Windows (inc. MSYS2), we provide our own fixed implementation */ -int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ); -#endif - -#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) -extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... ); - -/** - * \brief Set your own snprintf function pointer - * - * \param snprintf_func the snprintf function implementation - * - * \return 0 - */ -int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, - const char * format, ... ) ); -#else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ -#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) -#define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO -#else -#define mbedtls_snprintf snprintf -#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ -#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ - -/* - * The function pointers for exit - */ -#if defined(MBEDTLS_PLATFORM_EXIT_ALT) -extern void (*mbedtls_exit)( int status ); - -/** - * \brief Set your own exit function pointer - * - * \param exit_func the exit function implementation - * - * \return 0 - */ -int mbedtls_platform_set_exit( void (*exit_func)( int status ) ); -#else -#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) -#define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO -#else -#define mbedtls_exit exit -#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */ -#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ - -/* - * The default exit values - */ -#if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) -#define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS -#else -#define MBEDTLS_EXIT_SUCCESS 0 -#endif -#if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) -#define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE -#else -#define MBEDTLS_EXIT_FAILURE 1 -#endif - -/* - * The function pointers for reading from and writing a seed file to - * Non-Volatile storage (NV) in a platform-independent way - * - * Only enabled when the NV seed entropy source is enabled - */ -#if defined(MBEDTLS_ENTROPY_NV_SEED) -#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) -/* Internal standard platform definitions */ -int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ); -int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ); -#endif - -#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) -extern int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ); -extern int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ); - -/** - * \brief Set your own seed file writing/reading functions - * - * \param nv_seed_read_func the seed reading function implementation - * \param nv_seed_write_func the seed writing function implementation - * - * \return 0 - */ -int mbedtls_platform_set_nv_seed( - int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), - int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) - ); -#else -#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ - defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) -#define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO -#define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO -#else -#define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read -#define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write -#endif -#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ -#endif /* MBEDTLS_ENTROPY_NV_SEED */ - -#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) - -/** - * \brief Platform context structure - * - * \note This structure may be used to assist platform-specific - * setup/teardown operations. - */ -typedef struct { - char dummy; /**< Placeholder member as empty structs are not portable */ -} -mbedtls_platform_context; - -#else -#include "platform_alt.h" -#endif /* !MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ - -/** - * \brief Perform any platform initialisation operations - * - * \param ctx mbed TLS context - * - * \return 0 if successful - * - * \note This function is intended to allow platform specific initialisation, - * and should be called before any other library functions. Its - * implementation is platform specific, and by default, unless platform - * specific code is provided, it does nothing. - * - * Its use and whether its necessary to be called is dependent on the - * platform. - */ -int mbedtls_platform_setup( mbedtls_platform_context *ctx ); -/** - * \brief Perform any platform teardown operations - * - * \param ctx mbed TLS context - * - * \note This function should be called after every other mbed TLS module has - * been correctly freed using the appropriate free function. - * Its implementation is platform specific, and by default, unless - * platform specific code is provided, it does nothing. - * - * Its use and whether its necessary to be called is dependent on the - * platform. - */ -void mbedtls_platform_teardown( mbedtls_platform_context *ctx ); - -#ifdef __cplusplus -} -#endif - -#endif /* platform.h */ diff --git a/components/mbedtls/include/mbedtls/platform_time.h b/components/mbedtls/include/mbedtls/platform_time.h deleted file mode 100644 index abb3431420..0000000000 --- a/components/mbedtls/include/mbedtls/platform_time.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * \file platform_time.h - * - * \brief mbed TLS Platform time abstraction - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_PLATFORM_TIME_H -#define MBEDTLS_PLATFORM_TIME_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -/* - * The time_t datatype - */ -#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) -typedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t; -#else -/* For time_t */ -#include -typedef time_t mbedtls_time_t; -#endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */ - -/* - * The function pointers for time - */ -#if defined(MBEDTLS_PLATFORM_TIME_ALT) -extern mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* time ); - -/** - * \brief Set your own time function pointer - * - * \param time_func the time function implementation - * - * \return 0 - */ -int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* time ) ); -#else -#if defined(MBEDTLS_PLATFORM_TIME_MACRO) -#define mbedtls_time MBEDTLS_PLATFORM_TIME_MACRO -#else -#define mbedtls_time time -#endif /* MBEDTLS_PLATFORM_TIME_MACRO */ -#endif /* MBEDTLS_PLATFORM_TIME_ALT */ - -#ifdef __cplusplus -} -#endif - -#endif /* platform_time.h */ diff --git a/components/mbedtls/include/mbedtls/ripemd160.h b/components/mbedtls/include/mbedtls/ripemd160.h deleted file mode 100644 index 7083fc8599..0000000000 --- a/components/mbedtls/include/mbedtls/ripemd160.h +++ /dev/null @@ -1,138 +0,0 @@ -/** - * \file ripemd160.h - * - * \brief RIPE MD-160 message digest - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_RIPEMD160_H -#define MBEDTLS_RIPEMD160_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#if !defined(MBEDTLS_RIPEMD160_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief RIPEMD-160 context structure - */ -typedef struct -{ - uint32_t total[2]; /*!< number of bytes processed */ - uint32_t state[5]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ -} -mbedtls_ripemd160_context; - -/** - * \brief Initialize RIPEMD-160 context - * - * \param ctx RIPEMD-160 context to be initialized - */ -void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ); - -/** - * \brief Clear RIPEMD-160 context - * - * \param ctx RIPEMD-160 context to be cleared - */ -void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ); - -/** - * \brief Clone (the state of) an RIPEMD-160 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, - const mbedtls_ripemd160_context *src ); - -/** - * \brief RIPEMD-160 context setup - * - * \param ctx context to be initialized - */ -void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ); - -/** - * \brief RIPEMD-160 process buffer - * - * \param ctx RIPEMD-160 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, - const unsigned char *input, size_t ilen ); - -/** - * \brief RIPEMD-160 final digest - * - * \param ctx RIPEMD-160 context - * \param output RIPEMD-160 checksum result - */ -void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, unsigned char output[20] ); - -/* Internal use */ -void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, const unsigned char data[64] ); - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_RIPEMD160_ALT */ -#include "ripemd160.h" -#endif /* MBEDTLS_RIPEMD160_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Output = RIPEMD-160( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output RIPEMD-160 checksum result - */ -void mbedtls_ripemd160( const unsigned char *input, size_t ilen, - unsigned char output[20] ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_ripemd160_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_ripemd160.h */ diff --git a/components/mbedtls/include/mbedtls/rsa.h b/components/mbedtls/include/mbedtls/rsa.h deleted file mode 100644 index 7d7469d509..0000000000 --- a/components/mbedtls/include/mbedtls/rsa.h +++ /dev/null @@ -1,670 +0,0 @@ -/** - * \file rsa.h - * - * \brief The RSA public-key cryptosystem - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_RSA_H -#define MBEDTLS_RSA_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "bignum.h" -#include "md.h" - -#if defined(MBEDTLS_THREADING_C) -#include "threading.h" -#endif - -/* - * RSA Error codes - */ -#define MBEDTLS_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */ -#define MBEDTLS_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */ -#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the library's validity check. */ -#define MBEDTLS_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ -#define MBEDTLS_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */ -#define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ -#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ -#define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ - -/* - * RSA constants - */ -#define MBEDTLS_RSA_PUBLIC 0 -#define MBEDTLS_RSA_PRIVATE 1 - -#define MBEDTLS_RSA_PKCS_V15 0 -#define MBEDTLS_RSA_PKCS_V21 1 - -#define MBEDTLS_RSA_SIGN 1 -#define MBEDTLS_RSA_CRYPT 2 - -#define MBEDTLS_RSA_SALT_LEN_ANY -1 - -/* - * The above constants may be used even if the RSA module is compile out, - * eg for alternative (PKCS#11) RSA implemenations in the PK layers. - */ -#if defined(MBEDTLS_RSA_C) - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief RSA context structure - */ -typedef struct -{ - int ver; /*!< always 0 */ - size_t len; /*!< size(N) in chars */ - - mbedtls_mpi N; /*!< public modulus */ - mbedtls_mpi E; /*!< public exponent */ - - mbedtls_mpi D; /*!< private exponent */ - mbedtls_mpi P; /*!< 1st prime factor */ - mbedtls_mpi Q; /*!< 2nd prime factor */ - mbedtls_mpi DP; /*!< D % (P - 1) */ - mbedtls_mpi DQ; /*!< D % (Q - 1) */ - mbedtls_mpi QP; /*!< 1 / (Q % P) */ - - mbedtls_mpi RN; /*!< cached R^2 mod N */ - mbedtls_mpi RP; /*!< cached R^2 mod P */ - mbedtls_mpi RQ; /*!< cached R^2 mod Q */ - - mbedtls_mpi Vi; /*!< cached blinding value */ - mbedtls_mpi Vf; /*!< cached un-blinding value */ - - int padding; /*!< MBEDTLS_RSA_PKCS_V15 for 1.5 padding and - MBEDTLS_RSA_PKCS_v21 for OAEP/PSS */ - int hash_id; /*!< Hash identifier of mbedtls_md_type_t as - specified in the mbedtls_md.h header file - for the EME-OAEP and EMSA-PSS - encoding */ -#if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex */ -#endif -} -mbedtls_rsa_context; - -/** - * \brief Initialize an RSA context - * - * Note: Set padding to MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP - * encryption scheme and the RSASSA-PSS signature scheme. - * - * \param ctx RSA context to be initialized - * \param padding MBEDTLS_RSA_PKCS_V15 or MBEDTLS_RSA_PKCS_V21 - * \param hash_id MBEDTLS_RSA_PKCS_V21 hash identifier - * - * \note The hash_id parameter is actually ignored - * when using MBEDTLS_RSA_PKCS_V15 padding. - * - * \note Choice of padding mode is strictly enforced for private key - * operations, since there might be security concerns in - * mixing padding modes. For public key operations it's merely - * a default value, which can be overriden by calling specific - * rsa_rsaes_xxx or rsa_rsassa_xxx functions. - * - * \note The chosen hash is always used for OEAP encryption. - * For PSS signatures, it's always used for making signatures, - * but can be overriden (and always is, if set to - * MBEDTLS_MD_NONE) for verifying them. - */ -void mbedtls_rsa_init( mbedtls_rsa_context *ctx, - int padding, - int hash_id); - -/** - * \brief Set padding for an already initialized RSA context - * See \c mbedtls_rsa_init() for details. - * - * \param ctx RSA context to be set - * \param padding MBEDTLS_RSA_PKCS_V15 or MBEDTLS_RSA_PKCS_V21 - * \param hash_id MBEDTLS_RSA_PKCS_V21 hash identifier - */ -void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id); - -/** - * \brief Generate an RSA keypair - * - * \param ctx RSA context that will hold the key - * \param f_rng RNG function - * \param p_rng RNG parameter - * \param nbits size of the public key in bits - * \param exponent public exponent (e.g., 65537) - * - * \note mbedtls_rsa_init() must be called beforehand to setup - * the RSA context. - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - */ -int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - unsigned int nbits, int exponent ); - -/** - * \brief Check a public RSA key - * - * \param ctx RSA context to be checked - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - */ -int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); - -/** - * \brief Check a private RSA key - * - * \param ctx RSA context to be checked - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - */ -int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); - -/** - * \brief Check a public-private RSA key pair. - * Check each of the contexts, and make sure they match. - * - * \param pub RSA context holding the public key - * \param prv RSA context holding the private key - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - */ -int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv ); - -/** - * \brief Do an RSA public key operation - * - * \param ctx RSA context - * \param input input buffer - * \param output output buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note This function does NOT take care of message - * padding. Also, be sure to set input[0] = 0 or ensure that - * input is smaller than N. - * - * \note The input and output buffers must be large - * enough (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_rsa_public( mbedtls_rsa_context *ctx, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Do an RSA private key operation - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for blinding) - * \param p_rng RNG parameter - * \param input input buffer - * \param output output buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The input and output buffers must be large - * enough (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_rsa_private( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Generic wrapper to perform a PKCS#1 encryption using the - * mode from the context. Add the message padding, then do an - * RSA operation. - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding - * and MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param ilen contains the plaintext length - * \param input buffer holding the data to be encrypted - * \param output buffer that will hold the ciphertext - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t ilen, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Perform a PKCS#1 v1.5 encryption (RSAES-PKCS1-v1_5-ENCRYPT) - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for padding and MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param ilen contains the plaintext length - * \param input buffer holding the data to be encrypted - * \param output buffer that will hold the ciphertext - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t ilen, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Perform a PKCS#1 v2.1 OAEP encryption (RSAES-OAEP-ENCRYPT) - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding - * and MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param label buffer holding the custom label to use - * \param label_len contains the label length - * \param ilen contains the plaintext length - * \param input buffer holding the data to be encrypted - * \param output buffer that will hold the ciphertext - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - const unsigned char *label, size_t label_len, - size_t ilen, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Generic wrapper to perform a PKCS#1 decryption using the - * mode from the context. Do an RSA operation, then remove - * the message padding - * - * \param ctx RSA context - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param olen will contain the plaintext length - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param output_max_len maximum length of the output buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The output buffer length \c output_max_len should be - * as large as the size ctx->len of ctx->N (eg. 128 bytes - * if RSA-1024 is used) to be able to hold an arbitrary - * decrypted message. If it is not large enough to hold - * the decryption of the particular ciphertext provided, - * the function will return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. - * - * \note The input buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ); - -/** - * \brief Perform a PKCS#1 v1.5 decryption (RSAES-PKCS1-v1_5-DECRYPT) - * - * \param ctx RSA context - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param olen will contain the plaintext length - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param output_max_len maximum length of the output buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The output buffer length \c output_max_len should be - * as large as the size ctx->len of ctx->N (eg. 128 bytes - * if RSA-1024 is used) to be able to hold an arbitrary - * decrypted message. If it is not large enough to hold - * the decryption of the particular ciphertext provided, - * the function will return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. - * - * \note The input buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ); - -/** - * \brief Perform a PKCS#1 v2.1 OAEP decryption (RSAES-OAEP-DECRYPT) - * - * \param ctx RSA context - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param label buffer holding the custom label to use - * \param label_len contains the label length - * \param olen will contain the plaintext length - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param output_max_len maximum length of the output buffer - * - * \return 0 if successful, or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The output buffer length \c output_max_len should be - * as large as the size ctx->len of ctx->N (eg. 128 bytes - * if RSA-1024 is used) to be able to hold an arbitrary - * decrypted message. If it is not large enough to hold - * the decryption of the particular ciphertext provided, - * the function will return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. - * - * \note The input buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - const unsigned char *label, size_t label_len, - size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ); - -/** - * \brief Generic wrapper to perform a PKCS#1 signature using the - * mode from the context. Do a private RSA operation to sign - * a message digest - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding and for - * MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext - * - * \return 0 if the signing operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - * - * \note In case of PKCS#1 v2.1 encoding, see comments on - * \note \c mbedtls_rsa_rsassa_pss_sign() for details on md_alg and hash_id. - */ -int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * \brief Perform a PKCS#1 v1.5 signature (RSASSA-PKCS1-v1_5-SIGN) - * - * \param ctx RSA context - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext - * - * \return 0 if the signing operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * \brief Perform a PKCS#1 v2.1 PSS signature (RSASSA-PSS-SIGN) - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding and for - * MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext - * - * \return 0 if the signing operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - * - * \note The hash_id in the RSA context is the one used for the - * encoding. md_alg in the function call is the type of hash - * that is encoded. According to RFC 3447 it is advised to - * keep both hashes the same. - */ -int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * \brief Generic wrapper to perform a PKCS#1 verification using the - * mode from the context. Do a public RSA operation and check - * the message digest - * - * \param ctx points to an RSA public key - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer holding the ciphertext - * - * \return 0 if the verify operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - * - * \note In case of PKCS#1 v2.1 encoding, see comments on - * \c mbedtls_rsa_rsassa_pss_verify() about md_alg and hash_id. - */ -int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - const unsigned char *sig ); - -/** - * \brief Perform a PKCS#1 v1.5 verification (RSASSA-PKCS1-v1_5-VERIFY) - * - * \param ctx points to an RSA public key - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer holding the ciphertext - * - * \return 0 if the verify operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - const unsigned char *sig ); - -/** - * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY) - * (This is the "simple" version.) - * - * \param ctx points to an RSA public key - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param sig buffer holding the ciphertext - * - * \return 0 if the verify operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - * - * \note The hash_id in the RSA context is the one used for the - * verification. md_alg in the function call is the type of - * hash that is verified. According to RFC 3447 it is advised to - * keep both hashes the same. If hash_id in the RSA context is - * unset, the md_alg from the function call is used. - */ -int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - const unsigned char *sig ); - -/** - * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY) - * (This is the version with "full" options.) - * - * \param ctx points to an RSA public key - * \param f_rng RNG function (Only needed for MBEDTLS_RSA_PRIVATE) - * \param p_rng RNG parameter - * \param mode MBEDTLS_RSA_PUBLIC or MBEDTLS_RSA_PRIVATE - * \param md_alg a MBEDTLS_MD_XXX (use MBEDTLS_MD_NONE for signing raw data) - * \param hashlen message digest length (for MBEDTLS_MD_NONE only) - * \param hash buffer holding the message digest - * \param mgf1_hash_id message digest used for mask generation - * \param expected_salt_len Length of the salt used in padding, use - * MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length - * \param sig buffer holding the ciphertext - * - * \return 0 if the verify operation was successful, - * or an MBEDTLS_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - * - * \note The hash_id in the RSA context is ignored. - */ -int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - mbedtls_md_type_t mgf1_hash_id, - int expected_salt_len, - const unsigned char *sig ); - -/** - * \brief Copy the components of an RSA context - * - * \param dst Destination context - * \param src Source context - * - * \return 0 on success, - * MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure - */ -int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ); - -/** - * \brief Free the components of an RSA key - * - * \param ctx RSA Context to free - */ -void mbedtls_rsa_free( mbedtls_rsa_context *ctx ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_rsa_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_RSA_C */ - -#endif /* rsa.h */ diff --git a/components/mbedtls/include/mbedtls/sha1.h b/components/mbedtls/include/mbedtls/sha1.h deleted file mode 100644 index 7a67c6c1fb..0000000000 --- a/components/mbedtls/include/mbedtls/sha1.h +++ /dev/null @@ -1,136 +0,0 @@ -/** - * \file sha1.h - * - * \brief SHA-1 cryptographic hash function - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_SHA1_H -#define MBEDTLS_SHA1_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#if !defined(MBEDTLS_SHA1_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief SHA-1 context structure - */ -typedef struct -{ - uint32_t total[2]; /*!< number of bytes processed */ - uint32_t state[5]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ -} -mbedtls_sha1_context; - -/** - * \brief Initialize SHA-1 context - * - * \param ctx SHA-1 context to be initialized - */ -void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); - -/** - * \brief Clear SHA-1 context - * - * \param ctx SHA-1 context to be cleared - */ -void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); - -/** - * \brief Clone (the state of) a SHA-1 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_sha1_clone( mbedtls_sha1_context *dst, - const mbedtls_sha1_context *src ); - -/** - * \brief SHA-1 context setup - * - * \param ctx context to be initialized - */ -void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); - -/** - * \brief SHA-1 process buffer - * - * \param ctx SHA-1 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief SHA-1 final digest - * - * \param ctx SHA-1 context - * \param output SHA-1 checksum result - */ -void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ); - -/* Internal use */ -void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ); - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_SHA1_ALT */ -#include "sha1_alt.h" -#endif /* MBEDTLS_SHA1_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Output = SHA-1( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-1 checksum result - */ -void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_sha1_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_sha1.h */ diff --git a/components/mbedtls/include/mbedtls/sha256.h b/components/mbedtls/include/mbedtls/sha256.h deleted file mode 100644 index f8041adf08..0000000000 --- a/components/mbedtls/include/mbedtls/sha256.h +++ /dev/null @@ -1,141 +0,0 @@ -/** - * \file sha256.h - * - * \brief SHA-224 and SHA-256 cryptographic hash function - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_SHA256_H -#define MBEDTLS_SHA256_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#if !defined(MBEDTLS_SHA256_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief SHA-256 context structure - */ -typedef struct -{ - uint32_t total[2]; /*!< number of bytes processed */ - uint32_t state[8]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ - int is224; /*!< 0 => SHA-256, else SHA-224 */ -} -mbedtls_sha256_context; - -/** - * \brief Initialize SHA-256 context - * - * \param ctx SHA-256 context to be initialized - */ -void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); - -/** - * \brief Clear SHA-256 context - * - * \param ctx SHA-256 context to be cleared - */ -void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); - -/** - * \brief Clone (the state of) a SHA-256 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_sha256_clone( mbedtls_sha256_context *dst, - const mbedtls_sha256_context *src ); - -/** - * \brief SHA-256 context setup - * - * \param ctx context to be initialized - * \param is224 0 = use SHA256, 1 = use SHA224 - */ -void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ); - -/** - * \brief SHA-256 process buffer - * - * \param ctx SHA-256 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, - size_t ilen ); - -/** - * \brief SHA-256 final digest - * - * \param ctx SHA-256 context - * \param output SHA-224/256 checksum result - */ -void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ); - -/* Internal use */ -void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ); - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_SHA256_ALT */ -#include "sha256_alt.h" -#endif /* MBEDTLS_SHA256_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Output = SHA-256( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-224/256 checksum result - * \param is224 0 = use SHA256, 1 = use SHA224 - */ -void mbedtls_sha256( const unsigned char *input, size_t ilen, - unsigned char output[32], int is224 ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_sha256_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_sha256.h */ diff --git a/components/mbedtls/include/mbedtls/sha512.h b/components/mbedtls/include/mbedtls/sha512.h deleted file mode 100644 index 12f4fab4f1..0000000000 --- a/components/mbedtls/include/mbedtls/sha512.h +++ /dev/null @@ -1,141 +0,0 @@ -/** - * \file sha512.h - * - * \brief SHA-384 and SHA-512 cryptographic hash function - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_SHA512_H -#define MBEDTLS_SHA512_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#if !defined(MBEDTLS_SHA512_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief SHA-512 context structure - */ -typedef struct -{ - uint64_t total[2]; /*!< number of bytes processed */ - uint64_t state[8]; /*!< intermediate digest state */ - unsigned char buffer[128]; /*!< data block being processed */ - int is384; /*!< 0 => SHA-512, else SHA-384 */ -} -mbedtls_sha512_context; - -/** - * \brief Initialize SHA-512 context - * - * \param ctx SHA-512 context to be initialized - */ -void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); - -/** - * \brief Clear SHA-512 context - * - * \param ctx SHA-512 context to be cleared - */ -void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); - -/** - * \brief Clone (the state of) a SHA-512 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_sha512_clone( mbedtls_sha512_context *dst, - const mbedtls_sha512_context *src ); - -/** - * \brief SHA-512 context setup - * - * \param ctx context to be initialized - * \param is384 0 = use SHA512, 1 = use SHA384 - */ -void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ); - -/** - * \brief SHA-512 process buffer - * - * \param ctx SHA-512 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input, - size_t ilen ); - -/** - * \brief SHA-512 final digest - * - * \param ctx SHA-512 context - * \param output SHA-384/512 checksum result - */ -void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] ); - -/* Internal use */ -void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ); - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_SHA512_ALT */ -#include "sha512_alt.h" -#endif /* MBEDTLS_SHA512_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Output = SHA-512( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-384/512 checksum result - * \param is384 0 = use SHA512, 1 = use SHA384 - */ -void mbedtls_sha512( const unsigned char *input, size_t ilen, - unsigned char output[64], int is384 ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_sha512_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_sha512.h */ diff --git a/components/mbedtls/include/mbedtls/ssl.h b/components/mbedtls/include/mbedtls/ssl.h deleted file mode 100644 index cc00070062..0000000000 --- a/components/mbedtls/include/mbedtls/ssl.h +++ /dev/null @@ -1,2583 +0,0 @@ -/** - * \file ssl.h - * - * \brief SSL/TLS functions. - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_SSL_H -#define MBEDTLS_SSL_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "bignum.h" -#include "ecp.h" - -#include "ssl_ciphersuites.h" - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#include "x509_crt.h" -#include "x509_crl.h" -#endif - -#if defined(MBEDTLS_DHM_C) -#include "dhm.h" -#endif - -#if defined(MBEDTLS_ECDH_C) -#include "ecdh.h" -#endif - -#if defined(MBEDTLS_ZLIB_SUPPORT) -#include "zlib.h" -#endif - -#if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" -#endif - -/* - * SSL Error codes - */ -#define MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 /**< The requested feature is not available. */ -#define MBEDTLS_ERR_SSL_BAD_INPUT_DATA -0x7100 /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_SSL_INVALID_MAC -0x7180 /**< Verification of the message MAC failed. */ -#define MBEDTLS_ERR_SSL_INVALID_RECORD -0x7200 /**< An invalid SSL record was received. */ -#define MBEDTLS_ERR_SSL_CONN_EOF -0x7280 /**< The connection indicated an EOF. */ -#define MBEDTLS_ERR_SSL_UNKNOWN_CIPHER -0x7300 /**< An unknown cipher was received. */ -#define MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN -0x7380 /**< The server has no ciphersuites in common with the client. */ -#define MBEDTLS_ERR_SSL_NO_RNG -0x7400 /**< No RNG was provided to the SSL module. */ -#define MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 /**< No client certification received from the client, but required by the authentication mode. */ -#define MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500 /**< Our own certificate(s) is/are too large to send in an SSL message. */ -#define MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED -0x7580 /**< The own certificate is not set, but needed by the server. */ -#define MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 /**< The own private key or pre-shared key is not set, but needed. */ -#define MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 /**< No CA Chain is set, but required to operate. */ -#define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 /**< An unexpected message was received from our peer. */ -#define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 /**< A fatal alert message was received from our peer. */ -#define MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED -0x7800 /**< Verification of our peer failed. */ -#define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 /**< The peer notified us that the connection is going to be closed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900 /**< Processing of the ClientHello handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980 /**< Processing of the ServerHello handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00 /**< Processing of the Certificate handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80 /**< Processing of the CertificateRequest handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00 /**< Processing of the ServerKeyExchange handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80 /**< Processing of the ServerHelloDone handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00 /**< Processing of the ClientKeyExchange handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -0x7C80 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -0x7D00 /**< Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80 /**< Processing of the CertificateVerify handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00 /**< Processing of the ChangeCipherSpec handshake message failed. */ -#define MBEDTLS_ERR_SSL_BAD_HS_FINISHED -0x7E80 /**< Processing of the Finished handshake message failed. */ -#define MBEDTLS_ERR_SSL_ALLOC_FAILED -0x7F00 /**< Memory allocation failed */ -#define MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -0x7F80 /**< Hardware acceleration function returned with error */ -#define MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 /**< Hardware acceleration function skipped / left alone data */ -#define MBEDTLS_ERR_SSL_COMPRESSION_FAILED -0x6F00 /**< Processing of the compression / decompression failed */ -#define MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80 /**< Handshake protocol not within min/max boundaries */ -#define MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00 /**< Processing of the NewSessionTicket handshake message failed. */ -#define MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 /**< Session ticket has expired. */ -#define MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH -0x6D00 /**< Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */ -#define MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 /**< Unknown identity received (eg, PSK identity) */ -#define MBEDTLS_ERR_SSL_INTERNAL_ERROR -0x6C00 /**< Internal error (eg, unexpected failure in lower-level module) */ -#define MBEDTLS_ERR_SSL_COUNTER_WRAPPING -0x6B80 /**< A counter would wrap (eg, too many messages exchanged). */ -#define MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00 /**< Unexpected message at ServerHello in renegotiation. */ -#define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 /**< DTLS client must retry for hello verification */ -#define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 /**< A buffer is too small to receive or write a message */ -#define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980 /**< None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */ -#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< Connection requires a read call. */ -#define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 /**< Connection requires a write call. */ -#define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 /**< The operation timed out. */ -#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 /**< The client initiated a reconnect from the same port. */ -#define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /**< Record header looks valid but is not expected. */ -#define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */ -#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */ - -/* - * Various constants - */ -#define MBEDTLS_SSL_MAJOR_VERSION_3 3 -#define MBEDTLS_SSL_MINOR_VERSION_0 0 /*!< SSL v3.0 */ -#define MBEDTLS_SSL_MINOR_VERSION_1 1 /*!< TLS v1.0 */ -#define MBEDTLS_SSL_MINOR_VERSION_2 2 /*!< TLS v1.1 */ -#define MBEDTLS_SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ - -#define MBEDTLS_SSL_TRANSPORT_STREAM 0 /*!< TLS */ -#define MBEDTLS_SSL_TRANSPORT_DATAGRAM 1 /*!< DTLS */ - -#define MBEDTLS_SSL_MAX_HOST_NAME_LEN 255 /*!< Maximum host name defined in RFC 1035 */ - -/* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c - * NONE must be zero so that memset()ing structure to zero works */ -#define MBEDTLS_SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ -#define MBEDTLS_SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ -#define MBEDTLS_SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ -#define MBEDTLS_SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */ -#define MBEDTLS_SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */ -#define MBEDTLS_SSL_MAX_FRAG_LEN_INVALID 5 /*!< first invalid value */ - -#define MBEDTLS_SSL_IS_CLIENT 0 -#define MBEDTLS_SSL_IS_SERVER 1 - -#define MBEDTLS_SSL_IS_NOT_FALLBACK 0 -#define MBEDTLS_SSL_IS_FALLBACK 1 - -#define MBEDTLS_SSL_EXTENDED_MS_DISABLED 0 -#define MBEDTLS_SSL_EXTENDED_MS_ENABLED 1 - -#define MBEDTLS_SSL_ETM_DISABLED 0 -#define MBEDTLS_SSL_ETM_ENABLED 1 - -#define MBEDTLS_SSL_COMPRESS_NULL 0 -#define MBEDTLS_SSL_COMPRESS_DEFLATE 1 - -#define MBEDTLS_SSL_VERIFY_NONE 0 -#define MBEDTLS_SSL_VERIFY_OPTIONAL 1 -#define MBEDTLS_SSL_VERIFY_REQUIRED 2 -#define MBEDTLS_SSL_VERIFY_UNSET 3 /* Used only for sni_authmode */ - -#define MBEDTLS_SSL_LEGACY_RENEGOTIATION 0 -#define MBEDTLS_SSL_SECURE_RENEGOTIATION 1 - -#define MBEDTLS_SSL_RENEGOTIATION_DISABLED 0 -#define MBEDTLS_SSL_RENEGOTIATION_ENABLED 1 - -#define MBEDTLS_SSL_ANTI_REPLAY_DISABLED 0 -#define MBEDTLS_SSL_ANTI_REPLAY_ENABLED 1 - -#define MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED -1 -#define MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT 16 - -#define MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION 0 -#define MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION 1 -#define MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE 2 - -#define MBEDTLS_SSL_TRUNC_HMAC_DISABLED 0 -#define MBEDTLS_SSL_TRUNC_HMAC_ENABLED 1 -#define MBEDTLS_SSL_TRUNCATED_HMAC_LEN 10 /* 80 bits, rfc 6066 section 7 */ - -#define MBEDTLS_SSL_SESSION_TICKETS_DISABLED 0 -#define MBEDTLS_SSL_SESSION_TICKETS_ENABLED 1 - -#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED 0 -#define MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED 1 - -#define MBEDTLS_SSL_ARC4_ENABLED 0 -#define MBEDTLS_SSL_ARC4_DISABLED 1 - -#define MBEDTLS_SSL_PRESET_DEFAULT 0 -#define MBEDTLS_SSL_PRESET_SUITEB 2 - -#define MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED 1 -#define MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED 0 - -/* - * Default range for DTLS retransmission timer value, in milliseconds. - * RFC 6347 4.2.4.1 says from 1 second to 60 seconds. - */ -#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN 1000 -#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX 60000 - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -#if !defined(MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME) -#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ -#endif - -/* - * Maxium fragment length in bytes, - * determines the size of each of the two internal I/O buffers. - * - * Note: the RFC defines the default size of SSL / TLS messages. If you - * change the value here, other clients / servers may not be able to - * communicate with you anymore. Only change this value if you control - * both sides of the connection and have it reduced at both sides, or - * if you're using the Max Fragment Length extension and you know all your - * peers are using it too! - */ -#if !defined(MBEDTLS_SSL_MAX_CONTENT_LEN) -#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ -#endif - -/* \} name SECTION: Module settings */ - -/* - * Length of the verify data for secure renegotiation - */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) -#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 36 -#else -#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12 -#endif - -/* - * Signaling ciphersuite values (SCSV) - */ -#define MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ -#define MBEDTLS_SSL_FALLBACK_SCSV_VALUE 0x5600 /**< RFC 7507 section 2 */ - -/* - * Supported Signature and Hash algorithms (For TLS 1.2) - * RFC 5246 section 7.4.1.4.1 - */ -#define MBEDTLS_SSL_HASH_NONE 0 -#define MBEDTLS_SSL_HASH_MD5 1 -#define MBEDTLS_SSL_HASH_SHA1 2 -#define MBEDTLS_SSL_HASH_SHA224 3 -#define MBEDTLS_SSL_HASH_SHA256 4 -#define MBEDTLS_SSL_HASH_SHA384 5 -#define MBEDTLS_SSL_HASH_SHA512 6 - -#define MBEDTLS_SSL_SIG_ANON 0 -#define MBEDTLS_SSL_SIG_RSA 1 -#define MBEDTLS_SSL_SIG_ECDSA 3 - -/* - * Client Certificate Types - * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5 - */ -#define MBEDTLS_SSL_CERT_TYPE_RSA_SIGN 1 -#define MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN 64 - -/* - * Message, alert and handshake types - */ -#define MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC 20 -#define MBEDTLS_SSL_MSG_ALERT 21 -#define MBEDTLS_SSL_MSG_HANDSHAKE 22 -#define MBEDTLS_SSL_MSG_APPLICATION_DATA 23 - -#define MBEDTLS_SSL_ALERT_LEVEL_WARNING 1 -#define MBEDTLS_SSL_ALERT_LEVEL_FATAL 2 - -#define MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */ -#define MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */ -#define MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */ -#define MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */ -#define MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */ -#define MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */ -#define MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */ -#define MBEDTLS_SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */ -#define MBEDTLS_SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */ -#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */ -#define MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */ -#define MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */ -#define MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */ -#define MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */ -#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */ -#define MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */ -#define MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */ -#define MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */ -#define MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */ -#define MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */ -#define MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */ -#define MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */ -#define MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK 86 /* 0x56 */ -#define MBEDTLS_SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */ -#define MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ -#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ -#define MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */ -#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115 /* 0x73 */ -#define MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */ - -#define MBEDTLS_SSL_HS_HELLO_REQUEST 0 -#define MBEDTLS_SSL_HS_CLIENT_HELLO 1 -#define MBEDTLS_SSL_HS_SERVER_HELLO 2 -#define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST 3 -#define MBEDTLS_SSL_HS_NEW_SESSION_TICKET 4 -#define MBEDTLS_SSL_HS_CERTIFICATE 11 -#define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE 12 -#define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST 13 -#define MBEDTLS_SSL_HS_SERVER_HELLO_DONE 14 -#define MBEDTLS_SSL_HS_CERTIFICATE_VERIFY 15 -#define MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE 16 -#define MBEDTLS_SSL_HS_FINISHED 20 - -/* - * TLS extensions - */ -#define MBEDTLS_TLS_EXT_SERVERNAME 0 -#define MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME 0 - -#define MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH 1 - -#define MBEDTLS_TLS_EXT_TRUNCATED_HMAC 4 - -#define MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 -#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS 11 - -#define MBEDTLS_TLS_EXT_SIG_ALG 13 - -#define MBEDTLS_TLS_EXT_ALPN 16 - -#define MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC 22 /* 0x16 */ -#define MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */ - -#define MBEDTLS_TLS_EXT_SESSION_TICKET 35 - -#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP 256 /* experimental */ - -#define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO 0xFF01 - -/* - * Size defines - */ -#if !defined(MBEDTLS_PSK_MAX_LEN) -#define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ -#endif - -/* Dummy type used only for its size */ -union mbedtls_ssl_premaster_secret -{ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) - unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) - unsigned char _pms_dhm[MBEDTLS_MPI_MAX_SIZE]; /* RFC 5246 8.1.2 */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) - unsigned char _pms_ecdh[MBEDTLS_ECP_MAX_BYTES]; /* RFC 4492 5.10 */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - unsigned char _pms_psk[4 + 2 * MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 2 */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) - unsigned char _pms_dhe_psk[4 + MBEDTLS_MPI_MAX_SIZE - + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 3 */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) - unsigned char _pms_rsa_psk[52 + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 4 */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) - unsigned char _pms_ecdhe_psk[4 + MBEDTLS_ECP_MAX_BYTES - + MBEDTLS_PSK_MAX_LEN]; /* RFC 5489 2 */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - unsigned char _pms_ecjpake[32]; /* Thread spec: SHA-256 output */ -#endif -}; - -#define MBEDTLS_PREMASTER_SIZE sizeof( union mbedtls_ssl_premaster_secret ) - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * SSL state machine - */ -typedef enum -{ - MBEDTLS_SSL_HELLO_REQUEST, - MBEDTLS_SSL_CLIENT_HELLO, - MBEDTLS_SSL_SERVER_HELLO, - MBEDTLS_SSL_SERVER_CERTIFICATE, - MBEDTLS_SSL_SERVER_KEY_EXCHANGE, - MBEDTLS_SSL_CERTIFICATE_REQUEST, - MBEDTLS_SSL_SERVER_HELLO_DONE, - MBEDTLS_SSL_CLIENT_CERTIFICATE, - MBEDTLS_SSL_CLIENT_KEY_EXCHANGE, - MBEDTLS_SSL_CERTIFICATE_VERIFY, - MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC, - MBEDTLS_SSL_CLIENT_FINISHED, - MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC, - MBEDTLS_SSL_SERVER_FINISHED, - MBEDTLS_SSL_FLUSH_BUFFERS, - MBEDTLS_SSL_HANDSHAKE_WRAPUP, - MBEDTLS_SSL_HANDSHAKE_OVER, - MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET, - MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT, -} -mbedtls_ssl_states; - -/** - * \brief Callback type: send data on the network. - * - * \note That callback may be either blocking or non-blocking. - * - * \param ctx Context for the send callback (typically a file descriptor) - * \param buf Buffer holding the data to send - * \param len Length of the data to send - * - * \return The callback must return the number of bytes sent if any, - * or a non-zero error code. - * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_WRITE - * must be returned when the operation would block. - * - * \note The callback is allowed to send fewer bytes than requested. - * It must always return the number of bytes actually sent. - */ -typedef int mbedtls_ssl_send_t( void *ctx, - const unsigned char *buf, - size_t len ); - -/** - * \brief Callback type: receive data from the network. - * - * \note That callback may be either blocking or non-blocking. - * - * \param ctx Context for the receive callback (typically a file - * descriptor) - * \param buf Buffer to write the received data to - * \param len Length of the receive buffer - * - * \return The callback must return the number of bytes received, - * or a non-zero error code. - * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_READ - * must be returned when the operation would block. - * - * \note The callback may receive fewer bytes than the length of the - * buffer. It must always return the number of bytes actually - * received and written to the buffer. - */ -typedef int mbedtls_ssl_recv_t( void *ctx, - unsigned char *buf, - size_t len ); - -/** - * \brief Callback type: receive data from the network, with timeout - * - * \note That callback must block until data is received, or the - * timeout delay expires, or the operation is interrupted by a - * signal. - * - * \param ctx Context for the receive callback (typically a file descriptor) - * \param buf Buffer to write the received data to - * \param len Length of the receive buffer - * \param timeout Maximum nomber of millisecondes to wait for data - * 0 means no timeout (potentially waiting forever) - * - * \return The callback must return the number of bytes received, - * or a non-zero error code: - * \c MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, - * \c MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. - * - * \note The callback may receive fewer bytes than the length of the - * buffer. It must always return the number of bytes actually - * received and written to the buffer. - */ -typedef int mbedtls_ssl_recv_timeout_t( void *ctx, - unsigned char *buf, - size_t len, - uint32_t timeout ); -/** - * \brief Callback type: set a pair of timers/delays to watch - * - * \param ctx Context pointer - * \param int_ms Intermediate delay in milliseconds - * \param fin_ms Final delay in milliseconds - * 0 cancels the current timer. - * - * \note This callback must at least store the necessary information - * for the associated \c mbedtls_ssl_get_timer_t callback to - * return correct information. - * - * \note If using a event-driven style of programming, an event must - * be generated when the final delay is passed. The event must - * cause a call to \c mbedtls_ssl_handshake() with the proper - * SSL context to be scheduled. Care must be taken to ensure - * that at most one such call happens at a time. - * - * \note Only one timer at a time must be running. Calling this - * function while a timer is running must cancel it. Cancelled - * timers must not generate any event. - */ -typedef void mbedtls_ssl_set_timer_t( void * ctx, - uint32_t int_ms, - uint32_t fin_ms ); - -/** - * \brief Callback type: get status of timers/delays - * - * \param ctx Context pointer - * - * \return This callback must return: - * -1 if cancelled (fin_ms == 0), - * 0 if none of the delays have passed, - * 1 if only the intermediate delay has passed, - * 2 if the final delay has passed. - */ -typedef int mbedtls_ssl_get_timer_t( void * ctx ); - - -/* Defined below */ -typedef struct mbedtls_ssl_session mbedtls_ssl_session; -typedef struct mbedtls_ssl_context mbedtls_ssl_context; -typedef struct mbedtls_ssl_config mbedtls_ssl_config; - -/* Defined in ssl_internal.h */ -typedef struct mbedtls_ssl_transform mbedtls_ssl_transform; -typedef struct mbedtls_ssl_handshake_params mbedtls_ssl_handshake_params; -typedef struct mbedtls_ssl_sig_hash_set_t mbedtls_ssl_sig_hash_set_t; -#if defined(MBEDTLS_X509_CRT_PARSE_C) -typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; -#endif -#if defined(MBEDTLS_SSL_PROTO_DTLS) -typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; -#endif - -/* - * This structure is used for storing current session data. - */ -struct mbedtls_ssl_session -{ -#if defined(MBEDTLS_HAVE_TIME) - mbedtls_time_t start; /*!< starting time */ -#endif - int ciphersuite; /*!< chosen ciphersuite */ - int compression; /*!< chosen compression */ - size_t id_len; /*!< session id length */ - unsigned char id[32]; /*!< session identifier */ - unsigned char master[48]; /*!< the master secret */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - mbedtls_x509_crt *peer_cert; /*!< peer X.509 cert chain */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - uint32_t verify_result; /*!< verification result */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) - unsigned char *ticket; /*!< RFC 5077 session ticket */ - size_t ticket_len; /*!< session ticket length */ - uint32_t ticket_lifetime; /*!< ticket lifetime hint */ -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - unsigned char mfl_code; /*!< MaxFragmentLength negotiated by peer */ -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - int trunc_hmac; /*!< flag for truncated hmac activation */ -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - int encrypt_then_mac; /*!< flag for EtM activation */ -#endif -}; - -/** - * SSL/TLS configuration to be shared between mbedtls_ssl_context structures. - */ -struct mbedtls_ssl_config -{ - /* Group items by size (largest first) to minimize padding overhead */ - - /* - * Pointers - */ - - const int *ciphersuite_list[4]; /*!< allowed ciphersuites per version */ - - /** Callback for printing debug output */ - void (*f_dbg)(void *, int, const char *, int, const char *); - void *p_dbg; /*!< context for the debug function */ - - /** Callback for getting (pseudo-)random numbers */ - int (*f_rng)(void *, unsigned char *, size_t); - void *p_rng; /*!< context for the RNG function */ - - /** Callback to retrieve a session from the cache */ - int (*f_get_cache)(void *, mbedtls_ssl_session *); - /** Callback to store a session into the cache */ - int (*f_set_cache)(void *, const mbedtls_ssl_session *); - void *p_cache; /*!< context for cache callbacks */ - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - /** Callback for setting cert according to SNI extension */ - int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); - void *p_sni; /*!< context for SNI callback */ -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - /** Callback to customize X.509 certificate chain verification */ - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); - void *p_vrfy; /*!< context for X.509 verify calllback */ -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - /** Callback to retrieve PSK key from identity */ - int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t); - void *p_psk; /*!< context for PSK callback */ -#endif - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) - /** Callback to create & write a cookie for ClientHello veirifcation */ - int (*f_cookie_write)( void *, unsigned char **, unsigned char *, - const unsigned char *, size_t ); - /** Callback to verify validity of a ClientHello cookie */ - int (*f_cookie_check)( void *, const unsigned char *, size_t, - const unsigned char *, size_t ); - void *p_cookie; /*!< context for the cookie callbacks */ -#endif - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) - /** Callback to create & write a session ticket */ - int (*f_ticket_write)( void *, const mbedtls_ssl_session *, - unsigned char *, const unsigned char *, size_t *, uint32_t * ); - /** Callback to parse a session ticket into a session structure */ - int (*f_ticket_parse)( void *, mbedtls_ssl_session *, unsigned char *, size_t); - void *p_ticket; /*!< context for the ticket callbacks */ -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_SSL_EXPORT_KEYS) - /** Callback to export key block and master secret */ - int (*f_export_keys)( void *, const unsigned char *, - const unsigned char *, size_t, size_t, size_t ); - void *p_export_keys; /*!< context for key export callback */ -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - const mbedtls_x509_crt_profile *cert_profile; /*!< verification profile */ - mbedtls_ssl_key_cert *key_cert; /*!< own certificate/key pair(s) */ - mbedtls_x509_crt *ca_chain; /*!< trusted CAs */ - mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - const int *sig_hashes; /*!< allowed signature hashes */ -#endif - -#if defined(MBEDTLS_ECP_C) - const mbedtls_ecp_group_id *curve_list; /*!< allowed curves */ -#endif - -#if defined(MBEDTLS_DHM_C) - mbedtls_mpi dhm_P; /*!< prime modulus for DHM */ - mbedtls_mpi dhm_G; /*!< generator for DHM */ -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - unsigned char *psk; /*!< pre-shared key */ - size_t psk_len; /*!< length of the pre-shared key */ - unsigned char *psk_identity; /*!< identity for PSK negotiation */ - size_t psk_identity_len;/*!< length of identity */ -#endif - -#if defined(MBEDTLS_SSL_ALPN) - const char **alpn_list; /*!< ordered list of protocols */ -#endif - - /* - * Numerical settings (int then char) - */ - - uint32_t read_timeout; /*!< timeout for mbedtls_ssl_read (ms) */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - uint32_t hs_timeout_min; /*!< initial value of the handshake - retransmission timeout (ms) */ - uint32_t hs_timeout_max; /*!< maximum value of the handshake - retransmission timeout (ms) */ -#endif - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - int renego_max_records; /*!< grace period for renegotiation */ - unsigned char renego_period[8]; /*!< value of the record counters - that triggers renegotiation */ -#endif - -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) - unsigned int badmac_limit; /*!< limit of records with a bad MAC */ -#endif - -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) - unsigned int dhm_min_bitlen; /*!< min. bit length of the DHM prime */ -#endif - - unsigned char max_major_ver; /*!< max. major version used */ - unsigned char max_minor_ver; /*!< max. minor version used */ - unsigned char min_major_ver; /*!< min. major version used */ - unsigned char min_minor_ver; /*!< min. minor version used */ - - /* - * Flags (bitfields) - */ - - unsigned int endpoint : 1; /*!< 0: client, 1: server */ - unsigned int transport : 1; /*!< stream (TLS) or datagram (DTLS) */ - unsigned int authmode : 2; /*!< MBEDTLS_SSL_VERIFY_XXX */ - /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE */ - unsigned int allow_legacy_renegotiation : 2 ; /*!< MBEDTLS_LEGACY_XXX */ -#if defined(MBEDTLS_ARC4_C) - unsigned int arc4_disabled : 1; /*!< blacklist RC4 ciphersuites? */ -#endif -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - unsigned int mfl_code : 3; /*!< desired fragment length */ -#endif -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - unsigned int encrypt_then_mac : 1 ; /*!< negotiate encrypt-then-mac? */ -#endif -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - unsigned int extended_ms : 1; /*!< negotiate extended master secret? */ -#endif -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - unsigned int anti_replay : 1; /*!< detect and prevent replay? */ -#endif -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - unsigned int cbc_record_splitting : 1; /*!< do cbc record splitting */ -#endif -#if defined(MBEDTLS_SSL_RENEGOTIATION) - unsigned int disable_renegotiation : 1; /*!< disable renegotiation? */ -#endif -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - unsigned int trunc_hmac : 1; /*!< negotiate truncated hmac? */ -#endif -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - unsigned int session_tickets : 1; /*!< use session tickets? */ -#endif -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) - unsigned int fallback : 1; /*!< is this a fallback? */ -#endif -#if defined(MBEDTLS_SSL_SRV_C) - unsigned int cert_req_ca_list : 1; /*!< enable sending CA list in - Certificate Request messages? */ -#endif -}; - - -struct mbedtls_ssl_context -{ - const mbedtls_ssl_config *conf; /*!< configuration information */ - - /* - * Miscellaneous - */ - int state; /*!< SSL handshake: current state */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - int renego_status; /*!< Initial, in progress, pending? */ - int renego_records_seen; /*!< Records since renego request, or with DTLS, - number of retransmissions of request if - renego_max_records is < 0 */ -#endif - - int major_ver; /*!< equal to MBEDTLS_SSL_MAJOR_VERSION_3 */ - int minor_ver; /*!< either 0 (SSL3) or 1 (TLS1.0) */ - -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) - unsigned badmac_seen; /*!< records with a bad MAC received */ -#endif - - mbedtls_ssl_send_t *f_send; /*!< Callback for network send */ - mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */ - mbedtls_ssl_recv_timeout_t *f_recv_timeout; - /*!< Callback for network receive with timeout */ - - void *p_bio; /*!< context for I/O operations */ - - /* - * Session layer - */ - mbedtls_ssl_session *session_in; /*!< current session data (in) */ - mbedtls_ssl_session *session_out; /*!< current session data (out) */ - mbedtls_ssl_session *session; /*!< negotiated session data */ - mbedtls_ssl_session *session_negotiate; /*!< session data in negotiation */ - - mbedtls_ssl_handshake_params *handshake; /*!< params required only during - the handshake process */ - - /* - * Record layer transformations - */ - mbedtls_ssl_transform *transform_in; /*!< current transform params (in) */ - mbedtls_ssl_transform *transform_out; /*!< current transform params (in) */ - mbedtls_ssl_transform *transform; /*!< negotiated transform params */ - mbedtls_ssl_transform *transform_negotiate; /*!< transform params in negotiation */ - - /* - * Timers - */ - void *p_timer; /*!< context for the timer callbacks */ - - mbedtls_ssl_set_timer_t *f_set_timer; /*!< set timer callback */ - mbedtls_ssl_get_timer_t *f_get_timer; /*!< get timer callback */ - - /* - * Record layer (incoming data) - */ - unsigned char *in_buf; /*!< input buffer */ - unsigned char *in_ctr; /*!< 64-bit incoming message counter - TLS: maintained by us - DTLS: read from peer */ - unsigned char *in_hdr; /*!< start of record header */ - unsigned char *in_len; /*!< two-bytes message length field */ - unsigned char *in_iv; /*!< ivlen-byte IV */ - unsigned char *in_msg; /*!< message contents (in_iv+ivlen) */ - unsigned char *in_offt; /*!< read offset in application data */ - - int in_msgtype; /*!< record header: message type */ - size_t in_msglen; /*!< record header: message length */ - size_t in_left; /*!< amount of data read so far */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - uint16_t in_epoch; /*!< DTLS epoch for incoming records */ - size_t next_record_offset; /*!< offset of the next record in datagram - (equal to in_left if none) */ -#endif -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - uint64_t in_window_top; /*!< last validated record seq_num */ - uint64_t in_window; /*!< bitmask for replay detection */ -#endif - - size_t in_hslen; /*!< current handshake message length, - including the handshake header */ - int nb_zero; /*!< # of 0-length encrypted messages */ - - int keep_current_message; /*!< drop or reuse current message - on next call to record layer? */ - - /* - * Record layer (outgoing data) - */ - unsigned char *out_buf; /*!< output buffer */ - unsigned char *out_ctr; /*!< 64-bit outgoing message counter */ - unsigned char *out_hdr; /*!< start of record header */ - unsigned char *out_len; /*!< two-bytes message length field */ - unsigned char *out_iv; /*!< ivlen-byte IV */ - unsigned char *out_msg; /*!< message contents (out_iv+ivlen) */ - - int out_msgtype; /*!< record header: message type */ - size_t out_msglen; /*!< record header: message length */ - size_t out_left; /*!< amount of data not yet written */ - -#if defined(MBEDTLS_ZLIB_SUPPORT) - unsigned char *compress_buf; /*!< zlib data buffer */ -#endif -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - signed char split_done; /*!< current record already splitted? */ -#endif - - /* - * PKI layer - */ - int client_auth; /*!< flag for client auth. */ - - /* - * User settings - */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) - char *hostname; /*!< expected peer CN for verification - (and SNI if available) */ -#endif - -#if defined(MBEDTLS_SSL_ALPN) - const char *alpn_chosen; /*!< negotiated protocol */ -#endif - - /* - * Information for DTLS hello verify - */ -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) - unsigned char *cli_id; /*!< transport-level ID of the client */ - size_t cli_id_len; /*!< length of cli_id */ -#endif - - /* - * Secure renegotiation - */ - /* needed to know when to send extension on server */ - int secure_renegotiation; /*!< does peer support legacy or - secure renegotiation */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - size_t verify_data_len; /*!< length of verify data stored */ - char own_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ - char peer_verify_data[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ -#endif -}; - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - -#define MBEDTLS_SSL_CHANNEL_OUTBOUND 0 -#define MBEDTLS_SSL_CHANNEL_INBOUND 1 - -extern int (*mbedtls_ssl_hw_record_init)(mbedtls_ssl_context *ssl, - const unsigned char *key_enc, const unsigned char *key_dec, - size_t keylen, - const unsigned char *iv_enc, const unsigned char *iv_dec, - size_t ivlen, - const unsigned char *mac_enc, const unsigned char *mac_dec, - size_t maclen); -extern int (*mbedtls_ssl_hw_record_activate)(mbedtls_ssl_context *ssl, int direction); -extern int (*mbedtls_ssl_hw_record_reset)(mbedtls_ssl_context *ssl); -extern int (*mbedtls_ssl_hw_record_write)(mbedtls_ssl_context *ssl); -extern int (*mbedtls_ssl_hw_record_read)(mbedtls_ssl_context *ssl); -extern int (*mbedtls_ssl_hw_record_finish)(mbedtls_ssl_context *ssl); -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ - -/** - * \brief Returns the list of ciphersuites supported by the SSL/TLS module. - * - * \return a statically allocated array of ciphersuites, the last - * entry is 0. - */ -const int *mbedtls_ssl_list_ciphersuites( void ); - -/** - * \brief Return the name of the ciphersuite associated with the - * given ID - * - * \param ciphersuite_id SSL ciphersuite ID - * - * \return a string containing the ciphersuite name - */ -const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ); - -/** - * \brief Return the ID of the ciphersuite associated with the - * given name - * - * \param ciphersuite_name SSL ciphersuite name - * - * \return the ID with the ciphersuite or 0 if not found - */ -int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ); - -/** - * \brief Initialize an SSL context - * Just makes the context ready for mbedtls_ssl_setup() or - * mbedtls_ssl_free() - * - * \param ssl SSL context - */ -void mbedtls_ssl_init( mbedtls_ssl_context *ssl ); - -/** - * \brief Set up an SSL context for use - * - * \note No copy of the configuration context is made, it can be - * shared by many mbedtls_ssl_context structures. - * - * \warning Modifying the conf structure after it has been used in this - * function is unsupported! - * - * \param ssl SSL context - * \param conf SSL configuration to use - * - * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED if - * memory allocation failed - */ -int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, - const mbedtls_ssl_config *conf ); - -/** - * \brief Reset an already initialized SSL context for re-use - * while retaining application-set variables, function - * pointers and data. - * - * \param ssl SSL context - * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED, - MBEDTLS_ERR_SSL_HW_ACCEL_FAILED or - * MBEDTLS_ERR_SSL_COMPRESSION_FAILED - */ -int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ); - -/** - * \brief Set the current endpoint type - * - * \param conf SSL configuration - * \param endpoint must be MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER - */ -void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ); - -/** - * \brief Set the transport type (TLS or DTLS). - * Default: TLS - * - * \note For DTLS, you must either provide a recv callback that - * doesn't block, or one that handles timeouts, see - * \c mbedtls_ssl_set_bio(). You also need to provide timer - * callbacks with \c mbedtls_ssl_set_timer_cb(). - * - * \param conf SSL configuration - * \param transport transport type: - * MBEDTLS_SSL_TRANSPORT_STREAM for TLS, - * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS. - */ -void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ); - -/** - * \brief Set the certificate verification mode - * Default: NONE on server, REQUIRED on client - * - * \param conf SSL configuration - * \param authmode can be: - * - * MBEDTLS_SSL_VERIFY_NONE: peer certificate is not checked - * (default on server) - * (insecure on client) - * - * MBEDTLS_SSL_VERIFY_OPTIONAL: peer certificate is checked, however the - * handshake continues even if verification failed; - * mbedtls_ssl_get_verify_result() can be called after the - * handshake is complete. - * - * MBEDTLS_SSL_VERIFY_REQUIRED: peer *must* present a valid certificate, - * handshake is aborted if verification failed. - * (default on client) - * - * \note On client, MBEDTLS_SSL_VERIFY_REQUIRED is the recommended mode. - * With MBEDTLS_SSL_VERIFY_OPTIONAL, the user needs to call mbedtls_ssl_get_verify_result() at - * the right time(s), which may not be obvious, while REQUIRED always perform - * the verification as soon as possible. For example, REQUIRED was protecting - * against the "triple handshake" attack even before it was found. - */ -void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/** - * \brief Set the verification callback (Optional). - * - * If set, the verify callback is called for each - * certificate in the chain. For implementation - * information, please see \c mbedtls_x509_crt_verify() - * - * \param conf SSL configuration - * \param f_vrfy verification function - * \param p_vrfy verification parameter - */ -void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ); -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -/** - * \brief Set the random number generator callback - * - * \param conf SSL configuration - * \param f_rng RNG function - * \param p_rng RNG parameter - */ -void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Set the debug callback - * - * The callback has the following argument: - * void * opaque context for the callback - * int debug level - * const char * file name - * int line number - * const char * message - * - * \param conf SSL configuration - * \param f_dbg debug function - * \param p_dbg debug parameter - */ -void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, - void (*f_dbg)(void *, int, const char *, int, const char *), - void *p_dbg ); - -/** - * \brief Set the underlying BIO callbacks for write, read and - * read-with-timeout. - * - * \param ssl SSL context - * \param p_bio parameter (context) shared by BIO callbacks - * \param f_send write callback - * \param f_recv read callback - * \param f_recv_timeout blocking read callback with timeout. - * - * \note One of f_recv or f_recv_timeout can be NULL, in which case - * the other is used. If both are non-NULL, f_recv_timeout is - * used and f_recv is ignored (as if it were NULL). - * - * \note The two most common use cases are: - * - non-blocking I/O, f_recv != NULL, f_recv_timeout == NULL - * - blocking I/O, f_recv == NULL, f_recv_timout != NULL - * - * \note For DTLS, you need to provide either a non-NULL - * f_recv_timeout callback, or a f_recv that doesn't block. - * - * \note See the documentations of \c mbedtls_ssl_sent_t, - * \c mbedtls_ssl_recv_t and \c mbedtls_ssl_recv_timeout_t for - * the conventions those callbacks must follow. - * - * \note On some platforms, net_sockets.c provides - * \c mbedtls_net_send(), \c mbedtls_net_recv() and - * \c mbedtls_net_recv_timeout() that are suitable to be used - * here. - */ -void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, - void *p_bio, - mbedtls_ssl_send_t *f_send, - mbedtls_ssl_recv_t *f_recv, - mbedtls_ssl_recv_timeout_t *f_recv_timeout ); - -/** - * \brief Set the timeout period for mbedtls_ssl_read() - * (Default: no timeout.) - * - * \param conf SSL configuration context - * \param timeout Timeout value in milliseconds. - * Use 0 for no timeout (default). - * - * \note With blocking I/O, this will only work if a non-NULL - * \c f_recv_timeout was set with \c mbedtls_ssl_set_bio(). - * With non-blocking I/O, this will only work if timer - * callbacks were set with \c mbedtls_ssl_set_timer_cb(). - * - * \note With non-blocking I/O, you may also skip this function - * altogether and handle timeouts at the application layer. - */ -void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ); - -/** - * \brief Set the timer callbacks (Mandatory for DTLS.) - * - * \param ssl SSL context - * \param p_timer parameter (context) shared by timer callbacks - * \param f_set_timer set timer callback - * \param f_get_timer get timer callback. Must return: - * - * \note See the documentation of \c mbedtls_ssl_set_timer_t and - * \c mbedtls_ssl_get_timer_t for the conventions this pair of - * callbacks must follow. - * - * \note On some platforms, timing.c provides - * \c mbedtls_timing_set_delay() and - * \c mbedtls_timing_get_delay() that are suitable for using - * here, except if using an event-driven style. - * - * \note See also the "DTLS tutorial" article in our knowledge base. - * https://tls.mbed.org/kb/how-to/dtls-tutorial - */ -void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, - void *p_timer, - mbedtls_ssl_set_timer_t *f_set_timer, - mbedtls_ssl_get_timer_t *f_get_timer ); - -/** - * \brief Callback type: generate and write session ticket - * - * \note This describes what a callback implementation should do. - * This callback should generate an encrypted and - * authenticated ticket for the session and write it to the - * output buffer. Here, ticket means the opaque ticket part - * of the NewSessionTicket structure of RFC 5077. - * - * \param p_ticket Context for the callback - * \param session SSL session to be written in the ticket - * \param start Start of the output buffer - * \param end End of the output buffer - * \param tlen On exit, holds the length written - * \param lifetime On exit, holds the lifetime of the ticket in seconds - * - * \return 0 if successful, or - * a specific MBEDTLS_ERR_XXX code. - */ -typedef int mbedtls_ssl_ticket_write_t( void *p_ticket, - const mbedtls_ssl_session *session, - unsigned char *start, - const unsigned char *end, - size_t *tlen, - uint32_t *lifetime ); - -#if defined(MBEDTLS_SSL_EXPORT_KEYS) -/** - * \brief Callback type: Export key block and master secret - * - * \note This is required for certain uses of TLS, e.g. EAP-TLS - * (RFC 5216) and Thread. The key pointers are ephemeral and - * therefore must not be stored. The master secret and keys - * should not be used directly except as an input to a key - * derivation function. - * - * \param p_expkey Context for the callback - * \param ms Pointer to master secret (fixed length: 48 bytes) - * \param kb Pointer to key block, see RFC 5246 section 6.3 - * (variable length: 2 * maclen + 2 * keylen + 2 * ivlen). - * \param maclen MAC length - * \param keylen Key length - * \param ivlen IV length - * - * \return 0 if successful, or - * a specific MBEDTLS_ERR_XXX code. - */ -typedef int mbedtls_ssl_export_keys_t( void *p_expkey, - const unsigned char *ms, - const unsigned char *kb, - size_t maclen, - size_t keylen, - size_t ivlen ); -#endif /* MBEDTLS_SSL_EXPORT_KEYS */ - -/** - * \brief Callback type: parse and load session ticket - * - * \note This describes what a callback implementation should do. - * This callback should parse a session ticket as generated - * by the corresponding mbedtls_ssl_ticket_write_t function, - * and, if the ticket is authentic and valid, load the - * session. - * - * \note The implementation is allowed to modify the first len - * bytes of the input buffer, eg to use it as a temporary - * area for the decrypted ticket contents. - * - * \param p_ticket Context for the callback - * \param session SSL session to be loaded - * \param buf Start of the buffer containing the ticket - * \param len Length of the ticket. - * - * \return 0 if successful, or - * MBEDTLS_ERR_SSL_INVALID_MAC if not authentic, or - * MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED if expired, or - * any other non-zero code for other failures. - */ -typedef int mbedtls_ssl_ticket_parse_t( void *p_ticket, - mbedtls_ssl_session *session, - unsigned char *buf, - size_t len ); - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) -/** - * \brief Configure SSL session ticket callbacks (server only). - * (Default: none.) - * - * \note On server, session tickets are enabled by providing - * non-NULL callbacks. - * - * \note On client, use \c mbedtls_ssl_conf_session_tickets(). - * - * \param conf SSL configuration context - * \param f_ticket_write Callback for writing a ticket - * \param f_ticket_parse Callback for parsing a ticket - * \param p_ticket Context shared by the two callbacks - */ -void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, - mbedtls_ssl_ticket_write_t *f_ticket_write, - mbedtls_ssl_ticket_parse_t *f_ticket_parse, - void *p_ticket ); -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_SSL_EXPORT_KEYS) -/** - * \brief Configure key export callback. - * (Default: none.) - * - * \note See \c mbedtls_ssl_export_keys_t. - * - * \param conf SSL configuration context - * \param f_export_keys Callback for exporting keys - * \param p_export_keys Context for the callback - */ -void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, - mbedtls_ssl_export_keys_t *f_export_keys, - void *p_export_keys ); -#endif /* MBEDTLS_SSL_EXPORT_KEYS */ - -/** - * \brief Callback type: generate a cookie - * - * \param ctx Context for the callback - * \param p Buffer to write to, - * must be updated to point right after the cookie - * \param end Pointer to one past the end of the output buffer - * \param info Client ID info that was passed to - * \c mbedtls_ssl_set_client_transport_id() - * \param ilen Length of info in bytes - * - * \return The callback must return 0 on success, - * or a negative error code. - */ -typedef int mbedtls_ssl_cookie_write_t( void *ctx, - unsigned char **p, unsigned char *end, - const unsigned char *info, size_t ilen ); - -/** - * \brief Callback type: verify a cookie - * - * \param ctx Context for the callback - * \param cookie Cookie to verify - * \param clen Length of cookie - * \param info Client ID info that was passed to - * \c mbedtls_ssl_set_client_transport_id() - * \param ilen Length of info in bytes - * - * \return The callback must return 0 if cookie is valid, - * or a negative error code. - */ -typedef int mbedtls_ssl_cookie_check_t( void *ctx, - const unsigned char *cookie, size_t clen, - const unsigned char *info, size_t ilen ); - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) -/** - * \brief Register callbacks for DTLS cookies - * (Server only. DTLS only.) - * - * Default: dummy callbacks that fail, in order to force you to - * register working callbacks (and initialize their context). - * - * To disable HelloVerifyRequest, register NULL callbacks. - * - * \warning Disabling hello verification allows your server to be used - * for amplification in DoS attacks against other hosts. - * Only disable if you known this can't happen in your - * particular environment. - * - * \note See comments on \c mbedtls_ssl_handshake() about handling - * the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED that is expected - * on the first handshake attempt when this is enabled. - * - * \note This is also necessary to handle client reconnection from - * the same port as described in RFC 6347 section 4.2.8 (only - * the variant with cookies is supported currently). See - * comments on \c mbedtls_ssl_read() for details. - * - * \param conf SSL configuration - * \param f_cookie_write Cookie write callback - * \param f_cookie_check Cookie check callback - * \param p_cookie Context for both callbacks - */ -void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, - mbedtls_ssl_cookie_write_t *f_cookie_write, - mbedtls_ssl_cookie_check_t *f_cookie_check, - void *p_cookie ); - -/** - * \brief Set client's transport-level identification info. - * (Server only. DTLS only.) - * - * This is usually the IP address (and port), but could be - * anything identify the client depending on the underlying - * network stack. Used for HelloVerifyRequest with DTLS. - * This is *not* used to route the actual packets. - * - * \param ssl SSL context - * \param info Transport-level info identifying the client (eg IP + port) - * \param ilen Length of info in bytes - * - * \note An internal copy is made, so the info buffer can be reused. - * - * \return 0 on success, - * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used on client, - * MBEDTLS_ERR_SSL_ALLOC_FAILED if out of memory. - */ -int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, - const unsigned char *info, - size_t ilen ); - -#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -/** - * \brief Enable or disable anti-replay protection for DTLS. - * (DTLS only, no effect on TLS.) - * Default: enabled. - * - * \param conf SSL configuration - * \param mode MBEDTLS_SSL_ANTI_REPLAY_ENABLED or MBEDTLS_SSL_ANTI_REPLAY_DISABLED. - * - * \warning Disabling this is a security risk unless the application - * protocol handles duplicated packets in a safe way. You - * should not disable this without careful consideration. - * However, if your application already detects duplicated - * packets and needs information about them to adjust its - * transmission strategy, then you'll want to disable this. - */ -void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ); -#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ - -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) -/** - * \brief Set a limit on the number of records with a bad MAC - * before terminating the connection. - * (DTLS only, no effect on TLS.) - * Default: 0 (disabled). - * - * \param conf SSL configuration - * \param limit Limit, or 0 to disable. - * - * \note If the limit is N, then the connection is terminated when - * the Nth non-authentic record is seen. - * - * \note Records with an invalid header are not counted, only the - * ones going through the authentication-decryption phase. - * - * \note This is a security trade-off related to the fact that it's - * often relatively easy for an active attacker ot inject UDP - * datagrams. On one hand, setting a low limit here makes it - * easier for such an attacker to forcibly terminated a - * connection. On the other hand, a high limit or no limit - * might make us waste resources checking authentication on - * many bogus packets. - */ -void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ); -#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -/** - * \brief Set retransmit timeout values for the DTLS handshake. - * (DTLS only, no effect on TLS.) - * - * \param conf SSL configuration - * \param min Initial timeout value in milliseconds. - * Default: 1000 (1 second). - * \param max Maximum timeout value in milliseconds. - * Default: 60000 (60 seconds). - * - * \note Default values are from RFC 6347 section 4.2.4.1. - * - * \note The 'min' value should typically be slightly above the - * expected round-trip time to your peer, plus whatever time - * it takes for the peer to process the message. For example, - * if your RTT is about 600ms and you peer needs up to 1s to - * do the cryptographic operations in the handshake, then you - * should set 'min' slightly above 1600. Lower values of 'min' - * might cause spurious resends which waste network resources, - * while larger value of 'min' will increase overall latency - * on unreliable network links. - * - * \note The more unreliable your network connection is, the larger - * your max / min ratio needs to be in order to achieve - * reliable handshakes. - * - * \note Messages are retransmitted up to log2(ceil(max/min)) times. - * For example, if min = 1s and max = 5s, the retransmit plan - * goes: send ... 1s -> resend ... 2s -> resend ... 4s -> - * resend ... 5s -> give up and return a timeout error. - */ -void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ); -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -#if defined(MBEDTLS_SSL_SRV_C) -/** - * \brief Set the session cache callbacks (server-side only) - * If not set, no session resuming is done (except if session - * tickets are enabled too). - * - * The session cache has the responsibility to check for stale - * entries based on timeout. See RFC 5246 for recommendations. - * - * Warning: session.peer_cert is cleared by the SSL/TLS layer on - * connection shutdown, so do not cache the pointer! Either set - * it to NULL or make a full copy of the certificate. - * - * The get callback is called once during the initial handshake - * to enable session resuming. The get function has the - * following parameters: (void *parameter, mbedtls_ssl_session *session) - * If a valid entry is found, it should fill the master of - * the session object with the cached values and return 0, - * return 1 otherwise. Optionally peer_cert can be set as well - * if it is properly present in cache entry. - * - * The set callback is called once during the initial handshake - * to enable session resuming after the entire handshake has - * been finished. The set function has the following parameters: - * (void *parameter, const mbedtls_ssl_session *session). The function - * should create a cache entry for future retrieval based on - * the data in the session structure and should keep in mind - * that the mbedtls_ssl_session object presented (and all its referenced - * data) is cleared by the SSL/TLS layer when the connection is - * terminated. It is recommended to add metadata to determine if - * an entry is still valid in the future. Return 0 if - * successfully cached, return 1 otherwise. - * - * \param conf SSL configuration - * \param p_cache parmater (context) for both callbacks - * \param f_get_cache session get callback - * \param f_set_cache session set callback - */ -void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, - void *p_cache, - int (*f_get_cache)(void *, mbedtls_ssl_session *), - int (*f_set_cache)(void *, const mbedtls_ssl_session *) ); -#endif /* MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_SSL_CLI_C) -/** - * \brief Request resumption of session (client-side only) - * Session data is copied from presented session structure. - * - * \param ssl SSL context - * \param session session context - * - * \return 0 if successful, - * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or - * arguments are otherwise invalid - * - * \sa mbedtls_ssl_get_session() - */ -int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ); -#endif /* MBEDTLS_SSL_CLI_C */ - -/** - * \brief Set the list of allowed ciphersuites and the preference - * order. First in the list has the highest preference. - * (Overrides all version-specific lists) - * - * The ciphersuites array is not copied, and must remain - * valid for the lifetime of the ssl_config. - * - * Note: The server uses its own preferences - * over the preference of the client unless - * MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE is defined! - * - * \param conf SSL configuration - * \param ciphersuites 0-terminated list of allowed ciphersuites - */ -void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, - const int *ciphersuites ); - -/** - * \brief Set the list of allowed ciphersuites and the - * preference order for a specific version of the protocol. - * (Only useful on the server side) - * - * The ciphersuites array is not copied, and must remain - * valid for the lifetime of the ssl_config. - * - * \param conf SSL configuration - * \param ciphersuites 0-terminated list of allowed ciphersuites - * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 - * supported) - * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, - * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, - * MBEDTLS_SSL_MINOR_VERSION_3 supported) - * - * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 - * and MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 - */ -void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, - const int *ciphersuites, - int major, int minor ); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/** - * \brief Set the X.509 security profile used for verification - * - * \note The restrictions are enforced for all certificates in the - * chain. However, signatures in the handshake are not covered - * by this setting but by \b mbedtls_ssl_conf_sig_hashes(). - * - * \param conf SSL configuration - * \param profile Profile to use - */ -void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, - const mbedtls_x509_crt_profile *profile ); - -/** - * \brief Set the data required to verify peer certificate - * - * \param conf SSL configuration - * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) - * \param ca_crl trusted CA CRLs - */ -void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, - mbedtls_x509_crt *ca_chain, - mbedtls_x509_crl *ca_crl ); - -/** - * \brief Set own certificate chain and private key - * - * \note own_cert should contain in order from the bottom up your - * certificate chain. The top certificate (self-signed) - * can be omitted. - * - * \note On server, this function can be called multiple times to - * provision more than one cert/key pair (eg one ECDSA, one - * RSA with SHA-256, one RSA with SHA-1). An adequate - * certificate will be selected according to the client's - * advertised capabilities. In case mutliple certificates are - * adequate, preference is given to the one set by the first - * call to this function, then second, etc. - * - * \note On client, only the first call has any effect. That is, - * only one client certificate can be provisioned. The - * server's preferences in its CertficateRequest message will - * be ignored and our only cert will be sent regardless of - * whether it matches those preferences - the server can then - * decide what it wants to do with it. - * - * \param conf SSL configuration - * \param own_cert own public certificate chain - * \param pk_key own private key - * - * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED - */ -int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, - mbedtls_x509_crt *own_cert, - mbedtls_pk_context *pk_key ); -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -/** - * \brief Set the Pre Shared Key (PSK) and the expected identity name - * - * \note This is mainly useful for clients. Servers will usually - * want to use \c mbedtls_ssl_conf_psk_cb() instead. - * - * \note Currently clients can only register one pre-shared key. - * In other words, the servers' identity hint is ignored. - * Support for setting multiple PSKs on clients and selecting - * one based on the identity hint is not a planned feature but - * feedback is welcomed. - * - * \param conf SSL configuration - * \param psk pointer to the pre-shared key - * \param psk_len pre-shared key length - * \param psk_identity pointer to the pre-shared key identity - * \param psk_identity_len identity key length - * - * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED - */ -int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, - const unsigned char *psk, size_t psk_len, - const unsigned char *psk_identity, size_t psk_identity_len ); - - -/** - * \brief Set the Pre Shared Key (PSK) for the current handshake - * - * \note This should only be called inside the PSK callback, - * ie the function passed to \c mbedtls_ssl_conf_psk_cb(). - * - * \param ssl SSL context - * \param psk pointer to the pre-shared key - * \param psk_len pre-shared key length - * - * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED - */ -int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, - const unsigned char *psk, size_t psk_len ); - -/** - * \brief Set the PSK callback (server-side only). - * - * If set, the PSK callback is called for each - * handshake where a PSK ciphersuite was negotiated. - * The caller provides the identity received and wants to - * receive the actual PSK data and length. - * - * The callback has the following parameters: (void *parameter, - * mbedtls_ssl_context *ssl, const unsigned char *psk_identity, - * size_t identity_len) - * If a valid PSK identity is found, the callback should use - * \c mbedtls_ssl_set_hs_psk() on the ssl context to set the - * correct PSK and return 0. - * Any other return value will result in a denied PSK identity. - * - * \note If you set a PSK callback using this function, then you - * don't need to set a PSK key and identity using - * \c mbedtls_ssl_conf_psk(). - * - * \param conf SSL configuration - * \param f_psk PSK identity function - * \param p_psk PSK identity parameter - */ -void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, - int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, - size_t), - void *p_psk ); -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ - -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) -/** - * \brief Set the Diffie-Hellman public P and G values, - * read as hexadecimal strings (server-side only) - * (Default: MBEDTLS_DHM_RFC5114_MODP_2048_[PG]) - * - * \param conf SSL configuration - * \param dhm_P Diffie-Hellman-Merkle modulus - * \param dhm_G Diffie-Hellman-Merkle generator - * - * \return 0 if successful - */ -int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G ); - -/** - * \brief Set the Diffie-Hellman public P and G values, - * read from existing context (server-side only) - * - * \param conf SSL configuration - * \param dhm_ctx Diffie-Hellman-Merkle context - * - * \return 0 if successful - */ -int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ); -#endif /* MBEDTLS_DHM_C && defined(MBEDTLS_SSL_SRV_C) */ - -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) -/** - * \brief Set the minimum length for Diffie-Hellman parameters. - * (Client-side only.) - * (Default: 1024 bits.) - * - * \param conf SSL configuration - * \param bitlen Minimum bit length of the DHM prime - */ -void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, - unsigned int bitlen ); -#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ - -#if defined(MBEDTLS_ECP_C) -/** - * \brief Set the allowed curves in order of preference. - * (Default: all defined curves.) - * - * On server: this only affects selection of the ECDHE curve; - * the curves used for ECDH and ECDSA are determined by the - * list of available certificates instead. - * - * On client: this affects the list of curves offered for any - * use. The server can override our preference order. - * - * Both sides: limits the set of curves accepted for use in - * ECDHE and in the peer's end-entity certificate. - * - * \note This has no influence on which curves are allowed inside the - * certificate chains, see \c mbedtls_ssl_conf_cert_profile() - * for that. For the end-entity certificate however, the key - * will be accepted only if it is allowed both by this list - * and by the cert profile. - * - * \note This list should be ordered by decreasing preference - * (preferred curve first). - * - * \param conf SSL configuration - * \param curves Ordered list of allowed curves, - * terminated by MBEDTLS_ECP_DP_NONE. - */ -void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, - const mbedtls_ecp_group_id *curves ); -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -/** - * \brief Set the allowed hashes for signatures during the handshake. - * (Default: all available hashes except MD5.) - * - * \note This only affects which hashes are offered and can be used - * for signatures during the handshake. Hashes for message - * authentication and the TLS PRF are controlled by the - * ciphersuite, see \c mbedtls_ssl_conf_ciphersuites(). Hashes - * used for certificate signature are controlled by the - * verification profile, see \c mbedtls_ssl_conf_cert_profile(). - * - * \note This list should be ordered by decreasing preference - * (preferred hash first). - * - * \param conf SSL configuration - * \param hashes Ordered list of allowed signature hashes, - * terminated by \c MBEDTLS_MD_NONE. - */ -void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, - const int *hashes ); -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/** - * \brief Set the hostname to check against the received server - * certificate. It sets the ServerName TLS extension too, - * if the extension is enabled. - * (client-side only) - * - * \param ssl SSL context - * \param hostname the server hostname - * - * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED - */ -int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ); -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) -/** - * \brief Set own certificate and key for the current handshake - * - * \note Same as \c mbedtls_ssl_conf_own_cert() but for use within - * the SNI callback. - * - * \param ssl SSL context - * \param own_cert own public certificate chain - * \param pk_key own private key - * - * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED - */ -int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, - mbedtls_x509_crt *own_cert, - mbedtls_pk_context *pk_key ); - -/** - * \brief Set the data required to verify peer certificate for the - * current handshake - * - * \note Same as \c mbedtls_ssl_conf_ca_chain() but for use within - * the SNI callback. - * - * \param ssl SSL context - * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) - * \param ca_crl trusted CA CRLs - */ -void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, - mbedtls_x509_crt *ca_chain, - mbedtls_x509_crl *ca_crl ); - -/** - * \brief Set authmode for the current handshake. - * - * \note Same as \c mbedtls_ssl_conf_authmode() but for use within - * the SNI callback. - * - * \param ssl SSL context - * \param authmode MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL or - * MBEDTLS_SSL_VERIFY_REQUIRED - */ -void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, - int authmode ); - -/** - * \brief Set server side ServerName TLS extension callback - * (optional, server-side only). - * - * If set, the ServerName callback is called whenever the - * server receives a ServerName TLS extension from the client - * during a handshake. The ServerName callback has the - * following parameters: (void *parameter, mbedtls_ssl_context *ssl, - * const unsigned char *hostname, size_t len). If a suitable - * certificate is found, the callback must set the - * certificate(s) and key(s) to use with \c - * mbedtls_ssl_set_hs_own_cert() (can be called repeatedly), - * and may optionally adjust the CA and associated CRL with \c - * mbedtls_ssl_set_hs_ca_chain() as well as the client - * authentication mode with \c mbedtls_ssl_set_hs_authmode(), - * then must return 0. If no matching name is found, the - * callback must either set a default cert, or - * return non-zero to abort the handshake at this point. - * - * \param conf SSL configuration - * \param f_sni verification function - * \param p_sni verification parameter - */ -void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, - int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, - size_t), - void *p_sni ); -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -/** - * \brief Set the EC J-PAKE password for current handshake. - * - * \note An internal copy is made, and destroyed as soon as the - * handshake is completed, or when the SSL context is reset or - * freed. - * - * \note The SSL context needs to be already set up. The right place - * to call this function is between \c mbedtls_ssl_setup() or - * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). - * - * \param ssl SSL context - * \param pw EC J-PAKE password (pre-shared secret) - * \param pw_len length of pw in bytes - * - * \return 0 on success, or a negative error code. - */ -int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, - const unsigned char *pw, - size_t pw_len ); -#endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_SSL_ALPN) -/** - * \brief Set the supported Application Layer Protocols. - * - * \param conf SSL configuration - * \param protos Pointer to a NULL-terminated list of supported protocols, - * in decreasing preference order. The pointer to the list is - * recorded by the library for later reference as required, so - * the lifetime of the table must be atleast as long as the - * lifetime of the SSL configuration structure. - * - * \return 0 on success, or MBEDTLS_ERR_SSL_BAD_INPUT_DATA. - */ -int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ); - -/** - * \brief Get the name of the negotiated Application Layer Protocol. - * This function should be called after the handshake is - * completed. - * - * \param ssl SSL context - * - * \return Protcol name, or NULL if no protocol was negotiated. - */ -const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ); -#endif /* MBEDTLS_SSL_ALPN */ - -/** - * \brief Set the maximum supported version sent from the client side - * and/or accepted at the server side - * (Default: MBEDTLS_SSL_MAX_MAJOR_VERSION, MBEDTLS_SSL_MAX_MINOR_VERSION) - * - * \note This ignores ciphersuites from higher versions. - * - * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and - * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 - * - * \param conf SSL configuration - * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) - * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, - * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, - * MBEDTLS_SSL_MINOR_VERSION_3 supported) - */ -void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ); - -/** - * \brief Set the minimum accepted SSL/TLS protocol version - * (Default: TLS 1.0) - * - * \note Input outside of the SSL_MAX_XXXXX_VERSION and - * SSL_MIN_XXXXX_VERSION range is ignored. - * - * \note MBEDTLS_SSL_MINOR_VERSION_0 (SSL v3) should be avoided. - * - * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_2 for DTLS 1.0 and - * MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 - * - * \param conf SSL configuration - * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) - * \param minor Minor version number (MBEDTLS_SSL_MINOR_VERSION_0, - * MBEDTLS_SSL_MINOR_VERSION_1 and MBEDTLS_SSL_MINOR_VERSION_2, - * MBEDTLS_SSL_MINOR_VERSION_3 supported) - */ -void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ); - -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) -/** - * \brief Set the fallback flag (client-side only). - * (Default: MBEDTLS_SSL_IS_NOT_FALLBACK). - * - * \note Set to MBEDTLS_SSL_IS_FALLBACK when preparing a fallback - * connection, that is a connection with max_version set to a - * lower value than the value you're willing to use. Such - * fallback connections are not recommended but are sometimes - * necessary to interoperate with buggy (version-intolerant) - * servers. - * - * \warning You should NOT set this to MBEDTLS_SSL_IS_FALLBACK for - * non-fallback connections! This would appear to work for a - * while, then cause failures when the server is upgraded to - * support a newer TLS version. - * - * \param conf SSL configuration - * \param fallback MBEDTLS_SSL_IS_NOT_FALLBACK or MBEDTLS_SSL_IS_FALLBACK - */ -void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ); -#endif /* MBEDTLS_SSL_FALLBACK_SCSV && MBEDTLS_SSL_CLI_C */ - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) -/** - * \brief Enable or disable Encrypt-then-MAC - * (Default: MBEDTLS_SSL_ETM_ENABLED) - * - * \note This should always be enabled, it is a security - * improvement, and should not cause any interoperability - * issue (used only if the peer supports it too). - * - * \param conf SSL configuration - * \param etm MBEDTLS_SSL_ETM_ENABLED or MBEDTLS_SSL_ETM_DISABLED - */ -void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ); -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) -/** - * \brief Enable or disable Extended Master Secret negotiation. - * (Default: MBEDTLS_SSL_EXTENDED_MS_ENABLED) - * - * \note This should always be enabled, it is a security fix to the - * protocol, and should not cause any interoperability issue - * (used only if the peer supports it too). - * - * \param conf SSL configuration - * \param ems MBEDTLS_SSL_EXTENDED_MS_ENABLED or MBEDTLS_SSL_EXTENDED_MS_DISABLED - */ -void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ); -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ - -#if defined(MBEDTLS_ARC4_C) -/** - * \brief Disable or enable support for RC4 - * (Default: MBEDTLS_SSL_ARC4_DISABLED) - * - * \warning Use of RC4 in DTLS/TLS has been prohibited by RFC 7465 - * for security reasons. Use at your own risk. - * - * \note This function is deprecated and will likely be removed in - * a future version of the library. - * RC4 is disabled by default at compile time and needs to be - * actively enabled for use with legacy systems. - * - * \param conf SSL configuration - * \param arc4 MBEDTLS_SSL_ARC4_ENABLED or MBEDTLS_SSL_ARC4_DISABLED - */ -void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ); -#endif /* MBEDTLS_ARC4_C */ - -#if defined(MBEDTLS_SSL_SRV_C) -/** - * \brief Whether to send a list of acceptable CAs in - * CertificateRequest messages. - * (Default: do send) - * - * \param conf SSL configuration - * \param cert_req_ca_list MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED or - * MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED - */ -void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, - char cert_req_ca_list ); -#endif /* MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -/** - * \brief Set the maximum fragment length to emit and/or negotiate - * (Default: MBEDTLS_SSL_MAX_CONTENT_LEN, usually 2^14 bytes) - * (Server: set maximum fragment length to emit, - * usually negotiated by the client during handshake - * (Client: set maximum fragment length to emit *and* - * negotiate with the server during handshake) - * - * \param conf SSL configuration - * \param mfl_code Code for maximum fragment length (allowed values: - * MBEDTLS_SSL_MAX_FRAG_LEN_512, MBEDTLS_SSL_MAX_FRAG_LEN_1024, - * MBEDTLS_SSL_MAX_FRAG_LEN_2048, MBEDTLS_SSL_MAX_FRAG_LEN_4096) - * - * \return 0 if successful or MBEDTLS_ERR_SSL_BAD_INPUT_DATA - */ -int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ); -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -/** - * \brief Activate negotiation of truncated HMAC - * (Default: MBEDTLS_SSL_TRUNC_HMAC_DISABLED) - * - * \param conf SSL configuration - * \param truncate Enable or disable (MBEDTLS_SSL_TRUNC_HMAC_ENABLED or - * MBEDTLS_SSL_TRUNC_HMAC_DISABLED) - */ -void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ); -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) -/** - * \brief Enable / Disable 1/n-1 record splitting - * (Default: MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED) - * - * \note Only affects SSLv3 and TLS 1.0, not higher versions. - * Does not affect non-CBC ciphersuites in any version. - * - * \param conf SSL configuration - * \param split MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED or - * MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED - */ -void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ); -#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) -/** - * \brief Enable / Disable session tickets (client only). - * (Default: MBEDTLS_SSL_SESSION_TICKETS_ENABLED.) - * - * \note On server, use \c mbedtls_ssl_conf_session_tickets_cb(). - * - * \param conf SSL configuration - * \param use_tickets Enable or disable (MBEDTLS_SSL_SESSION_TICKETS_ENABLED or - * MBEDTLS_SSL_SESSION_TICKETS_DISABLED) - */ -void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ); -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ - -#if defined(MBEDTLS_SSL_RENEGOTIATION) -/** - * \brief Enable / Disable renegotiation support for connection when - * initiated by peer - * (Default: MBEDTLS_SSL_RENEGOTIATION_DISABLED) - * - * \warning It is recommended to always disable renegotation unless you - * know you need it and you know what you're doing. In the - * past, there have been several issues associated with - * renegotiation or a poor understanding of its properties. - * - * \note Server-side, enabling renegotiation also makes the server - * susceptible to a resource DoS by a malicious client. - * - * \param conf SSL configuration - * \param renegotiation Enable or disable (MBEDTLS_SSL_RENEGOTIATION_ENABLED or - * MBEDTLS_SSL_RENEGOTIATION_DISABLED) - */ -void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ); -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - -/** - * \brief Prevent or allow legacy renegotiation. - * (Default: MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) - * - * MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION allows connections to - * be established even if the peer does not support - * secure renegotiation, but does not allow renegotiation - * to take place if not secure. - * (Interoperable and secure option) - * - * MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations - * with non-upgraded peers. Allowing legacy renegotiation - * makes the connection vulnerable to specific man in the - * middle attacks. (See RFC 5746) - * (Most interoperable and least secure option) - * - * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE breaks off connections - * if peer does not support secure renegotiation. Results - * in interoperability issues with non-upgraded peers - * that do not support renegotiation altogether. - * (Most secure option, interoperability issues) - * - * \param conf SSL configuration - * \param allow_legacy Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION, - * SSL_ALLOW_LEGACY_RENEGOTIATION or - * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) - */ -void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) -/** - * \brief Enforce renegotiation requests. - * (Default: enforced, max_records = 16) - * - * When we request a renegotiation, the peer can comply or - * ignore the request. This function allows us to decide - * whether to enforce our renegotiation requests by closing - * the connection if the peer doesn't comply. - * - * However, records could already be in transit from the peer - * when the request is emitted. In order to increase - * reliability, we can accept a number of records before the - * expected handshake records. - * - * The optimal value is highly dependent on the specific usage - * scenario. - * - * \note With DTLS and server-initiated renegotiation, the - * HelloRequest is retransmited every time mbedtls_ssl_read() times - * out or receives Application Data, until: - * - max_records records have beens seen, if it is >= 0, or - * - the number of retransmits that would happen during an - * actual handshake has been reached. - * Please remember the request might be lost a few times - * if you consider setting max_records to a really low value. - * - * \warning On client, the grace period can only happen during - * mbedtls_ssl_read(), as opposed to mbedtls_ssl_write() and mbedtls_ssl_renegotiate() - * which always behave as if max_record was 0. The reason is, - * if we receive application data from the server, we need a - * place to write it, which only happens during mbedtls_ssl_read(). - * - * \param conf SSL configuration - * \param max_records Use MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to - * enforce renegotiation, or a non-negative value to enforce - * it but allow for a grace period of max_records records. - */ -void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ); - -/** - * \brief Set record counter threshold for periodic renegotiation. - * (Default: 2^48 - 1) - * - * Renegotiation is automatically triggered when a record - * counter (outgoing or ingoing) crosses the defined - * threshold. The default value is meant to prevent the - * connection from being closed when the counter is about to - * reached its maximal value (it is not allowed to wrap). - * - * Lower values can be used to enforce policies such as "keys - * must be refreshed every N packets with cipher X". - * - * The renegotiation period can be disabled by setting - * conf->disable_renegotiation to - * MBEDTLS_SSL_RENEGOTIATION_DISABLED. - * - * \note When the configured transport is - * MBEDTLS_SSL_TRANSPORT_DATAGRAM the maximum renegotiation - * period is 2^48 - 1, and for MBEDTLS_SSL_TRANSPORT_STREAM, - * the maximum renegotiation period is 2^64 - 1. - * - * \param conf SSL configuration - * \param period The threshold value: a big-endian 64-bit number. - */ -void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, - const unsigned char period[8] ); -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - -/** - * \brief Return the number of data bytes available to read - * - * \param ssl SSL context - * - * \return how many bytes are available in the read buffer - */ -size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ); - -/** - * \brief Return the result of the certificate verification - * - * \param ssl SSL context - * - * \return 0 if successful, - * -1 if result is not available (eg because the handshake was - * aborted too early), or - * a combination of BADCERT_xxx and BADCRL_xxx flags, see - * x509.h - */ -uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ); - -/** - * \brief Return the name of the current ciphersuite - * - * \param ssl SSL context - * - * \return a string containing the ciphersuite name - */ -const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ); - -/** - * \brief Return the current SSL version (SSLv3/TLSv1/etc) - * - * \param ssl SSL context - * - * \return a string containing the SSL version - */ -const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ); - -/** - * \brief Return the (maximum) number of bytes added by the record - * layer: header + encryption/MAC overhead (inc. padding) - * - * \param ssl SSL context - * - * \return Current maximum record expansion in bytes, or - * MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if compression is - * enabled, which makes expansion much less predictable - */ -int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ); - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -/** - * \brief Return the maximum fragment length (payload, in bytes). - * This is the value negotiated with peer if any, - * or the locally configured value. - * - * \note With DTLS, \c mbedtls_ssl_write() will return an error if - * called with a larger length value. - * With TLS, \c mbedtls_ssl_write() will fragment the input if - * necessary and return the number of bytes written; it is up - * to the caller to call \c mbedtls_ssl_write() again in - * order to send the remaining bytes if any. - * - * \param ssl SSL context - * - * \return Current maximum fragment length. - */ -size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ); -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/** - * \brief Return the peer certificate from the current connection - * - * Note: Can be NULL in case no certificate was sent during - * the handshake. Different calls for the same connection can - * return the same or different pointers for the same - * certificate and even a different certificate altogether. - * The peer cert CAN change in a single connection if - * renegotiation is performed. - * - * \param ssl SSL context - * - * \return the current peer certificate - */ -const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ); -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_SSL_CLI_C) -/** - * \brief Save session in order to resume it later (client-side only) - * Session data is copied to presented session structure. - * - * \warning Currently, peer certificate is lost in the operation. - * - * \param ssl SSL context - * \param session session context - * - * \return 0 if successful, - * MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed, - * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used server-side or - * arguments are otherwise invalid - * - * \sa mbedtls_ssl_set_session() - */ -int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *session ); -#endif /* MBEDTLS_SSL_CLI_C */ - -/** - * \brief Perform the SSL handshake - * - * \param ssl SSL context - * - * \return 0 if successful, or - * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or - * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or - * a specific SSL error code. - * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. - * - * \note If DTLS is in use, then you may choose to handle - * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging - * purposes, as it is an expected return value rather than an - * actual error, but you still need to reset/free the context. - */ -int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); - -/** - * \brief Perform a single step of the SSL handshake - * - * \note The state of the context (ssl->state) will be at - * the next state after execution of this function. Do not - * call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER. - * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. - * - * \param ssl SSL context - * - * \return 0 if successful, or - * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or - * a specific SSL error code. - */ -int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) -/** - * \brief Initiate an SSL renegotiation on the running connection. - * Client: perform the renegotiation right now. - * Server: request renegotiation, which will be performed - * during the next call to mbedtls_ssl_read() if honored by - * client. - * - * \param ssl SSL context - * - * \return 0 if successful, or any mbedtls_ssl_handshake() return - * value. - * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. - */ -int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - -/** - * \brief Read at most 'len' application data bytes - * - * \param ssl SSL context - * \param buf buffer that will hold the data - * \param len maximum number of bytes to read - * - * \return the number of bytes read, or - * 0 for EOF, or - * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or - * MBEDTLS_ERR_SSL_CLIENT_RECONNECT (see below), or - * another negative error code. - * - * \note If this function returns something other than a positive - * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE or - * MBEDTLS_ERR_SSL_CLIENT_RECONNECT, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. - * - * \note When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT - * (which can only happen server-side), it means that a client - * is initiating a new connection using the same source port. - * You can either treat that as a connection close and wait - * for the client to resend a ClientHello, or directly - * continue with \c mbedtls_ssl_handshake() with the same - * context (as it has beeen reset internally). Either way, you - * should make sure this is seen by the application as a new - * connection: application state, if any, should be reset, and - * most importantly the identity of the client must be checked - * again. WARNING: not validating the identity of the client - * again, or not transmitting the new identity to the - * application layer, would allow authentication bypass! - */ -int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ); - -/** - * \brief Try to write exactly 'len' application data bytes - * - * \warning This function will do partial writes in some cases. If the - * return value is non-negative but less than length, the - * function must be called again with updated arguments: - * buf + ret, len - ret (if ret is the return value) until - * it returns a value equal to the last 'len' argument. - * - * \param ssl SSL context - * \param buf buffer holding the data - * \param len how many bytes must be written - * - * \return the number of bytes actually written (may be less than len), - * or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ, - * or another negative error code. - * - * \note If this function returns something other than a positive - * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. - * - * \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ, - * it must be called later with the *same* arguments, - * until it returns a positive value. - * - * \note If the requested length is greater than the maximum - * fragment length (either the built-in limit or the one set - * or negotiated with the peer), then: - * - with TLS, less bytes than requested are written. - * - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned. - * \c mbedtls_ssl_get_max_frag_len() may be used to query the - * active maximum fragment length. - */ -int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ); - -/** - * \brief Send an alert message - * - * \param ssl SSL context - * \param level The alert level of the message - * (MBEDTLS_SSL_ALERT_LEVEL_WARNING or MBEDTLS_SSL_ALERT_LEVEL_FATAL) - * \param message The alert message (SSL_ALERT_MSG_*) - * - * \return 0 if successful, or a specific SSL error code. - * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. - */ -int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, - unsigned char level, - unsigned char message ); -/** - * \brief Notify the peer that the connection is being closed - * - * \param ssl SSL context - * - * \return 0 if successful, or a specific SSL error code. - * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context - * becomes unusable, and you should either free it or call - * \c mbedtls_ssl_session_reset() on it before re-using it for - * a new connection; the current connection must be closed. - */ -int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); - -/** - * \brief Free referenced items in an SSL context and clear memory - * - * \param ssl SSL context - */ -void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); - -/** - * \brief Initialize an SSL configuration context - * Just makes the context ready for - * mbedtls_ssl_config_defaults() or mbedtls_ssl_config_free(). - * - * \note You need to call mbedtls_ssl_config_defaults() unless you - * manually set all of the relevent fields yourself. - * - * \param conf SSL configuration context - */ -void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ); - -/** - * \brief Load reasonnable default SSL configuration values. - * (You need to call mbedtls_ssl_config_init() first.) - * - * \param conf SSL configuration context - * \param endpoint MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER - * \param transport MBEDTLS_SSL_TRANSPORT_STREAM for TLS, or - * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS - * \param preset a MBEDTLS_SSL_PRESET_XXX value - * - * \note See \c mbedtls_ssl_conf_transport() for notes on DTLS. - * - * \return 0 if successful, or - * MBEDTLS_ERR_XXX_ALLOC_FAILED on memory allocation error. - */ -int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, - int endpoint, int transport, int preset ); - -/** - * \brief Free an SSL configuration context - * - * \param conf SSL configuration context - */ -void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ); - -/** - * \brief Initialize SSL session structure - * - * \param session SSL session - */ -void mbedtls_ssl_session_init( mbedtls_ssl_session *session ); - -/** - * \brief Free referenced items in an SSL session including the - * peer certificate and clear memory - * - * \param session SSL session - */ -void mbedtls_ssl_session_free( mbedtls_ssl_session *session ); - -#ifdef __cplusplus -} -#endif - -#endif /* ssl.h */ diff --git a/components/mbedtls/include/mbedtls/ssl_cache.h b/components/mbedtls/include/mbedtls/ssl_cache.h deleted file mode 100644 index 3734bb7274..0000000000 --- a/components/mbedtls/include/mbedtls/ssl_cache.h +++ /dev/null @@ -1,143 +0,0 @@ -/** - * \file ssl_cache.h - * - * \brief SSL session cache implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_SSL_CACHE_H -#define MBEDTLS_SSL_CACHE_H - -#include "ssl.h" - -#if defined(MBEDTLS_THREADING_C) -#include "threading.h" -#endif - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ - -#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT) -#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /*!< 1 day */ -#endif - -#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES) -#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */ -#endif - -/* \} name SECTION: Module settings */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct mbedtls_ssl_cache_context mbedtls_ssl_cache_context; -typedef struct mbedtls_ssl_cache_entry mbedtls_ssl_cache_entry; - -/** - * \brief This structure is used for storing cache entries - */ -struct mbedtls_ssl_cache_entry -{ -#if defined(MBEDTLS_HAVE_TIME) - mbedtls_time_t timestamp; /*!< entry timestamp */ -#endif - mbedtls_ssl_session session; /*!< entry session */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) - mbedtls_x509_buf peer_cert; /*!< entry peer_cert */ -#endif - mbedtls_ssl_cache_entry *next; /*!< chain pointer */ -}; - -/** - * \brief Cache context - */ -struct mbedtls_ssl_cache_context -{ - mbedtls_ssl_cache_entry *chain; /*!< start of the chain */ - int timeout; /*!< cache entry timeout */ - int max_entries; /*!< maximum entries */ -#if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; /*!< mutex */ -#endif -}; - -/** - * \brief Initialize an SSL cache context - * - * \param cache SSL cache context - */ -void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ); - -/** - * \brief Cache get callback implementation - * (Thread-safe if MBEDTLS_THREADING_C is enabled) - * - * \param data SSL cache context - * \param session session to retrieve entry for - */ -int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ); - -/** - * \brief Cache set callback implementation - * (Thread-safe if MBEDTLS_THREADING_C is enabled) - * - * \param data SSL cache context - * \param session session to store entry for - */ -int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ); - -#if defined(MBEDTLS_HAVE_TIME) -/** - * \brief Set the cache timeout - * (Default: MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT (1 day)) - * - * A timeout of 0 indicates no timeout. - * - * \param cache SSL cache context - * \param timeout cache entry timeout in seconds - */ -void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ); -#endif /* MBEDTLS_HAVE_TIME */ - -/** - * \brief Set the maximum number of cache entries - * (Default: MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES (50)) - * - * \param cache SSL cache context - * \param max cache entry maximum - */ -void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ); - -/** - * \brief Free referenced items in a cache context and clear memory - * - * \param cache SSL cache context - */ -void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ); - -#ifdef __cplusplus -} -#endif - -#endif /* ssl_cache.h */ diff --git a/components/mbedtls/include/mbedtls/ssl_ciphersuites.h b/components/mbedtls/include/mbedtls/ssl_ciphersuites.h deleted file mode 100644 index 9101d9cc7c..0000000000 --- a/components/mbedtls/include/mbedtls/ssl_ciphersuites.h +++ /dev/null @@ -1,485 +0,0 @@ -/** - * \file ssl_ciphersuites.h - * - * \brief SSL Ciphersuites for mbed TLS - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_SSL_CIPHERSUITES_H -#define MBEDTLS_SSL_CIPHERSUITES_H - -#include "pk.h" -#include "cipher.h" -#include "md.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Supported ciphersuites (Official IANA names) - */ -#define MBEDTLS_TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ -#define MBEDTLS_TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ - -#define MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 0x04 -#define MBEDTLS_TLS_RSA_WITH_RC4_128_SHA 0x05 -#define MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA 0x09 /**< Weak! Not in TLS 1.2 */ - -#define MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x0A - -#define MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA 0x15 /**< Weak! Not in TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x16 - -#define MBEDTLS_TLS_PSK_WITH_NULL_SHA 0x2C /**< Weak! */ -#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA 0x2D /**< Weak! */ -#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA 0x2E /**< Weak! */ -#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA 0x2F - -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 -#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA 0x35 -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 - -#define MBEDTLS_TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */ -#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ - -#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41 -#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 - -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */ - -#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 -#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 - -#define MBEDTLS_TLS_PSK_WITH_RC4_128_SHA 0x8A -#define MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA 0x8B -#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA 0x8C -#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA 0x8D - -#define MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA 0x8E -#define MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA 0x8F -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x90 -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x91 - -#define MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA 0x92 -#define MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA 0x93 -#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x94 -#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x95 - -#define MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F /**< TLS 1.2 */ - -#define MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 0xA8 /**< TLS 1.2 */ -#define MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 0xA9 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 0xAA /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 0xAB /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 0xAC /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 0xAD /**< TLS 1.2 */ - -#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 0xAE -#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 0xAF -#define MBEDTLS_TLS_PSK_WITH_NULL_SHA256 0xB0 /**< Weak! */ -#define MBEDTLS_TLS_PSK_WITH_NULL_SHA384 0xB1 /**< Weak! */ - -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 0xB2 -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 0xB3 -#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 0xB4 /**< Weak! */ -#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 0xB5 /**< Weak! */ - -#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 0xB6 -#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 0xB7 -#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 0xB8 /**< Weak! */ -#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 0xB9 /**< Weak! */ - -#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ - -#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ - -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 /**< Weak! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 /**< Not in SSL3! */ - -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 /**< Weak! */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xC007 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC008 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A /**< Not in SSL3! */ - -#define MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B /**< Weak! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA 0xC00C /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xC00D /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F /**< Not in SSL3! */ - -#define MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 /**< Weak! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xC011 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xC012 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 /**< Not in SSL3! */ - -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /**< TLS 1.2 */ - -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /**< TLS 1.2 */ - -#define MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA 0xC033 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA 0xC034 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 /**< Weak! No SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A /**< Weak! No SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B /**< Weak! No SSL3! */ - -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 /**< Not in SSL3! */ - -#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07A /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07B /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07C /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07D /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC088 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC089 /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08A /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08B /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08C /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08D /**< TLS 1.2 */ - -#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC08E /**< TLS 1.2 */ -#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC08F /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC090 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC091 /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC092 /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC093 /**< TLS 1.2 */ - -#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC094 -#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC095 -#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC096 -#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC097 -#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC098 -#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC099 -#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A /**< Not in SSL3! */ -#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B /**< Not in SSL3! */ - -#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM 0xC09C /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM 0xC09D /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /**< TLS 1.2 */ -#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /**< TLS 1.2 */ -#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM 0xC0A4 /**< TLS 1.2 */ -#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM 0xC0A5 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM 0xC0A6 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM 0xC0A7 /**< TLS 1.2 */ -#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 0xC0A8 /**< TLS 1.2 */ -#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 0xC0A9 /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 0xC0AA /**< TLS 1.2 */ -#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 0xC0AB /**< TLS 1.2 */ -/* The last two are named with PSK_DHE in the RFC, which looks like a typo */ - -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /**< TLS 1.2 */ -#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /**< TLS 1.2 */ - -#define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */ - -/* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange. - * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below - */ -typedef enum { - MBEDTLS_KEY_EXCHANGE_NONE = 0, - MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_KEY_EXCHANGE_ECJPAKE, -} mbedtls_key_exchange_type_t; - -/* Key exchanges using a certificate */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED -#endif - -/* Key exchanges allowing client certificate requests */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED -#endif - -/* Key exchanges involving server signature in ServerKeyExchange */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED -#endif - -/* Key exchanges using ECDH */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED -#endif - -/* Key exchanges that don't involve ephemeral keys */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED -#endif - -/* Key exchanges that involve ephemeral keys */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED -#endif - -/* Key exchanges using a PSK */ -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED -#endif - -/* Key exchanges using DHE */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED -#endif - -/* Key exchanges using ECDHE */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) -#define MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED -#endif - -typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t; - -#define MBEDTLS_CIPHERSUITE_WEAK 0x01 /**< Weak ciphersuite flag */ -#define MBEDTLS_CIPHERSUITE_SHORT_TAG 0x02 /**< Short authentication tag, - eg for CCM_8 */ -#define MBEDTLS_CIPHERSUITE_NODTLS 0x04 /**< Can't be used with DTLS */ - -/** - * \brief This structure is used for storing ciphersuite information - */ -struct mbedtls_ssl_ciphersuite_t -{ - int id; - const char * name; - - mbedtls_cipher_type_t cipher; - mbedtls_md_type_t mac; - mbedtls_key_exchange_type_t key_exchange; - - int min_major_ver; - int min_minor_ver; - int max_major_ver; - int max_minor_ver; - - unsigned char flags; -}; - -const int *mbedtls_ssl_list_ciphersuites( void ); - -const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( const char *ciphersuite_name ); -const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite_id ); - -#if defined(MBEDTLS_PK_C) -mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ); -mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ); -#endif - -int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ); -int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ); - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED) -static inline int mbedtls_ssl_ciphersuite_has_pfs( const mbedtls_ssl_ciphersuite_t *info ) -{ - switch( info->key_exchange ) - { - case MBEDTLS_KEY_EXCHANGE_DHE_RSA: - case MBEDTLS_KEY_EXCHANGE_DHE_PSK: - case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: - case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: - case MBEDTLS_KEY_EXCHANGE_ECJPAKE: - return( 1 ); - - default: - return( 0 ); - } -} -#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) -static inline int mbedtls_ssl_ciphersuite_no_pfs( const mbedtls_ssl_ciphersuite_t *info ) -{ - switch( info->key_exchange ) - { - case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: - case MBEDTLS_KEY_EXCHANGE_RSA: - case MBEDTLS_KEY_EXCHANGE_PSK: - case MBEDTLS_KEY_EXCHANGE_RSA_PSK: - return( 1 ); - - default: - return( 0 ); - } -} -#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) -static inline int mbedtls_ssl_ciphersuite_uses_ecdh( const mbedtls_ssl_ciphersuite_t *info ) -{ - switch( info->key_exchange ) - { - case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: - return( 1 ); - - default: - return( 0 ); - } -} -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ - -static inline int mbedtls_ssl_ciphersuite_cert_req_allowed( const mbedtls_ssl_ciphersuite_t *info ) -{ - switch( info->key_exchange ) - { - case MBEDTLS_KEY_EXCHANGE_RSA: - case MBEDTLS_KEY_EXCHANGE_DHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: - return( 1 ); - - default: - return( 0 ); - } -} - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) -static inline int mbedtls_ssl_ciphersuite_uses_dhe( const mbedtls_ssl_ciphersuite_t *info ) -{ - switch( info->key_exchange ) - { - case MBEDTLS_KEY_EXCHANGE_DHE_RSA: - case MBEDTLS_KEY_EXCHANGE_DHE_PSK: - return( 1 ); - - default: - return( 0 ); - } -} -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) */ - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) -static inline int mbedtls_ssl_ciphersuite_uses_ecdhe( const mbedtls_ssl_ciphersuite_t *info ) -{ - switch( info->key_exchange ) - { - case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: - return( 1 ); - - default: - return( 0 ); - } -} -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) */ - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) -static inline int mbedtls_ssl_ciphersuite_uses_server_signature( const mbedtls_ssl_ciphersuite_t *info ) -{ - switch( info->key_exchange ) - { - case MBEDTLS_KEY_EXCHANGE_DHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: - return( 1 ); - - default: - return( 0 ); - } -} -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ - -#ifdef __cplusplus -} -#endif - -#endif /* ssl_ciphersuites.h */ diff --git a/components/mbedtls/include/mbedtls/ssl_cookie.h b/components/mbedtls/include/mbedtls/ssl_cookie.h deleted file mode 100644 index 037e1c3112..0000000000 --- a/components/mbedtls/include/mbedtls/ssl_cookie.h +++ /dev/null @@ -1,108 +0,0 @@ -/** - * \file ssl_cookie.h - * - * \brief DTLS cookie callbacks implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_SSL_COOKIE_H -#define MBEDTLS_SSL_COOKIE_H - -#include "ssl.h" - -#if defined(MBEDTLS_THREADING_C) -#include "threading.h" -#endif - -/** - * \name SECTION: Module settings - * - * The configuration options you can set for this module are in this section. - * Either change them in config.h or define them on the compiler command line. - * \{ - */ -#ifndef MBEDTLS_SSL_COOKIE_TIMEOUT -#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ -#endif - -/* \} name SECTION: Module settings */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Context for the default cookie functions. - */ -typedef struct -{ - mbedtls_md_context_t hmac_ctx; /*!< context for the HMAC portion */ -#if !defined(MBEDTLS_HAVE_TIME) - unsigned long serial; /*!< serial number for expiration */ -#endif - unsigned long timeout; /*!< timeout delay, in seconds if HAVE_TIME, - or in number of tickets issued */ - -#if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; -#endif -} mbedtls_ssl_cookie_ctx; - -/** - * \brief Initialize cookie context - */ -void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ); - -/** - * \brief Setup cookie context (generate keys) - */ -int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Set expiration delay for cookies - * (Default MBEDTLS_SSL_COOKIE_TIMEOUT) - * - * \param ctx Cookie contex - * \param delay Delay, in seconds if HAVE_TIME, or in number of cookies - * issued in the meantime. - * 0 to disable expiration (NOT recommended) - */ -void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ); - -/** - * \brief Free cookie context - */ -void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ); - -/** - * \brief Generate cookie, see \c mbedtls_ssl_cookie_write_t - */ -mbedtls_ssl_cookie_write_t mbedtls_ssl_cookie_write; - -/** - * \brief Verify cookie, see \c mbedtls_ssl_cookie_write_t - */ -mbedtls_ssl_cookie_check_t mbedtls_ssl_cookie_check; - -#ifdef __cplusplus -} -#endif - -#endif /* ssl_cookie.h */ diff --git a/components/mbedtls/include/mbedtls/ssl_internal.h b/components/mbedtls/include/mbedtls/ssl_internal.h deleted file mode 100644 index 756360b181..0000000000 --- a/components/mbedtls/include/mbedtls/ssl_internal.h +++ /dev/null @@ -1,617 +0,0 @@ -/** - * \file ssl_ticket.h - * - * \brief Internal functions shared by the SSL modules - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_SSL_INTERNAL_H -#define MBEDTLS_SSL_INTERNAL_H - -#include "ssl.h" - -#if defined(MBEDTLS_MD5_C) -#include "md5.h" -#endif - -#if defined(MBEDTLS_SHA1_C) -#include "sha1.h" -#endif - -#if defined(MBEDTLS_SHA256_C) -#include "sha256.h" -#endif - -#if defined(MBEDTLS_SHA512_C) -#include "sha512.h" -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -#include "ecjpake.h" -#endif - -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -/* Determine minimum supported version */ -#define MBEDTLS_SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 - -#if defined(MBEDTLS_SSL_PROTO_SSL3) -#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1) -#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) -#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1 */ -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - -/* Determine maximum supported version */ -#define MBEDTLS_SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) -#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_2 -#else -#if defined(MBEDTLS_SSL_PROTO_TLS1) -#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_1 -#else -#if defined(MBEDTLS_SSL_PROTO_SSL3) -#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_0 -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -#define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 -#define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ -#define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ -#define MBEDTLS_SSL_RENEGOTIATION_PENDING 3 /* Requested (server only) */ - -/* - * DTLS retransmission states, see RFC 6347 4.2.4 - * - * The SENDING state is merged in PREPARING for initial sends, - * but is distinct for resends. - * - * Note: initial state is wrong for server, but is not used anyway. - */ -#define MBEDTLS_SSL_RETRANS_PREPARING 0 -#define MBEDTLS_SSL_RETRANS_SENDING 1 -#define MBEDTLS_SSL_RETRANS_WAITING 2 -#define MBEDTLS_SSL_RETRANS_FINISHED 3 - -/* - * Allow extra bytes for record, authentication and encryption overhead: - * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256) - * and allow for a maximum of 1024 of compression expansion if - * enabled. - */ -#if defined(MBEDTLS_ZLIB_SUPPORT) -#define MBEDTLS_SSL_COMPRESSION_ADD 1024 -#else -#define MBEDTLS_SSL_COMPRESSION_ADD 0 -#endif - -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_MODE_CBC) -/* Ciphersuites using HMAC */ -#if defined(MBEDTLS_SHA512_C) -#define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ -#elif defined(MBEDTLS_SHA256_C) -#define MBEDTLS_SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ -#else -#define MBEDTLS_SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ -#endif -#else -/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ -#define MBEDTLS_SSL_MAC_ADD 16 -#endif - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#define MBEDTLS_SSL_PADDING_ADD 256 -#else -#define MBEDTLS_SSL_PADDING_ADD 0 -#endif - -#define MBEDTLS_SSL_BUFFER_LEN ( MBEDTLS_SSL_MAX_CONTENT_LEN \ - + MBEDTLS_SSL_COMPRESSION_ADD \ - + 29 /* counter + header + IV */ \ - + MBEDTLS_SSL_MAC_ADD \ - + MBEDTLS_SSL_PADDING_ADD \ - ) - -/* - * TLS extension flags (for extensions with outgoing ServerHello content - * that need it (e.g. for RENEGOTIATION_INFO the server already knows because - * of state of the renegotiation flag, so no indicator is required) - */ -#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) -#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK (1 << 1) - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -/* - * Abstraction for a grid of allowed signature-hash-algorithm pairs. - */ -struct mbedtls_ssl_sig_hash_set_t -{ - /* At the moment, we only need to remember a single suitable - * hash algorithm per signature algorithm. As long as that's - * the case - and we don't need a general lookup function - - * we can implement the sig-hash-set as a map from signatures - * to hash algorithms. */ - mbedtls_md_type_t rsa; - mbedtls_md_type_t ecdsa; -}; -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ - -/* - * This structure contains the parameters only needed during handshake. - */ -struct mbedtls_ssl_handshake_params -{ - /* - * Handshake specific crypto variables - */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - mbedtls_ssl_sig_hash_set_t hash_algs; /*!< Set of suitable sig-hash pairs */ -#endif -#if defined(MBEDTLS_DHM_C) - mbedtls_dhm_context dhm_ctx; /*!< DHM key exchange */ -#endif -#if defined(MBEDTLS_ECDH_C) - mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - mbedtls_ecjpake_context ecjpake_ctx; /*!< EC J-PAKE key exchange */ -#if defined(MBEDTLS_SSL_CLI_C) - unsigned char *ecjpake_cache; /*!< Cache for ClientHello ext */ - size_t ecjpake_cache_len; /*!< Length of cached data */ -#endif -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - const mbedtls_ecp_curve_info **curves; /*!< Supported elliptic curves */ -#endif -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - unsigned char *psk; /*!< PSK from the callback */ - size_t psk_len; /*!< Length of PSK from callback */ -#endif -#if defined(MBEDTLS_X509_CRT_PARSE_C) - mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - int sni_authmode; /*!< authmode from SNI callback */ - mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ - mbedtls_x509_crt *sni_ca_chain; /*!< trusted CAs from SNI callback */ - mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ -#endif /* MBEDTLS_X509_CRT_PARSE_C */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ - unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ - - unsigned char *verify_cookie; /*!< Cli: HelloVerifyRequest cookie - Srv: unused */ - unsigned char verify_cookie_len; /*!< Cli: cookie length - Srv: flag for sending a cookie */ - - unsigned char *hs_msg; /*!< Reassembled handshake message */ - - uint32_t retransmit_timeout; /*!< Current value of timeout */ - unsigned char retransmit_state; /*!< Retransmission state */ - mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ - mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ - unsigned int in_flight_start_seq; /*!< Minimum message sequence in the - flight being received */ - mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for - resending messages */ - unsigned char alt_out_ctr[8]; /*!< Alternative record epoch/counter - for resending messages */ -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - /* - * Checksum contexts - */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_context fin_md5; - mbedtls_sha1_context fin_sha1; -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) - mbedtls_sha256_context fin_sha256; -#endif -#if defined(MBEDTLS_SHA512_C) - mbedtls_sha512_context fin_sha512; -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - - void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t); - void (*calc_verify)(mbedtls_ssl_context *, unsigned char *); - void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); - int (*tls_prf)(const unsigned char *, size_t, const char *, - const unsigned char *, size_t, - unsigned char *, size_t); - - size_t pmslen; /*!< premaster length */ - - unsigned char randbytes[64]; /*!< random bytes */ - unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; - /*!< premaster secret */ - - int resume; /*!< session resume indicator*/ - int max_major_ver; /*!< max. major version client*/ - int max_minor_ver; /*!< max. minor version client*/ - int cli_exts; /*!< client extension presence*/ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - int new_session_ticket; /*!< use NewSessionTicket? */ -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - int extended_ms; /*!< use Extended Master Secret? */ -#endif -}; - -/* - * This structure contains a full set of runtime transform parameters - * either in negotiation or active. - */ -struct mbedtls_ssl_transform -{ - /* - * Session specific crypto layer - */ - const mbedtls_ssl_ciphersuite_t *ciphersuite_info; - /*!< Chosen cipersuite_info */ - unsigned int keylen; /*!< symmetric key length (bytes) */ - size_t minlen; /*!< min. ciphertext length */ - size_t ivlen; /*!< IV length */ - size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ - size_t maclen; /*!< MAC length */ - - unsigned char iv_enc[16]; /*!< IV (encryption) */ - unsigned char iv_dec[16]; /*!< IV (decryption) */ - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - /* Needed only for SSL v3.0 secret */ - unsigned char mac_enc[20]; /*!< SSL v3.0 secret (enc) */ - unsigned char mac_dec[20]; /*!< SSL v3.0 secret (dec) */ -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - - mbedtls_md_context_t md_ctx_enc; /*!< MAC (encryption) */ - mbedtls_md_context_t md_ctx_dec; /*!< MAC (decryption) */ - - mbedtls_cipher_context_t cipher_ctx_enc; /*!< encryption context */ - mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */ - - /* - * Session specific compression layer - */ -#if defined(MBEDTLS_ZLIB_SUPPORT) - z_stream ctx_deflate; /*!< compression context */ - z_stream ctx_inflate; /*!< decompression context */ -#endif -}; - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/* - * List of certificate + private key pairs - */ -struct mbedtls_ssl_key_cert -{ - mbedtls_x509_crt *cert; /*!< cert */ - mbedtls_pk_context *key; /*!< private key */ - mbedtls_ssl_key_cert *next; /*!< next key/cert pair */ -}; -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -/* - * List of handshake messages kept around for resending - */ -struct mbedtls_ssl_flight_item -{ - unsigned char *p; /*!< message, including handshake headers */ - size_t len; /*!< length of p */ - unsigned char type; /*!< type of the message: handshake or CCS */ - mbedtls_ssl_flight_item *next; /*!< next handshake message(s) */ -}; -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - -/* Find an entry in a signature-hash set matching a given hash algorithm. */ -mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, - mbedtls_pk_type_t sig_alg ); -/* Add a signature-hash-pair to a signature-hash set */ -void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, - mbedtls_pk_type_t sig_alg, - mbedtls_md_type_t md_alg ); -/* Allow exactly one hash algorithm for each signature. */ -void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, - mbedtls_md_type_t md_alg ); - -/* Setup an empty signature-hash set */ -static inline void mbedtls_ssl_sig_hash_set_init( mbedtls_ssl_sig_hash_set_t *set ) -{ - mbedtls_ssl_sig_hash_set_const_hash( set, MBEDTLS_MD_NONE ); -} - -#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ - -/** - * \brief Free referenced items in an SSL transform context and clear - * memory - * - * \param transform SSL transform context - */ -void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ); - -/** - * \brief Free referenced items in an SSL handshake context and clear - * memory - * - * \param handshake SSL handshake context - */ -void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ); - -int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ); -void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ); - -int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ); - -void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ); - -int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ); -void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ); - -/** - * \brief Update record layer - * - * This function roughly separates the implementation - * of the logic of (D)TLS from the implementation - * of the secure transport. - * - * \param ssl SSL context to use - * - * \return 0 or non-zero error code. - * - * \note A clarification on what is called 'record layer' here - * is in order, as many sensible definitions are possible: - * - * The record layer takes as input an untrusted underlying - * transport (stream or datagram) and transforms it into - * a serially multiplexed, secure transport, which - * conceptually provides the following: - * - * (1) Three datagram based, content-agnostic transports - * for handshake, alert and CCS messages. - * (2) One stream- or datagram-based transport - * for application data. - * (3) Functionality for changing the underlying transform - * securing the contents. - * - * The interface to this functionality is given as follows: - * - * a Updating - * [Currently implemented by mbedtls_ssl_read_record] - * - * Check if and on which of the four 'ports' data is pending: - * Nothing, a controlling datagram of type (1), or application - * data (2). In any case data is present, internal buffers - * provide access to the data for the user to process it. - * Consumption of type (1) datagrams is done automatically - * on the next update, invalidating that the internal buffers - * for previous datagrams, while consumption of application - * data (2) is user-controlled. - * - * b Reading of application data - * [Currently manual adaption of ssl->in_offt pointer] - * - * As mentioned in the last paragraph, consumption of data - * is different from the automatic consumption of control - * datagrams (1) because application data is treated as a stream. - * - * c Tracking availability of application data - * [Currently manually through decreasing ssl->in_msglen] - * - * For efficiency and to retain datagram semantics for - * application data in case of DTLS, the record layer - * provides functionality for checking how much application - * data is still available in the internal buffer. - * - * d Changing the transformation securing the communication. - * - * Given an opaque implementation of the record layer in the - * above sense, it should be possible to implement the logic - * of (D)TLS on top of it without the need to know anything - * about the record layer's internals. This is done e.g. - * in all the handshake handling functions, and in the - * application data reading function mbedtls_ssl_read. - * - * \note The above tries to give a conceptual picture of the - * record layer, but the current implementation deviates - * from it in some places. For example, our implementation of - * the update functionality through mbedtls_ssl_read_record - * discards datagrams depending on the current state, which - * wouldn't fall under the record layer's responsibility - * following the above definition. - * - */ -int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ); - -int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ); - -int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ); - -int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ); - -int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ); - -void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, - const mbedtls_ssl_ciphersuite_t *ciphersuite_info ); - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ); -#endif - -#if defined(MBEDTLS_PK_C) -unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ); -unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ); -mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ); -#endif - -mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ); -unsigned char mbedtls_ssl_hash_from_md_alg( int md ); -int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ); - -#if defined(MBEDTLS_ECP_C) -int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ); -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, - mbedtls_md_type_t md ); -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -static inline mbedtls_pk_context *mbedtls_ssl_own_key( mbedtls_ssl_context *ssl ) -{ - mbedtls_ssl_key_cert *key_cert; - - if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) - key_cert = ssl->handshake->key_cert; - else - key_cert = ssl->conf->key_cert; - - return( key_cert == NULL ? NULL : key_cert->key ); -} - -static inline mbedtls_x509_crt *mbedtls_ssl_own_cert( mbedtls_ssl_context *ssl ) -{ - mbedtls_ssl_key_cert *key_cert; - - if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) - key_cert = ssl->handshake->key_cert; - else - key_cert = ssl->conf->key_cert; - - return( key_cert == NULL ? NULL : key_cert->cert ); -} - -/* - * Check usage of a certificate wrt extensions: - * keyUsage, extendedKeyUsage (later), and nSCertType (later). - * - * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we - * check a cert we received from them)! - * - * Return 0 if everything is OK, -1 if not. - */ -int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, - const mbedtls_ssl_ciphersuite_t *ciphersuite, - int cert_endpoint, - uint32_t *flags ); -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -void mbedtls_ssl_write_version( int major, int minor, int transport, - unsigned char ver[2] ); -void mbedtls_ssl_read_version( int *major, int *minor, int transport, - const unsigned char ver[2] ); - -static inline size_t mbedtls_ssl_hdr_len( const mbedtls_ssl_context *ssl ) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( 13 ); -#else - ((void) ssl); -#endif - return( 5 ); -} - -static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl ) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( 12 ); -#else - ((void) ssl); -#endif - return( 4 ); -} - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ); -void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ); -int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ); -#endif - -/* Visible for testing purposes only */ -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl ); -void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ); -#endif - -/* constant-time buffer comparison */ -static inline int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t n ) -{ - size_t i; - const unsigned char *A = (const unsigned char *) a; - const unsigned char *B = (const unsigned char *) b; - unsigned char diff = 0; - - for( i = 0; i < n; i++ ) - diff |= A[i] ^ B[i]; - - return( diff ); -} - -#ifdef __cplusplus -} -#endif - -#endif /* ssl_internal.h */ diff --git a/components/mbedtls/include/mbedtls/ssl_ticket.h b/components/mbedtls/include/mbedtls/ssl_ticket.h deleted file mode 100644 index 7c6bc61bfb..0000000000 --- a/components/mbedtls/include/mbedtls/ssl_ticket.h +++ /dev/null @@ -1,135 +0,0 @@ -/** - * \file ssl_ticket.h - * - * \brief TLS server ticket callbacks implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_SSL_TICKET_H -#define MBEDTLS_SSL_TICKET_H - -/* - * This implementation of the session ticket callbacks includes key - * management, rotating the keys periodically in order to preserve forward - * secrecy, when MBEDTLS_HAVE_TIME is defined. - */ - -#include "ssl.h" -#include "cipher.h" - -#if defined(MBEDTLS_THREADING_C) -#include "threading.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Information for session ticket protection - */ -typedef struct -{ - unsigned char name[4]; /*!< random key identifier */ - uint32_t generation_time; /*!< key generation timestamp (seconds) */ - mbedtls_cipher_context_t ctx; /*!< context for auth enc/decryption */ -} -mbedtls_ssl_ticket_key; - -/** - * \brief Context for session ticket handling functions - */ -typedef struct -{ - mbedtls_ssl_ticket_key keys[2]; /*!< ticket protection keys */ - unsigned char active; /*!< index of the currently active key */ - - uint32_t ticket_lifetime; /*!< lifetime of tickets in seconds */ - - /** Callback for getting (pseudo-)random numbers */ - int (*f_rng)(void *, unsigned char *, size_t); - void *p_rng; /*!< context for the RNG function */ - -#if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; -#endif -} -mbedtls_ssl_ticket_context; - -/** - * \brief Initialize a ticket context. - * (Just make it ready for mbedtls_ssl_ticket_setup() - * or mbedtls_ssl_ticket_free().) - * - * \param ctx Context to be initialized - */ -void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ); - -/** - * \brief Prepare context to be actually used - * - * \param ctx Context to be set up - * \param f_rng RNG callback function - * \param p_rng RNG callback context - * \param cipher AEAD cipher to use for ticket protection. - * Recommended value: MBEDTLS_CIPHER_AES_256_GCM. - * \param lifetime Tickets lifetime in seconds - * Recommended value: 86400 (one day). - * - * \note It is highly recommended to select a cipher that is at - * least as strong as the the strongest ciphersuite - * supported. Usually that means a 256-bit key. - * - * \note The lifetime of the keys is twice the lifetime of tickets. - * It is recommended to pick a reasonnable lifetime so as not - * to negate the benefits of forward secrecy. - * - * \return 0 if successful, - * or a specific MBEDTLS_ERR_XXX error code - */ -int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - mbedtls_cipher_type_t cipher, - uint32_t lifetime ); - -/** - * \brief Implementation of the ticket write callback - * - * \note See \c mbedlts_ssl_ticket_write_t for description - */ -mbedtls_ssl_ticket_write_t mbedtls_ssl_ticket_write; - -/** - * \brief Implementation of the ticket parse callback - * - * \note See \c mbedlts_ssl_ticket_parse_t for description - */ -mbedtls_ssl_ticket_parse_t mbedtls_ssl_ticket_parse; - -/** - * \brief Free a context's content and zeroize it. - * - * \param ctx Context to be cleaned up - */ -void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ); - -#ifdef __cplusplus -} -#endif - -#endif /* ssl_ticket.h */ diff --git a/components/mbedtls/include/mbedtls/threading.h b/components/mbedtls/include/mbedtls/threading.h deleted file mode 100644 index b0c34ecc74..0000000000 --- a/components/mbedtls/include/mbedtls/threading.h +++ /dev/null @@ -1,106 +0,0 @@ -/** - * \file threading.h - * - * \brief Threading abstraction layer - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_THREADING_H -#define MBEDTLS_THREADING_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A /**< The selected feature is not available. */ -#define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C /**< Bad input parameters to function. */ -#define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E /**< Locking / unlocking / free failed with error code. */ - -#if defined(MBEDTLS_THREADING_PTHREAD) -#include -typedef struct -{ - pthread_mutex_t mutex; - char is_valid; -} mbedtls_threading_mutex_t; -#endif - -#if defined(MBEDTLS_THREADING_ALT) -/* You should define the mbedtls_threading_mutex_t type in your header */ -#include "threading_alt.h" - -/** - * \brief Set your alternate threading implementation function - * pointers and initialize global mutexes. If used, this - * function must be called once in the main thread before any - * other mbed TLS function is called, and - * mbedtls_threading_free_alt() must be called once in the main - * thread after all other mbed TLS functions. - * - * \note mutex_init() and mutex_free() don't return a status code. - * If mutex_init() fails, it should leave its argument (the - * mutex) in a state such that mutex_lock() will fail when - * called with this argument. - * - * \param mutex_init the init function implementation - * \param mutex_free the free function implementation - * \param mutex_lock the lock function implementation - * \param mutex_unlock the unlock function implementation - */ -void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), - void (*mutex_free)( mbedtls_threading_mutex_t * ), - int (*mutex_lock)( mbedtls_threading_mutex_t * ), - int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ); - -/** - * \brief Free global mutexes. - */ -void mbedtls_threading_free_alt( void ); -#endif /* MBEDTLS_THREADING_ALT */ - -#if defined(MBEDTLS_THREADING_C) -/* - * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock - * - * All these functions are expected to work or the result will be undefined. - */ -extern void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t *mutex ); -extern void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t *mutex ); -extern int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t *mutex ); -extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex ); - -/* - * Global mutexes - */ -extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; -extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; -#endif /* MBEDTLS_THREADING_C */ - -#ifdef __cplusplus -} -#endif - -#endif /* threading.h */ diff --git a/components/mbedtls/include/mbedtls/timing.h b/components/mbedtls/include/mbedtls/timing.h deleted file mode 100644 index ae7a713e7a..0000000000 --- a/components/mbedtls/include/mbedtls/timing.h +++ /dev/null @@ -1,141 +0,0 @@ -/** - * \file timing.h - * - * \brief Portable interface to the CPU cycle counter - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_TIMING_H -#define MBEDTLS_TIMING_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if !defined(MBEDTLS_TIMING_ALT) -// Regular implementation -// - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief timer structure - */ -struct mbedtls_timing_hr_time -{ - unsigned char opaque[32]; -}; - -/** - * \brief Context for mbedtls_timing_set/get_delay() - */ -typedef struct -{ - struct mbedtls_timing_hr_time timer; - uint32_t int_ms; - uint32_t fin_ms; -} mbedtls_timing_delay_context; - -extern volatile int mbedtls_timing_alarmed; - -/** - * \brief Return the CPU cycle counter value - * - * \warning This is only a best effort! Do not rely on this! - * In particular, it is known to be unreliable on virtual - * machines. - */ -unsigned long mbedtls_timing_hardclock( void ); - -/** - * \brief Return the elapsed time in milliseconds - * - * \param val points to a timer structure - * \param reset if set to 1, the timer is restarted - */ -unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ); - -/** - * \brief Setup an alarm clock - * - * \param seconds delay before the "mbedtls_timing_alarmed" flag is set - * - * \warning Only one alarm at a time is supported. In a threaded - * context, this means one for the whole process, not one per - * thread. - */ -void mbedtls_set_alarm( int seconds ); - -/** - * \brief Set a pair of delays to watch - * (See \c mbedtls_timing_get_delay().) - * - * \param data Pointer to timing data - * Must point to a valid \c mbedtls_timing_delay_context struct. - * \param int_ms First (intermediate) delay in milliseconds. - * \param fin_ms Second (final) delay in milliseconds. - * Pass 0 to cancel the current delay. - */ -void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); - -/** - * \brief Get the status of delays - * (Memory helper: number of delays passed.) - * - * \param data Pointer to timing data - * Must point to a valid \c mbedtls_timing_delay_context struct. - * - * \return -1 if cancelled (fin_ms = 0) - * 0 if none of the delays are passed, - * 1 if only the intermediate delay is passed, - * 2 if the final delay is passed. - */ -int mbedtls_timing_get_delay( void *data ); - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_TIMING_ALT */ -#include "timing_alt.h" -#endif /* MBEDTLS_TIMING_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(MBEDTLS_SELF_TEST) -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if a test failed - */ -int mbedtls_timing_self_test( int verbose ); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* timing.h */ diff --git a/components/mbedtls/include/mbedtls/version.h b/components/mbedtls/include/mbedtls/version.h deleted file mode 100644 index 3b209a6b07..0000000000 --- a/components/mbedtls/include/mbedtls/version.h +++ /dev/null @@ -1,111 +0,0 @@ -/** - * \file version.h - * - * \brief Run-time version information - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * This set of compile-time defines and run-time variables can be used to - * determine the version number of the mbed TLS library used. - */ -#ifndef MBEDTLS_VERSION_H -#define MBEDTLS_VERSION_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -/** - * The version number x.y.z is split into three parts. - * Major, Minor, Patchlevel - */ -#define MBEDTLS_VERSION_MAJOR 2 -#define MBEDTLS_VERSION_MINOR 6 -#define MBEDTLS_VERSION_PATCH 0 - -/** - * The single version number has the following structure: - * MMNNPP00 - * Major version | Minor version | Patch version - */ -#define MBEDTLS_VERSION_NUMBER 0x02060000 -#define MBEDTLS_VERSION_STRING "2.6.0" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.6.0" - -#if defined(MBEDTLS_VERSION_C) - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Get the version number. - * - * \return The constructed version number in the format - * MMNNPP00 (Major, Minor, Patch). - */ -unsigned int mbedtls_version_get_number( void ); - -/** - * Get the version string ("x.y.z"). - * - * \param string The string that will receive the value. - * (Should be at least 9 bytes in size) - */ -void mbedtls_version_get_string( char *string ); - -/** - * Get the full version string ("mbed TLS x.y.z"). - * - * \param string The string that will receive the value. The mbed TLS version - * string will use 18 bytes AT MOST including a terminating - * null byte. - * (So the buffer should be at least 18 bytes to receive this - * version string). - */ -void mbedtls_version_get_string_full( char *string ); - -/** - * \brief Check if support for a feature was compiled into this - * mbed TLS binary. This allows you to see at runtime if the - * library was for instance compiled with or without - * Multi-threading support. - * - * \note only checks against defines in the sections "System - * support", "mbed TLS modules" and "mbed TLS feature - * support" in config.h - * - * \param feature The string for the define to check (e.g. "MBEDTLS_AES_C") - * - * \return 0 if the feature is present, - * -1 if the feature is not present and - * -2 if support for feature checking as a whole was not - * compiled in. - */ -int mbedtls_version_check_feature( const char *feature ); - -#ifdef __cplusplus -} -#endif - -#endif /* MBEDTLS_VERSION_C */ - -#endif /* version.h */ diff --git a/components/mbedtls/include/mbedtls/x509.h b/components/mbedtls/include/mbedtls/x509.h deleted file mode 100644 index d7e318dfdc..0000000000 --- a/components/mbedtls/include/mbedtls/x509.h +++ /dev/null @@ -1,332 +0,0 @@ -/** - * \file x509.h - * - * \brief X.509 generic defines and structures - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_X509_H -#define MBEDTLS_X509_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "asn1.h" -#include "pk.h" - -#if defined(MBEDTLS_RSA_C) -#include "rsa.h" -#endif - -/** - * \addtogroup x509_module - * \{ - */ - -#if !defined(MBEDTLS_X509_MAX_INTERMEDIATE_CA) -/** - * Maximum number of intermediate CAs in a verification chain. - * That is, maximum length of the chain, excluding the end-entity certificate - * and the trusted root certificate. - * - * Set this to a low value to prevent an adversary from making you waste - * resources verifying an overlong certificate chain. - */ -#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 -#endif - -/** - * \name X509 Error codes - * \{ - */ -#define MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE -0x2080 /**< Unavailable feature, e.g. RSA hashing/encryption combination. */ -#define MBEDTLS_ERR_X509_UNKNOWN_OID -0x2100 /**< Requested OID is unknown. */ -#define MBEDTLS_ERR_X509_INVALID_FORMAT -0x2180 /**< The CRT/CRL/CSR format is invalid, e.g. different type expected. */ -#define MBEDTLS_ERR_X509_INVALID_VERSION -0x2200 /**< The CRT/CRL/CSR version element is invalid. */ -#define MBEDTLS_ERR_X509_INVALID_SERIAL -0x2280 /**< The serial tag or value is invalid. */ -#define MBEDTLS_ERR_X509_INVALID_ALG -0x2300 /**< The algorithm tag or value is invalid. */ -#define MBEDTLS_ERR_X509_INVALID_NAME -0x2380 /**< The name tag or value is invalid. */ -#define MBEDTLS_ERR_X509_INVALID_DATE -0x2400 /**< The date tag or value is invalid. */ -#define MBEDTLS_ERR_X509_INVALID_SIGNATURE -0x2480 /**< The signature tag or value invalid. */ -#define MBEDTLS_ERR_X509_INVALID_EXTENSIONS -0x2500 /**< The extension tag or value is invalid. */ -#define MBEDTLS_ERR_X509_UNKNOWN_VERSION -0x2580 /**< CRT/CRL/CSR has an unsupported version number. */ -#define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG -0x2600 /**< Signature algorithm (oid) is unsupported. */ -#define MBEDTLS_ERR_X509_SIG_MISMATCH -0x2680 /**< Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) */ -#define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED -0x2700 /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */ -#define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT -0x2780 /**< Format not recognized as DER or PEM. */ -#define MBEDTLS_ERR_X509_BAD_INPUT_DATA -0x2800 /**< Input invalid. */ -#define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 /**< Allocation of memory failed. */ -#define MBEDTLS_ERR_X509_FILE_IO_ERROR -0x2900 /**< Read/write of file failed. */ -#define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 /**< Destination buffer is too small. */ -#define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000 /**< A fatal error occured, eg the chain is too long or the vrfy callback failed. */ -/* \} name */ - -/** - * \name X509 Verify codes - * \{ - */ -/* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */ -#define MBEDTLS_X509_BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ -#define MBEDTLS_X509_BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ -#define MBEDTLS_X509_BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ -#define MBEDTLS_X509_BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ -#define MBEDTLS_X509_BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ -#define MBEDTLS_X509_BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ -#define MBEDTLS_X509_BADCERT_MISSING 0x40 /**< Certificate was missing. */ -#define MBEDTLS_X509_BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ -#define MBEDTLS_X509_BADCERT_OTHER 0x0100 /**< Other reason (can be used by verify callback) */ -#define MBEDTLS_X509_BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ -#define MBEDTLS_X509_BADCRL_FUTURE 0x0400 /**< The CRL is from the future */ -#define MBEDTLS_X509_BADCERT_KEY_USAGE 0x0800 /**< Usage does not match the keyUsage extension. */ -#define MBEDTLS_X509_BADCERT_EXT_KEY_USAGE 0x1000 /**< Usage does not match the extendedKeyUsage extension. */ -#define MBEDTLS_X509_BADCERT_NS_CERT_TYPE 0x2000 /**< Usage does not match the nsCertType extension. */ -#define MBEDTLS_X509_BADCERT_BAD_MD 0x4000 /**< The certificate is signed with an unacceptable hash. */ -#define MBEDTLS_X509_BADCERT_BAD_PK 0x8000 /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ -#define MBEDTLS_X509_BADCERT_BAD_KEY 0x010000 /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */ -#define MBEDTLS_X509_BADCRL_BAD_MD 0x020000 /**< The CRL is signed with an unacceptable hash. */ -#define MBEDTLS_X509_BADCRL_BAD_PK 0x040000 /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ -#define MBEDTLS_X509_BADCRL_BAD_KEY 0x080000 /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */ - -/* \} name */ -/* \} addtogroup x509_module */ - -/* - * X.509 v3 Key Usage Extension flags - * Reminder: update x509_info_key_usage() when adding new flags. - */ -#define MBEDTLS_X509_KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ -#define MBEDTLS_X509_KU_NON_REPUDIATION (0x40) /* bit 1 */ -#define MBEDTLS_X509_KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */ -#define MBEDTLS_X509_KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */ -#define MBEDTLS_X509_KU_KEY_AGREEMENT (0x08) /* bit 4 */ -#define MBEDTLS_X509_KU_KEY_CERT_SIGN (0x04) /* bit 5 */ -#define MBEDTLS_X509_KU_CRL_SIGN (0x02) /* bit 6 */ -#define MBEDTLS_X509_KU_ENCIPHER_ONLY (0x01) /* bit 7 */ -#define MBEDTLS_X509_KU_DECIPHER_ONLY (0x8000) /* bit 8 */ - -/* - * Netscape certificate types - * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html) - */ - -#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */ -#define MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ -#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ -#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */ -#define MBEDTLS_X509_NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */ -#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */ -#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */ -#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */ - -/* - * X.509 extension types - * - * Comments refer to the status for using certificates. Status can be - * different for writing certificates or reading CRLs or CSRs. - */ -#define MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) -#define MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) -#define MBEDTLS_X509_EXT_KEY_USAGE (1 << 2) -#define MBEDTLS_X509_EXT_CERTIFICATE_POLICIES (1 << 3) -#define MBEDTLS_X509_EXT_POLICY_MAPPINGS (1 << 4) -#define MBEDTLS_X509_EXT_SUBJECT_ALT_NAME (1 << 5) /* Supported (DNS) */ -#define MBEDTLS_X509_EXT_ISSUER_ALT_NAME (1 << 6) -#define MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) -#define MBEDTLS_X509_EXT_BASIC_CONSTRAINTS (1 << 8) /* Supported */ -#define MBEDTLS_X509_EXT_NAME_CONSTRAINTS (1 << 9) -#define MBEDTLS_X509_EXT_POLICY_CONSTRAINTS (1 << 10) -#define MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) -#define MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) -#define MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) -#define MBEDTLS_X509_EXT_FRESHEST_CRL (1 << 14) - -#define MBEDTLS_X509_EXT_NS_CERT_TYPE (1 << 16) - -/* - * Storage format identifiers - * Recognized formats: PEM and DER - */ -#define MBEDTLS_X509_FORMAT_DER 1 -#define MBEDTLS_X509_FORMAT_PEM 2 - -#define MBEDTLS_X509_MAX_DN_NAME_SIZE 256 /**< Maximum value size of a DN entry */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \addtogroup x509_module - * \{ */ - -/** - * \name Structures for parsing X.509 certificates, CRLs and CSRs - * \{ - */ - -/** - * Type-length-value structure that allows for ASN1 using DER. - */ -typedef mbedtls_asn1_buf mbedtls_x509_buf; - -/** - * Container for ASN1 bit strings. - */ -typedef mbedtls_asn1_bitstring mbedtls_x509_bitstring; - -/** - * Container for ASN1 named information objects. - * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). - */ -typedef mbedtls_asn1_named_data mbedtls_x509_name; - -/** - * Container for a sequence of ASN.1 items - */ -typedef mbedtls_asn1_sequence mbedtls_x509_sequence; - -/** Container for date and time (precision in seconds). */ -typedef struct mbedtls_x509_time -{ - int year, mon, day; /**< Date. */ - int hour, min, sec; /**< Time. */ -} -mbedtls_x509_time; - -/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ -/** \} addtogroup x509_module */ - -/** - * \brief Store the certificate DN in printable form into buf; - * no more than size characters will be written. - * - * \param buf Buffer to write to - * \param size Maximum size of buffer - * \param dn The X509 name to represent - * - * \return The length of the string written (not including the - * terminated nul byte), or a negative error code. - */ -int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ); - -/** - * \brief Store the certificate serial in printable form into buf; - * no more than size characters will be written. - * - * \param buf Buffer to write to - * \param size Maximum size of buffer - * \param serial The X509 serial to represent - * - * \return The length of the string written (not including the - * terminated nul byte), or a negative error code. - */ -int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ); - -/** - * \brief Check a given mbedtls_x509_time against the system time - * and tell if it's in the past. - * - * \note Intended usage is "if( is_past( valid_to ) ) ERROR". - * Hence the return value of 1 if on internal errors. - * - * \param to mbedtls_x509_time to check - * - * \return 1 if the given time is in the past or an error occured, - * 0 otherwise. - */ -int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ); - -/** - * \brief Check a given mbedtls_x509_time against the system time - * and tell if it's in the future. - * - * \note Intended usage is "if( is_future( valid_from ) ) ERROR". - * Hence the return value of 1 if on internal errors. - * - * \param from mbedtls_x509_time to check - * - * \return 1 if the given time is in the future or an error occured, - * 0 otherwise. - */ -int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_x509_self_test( int verbose ); - -/* - * Internal module functions. You probably do not want to use these unless you - * know you do. - */ -int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, - mbedtls_x509_name *cur ); -int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *alg ); -int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *alg, mbedtls_x509_buf *params ); -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) -int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, - mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, - int *salt_len ); -#endif -int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ); -int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, - mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, - void **sig_opts ); -int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, - mbedtls_x509_time *t ); -int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *serial ); -int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *ext, int tag ); -int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, - mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, - const void *sig_opts ); -int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ); -int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ); -int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, - int critical, const unsigned char *val, - size_t val_len ); -int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, - mbedtls_asn1_named_data *first ); -int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, - mbedtls_asn1_named_data *first ); -int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len, - unsigned char *sig, size_t size ); - -#define MBEDTLS_X509_SAFE_SNPRINTF \ - do { \ - if( ret < 0 || (size_t) ret >= n ) \ - return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); \ - \ - n -= (size_t) ret; \ - p += (size_t) ret; \ - } while( 0 ) - -#ifdef __cplusplus -} -#endif - -#endif /* x509.h */ diff --git a/components/mbedtls/include/mbedtls/x509_crl.h b/components/mbedtls/include/mbedtls/x509_crl.h deleted file mode 100644 index 7988439900..0000000000 --- a/components/mbedtls/include/mbedtls/x509_crl.h +++ /dev/null @@ -1,173 +0,0 @@ -/** - * \file x509_crl.h - * - * \brief X.509 certificate revocation list parsing - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_X509_CRL_H -#define MBEDTLS_X509_CRL_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "x509.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \addtogroup x509_module - * \{ */ - -/** - * \name Structures and functions for parsing CRLs - * \{ - */ - -/** - * Certificate revocation list entry. - * Contains the CA-specific serial numbers and revocation dates. - */ -typedef struct mbedtls_x509_crl_entry -{ - mbedtls_x509_buf raw; - - mbedtls_x509_buf serial; - - mbedtls_x509_time revocation_date; - - mbedtls_x509_buf entry_ext; - - struct mbedtls_x509_crl_entry *next; -} -mbedtls_x509_crl_entry; - -/** - * Certificate revocation list structure. - * Every CRL may have multiple entries. - */ -typedef struct mbedtls_x509_crl -{ - mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ - mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ - - int version; /**< CRL version (1=v1, 2=v2) */ - mbedtls_x509_buf sig_oid; /**< CRL signature type identifier */ - - mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). */ - - mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ - - mbedtls_x509_time this_update; - mbedtls_x509_time next_update; - - mbedtls_x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */ - - mbedtls_x509_buf crl_ext; - - mbedtls_x509_buf sig_oid2; - mbedtls_x509_buf sig; - mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ - mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ - void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ - - struct mbedtls_x509_crl *next; -} -mbedtls_x509_crl; - -/** - * \brief Parse a DER-encoded CRL and append it to the chained list - * - * \param chain points to the start of the chain - * \param buf buffer holding the CRL data in DER format - * \param buflen size of the buffer - * (including the terminating null byte for PEM data) - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, - const unsigned char *buf, size_t buflen ); -/** - * \brief Parse one or more CRLs and append them to the chained list - * - * \note Mutliple CRLs are accepted only if using PEM format - * - * \param chain points to the start of the chain - * \param buf buffer holding the CRL data in PEM or DER format - * \param buflen size of the buffer - * (including the terminating null byte for PEM data) - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ); - -#if defined(MBEDTLS_FS_IO) -/** - * \brief Load one or more CRLs and append them to the chained list - * - * \note Mutliple CRLs are accepted only if using PEM format - * - * \param chain points to the start of the chain - * \param path filename to read the CRLs from (in PEM or DER encoding) - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ); -#endif /* MBEDTLS_FS_IO */ - -/** - * \brief Returns an informational string about the CRL. - * - * \param buf Buffer to write to - * \param size Maximum size of buffer - * \param prefix A line prefix - * \param crl The X509 CRL to represent - * - * \return The length of the string written (not including the - * terminated nul byte), or a negative error code. - */ -int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, - const mbedtls_x509_crl *crl ); - -/** - * \brief Initialize a CRL (chain) - * - * \param crl CRL chain to initialize - */ -void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ); - -/** - * \brief Unallocate all CRL data - * - * \param crl CRL chain to free - */ -void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ); - -/* \} name */ -/* \} addtogroup x509_module */ - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_x509_crl.h */ diff --git a/components/mbedtls/include/mbedtls/x509_crt.h b/components/mbedtls/include/mbedtls/x509_crt.h deleted file mode 100644 index 06166d8b18..0000000000 --- a/components/mbedtls/include/mbedtls/x509_crt.h +++ /dev/null @@ -1,661 +0,0 @@ -/** - * \file x509_crt.h - * - * \brief X.509 certificate parsing and writing - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_X509_CRT_H -#define MBEDTLS_X509_CRT_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "x509.h" -#include "x509_crl.h" - -/** - * \addtogroup x509_module - * \{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \name Structures and functions for parsing and writing X.509 certificates - * \{ - */ - -/** - * Container for an X.509 certificate. The certificate may be chained. - */ -typedef struct mbedtls_x509_crt -{ - mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ - mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ - - int version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */ - mbedtls_x509_buf serial; /**< Unique id for certificate issued by a specific CA. */ - mbedtls_x509_buf sig_oid; /**< Signature algorithm, e.g. sha1RSA */ - - mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */ - mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */ - - mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ - mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ - - mbedtls_x509_time valid_from; /**< Start time of certificate validity. */ - mbedtls_x509_time valid_to; /**< End time of certificate validity. */ - - mbedtls_pk_context pk; /**< Container for the public key context. */ - - mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ - mbedtls_x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ - mbedtls_x509_buf v3_ext; /**< Optional X.509 v3 extensions. */ - mbedtls_x509_sequence subject_alt_names; /**< Optional list of Subject Alternative Names (Only dNSName supported). */ - - int ext_types; /**< Bit string containing detected and parsed extensions */ - int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ - int max_pathlen; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ - - unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */ - - mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ - - unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ - - mbedtls_x509_buf sig; /**< Signature: hash of the tbs part signed with the private key. */ - mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ - mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ - void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ - - struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */ -} -mbedtls_x509_crt; - -/** - * Build flag from an algorithm/curve identifier (pk, md, ecp) - * Since 0 is always XXX_NONE, ignore it. - */ -#define MBEDTLS_X509_ID_FLAG( id ) ( 1 << ( id - 1 ) ) - -/** - * Security profile for certificate verification. - * - * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). - */ -typedef struct -{ - uint32_t allowed_mds; /**< MDs for signatures */ - uint32_t allowed_pks; /**< PK algs for signatures */ - uint32_t allowed_curves; /**< Elliptic curves for ECDSA */ - uint32_t rsa_min_bitlen; /**< Minimum size for RSA keys */ -} -mbedtls_x509_crt_profile; - -#define MBEDTLS_X509_CRT_VERSION_1 0 -#define MBEDTLS_X509_CRT_VERSION_2 1 -#define MBEDTLS_X509_CRT_VERSION_3 2 - -#define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 32 -#define MBEDTLS_X509_RFC5280_UTC_TIME_LEN 15 - -#if !defined( MBEDTLS_X509_MAX_FILE_PATH_LEN ) -#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 -#endif - -/** - * Container for writing a certificate (CRT) - */ -typedef struct mbedtls_x509write_cert -{ - int version; - mbedtls_mpi serial; - mbedtls_pk_context *subject_key; - mbedtls_pk_context *issuer_key; - mbedtls_asn1_named_data *subject; - mbedtls_asn1_named_data *issuer; - mbedtls_md_type_t md_alg; - char not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; - char not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; - mbedtls_asn1_named_data *extensions; -} -mbedtls_x509write_cert; - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/** - * Default security profile. Should provide a good balance between security - * and compatibility with current deployments. - */ -extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default; - -/** - * Expected next default profile. Recommended for new deployments. - * Currently targets a 128-bit security level, except for RSA-2048. - */ -extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next; - -/** - * NSA Suite B profile. - */ -extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb; - -/** - * \brief Parse a single DER formatted certificate and add it - * to the chained list. - * - * \param chain points to the start of the chain - * \param buf buffer holding the certificate DER data - * \param buflen size of the buffer - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf, - size_t buflen ); - -/** - * \brief Parse one or more certificates and add them - * to the chained list. Parses permissively. If some - * certificates can be parsed, the result is the number - * of failed certificates it encountered. If none complete - * correctly, the first error is returned. - * - * \param chain points to the start of the chain - * \param buf buffer holding the certificate data in PEM or DER format - * \param buflen size of the buffer - * (including the terminating null byte for PEM data) - * - * \return 0 if all certificates parsed successfully, a positive number - * if partly successful or a specific X509 or PEM error code - */ -int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); - -#if defined(MBEDTLS_FS_IO) -/** - * \brief Load one or more certificates and add them - * to the chained list. Parses permissively. If some - * certificates can be parsed, the result is the number - * of failed certificates it encountered. If none complete - * correctly, the first error is returned. - * - * \param chain points to the start of the chain - * \param path filename to read the certificates from - * - * \return 0 if all certificates parsed successfully, a positive number - * if partly successful or a specific X509 or PEM error code - */ -int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ); - -/** - * \brief Load one or more certificate files from a path and add them - * to the chained list. Parses permissively. If some - * certificates can be parsed, the result is the number - * of failed certificates it encountered. If none complete - * correctly, the first error is returned. - * - * \param chain points to the start of the chain - * \param path directory / folder to read the certificate files from - * - * \return 0 if all certificates parsed successfully, a positive number - * if partly successful or a specific X509 or PEM error code - */ -int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ); -#endif /* MBEDTLS_FS_IO */ - -/** - * \brief Returns an informational string about the - * certificate. - * - * \param buf Buffer to write to - * \param size Maximum size of buffer - * \param prefix A line prefix - * \param crt The X509 certificate to represent - * - * \return The length of the string written (not including the - * terminated nul byte), or a negative error code. - */ -int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, - const mbedtls_x509_crt *crt ); - -/** - * \brief Returns an informational string about the - * verification status of a certificate. - * - * \param buf Buffer to write to - * \param size Maximum size of buffer - * \param prefix A line prefix - * \param flags Verification flags created by mbedtls_x509_crt_verify() - * - * \return The length of the string written (not including the - * terminated nul byte), or a negative error code. - */ -int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, - uint32_t flags ); - -/** - * \brief Verify the certificate signature - * - * The verify callback is a user-supplied callback that - * can clear / modify / add flags for a certificate. If set, - * the verification callback is called for each - * certificate in the chain (from the trust-ca down to the - * presented crt). The parameters for the callback are: - * (void *parameter, mbedtls_x509_crt *crt, int certificate_depth, - * int *flags). With the flags representing current flags for - * that specific certificate and the certificate depth from - * the bottom (Peer cert depth = 0). - * - * All flags left after returning from the callback - * are also returned to the application. The function should - * return 0 for anything (including invalid certificates) - * other than fatal error, as a non-zero return code - * immediately aborts the verification process. For fatal - * errors, a specific error code should be used (different - * from MBEDTLS_ERR_X509_CERT_VERIFY_FAILED which should not - * be returned at this point), or MBEDTLS_ERR_X509_FATAL_ERROR - * can be used if no better code is available. - * - * \note In case verification failed, the results can be displayed - * using \c mbedtls_x509_crt_verify_info() - * - * \note Same as \c mbedtls_x509_crt_verify_with_profile() with the - * default security profile. - * - * \note It is your responsibility to provide up-to-date CRLs for - * all trusted CAs. If no CRL is provided for the CA that was - * used to sign the certificate, CRL verification is skipped - * silently, that is *without* setting any flag. - * - * \param crt a certificate (chain) to be verified - * \param trust_ca the list of trusted CAs - * \param ca_crl the list of CRLs for trusted CAs (see note above) - * \param cn expected Common Name (can be set to - * NULL if the CN must not be verified) - * \param flags result of the verification - * \param f_vrfy verification function - * \param p_vrfy verification parameter - * - * \return 0 (and flags set to 0) if the chain was verified and valid, - * MBEDTLS_ERR_X509_CERT_VERIFY_FAILED if the chain was verified - * but found to be invalid, in which case *flags will have one - * or more MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX - * flags set, or another error (and flags set to 0xffffffff) - * in case of a fatal error encountered during the - * verification process. - */ -int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ); - -/** - * \brief Verify the certificate signature according to profile - * - * \note Same as \c mbedtls_x509_crt_verify(), but with explicit - * security profile. - * - * \note The restrictions on keys (RSA minimum size, allowed curves - * for ECDSA) apply to all certificates: trusted root, - * intermediate CAs if any, and end entity certificate. - * - * \param crt a certificate (chain) to be verified - * \param trust_ca the list of trusted CAs - * \param ca_crl the list of CRLs for trusted CAs - * \param profile security profile for verification - * \param cn expected Common Name (can be set to - * NULL if the CN must not be verified) - * \param flags result of the verification - * \param f_vrfy verification function - * \param p_vrfy verification parameter - * - * \return 0 if successful or MBEDTLS_ERR_X509_CERT_VERIFY_FAILED - * in which case *flags will have one or more - * MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX flags - * set, - * or another error in case of a fatal error encountered - * during the verification process. - */ -int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const mbedtls_x509_crt_profile *profile, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ); - -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) -/** - * \brief Check usage of certificate against keyUsage extension. - * - * \param crt Leaf certificate used. - * \param usage Intended usage(s) (eg MBEDTLS_X509_KU_KEY_ENCIPHERMENT - * before using the certificate to perform an RSA key - * exchange). - * - * \note Except for decipherOnly and encipherOnly, a bit set in the - * usage argument means this bit MUST be set in the - * certificate. For decipherOnly and encipherOnly, it means - * that bit MAY be set. - * - * \return 0 is these uses of the certificate are allowed, - * MBEDTLS_ERR_X509_BAD_INPUT_DATA if the keyUsage extension - * is present but does not match the usage argument. - * - * \note You should only call this function on leaf certificates, on - * (intermediate) CAs the keyUsage extension is automatically - * checked by \c mbedtls_x509_crt_verify(). - */ -int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, - unsigned int usage ); -#endif /* MBEDTLS_X509_CHECK_KEY_USAGE) */ - -#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) -/** - * \brief Check usage of certificate against extentedJeyUsage. - * - * \param crt Leaf certificate used. - * \param usage_oid Intended usage (eg MBEDTLS_OID_SERVER_AUTH or MBEDTLS_OID_CLIENT_AUTH). - * \param usage_len Length of usage_oid (eg given by MBEDTLS_OID_SIZE()). - * - * \return 0 if this use of the certificate is allowed, - * MBEDTLS_ERR_X509_BAD_INPUT_DATA if not. - * - * \note Usually only makes sense on leaf certificates. - */ -int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, - const char *usage_oid, - size_t usage_len ); -#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) */ - -#if defined(MBEDTLS_X509_CRL_PARSE_C) -/** - * \brief Verify the certificate revocation status - * - * \param crt a certificate to be verified - * \param crl the CRL to verify against - * - * \return 1 if the certificate is revoked, 0 otherwise - * - */ -int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ); -#endif /* MBEDTLS_X509_CRL_PARSE_C */ - -/** - * \brief Initialize a certificate (chain) - * - * \param crt Certificate chain to initialize - */ -void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ); - -/** - * \brief Unallocate all certificate data - * - * \param crt Certificate chain to free - */ -void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ); -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -/* \} name */ -/* \} addtogroup x509_module */ - -#if defined(MBEDTLS_X509_CRT_WRITE_C) -/** - * \brief Initialize a CRT writing context - * - * \param ctx CRT context to initialize - */ -void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ); - -/** - * \brief Set the verion for a Certificate - * Default: MBEDTLS_X509_CRT_VERSION_3 - * - * \param ctx CRT context to use - * \param version version to set (MBEDTLS_X509_CRT_VERSION_1, MBEDTLS_X509_CRT_VERSION_2 or - * MBEDTLS_X509_CRT_VERSION_3) - */ -void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ); - -/** - * \brief Set the serial number for a Certificate. - * - * \param ctx CRT context to use - * \param serial serial number to set - * - * \return 0 if successful - */ -int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ); - -/** - * \brief Set the validity period for a Certificate - * Timestamps should be in string format for UTC timezone - * i.e. "YYYYMMDDhhmmss" - * e.g. "20131231235959" for December 31st 2013 - * at 23:59:59 - * - * \param ctx CRT context to use - * \param not_before not_before timestamp - * \param not_after not_after timestamp - * - * \return 0 if timestamp was parsed successfully, or - * a specific error code - */ -int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, - const char *not_after ); - -/** - * \brief Set the issuer name for a Certificate - * Issuer names should contain a comma-separated list - * of OID types and values: - * e.g. "C=UK,O=ARM,CN=mbed TLS CA" - * - * \param ctx CRT context to use - * \param issuer_name issuer name to set - * - * \return 0 if issuer name was parsed successfully, or - * a specific error code - */ -int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, - const char *issuer_name ); - -/** - * \brief Set the subject name for a Certificate - * Subject names should contain a comma-separated list - * of OID types and values: - * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" - * - * \param ctx CRT context to use - * \param subject_name subject name to set - * - * \return 0 if subject name was parsed successfully, or - * a specific error code - */ -int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, - const char *subject_name ); - -/** - * \brief Set the subject public key for the certificate - * - * \param ctx CRT context to use - * \param key public key to include - */ -void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); - -/** - * \brief Set the issuer key used for signing the certificate - * - * \param ctx CRT context to use - * \param key private key to sign with - */ -void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); - -/** - * \brief Set the MD algorithm to use for the signature - * (e.g. MBEDTLS_MD_SHA1) - * - * \param ctx CRT context to use - * \param md_alg MD algorithm to use - */ -void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ); - -/** - * \brief Generic function to add to or replace an extension in the - * CRT - * - * \param ctx CRT context to use - * \param oid OID of the extension - * \param oid_len length of the OID - * \param critical if the extension is critical (per the RFC's definition) - * \param val value of the extension OCTET STRING - * \param val_len length of the value data - * - * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, - const char *oid, size_t oid_len, - int critical, - const unsigned char *val, size_t val_len ); - -/** - * \brief Set the basicConstraints extension for a CRT - * - * \param ctx CRT context to use - * \param is_ca is this a CA certificate - * \param max_pathlen maximum length of certificate chains below this - * certificate (only for CA certificates, -1 is - * inlimited) - * - * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, - int is_ca, int max_pathlen ); - -#if defined(MBEDTLS_SHA1_C) -/** - * \brief Set the subjectKeyIdentifier extension for a CRT - * Requires that mbedtls_x509write_crt_set_subject_key() has been - * called before - * - * \param ctx CRT context to use - * - * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ); - -/** - * \brief Set the authorityKeyIdentifier extension for a CRT - * Requires that mbedtls_x509write_crt_set_issuer_key() has been - * called before - * - * \param ctx CRT context to use - * - * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ); -#endif /* MBEDTLS_SHA1_C */ - -/** - * \brief Set the Key Usage Extension flags - * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) - * - * \param ctx CRT context to use - * \param key_usage key usage flags to set - * - * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, - unsigned int key_usage ); - -/** - * \brief Set the Netscape Cert Type flags - * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) - * - * \param ctx CRT context to use - * \param ns_cert_type Netscape Cert Type flags to set - * - * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, - unsigned char ns_cert_type ); - -/** - * \brief Free the contents of a CRT write context - * - * \param ctx CRT context to free - */ -void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ); - -/** - * \brief Write a built up certificate to a X509 DER structure - * Note: data is written at the end of the buffer! Use the - * return value to determine where you should start - * using the buffer - * - * \param ctx certificate to write away - * \param buf buffer to write to - * \param size size of the buffer - * \param f_rng RNG function (for signature, see note) - * \param p_rng RNG parameter - * - * \return length of data written if successful, or a specific - * error code - * - * \note f_rng may be NULL if RSA is used for signature and the - * signature is made offline (otherwise f_rng is desirable - * for countermeasures against timing attacks). - * ECDSA signatures always require a non-NULL f_rng. - */ -int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -#if defined(MBEDTLS_PEM_WRITE_C) -/** - * \brief Write a built up certificate to a X509 PEM string - * - * \param ctx certificate to write away - * \param buf buffer to write to - * \param size size of the buffer - * \param f_rng RNG function (for signature, see note) - * \param p_rng RNG parameter - * - * \return 0 if successful, or a specific error code - * - * \note f_rng may be NULL if RSA is used for signature and the - * signature is made offline (otherwise f_rng is desirable - * for countermeasures against timing attacks). - * ECDSA signatures always require a non-NULL f_rng. - */ -int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); -#endif /* MBEDTLS_PEM_WRITE_C */ -#endif /* MBEDTLS_X509_CRT_WRITE_C */ - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_x509_crt.h */ diff --git a/components/mbedtls/include/mbedtls/x509_csr.h b/components/mbedtls/include/mbedtls/x509_csr.h deleted file mode 100644 index fe9843cb54..0000000000 --- a/components/mbedtls/include/mbedtls/x509_csr.h +++ /dev/null @@ -1,298 +0,0 @@ -/** - * \file x509_csr.h - * - * \brief X.509 certificate signing request parsing and writing - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_X509_CSR_H -#define MBEDTLS_X509_CSR_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "x509.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \addtogroup x509_module - * \{ */ - -/** - * \name Structures and functions for X.509 Certificate Signing Requests (CSR) - * \{ - */ - -/** - * Certificate Signing Request (CSR) structure. - */ -typedef struct mbedtls_x509_csr -{ - mbedtls_x509_buf raw; /**< The raw CSR data (DER). */ - mbedtls_x509_buf cri; /**< The raw CertificateRequestInfo body (DER). */ - - int version; /**< CSR version (1=v1). */ - - mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). */ - mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ - - mbedtls_pk_context pk; /**< Container for the public key context. */ - - mbedtls_x509_buf sig_oid; - mbedtls_x509_buf sig; - mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ - mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ - void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ -} -mbedtls_x509_csr; - -/** - * Container for writing a CSR - */ -typedef struct mbedtls_x509write_csr -{ - mbedtls_pk_context *key; - mbedtls_asn1_named_data *subject; - mbedtls_md_type_t md_alg; - mbedtls_asn1_named_data *extensions; -} -mbedtls_x509write_csr; - -#if defined(MBEDTLS_X509_CSR_PARSE_C) -/** - * \brief Load a Certificate Signing Request (CSR) in DER format - * - * \note CSR attributes (if any) are currently silently ignored. - * - * \param csr CSR context to fill - * \param buf buffer holding the CRL data - * \param buflen size of the buffer - * - * \return 0 if successful, or a specific X509 error code - */ -int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, - const unsigned char *buf, size_t buflen ); - -/** - * \brief Load a Certificate Signing Request (CSR), DER or PEM format - * - * \note See notes for \c mbedtls_x509_csr_parse_der() - * - * \param csr CSR context to fill - * \param buf buffer holding the CRL data - * \param buflen size of the buffer - * (including the terminating null byte for PEM data) - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ); - -#if defined(MBEDTLS_FS_IO) -/** - * \brief Load a Certificate Signing Request (CSR) - * - * \note See notes for \c mbedtls_x509_csr_parse() - * - * \param csr CSR context to fill - * \param path filename to read the CSR from - * - * \return 0 if successful, or a specific X509 or PEM error code - */ -int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ); -#endif /* MBEDTLS_FS_IO */ - -/** - * \brief Returns an informational string about the - * CSR. - * - * \param buf Buffer to write to - * \param size Maximum size of buffer - * \param prefix A line prefix - * \param csr The X509 CSR to represent - * - * \return The length of the string written (not including the - * terminated nul byte), or a negative error code. - */ -int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, - const mbedtls_x509_csr *csr ); - -/** - * \brief Initialize a CSR - * - * \param csr CSR to initialize - */ -void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ); - -/** - * \brief Unallocate all CSR data - * - * \param csr CSR to free - */ -void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ); -#endif /* MBEDTLS_X509_CSR_PARSE_C */ - -/* \} name */ -/* \} addtogroup x509_module */ - -#if defined(MBEDTLS_X509_CSR_WRITE_C) -/** - * \brief Initialize a CSR context - * - * \param ctx CSR context to initialize - */ -void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ); - -/** - * \brief Set the subject name for a CSR - * Subject names should contain a comma-separated list - * of OID types and values: - * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" - * - * \param ctx CSR context to use - * \param subject_name subject name to set - * - * \return 0 if subject name was parsed successfully, or - * a specific error code - */ -int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, - const char *subject_name ); - -/** - * \brief Set the key for a CSR (public key will be included, - * private key used to sign the CSR when writing it) - * - * \param ctx CSR context to use - * \param key Asymetric key to include - */ -void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ); - -/** - * \brief Set the MD algorithm to use for the signature - * (e.g. MBEDTLS_MD_SHA1) - * - * \param ctx CSR context to use - * \param md_alg MD algorithm to use - */ -void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ); - -/** - * \brief Set the Key Usage Extension flags - * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) - * - * \param ctx CSR context to use - * \param key_usage key usage flags to set - * - * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ); - -/** - * \brief Set the Netscape Cert Type flags - * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) - * - * \param ctx CSR context to use - * \param ns_cert_type Netscape Cert Type flags to set - * - * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, - unsigned char ns_cert_type ); - -/** - * \brief Generic function to add to or replace an extension in the - * CSR - * - * \param ctx CSR context to use - * \param oid OID of the extension - * \param oid_len length of the OID - * \param val value of the extension OCTET STRING - * \param val_len length of the value data - * - * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED - */ -int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, - const char *oid, size_t oid_len, - const unsigned char *val, size_t val_len ); - -/** - * \brief Free the contents of a CSR context - * - * \param ctx CSR context to free - */ -void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ); - -/** - * \brief Write a CSR (Certificate Signing Request) to a - * DER structure - * Note: data is written at the end of the buffer! Use the - * return value to determine where you should start - * using the buffer - * - * \param ctx CSR to write away - * \param buf buffer to write to - * \param size size of the buffer - * \param f_rng RNG function (for signature, see note) - * \param p_rng RNG parameter - * - * \return length of data written if successful, or a specific - * error code - * - * \note f_rng may be NULL if RSA is used for signature and the - * signature is made offline (otherwise f_rng is desirable - * for countermeasures against timing attacks). - * ECDSA signatures always require a non-NULL f_rng. - */ -int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -#if defined(MBEDTLS_PEM_WRITE_C) -/** - * \brief Write a CSR (Certificate Signing Request) to a - * PEM string - * - * \param ctx CSR to write away - * \param buf buffer to write to - * \param size size of the buffer - * \param f_rng RNG function (for signature, see note) - * \param p_rng RNG parameter - * - * \return 0 if successful, or a specific error code - * - * \note f_rng may be NULL if RSA is used for signature and the - * signature is made offline (otherwise f_rng is desirable - * for countermeasures against timing attacks). - * ECDSA signatures always require a non-NULL f_rng. - */ -int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); -#endif /* MBEDTLS_PEM_WRITE_C */ -#endif /* MBEDTLS_X509_CSR_WRITE_C */ - -#ifdef __cplusplus -} -#endif - -#endif /* mbedtls_x509_csr.h */ diff --git a/components/mbedtls/include/mbedtls/xtea.h b/components/mbedtls/include/mbedtls/xtea.h deleted file mode 100644 index b073f84efa..0000000000 --- a/components/mbedtls/include/mbedtls/xtea.h +++ /dev/null @@ -1,139 +0,0 @@ -/** - * \file xtea.h - * - * \brief XTEA block cipher (32-bit) - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -#ifndef MBEDTLS_XTEA_H -#define MBEDTLS_XTEA_H - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include -#include - -#define MBEDTLS_XTEA_ENCRYPT 1 -#define MBEDTLS_XTEA_DECRYPT 0 - -#define MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH -0x0028 /**< The data input has an invalid length. */ - -#if !defined(MBEDTLS_XTEA_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief XTEA context structure - */ -typedef struct -{ - uint32_t k[4]; /*!< key */ -} -mbedtls_xtea_context; - -/** - * \brief Initialize XTEA context - * - * \param ctx XTEA context to be initialized - */ -void mbedtls_xtea_init( mbedtls_xtea_context *ctx ); - -/** - * \brief Clear XTEA context - * - * \param ctx XTEA context to be cleared - */ -void mbedtls_xtea_free( mbedtls_xtea_context *ctx ); - -/** - * \brief XTEA key schedule - * - * \param ctx XTEA context to be initialized - * \param key the secret key - */ -void mbedtls_xtea_setup( mbedtls_xtea_context *ctx, const unsigned char key[16] ); - -/** - * \brief XTEA cipher function - * - * \param ctx XTEA context - * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT - * \param input 8-byte input block - * \param output 8-byte output block - * - * \return 0 if successful - */ -int mbedtls_xtea_crypt_ecb( mbedtls_xtea_context *ctx, - int mode, - const unsigned char input[8], - unsigned char output[8] ); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/** - * \brief XTEA CBC cipher function - * - * \param ctx XTEA context - * \param mode MBEDTLS_XTEA_ENCRYPT or MBEDTLS_XTEA_DECRYPT - * \param length the length of input, multiple of 8 - * \param iv initialization vector for CBC mode - * \param input input block - * \param output output block - * - * \return 0 if successful, - * MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH if the length % 8 != 0 - */ -int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output); -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#ifdef __cplusplus -} -#endif - -#else /* MBEDTLS_XTEA_ALT */ -#include "xtea_alt.h" -#endif /* MBEDTLS_XTEA_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mbedtls_xtea_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* xtea.h */ diff --git a/components/mbedtls/library/.gitignore b/components/mbedtls/library/.gitignore deleted file mode 100644 index 3a63a63a43..0000000000 --- a/components/mbedtls/library/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*.o -libmbed* -*.sln -*.vcxproj diff --git a/components/mbedtls/library/aes.c b/components/mbedtls/library/aes.c deleted file mode 100644 index 58603849cc..0000000000 --- a/components/mbedtls/library/aes.c +++ /dev/null @@ -1,1508 +0,0 @@ -/* - * FIPS-197 compliant AES implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. - * - * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf - * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_AES_C) - -#include - -#include "mbedtls/aes.h" -#if defined(MBEDTLS_PADLOCK_C) -#include "mbedtls/padlock.h" -#endif -#if defined(MBEDTLS_AESNI_C) -#include "mbedtls/aesni.h" -#endif - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_AES_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_UINT32_LE -#define GET_UINT32_LE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] ) \ - | ( (uint32_t) (b)[(i) + 1] << 8 ) \ - | ( (uint32_t) (b)[(i) + 2] << 16 ) \ - | ( (uint32_t) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_UINT32_LE -#define PUT_UINT32_LE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ - (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ - (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ - (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ -} -#endif - -#if defined(MBEDTLS_PADLOCK_C) && \ - ( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) ) -static int aes_padlock_ace = -1; -#endif - -#if defined(MBEDTLS_AES_ROM_TABLES) -/* - * Forward S-box - */ -static const unsigned char FSb[256] = -{ - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, - 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, - 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, - 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, - 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, - 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, - 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, - 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, - 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, - 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, - 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, - 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, - 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, - 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, - 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, - 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, - 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, - 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, - 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, - 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, - 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, - 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, - 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, - 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, - 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, - 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, - 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, - 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, - 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, - 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, - 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, - 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 -}; - -/* - * Forward tables - */ -#define FT \ -\ - V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ - V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ - V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ - V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ - V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ - V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ - V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ - V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ - V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ - V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ - V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ - V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ - V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ - V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ - V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ - V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ - V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ - V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ - V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ - V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ - V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ - V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ - V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ - V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ - V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ - V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ - V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ - V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ - V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ - V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ - V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ - V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ - V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ - V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ - V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ - V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ - V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ - V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ - V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ - V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ - V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ - V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ - V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ - V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ - V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ - V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ - V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ - V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ - V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ - V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ - V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ - V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ - V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ - V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ - V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ - V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ - V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ - V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ - V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ - V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ - V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ - V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ - V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ - V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) - -#define V(a,b,c,d) 0x##a##b##c##d -static const uint32_t FT0[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##b##c##d##a -static const uint32_t FT1[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##c##d##a##b -static const uint32_t FT2[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##d##a##b##c -static const uint32_t FT3[256] = { FT }; -#undef V - -#undef FT - -/* - * Reverse S-box - */ -static const unsigned char RSb[256] = -{ - 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, - 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, - 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, - 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, - 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, - 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, - 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, - 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, - 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, - 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, - 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, - 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, - 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, - 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, - 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, - 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, - 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, - 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, - 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, - 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, - 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, - 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, - 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, - 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, - 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, - 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, - 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, - 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, - 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, - 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, - 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D -}; - -/* - * Reverse tables - */ -#define RT \ -\ - V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ - V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ - V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ - V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ - V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ - V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ - V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ - V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ - V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ - V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ - V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ - V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ - V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ - V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ - V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ - V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ - V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ - V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ - V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ - V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ - V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ - V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ - V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ - V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ - V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ - V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ - V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ - V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ - V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ - V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ - V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ - V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ - V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ - V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ - V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ - V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ - V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ - V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ - V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ - V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ - V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ - V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ - V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ - V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ - V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ - V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ - V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ - V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ - V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ - V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ - V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ - V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ - V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ - V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ - V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ - V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ - V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ - V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ - V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ - V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ - V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ - V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ - V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ - V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) - -#define V(a,b,c,d) 0x##a##b##c##d -static const uint32_t RT0[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##b##c##d##a -static const uint32_t RT1[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##c##d##a##b -static const uint32_t RT2[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##d##a##b##c -static const uint32_t RT3[256] = { RT }; -#undef V - -#undef RT - -/* - * Round constants - */ -static const uint32_t RCON[10] = -{ - 0x00000001, 0x00000002, 0x00000004, 0x00000008, - 0x00000010, 0x00000020, 0x00000040, 0x00000080, - 0x0000001B, 0x00000036 -}; - -#else /* MBEDTLS_AES_ROM_TABLES */ - -/* - * Forward S-box & tables - */ -static unsigned char FSb[256]; -static uint32_t FT0[256]; -static uint32_t FT1[256]; -static uint32_t FT2[256]; -static uint32_t FT3[256]; - -/* - * Reverse S-box & tables - */ -static unsigned char RSb[256]; -static uint32_t RT0[256]; -static uint32_t RT1[256]; -static uint32_t RT2[256]; -static uint32_t RT3[256]; - -/* - * Round constants - */ -static uint32_t RCON[10]; - -/* - * Tables generation code - */ -#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) -#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) -#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) - -static int aes_init_done = 0; - -static void aes_gen_tables( void ) -{ - int i, x, y, z; - int pow[256]; - int log[256]; - - /* - * compute pow and log tables over GF(2^8) - */ - for( i = 0, x = 1; i < 256; i++ ) - { - pow[i] = x; - log[x] = i; - x = ( x ^ XTIME( x ) ) & 0xFF; - } - - /* - * calculate the round constants - */ - for( i = 0, x = 1; i < 10; i++ ) - { - RCON[i] = (uint32_t) x; - x = XTIME( x ) & 0xFF; - } - - /* - * generate the forward and reverse S-boxes - */ - FSb[0x00] = 0x63; - RSb[0x63] = 0x00; - - for( i = 1; i < 256; i++ ) - { - x = pow[255 - log[i]]; - - y = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; - x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; - x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; - x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; - x ^= y ^ 0x63; - - FSb[i] = (unsigned char) x; - RSb[x] = (unsigned char) i; - } - - /* - * generate the forward and reverse tables - */ - for( i = 0; i < 256; i++ ) - { - x = FSb[i]; - y = XTIME( x ) & 0xFF; - z = ( y ^ x ) & 0xFF; - - FT0[i] = ( (uint32_t) y ) ^ - ( (uint32_t) x << 8 ) ^ - ( (uint32_t) x << 16 ) ^ - ( (uint32_t) z << 24 ); - - FT1[i] = ROTL8( FT0[i] ); - FT2[i] = ROTL8( FT1[i] ); - FT3[i] = ROTL8( FT2[i] ); - - x = RSb[i]; - - RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^ - ( (uint32_t) MUL( 0x09, x ) << 8 ) ^ - ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ - ( (uint32_t) MUL( 0x0B, x ) << 24 ); - - RT1[i] = ROTL8( RT0[i] ); - RT2[i] = ROTL8( RT1[i] ); - RT3[i] = ROTL8( RT2[i] ); - } -} - -#endif /* MBEDTLS_AES_ROM_TABLES */ - -void mbedtls_aes_init( mbedtls_aes_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_aes_context ) ); -} - -void mbedtls_aes_free( mbedtls_aes_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) ); -} - -/* - * AES key schedule (encryption) - */ -#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) -int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, - unsigned int keybits ) -{ - unsigned int i; - uint32_t *RK; - -#if !defined(MBEDTLS_AES_ROM_TABLES) - if( aes_init_done == 0 ) - { - aes_gen_tables(); - aes_init_done = 1; - - } -#endif - - switch( keybits ) - { - case 128: ctx->nr = 10; break; - case 192: ctx->nr = 12; break; - case 256: ctx->nr = 14; break; - default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); - } - -#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) - if( aes_padlock_ace == -1 ) - aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); - - if( aes_padlock_ace ) - ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); - else -#endif - ctx->rk = RK = ctx->buf; - -#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) - if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) - return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) ); -#endif - - for( i = 0; i < ( keybits >> 5 ); i++ ) - { - GET_UINT32_LE( RK[i], key, i << 2 ); - } - - switch( ctx->nr ) - { - case 10: - - for( i = 0; i < 10; i++, RK += 4 ) - { - RK[4] = RK[0] ^ RCON[i] ^ - ( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 ); - - RK[5] = RK[1] ^ RK[4]; - RK[6] = RK[2] ^ RK[5]; - RK[7] = RK[3] ^ RK[6]; - } - break; - - case 12: - - for( i = 0; i < 8; i++, RK += 6 ) - { - RK[6] = RK[0] ^ RCON[i] ^ - ( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 ); - - RK[7] = RK[1] ^ RK[6]; - RK[8] = RK[2] ^ RK[7]; - RK[9] = RK[3] ^ RK[8]; - RK[10] = RK[4] ^ RK[9]; - RK[11] = RK[5] ^ RK[10]; - } - break; - - case 14: - - for( i = 0; i < 7; i++, RK += 8 ) - { - RK[8] = RK[0] ^ RCON[i] ^ - ( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 ); - - RK[9] = RK[1] ^ RK[8]; - RK[10] = RK[2] ^ RK[9]; - RK[11] = RK[3] ^ RK[10]; - - RK[12] = RK[4] ^ - ( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); - - RK[13] = RK[5] ^ RK[12]; - RK[14] = RK[6] ^ RK[13]; - RK[15] = RK[7] ^ RK[14]; - } - break; - } - - return( 0 ); -} -#endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */ - -/* - * AES key schedule (decryption) - */ -#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) -int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, - unsigned int keybits ) -{ - int i, j, ret; - mbedtls_aes_context cty; - uint32_t *RK; - uint32_t *SK; - - mbedtls_aes_init( &cty ); - -#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) - if( aes_padlock_ace == -1 ) - aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); - - if( aes_padlock_ace ) - ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); - else -#endif - ctx->rk = RK = ctx->buf; - - /* Also checks keybits */ - if( ( ret = mbedtls_aes_setkey_enc( &cty, key, keybits ) ) != 0 ) - goto exit; - - ctx->nr = cty.nr; - -#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) - if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) - { - mbedtls_aesni_inverse_key( (unsigned char *) ctx->rk, - (const unsigned char *) cty.rk, ctx->nr ); - goto exit; - } -#endif - - SK = cty.rk + cty.nr * 4; - - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - - for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) - { - for( j = 0; j < 4; j++, SK++ ) - { - *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ - RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ - RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ - RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; - } - } - - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - -exit: - mbedtls_aes_free( &cty ); - - return( ret ); -} -#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ - -#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ - X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ - FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y3 >> 24 ) & 0xFF ]; \ - \ - X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ - FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y0 >> 24 ) & 0xFF ]; \ - \ - X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ - FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y1 >> 24 ) & 0xFF ]; \ - \ - X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ - FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y2 >> 24 ) & 0xFF ]; \ -} - -#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ - X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ - RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y1 >> 24 ) & 0xFF ]; \ - \ - X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ - RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y2 >> 24 ) & 0xFF ]; \ - \ - X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ - RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y3 >> 24 ) & 0xFF ]; \ - \ - X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ - RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y0 >> 24 ) & 0xFF ]; \ -} - -/* - * AES-ECB block encryption - */ -#if !defined(MBEDTLS_AES_ENCRYPT_ALT) -int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ) -{ - int i; - uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; - - RK = ctx->rk; - - GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; - GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; - GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; - GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; - - for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) - { - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); - } - - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - - X0 = *RK++ ^ \ - ( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); - - X1 = *RK++ ^ \ - ( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); - - X2 = *RK++ ^ \ - ( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); - - X3 = *RK++ ^ \ - ( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); - - PUT_UINT32_LE( X0, output, 0 ); - PUT_UINT32_LE( X1, output, 4 ); - PUT_UINT32_LE( X2, output, 8 ); - PUT_UINT32_LE( X3, output, 12 ); - - return( 0 ); -} -#endif /* !MBEDTLS_AES_ENCRYPT_ALT */ - -void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ) -{ - mbedtls_internal_aes_encrypt( ctx, input, output ); -} - -/* - * AES-ECB block decryption - */ -#if !defined(MBEDTLS_AES_DECRYPT_ALT) -int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ) -{ - int i; - uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; - - RK = ctx->rk; - - GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; - GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; - GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; - GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; - - for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) - { - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); - } - - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - - X0 = *RK++ ^ \ - ( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^ - ( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); - - X1 = *RK++ ^ \ - ( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^ - ( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); - - X2 = *RK++ ^ \ - ( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^ - ( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); - - X3 = *RK++ ^ \ - ( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^ - ( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); - - PUT_UINT32_LE( X0, output, 0 ); - PUT_UINT32_LE( X1, output, 4 ); - PUT_UINT32_LE( X2, output, 8 ); - PUT_UINT32_LE( X3, output, 12 ); - - return( 0 ); -} -#endif /* !MBEDTLS_AES_DECRYPT_ALT */ - -void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ) -{ - mbedtls_internal_aes_decrypt( ctx, input, output ); -} - -/* - * AES-ECB block encryption/decryption - */ -int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ) -{ -#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) - if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) - return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) ); -#endif - -#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) - if( aes_padlock_ace ) - { - if( mbedtls_padlock_xcryptecb( ctx, mode, input, output ) == 0 ) - return( 0 ); - - // If padlock data misaligned, we just fall back to - // unaccelerated mode - // - } -#endif - - if( mode == MBEDTLS_AES_ENCRYPT ) - return( mbedtls_internal_aes_encrypt( ctx, input, output ) ); - else - return( mbedtls_internal_aes_decrypt( ctx, input, output ) ); -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/* - * AES-CBC buffer encryption/decryption - */ -int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[16]; - - if( length % 16 ) - return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH ); - -#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) - if( aes_padlock_ace ) - { - if( mbedtls_padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) - return( 0 ); - - // If padlock data misaligned, we just fall back to - // unaccelerated mode - // - } -#endif - - if( mode == MBEDTLS_AES_DECRYPT ) - { - while( length > 0 ) - { - memcpy( temp, input, 16 ); - mbedtls_aes_crypt_ecb( ctx, mode, input, output ); - - for( i = 0; i < 16; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 16 ); - - input += 16; - output += 16; - length -= 16; - } - } - else - { - while( length > 0 ) - { - for( i = 0; i < 16; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - mbedtls_aes_crypt_ecb( ctx, mode, output, output ); - memcpy( iv, output, 16 ); - - input += 16; - output += 16; - length -= 16; - } - } - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -/* - * AES-CFB128 buffer encryption/decryption - */ -int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int c; - size_t n = *iv_off; - - if( mode == MBEDTLS_AES_DECRYPT ) - { - while( length-- ) - { - if( n == 0 ) - mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); - - c = *input++; - *output++ = (unsigned char)( c ^ iv[n] ); - iv[n] = (unsigned char) c; - - n = ( n + 1 ) & 0x0F; - } - } - else - { - while( length-- ) - { - if( n == 0 ) - mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); - - iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); - - n = ( n + 1 ) & 0x0F; - } - } - - *iv_off = n; - - return( 0 ); -} - -/* - * AES-CFB8 buffer encryption/decryption - */ -int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - unsigned char c; - unsigned char ov[17]; - - while( length-- ) - { - memcpy( ov, iv, 16 ); - mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); - - if( mode == MBEDTLS_AES_DECRYPT ) - ov[16] = *input; - - c = *output++ = (unsigned char)( iv[0] ^ *input++ ); - - if( mode == MBEDTLS_AES_ENCRYPT ) - ov[16] = c; - - memcpy( iv, ov + 1, 16 ); - } - - return( 0 ); -} -#endif /*MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -/* - * AES-CTR buffer encryption/decryption - */ -int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[16], - unsigned char stream_block[16], - const unsigned char *input, - unsigned char *output ) -{ - int c, i; - size_t n = *nc_off; - - while( length-- ) - { - if( n == 0 ) { - mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block ); - - for( i = 16; i > 0; i-- ) - if( ++nonce_counter[i - 1] != 0 ) - break; - } - c = *input++; - *output++ = (unsigned char)( c ^ stream_block[n] ); - - n = ( n + 1 ) & 0x0F; - } - - *nc_off = n; - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -#endif /* !MBEDTLS_AES_ALT */ - -#if defined(MBEDTLS_SELF_TEST) -/* - * AES test vectors from: - * - * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip - */ -static const unsigned char aes_test_ecb_dec[3][16] = -{ - { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, - 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, - { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, - 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, - { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, - 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } -}; - -static const unsigned char aes_test_ecb_enc[3][16] = -{ - { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, - 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, - { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, - 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, - { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, - 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } -}; - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static const unsigned char aes_test_cbc_dec[3][16] = -{ - { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, - 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, - { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, - 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, - { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, - 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } -}; - -static const unsigned char aes_test_cbc_enc[3][16] = -{ - { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, - 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, - { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, - 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, - { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, - 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -/* - * AES-CFB128 test vectors from: - * - * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - */ -static const unsigned char aes_test_cfb128_key[3][32] = -{ - { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, - 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, - { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, - 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, - 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, - { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, - 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, - 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, - 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } -}; - -static const unsigned char aes_test_cfb128_iv[16] = -{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F -}; - -static const unsigned char aes_test_cfb128_pt[64] = -{ - 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, - 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, - 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, - 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, - 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, - 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, - 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, - 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 -}; - -static const unsigned char aes_test_cfb128_ct[3][64] = -{ - { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, - 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, - 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, - 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, - 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, - 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, - 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, - 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, - { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, - 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, - 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, - 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, - 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, - 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, - 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, - 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, - { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, - 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, - 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, - 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, - 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, - 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, - 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, - 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } -}; -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -/* - * AES-CTR test vectors from: - * - * http://www.faqs.org/rfcs/rfc3686.html - */ - -static const unsigned char aes_test_ctr_key[3][16] = -{ - { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, - 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, - { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, - 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, - { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, - 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } -}; - -static const unsigned char aes_test_ctr_nonce_counter[3][16] = -{ - { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, - 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, - { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, - 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } -}; - -static const unsigned char aes_test_ctr_pt[3][48] = -{ - { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, - 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, - 0x20, 0x21, 0x22, 0x23 } -}; - -static const unsigned char aes_test_ctr_ct[3][48] = -{ - { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, - 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, - { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, - 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, - 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, - 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 }, - { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, - 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, - 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, - 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, - 0x25, 0xB2, 0x07, 0x2F } -}; - -static const int aes_test_ctr_len[3] = - { 16, 32, 36 }; -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -/* - * Checkup routine - */ -int mbedtls_aes_self_test( int verbose ) -{ - int ret = 0, i, j, u, v; - unsigned char key[32]; - unsigned char buf[64]; -#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) - unsigned char iv[16]; -#endif -#if defined(MBEDTLS_CIPHER_MODE_CBC) - unsigned char prv[16]; -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) - size_t offset; -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - int len; - unsigned char nonce_counter[16]; - unsigned char stream_block[16]; -#endif - mbedtls_aes_context ctx; - - memset( key, 0, 32 ); - mbedtls_aes_init( &ctx ); - - /* - * ECB mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - mbedtls_printf( " AES-ECB-%3d (%s): ", 128 + u * 64, - ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); - - memset( buf, 0, 16 ); - - if( v == MBEDTLS_AES_DECRYPT ) - { - mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - mbedtls_aes_crypt_ecb( &ctx, v, buf, buf ); - - if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - else - { - mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - mbedtls_aes_crypt_ecb( &ctx, v, buf, buf ); - - if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - /* - * CBC mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - mbedtls_printf( " AES-CBC-%3d (%s): ", 128 + u * 64, - ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); - - memset( iv , 0, 16 ); - memset( prv, 0, 16 ); - memset( buf, 0, 16 ); - - if( v == MBEDTLS_AES_DECRYPT ) - { - mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); - - if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - else - { - mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - { - unsigned char tmp[16]; - - mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); - - memcpy( tmp, prv, 16 ); - memcpy( prv, buf, 16 ); - memcpy( buf, tmp, 16 ); - } - - if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) - /* - * CFB128 mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - mbedtls_printf( " AES-CFB128-%3d (%s): ", 128 + u * 64, - ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); - - memcpy( iv, aes_test_cfb128_iv, 16 ); - memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 ); - - offset = 0; - mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 ); - - if( v == MBEDTLS_AES_DECRYPT ) - { - memcpy( buf, aes_test_cfb128_ct[u], 64 ); - mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); - - if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - else - { - memcpy( buf, aes_test_cfb128_pt, 64 ); - mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); - - if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) - /* - * CTR mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - mbedtls_printf( " AES-CTR-128 (%s): ", - ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); - - memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 ); - memcpy( key, aes_test_ctr_key[u], 16 ); - - offset = 0; - mbedtls_aes_setkey_enc( &ctx, key, 128 ); - - if( v == MBEDTLS_AES_DECRYPT ) - { - len = aes_test_ctr_len[u]; - memcpy( buf, aes_test_ctr_ct[u], len ); - - mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, - buf, buf ); - - if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - else - { - len = aes_test_ctr_len[u]; - memcpy( buf, aes_test_ctr_pt[u], len ); - - mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, - buf, buf ); - - if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - - ret = 0; - -exit: - mbedtls_aes_free( &ctx ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_AES_C */ diff --git a/components/mbedtls/library/aesni.c b/components/mbedtls/library/aesni.c deleted file mode 100644 index 1ca3c3ef5b..0000000000 --- a/components/mbedtls/library/aesni.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * AES-NI support functions - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -/* - * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set - * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/ - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_AESNI_C) - -#include "mbedtls/aesni.h" - -#include - -#ifndef asm -#define asm __asm -#endif - -#if defined(MBEDTLS_HAVE_X86_64) - -/* - * AES-NI support detection routine - */ -int mbedtls_aesni_has_support( unsigned int what ) -{ - static int done = 0; - static unsigned int c = 0; - - if( ! done ) - { - asm( "movl $1, %%eax \n\t" - "cpuid \n\t" - : "=c" (c) - : - : "eax", "ebx", "edx" ); - done = 1; - } - - return( ( c & what ) != 0 ); -} - -/* - * Binutils needs to be at least 2.19 to support AES-NI instructions. - * Unfortunately, a lot of users have a lower version now (2014-04). - * Emit bytecode directly in order to support "old" version of gas. - * - * Opcodes from the Intel architecture reference manual, vol. 3. - * We always use registers, so we don't need prefixes for memory operands. - * Operand macros are in gas order (src, dst) as opposed to Intel order - * (dst, src) in order to blend better into the surrounding assembly code. - */ -#define AESDEC ".byte 0x66,0x0F,0x38,0xDE," -#define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF," -#define AESENC ".byte 0x66,0x0F,0x38,0xDC," -#define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD," -#define AESIMC ".byte 0x66,0x0F,0x38,0xDB," -#define AESKEYGENA ".byte 0x66,0x0F,0x3A,0xDF," -#define PCLMULQDQ ".byte 0x66,0x0F,0x3A,0x44," - -#define xmm0_xmm0 "0xC0" -#define xmm0_xmm1 "0xC8" -#define xmm0_xmm2 "0xD0" -#define xmm0_xmm3 "0xD8" -#define xmm0_xmm4 "0xE0" -#define xmm1_xmm0 "0xC1" -#define xmm1_xmm2 "0xD1" - -/* - * AES-NI AES-ECB block en(de)cryption - */ -int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ) -{ - asm( "movdqu (%3), %%xmm0 \n\t" // load input - "movdqu (%1), %%xmm1 \n\t" // load round key 0 - "pxor %%xmm1, %%xmm0 \n\t" // round 0 - "add $16, %1 \n\t" // point to next round key - "subl $1, %0 \n\t" // normal rounds = nr - 1 - "test %2, %2 \n\t" // mode? - "jz 2f \n\t" // 0 = decrypt - - "1: \n\t" // encryption loop - "movdqu (%1), %%xmm1 \n\t" // load round key - AESENC xmm1_xmm0 "\n\t" // do round - "add $16, %1 \n\t" // point to next round key - "subl $1, %0 \n\t" // loop - "jnz 1b \n\t" - "movdqu (%1), %%xmm1 \n\t" // load round key - AESENCLAST xmm1_xmm0 "\n\t" // last round - "jmp 3f \n\t" - - "2: \n\t" // decryption loop - "movdqu (%1), %%xmm1 \n\t" - AESDEC xmm1_xmm0 "\n\t" // do round - "add $16, %1 \n\t" - "subl $1, %0 \n\t" - "jnz 2b \n\t" - "movdqu (%1), %%xmm1 \n\t" // load round key - AESDECLAST xmm1_xmm0 "\n\t" // last round - - "3: \n\t" - "movdqu %%xmm0, (%4) \n\t" // export output - : - : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output) - : "memory", "cc", "xmm0", "xmm1" ); - - - return( 0 ); -} - -/* - * GCM multiplication: c = a times b in GF(2^128) - * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5. - */ -void mbedtls_aesni_gcm_mult( unsigned char c[16], - const unsigned char a[16], - const unsigned char b[16] ) -{ - unsigned char aa[16], bb[16], cc[16]; - size_t i; - - /* The inputs are in big-endian order, so byte-reverse them */ - for( i = 0; i < 16; i++ ) - { - aa[i] = a[15 - i]; - bb[i] = b[15 - i]; - } - - asm( "movdqu (%0), %%xmm0 \n\t" // a1:a0 - "movdqu (%1), %%xmm1 \n\t" // b1:b0 - - /* - * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1 - * using [CLMUL-WP] algorithm 1 (p. 13). - */ - "movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0 - "movdqa %%xmm1, %%xmm3 \n\t" // same - "movdqa %%xmm1, %%xmm4 \n\t" // same - PCLMULQDQ xmm0_xmm1 ",0x00 \n\t" // a0*b0 = c1:c0 - PCLMULQDQ xmm0_xmm2 ",0x11 \n\t" // a1*b1 = d1:d0 - PCLMULQDQ xmm0_xmm3 ",0x10 \n\t" // a0*b1 = e1:e0 - PCLMULQDQ xmm0_xmm4 ",0x01 \n\t" // a1*b0 = f1:f0 - "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0 - "movdqa %%xmm4, %%xmm3 \n\t" // same - "psrldq $8, %%xmm4 \n\t" // 0:e1+f1 - "pslldq $8, %%xmm3 \n\t" // e0+f0:0 - "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1 - "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0 - - /* - * Now shift the result one bit to the left, - * taking advantage of [CLMUL-WP] eq 27 (p. 20) - */ - "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0 - "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2 - "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1 - "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1 - "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63 - "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63 - "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63 - "pslldq $8, %%xmm3 \n\t" // r0>>63:0 - "pslldq $8, %%xmm4 \n\t" // r2>>63:0 - "psrldq $8, %%xmm5 \n\t" // 0:r1>>63 - "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1 - "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1 - "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63 - - /* - * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 - * using [CLMUL-WP] algorithm 5 (p. 20). - * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted). - */ - /* Step 2 (1) */ - "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0 - "movdqa %%xmm1, %%xmm4 \n\t" // same - "movdqa %%xmm1, %%xmm5 \n\t" // same - "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a - "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b - "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c - - /* Step 2 (2) */ - "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b - "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c - "pslldq $8, %%xmm3 \n\t" // a+b+c:0 - "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0 - - /* Steps 3 and 4 */ - "movdqa %%xmm1,%%xmm0 \n\t" // d:x0 - "movdqa %%xmm1,%%xmm4 \n\t" // same - "movdqa %%xmm1,%%xmm5 \n\t" // same - "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0' - "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0' - "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0' - "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0' - "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0' - // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing - // bits carried from d. Now get those\t bits back in. - "movdqa %%xmm1,%%xmm3 \n\t" // d:x0 - "movdqa %%xmm1,%%xmm4 \n\t" // same - "movdqa %%xmm1,%%xmm5 \n\t" // same - "psllq $63, %%xmm3 \n\t" // d<<63:stuff - "psllq $62, %%xmm4 \n\t" // d<<62:stuff - "psllq $57, %%xmm5 \n\t" // d<<57:stuff - "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff - "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff - "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d - "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0 - "pxor %%xmm1, %%xmm0 \n\t" // h1:h0 - "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0 - - "movdqu %%xmm0, (%2) \n\t" // done - : - : "r" (aa), "r" (bb), "r" (cc) - : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" ); - - /* Now byte-reverse the outputs */ - for( i = 0; i < 16; i++ ) - c[i] = cc[15 - i]; - - return; -} - -/* - * Compute decryption round keys from encryption round keys - */ -void mbedtls_aesni_inverse_key( unsigned char *invkey, - const unsigned char *fwdkey, int nr ) -{ - unsigned char *ik = invkey; - const unsigned char *fk = fwdkey + 16 * nr; - - memcpy( ik, fk, 16 ); - - for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 ) - asm( "movdqu (%0), %%xmm0 \n\t" - AESIMC xmm0_xmm0 "\n\t" - "movdqu %%xmm0, (%1) \n\t" - : - : "r" (fk), "r" (ik) - : "memory", "xmm0" ); - - memcpy( ik, fk, 16 ); -} - -/* - * Key expansion, 128-bit case - */ -static void aesni_setkey_enc_128( unsigned char *rk, - const unsigned char *key ) -{ - asm( "movdqu (%1), %%xmm0 \n\t" // copy the original key - "movdqu %%xmm0, (%0) \n\t" // as round key 0 - "jmp 2f \n\t" // skip auxiliary routine - - /* - * Finish generating the next round key. - * - * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff - * with X = rot( sub( r3 ) ) ^ RCON. - * - * On exit, xmm0 is r7:r6:r5:r4 - * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3 - * and those are written to the round key buffer. - */ - "1: \n\t" - "pshufd $0xff, %%xmm1, %%xmm1 \n\t" // X:X:X:X - "pxor %%xmm0, %%xmm1 \n\t" // X+r3:X+r2:X+r1:r4 - "pslldq $4, %%xmm0 \n\t" // r2:r1:r0:0 - "pxor %%xmm0, %%xmm1 \n\t" // X+r3+r2:X+r2+r1:r5:r4 - "pslldq $4, %%xmm0 \n\t" // etc - "pxor %%xmm0, %%xmm1 \n\t" - "pslldq $4, %%xmm0 \n\t" - "pxor %%xmm1, %%xmm0 \n\t" // update xmm0 for next time! - "add $16, %0 \n\t" // point to next round key - "movdqu %%xmm0, (%0) \n\t" // write it - "ret \n\t" - - /* Main "loop" */ - "2: \n\t" - AESKEYGENA xmm0_xmm1 ",0x01 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x02 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x04 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x08 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x10 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x20 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x40 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x80 \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x1B \n\tcall 1b \n\t" - AESKEYGENA xmm0_xmm1 ",0x36 \n\tcall 1b \n\t" - : - : "r" (rk), "r" (key) - : "memory", "cc", "0" ); -} - -/* - * Key expansion, 192-bit case - */ -static void aesni_setkey_enc_192( unsigned char *rk, - const unsigned char *key ) -{ - asm( "movdqu (%1), %%xmm0 \n\t" // copy original round key - "movdqu %%xmm0, (%0) \n\t" - "add $16, %0 \n\t" - "movq 16(%1), %%xmm1 \n\t" - "movq %%xmm1, (%0) \n\t" - "add $8, %0 \n\t" - "jmp 2f \n\t" // skip auxiliary routine - - /* - * Finish generating the next 6 quarter-keys. - * - * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4 - * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON. - * - * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10 - * and those are written to the round key buffer. - */ - "1: \n\t" - "pshufd $0x55, %%xmm2, %%xmm2 \n\t" // X:X:X:X - "pxor %%xmm0, %%xmm2 \n\t" // X+r3:X+r2:X+r1:r4 - "pslldq $4, %%xmm0 \n\t" // etc - "pxor %%xmm0, %%xmm2 \n\t" - "pslldq $4, %%xmm0 \n\t" - "pxor %%xmm0, %%xmm2 \n\t" - "pslldq $4, %%xmm0 \n\t" - "pxor %%xmm2, %%xmm0 \n\t" // update xmm0 = r9:r8:r7:r6 - "movdqu %%xmm0, (%0) \n\t" - "add $16, %0 \n\t" - "pshufd $0xff, %%xmm0, %%xmm2 \n\t" // r9:r9:r9:r9 - "pxor %%xmm1, %%xmm2 \n\t" // stuff:stuff:r9+r5:r10 - "pslldq $4, %%xmm1 \n\t" // r2:r1:r0:0 - "pxor %%xmm2, %%xmm1 \n\t" // xmm1 = stuff:stuff:r11:r10 - "movq %%xmm1, (%0) \n\t" - "add $8, %0 \n\t" - "ret \n\t" - - "2: \n\t" - AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x80 \n\tcall 1b \n\t" - - : - : "r" (rk), "r" (key) - : "memory", "cc", "0" ); -} - -/* - * Key expansion, 256-bit case - */ -static void aesni_setkey_enc_256( unsigned char *rk, - const unsigned char *key ) -{ - asm( "movdqu (%1), %%xmm0 \n\t" - "movdqu %%xmm0, (%0) \n\t" - "add $16, %0 \n\t" - "movdqu 16(%1), %%xmm1 \n\t" - "movdqu %%xmm1, (%0) \n\t" - "jmp 2f \n\t" // skip auxiliary routine - - /* - * Finish generating the next two round keys. - * - * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and - * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON - * - * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12 - * and those have been written to the output buffer. - */ - "1: \n\t" - "pshufd $0xff, %%xmm2, %%xmm2 \n\t" - "pxor %%xmm0, %%xmm2 \n\t" - "pslldq $4, %%xmm0 \n\t" - "pxor %%xmm0, %%xmm2 \n\t" - "pslldq $4, %%xmm0 \n\t" - "pxor %%xmm0, %%xmm2 \n\t" - "pslldq $4, %%xmm0 \n\t" - "pxor %%xmm2, %%xmm0 \n\t" - "add $16, %0 \n\t" - "movdqu %%xmm0, (%0) \n\t" - - /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 ) - * and proceed to generate next round key from there */ - AESKEYGENA xmm0_xmm2 ",0x00 \n\t" - "pshufd $0xaa, %%xmm2, %%xmm2 \n\t" - "pxor %%xmm1, %%xmm2 \n\t" - "pslldq $4, %%xmm1 \n\t" - "pxor %%xmm1, %%xmm2 \n\t" - "pslldq $4, %%xmm1 \n\t" - "pxor %%xmm1, %%xmm2 \n\t" - "pslldq $4, %%xmm1 \n\t" - "pxor %%xmm2, %%xmm1 \n\t" - "add $16, %0 \n\t" - "movdqu %%xmm1, (%0) \n\t" - "ret \n\t" - - /* - * Main "loop" - Generating one more key than necessary, - * see definition of mbedtls_aes_context.buf - */ - "2: \n\t" - AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" - AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" - : - : "r" (rk), "r" (key) - : "memory", "cc", "0" ); -} - -/* - * Key expansion, wrapper - */ -int mbedtls_aesni_setkey_enc( unsigned char *rk, - const unsigned char *key, - size_t bits ) -{ - switch( bits ) - { - case 128: aesni_setkey_enc_128( rk, key ); break; - case 192: aesni_setkey_enc_192( rk, key ); break; - case 256: aesni_setkey_enc_256( rk, key ); break; - default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); - } - - return( 0 ); -} - -#endif /* MBEDTLS_HAVE_X86_64 */ - -#endif /* MBEDTLS_AESNI_C */ diff --git a/components/mbedtls/library/arc4.c b/components/mbedtls/library/arc4.c deleted file mode 100644 index 05b33d3fdb..0000000000 --- a/components/mbedtls/library/arc4.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * An implementation of the ARCFOUR algorithm - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The ARCFOUR algorithm was publicly disclosed on 94/09. - * - * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_ARC4_C) - -#include "mbedtls/arc4.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_ARC4_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -void mbedtls_arc4_init( mbedtls_arc4_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_arc4_context ) ); -} - -void mbedtls_arc4_free( mbedtls_arc4_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_arc4_context ) ); -} - -/* - * ARC4 key schedule - */ -void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, - unsigned int keylen ) -{ - int i, j, a; - unsigned int k; - unsigned char *m; - - ctx->x = 0; - ctx->y = 0; - m = ctx->m; - - for( i = 0; i < 256; i++ ) - m[i] = (unsigned char) i; - - j = k = 0; - - for( i = 0; i < 256; i++, k++ ) - { - if( k >= keylen ) k = 0; - - a = m[i]; - j = ( j + a + key[k] ) & 0xFF; - m[i] = m[j]; - m[j] = (unsigned char) a; - } -} - -/* - * ARC4 cipher function - */ -int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, - unsigned char *output ) -{ - int x, y, a, b; - size_t i; - unsigned char *m; - - x = ctx->x; - y = ctx->y; - m = ctx->m; - - for( i = 0; i < length; i++ ) - { - x = ( x + 1 ) & 0xFF; a = m[x]; - y = ( y + a ) & 0xFF; b = m[y]; - - m[x] = (unsigned char) b; - m[y] = (unsigned char) a; - - output[i] = (unsigned char) - ( input[i] ^ m[(unsigned char)( a + b )] ); - } - - ctx->x = x; - ctx->y = y; - - return( 0 ); -} - -#endif /* !MBEDTLS_ARC4_ALT */ - -#if defined(MBEDTLS_SELF_TEST) -/* - * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994: - * - * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0 - */ -static const unsigned char arc4_test_key[3][8] = -{ - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}; - -static const unsigned char arc4_test_pt[3][8] = -{ - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}; - -static const unsigned char arc4_test_ct[3][8] = -{ - { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 }, - { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 }, - { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A } -}; - -/* - * Checkup routine - */ -int mbedtls_arc4_self_test( int verbose ) -{ - int i, ret = 0; - unsigned char ibuf[8]; - unsigned char obuf[8]; - mbedtls_arc4_context ctx; - - mbedtls_arc4_init( &ctx ); - - for( i = 0; i < 3; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " ARC4 test #%d: ", i + 1 ); - - memcpy( ibuf, arc4_test_pt[i], 8 ); - - mbedtls_arc4_setup( &ctx, arc4_test_key[i], 8 ); - mbedtls_arc4_crypt( &ctx, 8, ibuf, obuf ); - - if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -exit: - mbedtls_arc4_free( &ctx ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_ARC4_C */ diff --git a/components/mbedtls/library/asn1parse.c b/components/mbedtls/library/asn1parse.c deleted file mode 100644 index 4dd65c03c0..0000000000 --- a/components/mbedtls/library/asn1parse.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Generic ASN.1 parsing - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_ASN1_PARSE_C) - -#include "mbedtls/asn1.h" - -#include - -#if defined(MBEDTLS_BIGNUM_C) -#include "mbedtls/bignum.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -/* - * ASN.1 DER decoding routines - */ -int mbedtls_asn1_get_len( unsigned char **p, - const unsigned char *end, - size_t *len ) -{ - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - if( ( **p & 0x80 ) == 0 ) - *len = *(*p)++; - else - { - switch( **p & 0x7F ) - { - case 1: - if( ( end - *p ) < 2 ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - *len = (*p)[1]; - (*p) += 2; - break; - - case 2: - if( ( end - *p ) < 3 ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2]; - (*p) += 3; - break; - - case 3: - if( ( end - *p ) < 4 ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - *len = ( (size_t)(*p)[1] << 16 ) | - ( (size_t)(*p)[2] << 8 ) | (*p)[3]; - (*p) += 4; - break; - - case 4: - if( ( end - *p ) < 5 ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) | - ( (size_t)(*p)[3] << 8 ) | (*p)[4]; - (*p) += 5; - break; - - default: - return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); - } - } - - if( *len > (size_t) ( end - *p ) ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - return( 0 ); -} - -int mbedtls_asn1_get_tag( unsigned char **p, - const unsigned char *end, - size_t *len, int tag ) -{ - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - if( **p != tag ) - return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - (*p)++; - - return( mbedtls_asn1_get_len( p, end, len ) ); -} - -int mbedtls_asn1_get_bool( unsigned char **p, - const unsigned char *end, - int *val ) -{ - int ret; - size_t len; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 ) - return( ret ); - - if( len != 1 ) - return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); - - *val = ( **p != 0 ) ? 1 : 0; - (*p)++; - - return( 0 ); -} - -int mbedtls_asn1_get_int( unsigned char **p, - const unsigned char *end, - int *val ) -{ - int ret; - size_t len; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) - return( ret ); - - if( len == 0 || len > sizeof( int ) || ( **p & 0x80 ) != 0 ) - return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); - - *val = 0; - - while( len-- > 0 ) - { - *val = ( *val << 8 ) | **p; - (*p)++; - } - - return( 0 ); -} - -#if defined(MBEDTLS_BIGNUM_C) -int mbedtls_asn1_get_mpi( unsigned char **p, - const unsigned char *end, - mbedtls_mpi *X ) -{ - int ret; - size_t len; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) - return( ret ); - - ret = mbedtls_mpi_read_binary( X, *p, len ); - - *p += len; - - return( ret ); -} -#endif /* MBEDTLS_BIGNUM_C */ - -int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, - mbedtls_asn1_bitstring *bs) -{ - int ret; - - /* Certificate type is a single byte bitstring */ - if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) - return( ret ); - - /* Check length, subtract one for actual bit string length */ - if( bs->len < 1 ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - bs->len -= 1; - - /* Get number of unused bits, ensure unused bits <= 7 */ - bs->unused_bits = **p; - if( bs->unused_bits > 7 ) - return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); - (*p)++; - - /* Get actual bitstring */ - bs->p = *p; - *p += bs->len; - - if( *p != end ) - return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * Get a bit string without unused bits - */ -int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, - size_t *len ) -{ - int ret; - - if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) - return( ret ); - - if( (*len)-- < 2 || *(*p)++ != 0 ) - return( MBEDTLS_ERR_ASN1_INVALID_DATA ); - - return( 0 ); -} - - - -/* - * Parses and splits an ASN.1 "SEQUENCE OF " - */ -int mbedtls_asn1_get_sequence_of( unsigned char **p, - const unsigned char *end, - mbedtls_asn1_sequence *cur, - int tag) -{ - int ret; - size_t len; - mbedtls_asn1_buf *buf; - - /* Get main sequence tag */ - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( ret ); - - if( *p + len != end ) - return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - while( *p < end ) - { - buf = &(cur->buf); - buf->tag = **p; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &buf->len, tag ) ) != 0 ) - return( ret ); - - buf->p = *p; - *p += buf->len; - - /* Allocate and assign next pointer */ - if( *p < end ) - { - cur->next = (mbedtls_asn1_sequence*)mbedtls_calloc( 1, - sizeof( mbedtls_asn1_sequence ) ); - - if( cur->next == NULL ) - return( MBEDTLS_ERR_ASN1_ALLOC_FAILED ); - - cur = cur->next; - } - } - - /* Set final sequence entry's next pointer to NULL */ - cur->next = NULL; - - if( *p != end ) - return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -int mbedtls_asn1_get_alg( unsigned char **p, - const unsigned char *end, - mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ) -{ - int ret; - size_t len; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( ret ); - - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - alg->tag = **p; - end = *p + len; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &alg->len, MBEDTLS_ASN1_OID ) ) != 0 ) - return( ret ); - - alg->p = *p; - *p += alg->len; - - if( *p == end ) - { - mbedtls_zeroize( params, sizeof(mbedtls_asn1_buf) ); - return( 0 ); - } - - params->tag = **p; - (*p)++; - - if( ( ret = mbedtls_asn1_get_len( p, end, ¶ms->len ) ) != 0 ) - return( ret ); - - params->p = *p; - *p += params->len; - - if( *p != end ) - return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -int mbedtls_asn1_get_alg_null( unsigned char **p, - const unsigned char *end, - mbedtls_asn1_buf *alg ) -{ - int ret; - mbedtls_asn1_buf params; - - memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) ); - - if( ( ret = mbedtls_asn1_get_alg( p, end, alg, ¶ms ) ) != 0 ) - return( ret ); - - if( ( params.tag != MBEDTLS_ASN1_NULL && params.tag != 0 ) || params.len != 0 ) - return( MBEDTLS_ERR_ASN1_INVALID_DATA ); - - return( 0 ); -} - -void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur ) -{ - if( cur == NULL ) - return; - - mbedtls_free( cur->oid.p ); - mbedtls_free( cur->val.p ); - - mbedtls_zeroize( cur, sizeof( mbedtls_asn1_named_data ) ); -} - -void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ) -{ - mbedtls_asn1_named_data *cur; - - while( ( cur = *head ) != NULL ) - { - *head = cur->next; - mbedtls_asn1_free_named_data( cur ); - mbedtls_free( cur ); - } -} - -mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, - const char *oid, size_t len ) -{ - while( list != NULL ) - { - if( list->oid.len == len && - memcmp( list->oid.p, oid, len ) == 0 ) - { - break; - } - - list = list->next; - } - - return( list ); -} - -#endif /* MBEDTLS_ASN1_PARSE_C */ diff --git a/components/mbedtls/library/asn1write.c b/components/mbedtls/library/asn1write.c deleted file mode 100644 index 69b61b205f..0000000000 --- a/components/mbedtls/library/asn1write.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * ASN.1 buffer writing functionality - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_ASN1_WRITE_C) - -#include "mbedtls/asn1write.h" - -#include - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) -{ - if( len < 0x80 ) - { - if( *p - start < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = (unsigned char) len; - return( 1 ); - } - - if( len <= 0xFF ) - { - if( *p - start < 2 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = (unsigned char) len; - *--(*p) = 0x81; - return( 2 ); - } - - if( len <= 0xFFFF ) - { - if( *p - start < 3 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = ( len ) & 0xFF; - *--(*p) = ( len >> 8 ) & 0xFF; - *--(*p) = 0x82; - return( 3 ); - } - - if( len <= 0xFFFFFF ) - { - if( *p - start < 4 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = ( len ) & 0xFF; - *--(*p) = ( len >> 8 ) & 0xFF; - *--(*p) = ( len >> 16 ) & 0xFF; - *--(*p) = 0x83; - return( 4 ); - } - - if( len <= 0xFFFFFFFF ) - { - if( *p - start < 5 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = ( len ) & 0xFF; - *--(*p) = ( len >> 8 ) & 0xFF; - *--(*p) = ( len >> 16 ) & 0xFF; - *--(*p) = ( len >> 24 ) & 0xFF; - *--(*p) = 0x84; - return( 5 ); - } - - return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); -} - -int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) -{ - if( *p - start < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = tag; - - return( 1 ); -} - -int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t size ) -{ - size_t len = 0; - - if( *p < start || (size_t)( *p - start ) < size ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - len = size; - (*p) -= len; - memcpy( *p, buf, len ); - - return( (int) len ); -} - -#if defined(MBEDTLS_BIGNUM_C) -int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ) -{ - int ret; - size_t len = 0; - - // Write the MPI - // - len = mbedtls_mpi_size( X ); - - if( *p < start || (size_t)( *p - start ) < len ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - (*p) -= len; - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) ); - - // DER format assumes 2s complement for numbers, so the leftmost bit - // should be 0 for positive numbers and 1 for negative numbers. - // - if( X->s ==1 && **p & 0x80 ) - { - if( *p - start < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = 0x00; - len += 1; - } - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); - - ret = (int) len; - -cleanup: - return( ret ); -} -#endif /* MBEDTLS_BIGNUM_C */ - -int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ) -{ - int ret; - size_t len = 0; - - // Write NULL - // - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) ); - - return( (int) len ); -} - -int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len ) -{ - int ret; - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, - (const unsigned char *) oid, oid_len ) ); - MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); - - return( (int) len ); -} - -int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len, - size_t par_len ) -{ - int ret; - size_t len = 0; - - if( par_len == 0 ) - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) ); - else - len += par_len; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); - - return( (int) len ); -} - -int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) -{ - int ret; - size_t len = 0; - - if( *p - start < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = (boolean) ? 255 : 0; - len++; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) ); - - return( (int) len ); -} - -int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) -{ - int ret; - size_t len = 0; - - // TODO negative values and values larger than 128 - // DER format assumes 2s complement for numbers, so the leftmost bit - // should be 0 for positive numbers and 1 for negative numbers. - // - if( *p - start < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - len += 1; - *--(*p) = val; - - if( val > 0 && **p & 0x80 ) - { - if( *p - start < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = 0x00; - len += 1; - } - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); - - return( (int) len ); -} - -int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, - const char *text, size_t text_len ) -{ - int ret; - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, - (const unsigned char *) text, text_len ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_PRINTABLE_STRING ) ); - - return( (int) len ); -} - -int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, - const char *text, size_t text_len ) -{ - int ret; - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, - (const unsigned char *) text, text_len ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_IA5_STRING ) ); - - return( (int) len ); -} - -int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t bits ) -{ - int ret; - size_t len = 0, size; - - size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 ); - - // Calculate byte length - // - if( *p < start || (size_t)( *p - start ) < size + 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - len = size + 1; - (*p) -= size; - memcpy( *p, buf, size ); - - // Write unused bits - // - *--(*p) = (unsigned char) (size * 8 - bits); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); - - return( (int) len ); -} - -int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, - const unsigned char *buf, size_t size ) -{ - int ret; - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); - - return( (int) len ); -} - -mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **head, - const char *oid, size_t oid_len, - const unsigned char *val, - size_t val_len ) -{ - mbedtls_asn1_named_data *cur; - - if( ( cur = mbedtls_asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) - { - // Add new entry if not present yet based on OID - // - cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1, - sizeof(mbedtls_asn1_named_data) ); - if( cur == NULL ) - return( NULL ); - - cur->oid.len = oid_len; - cur->oid.p = mbedtls_calloc( 1, oid_len ); - if( cur->oid.p == NULL ) - { - mbedtls_free( cur ); - return( NULL ); - } - - memcpy( cur->oid.p, oid, oid_len ); - - cur->val.len = val_len; - cur->val.p = mbedtls_calloc( 1, val_len ); - if( cur->val.p == NULL ) - { - mbedtls_free( cur->oid.p ); - mbedtls_free( cur ); - return( NULL ); - } - - cur->next = *head; - *head = cur; - } - else if( cur->val.len < val_len ) - { - /* - * Enlarge existing value buffer if needed - * Preserve old data until the allocation succeeded, to leave list in - * a consistent state in case allocation fails. - */ - void *p = mbedtls_calloc( 1, val_len ); - if( p == NULL ) - return( NULL ); - - mbedtls_free( cur->val.p ); - cur->val.p = p; - cur->val.len = val_len; - } - - if( val != NULL ) - memcpy( cur->val.p, val, val_len ); - - return( cur ); -} -#endif /* MBEDTLS_ASN1_WRITE_C */ diff --git a/components/mbedtls/library/base64.c b/components/mbedtls/library/base64.c deleted file mode 100644 index f06b57b31f..0000000000 --- a/components/mbedtls/library/base64.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * RFC 1521 base64 encoding/decoding - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_BASE64_C) - -#include "mbedtls/base64.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#include -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -static const unsigned char base64_enc_map[64] = -{ - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', - 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '+', '/' -}; - -static const unsigned char base64_dec_map[128] = -{ - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, - 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, - 127, 64, 127, 127, 127, 0, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 127, 127, 127, 127, 127, 127, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 127, 127, 127, 127, 127 -}; - -#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ - -/* - * Encode a buffer into base64 format - */ -int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, - const unsigned char *src, size_t slen ) -{ - size_t i, n; - int C1, C2, C3; - unsigned char *p; - - if( slen == 0 ) - { - *olen = 0; - return( 0 ); - } - - n = slen / 3 + ( slen % 3 != 0 ); - - if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 ) - { - *olen = BASE64_SIZE_T_MAX; - return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); - } - - n *= 4; - - if( ( dlen < n + 1 ) || ( NULL == dst ) ) - { - *olen = n + 1; - return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); - } - - n = ( slen / 3 ) * 3; - - for( i = 0, p = dst; i < n; i += 3 ) - { - C1 = *src++; - C2 = *src++; - C3 = *src++; - - *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; - *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; - *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; - *p++ = base64_enc_map[C3 & 0x3F]; - } - - if( i < slen ) - { - C1 = *src++; - C2 = ( ( i + 1 ) < slen ) ? *src++ : 0; - - *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; - *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; - - if( ( i + 1 ) < slen ) - *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; - else *p++ = '='; - - *p++ = '='; - } - - *olen = p - dst; - *p = 0; - - return( 0 ); -} - -/* - * Decode a base64-formatted buffer - */ -int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, - const unsigned char *src, size_t slen ) -{ - size_t i, n; - uint32_t j, x; - unsigned char *p; - - /* First pass: check for validity and get output length */ - for( i = n = j = 0; i < slen; i++ ) - { - /* Skip spaces before checking for EOL */ - x = 0; - while( i < slen && src[i] == ' ' ) - { - ++i; - ++x; - } - - /* Spaces at end of buffer are OK */ - if( i == slen ) - break; - - if( ( slen - i ) >= 2 && - src[i] == '\r' && src[i + 1] == '\n' ) - continue; - - if( src[i] == '\n' ) - continue; - - /* Space inside a line is an error */ - if( x != 0 ) - return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); - - if( src[i] == '=' && ++j > 2 ) - return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); - - if( src[i] > 127 || base64_dec_map[src[i]] == 127 ) - return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); - - if( base64_dec_map[src[i]] < 64 && j != 0 ) - return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); - - n++; - } - - if( n == 0 ) - { - *olen = 0; - return( 0 ); - } - - /* The following expression is to calculate the following formula without - * risk of integer overflow in n: - * n = ( ( n * 6 ) + 7 ) >> 3; - */ - n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 ); - n -= j; - - if( dst == NULL || dlen < n ) - { - *olen = n; - return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); - } - - for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ ) - { - if( *src == '\r' || *src == '\n' || *src == ' ' ) - continue; - - j -= ( base64_dec_map[*src] == 64 ); - x = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F ); - - if( ++n == 4 ) - { - n = 0; - if( j > 0 ) *p++ = (unsigned char)( x >> 16 ); - if( j > 1 ) *p++ = (unsigned char)( x >> 8 ); - if( j > 2 ) *p++ = (unsigned char)( x ); - } - } - - *olen = p - dst; - - return( 0 ); -} - -#if defined(MBEDTLS_SELF_TEST) - -static const unsigned char base64_test_dec[64] = -{ - 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, - 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, - 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, - 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, - 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, - 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, - 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, - 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 -}; - -static const unsigned char base64_test_enc[] = - "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" - "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; - -/* - * Checkup routine - */ -int mbedtls_base64_self_test( int verbose ) -{ - size_t len; - const unsigned char *src; - unsigned char buffer[128]; - - if( verbose != 0 ) - mbedtls_printf( " Base64 encoding test: " ); - - src = base64_test_dec; - - if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 || - memcmp( base64_test_enc, buffer, 88 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n Base64 decoding test: " ); - - src = base64_test_enc; - - if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 || - memcmp( base64_test_dec, buffer, 64 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_BASE64_C */ diff --git a/components/mbedtls/library/bignum.c b/components/mbedtls/library/bignum.c deleted file mode 100644 index dad1976b64..0000000000 --- a/components/mbedtls/library/bignum.c +++ /dev/null @@ -1,2460 +0,0 @@ -/* - * Multi-precision integer library - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -/* - * The following sources were referenced in the design of this Multi-precision - * Integer library: - * - * [1] Handbook of Applied Cryptography - 1997 - * Menezes, van Oorschot and Vanstone - * - * [2] Multi-Precision Math - * Tom St Denis - * https://github.com/libtom/libtommath/blob/develop/tommath.pdf - * - * [3] GNU Multi-Precision Arithmetic Library - * https://gmplib.org/manual/index.html - * - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_BIGNUM_C) - -#include "mbedtls/bignum.h" -#include "mbedtls/bn_mul.h" - -#include - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_printf printf -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#if !defined(MBEDTLS_BIGNUM_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) { - volatile mbedtls_mpi_uint *p = v; while( n-- ) *p++ = 0; -} - -#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ -#define biL (ciL << 3) /* bits in limb */ -#define biH (ciL << 2) /* half limb size */ - -#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ - -/* - * Convert between bits/chars and number of limbs - * Divide first in order to avoid potential overflows - */ -#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) -#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) - -/* - * Initialize one MPI - */ -void mbedtls_mpi_init( mbedtls_mpi *X ) -{ - if( X == NULL ) - return; - - X->s = 1; - X->n = 0; - X->p = NULL; -} - -/* - * Unallocate one MPI - */ -void mbedtls_mpi_free( mbedtls_mpi *X ) -{ - if( X == NULL ) - return; - - if( X->p != NULL ) - { - mbedtls_mpi_zeroize( X->p, X->n ); - mbedtls_free( X->p ); - } - - X->s = 1; - X->n = 0; - X->p = NULL; -} - -/* - * Enlarge to the specified number of limbs - */ -int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) -{ - mbedtls_mpi_uint *p; - - if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) - return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); - - if( X->n < nblimbs ) - { - if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL ) - return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); - - if( X->p != NULL ) - { - memcpy( p, X->p, X->n * ciL ); - mbedtls_mpi_zeroize( X->p, X->n ); - mbedtls_free( X->p ); - } - - X->n = nblimbs; - X->p = p; - } - - return( 0 ); -} - -/* - * Resize down as much as possible, - * while keeping at least the specified number of limbs - */ -int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) -{ - mbedtls_mpi_uint *p; - size_t i; - - /* Actually resize up in this case */ - if( X->n <= nblimbs ) - return( mbedtls_mpi_grow( X, nblimbs ) ); - - for( i = X->n - 1; i > 0; i-- ) - if( X->p[i] != 0 ) - break; - i++; - - if( i < nblimbs ) - i = nblimbs; - - if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL ) - return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); - - if( X->p != NULL ) - { - memcpy( p, X->p, i * ciL ); - mbedtls_mpi_zeroize( X->p, X->n ); - mbedtls_free( X->p ); - } - - X->n = i; - X->p = p; - - return( 0 ); -} - -/* - * Copy the contents of Y into X - */ -int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) -{ - int ret; - size_t i; - - if( X == Y ) - return( 0 ); - - if( Y->p == NULL ) - { - mbedtls_mpi_free( X ); - return( 0 ); - } - - for( i = Y->n - 1; i > 0; i-- ) - if( Y->p[i] != 0 ) - break; - i++; - - X->s = Y->s; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); - - memset( X->p, 0, X->n * ciL ); - memcpy( X->p, Y->p, i * ciL ); - -cleanup: - - return( ret ); -} - -/* - * Swap the contents of X and Y - */ -void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) -{ - mbedtls_mpi T; - - memcpy( &T, X, sizeof( mbedtls_mpi ) ); - memcpy( X, Y, sizeof( mbedtls_mpi ) ); - memcpy( Y, &T, sizeof( mbedtls_mpi ) ); -} - -/* - * Conditionally assign X = Y, without leaking information - * about whether the assignment was made or not. - * (Leaking information about the respective sizes of X and Y is ok however.) - */ -int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ) -{ - int ret = 0; - size_t i; - - /* make sure assign is 0 or 1 in a time-constant manner */ - assign = (assign | (unsigned char)-assign) >> 7; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); - - X->s = X->s * ( 1 - assign ) + Y->s * assign; - - for( i = 0; i < Y->n; i++ ) - X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign; - - for( ; i < X->n; i++ ) - X->p[i] *= ( 1 - assign ); - -cleanup: - return( ret ); -} - -/* - * Conditionally swap X and Y, without leaking information - * about whether the swap was made or not. - * Here it is not ok to simply swap the pointers, which whould lead to - * different memory access patterns when X and Y are used afterwards. - */ -int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap ) -{ - int ret, s; - size_t i; - mbedtls_mpi_uint tmp; - - if( X == Y ) - return( 0 ); - - /* make sure swap is 0 or 1 in a time-constant manner */ - swap = (swap | (unsigned char)-swap) >> 7; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); - - s = X->s; - X->s = X->s * ( 1 - swap ) + Y->s * swap; - Y->s = Y->s * ( 1 - swap ) + s * swap; - - - for( i = 0; i < X->n; i++ ) - { - tmp = X->p[i]; - X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap; - Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap; - } - -cleanup: - return( ret ); -} - -/* - * Set value from integer - */ -int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) -{ - int ret; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); - memset( X->p, 0, X->n * ciL ); - - X->p[0] = ( z < 0 ) ? -z : z; - X->s = ( z < 0 ) ? -1 : 1; - -cleanup: - - return( ret ); -} - -/* - * Get a specific bit - */ -int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) -{ - if( X->n * biL <= pos ) - return( 0 ); - - return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); -} - -/* - * Set a bit to a specific value of 0 or 1 - */ -int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) -{ - int ret = 0; - size_t off = pos / biL; - size_t idx = pos % biL; - - if( val != 0 && val != 1 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - if( X->n * biL <= pos ) - { - if( val == 0 ) - return( 0 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); - } - - X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); - X->p[off] |= (mbedtls_mpi_uint) val << idx; - -cleanup: - - return( ret ); -} - -/* - * Return the number of less significant zero-bits - */ -size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) -{ - size_t i, j, count = 0; - - for( i = 0; i < X->n; i++ ) - for( j = 0; j < biL; j++, count++ ) - if( ( ( X->p[i] >> j ) & 1 ) != 0 ) - return( count ); - - return( 0 ); -} - -/* - * Count leading zero bits in a given integer - */ -static size_t mbedtls_clz( const mbedtls_mpi_uint x ) -{ - size_t j; - mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); - - for( j = 0; j < biL; j++ ) - { - if( x & mask ) break; - - mask >>= 1; - } - - return j; -} - -/* - * Return the number of bits - */ -size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) -{ - size_t i, j; - - if( X->n == 0 ) - return( 0 ); - - for( i = X->n - 1; i > 0; i-- ) - if( X->p[i] != 0 ) - break; - - j = biL - mbedtls_clz( X->p[i] ); - - return( ( i * biL ) + j ); -} - -/* - * Return the total size in bytes - */ -size_t mbedtls_mpi_size( const mbedtls_mpi *X ) -{ - return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); -} - -/* - * Convert an ASCII character to digit value - */ -static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) -{ - *d = 255; - - if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; - if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; - if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; - - if( *d >= (mbedtls_mpi_uint) radix ) - return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); - - return( 0 ); -} - -/* - * Import from an ASCII string - */ -int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) -{ - int ret; - size_t i, j, slen, n; - mbedtls_mpi_uint d; - mbedtls_mpi T; - - if( radix < 2 || radix > 16 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &T ); - - slen = strlen( s ); - - if( radix == 16 ) - { - if( slen > MPI_SIZE_T_MAX >> 2 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - n = BITS_TO_LIMBS( slen << 2 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); - - for( i = slen, j = 0; i > 0; i--, j++ ) - { - if( i == 1 && s[i - 1] == '-' ) - { - X->s = -1; - break; - } - - MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); - X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); - } - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); - - for( i = 0; i < slen; i++ ) - { - if( i == 0 && s[i] == '-' ) - { - X->s = -1; - continue; - } - - MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); - - if( X->s == 1 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) ); - } - } - } - -cleanup: - - mbedtls_mpi_free( &T ); - - return( ret ); -} - -/* - * Helper to write the digits high-order first - */ -static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p ) -{ - int ret; - mbedtls_mpi_uint r; - - if( radix < 2 || radix > 16 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); - - if( mbedtls_mpi_cmp_int( X, 0 ) != 0 ) - MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) ); - - if( r < 10 ) - *(*p)++ = (char)( r + 0x30 ); - else - *(*p)++ = (char)( r + 0x37 ); - -cleanup: - - return( ret ); -} - -/* - * Export into an ASCII string - */ -int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, - char *buf, size_t buflen, size_t *olen ) -{ - int ret = 0; - size_t n; - char *p; - mbedtls_mpi T; - - if( radix < 2 || radix > 16 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - n = mbedtls_mpi_bitlen( X ); - if( radix >= 4 ) n >>= 1; - if( radix >= 16 ) n >>= 1; - /* - * Round up the buffer length to an even value to ensure that there is - * enough room for hexadecimal values that can be represented in an odd - * number of digits. - */ - n += 3 + ( ( n + 1 ) & 1 ); - - if( buflen < n ) - { - *olen = n; - return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); - } - - p = buf; - mbedtls_mpi_init( &T ); - - if( X->s == -1 ) - *p++ = '-'; - - if( radix == 16 ) - { - int c; - size_t i, j, k; - - for( i = X->n, k = 0; i > 0; i-- ) - { - for( j = ciL; j > 0; j-- ) - { - c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; - - if( c == 0 && k == 0 && ( i + j ) != 2 ) - continue; - - *(p++) = "0123456789ABCDEF" [c / 16]; - *(p++) = "0123456789ABCDEF" [c % 16]; - k = 1; - } - } - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); - - if( T.s == -1 ) - T.s = 1; - - MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) ); - } - - *p++ = '\0'; - *olen = p - buf; - -cleanup: - - mbedtls_mpi_free( &T ); - - return( ret ); -} - -#if defined(MBEDTLS_FS_IO) -/* - * Read X from an opened file - */ -int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) -{ - mbedtls_mpi_uint d; - size_t slen; - char *p; - /* - * Buffer should have space for (short) label and decimal formatted MPI, - * newline characters and '\0' - */ - char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; - - memset( s, 0, sizeof( s ) ); - if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) - return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); - - slen = strlen( s ); - if( slen == sizeof( s ) - 2 ) - return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); - - if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } - if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } - - p = s + slen; - while( p-- > s ) - if( mpi_get_digit( &d, radix, *p ) != 0 ) - break; - - return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); -} - -/* - * Write X into an opened file (or stdout if fout == NULL) - */ -int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) -{ - int ret; - size_t n, slen, plen; - /* - * Buffer should have space for (short) label and decimal formatted MPI, - * newline characters and '\0' - */ - char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; - - memset( s, 0, sizeof( s ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); - - if( p == NULL ) p = ""; - - plen = strlen( p ); - slen = strlen( s ); - s[slen++] = '\r'; - s[slen++] = '\n'; - - if( fout != NULL ) - { - if( fwrite( p, 1, plen, fout ) != plen || - fwrite( s, 1, slen, fout ) != slen ) - return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); - } - else - mbedtls_printf( "%s%s", p, s ); - -cleanup: - - return( ret ); -} -#endif /* MBEDTLS_FS_IO */ - -/* - * Import X from unsigned binary data, big endian - */ -int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) -{ - int ret; - size_t i, j, n; - - for( n = 0; n < buflen; n++ ) - if( buf[n] != 0 ) - break; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); - - for( i = buflen, j = 0; i > n; i--, j++ ) - X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3); - -cleanup: - - return( ret ); -} - -/* - * Export X into unsigned binary data, big endian - */ -int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ) -{ - size_t i, j, n; - - n = mbedtls_mpi_size( X ); - - if( buflen < n ) - return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); - - memset( buf, 0, buflen ); - - for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) - buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); - - return( 0 ); -} - -/* - * Left-shift: X <<= count - */ -int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) -{ - int ret; - size_t i, v0, t1; - mbedtls_mpi_uint r0 = 0, r1; - - v0 = count / (biL ); - t1 = count & (biL - 1); - - i = mbedtls_mpi_bitlen( X ) + count; - - if( X->n * biL < i ) - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); - - ret = 0; - - /* - * shift by count / limb_size - */ - if( v0 > 0 ) - { - for( i = X->n; i > v0; i-- ) - X->p[i - 1] = X->p[i - v0 - 1]; - - for( ; i > 0; i-- ) - X->p[i - 1] = 0; - } - - /* - * shift by count % limb_size - */ - if( t1 > 0 ) - { - for( i = v0; i < X->n; i++ ) - { - r1 = X->p[i] >> (biL - t1); - X->p[i] <<= t1; - X->p[i] |= r0; - r0 = r1; - } - } - -cleanup: - - return( ret ); -} - -/* - * Right-shift: X >>= count - */ -int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) -{ - size_t i, v0, v1; - mbedtls_mpi_uint r0 = 0, r1; - - v0 = count / biL; - v1 = count & (biL - 1); - - if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) - return mbedtls_mpi_lset( X, 0 ); - - /* - * shift by count / limb_size - */ - if( v0 > 0 ) - { - for( i = 0; i < X->n - v0; i++ ) - X->p[i] = X->p[i + v0]; - - for( ; i < X->n; i++ ) - X->p[i] = 0; - } - - /* - * shift by count % limb_size - */ - if( v1 > 0 ) - { - for( i = X->n; i > 0; i-- ) - { - r1 = X->p[i - 1] << (biL - v1); - X->p[i - 1] >>= v1; - X->p[i - 1] |= r0; - r0 = r1; - } - } - - return( 0 ); -} - -/* - * Compare unsigned values - */ -int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) -{ - size_t i, j; - - for( i = X->n; i > 0; i-- ) - if( X->p[i - 1] != 0 ) - break; - - for( j = Y->n; j > 0; j-- ) - if( Y->p[j - 1] != 0 ) - break; - - if( i == 0 && j == 0 ) - return( 0 ); - - if( i > j ) return( 1 ); - if( j > i ) return( -1 ); - - for( ; i > 0; i-- ) - { - if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); - if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); - } - - return( 0 ); -} - -/* - * Compare signed values - */ -int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) -{ - size_t i, j; - - for( i = X->n; i > 0; i-- ) - if( X->p[i - 1] != 0 ) - break; - - for( j = Y->n; j > 0; j-- ) - if( Y->p[j - 1] != 0 ) - break; - - if( i == 0 && j == 0 ) - return( 0 ); - - if( i > j ) return( X->s ); - if( j > i ) return( -Y->s ); - - if( X->s > 0 && Y->s < 0 ) return( 1 ); - if( Y->s > 0 && X->s < 0 ) return( -1 ); - - for( ; i > 0; i-- ) - { - if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); - if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); - } - - return( 0 ); -} - -/* - * Compare signed values - */ -int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) -{ - mbedtls_mpi Y; - mbedtls_mpi_uint p[1]; - - *p = ( z < 0 ) ? -z : z; - Y.s = ( z < 0 ) ? -1 : 1; - Y.n = 1; - Y.p = p; - - return( mbedtls_mpi_cmp_mpi( X, &Y ) ); -} - -/* - * Unsigned addition: X = |A| + |B| (HAC 14.7) - */ -int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret; - size_t i, j; - mbedtls_mpi_uint *o, *p, c, tmp; - - if( X == B ) - { - const mbedtls_mpi *T = A; A = X; B = T; - } - - if( X != A ) - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); - - /* - * X should always be positive as a result of unsigned additions. - */ - X->s = 1; - - for( j = B->n; j > 0; j-- ) - if( B->p[j - 1] != 0 ) - break; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); - - o = B->p; p = X->p; c = 0; - - /* - * tmp is used because it might happen that p == o - */ - for( i = 0; i < j; i++, o++, p++ ) - { - tmp= *o; - *p += c; c = ( *p < c ); - *p += tmp; c += ( *p < tmp ); - } - - while( c != 0 ) - { - if( i >= X->n ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) ); - p = X->p + i; - } - - *p += c; c = ( *p < c ); i++; p++; - } - -cleanup: - - return( ret ); -} - -/* - * Helper for mbedtls_mpi subtraction - */ -static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d ) -{ - size_t i; - mbedtls_mpi_uint c, z; - - for( i = c = 0; i < n; i++, s++, d++ ) - { - z = ( *d < c ); *d -= c; - c = ( *d < *s ) + z; *d -= *s; - } - - while( c != 0 ) - { - z = ( *d < c ); *d -= c; - c = z; i++; d++; - } -} - -/* - * Unsigned subtraction: X = |A| - |B| (HAC 14.9) - */ -int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - mbedtls_mpi TB; - int ret; - size_t n; - - if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) - return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); - - mbedtls_mpi_init( &TB ); - - if( X == B ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); - B = &TB; - } - - if( X != A ) - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); - - /* - * X should always be positive as a result of unsigned subtractions. - */ - X->s = 1; - - ret = 0; - - for( n = B->n; n > 0; n-- ) - if( B->p[n - 1] != 0 ) - break; - - mpi_sub_hlp( n, B->p, X->p ); - -cleanup: - - mbedtls_mpi_free( &TB ); - - return( ret ); -} - -/* - * Signed addition: X = A + B - */ -int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret, s = A->s; - - if( A->s * B->s < 0 ) - { - if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); - X->s = s; - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); - X->s = -s; - } - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); - X->s = s; - } - -cleanup: - - return( ret ); -} - -/* - * Signed subtraction: X = A - B - */ -int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret, s = A->s; - - if( A->s * B->s > 0 ) - { - if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); - X->s = s; - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); - X->s = -s; - } - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); - X->s = s; - } - -cleanup: - - return( ret ); -} - -/* - * Signed addition: X = A + b - */ -int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) -{ - mbedtls_mpi _B; - mbedtls_mpi_uint p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mbedtls_mpi_add_mpi( X, A, &_B ) ); -} - -/* - * Signed subtraction: X = A - b - */ -int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) -{ - mbedtls_mpi _B; - mbedtls_mpi_uint p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mbedtls_mpi_sub_mpi( X, A, &_B ) ); -} - -#if !defined(MBEDTLS_MPI_MUL_MPI_ALT) || !defined(MBEDTLS_MPI_EXP_MOD_ALT) - -/* - * Helper for mbedtls_mpi multiplication - */ -static -#if defined(__APPLE__) && defined(__arm__) -/* - * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) - * appears to need this to prevent bad ARM code generation at -O3. - */ -__attribute__ ((noinline)) -#endif - -void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b ) -{ - mbedtls_mpi_uint c = 0, t = 0; - -#if defined(MULADDC_HUIT) - for( ; i >= 8; i -= 8 ) - { - MULADDC_INIT - MULADDC_HUIT - MULADDC_STOP - } - - for( ; i > 0; i-- ) - { - MULADDC_INIT - MULADDC_CORE - MULADDC_STOP - } -#else /* MULADDC_HUIT */ - for( ; i >= 16; i -= 16 ) - { - MULADDC_INIT - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_STOP - } - - for( ; i >= 8; i -= 8 ) - { - MULADDC_INIT - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_STOP - } - - for( ; i > 0; i-- ) - { - MULADDC_INIT - MULADDC_CORE - MULADDC_STOP - } -#endif /* MULADDC_HUIT */ - - t++; - - do { - *d += c; c = ( *d < c ); d++; - } - while( c != 0 ); -} - -#endif - -#if !defined(MBEDTLS_MPI_MUL_MPI_ALT) -/* - * Baseline multiplication: X = A * B (HAC 14.12) - */ -int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret; - size_t i, j; - mbedtls_mpi TA, TB; - - mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); - - if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } - if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } - - for( i = A->n; i > 0; i-- ) - if( A->p[i - 1] != 0 ) - break; - - for( j = B->n; j > 0; j-- ) - if( B->p[j - 1] != 0 ) - break; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); - - for( i++; j > 0; j-- ) - mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] ); - - X->s = A->s * B->s; - -cleanup: - - mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); - - return( ret ); -} -#endif - -/* - * Baseline multiplication: X = A * b - */ -int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) -{ - mbedtls_mpi _B; - mbedtls_mpi_uint p[1]; - - _B.s = 1; - _B.n = 1; - _B.p = p; - p[0] = b; - - return( mbedtls_mpi_mul_mpi( X, A, &_B ) ); -} - -/* - * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and - * mbedtls_mpi_uint divisor, d - */ -static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, - mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r ) -{ -#if defined(MBEDTLS_HAVE_UDBL) - mbedtls_t_udbl dividend, quotient; -#else - const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; - const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1; - mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; - mbedtls_mpi_uint u0_msw, u0_lsw; - size_t s; -#endif - - /* - * Check for overflow - */ - if( 0 == d || u1 >= d ) - { - if (r != NULL) *r = ~0; - - return ( ~0 ); - } - -#if defined(MBEDTLS_HAVE_UDBL) - dividend = (mbedtls_t_udbl) u1 << biL; - dividend |= (mbedtls_t_udbl) u0; - quotient = dividend / d; - if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 ) - quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1; - - if( r != NULL ) - *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) ); - - return (mbedtls_mpi_uint) quotient; -#else - - /* - * Algorithm D, Section 4.3.1 - The Art of Computer Programming - * Vol. 2 - Seminumerical Algorithms, Knuth - */ - - /* - * Normalize the divisor, d, and dividend, u0, u1 - */ - s = mbedtls_clz( d ); - d = d << s; - - u1 = u1 << s; - u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) ); - u0 = u0 << s; - - d1 = d >> biH; - d0 = d & uint_halfword_mask; - - u0_msw = u0 >> biH; - u0_lsw = u0 & uint_halfword_mask; - - /* - * Find the first quotient and remainder - */ - q1 = u1 / d1; - r0 = u1 - d1 * q1; - - while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) ) - { - q1 -= 1; - r0 += d1; - - if ( r0 >= radix ) break; - } - - rAX = ( u1 * radix ) + ( u0_msw - q1 * d ); - q0 = rAX / d1; - r0 = rAX - q0 * d1; - - while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) ) - { - q0 -= 1; - r0 += d1; - - if ( r0 >= radix ) break; - } - - if (r != NULL) - *r = ( rAX * radix + u0_lsw - q0 * d ) >> s; - - quotient = q1 * radix + q0; - - return quotient; -#endif -} - -/* - * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) - */ -int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret; - size_t i, n, t, k; - mbedtls_mpi X, Y, Z, T1, T2; - - if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) - return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); - - mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); - mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); - - if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) - { - if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) ); - if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) ); - return( 0 ); - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) ); - X.s = Y.s = 1; - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) ); - - k = mbedtls_mpi_bitlen( &Y ) % biL; - if( k < biL - 1 ) - { - k = biL - 1 - k; - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) ); - } - else k = 0; - - n = X.n - 1; - t = Y.n - 1; - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) ); - - while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 ) - { - Z.p[n - t]++; - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) ); - } - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) ); - - for( i = n; i > t ; i-- ) - { - if( X.p[i] >= Y.p[t] ) - Z.p[i - t - 1] = ~0; - else - { - Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], - Y.p[t], NULL); - } - - Z.p[i - t - 1]++; - do - { - Z.p[i - t - 1]--; - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) ); - T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; - T1.p[1] = Y.p[t]; - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) ); - T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; - T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; - T2.p[2] = X.p[i]; - } - while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); - - if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) ); - Z.p[i - t - 1]--; - } - } - - if( Q != NULL ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) ); - Q->s = A->s * B->s; - } - - if( R != NULL ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) ); - X.s = A->s; - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) ); - - if( mbedtls_mpi_cmp_int( R, 0 ) == 0 ) - R->s = 1; - } - -cleanup: - - mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); - mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); - - return( ret ); -} - -/* - * Division by int: A = Q * b + R - */ -int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ) -{ - mbedtls_mpi _B; - mbedtls_mpi_uint p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) ); -} - -/* - * Modulo: R = A mod B - */ -int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret; - - if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) - return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) ); - - while( mbedtls_mpi_cmp_int( R, 0 ) < 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) ); - - while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) ); - -cleanup: - - return( ret ); -} - -/* - * Modulo: r = A mod b - */ -int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ) -{ - size_t i; - mbedtls_mpi_uint x, y, z; - - if( b == 0 ) - return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); - - if( b < 0 ) - return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); - - /* - * handle trivial cases - */ - if( b == 1 ) - { - *r = 0; - return( 0 ); - } - - if( b == 2 ) - { - *r = A->p[0] & 1; - return( 0 ); - } - - /* - * general case - */ - for( i = A->n, y = 0; i > 0; i-- ) - { - x = A->p[i - 1]; - y = ( y << biH ) | ( x >> biH ); - z = y / b; - y -= z * b; - - x <<= biH; - y = ( y << biH ) | ( x >> biH ); - z = y / b; - y -= z * b; - } - - /* - * If A is negative, then the current y represents a negative value. - * Flipping it to the positive side. - */ - if( A->s < 0 && y != 0 ) - y = b - y; - - *r = y; - - return( 0 ); -} - -#if !defined(MBEDTLS_MPI_EXP_MOD_ALT) - -/* - * Fast Montgomery initialization (thanks to Tom St Denis) - */ -static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) -{ - mbedtls_mpi_uint x, m0 = N->p[0]; - unsigned int i; - - x = m0; - x += ( ( m0 + 2 ) & 4 ) << 1; - - for( i = biL; i >= 8; i /= 2 ) - x *= ( 2 - ( m0 * x ) ); - - *mm = ~x + 1; -} - -/* - * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) - */ -static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, - const mbedtls_mpi *T ) -{ - size_t i, n, m; - mbedtls_mpi_uint u0, u1, *d; - - if( T->n < N->n + 1 || T->p == NULL ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - memset( T->p, 0, T->n * ciL ); - - d = T->p; - n = N->n; - m = ( B->n < n ) ? B->n : n; - - for( i = 0; i < n; i++ ) - { - /* - * T = (T + u0*B + u1*N) / 2^biL - */ - u0 = A->p[i]; - u1 = ( d[0] + u0 * B->p[0] ) * mm; - - mpi_mul_hlp( m, B->p, d, u0 ); - mpi_mul_hlp( n, N->p, d, u1 ); - - *d++ = u0; d[n + 1] = 0; - } - - memcpy( A->p, d, ( n + 1 ) * ciL ); - - if( mbedtls_mpi_cmp_abs( A, N ) >= 0 ) - mpi_sub_hlp( n, N->p, A->p ); - else - /* prevent timing attacks */ - mpi_sub_hlp( n, A->p, T->p ); - - return( 0 ); -} - -/* - * Montgomery reduction: A = A * R^-1 mod N - */ -static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T ) -{ - mbedtls_mpi_uint z = 1; - mbedtls_mpi U; - - U.n = U.s = (int) z; - U.p = &z; - - return( mpi_montmul( A, &U, N, mm, T ) ); -} - -/* - * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) - */ -int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ) -{ - int ret; - size_t wbits, wsize, one = 1; - size_t i, j, nblimbs; - size_t bufsize, nbits; - mbedtls_mpi_uint ei, mm, state; - mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; - int neg; - - if( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - /* - * Init temps and window size - */ - mpi_montg_init( &mm, N ); - mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); - mbedtls_mpi_init( &Apos ); - memset( W, 0, sizeof( W ) ); - - i = mbedtls_mpi_bitlen( E ); - - wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : - ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; - - if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) - wsize = MBEDTLS_MPI_WINDOW_SIZE; - - j = N->n + 1; - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); - - /* - * Compensate for negative A (and correct at the end) - */ - neg = ( A->s == -1 ); - if( neg ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); - Apos.s = 1; - A = &Apos; - } - - /* - * If 1st call, pre-compute R^2 mod N - */ - if( _RR == NULL || _RR->p == NULL ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); - - if( _RR != NULL ) - memcpy( _RR, &RR, sizeof( mbedtls_mpi ) ); - } - else - memcpy( &RR, _RR, sizeof( mbedtls_mpi ) ); - - /* - * W[1] = A * R^2 * R^-1 mod N = A * R mod N - */ - if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); - else - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); - - MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) ); - - /* - * X = R^2 * R^-1 mod N = R mod N - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); - MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); - - if( wsize > 1 ) - { - /* - * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) - */ - j = one << ( wsize - 1 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); - - for( i = 0; i < wsize - 1; i++ ) - MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) ); - - /* - * W[i] = W[i - 1] * W[1] - */ - for( i = j + 1; i < ( one << wsize ); i++ ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); - - MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) ); - } - } - - nblimbs = E->n; - bufsize = 0; - nbits = 0; - wbits = 0; - state = 0; - - while( 1 ) - { - if( bufsize == 0 ) - { - if( nblimbs == 0 ) - break; - - nblimbs--; - - bufsize = sizeof( mbedtls_mpi_uint ) << 3; - } - - bufsize--; - - ei = (E->p[nblimbs] >> bufsize) & 1; - - /* - * skip leading 0s - */ - if( ei == 0 && state == 0 ) - continue; - - if( ei == 0 && state == 1 ) - { - /* - * out of window, square X - */ - MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); - continue; - } - - /* - * add ei to current window - */ - state = 2; - - nbits++; - wbits |= ( ei << ( wsize - nbits ) ); - - if( nbits == wsize ) - { - /* - * X = X^wsize R^-1 mod N - */ - for( i = 0; i < wsize; i++ ) - MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); - - /* - * X = X * W[wbits] R^-1 mod N - */ - MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) ); - - state--; - nbits = 0; - wbits = 0; - } - } - - /* - * process the remaining bits - */ - for( i = 0; i < nbits; i++ ) - { - MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); - - wbits <<= 1; - - if( ( wbits & ( one << wsize ) ) != 0 ) - MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) ); - } - - /* - * X = A^E * R * R^-1 mod N = A^E mod N - */ - MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); - - if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) - { - X->s = -1; - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); - } - -cleanup: - - for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) - mbedtls_mpi_free( &W[i] ); - - mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); - - if( _RR == NULL || _RR->p == NULL ) - mbedtls_mpi_free( &RR ); - - return( ret ); -} -#endif - -/* - * Greatest common divisor: G = gcd(A, B) (HAC 14.54) - */ -int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ) -{ - int ret; - size_t lz, lzt; - mbedtls_mpi TG, TA, TB; - - mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); - - lz = mbedtls_mpi_lsb( &TA ); - lzt = mbedtls_mpi_lsb( &TB ); - - if( lzt < lz ) - lz = lzt; - - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) ); - - TA.s = TB.s = 1; - - while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) ); - - if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) ); - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) ); - } - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) ); - -cleanup: - - mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB ); - - return( ret ); -} - -/* - * Fill X with size bytes of random. - * - * Use a temporary bytes representation to make sure the result is the same - * regardless of the platform endianness (useful when f_rng is actually - * deterministic, eg for tests). - */ -int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; - - if( size > MBEDTLS_MPI_MAX_SIZE ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) ); - -cleanup: - return( ret ); -} - -/* - * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) - */ -int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) -{ - int ret; - mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; - - if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); - mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV ); - mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); - - if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) - { - ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; - goto cleanup; - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); - - do - { - while( ( TU.p[0] & 1 ) == 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); - - if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); - } - - while( ( TV.p[0] & 1 ) == 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); - - if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); - } - - if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); - } - } - while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); - - while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); - - while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); - -cleanup: - - mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); - mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); - mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); - - return( ret ); -} - -#if defined(MBEDTLS_GENPRIME) - -static const int small_prime[] = -{ - 3, 5, 7, 11, 13, 17, 19, 23, - 29, 31, 37, 41, 43, 47, 53, 59, - 61, 67, 71, 73, 79, 83, 89, 97, - 101, 103, 107, 109, 113, 127, 131, 137, - 139, 149, 151, 157, 163, 167, 173, 179, - 181, 191, 193, 197, 199, 211, 223, 227, - 229, 233, 239, 241, 251, 257, 263, 269, - 271, 277, 281, 283, 293, 307, 311, 313, - 317, 331, 337, 347, 349, 353, 359, 367, - 373, 379, 383, 389, 397, 401, 409, 419, - 421, 431, 433, 439, 443, 449, 457, 461, - 463, 467, 479, 487, 491, 499, 503, 509, - 521, 523, 541, 547, 557, 563, 569, 571, - 577, 587, 593, 599, 601, 607, 613, 617, - 619, 631, 641, 643, 647, 653, 659, 661, - 673, 677, 683, 691, 701, 709, 719, 727, - 733, 739, 743, 751, 757, 761, 769, 773, - 787, 797, 809, 811, 821, 823, 827, 829, - 839, 853, 857, 859, 863, 877, 881, 883, - 887, 907, 911, 919, 929, 937, 941, 947, - 953, 967, 971, 977, 983, 991, 997, -103 -}; - -/* - * Small divisors test (X must be positive) - * - * Return values: - * 0: no small factor (possible prime, more tests needed) - * 1: certain prime - * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime - * other negative: error - */ -static int mpi_check_small_factors( const mbedtls_mpi *X ) -{ - int ret = 0; - size_t i; - mbedtls_mpi_uint r; - - if( ( X->p[0] & 1 ) == 0 ) - return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); - - for( i = 0; small_prime[i] > 0; i++ ) - { - if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) - return( 1 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); - - if( r == 0 ) - return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); - } - -cleanup: - return( ret ); -} - -/* - * Miller-Rabin pseudo-primality test (HAC 4.24) - */ -static int mpi_miller_rabin( const mbedtls_mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret, count; - size_t i, j, k, n, s; - mbedtls_mpi W, R, T, A, RR; - - mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); - mbedtls_mpi_init( &RR ); - - /* - * W = |X| - 1 - * R = W >> lsb( W ) - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); - s = mbedtls_mpi_lsb( &W ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); - - i = mbedtls_mpi_bitlen( X ); - /* - * HAC, table 4.4 - */ - n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : - ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : - ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); - - for( i = 0; i < n; i++ ) - { - /* - * pick a random A, 1 < A < |X| - 1 - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); - - if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ) - { - j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) ); - } - A.p[0] |= 3; - - count = 0; - do { - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); - - j = mbedtls_mpi_bitlen( &A ); - k = mbedtls_mpi_bitlen( &W ); - if (j > k) { - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) ); - } - - if (count++ > 30) { - return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; - } - - } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || - mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); - - /* - * A = A^R mod |X| - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); - - if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || - mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) - continue; - - j = 1; - while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) - { - /* - * A = A * A mod |X| - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); - - if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) - break; - - j++; - } - - /* - * not prime if A != |X| - 1 or A == 1 - */ - if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || - mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) - { - ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; - break; - } - } - -cleanup: - mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); - mbedtls_mpi_free( &RR ); - - return( ret ); -} - -/* - * Pseudo-primality test: small factors, then Miller-Rabin - */ -int mbedtls_mpi_is_prime( const mbedtls_mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_mpi XX; - - XX.s = 1; - XX.n = X->n; - XX.p = X->p; - - if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || - mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) - return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); - - if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) - return( 0 ); - - if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) - { - if( ret == 1 ) - return( 0 ); - - return( ret ); - } - - return( mpi_miller_rabin( &XX, f_rng, p_rng ) ); -} - -/* - * Prime number generation - */ -int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - size_t k, n; - mbedtls_mpi_uint r; - mbedtls_mpi Y; - - if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) - return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &Y ); - - n = BITS_TO_LIMBS( nbits ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); - - k = mbedtls_mpi_bitlen( X ); - if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) ); - - mbedtls_mpi_set_bit( X, nbits-1, 1 ); - - X->p[0] |= 1; - - if( dh_flag == 0 ) - { - while( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) - { - if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; - - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) ); - } - } - else - { - /* - * An necessary condition for Y and X = 2Y + 1 to be prime - * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). - * Make sure it is satisfied, while keeping X = 3 mod 4 - */ - - X->p[0] |= 2; - - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); - if( r == 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); - else if( r == 1 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); - - /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); - - while( 1 ) - { - /* - * First, check small factors for X and Y - * before doing Miller-Rabin on any of them - */ - if( ( ret = mpi_check_small_factors( X ) ) == 0 && - ( ret = mpi_check_small_factors( &Y ) ) == 0 && - ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 && - ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 ) - { - break; - } - - if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; - - /* - * Next candidates. We want to preserve Y = (X-1) / 2 and - * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) - * so up Y by 6 and X by 12. - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); - } - } - -cleanup: - - mbedtls_mpi_free( &Y ); - - return( ret ); -} - -#endif /* MBEDTLS_GENPRIME */ -#endif /* MBEDTLS_BIGNUM_ALT */ - -#if defined(MBEDTLS_SELF_TEST) - -#define GCD_PAIR_COUNT 3 - -static const int gcd_pairs[GCD_PAIR_COUNT][3] = -{ - { 693, 609, 21 }, - { 1764, 868, 28 }, - { 768454923, 542167814, 1 } -}; - -/* - * Checkup routine - */ -int mbedtls_mpi_self_test( int verbose ) -{ - int ret, i; - mbedtls_mpi A, E, N, X, Y, U, V; - - mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X ); - mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16, - "EFE021C2645FD1DC586E69184AF4A31E" \ - "D5F53E93B5F123FA41680867BA110131" \ - "944FE7952E2517337780CB0DB80E61AA" \ - "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16, - "B2E7EFD37075B9F03FF989C7C5051C20" \ - "34D2A323810251127E7BF8625A4F49A5" \ - "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ - "5B5C25763222FEFCCFC38B832366C29E" ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16, - "0066A198186C18C10B2F5ED9B522752A" \ - "9830B69916E535C8F047518A889A43A5" \ - "94B6BED27A168D31D4A52F88925AA8F5" ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, - "602AB7ECA597A3D6B56FF9829A5E8B85" \ - "9E857EA95A03512E2BAE7391688D264A" \ - "A5663B0341DB9CCFD2C4C5F421FEC814" \ - "8001B72E848A38CAE1C65F78E56ABDEF" \ - "E12D3C039B8A02D6BE593F0BBBDA56F1" \ - "ECF677152EF804370C1A305CAF3B5BF1" \ - "30879B56C61DE584A0F53A2447A51E" ) ); - - if( verbose != 0 ) - mbedtls_printf( " MPI test #1 (mul_mpi): " ); - - if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto cleanup; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, - "256567336059E52CAE22925474705F39A94" ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16, - "6613F26162223DF488E9CD48CC132C7A" \ - "0AC93C701B001B092E4E5B9F73BCD27B" \ - "9EE50D0657C77F374E903CDFA4C642" ) ); - - if( verbose != 0 ) - mbedtls_printf( " MPI test #2 (div_mpi): " ); - - if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 || - mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto cleanup; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, - "36E139AEA55215609D2816998ED020BB" \ - "BD96C37890F65171D948E9BC7CBAA4D9" \ - "325D24D6A3C12710F10A09FA08AB87" ) ); - - if( verbose != 0 ) - mbedtls_printf( " MPI test #3 (exp_mod): " ); - - if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto cleanup; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, - "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ - "C3DBA76456363A10869622EAC2DD84EC" \ - "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); - - if( verbose != 0 ) - mbedtls_printf( " MPI test #4 (inv_mod): " ); - - if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto cleanup; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " MPI test #5 (simple gcd): " ); - - for( i = 0; i < GCD_PAIR_COUNT; i++ ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) ); - - if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed at %d\n", i ); - - ret = 1; - goto cleanup; - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - -cleanup: - - if( ret != 0 && verbose != 0 ) - mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); - - mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X ); - mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V ); - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_BIGNUM_C */ diff --git a/components/mbedtls/library/blowfish.c b/components/mbedtls/library/blowfish.c deleted file mode 100644 index 9003f0dfeb..0000000000 --- a/components/mbedtls/library/blowfish.c +++ /dev/null @@ -1,656 +0,0 @@ -/* - * Blowfish implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The Blowfish block cipher was designed by Bruce Schneier in 1993. - * http://www.schneier.com/blowfish.html - * http://en.wikipedia.org/wiki/Blowfish_%28cipher%29 - * - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_BLOWFISH_C) - -#include "mbedtls/blowfish.h" - -#include - -#if !defined(MBEDTLS_BLOWFISH_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT32_BE -#define GET_UINT32_BE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ - | ( (uint32_t) (b)[(i) + 1] << 16 ) \ - | ( (uint32_t) (b)[(i) + 2] << 8 ) \ - | ( (uint32_t) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_UINT32_BE -#define PUT_UINT32_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -static const uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2] = { - 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L, - 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L, - 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL, - 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L, - 0x9216D5D9L, 0x8979FB1BL -}; - -/* declarations of data at the end of this file */ -static const uint32_t S[4][256]; - -static uint32_t F( mbedtls_blowfish_context *ctx, uint32_t x ) -{ - unsigned short a, b, c, d; - uint32_t y; - - d = (unsigned short)(x & 0xFF); - x >>= 8; - c = (unsigned short)(x & 0xFF); - x >>= 8; - b = (unsigned short)(x & 0xFF); - x >>= 8; - a = (unsigned short)(x & 0xFF); - y = ctx->S[0][a] + ctx->S[1][b]; - y = y ^ ctx->S[2][c]; - y = y + ctx->S[3][d]; - - return( y ); -} - -static void blowfish_enc( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) -{ - uint32_t Xl, Xr, temp; - short i; - - Xl = *xl; - Xr = *xr; - - for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS; ++i ) - { - Xl = Xl ^ ctx->P[i]; - Xr = F( ctx, Xl ) ^ Xr; - - temp = Xl; - Xl = Xr; - Xr = temp; - } - - temp = Xl; - Xl = Xr; - Xr = temp; - - Xr = Xr ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS]; - Xl = Xl ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS + 1]; - - *xl = Xl; - *xr = Xr; -} - -static void blowfish_dec( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) -{ - uint32_t Xl, Xr, temp; - short i; - - Xl = *xl; - Xr = *xr; - - for( i = MBEDTLS_BLOWFISH_ROUNDS + 1; i > 1; --i ) - { - Xl = Xl ^ ctx->P[i]; - Xr = F( ctx, Xl ) ^ Xr; - - temp = Xl; - Xl = Xr; - Xr = temp; - } - - temp = Xl; - Xl = Xr; - Xr = temp; - - Xr = Xr ^ ctx->P[1]; - Xl = Xl ^ ctx->P[0]; - - *xl = Xl; - *xr = Xr; -} - -void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_blowfish_context ) ); -} - -void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_blowfish_context ) ); -} - -/* - * Blowfish key schedule - */ -int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, - unsigned int keybits ) -{ - unsigned int i, j, k; - uint32_t data, datal, datar; - - if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS || - ( keybits % 8 ) ) - { - return( MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH ); - } - - keybits >>= 3; - - for( i = 0; i < 4; i++ ) - { - for( j = 0; j < 256; j++ ) - ctx->S[i][j] = S[i][j]; - } - - j = 0; - for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; ++i ) - { - data = 0x00000000; - for( k = 0; k < 4; ++k ) - { - data = ( data << 8 ) | key[j++]; - if( j >= keybits ) - j = 0; - } - ctx->P[i] = P[i] ^ data; - } - - datal = 0x00000000; - datar = 0x00000000; - - for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; i += 2 ) - { - blowfish_enc( ctx, &datal, &datar ); - ctx->P[i] = datal; - ctx->P[i + 1] = datar; - } - - for( i = 0; i < 4; i++ ) - { - for( j = 0; j < 256; j += 2 ) - { - blowfish_enc( ctx, &datal, &datar ); - ctx->S[i][j] = datal; - ctx->S[i][j + 1] = datar; - } - } - return( 0 ); -} - -/* - * Blowfish-ECB block encryption/decryption - */ -int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, - int mode, - const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], - unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ) -{ - uint32_t X0, X1; - - GET_UINT32_BE( X0, input, 0 ); - GET_UINT32_BE( X1, input, 4 ); - - if( mode == MBEDTLS_BLOWFISH_DECRYPT ) - { - blowfish_dec( ctx, &X0, &X1 ); - } - else /* MBEDTLS_BLOWFISH_ENCRYPT */ - { - blowfish_enc( ctx, &X0, &X1 ); - } - - PUT_UINT32_BE( X0, output, 0 ); - PUT_UINT32_BE( X1, output, 4 ); - - return( 0 ); -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/* - * Blowfish-CBC buffer encryption/decryption - */ -int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, - int mode, - size_t length, - unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[MBEDTLS_BLOWFISH_BLOCKSIZE]; - - if( length % MBEDTLS_BLOWFISH_BLOCKSIZE ) - return( MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH ); - - if( mode == MBEDTLS_BLOWFISH_DECRYPT ) - { - while( length > 0 ) - { - memcpy( temp, input, MBEDTLS_BLOWFISH_BLOCKSIZE ); - mbedtls_blowfish_crypt_ecb( ctx, mode, input, output ); - - for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE;i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, MBEDTLS_BLOWFISH_BLOCKSIZE ); - - input += MBEDTLS_BLOWFISH_BLOCKSIZE; - output += MBEDTLS_BLOWFISH_BLOCKSIZE; - length -= MBEDTLS_BLOWFISH_BLOCKSIZE; - } - } - else - { - while( length > 0 ) - { - for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - mbedtls_blowfish_crypt_ecb( ctx, mode, output, output ); - memcpy( iv, output, MBEDTLS_BLOWFISH_BLOCKSIZE ); - - input += MBEDTLS_BLOWFISH_BLOCKSIZE; - output += MBEDTLS_BLOWFISH_BLOCKSIZE; - length -= MBEDTLS_BLOWFISH_BLOCKSIZE; - } - } - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -/* - * Blowfish CFB buffer encryption/decryption - */ -int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], - const unsigned char *input, - unsigned char *output ) -{ - int c; - size_t n = *iv_off; - - if( mode == MBEDTLS_BLOWFISH_DECRYPT ) - { - while( length-- ) - { - if( n == 0 ) - mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); - - c = *input++; - *output++ = (unsigned char)( c ^ iv[n] ); - iv[n] = (unsigned char) c; - - n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; - } - } - else - { - while( length-- ) - { - if( n == 0 ) - mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); - - iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); - - n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; - } - } - - *iv_off = n; - - return( 0 ); -} -#endif /*MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -/* - * Blowfish CTR buffer encryption/decryption - */ -int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], - unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], - const unsigned char *input, - unsigned char *output ) -{ - int c, i; - size_t n = *nc_off; - - while( length-- ) - { - if( n == 0 ) { - mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, nonce_counter, - stream_block ); - - for( i = MBEDTLS_BLOWFISH_BLOCKSIZE; i > 0; i-- ) - if( ++nonce_counter[i - 1] != 0 ) - break; - } - c = *input++; - *output++ = (unsigned char)( c ^ stream_block[n] ); - - n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; - } - - *nc_off = n; - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -static const uint32_t S[4][256] = { - { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L, - 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L, - 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L, - 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL, - 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL, - 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L, - 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL, - 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL, - 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L, - 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L, - 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL, - 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL, - 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL, - 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L, - 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L, - 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L, - 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L, - 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L, - 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL, - 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L, - 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L, - 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L, - 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L, - 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL, - 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L, - 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL, - 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL, - 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L, - 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL, - 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L, - 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL, - 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L, - 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L, - 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL, - 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L, - 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L, - 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL, - 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L, - 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL, - 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L, - 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L, - 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL, - 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L, - 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L, - 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L, - 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L, - 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L, - 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL, - 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL, - 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L, - 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L, - 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L, - 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L, - 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL, - 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L, - 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL, - 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL, - 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L, - 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L, - 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L, - 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L, - 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L, - 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L, - 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL }, - { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L, - 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L, - 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L, - 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL, - 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L, - 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L, - 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL, - 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L, - 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L, - 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L, - 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL, - 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL, - 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L, - 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L, - 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L, - 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L, - 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL, - 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL, - 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL, - 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L, - 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL, - 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L, - 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L, - 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL, - 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL, - 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L, - 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL, - 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L, - 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL, - 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL, - 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L, - 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L, - 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L, - 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L, - 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L, - 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L, - 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L, - 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL, - 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L, - 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL, - 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L, - 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L, - 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L, - 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L, - 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L, - 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L, - 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L, - 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L, - 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L, - 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L, - 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L, - 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L, - 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L, - 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L, - 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L, - 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L, - 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL, - 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL, - 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L, - 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL, - 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L, - 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L, - 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L, - 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L }, - { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L, - 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L, - 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL, - 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L, - 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L, - 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L, - 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL, - 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL, - 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL, - 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L, - 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L, - 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL, - 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L, - 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL, - 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L, - 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL, - 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L, - 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL, - 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L, - 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL, - 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L, - 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L, - 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL, - 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L, - 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L, - 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L, - 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L, - 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL, - 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L, - 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL, - 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L, - 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL, - 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L, - 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL, - 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL, - 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL, - 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L, - 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L, - 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL, - 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL, - 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL, - 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL, - 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL, - 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L, - 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L, - 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L, - 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L, - 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL, - 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL, - 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L, - 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L, - 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L, - 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L, - 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L, - 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L, - 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L, - 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L, - 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L, - 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L, - 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL, - 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L, - 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL, - 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L, - 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L }, - { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL, - 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL, - 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL, - 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L, - 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L, - 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L, - 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L, - 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L, - 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L, - 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L, - 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L, - 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L, - 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L, - 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L, - 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L, - 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL, - 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL, - 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L, - 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL, - 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL, - 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL, - 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L, - 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL, - 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL, - 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L, - 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L, - 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L, - 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L, - 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL, - 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL, - 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L, - 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L, - 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L, - 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL, - 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L, - 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L, - 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L, - 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL, - 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L, - 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L, - 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L, - 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL, - 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL, - 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L, - 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L, - 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L, - 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L, - 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL, - 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L, - 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL, - 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL, - 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L, - 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L, - 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL, - 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L, - 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL, - 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L, - 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL, - 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L, - 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L, - 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL, - 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L, - 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL, - 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L } -}; - -#endif /* !MBEDTLS_BLOWFISH_ALT */ -#endif /* MBEDTLS_BLOWFISH_C */ diff --git a/components/mbedtls/library/camellia.c b/components/mbedtls/library/camellia.c deleted file mode 100644 index ac6f96a83a..0000000000 --- a/components/mbedtls/library/camellia.c +++ /dev/null @@ -1,1072 +0,0 @@ -/* - * Camellia implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The Camellia block cipher was designed by NTT and Mitsubishi Electric - * Corporation. - * - * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_CAMELLIA_C) - -#include "mbedtls/camellia.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_CAMELLIA_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT32_BE -#define GET_UINT32_BE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ - | ( (uint32_t) (b)[(i) + 1] << 16 ) \ - | ( (uint32_t) (b)[(i) + 2] << 8 ) \ - | ( (uint32_t) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_UINT32_BE -#define PUT_UINT32_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -static const unsigned char SIGMA_CHARS[6][8] = -{ - { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b }, - { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 }, - { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe }, - { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c }, - { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d }, - { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd } -}; - -#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) - -static const unsigned char FSb[256] = -{ - 112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65, - 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189, - 134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26, - 166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77, - 139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153, - 223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215, - 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34, - 254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80, - 170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210, - 16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148, - 135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226, - 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46, - 233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89, - 120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250, - 114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164, - 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158 -}; - -#define SBOX1(n) FSb[(n)] -#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff) -#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff) -#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff] - -#else /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ - -static const unsigned char FSb[256] = -{ - 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, - 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, - 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26, - 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77, - 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, - 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, - 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, - 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80, - 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210, - 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148, - 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226, - 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, - 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, - 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250, - 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164, - 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158 -}; - -static const unsigned char FSb2[256] = -{ - 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130, - 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123, - 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52, - 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154, - 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51, - 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175, - 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68, - 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160, - 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165, - 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41, - 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197, - 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92, - 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178, - 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245, - 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73, - 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61 -}; - -static const unsigned char FSb3[256] = -{ - 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160, - 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222, - 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13, - 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166, - 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204, - 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235, - 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17, - 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40, - 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105, - 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74, - 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113, - 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23, - 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172, - 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125, - 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82, - 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79 -}; - -static const unsigned char FSb4[256] = -{ - 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146, - 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108, - 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4, - 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105, - 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221, - 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99, - 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141, - 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128, - 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189, - 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77, - 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215, - 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80, - 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148, - 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46, - 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250, - 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158 -}; - -#define SBOX1(n) FSb[(n)] -#define SBOX2(n) FSb2[(n)] -#define SBOX3(n) FSb3[(n)] -#define SBOX4(n) FSb4[(n)] - -#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ - -static const unsigned char shifts[2][4][4] = -{ - { - { 1, 1, 1, 1 }, /* KL */ - { 0, 0, 0, 0 }, /* KR */ - { 1, 1, 1, 1 }, /* KA */ - { 0, 0, 0, 0 } /* KB */ - }, - { - { 1, 0, 1, 1 }, /* KL */ - { 1, 1, 0, 1 }, /* KR */ - { 1, 1, 1, 0 }, /* KA */ - { 1, 1, 0, 1 } /* KB */ - } -}; - -static const signed char indexes[2][4][20] = -{ - { - { 0, 1, 2, 3, 8, 9, 10, 11, 38, 39, - 36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */ - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */ - { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, - 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */ - { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */ - }, - { - { 0, 1, 2, 3, 61, 62, 63, 60, -1, -1, - -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */ - { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17, - 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */ - { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59, - 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */ - { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21, - 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */ - } -}; - -static const signed char transposes[2][20] = -{ - { - 21, 22, 23, 20, - -1, -1, -1, -1, - 18, 19, 16, 17, - 11, 8, 9, 10, - 15, 12, 13, 14 - }, - { - 25, 26, 27, 24, - 29, 30, 31, 28, - 18, 19, 16, 17, - -1, -1, -1, -1, - -1, -1, -1, -1 - } -}; - -/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */ -#define ROTL(DEST, SRC, SHIFT) \ -{ \ - (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \ - (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \ - (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \ - (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \ -} - -#define FL(XL, XR, KL, KR) \ -{ \ - (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR); \ - (XL) = ((XR) | (KR)) ^ (XL); \ -} - -#define FLInv(YL, YR, KL, KR) \ -{ \ - (YL) = ((YR) | (KR)) ^ (YL); \ - (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR); \ -} - -#define SHIFT_AND_PLACE(INDEX, OFFSET) \ -{ \ - TK[0] = KC[(OFFSET) * 4 + 0]; \ - TK[1] = KC[(OFFSET) * 4 + 1]; \ - TK[2] = KC[(OFFSET) * 4 + 2]; \ - TK[3] = KC[(OFFSET) * 4 + 3]; \ - \ - for( i = 1; i <= 4; i++ ) \ - if( shifts[(INDEX)][(OFFSET)][i -1] ) \ - ROTL(TK + i * 4, TK, ( 15 * i ) % 32); \ - \ - for( i = 0; i < 20; i++ ) \ - if( indexes[(INDEX)][(OFFSET)][i] != -1 ) { \ - RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ]; \ - } \ -} - -static void camellia_feistel( const uint32_t x[2], const uint32_t k[2], - uint32_t z[2]) -{ - uint32_t I0, I1; - I0 = x[0] ^ k[0]; - I1 = x[1] ^ k[1]; - - I0 = ((uint32_t) SBOX1((I0 >> 24) & 0xFF) << 24) | - ((uint32_t) SBOX2((I0 >> 16) & 0xFF) << 16) | - ((uint32_t) SBOX3((I0 >> 8) & 0xFF) << 8) | - ((uint32_t) SBOX4((I0 ) & 0xFF) ); - I1 = ((uint32_t) SBOX2((I1 >> 24) & 0xFF) << 24) | - ((uint32_t) SBOX3((I1 >> 16) & 0xFF) << 16) | - ((uint32_t) SBOX4((I1 >> 8) & 0xFF) << 8) | - ((uint32_t) SBOX1((I1 ) & 0xFF) ); - - I0 ^= (I1 << 8) | (I1 >> 24); - I1 ^= (I0 << 16) | (I0 >> 16); - I0 ^= (I1 >> 8) | (I1 << 24); - I1 ^= (I0 >> 8) | (I0 << 24); - - z[0] ^= I1; - z[1] ^= I0; -} - -void mbedtls_camellia_init( mbedtls_camellia_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_camellia_context ) ); -} - -void mbedtls_camellia_free( mbedtls_camellia_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_camellia_context ) ); -} - -/* - * Camellia key schedule (encryption) - */ -int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned char *key, - unsigned int keybits ) -{ - int idx; - size_t i; - uint32_t *RK; - unsigned char t[64]; - uint32_t SIGMA[6][2]; - uint32_t KC[16]; - uint32_t TK[20]; - - RK = ctx->rk; - - memset( t, 0, 64 ); - memset( RK, 0, sizeof(ctx->rk) ); - - switch( keybits ) - { - case 128: ctx->nr = 3; idx = 0; break; - case 192: - case 256: ctx->nr = 4; idx = 1; break; - default : return( MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH ); - } - - for( i = 0; i < keybits / 8; ++i ) - t[i] = key[i]; - - if( keybits == 192 ) { - for( i = 0; i < 8; i++ ) - t[24 + i] = ~t[16 + i]; - } - - /* - * Prepare SIGMA values - */ - for( i = 0; i < 6; i++ ) { - GET_UINT32_BE( SIGMA[i][0], SIGMA_CHARS[i], 0 ); - GET_UINT32_BE( SIGMA[i][1], SIGMA_CHARS[i], 4 ); - } - - /* - * Key storage in KC - * Order: KL, KR, KA, KB - */ - memset( KC, 0, sizeof(KC) ); - - /* Store KL, KR */ - for( i = 0; i < 8; i++ ) - GET_UINT32_BE( KC[i], t, i * 4 ); - - /* Generate KA */ - for( i = 0; i < 4; ++i ) - KC[8 + i] = KC[i] ^ KC[4 + i]; - - camellia_feistel( KC + 8, SIGMA[0], KC + 10 ); - camellia_feistel( KC + 10, SIGMA[1], KC + 8 ); - - for( i = 0; i < 4; ++i ) - KC[8 + i] ^= KC[i]; - - camellia_feistel( KC + 8, SIGMA[2], KC + 10 ); - camellia_feistel( KC + 10, SIGMA[3], KC + 8 ); - - if( keybits > 128 ) { - /* Generate KB */ - for( i = 0; i < 4; ++i ) - KC[12 + i] = KC[4 + i] ^ KC[8 + i]; - - camellia_feistel( KC + 12, SIGMA[4], KC + 14 ); - camellia_feistel( KC + 14, SIGMA[5], KC + 12 ); - } - - /* - * Generating subkeys - */ - - /* Manipulating KL */ - SHIFT_AND_PLACE( idx, 0 ); - - /* Manipulating KR */ - if( keybits > 128 ) { - SHIFT_AND_PLACE( idx, 1 ); - } - - /* Manipulating KA */ - SHIFT_AND_PLACE( idx, 2 ); - - /* Manipulating KB */ - if( keybits > 128 ) { - SHIFT_AND_PLACE( idx, 3 ); - } - - /* Do transpositions */ - for( i = 0; i < 20; i++ ) { - if( transposes[idx][i] != -1 ) { - RK[32 + 12 * idx + i] = RK[transposes[idx][i]]; - } - } - - return( 0 ); -} - -/* - * Camellia key schedule (decryption) - */ -int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, const unsigned char *key, - unsigned int keybits ) -{ - int idx, ret; - size_t i; - mbedtls_camellia_context cty; - uint32_t *RK; - uint32_t *SK; - - mbedtls_camellia_init( &cty ); - - /* Also checks keybits */ - if( ( ret = mbedtls_camellia_setkey_enc( &cty, key, keybits ) ) != 0 ) - goto exit; - - ctx->nr = cty.nr; - idx = ( ctx->nr == 4 ); - - RK = ctx->rk; - SK = cty.rk + 24 * 2 + 8 * idx * 2; - - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - - for( i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4 ) - { - *RK++ = *SK++; - *RK++ = *SK++; - } - - SK -= 2; - - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - -exit: - mbedtls_camellia_free( &cty ); - - return( ret ); -} - -/* - * Camellia-ECB block encryption/decryption - */ -int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ) -{ - int NR; - uint32_t *RK, X[4]; - - ( (void) mode ); - - NR = ctx->nr; - RK = ctx->rk; - - GET_UINT32_BE( X[0], input, 0 ); - GET_UINT32_BE( X[1], input, 4 ); - GET_UINT32_BE( X[2], input, 8 ); - GET_UINT32_BE( X[3], input, 12 ); - - X[0] ^= *RK++; - X[1] ^= *RK++; - X[2] ^= *RK++; - X[3] ^= *RK++; - - while( NR ) { - --NR; - camellia_feistel( X, RK, X + 2 ); - RK += 2; - camellia_feistel( X + 2, RK, X ); - RK += 2; - camellia_feistel( X, RK, X + 2 ); - RK += 2; - camellia_feistel( X + 2, RK, X ); - RK += 2; - camellia_feistel( X, RK, X + 2 ); - RK += 2; - camellia_feistel( X + 2, RK, X ); - RK += 2; - - if( NR ) { - FL(X[0], X[1], RK[0], RK[1]); - RK += 2; - FLInv(X[2], X[3], RK[0], RK[1]); - RK += 2; - } - } - - X[2] ^= *RK++; - X[3] ^= *RK++; - X[0] ^= *RK++; - X[1] ^= *RK++; - - PUT_UINT32_BE( X[2], output, 0 ); - PUT_UINT32_BE( X[3], output, 4 ); - PUT_UINT32_BE( X[0], output, 8 ); - PUT_UINT32_BE( X[1], output, 12 ); - - return( 0 ); -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/* - * Camellia-CBC buffer encryption/decryption - */ -int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[16]; - - if( length % 16 ) - return( MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH ); - - if( mode == MBEDTLS_CAMELLIA_DECRYPT ) - { - while( length > 0 ) - { - memcpy( temp, input, 16 ); - mbedtls_camellia_crypt_ecb( ctx, mode, input, output ); - - for( i = 0; i < 16; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 16 ); - - input += 16; - output += 16; - length -= 16; - } - } - else - { - while( length > 0 ) - { - for( i = 0; i < 16; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - mbedtls_camellia_crypt_ecb( ctx, mode, output, output ); - memcpy( iv, output, 16 ); - - input += 16; - output += 16; - length -= 16; - } - } - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -/* - * Camellia-CFB128 buffer encryption/decryption - */ -int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int c; - size_t n = *iv_off; - - if( mode == MBEDTLS_CAMELLIA_DECRYPT ) - { - while( length-- ) - { - if( n == 0 ) - mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); - - c = *input++; - *output++ = (unsigned char)( c ^ iv[n] ); - iv[n] = (unsigned char) c; - - n = ( n + 1 ) & 0x0F; - } - } - else - { - while( length-- ) - { - if( n == 0 ) - mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); - - iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); - - n = ( n + 1 ) & 0x0F; - } - } - - *iv_off = n; - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -/* - * Camellia-CTR buffer encryption/decryption - */ -int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[16], - unsigned char stream_block[16], - const unsigned char *input, - unsigned char *output ) -{ - int c, i; - size_t n = *nc_off; - - while( length-- ) - { - if( n == 0 ) { - mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, nonce_counter, - stream_block ); - - for( i = 16; i > 0; i-- ) - if( ++nonce_counter[i - 1] != 0 ) - break; - } - c = *input++; - *output++ = (unsigned char)( c ^ stream_block[n] ); - - n = ( n + 1 ) & 0x0F; - } - - *nc_off = n; - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CTR */ -#endif /* !MBEDTLS_CAMELLIA_ALT */ - -#if defined(MBEDTLS_SELF_TEST) - -/* - * Camellia test vectors from: - * - * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html: - * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt - * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt - * (For each bitlength: Key 0, Nr 39) - */ -#define CAMELLIA_TESTS_ECB 2 - -static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] = -{ - { - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - }, - { - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - }, - { - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, - 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, - 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } - }, -}; - -static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] = -{ - { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, - { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } -}; - -static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] = -{ - { - { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, - 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 }, - { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE, - 0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 } - }, - { - { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, - 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 }, - { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9, - 0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 } - }, - { - { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, - 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 }, - { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C, - 0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 } - } -}; - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#define CAMELLIA_TESTS_CBC 3 - -static const unsigned char camellia_test_cbc_key[3][32] = -{ - { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, - 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } - , - { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, - 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, - 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B } - , - { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, - 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, - 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, - 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } -}; - -static const unsigned char camellia_test_cbc_iv[16] = - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F } -; - -static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] = -{ - { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, - 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A }, - { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, - 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 }, - { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, - 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF } - -}; - -static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] = -{ - { - { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0, - 0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB }, - { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78, - 0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 }, - { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B, - 0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 } - }, - { - { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2, - 0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 }, - { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42, - 0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 }, - { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8, - 0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 } - }, - { - { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A, - 0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA }, - { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40, - 0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 }, - { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA, - 0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 } - } -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -/* - * Camellia-CTR test vectors from: - * - * http://www.faqs.org/rfcs/rfc5528.html - */ - -static const unsigned char camellia_test_ctr_key[3][16] = -{ - { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, - 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, - { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, - 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, - { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, - 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } -}; - -static const unsigned char camellia_test_ctr_nonce_counter[3][16] = -{ - { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, - 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, - { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, - 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } -}; - -static const unsigned char camellia_test_ctr_pt[3][48] = -{ - { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, - 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, - 0x20, 0x21, 0x22, 0x23 } -}; - -static const unsigned char camellia_test_ctr_ct[3][48] = -{ - { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A, - 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F }, - { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4, - 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44, - 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7, - 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 }, - { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88, - 0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73, - 0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1, - 0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD, - 0xDF, 0x50, 0x86, 0x96 } -}; - -static const int camellia_test_ctr_len[3] = - { 16, 32, 36 }; -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -/* - * Checkup routine - */ -int mbedtls_camellia_self_test( int verbose ) -{ - int i, j, u, v; - unsigned char key[32]; - unsigned char buf[64]; - unsigned char src[16]; - unsigned char dst[16]; -#if defined(MBEDTLS_CIPHER_MODE_CBC) - unsigned char iv[16]; -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - size_t offset, len; - unsigned char nonce_counter[16]; - unsigned char stream_block[16]; -#endif - - mbedtls_camellia_context ctx; - - memset( key, 0, 32 ); - - for( j = 0; j < 6; j++ ) { - u = j >> 1; - v = j & 1; - - if( verbose != 0 ) - mbedtls_printf( " CAMELLIA-ECB-%3d (%s): ", 128 + u * 64, - (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); - - for( i = 0; i < CAMELLIA_TESTS_ECB; i++ ) { - memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u ); - - if( v == MBEDTLS_CAMELLIA_DECRYPT ) { - mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); - memcpy( src, camellia_test_ecb_cipher[u][i], 16 ); - memcpy( dst, camellia_test_ecb_plain[i], 16 ); - } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ - mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); - memcpy( src, camellia_test_ecb_plain[i], 16 ); - memcpy( dst, camellia_test_ecb_cipher[u][i], 16 ); - } - - mbedtls_camellia_crypt_ecb( &ctx, v, src, buf ); - - if( memcmp( buf, dst, 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - /* - * CBC mode - */ - for( j = 0; j < 6; j++ ) - { - u = j >> 1; - v = j & 1; - - if( verbose != 0 ) - mbedtls_printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64, - ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); - - memcpy( src, camellia_test_cbc_iv, 16 ); - memcpy( dst, camellia_test_cbc_iv, 16 ); - memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u ); - - if( v == MBEDTLS_CAMELLIA_DECRYPT ) { - mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); - } else { - mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); - } - - for( i = 0; i < CAMELLIA_TESTS_CBC; i++ ) { - - if( v == MBEDTLS_CAMELLIA_DECRYPT ) { - memcpy( iv , src, 16 ); - memcpy( src, camellia_test_cbc_cipher[u][i], 16 ); - memcpy( dst, camellia_test_cbc_plain[i], 16 ); - } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ - memcpy( iv , dst, 16 ); - memcpy( src, camellia_test_cbc_plain[i], 16 ); - memcpy( dst, camellia_test_cbc_cipher[u][i], 16 ); - } - - mbedtls_camellia_crypt_cbc( &ctx, v, 16, iv, src, buf ); - - if( memcmp( buf, dst, 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -#if defined(MBEDTLS_CIPHER_MODE_CTR) - /* - * CTR mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - mbedtls_printf( " CAMELLIA-CTR-128 (%s): ", - ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); - - memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 ); - memcpy( key, camellia_test_ctr_key[u], 16 ); - - offset = 0; - mbedtls_camellia_setkey_enc( &ctx, key, 128 ); - - if( v == MBEDTLS_CAMELLIA_DECRYPT ) - { - len = camellia_test_ctr_len[u]; - memcpy( buf, camellia_test_ctr_ct[u], len ); - - mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, - buf, buf ); - - if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - else - { - len = camellia_test_ctr_len[u]; - memcpy( buf, camellia_test_ctr_pt[u], len ); - - mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, - buf, buf ); - - if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_CAMELLIA_C */ diff --git a/components/mbedtls/library/ccm.c b/components/mbedtls/library/ccm.c deleted file mode 100644 index 13a8fd1a24..0000000000 --- a/components/mbedtls/library/ccm.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * NIST SP800-38C compliant CCM implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -/* - * Definition of CCM: - * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf - * RFC 3610 "Counter with CBC-MAC (CCM)" - * - * Related: - * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_CCM_C) - -#include "mbedtls/ccm.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -#define CCM_ENCRYPT 0 -#define CCM_DECRYPT 1 - -/* - * Initialize context - */ -void mbedtls_ccm_init( mbedtls_ccm_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_ccm_context ) ); -} - -int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, - mbedtls_cipher_id_t cipher, - const unsigned char *key, - unsigned int keybits ) -{ - int ret; - const mbedtls_cipher_info_t *cipher_info; - - cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); - if( cipher_info == NULL ) - return( MBEDTLS_ERR_CCM_BAD_INPUT ); - - if( cipher_info->block_size != 16 ) - return( MBEDTLS_ERR_CCM_BAD_INPUT ); - - mbedtls_cipher_free( &ctx->cipher_ctx ); - - if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, - MBEDTLS_ENCRYPT ) ) != 0 ) - { - return( ret ); - } - - return( 0 ); -} - -/* - * Free context - */ -void mbedtls_ccm_free( mbedtls_ccm_context *ctx ) -{ - mbedtls_cipher_free( &ctx->cipher_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_ccm_context ) ); -} - -/* - * Macros for common operations. - * Results in smaller compiled code than static inline functions. - */ - -/* - * Update the CBC-MAC state in y using a block in b - * (Always using b as the source helps the compiler optimise a bit better.) - */ -#define UPDATE_CBC_MAC \ - for( i = 0; i < 16; i++ ) \ - y[i] ^= b[i]; \ - \ - if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \ - return( ret ); - -/* - * Encrypt or decrypt a partial block with CTR - * Warning: using b for temporary storage! src and dst must not be b! - * This avoids allocating one more 16 bytes buffer while allowing src == dst. - */ -#define CTR_CRYPT( dst, src, len ) \ - if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr, 16, b, &olen ) ) != 0 ) \ - return( ret ); \ - \ - for( i = 0; i < len; i++ ) \ - dst[i] = src[i] ^ b[i]; - -/* - * Authenticated encryption or decryption - */ -static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, - const unsigned char *iv, size_t iv_len, - const unsigned char *add, size_t add_len, - const unsigned char *input, unsigned char *output, - unsigned char *tag, size_t tag_len ) -{ - int ret; - unsigned char i; - unsigned char q; - size_t len_left, olen; - unsigned char b[16]; - unsigned char y[16]; - unsigned char ctr[16]; - const unsigned char *src; - unsigned char *dst; - - /* - * Check length requirements: SP800-38C A.1 - * Additional requirement: a < 2^16 - 2^8 to simplify the code. - * 'length' checked later (when writing it to the first block) - */ - if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 ) - return( MBEDTLS_ERR_CCM_BAD_INPUT ); - - /* Also implies q is within bounds */ - if( iv_len < 7 || iv_len > 13 ) - return( MBEDTLS_ERR_CCM_BAD_INPUT ); - - if( add_len > 0xFF00 ) - return( MBEDTLS_ERR_CCM_BAD_INPUT ); - - q = 16 - 1 - (unsigned char) iv_len; - - /* - * First block B_0: - * 0 .. 0 flags - * 1 .. iv_len nonce (aka iv) - * iv_len+1 .. 15 length - * - * With flags as (bits): - * 7 0 - * 6 add present? - * 5 .. 3 (t - 2) / 2 - * 2 .. 0 q - 1 - */ - b[0] = 0; - b[0] |= ( add_len > 0 ) << 6; - b[0] |= ( ( tag_len - 2 ) / 2 ) << 3; - b[0] |= q - 1; - - memcpy( b + 1, iv, iv_len ); - - for( i = 0, len_left = length; i < q; i++, len_left >>= 8 ) - b[15-i] = (unsigned char)( len_left & 0xFF ); - - if( len_left > 0 ) - return( MBEDTLS_ERR_CCM_BAD_INPUT ); - - - /* Start CBC-MAC with first block */ - memset( y, 0, 16 ); - UPDATE_CBC_MAC; - - /* - * If there is additional data, update CBC-MAC with - * add_len, add, 0 (padding to a block boundary) - */ - if( add_len > 0 ) - { - size_t use_len; - len_left = add_len; - src = add; - - memset( b, 0, 16 ); - b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF ); - b[1] = (unsigned char)( ( add_len ) & 0xFF ); - - use_len = len_left < 16 - 2 ? len_left : 16 - 2; - memcpy( b + 2, src, use_len ); - len_left -= use_len; - src += use_len; - - UPDATE_CBC_MAC; - - while( len_left > 0 ) - { - use_len = len_left > 16 ? 16 : len_left; - - memset( b, 0, 16 ); - memcpy( b, src, use_len ); - UPDATE_CBC_MAC; - - len_left -= use_len; - src += use_len; - } - } - - /* - * Prepare counter block for encryption: - * 0 .. 0 flags - * 1 .. iv_len nonce (aka iv) - * iv_len+1 .. 15 counter (initially 1) - * - * With flags as (bits): - * 7 .. 3 0 - * 2 .. 0 q - 1 - */ - ctr[0] = q - 1; - memcpy( ctr + 1, iv, iv_len ); - memset( ctr + 1 + iv_len, 0, q ); - ctr[15] = 1; - - /* - * Authenticate and {en,de}crypt the message. - * - * The only difference between encryption and decryption is - * the respective order of authentication and {en,de}cryption. - */ - len_left = length; - src = input; - dst = output; - - while( len_left > 0 ) - { - size_t use_len = len_left > 16 ? 16 : len_left; - - if( mode == CCM_ENCRYPT ) - { - memset( b, 0, 16 ); - memcpy( b, src, use_len ); - UPDATE_CBC_MAC; - } - - CTR_CRYPT( dst, src, use_len ); - - if( mode == CCM_DECRYPT ) - { - memset( b, 0, 16 ); - memcpy( b, dst, use_len ); - UPDATE_CBC_MAC; - } - - dst += use_len; - src += use_len; - len_left -= use_len; - - /* - * Increment counter. - * No need to check for overflow thanks to the length check above. - */ - for( i = 0; i < q; i++ ) - if( ++ctr[15-i] != 0 ) - break; - } - - /* - * Authentication: reset counter and crypt/mask internal tag - */ - for( i = 0; i < q; i++ ) - ctr[15-i] = 0; - - CTR_CRYPT( y, y, 16 ); - memcpy( tag, y, tag_len ); - - return( 0 ); -} - -/* - * Authenticated encryption - */ -int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, - const unsigned char *iv, size_t iv_len, - const unsigned char *add, size_t add_len, - const unsigned char *input, unsigned char *output, - unsigned char *tag, size_t tag_len ) -{ - return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len, - add, add_len, input, output, tag, tag_len ) ); -} - -/* - * Authenticated decryption - */ -int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, - const unsigned char *iv, size_t iv_len, - const unsigned char *add, size_t add_len, - const unsigned char *input, unsigned char *output, - const unsigned char *tag, size_t tag_len ) -{ - int ret; - unsigned char check_tag[16]; - unsigned char i; - int diff; - - if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length, - iv, iv_len, add, add_len, - input, output, check_tag, tag_len ) ) != 0 ) - { - return( ret ); - } - - /* Check tag in "constant-time" */ - for( diff = 0, i = 0; i < tag_len; i++ ) - diff |= tag[i] ^ check_tag[i]; - - if( diff != 0 ) - { - mbedtls_zeroize( output, length ); - return( MBEDTLS_ERR_CCM_AUTH_FAILED ); - } - - return( 0 ); -} - - -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) -/* - * Examples 1 to 3 from SP800-38C Appendix C - */ - -#define NB_TESTS 3 - -/* - * The data is the same for all tests, only the used length changes - */ -static const unsigned char key[] = { - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f -}; - -static const unsigned char iv[] = { - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b -}; - -static const unsigned char ad[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13 -}; - -static const unsigned char msg[] = { - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, -}; - -static const size_t iv_len [NB_TESTS] = { 7, 8, 12 }; -static const size_t add_len[NB_TESTS] = { 8, 16, 20 }; -static const size_t msg_len[NB_TESTS] = { 4, 16, 24 }; -static const size_t tag_len[NB_TESTS] = { 4, 6, 8 }; - -static const unsigned char res[NB_TESTS][32] = { - { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d }, - { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62, - 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d, - 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd }, - { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a, - 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b, - 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5, - 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 } -}; - -int mbedtls_ccm_self_test( int verbose ) -{ - mbedtls_ccm_context ctx; - unsigned char out[32]; - size_t i; - int ret; - - mbedtls_ccm_init( &ctx ); - - if( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( " CCM: setup failed" ); - - return( 1 ); - } - - for( i = 0; i < NB_TESTS; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 ); - - ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i], - iv, iv_len[i], ad, add_len[i], - msg, out, - out + msg_len[i], tag_len[i] ); - - if( ret != 0 || - memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i], - iv, iv_len[i], ad, add_len[i], - res[i], out, - res[i] + msg_len[i], tag_len[i] ); - - if( ret != 0 || - memcmp( out, msg, msg_len[i] ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - mbedtls_ccm_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ - -#endif /* MBEDTLS_CCM_C */ diff --git a/components/mbedtls/library/certs.c b/components/mbedtls/library/certs.c deleted file mode 100644 index f1379b8cb1..0000000000 --- a/components/mbedtls/library/certs.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - * X.509 test certificates - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#include "mbedtls/certs.h" - -#if defined(MBEDTLS_CERTS_C) - -#if defined(MBEDTLS_ECDSA_C) -#define TEST_CA_CRT_EC \ -"-----BEGIN CERTIFICATE-----\r\n" \ -"MIICUjCCAdegAwIBAgIJAMFD4n5iQ8zoMAoGCCqGSM49BAMCMD4xCzAJBgNVBAYT\r\n" \ -"Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n" \ -"QyBDQTAeFw0xMzA5MjQxNTQ5NDhaFw0yMzA5MjIxNTQ5NDhaMD4xCzAJBgNVBAYT\r\n" \ -"Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n" \ -"QyBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMPaKzRBN1gvh1b+/Im6KUNLTuBu\r\n" \ -"ww5XUzM5WNRStJGVOQsj318XJGJI/BqVKc4sLYfCiFKAr9ZqqyHduNMcbli4yuiy\r\n" \ -"aY7zQa0pw7RfdadHb9UZKVVpmlM7ILRmFmAzHqOBoDCBnTAdBgNVHQ4EFgQUnW0g\r\n" \ -"JEkBPyvLeLUZvH4kydv7NnwwbgYDVR0jBGcwZYAUnW0gJEkBPyvLeLUZvH4kydv7\r\n" \ -"NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UE\r\n" \ -"AxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAwGA1UdEwQFMAMBAf8w\r\n" \ -"CgYIKoZIzj0EAwIDaQAwZgIxAMO0YnNWKJUAfXgSJtJxexn4ipg+kv4znuR50v56\r\n" \ -"t4d0PCu412mUC6Nnd7izvtE2MgIxAP1nnJQjZ8BWukszFQDG48wxCCyci9qpdSMv\r\n" \ -"uCjn8pwUOkABXK8Mss90fzCfCEOtIA==\r\n" \ -"-----END CERTIFICATE-----\r\n" -const char mbedtls_test_ca_crt_ec[] = TEST_CA_CRT_EC; -const size_t mbedtls_test_ca_crt_ec_len = sizeof( mbedtls_test_ca_crt_ec ); - -const char mbedtls_test_ca_key_ec[] = -"-----BEGIN EC PRIVATE KEY-----\r\n" -"Proc-Type: 4,ENCRYPTED\r\n" -"DEK-Info: DES-EDE3-CBC,307EAB469933D64E\r\n" -"\r\n" -"IxbrRmKcAzctJqPdTQLA4SWyBYYGYJVkYEna+F7Pa5t5Yg/gKADrFKcm6B72e7DG\r\n" -"ihExtZI648s0zdYw6qSJ74vrPSuWDe5qm93BqsfVH9svtCzWHW0pm1p0KTBCFfUq\r\n" -"UsuWTITwJImcnlAs1gaRZ3sAWm7cOUidL0fo2G0fYUFNcYoCSLffCFTEHBuPnagb\r\n" -"a77x/sY1Bvii8S9/XhDTb6pTMx06wzrm\r\n" -"-----END EC PRIVATE KEY-----\r\n"; -const size_t mbedtls_test_ca_key_ec_len = sizeof( mbedtls_test_ca_key_ec ); - -const char mbedtls_test_ca_pwd_ec[] = "PolarSSLTest"; -const size_t mbedtls_test_ca_pwd_ec_len = sizeof( mbedtls_test_ca_pwd_ec ) - 1; - -const char mbedtls_test_srv_crt_ec[] = -"-----BEGIN CERTIFICATE-----\r\n" -"MIICHzCCAaWgAwIBAgIBCTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" -"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG\r\n" -"CCqGSM49AwEHA0IABDfMVtl2CR5acj7HWS3/IG7ufPkGkXTQrRS192giWWKSTuUA\r\n" -"2CMR/+ov0jRdXRa9iojCa3cNVc2KKg76Aci07f+jgZ0wgZowCQYDVR0TBAIwADAd\r\n" -"BgNVHQ4EFgQUUGGlj9QH2deCAQzlZX+MY0anE74wbgYDVR0jBGcwZYAUnW0gJEkB\r\n" -"PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xh\r\n" -"clNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG\r\n" -"CCqGSM49BAMCA2gAMGUCMQCaLFzXptui5WQN8LlO3ddh1hMxx6tzgLvT03MTVK2S\r\n" -"C12r0Lz3ri/moSEpNZWqPjkCMCE2f53GXcYLqyfyJR078c/xNSUU5+Xxl7VZ414V\r\n" -"fGa5kHvHARBPc8YAIVIqDvHH1Q==\r\n" -"-----END CERTIFICATE-----\r\n"; -const size_t mbedtls_test_srv_crt_ec_len = sizeof( mbedtls_test_srv_crt_ec ); - -const char mbedtls_test_srv_key_ec[] = -"-----BEGIN EC PRIVATE KEY-----\r\n" -"MHcCAQEEIPEqEyB2AnCoPL/9U/YDHvdqXYbIogTywwyp6/UfDw6noAoGCCqGSM49\r\n" -"AwEHoUQDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/\r\n" -"6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/w==\r\n" -"-----END EC PRIVATE KEY-----\r\n"; -const size_t mbedtls_test_srv_key_ec_len = sizeof( mbedtls_test_srv_key_ec ); - -const char mbedtls_test_cli_crt_ec[] = -"-----BEGIN CERTIFICATE-----\r\n" -"MIICLDCCAbKgAwIBAgIBDTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" -"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjBBMQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxHzAdBgNVBAMTFlBvbGFyU1NMIFRlc3QgQ2xpZW50IDIw\r\n" -"WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARX5a6xc9/TrLuTuIH/Eq7u5lOszlVT\r\n" -"9jQOzC7jYyUL35ji81xgNpbA1RgUcOV/n9VLRRjlsGzVXPiWj4dwo+THo4GdMIGa\r\n" -"MAkGA1UdEwQCMAAwHQYDVR0OBBYEFHoAX4Zk/OBd5REQO7LmO8QmP8/iMG4GA1Ud\r\n" -"IwRnMGWAFJ1tICRJAT8ry3i1Gbx+JMnb+zZ8oUKkQDA+MQswCQYDVQQGEwJOTDER\r\n" -"MA8GA1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0GC\r\n" -"CQDBQ+J+YkPM6DAKBggqhkjOPQQDAgNoADBlAjBKZQ17IIOimbmoD/yN7o89u3BM\r\n" -"lgOsjnhw3fIOoLIWy2WOGsk/LGF++DzvrRzuNiACMQCd8iem1XS4JK7haj8xocpU\r\n" -"LwjQje5PDGHfd3h9tP38Qknu5bJqws0md2KOKHyeV0U=\r\n" -"-----END CERTIFICATE-----\r\n"; -const size_t mbedtls_test_cli_crt_ec_len = sizeof( mbedtls_test_cli_crt_ec ); - -const char mbedtls_test_cli_key_ec[] = -"-----BEGIN EC PRIVATE KEY-----\r\n" -"MHcCAQEEIPb3hmTxZ3/mZI3vyk7p3U3wBf+WIop6hDhkFzJhmLcqoAoGCCqGSM49\r\n" -"AwEHoUQDQgAEV+WusXPf06y7k7iB/xKu7uZTrM5VU/Y0Dswu42MlC9+Y4vNcYDaW\r\n" -"wNUYFHDlf5/VS0UY5bBs1Vz4lo+HcKPkxw==\r\n" -"-----END EC PRIVATE KEY-----\r\n"; -const size_t mbedtls_test_cli_key_ec_len = sizeof( mbedtls_test_cli_key_ec ); -#endif /* MBEDTLS_ECDSA_C */ - -#if defined(MBEDTLS_RSA_C) - -#if defined(MBEDTLS_SHA256_C) -#define TEST_CA_CRT_RSA_SHA256 \ -"-----BEGIN CERTIFICATE-----\r\n" \ -"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ -"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ -"MTcwNTA0MTY1NzAxWhcNMjcwNTA1MTY1NzAxWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ -"A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ -"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ -"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ -"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ -"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ -"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ -"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ -"gZUwgZIwHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/MGMGA1UdIwRcMFqA\r\n" \ -"FLRa5KWz3tJS9rnVppUP6z68x/3/oT+kPTA7MQswCQYDVQQGEwJOTDERMA8GA1UE\r\n" \ -"CgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0GCAQAwDAYDVR0T\r\n" \ -"BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAHK/HHrTZMnnVMpde1io+voAtql7j\r\n" \ -"4sRhLrjD7o3THtwRbDa2diCvpq0Sq23Ng2LMYoXsOxoL/RQK3iN7UKxV3MKPEr0w\r\n" \ -"XQS+kKQqiT2bsfrjnWMVHZtUOMpm6FNqcdGm/Rss3vKda2lcKl8kUnq/ylc1+QbB\r\n" \ -"G6A6tUvQcr2ZyWfVg+mM5XkhTrOOXus2OLikb4WwEtJTJRNE0f+yPODSUz0/vT57\r\n" \ -"ApH0CnB80bYJshYHPHHymOtleAB8KSYtqm75g/YNobjnjB6cm4HkW3OZRVIl6fYY\r\n" \ -"n20NRVA1Vjs6GAROr4NqW4k/+LofY9y0LLDE+p0oIEKXIsIvhPr39swxSA==\r\n" \ -"-----END CERTIFICATE-----\r\n" - -const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA_SHA256; -const size_t mbedtls_test_ca_crt_rsa_len = sizeof( mbedtls_test_ca_crt_rsa ); -#define TEST_CA_CRT_RSA_SOME - -static const char mbedtls_test_ca_crt_rsa_sha256[] = TEST_CA_CRT_RSA_SHA256; - -#endif - -#if !defined(TEST_CA_CRT_RSA_SOME) || defined(MBEDTLS_SHA1_C) -#define TEST_CA_CRT_RSA_SHA1 \ -"-----BEGIN CERTIFICATE-----\r\n" \ -"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ -"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ -"MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ -"A1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ -"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ -"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ -"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ -"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ -"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ -"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ -"gZUwgZIwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUtFrkpbPe0lL2udWmlQ/rPrzH\r\n" \ -"/f8wYwYDVR0jBFwwWoAUtFrkpbPe0lL2udWmlQ/rPrzH/f+hP6Q9MDsxCzAJBgNV\r\n" \ -"BAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEZMBcGA1UEAxMQUG9sYXJTU0wgVGVz\r\n" \ -"dCBDQYIBADANBgkqhkiG9w0BAQUFAAOCAQEAuP1U2ABUkIslsCfdlc2i94QHHYeJ\r\n" \ -"SsR4EdgHtdciUI5I62J6Mom+Y0dT/7a+8S6MVMCZP6C5NyNyXw1GWY/YR82XTJ8H\r\n" \ -"DBJiCTok5DbZ6SzaONBzdWHXwWwmi5vg1dxn7YxrM9d0IjxM27WNKs4sDQhZBQkF\r\n" \ -"pjmfs2cb4oPl4Y9T9meTx/lvdkRYEug61Jfn6cA+qHpyPYdTH+UshITnmp5/Ztkf\r\n" \ -"m/UTSLBNFNHesiTZeH31NcxYGdHSme9Nc/gfidRa0FLOCfWxRlFqAI47zG9jAQCZ\r\n" \ -"7Z2mCGDNMhjQc+BYcdnl0lPXjdDK6V0qCg1dVewhUBcW5gZKzV7e9+DpVA==\r\n" \ -"-----END CERTIFICATE-----\r\n" - -#if !defined (TEST_CA_CRT_RSA_SOME) -const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA_SHA1; -const size_t mbedtls_test_ca_crt_rsa_len = sizeof( mbedtls_test_ca_crt_rsa ); -#endif - -static const char mbedtls_test_ca_crt_rsa_sha1[] = TEST_CA_CRT_RSA_SHA1; - -#endif - -const char mbedtls_test_ca_key_rsa[] = -"-----BEGIN RSA PRIVATE KEY-----\r\n" -"Proc-Type: 4,ENCRYPTED\r\n" -"DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n" -"\r\n" -"9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n" -"7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n" -"Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n" -"PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n" -"GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n" -"gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n" -"QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n" -"PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n" -"vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n" -"WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n" -"JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n" -"KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n" -"Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n" -"9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n" -"iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n" -"tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n" -"P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n" -"1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n" -"nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n" -"X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n" -"rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n" -"L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n" -"I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n" -"wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n" -"P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n" -"-----END RSA PRIVATE KEY-----\r\n"; -const size_t mbedtls_test_ca_key_rsa_len = sizeof( mbedtls_test_ca_key_rsa ); - -const char mbedtls_test_ca_pwd_rsa[] = "PolarSSLTest"; -const size_t mbedtls_test_ca_pwd_rsa_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1; - -const char mbedtls_test_srv_crt_rsa[] = -"-----BEGIN CERTIFICATE-----\r\n" -"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" -"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" -"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" -"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" -"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" -"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" -"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" -"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" -"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" -"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" -"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJxnXClY\r\n" -"oHkbp70cqBrsGXLybA74czbO5RdLEgFs7rHVS9r+c293luS/KdliLScZqAzYVylw\r\n" -"UfRWvKMoWhHYKp3dEIS4xTXk6/5zXxhv9Rw8SGc8qn6vITHk1S1mPevtekgasY5Y\r\n" -"iWQuM3h4YVlRH3HHEMAD1TnAexfXHHDFQGe+Bd1iAbz1/sH9H8l4StwX6egvTK3M\r\n" -"wXRwkKkvjKaEDA9ATbZx0mI8LGsxSuCqe9r9dyjmttd47J1p1Rulz3CLzaRcVIuS\r\n" -"RRQfaD8neM9c1S/iJ/amTVqJxA1KOdOS5780WhPfSArA+g4qAmSjelc3p4wWpha8\r\n" -"zhuYwjVuX6JHG0c=\r\n" -"-----END CERTIFICATE-----\r\n"; -const size_t mbedtls_test_srv_crt_rsa_len = sizeof( mbedtls_test_srv_crt_rsa ); - -const char mbedtls_test_srv_key_rsa[] = -"-----BEGIN RSA PRIVATE KEY-----\r\n" -"MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n" -"lqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\r\n" -"2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\r\n" -"Zn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\r\n" -"GMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\r\n" -"y3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\r\n" -"++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\r\n" -"Z0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\r\n" -"/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\r\n" -"WYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\r\n" -"GTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\r\n" -"TWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\r\n" -"CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n" -"nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n" -"AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n" -"sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n" -"mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n" -"BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n" -"whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n" -"vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n" -"3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n" -"3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n" -"ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n" -"4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n" -"TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n" -"-----END RSA PRIVATE KEY-----\r\n"; -const size_t mbedtls_test_srv_key_rsa_len = sizeof( mbedtls_test_srv_key_rsa ); - -const char mbedtls_test_cli_crt_rsa[] = -"-----BEGIN CERTIFICATE-----\r\n" -"MIIDhTCCAm2gAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" -"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" -"MTcwNTA1MTMwNzU5WhcNMjcwNTA2MTMwNzU5WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" -"A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" -"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n" -"M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n" -"1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n" -"MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n" -"4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n" -"/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n" -"o4GSMIGPMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITBjBgNVHSMEXDBa\r\n" -"gBS0WuSls97SUva51aaVD+s+vMf9/6E/pD0wOzELMAkGA1UEBhMCTkwxETAPBgNV\r\n" -"BAoMCFBvbGFyU1NMMRkwFwYDVQQDDBBQb2xhclNTTCBUZXN0IENBggEAMAkGA1Ud\r\n" -"EwQCMAAwDQYJKoZIhvcNAQELBQADggEBAC7yO786NvcHpK8UovKIG9cB32oSQQom\r\n" -"LoR0eHDRzdqEkoq7yGZufHFiRAAzbMqJfogRtxlrWAeB4y/jGaMBV25IbFOIcH2W\r\n" -"iCEaMMbG+VQLKNvuC63kmw/Zewc9ThM6Pa1Hcy0axT0faf1B/U01j0FIcw/6mTfK\r\n" -"D8w48OIwc1yr0JtutCVjig5DC0yznGMt32RyseOLcUe+lfq005v2PAiCozr5X8rE\r\n" -"ofGZpiM2NqRPePgYy+Vc75Zk28xkRQq1ncprgQb3S4vTsZdScpM9hLf+eMlrgqlj\r\n" -"c5PLSkXBeLE5+fedkyfTaLxxQlgCpuoOhKBm04/R1pWNzUHyqagjO9Q=\r\n" -"-----END CERTIFICATE-----\r\n"; -const size_t mbedtls_test_cli_crt_rsa_len = sizeof( mbedtls_test_cli_crt_rsa ); - -const char mbedtls_test_cli_key_rsa[] = -"-----BEGIN RSA PRIVATE KEY-----\r\n" -"MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n" -"B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n" -"bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n" -"Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n" -"7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n" -"dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n" -"yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n" -"4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n" -"ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n" -"zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n" -"l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n" -"DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n" -"VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n" -"Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n" -"wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n" -"c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n" -"33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n" -"ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n" -"BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n" -"KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n" -"UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n" -"7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n" -"gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n" -"bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n" -"8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n" -"-----END RSA PRIVATE KEY-----\r\n"; -const size_t mbedtls_test_cli_key_rsa_len = sizeof( mbedtls_test_cli_key_rsa ); -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_PEM_PARSE_C) -/* Concatenation of all available CA certificates */ -const char mbedtls_test_cas_pem[] = -#ifdef TEST_CA_CRT_RSA_SHA1 - TEST_CA_CRT_RSA_SHA1 -#endif -#ifdef TEST_CA_CRT_RSA_SHA256 - TEST_CA_CRT_RSA_SHA256 -#endif -#ifdef TEST_CA_CRT_EC - TEST_CA_CRT_EC -#endif - ""; -const size_t mbedtls_test_cas_pem_len = sizeof( mbedtls_test_cas_pem ); -#endif - -/* List of all available CA certificates */ -const char * mbedtls_test_cas[] = { -#if defined(TEST_CA_CRT_RSA_SHA1) - mbedtls_test_ca_crt_rsa_sha1, -#endif -#if defined(TEST_CA_CRT_RSA_SHA256) - mbedtls_test_ca_crt_rsa_sha256, -#endif -#if defined(MBEDTLS_ECDSA_C) - mbedtls_test_ca_crt_ec, -#endif - NULL -}; -const size_t mbedtls_test_cas_len[] = { -#if defined(TEST_CA_CRT_RSA_SHA1) - sizeof( mbedtls_test_ca_crt_rsa_sha1 ), -#endif -#if defined(TEST_CA_CRT_RSA_SHA256) - sizeof( mbedtls_test_ca_crt_rsa_sha256 ), -#endif -#if defined(MBEDTLS_ECDSA_C) - sizeof( mbedtls_test_ca_crt_ec ), -#endif - 0 -}; - -#if defined(MBEDTLS_RSA_C) -const char *mbedtls_test_ca_crt = mbedtls_test_ca_crt_rsa; /* SHA1 or SHA256 */ -const char *mbedtls_test_ca_key = mbedtls_test_ca_key_rsa; -const char *mbedtls_test_ca_pwd = mbedtls_test_ca_pwd_rsa; -const char *mbedtls_test_srv_crt = mbedtls_test_srv_crt_rsa; -const char *mbedtls_test_srv_key = mbedtls_test_srv_key_rsa; -const char *mbedtls_test_cli_crt = mbedtls_test_cli_crt_rsa; -const char *mbedtls_test_cli_key = mbedtls_test_cli_key_rsa; -const size_t mbedtls_test_ca_crt_len = sizeof( mbedtls_test_ca_crt_rsa ); -const size_t mbedtls_test_ca_key_len = sizeof( mbedtls_test_ca_key_rsa ); -const size_t mbedtls_test_ca_pwd_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1; -const size_t mbedtls_test_srv_crt_len = sizeof( mbedtls_test_srv_crt_rsa ); -const size_t mbedtls_test_srv_key_len = sizeof( mbedtls_test_srv_key_rsa ); -const size_t mbedtls_test_cli_crt_len = sizeof( mbedtls_test_cli_crt_rsa ); -const size_t mbedtls_test_cli_key_len = sizeof( mbedtls_test_cli_key_rsa ); -#else /* ! MBEDTLS_RSA_C, so MBEDTLS_ECDSA_C */ -const char *mbedtls_test_ca_crt = mbedtls_test_ca_crt_ec; -const char *mbedtls_test_ca_key = mbedtls_test_ca_key_ec; -const char *mbedtls_test_ca_pwd = mbedtls_test_ca_pwd_ec; -const char *mbedtls_test_srv_crt = mbedtls_test_srv_crt_ec; -const char *mbedtls_test_srv_key = mbedtls_test_srv_key_ec; -const char *mbedtls_test_cli_crt = mbedtls_test_cli_crt_ec; -const char *mbedtls_test_cli_key = mbedtls_test_cli_key_ec; -const size_t mbedtls_test_ca_crt_len = sizeof( mbedtls_test_ca_crt_ec ); -const size_t mbedtls_test_ca_key_len = sizeof( mbedtls_test_ca_key_ec ); -const size_t mbedtls_test_ca_pwd_len = sizeof( mbedtls_test_ca_pwd_ec ) - 1; -const size_t mbedtls_test_srv_crt_len = sizeof( mbedtls_test_srv_crt_ec ); -const size_t mbedtls_test_srv_key_len = sizeof( mbedtls_test_srv_key_ec ); -const size_t mbedtls_test_cli_crt_len = sizeof( mbedtls_test_cli_crt_ec ); -const size_t mbedtls_test_cli_key_len = sizeof( mbedtls_test_cli_key_ec ); -#endif /* MBEDTLS_RSA_C */ - -#endif /* MBEDTLS_CERTS_C */ diff --git a/components/mbedtls/library/cipher.c b/components/mbedtls/library/cipher.c deleted file mode 100644 index e9e0b223e5..0000000000 --- a/components/mbedtls/library/cipher.c +++ /dev/null @@ -1,917 +0,0 @@ -/** - * \file cipher.c - * - * \brief Generic cipher wrapper for mbed TLS - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_CIPHER_C) - -#include "mbedtls/cipher.h" -#include "mbedtls/cipher_internal.h" - -#include -#include - -#if defined(MBEDTLS_GCM_C) -#include "mbedtls/gcm.h" -#endif - -#if defined(MBEDTLS_CCM_C) -#include "mbedtls/ccm.h" -#endif - -#if defined(MBEDTLS_CMAC_C) -#include "mbedtls/cmac.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) -#define MBEDTLS_CIPHER_MODE_STREAM -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -static int supported_init = 0; - -const int *mbedtls_cipher_list( void ) -{ - const mbedtls_cipher_definition_t *def; - int *type; - - if( ! supported_init ) - { - def = mbedtls_cipher_definitions; - type = mbedtls_cipher_supported; - - while( def->type != 0 ) - *type++ = (*def++).type; - - *type = 0; - - supported_init = 1; - } - - return( mbedtls_cipher_supported ); -} - -const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ) -{ - const mbedtls_cipher_definition_t *def; - - for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) - if( def->type == cipher_type ) - return( def->info ); - - return( NULL ); -} - -const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ) -{ - const mbedtls_cipher_definition_t *def; - - if( NULL == cipher_name ) - return( NULL ); - - for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) - if( ! strcmp( def->info->name, cipher_name ) ) - return( def->info ); - - return( NULL ); -} - -const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, - int key_bitlen, - const mbedtls_cipher_mode_t mode ) -{ - const mbedtls_cipher_definition_t *def; - - for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) - if( def->info->base->cipher == cipher_id && - def->info->key_bitlen == (unsigned) key_bitlen && - def->info->mode == mode ) - return( def->info ); - - return( NULL ); -} - -void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); -} - -void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) -{ - if( ctx == NULL ) - return; - -#if defined(MBEDTLS_CMAC_C) - if( ctx->cmac_ctx ) - { - mbedtls_zeroize( ctx->cmac_ctx, sizeof( mbedtls_cmac_context_t ) ); - mbedtls_free( ctx->cmac_ctx ); - } -#endif - - if( ctx->cipher_ctx ) - ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); - - mbedtls_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); -} - -int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) -{ - if( NULL == cipher_info || NULL == ctx ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); - - if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) - return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); - - ctx->cipher_info = cipher_info; - -#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) - /* - * Ignore possible errors caused by a cipher mode that doesn't use padding - */ -#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) - (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 ); -#else - (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE ); -#endif -#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ - - return( 0 ); -} - -int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, - int key_bitlen, const mbedtls_operation_t operation ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && - (int) ctx->cipher_info->key_bitlen != key_bitlen ) - { - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } - - ctx->key_bitlen = key_bitlen; - ctx->operation = operation; - - /* - * For CFB and CTR mode always use the encryption key schedule - */ - if( MBEDTLS_ENCRYPT == operation || - MBEDTLS_MODE_CFB == ctx->cipher_info->mode || - MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) - { - return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, - ctx->key_bitlen ); - } - - if( MBEDTLS_DECRYPT == operation ) - return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, - ctx->key_bitlen ); - - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); -} - -int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len ) -{ - size_t actual_iv_size; - - if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - /* avoid buffer overflow in ctx->iv */ - if( iv_len > MBEDTLS_MAX_IV_LENGTH ) - return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); - - if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 ) - actual_iv_size = iv_len; - else - { - actual_iv_size = ctx->cipher_info->iv_size; - - /* avoid reading past the end of input buffer */ - if( actual_iv_size > iv_len ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } - - memcpy( ctx->iv, iv, actual_iv_size ); - ctx->iv_size = actual_iv_size; - - return( 0 ); -} - -int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - ctx->unprocessed_len = 0; - - return( 0 ); -} - -#if defined(MBEDTLS_GCM_C) -int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, - const unsigned char *ad, size_t ad_len ) -{ - if( NULL == ctx || NULL == ctx->cipher_info ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) - { - return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, - ctx->iv, ctx->iv_size, ad, ad_len ); - } - - return( 0 ); -} -#endif /* MBEDTLS_GCM_C */ - -int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, - size_t ilen, unsigned char *output, size_t *olen ) -{ - int ret; - size_t block_size = 0; - - if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) - { - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } - - *olen = 0; - block_size = mbedtls_cipher_get_block_size( ctx ); - - if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) - { - if( ilen != block_size ) - return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); - - *olen = ilen; - - if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, - ctx->operation, input, output ) ) ) - { - return( ret ); - } - - return( 0 ); - } - -#if defined(MBEDTLS_GCM_C) - if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) - { - *olen = ilen; - return mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, - output ); - } -#endif - - if ( 0 == block_size ) - { - return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; - } - - if( input == output && - ( ctx->unprocessed_len != 0 || ilen % block_size ) ) - { - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC ) - { - size_t copy_len = 0; - - /* - * If there is not enough data for a full block, cache it. - */ - if( ( ctx->operation == MBEDTLS_DECRYPT && - ilen <= block_size - ctx->unprocessed_len ) || - ( ctx->operation == MBEDTLS_ENCRYPT && - ilen < block_size - ctx->unprocessed_len ) ) - { - memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, - ilen ); - - ctx->unprocessed_len += ilen; - return( 0 ); - } - - /* - * Process cached data first - */ - if( 0 != ctx->unprocessed_len ) - { - copy_len = block_size - ctx->unprocessed_len; - - memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, - copy_len ); - - if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, - ctx->operation, block_size, ctx->iv, - ctx->unprocessed_data, output ) ) ) - { - return( ret ); - } - - *olen += block_size; - output += block_size; - ctx->unprocessed_len = 0; - - input += copy_len; - ilen -= copy_len; - } - - /* - * Cache final, incomplete block - */ - if( 0 != ilen ) - { - if( 0 == block_size ) - { - return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; - } - - copy_len = ilen % block_size; - if( copy_len == 0 && ctx->operation == MBEDTLS_DECRYPT ) - copy_len = block_size; - - memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), - copy_len ); - - ctx->unprocessed_len += copy_len; - ilen -= copy_len; - } - - /* - * Process remaining full blocks - */ - if( ilen ) - { - if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, - ctx->operation, ilen, ctx->iv, input, output ) ) ) - { - return( ret ); - } - - *olen += ilen; - } - - return( 0 ); - } -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) - if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB ) - { - if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, - ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, - input, output ) ) ) - { - return( ret ); - } - - *olen = ilen; - - return( 0 ); - } -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) - if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) - { - if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, - ilen, &ctx->unprocessed_len, ctx->iv, - ctx->unprocessed_data, input, output ) ) ) - { - return( ret ); - } - - *olen = ilen; - - return( 0 ); - } -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) - { - if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, - ilen, input, output ) ) ) - { - return( ret ); - } - - *olen = ilen; - - return( 0 ); - } -#endif /* MBEDTLS_CIPHER_MODE_STREAM */ - - return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); -} - -#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) -#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) -/* - * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len - */ -static void add_pkcs_padding( unsigned char *output, size_t output_len, - size_t data_len ) -{ - size_t padding_len = output_len - data_len; - unsigned char i; - - for( i = 0; i < padding_len; i++ ) - output[data_len + i] = (unsigned char) padding_len; -} - -static int get_pkcs_padding( unsigned char *input, size_t input_len, - size_t *data_len ) -{ - size_t i, pad_idx; - unsigned char padding_len, bad = 0; - - if( NULL == input || NULL == data_len ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - padding_len = input[input_len - 1]; - *data_len = input_len - padding_len; - - /* Avoid logical || since it results in a branch */ - bad |= padding_len > input_len; - bad |= padding_len == 0; - - /* The number of bytes checked must be independent of padding_len, - * so pick input_len, which is usually 8 or 16 (one block) */ - pad_idx = input_len - padding_len; - for( i = 0; i < input_len; i++ ) - bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx ); - - return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); -} -#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ - -#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) -/* - * One and zeros padding: fill with 80 00 ... 00 - */ -static void add_one_and_zeros_padding( unsigned char *output, - size_t output_len, size_t data_len ) -{ - size_t padding_len = output_len - data_len; - unsigned char i = 0; - - output[data_len] = 0x80; - for( i = 1; i < padding_len; i++ ) - output[data_len + i] = 0x00; -} - -static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, - size_t *data_len ) -{ - size_t i; - unsigned char done = 0, prev_done, bad; - - if( NULL == input || NULL == data_len ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - bad = 0xFF; - *data_len = 0; - for( i = input_len; i > 0; i-- ) - { - prev_done = done; - done |= ( input[i-1] != 0 ); - *data_len |= ( i - 1 ) * ( done != prev_done ); - bad &= ( input[i-1] ^ 0x80 ) | ( done == prev_done ); - } - - return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); - -} -#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ - -#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) -/* - * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length - */ -static void add_zeros_and_len_padding( unsigned char *output, - size_t output_len, size_t data_len ) -{ - size_t padding_len = output_len - data_len; - unsigned char i = 0; - - for( i = 1; i < padding_len; i++ ) - output[data_len + i - 1] = 0x00; - output[output_len - 1] = (unsigned char) padding_len; -} - -static int get_zeros_and_len_padding( unsigned char *input, size_t input_len, - size_t *data_len ) -{ - size_t i, pad_idx; - unsigned char padding_len, bad = 0; - - if( NULL == input || NULL == data_len ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - padding_len = input[input_len - 1]; - *data_len = input_len - padding_len; - - /* Avoid logical || since it results in a branch */ - bad |= padding_len > input_len; - bad |= padding_len == 0; - - /* The number of bytes checked must be independent of padding_len */ - pad_idx = input_len - padding_len; - for( i = 0; i < input_len - 1; i++ ) - bad |= input[i] * ( i >= pad_idx ); - - return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); -} -#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ - -#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) -/* - * Zero padding: fill with 00 ... 00 - */ -static void add_zeros_padding( unsigned char *output, - size_t output_len, size_t data_len ) -{ - size_t i; - - for( i = data_len; i < output_len; i++ ) - output[i] = 0x00; -} - -static int get_zeros_padding( unsigned char *input, size_t input_len, - size_t *data_len ) -{ - size_t i; - unsigned char done = 0, prev_done; - - if( NULL == input || NULL == data_len ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - *data_len = 0; - for( i = input_len; i > 0; i-- ) - { - prev_done = done; - done |= ( input[i-1] != 0 ); - *data_len |= i * ( done != prev_done ); - } - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ - -/* - * No padding: don't pad :) - * - * There is no add_padding function (check for NULL in mbedtls_cipher_finish) - * but a trivial get_padding function - */ -static int get_no_padding( unsigned char *input, size_t input_len, - size_t *data_len ) -{ - if( NULL == input || NULL == data_len ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - *data_len = input_len; - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ - -int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, - unsigned char *output, size_t *olen ) -{ - if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - *olen = 0; - - if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || - MBEDTLS_MODE_CTR == ctx->cipher_info->mode || - MBEDTLS_MODE_GCM == ctx->cipher_info->mode || - MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) - { - return( 0 ); - } - - if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) - { - if( ctx->unprocessed_len != 0 ) - return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); - - return( 0 ); - } - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode ) - { - int ret = 0; - - if( MBEDTLS_ENCRYPT == ctx->operation ) - { - /* check for 'no padding' mode */ - if( NULL == ctx->add_padding ) - { - if( 0 != ctx->unprocessed_len ) - return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); - - return( 0 ); - } - - ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ), - ctx->unprocessed_len ); - } - else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len ) - { - /* - * For decrypt operations, expect a full block, - * or an empty block if no padding - */ - if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len ) - return( 0 ); - - return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); - } - - /* cipher block */ - if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, - ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv, - ctx->unprocessed_data, output ) ) ) - { - return( ret ); - } - - /* Set output size for decryption */ - if( MBEDTLS_DECRYPT == ctx->operation ) - return ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), - olen ); - - /* Set output size for encryption */ - *olen = mbedtls_cipher_get_block_size( ctx ); - return( 0 ); - } -#else - ((void) output); -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - - return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); -} - -#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) -int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ) -{ - if( NULL == ctx || - MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) - { - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } - - switch( mode ) - { -#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) - case MBEDTLS_PADDING_PKCS7: - ctx->add_padding = add_pkcs_padding; - ctx->get_padding = get_pkcs_padding; - break; -#endif -#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) - case MBEDTLS_PADDING_ONE_AND_ZEROS: - ctx->add_padding = add_one_and_zeros_padding; - ctx->get_padding = get_one_and_zeros_padding; - break; -#endif -#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) - case MBEDTLS_PADDING_ZEROS_AND_LEN: - ctx->add_padding = add_zeros_and_len_padding; - ctx->get_padding = get_zeros_and_len_padding; - break; -#endif -#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) - case MBEDTLS_PADDING_ZEROS: - ctx->add_padding = add_zeros_padding; - ctx->get_padding = get_zeros_padding; - break; -#endif - case MBEDTLS_PADDING_NONE: - ctx->add_padding = NULL; - ctx->get_padding = get_no_padding; - break; - - default: - return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); - } - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ - -#if defined(MBEDTLS_GCM_C) -int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, - unsigned char *tag, size_t tag_len ) -{ - if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - if( MBEDTLS_ENCRYPT != ctx->operation ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) - return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len ); - - return( 0 ); -} - -int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, - const unsigned char *tag, size_t tag_len ) -{ - int ret; - - if( NULL == ctx || NULL == ctx->cipher_info || - MBEDTLS_DECRYPT != ctx->operation ) - { - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } - - if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) - { - unsigned char check_tag[16]; - size_t i; - int diff; - - if( tag_len > sizeof( check_tag ) ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - if( 0 != ( ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, - check_tag, tag_len ) ) ) - { - return( ret ); - } - - /* Check the tag in "constant-time" */ - for( diff = 0, i = 0; i < tag_len; i++ ) - diff |= tag[i] ^ check_tag[i]; - - if( diff != 0 ) - return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); - - return( 0 ); - } - - return( 0 ); -} -#endif /* MBEDTLS_GCM_C */ - -/* - * Packet-oriented wrapper for non-AEAD modes - */ -int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen ) -{ - int ret; - size_t finish_olen; - - if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_cipher_update( ctx, input, ilen, output, olen ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 ) - return( ret ); - - *olen += finish_olen; - - return( 0 ); -} - -#if defined(MBEDTLS_CIPHER_MODE_AEAD) -/* - * Packet-oriented encryption for AEAD modes - */ -int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *ad, size_t ad_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, - unsigned char *tag, size_t tag_len ) -{ -#if defined(MBEDTLS_GCM_C) - if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) - { - *olen = ilen; - return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen, - iv, iv_len, ad, ad_len, input, output, - tag_len, tag ) ); - } -#endif /* MBEDTLS_GCM_C */ -#if defined(MBEDTLS_CCM_C) - if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) - { - *olen = ilen; - return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen, - iv, iv_len, ad, ad_len, input, output, - tag, tag_len ) ); - } -#endif /* MBEDTLS_CCM_C */ - - return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); -} - -/* - * Packet-oriented decryption for AEAD modes - */ -int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, - const unsigned char *iv, size_t iv_len, - const unsigned char *ad, size_t ad_len, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, - const unsigned char *tag, size_t tag_len ) -{ -#if defined(MBEDTLS_GCM_C) - if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) - { - int ret; - - *olen = ilen; - ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen, - iv, iv_len, ad, ad_len, - tag, tag_len, input, output ); - - if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED ) - ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; - - return( ret ); - } -#endif /* MBEDTLS_GCM_C */ -#if defined(MBEDTLS_CCM_C) - if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) - { - int ret; - - *olen = ilen; - ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen, - iv, iv_len, ad, ad_len, - input, output, tag, tag_len ); - - if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED ) - ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; - - return( ret ); - } -#endif /* MBEDTLS_CCM_C */ - - return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); -} -#endif /* MBEDTLS_CIPHER_MODE_AEAD */ - -#endif /* MBEDTLS_CIPHER_C */ diff --git a/components/mbedtls/library/cipher_wrap.c b/components/mbedtls/library/cipher_wrap.c deleted file mode 100644 index dc76af8ff4..0000000000 --- a/components/mbedtls/library/cipher_wrap.c +++ /dev/null @@ -1,1451 +0,0 @@ -/** - * \file cipher_wrap.c - * - * \brief Generic cipher wrapper for mbed TLS - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_CIPHER_C) - -#include "mbedtls/cipher_internal.h" - -#if defined(MBEDTLS_AES_C) -#include "mbedtls/aes.h" -#endif - -#if defined(MBEDTLS_ARC4_C) -#include "mbedtls/arc4.h" -#endif - -#if defined(MBEDTLS_CAMELLIA_C) -#include "mbedtls/camellia.h" -#endif - -#if defined(MBEDTLS_DES_C) -#include "mbedtls/des.h" -#endif - -#if defined(MBEDTLS_BLOWFISH_C) -#include "mbedtls/blowfish.h" -#endif - -#if defined(MBEDTLS_GCM_C) -#include "mbedtls/gcm.h" -#endif - -#if defined(MBEDTLS_CCM_C) -#include "mbedtls/ccm.h" -#endif - -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) -#include -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#if defined(MBEDTLS_GCM_C) -/* shared by all GCM ciphers */ -static void *gcm_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_gcm_context ) ); - - if( ctx != NULL ) - mbedtls_gcm_init( (mbedtls_gcm_context *) ctx ); - - return( ctx ); -} - -static void gcm_ctx_free( void *ctx ) -{ - mbedtls_gcm_free( ctx ); - mbedtls_free( ctx ); -} -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CCM_C) -/* shared by all CCM ciphers */ -static void *ccm_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ccm_context ) ); - - if( ctx != NULL ) - mbedtls_ccm_init( (mbedtls_ccm_context *) ctx ); - - return( ctx ); -} - -static void ccm_ctx_free( void *ctx ) -{ - mbedtls_ccm_free( ctx ); - mbedtls_free( ctx ); -} -#endif /* MBEDTLS_CCM_C */ - -#if defined(MBEDTLS_AES_C) - -static int aes_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_aes_crypt_ecb( (mbedtls_aes_context *) ctx, operation, input, output ); -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static int aes_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, - unsigned char *iv, const unsigned char *input, unsigned char *output ) -{ - return mbedtls_aes_crypt_cbc( (mbedtls_aes_context *) ctx, operation, length, iv, input, - output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -static int aes_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, - size_t length, size_t *iv_off, unsigned char *iv, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_aes_crypt_cfb128( (mbedtls_aes_context *) ctx, operation, length, iv_off, iv, - input, output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, - unsigned char *nonce_counter, unsigned char *stream_block, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_aes_crypt_ctr( (mbedtls_aes_context *) ctx, length, nc_off, nonce_counter, - stream_block, input, output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_aes_setkey_dec( (mbedtls_aes_context *) ctx, key, key_bitlen ); -} - -static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_aes_setkey_enc( (mbedtls_aes_context *) ctx, key, key_bitlen ); -} - -static void * aes_ctx_alloc( void ) -{ - mbedtls_aes_context *aes = mbedtls_calloc( 1, sizeof( mbedtls_aes_context ) ); - - if( aes == NULL ) - return( NULL ); - - mbedtls_aes_init( aes ); - - return( aes ); -} - -static void aes_ctx_free( void *ctx ) -{ - mbedtls_aes_free( (mbedtls_aes_context *) ctx ); - mbedtls_free( ctx ); -} - -static const mbedtls_cipher_base_t aes_info = { - MBEDTLS_CIPHER_ID_AES, - aes_crypt_ecb_wrap, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - aes_crypt_cbc_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - aes_crypt_cfb128_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - aes_crypt_ctr_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - aes_setkey_enc_wrap, - aes_setkey_dec_wrap, - aes_ctx_alloc, - aes_ctx_free -}; - -static const mbedtls_cipher_info_t aes_128_ecb_info = { - MBEDTLS_CIPHER_AES_128_ECB, - MBEDTLS_MODE_ECB, - 128, - "AES-128-ECB", - 16, - 0, - 16, - &aes_info -}; - -static const mbedtls_cipher_info_t aes_192_ecb_info = { - MBEDTLS_CIPHER_AES_192_ECB, - MBEDTLS_MODE_ECB, - 192, - "AES-192-ECB", - 16, - 0, - 16, - &aes_info -}; - -static const mbedtls_cipher_info_t aes_256_ecb_info = { - MBEDTLS_CIPHER_AES_256_ECB, - MBEDTLS_MODE_ECB, - 256, - "AES-256-ECB", - 16, - 0, - 16, - &aes_info -}; - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static const mbedtls_cipher_info_t aes_128_cbc_info = { - MBEDTLS_CIPHER_AES_128_CBC, - MBEDTLS_MODE_CBC, - 128, - "AES-128-CBC", - 16, - 0, - 16, - &aes_info -}; - -static const mbedtls_cipher_info_t aes_192_cbc_info = { - MBEDTLS_CIPHER_AES_192_CBC, - MBEDTLS_MODE_CBC, - 192, - "AES-192-CBC", - 16, - 0, - 16, - &aes_info -}; - -static const mbedtls_cipher_info_t aes_256_cbc_info = { - MBEDTLS_CIPHER_AES_256_CBC, - MBEDTLS_MODE_CBC, - 256, - "AES-256-CBC", - 16, - 0, - 16, - &aes_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -static const mbedtls_cipher_info_t aes_128_cfb128_info = { - MBEDTLS_CIPHER_AES_128_CFB128, - MBEDTLS_MODE_CFB, - 128, - "AES-128-CFB128", - 16, - 0, - 16, - &aes_info -}; - -static const mbedtls_cipher_info_t aes_192_cfb128_info = { - MBEDTLS_CIPHER_AES_192_CFB128, - MBEDTLS_MODE_CFB, - 192, - "AES-192-CFB128", - 16, - 0, - 16, - &aes_info -}; - -static const mbedtls_cipher_info_t aes_256_cfb128_info = { - MBEDTLS_CIPHER_AES_256_CFB128, - MBEDTLS_MODE_CFB, - 256, - "AES-256-CFB128", - 16, - 0, - 16, - &aes_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -static const mbedtls_cipher_info_t aes_128_ctr_info = { - MBEDTLS_CIPHER_AES_128_CTR, - MBEDTLS_MODE_CTR, - 128, - "AES-128-CTR", - 16, - 0, - 16, - &aes_info -}; - -static const mbedtls_cipher_info_t aes_192_ctr_info = { - MBEDTLS_CIPHER_AES_192_CTR, - MBEDTLS_MODE_CTR, - 192, - "AES-192-CTR", - 16, - 0, - 16, - &aes_info -}; - -static const mbedtls_cipher_info_t aes_256_ctr_info = { - MBEDTLS_CIPHER_AES_256_CTR, - MBEDTLS_MODE_CTR, - 256, - "AES-256-CTR", - 16, - 0, - 16, - &aes_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -#if defined(MBEDTLS_GCM_C) -static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES, - key, key_bitlen ); -} - -static const mbedtls_cipher_base_t gcm_aes_info = { - MBEDTLS_CIPHER_ID_AES, - NULL, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - gcm_aes_setkey_wrap, - gcm_aes_setkey_wrap, - gcm_ctx_alloc, - gcm_ctx_free, -}; - -static const mbedtls_cipher_info_t aes_128_gcm_info = { - MBEDTLS_CIPHER_AES_128_GCM, - MBEDTLS_MODE_GCM, - 128, - "AES-128-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &gcm_aes_info -}; - -static const mbedtls_cipher_info_t aes_192_gcm_info = { - MBEDTLS_CIPHER_AES_192_GCM, - MBEDTLS_MODE_GCM, - 192, - "AES-192-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &gcm_aes_info -}; - -static const mbedtls_cipher_info_t aes_256_gcm_info = { - MBEDTLS_CIPHER_AES_256_GCM, - MBEDTLS_MODE_GCM, - 256, - "AES-256-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &gcm_aes_info -}; -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CCM_C) -static int ccm_aes_setkey_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES, - key, key_bitlen ); -} - -static const mbedtls_cipher_base_t ccm_aes_info = { - MBEDTLS_CIPHER_ID_AES, - NULL, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - ccm_aes_setkey_wrap, - ccm_aes_setkey_wrap, - ccm_ctx_alloc, - ccm_ctx_free, -}; - -static const mbedtls_cipher_info_t aes_128_ccm_info = { - MBEDTLS_CIPHER_AES_128_CCM, - MBEDTLS_MODE_CCM, - 128, - "AES-128-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &ccm_aes_info -}; - -static const mbedtls_cipher_info_t aes_192_ccm_info = { - MBEDTLS_CIPHER_AES_192_CCM, - MBEDTLS_MODE_CCM, - 192, - "AES-192-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &ccm_aes_info -}; - -static const mbedtls_cipher_info_t aes_256_ccm_info = { - MBEDTLS_CIPHER_AES_256_CCM, - MBEDTLS_MODE_CCM, - 256, - "AES-256-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &ccm_aes_info -}; -#endif /* MBEDTLS_CCM_C */ - -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) - -static int camellia_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_camellia_crypt_ecb( (mbedtls_camellia_context *) ctx, operation, input, - output ); -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static int camellia_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, - size_t length, unsigned char *iv, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_camellia_crypt_cbc( (mbedtls_camellia_context *) ctx, operation, length, iv, - input, output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -static int camellia_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, - size_t length, size_t *iv_off, unsigned char *iv, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_camellia_crypt_cfb128( (mbedtls_camellia_context *) ctx, operation, length, - iv_off, iv, input, output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -static int camellia_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, - unsigned char *nonce_counter, unsigned char *stream_block, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_camellia_crypt_ctr( (mbedtls_camellia_context *) ctx, length, nc_off, - nonce_counter, stream_block, input, output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_camellia_setkey_dec( (mbedtls_camellia_context *) ctx, key, key_bitlen ); -} - -static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_camellia_setkey_enc( (mbedtls_camellia_context *) ctx, key, key_bitlen ); -} - -static void * camellia_ctx_alloc( void ) -{ - mbedtls_camellia_context *ctx; - ctx = mbedtls_calloc( 1, sizeof( mbedtls_camellia_context ) ); - - if( ctx == NULL ) - return( NULL ); - - mbedtls_camellia_init( ctx ); - - return( ctx ); -} - -static void camellia_ctx_free( void *ctx ) -{ - mbedtls_camellia_free( (mbedtls_camellia_context *) ctx ); - mbedtls_free( ctx ); -} - -static const mbedtls_cipher_base_t camellia_info = { - MBEDTLS_CIPHER_ID_CAMELLIA, - camellia_crypt_ecb_wrap, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - camellia_crypt_cbc_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - camellia_crypt_cfb128_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - camellia_crypt_ctr_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - camellia_setkey_enc_wrap, - camellia_setkey_dec_wrap, - camellia_ctx_alloc, - camellia_ctx_free -}; - -static const mbedtls_cipher_info_t camellia_128_ecb_info = { - MBEDTLS_CIPHER_CAMELLIA_128_ECB, - MBEDTLS_MODE_ECB, - 128, - "CAMELLIA-128-ECB", - 16, - 0, - 16, - &camellia_info -}; - -static const mbedtls_cipher_info_t camellia_192_ecb_info = { - MBEDTLS_CIPHER_CAMELLIA_192_ECB, - MBEDTLS_MODE_ECB, - 192, - "CAMELLIA-192-ECB", - 16, - 0, - 16, - &camellia_info -}; - -static const mbedtls_cipher_info_t camellia_256_ecb_info = { - MBEDTLS_CIPHER_CAMELLIA_256_ECB, - MBEDTLS_MODE_ECB, - 256, - "CAMELLIA-256-ECB", - 16, - 0, - 16, - &camellia_info -}; - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static const mbedtls_cipher_info_t camellia_128_cbc_info = { - MBEDTLS_CIPHER_CAMELLIA_128_CBC, - MBEDTLS_MODE_CBC, - 128, - "CAMELLIA-128-CBC", - 16, - 0, - 16, - &camellia_info -}; - -static const mbedtls_cipher_info_t camellia_192_cbc_info = { - MBEDTLS_CIPHER_CAMELLIA_192_CBC, - MBEDTLS_MODE_CBC, - 192, - "CAMELLIA-192-CBC", - 16, - 0, - 16, - &camellia_info -}; - -static const mbedtls_cipher_info_t camellia_256_cbc_info = { - MBEDTLS_CIPHER_CAMELLIA_256_CBC, - MBEDTLS_MODE_CBC, - 256, - "CAMELLIA-256-CBC", - 16, - 0, - 16, - &camellia_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -static const mbedtls_cipher_info_t camellia_128_cfb128_info = { - MBEDTLS_CIPHER_CAMELLIA_128_CFB128, - MBEDTLS_MODE_CFB, - 128, - "CAMELLIA-128-CFB128", - 16, - 0, - 16, - &camellia_info -}; - -static const mbedtls_cipher_info_t camellia_192_cfb128_info = { - MBEDTLS_CIPHER_CAMELLIA_192_CFB128, - MBEDTLS_MODE_CFB, - 192, - "CAMELLIA-192-CFB128", - 16, - 0, - 16, - &camellia_info -}; - -static const mbedtls_cipher_info_t camellia_256_cfb128_info = { - MBEDTLS_CIPHER_CAMELLIA_256_CFB128, - MBEDTLS_MODE_CFB, - 256, - "CAMELLIA-256-CFB128", - 16, - 0, - 16, - &camellia_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -static const mbedtls_cipher_info_t camellia_128_ctr_info = { - MBEDTLS_CIPHER_CAMELLIA_128_CTR, - MBEDTLS_MODE_CTR, - 128, - "CAMELLIA-128-CTR", - 16, - 0, - 16, - &camellia_info -}; - -static const mbedtls_cipher_info_t camellia_192_ctr_info = { - MBEDTLS_CIPHER_CAMELLIA_192_CTR, - MBEDTLS_MODE_CTR, - 192, - "CAMELLIA-192-CTR", - 16, - 0, - 16, - &camellia_info -}; - -static const mbedtls_cipher_info_t camellia_256_ctr_info = { - MBEDTLS_CIPHER_CAMELLIA_256_CTR, - MBEDTLS_MODE_CTR, - 256, - "CAMELLIA-256-CTR", - 16, - 0, - 16, - &camellia_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -#if defined(MBEDTLS_GCM_C) -static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, - key, key_bitlen ); -} - -static const mbedtls_cipher_base_t gcm_camellia_info = { - MBEDTLS_CIPHER_ID_CAMELLIA, - NULL, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - gcm_camellia_setkey_wrap, - gcm_camellia_setkey_wrap, - gcm_ctx_alloc, - gcm_ctx_free, -}; - -static const mbedtls_cipher_info_t camellia_128_gcm_info = { - MBEDTLS_CIPHER_CAMELLIA_128_GCM, - MBEDTLS_MODE_GCM, - 128, - "CAMELLIA-128-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &gcm_camellia_info -}; - -static const mbedtls_cipher_info_t camellia_192_gcm_info = { - MBEDTLS_CIPHER_CAMELLIA_192_GCM, - MBEDTLS_MODE_GCM, - 192, - "CAMELLIA-192-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &gcm_camellia_info -}; - -static const mbedtls_cipher_info_t camellia_256_gcm_info = { - MBEDTLS_CIPHER_CAMELLIA_256_GCM, - MBEDTLS_MODE_GCM, - 256, - "CAMELLIA-256-GCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &gcm_camellia_info -}; -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CCM_C) -static int ccm_camellia_setkey_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, - key, key_bitlen ); -} - -static const mbedtls_cipher_base_t ccm_camellia_info = { - MBEDTLS_CIPHER_ID_CAMELLIA, - NULL, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - ccm_camellia_setkey_wrap, - ccm_camellia_setkey_wrap, - ccm_ctx_alloc, - ccm_ctx_free, -}; - -static const mbedtls_cipher_info_t camellia_128_ccm_info = { - MBEDTLS_CIPHER_CAMELLIA_128_CCM, - MBEDTLS_MODE_CCM, - 128, - "CAMELLIA-128-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &ccm_camellia_info -}; - -static const mbedtls_cipher_info_t camellia_192_ccm_info = { - MBEDTLS_CIPHER_CAMELLIA_192_CCM, - MBEDTLS_MODE_CCM, - 192, - "CAMELLIA-192-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &ccm_camellia_info -}; - -static const mbedtls_cipher_info_t camellia_256_ccm_info = { - MBEDTLS_CIPHER_CAMELLIA_256_CCM, - MBEDTLS_MODE_CCM, - 256, - "CAMELLIA-256-CCM", - 12, - MBEDTLS_CIPHER_VARIABLE_IV_LEN, - 16, - &ccm_camellia_info -}; -#endif /* MBEDTLS_CCM_C */ - -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) - -static int des_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, - const unsigned char *input, unsigned char *output ) -{ - ((void) operation); - return mbedtls_des_crypt_ecb( (mbedtls_des_context *) ctx, input, output ); -} - -static int des3_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, - const unsigned char *input, unsigned char *output ) -{ - ((void) operation); - return mbedtls_des3_crypt_ecb( (mbedtls_des3_context *) ctx, input, output ); -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static int des_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, - unsigned char *iv, const unsigned char *input, unsigned char *output ) -{ - return mbedtls_des_crypt_cbc( (mbedtls_des_context *) ctx, operation, length, iv, input, - output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static int des3_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, - unsigned char *iv, const unsigned char *input, unsigned char *output ) -{ - return mbedtls_des3_crypt_cbc( (mbedtls_des3_context *) ctx, operation, length, iv, input, - output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -static int des_setkey_dec_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - ((void) key_bitlen); - - return mbedtls_des_setkey_dec( (mbedtls_des_context *) ctx, key ); -} - -static int des_setkey_enc_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - ((void) key_bitlen); - - return mbedtls_des_setkey_enc( (mbedtls_des_context *) ctx, key ); -} - -static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - ((void) key_bitlen); - - return mbedtls_des3_set2key_dec( (mbedtls_des3_context *) ctx, key ); -} - -static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - ((void) key_bitlen); - - return mbedtls_des3_set2key_enc( (mbedtls_des3_context *) ctx, key ); -} - -static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - ((void) key_bitlen); - - return mbedtls_des3_set3key_dec( (mbedtls_des3_context *) ctx, key ); -} - -static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - ((void) key_bitlen); - - return mbedtls_des3_set3key_enc( (mbedtls_des3_context *) ctx, key ); -} - -static void * des_ctx_alloc( void ) -{ - mbedtls_des_context *des = mbedtls_calloc( 1, sizeof( mbedtls_des_context ) ); - - if( des == NULL ) - return( NULL ); - - mbedtls_des_init( des ); - - return( des ); -} - -static void des_ctx_free( void *ctx ) -{ - mbedtls_des_free( (mbedtls_des_context *) ctx ); - mbedtls_free( ctx ); -} - -static void * des3_ctx_alloc( void ) -{ - mbedtls_des3_context *des3; - des3 = mbedtls_calloc( 1, sizeof( mbedtls_des3_context ) ); - - if( des3 == NULL ) - return( NULL ); - - mbedtls_des3_init( des3 ); - - return( des3 ); -} - -static void des3_ctx_free( void *ctx ) -{ - mbedtls_des3_free( (mbedtls_des3_context *) ctx ); - mbedtls_free( ctx ); -} - -static const mbedtls_cipher_base_t des_info = { - MBEDTLS_CIPHER_ID_DES, - des_crypt_ecb_wrap, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - des_crypt_cbc_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - des_setkey_enc_wrap, - des_setkey_dec_wrap, - des_ctx_alloc, - des_ctx_free -}; - -static const mbedtls_cipher_info_t des_ecb_info = { - MBEDTLS_CIPHER_DES_ECB, - MBEDTLS_MODE_ECB, - MBEDTLS_KEY_LENGTH_DES, - "DES-ECB", - 8, - 0, - 8, - &des_info -}; - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static const mbedtls_cipher_info_t des_cbc_info = { - MBEDTLS_CIPHER_DES_CBC, - MBEDTLS_MODE_CBC, - MBEDTLS_KEY_LENGTH_DES, - "DES-CBC", - 8, - 0, - 8, - &des_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -static const mbedtls_cipher_base_t des_ede_info = { - MBEDTLS_CIPHER_ID_DES, - des3_crypt_ecb_wrap, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - des3_crypt_cbc_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - des3_set2key_enc_wrap, - des3_set2key_dec_wrap, - des3_ctx_alloc, - des3_ctx_free -}; - -static const mbedtls_cipher_info_t des_ede_ecb_info = { - MBEDTLS_CIPHER_DES_EDE_ECB, - MBEDTLS_MODE_ECB, - MBEDTLS_KEY_LENGTH_DES_EDE, - "DES-EDE-ECB", - 8, - 0, - 8, - &des_ede_info -}; - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static const mbedtls_cipher_info_t des_ede_cbc_info = { - MBEDTLS_CIPHER_DES_EDE_CBC, - MBEDTLS_MODE_CBC, - MBEDTLS_KEY_LENGTH_DES_EDE, - "DES-EDE-CBC", - 8, - 0, - 8, - &des_ede_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -static const mbedtls_cipher_base_t des_ede3_info = { - MBEDTLS_CIPHER_ID_3DES, - des3_crypt_ecb_wrap, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - des3_crypt_cbc_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - des3_set3key_enc_wrap, - des3_set3key_dec_wrap, - des3_ctx_alloc, - des3_ctx_free -}; - -static const mbedtls_cipher_info_t des_ede3_ecb_info = { - MBEDTLS_CIPHER_DES_EDE3_ECB, - MBEDTLS_MODE_ECB, - MBEDTLS_KEY_LENGTH_DES_EDE3, - "DES-EDE3-ECB", - 8, - 0, - 8, - &des_ede3_info -}; -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static const mbedtls_cipher_info_t des_ede3_cbc_info = { - MBEDTLS_CIPHER_DES_EDE3_CBC, - MBEDTLS_MODE_CBC, - MBEDTLS_KEY_LENGTH_DES_EDE3, - "DES-EDE3-CBC", - 8, - 0, - 8, - &des_ede3_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_BLOWFISH_C) - -static int blowfish_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_blowfish_crypt_ecb( (mbedtls_blowfish_context *) ctx, operation, input, - output ); -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static int blowfish_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, - size_t length, unsigned char *iv, const unsigned char *input, - unsigned char *output ) -{ - return mbedtls_blowfish_crypt_cbc( (mbedtls_blowfish_context *) ctx, operation, length, iv, - input, output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -static int blowfish_crypt_cfb64_wrap( void *ctx, mbedtls_operation_t operation, - size_t length, size_t *iv_off, unsigned char *iv, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_blowfish_crypt_cfb64( (mbedtls_blowfish_context *) ctx, operation, length, - iv_off, iv, input, output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -static int blowfish_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, - unsigned char *nonce_counter, unsigned char *stream_block, - const unsigned char *input, unsigned char *output ) -{ - return mbedtls_blowfish_crypt_ctr( (mbedtls_blowfish_context *) ctx, length, nc_off, - nonce_counter, stream_block, input, output ); -} -#endif /* MBEDTLS_CIPHER_MODE_CTR */ - -static int blowfish_setkey_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - return mbedtls_blowfish_setkey( (mbedtls_blowfish_context *) ctx, key, key_bitlen ); -} - -static void * blowfish_ctx_alloc( void ) -{ - mbedtls_blowfish_context *ctx; - ctx = mbedtls_calloc( 1, sizeof( mbedtls_blowfish_context ) ); - - if( ctx == NULL ) - return( NULL ); - - mbedtls_blowfish_init( ctx ); - - return( ctx ); -} - -static void blowfish_ctx_free( void *ctx ) -{ - mbedtls_blowfish_free( (mbedtls_blowfish_context *) ctx ); - mbedtls_free( ctx ); -} - -static const mbedtls_cipher_base_t blowfish_info = { - MBEDTLS_CIPHER_ID_BLOWFISH, - blowfish_crypt_ecb_wrap, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - blowfish_crypt_cbc_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - blowfish_crypt_cfb64_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - blowfish_crypt_ctr_wrap, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - NULL, -#endif - blowfish_setkey_wrap, - blowfish_setkey_wrap, - blowfish_ctx_alloc, - blowfish_ctx_free -}; - -static const mbedtls_cipher_info_t blowfish_ecb_info = { - MBEDTLS_CIPHER_BLOWFISH_ECB, - MBEDTLS_MODE_ECB, - 128, - "BLOWFISH-ECB", - 8, - MBEDTLS_CIPHER_VARIABLE_KEY_LEN, - 8, - &blowfish_info -}; - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static const mbedtls_cipher_info_t blowfish_cbc_info = { - MBEDTLS_CIPHER_BLOWFISH_CBC, - MBEDTLS_MODE_CBC, - 128, - "BLOWFISH-CBC", - 8, - MBEDTLS_CIPHER_VARIABLE_KEY_LEN, - 8, - &blowfish_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_CIPHER_MODE_CFB) -static const mbedtls_cipher_info_t blowfish_cfb64_info = { - MBEDTLS_CIPHER_BLOWFISH_CFB64, - MBEDTLS_MODE_CFB, - 128, - "BLOWFISH-CFB64", - 8, - MBEDTLS_CIPHER_VARIABLE_KEY_LEN, - 8, - &blowfish_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CFB */ - -#if defined(MBEDTLS_CIPHER_MODE_CTR) -static const mbedtls_cipher_info_t blowfish_ctr_info = { - MBEDTLS_CIPHER_BLOWFISH_CTR, - MBEDTLS_MODE_CTR, - 128, - "BLOWFISH-CTR", - 8, - MBEDTLS_CIPHER_VARIABLE_KEY_LEN, - 8, - &blowfish_info -}; -#endif /* MBEDTLS_CIPHER_MODE_CTR */ -#endif /* MBEDTLS_BLOWFISH_C */ - -#if defined(MBEDTLS_ARC4_C) -static int arc4_crypt_stream_wrap( void *ctx, size_t length, - const unsigned char *input, - unsigned char *output ) -{ - return( mbedtls_arc4_crypt( (mbedtls_arc4_context *) ctx, length, input, output ) ); -} - -static int arc4_setkey_wrap( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - /* we get key_bitlen in bits, arc4 expects it in bytes */ - if( key_bitlen % 8 != 0 ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - mbedtls_arc4_setup( (mbedtls_arc4_context *) ctx, key, key_bitlen / 8 ); - return( 0 ); -} - -static void * arc4_ctx_alloc( void ) -{ - mbedtls_arc4_context *ctx; - ctx = mbedtls_calloc( 1, sizeof( mbedtls_arc4_context ) ); - - if( ctx == NULL ) - return( NULL ); - - mbedtls_arc4_init( ctx ); - - return( ctx ); -} - -static void arc4_ctx_free( void *ctx ) -{ - mbedtls_arc4_free( (mbedtls_arc4_context *) ctx ); - mbedtls_free( ctx ); -} - -static const mbedtls_cipher_base_t arc4_base_info = { - MBEDTLS_CIPHER_ID_ARC4, - NULL, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - arc4_crypt_stream_wrap, -#endif - arc4_setkey_wrap, - arc4_setkey_wrap, - arc4_ctx_alloc, - arc4_ctx_free -}; - -static const mbedtls_cipher_info_t arc4_128_info = { - MBEDTLS_CIPHER_ARC4_128, - MBEDTLS_MODE_STREAM, - 128, - "ARC4-128", - 0, - 0, - 1, - &arc4_base_info -}; -#endif /* MBEDTLS_ARC4_C */ - -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) -static int null_crypt_stream( void *ctx, size_t length, - const unsigned char *input, - unsigned char *output ) -{ - ((void) ctx); - memmove( output, input, length ); - return( 0 ); -} - -static int null_setkey( void *ctx, const unsigned char *key, - unsigned int key_bitlen ) -{ - ((void) ctx); - ((void) key); - ((void) key_bitlen); - - return( 0 ); -} - -static void * null_ctx_alloc( void ) -{ - return( (void *) 1 ); -} - -static void null_ctx_free( void *ctx ) -{ - ((void) ctx); -} - -static const mbedtls_cipher_base_t null_base_info = { - MBEDTLS_CIPHER_ID_NULL, - NULL, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - NULL, -#endif -#if defined(MBEDTLS_CIPHER_MODE_STREAM) - null_crypt_stream, -#endif - null_setkey, - null_setkey, - null_ctx_alloc, - null_ctx_free -}; - -static const mbedtls_cipher_info_t null_cipher_info = { - MBEDTLS_CIPHER_NULL, - MBEDTLS_MODE_STREAM, - 0, - "NULL", - 0, - 0, - 1, - &null_base_info -}; -#endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */ - -const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = -{ -#if defined(MBEDTLS_AES_C) - { MBEDTLS_CIPHER_AES_128_ECB, &aes_128_ecb_info }, - { MBEDTLS_CIPHER_AES_192_ECB, &aes_192_ecb_info }, - { MBEDTLS_CIPHER_AES_256_ECB, &aes_256_ecb_info }, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_CIPHER_AES_128_CBC, &aes_128_cbc_info }, - { MBEDTLS_CIPHER_AES_192_CBC, &aes_192_cbc_info }, - { MBEDTLS_CIPHER_AES_256_CBC, &aes_256_cbc_info }, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - { MBEDTLS_CIPHER_AES_128_CFB128, &aes_128_cfb128_info }, - { MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, - { MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - { MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info }, - { MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info }, - { MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info }, -#endif -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info }, - { MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info }, - { MBEDTLS_CIPHER_AES_256_GCM, &aes_256_gcm_info }, -#endif -#if defined(MBEDTLS_CCM_C) - { MBEDTLS_CIPHER_AES_128_CCM, &aes_128_ccm_info }, - { MBEDTLS_CIPHER_AES_192_CCM, &aes_192_ccm_info }, - { MBEDTLS_CIPHER_AES_256_CCM, &aes_256_ccm_info }, -#endif -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_ARC4_C) - { MBEDTLS_CIPHER_ARC4_128, &arc4_128_info }, -#endif - -#if defined(MBEDTLS_BLOWFISH_C) - { MBEDTLS_CIPHER_BLOWFISH_ECB, &blowfish_ecb_info }, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_CIPHER_BLOWFISH_CBC, &blowfish_cbc_info }, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - { MBEDTLS_CIPHER_BLOWFISH_CFB64, &blowfish_cfb64_info }, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - { MBEDTLS_CIPHER_BLOWFISH_CTR, &blowfish_ctr_info }, -#endif -#endif /* MBEDTLS_BLOWFISH_C */ - -#if defined(MBEDTLS_CAMELLIA_C) - { MBEDTLS_CIPHER_CAMELLIA_128_ECB, &camellia_128_ecb_info }, - { MBEDTLS_CIPHER_CAMELLIA_192_ECB, &camellia_192_ecb_info }, - { MBEDTLS_CIPHER_CAMELLIA_256_ECB, &camellia_256_ecb_info }, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_CIPHER_CAMELLIA_128_CBC, &camellia_128_cbc_info }, - { MBEDTLS_CIPHER_CAMELLIA_192_CBC, &camellia_192_cbc_info }, - { MBEDTLS_CIPHER_CAMELLIA_256_CBC, &camellia_256_cbc_info }, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CFB) - { MBEDTLS_CIPHER_CAMELLIA_128_CFB128, &camellia_128_cfb128_info }, - { MBEDTLS_CIPHER_CAMELLIA_192_CFB128, &camellia_192_cfb128_info }, - { MBEDTLS_CIPHER_CAMELLIA_256_CFB128, &camellia_256_cfb128_info }, -#endif -#if defined(MBEDTLS_CIPHER_MODE_CTR) - { MBEDTLS_CIPHER_CAMELLIA_128_CTR, &camellia_128_ctr_info }, - { MBEDTLS_CIPHER_CAMELLIA_192_CTR, &camellia_192_ctr_info }, - { MBEDTLS_CIPHER_CAMELLIA_256_CTR, &camellia_256_ctr_info }, -#endif -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_CIPHER_CAMELLIA_128_GCM, &camellia_128_gcm_info }, - { MBEDTLS_CIPHER_CAMELLIA_192_GCM, &camellia_192_gcm_info }, - { MBEDTLS_CIPHER_CAMELLIA_256_GCM, &camellia_256_gcm_info }, -#endif -#if defined(MBEDTLS_CCM_C) - { MBEDTLS_CIPHER_CAMELLIA_128_CCM, &camellia_128_ccm_info }, - { MBEDTLS_CIPHER_CAMELLIA_192_CCM, &camellia_192_ccm_info }, - { MBEDTLS_CIPHER_CAMELLIA_256_CCM, &camellia_256_ccm_info }, -#endif -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) - { MBEDTLS_CIPHER_DES_ECB, &des_ecb_info }, - { MBEDTLS_CIPHER_DES_EDE_ECB, &des_ede_ecb_info }, - { MBEDTLS_CIPHER_DES_EDE3_ECB, &des_ede3_ecb_info }, -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_CIPHER_DES_CBC, &des_cbc_info }, - { MBEDTLS_CIPHER_DES_EDE_CBC, &des_ede_cbc_info }, - { MBEDTLS_CIPHER_DES_EDE3_CBC, &des_ede3_cbc_info }, -#endif -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) - { MBEDTLS_CIPHER_NULL, &null_cipher_info }, -#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ - - { MBEDTLS_CIPHER_NONE, NULL } -}; - -#define NUM_CIPHERS sizeof mbedtls_cipher_definitions / sizeof mbedtls_cipher_definitions[0] -int mbedtls_cipher_supported[NUM_CIPHERS]; - -#endif /* MBEDTLS_CIPHER_C */ diff --git a/components/mbedtls/library/cmac.c b/components/mbedtls/library/cmac.c deleted file mode 100644 index 6df56aa9a8..0000000000 --- a/components/mbedtls/library/cmac.c +++ /dev/null @@ -1,1074 +0,0 @@ -/** - * \file cmac.c - * - * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -/* - * References: - * - * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The - * CMAC Mode for Authentication - * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf - * - * - RFC 4493 - The AES-CMAC Algorithm - * https://tools.ietf.org/html/rfc4493 - * - * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message - * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128) - * Algorithm for the Internet Key Exchange Protocol (IKE) - * https://tools.ietf.org/html/rfc4615 - * - * Additional test vectors: ISO/IEC 9797-1 - * - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_CMAC_C) - -#include "mbedtls/cmac.h" - -#include - - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#if defined(MBEDTLS_SELF_TEST) -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_SELF_TEST */ -#endif /* MBEDTLS_PLATFORM_C */ - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -/* - * Multiplication by u in the Galois field of GF(2^n) - * - * As explained in NIST SP 800-38B, this can be computed: - * - * If MSB(p) = 0, then p = (p << 1) - * If MSB(p) = 1, then p = (p << 1) ^ R_n - * with R_64 = 0x1B and R_128 = 0x87 - * - * Input and output MUST NOT point to the same buffer - * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES. - */ -static int cmac_multiply_by_u( unsigned char *output, - const unsigned char *input, - size_t blocksize ) -{ - const unsigned char R_128 = 0x87; - const unsigned char R_64 = 0x1B; - unsigned char R_n, mask; - unsigned char overflow = 0x00; - int i; - - if( blocksize == MBEDTLS_AES_BLOCK_SIZE ) - { - R_n = R_128; - } - else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE ) - { - R_n = R_64; - } - else - { - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } - - for( i = (int)blocksize - 1; i >= 0; i-- ) - { - output[i] = input[i] << 1 | overflow; - overflow = input[i] >> 7; - } - - /* mask = ( input[0] >> 7 ) ? 0xff : 0x00 - * using bit operations to avoid branches */ - - /* MSVC has a warning about unary minus on unsigned, but this is - * well-defined and precisely what we want to do here */ -#if defined(_MSC_VER) -#pragma warning( push ) -#pragma warning( disable : 4146 ) -#endif - mask = - ( input[0] >> 7 ); -#if defined(_MSC_VER) -#pragma warning( pop ) -#endif - - output[ blocksize - 1 ] ^= R_n & mask; - - return( 0 ); -} - -/* - * Generate subkeys - * - * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm - */ -static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx, - unsigned char* K1, unsigned char* K2 ) -{ - int ret; - unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX]; - size_t olen, block_size; - - mbedtls_zeroize( L, sizeof( L ) ); - - block_size = ctx->cipher_info->block_size; - - /* Calculate Ek(0) */ - if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 ) - goto exit; - - /* - * Generate K1 and K2 - */ - if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 ) - goto exit; - - if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 ) - goto exit; - -exit: - mbedtls_zeroize( L, sizeof( L ) ); - - return( ret ); -} - -static void cmac_xor_block( unsigned char *output, const unsigned char *input1, - const unsigned char *input2, - const size_t block_size ) -{ - size_t idx; - - for( idx = 0; idx < block_size; idx++ ) - output[ idx ] = input1[ idx ] ^ input2[ idx ]; -} - -/* - * Create padded last block from (partial) last block. - * - * We can't use the padding option from the cipher layer, as it only works for - * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition. - */ -static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX], - size_t padded_block_len, - const unsigned char *last_block, - size_t last_block_len ) -{ - size_t j; - - for( j = 0; j < padded_block_len; j++ ) - { - if( j < last_block_len ) - padded_block[j] = last_block[j]; - else if( j == last_block_len ) - padded_block[j] = 0x80; - else - padded_block[j] = 0x00; - } -} - -int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, - const unsigned char *key, size_t keybits ) -{ - mbedtls_cipher_type_t type; - mbedtls_cmac_context_t *cmac_ctx; - int retval; - - if( ctx == NULL || ctx->cipher_info == NULL || key == NULL ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - if( ( retval = mbedtls_cipher_setkey( ctx, key, (int)keybits, - MBEDTLS_ENCRYPT ) ) != 0 ) - return( retval ); - - type = ctx->cipher_info->type; - - switch( type ) - { - case MBEDTLS_CIPHER_AES_128_ECB: - case MBEDTLS_CIPHER_AES_192_ECB: - case MBEDTLS_CIPHER_AES_256_ECB: - case MBEDTLS_CIPHER_DES_EDE3_ECB: - break; - default: - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - } - - /* Allocated and initialise in the cipher context memory for the CMAC - * context */ - cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) ); - if( cmac_ctx == NULL ) - return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); - - ctx->cmac_ctx = cmac_ctx; - - mbedtls_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); - - return 0; -} - -int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, - const unsigned char *input, size_t ilen ) -{ - mbedtls_cmac_context_t* cmac_ctx; - unsigned char *state; - int ret = 0; - size_t n, j, olen, block_size; - - if( ctx == NULL || ctx->cipher_info == NULL || input == NULL || - ctx->cmac_ctx == NULL ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - cmac_ctx = ctx->cmac_ctx; - block_size = ctx->cipher_info->block_size; - state = ctx->cmac_ctx->state; - - /* Is there data still to process from the last call, that's greater in - * size than a block? */ - if( cmac_ctx->unprocessed_len > 0 && - ilen > block_size - cmac_ctx->unprocessed_len ) - { - memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], - input, - block_size - cmac_ctx->unprocessed_len ); - - cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size ); - - if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, - &olen ) ) != 0 ) - { - goto exit; - } - - input += block_size - cmac_ctx->unprocessed_len; - ilen -= block_size - cmac_ctx->unprocessed_len; - cmac_ctx->unprocessed_len = 0; - } - - /* n is the number of blocks including any final partial block */ - n = ( ilen + block_size - 1 ) / block_size; - - /* Iterate across the input data in block sized chunks, excluding any - * final partial or complete block */ - for( j = 1; j < n; j++ ) - { - cmac_xor_block( state, input, state, block_size ); - - if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, - &olen ) ) != 0 ) - goto exit; - - ilen -= block_size; - input += block_size; - } - - /* If there is data left over that wasn't aligned to a block */ - if( ilen > 0 ) - { - memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], - input, - ilen ); - cmac_ctx->unprocessed_len += ilen; - } - -exit: - return( ret ); -} - -int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, - unsigned char *output ) -{ - mbedtls_cmac_context_t* cmac_ctx; - unsigned char *state, *last_block; - unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; - unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; - unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX]; - int ret; - size_t olen, block_size; - - if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL || - output == NULL ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - cmac_ctx = ctx->cmac_ctx; - block_size = ctx->cipher_info->block_size; - state = cmac_ctx->state; - - mbedtls_zeroize( K1, sizeof( K1 ) ); - mbedtls_zeroize( K2, sizeof( K2 ) ); - cmac_generate_subkeys( ctx, K1, K2 ); - - last_block = cmac_ctx->unprocessed_block; - - /* Calculate last block */ - if( cmac_ctx->unprocessed_len < block_size ) - { - cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len ); - cmac_xor_block( M_last, M_last, K2, block_size ); - } - else - { - /* Last block is complete block */ - cmac_xor_block( M_last, last_block, K1, block_size ); - } - - - cmac_xor_block( state, M_last, state, block_size ); - if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, - &olen ) ) != 0 ) - { - goto exit; - } - - memcpy( output, state, block_size ); - -exit: - /* Wipe the generated keys on the stack, and any other transients to avoid - * side channel leakage */ - mbedtls_zeroize( K1, sizeof( K1 ) ); - mbedtls_zeroize( K2, sizeof( K2 ) ); - - cmac_ctx->unprocessed_len = 0; - mbedtls_zeroize( cmac_ctx->unprocessed_block, - sizeof( cmac_ctx->unprocessed_block ) ); - - mbedtls_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX ); - return( ret ); -} - -int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) -{ - mbedtls_cmac_context_t* cmac_ctx; - - if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - cmac_ctx = ctx->cmac_ctx; - - /* Reset the internal state */ - cmac_ctx->unprocessed_len = 0; - mbedtls_zeroize( cmac_ctx->unprocessed_block, - sizeof( cmac_ctx->unprocessed_block ) ); - mbedtls_zeroize( cmac_ctx->state, - sizeof( cmac_ctx->state ) ); - - return( 0 ); -} - -int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, - const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - mbedtls_cipher_context_t ctx; - int ret; - - if( cipher_info == NULL || key == NULL || input == NULL || output == NULL ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - mbedtls_cipher_init( &ctx ); - - if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) - goto exit; - - ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen ); - if( ret != 0 ) - goto exit; - - ret = mbedtls_cipher_cmac_update( &ctx, input, ilen ); - if( ret != 0 ) - goto exit; - - ret = mbedtls_cipher_cmac_finish( &ctx, output ); - -exit: - mbedtls_cipher_free( &ctx ); - - return( ret ); -} - -#if defined(MBEDTLS_AES_C) -/* - * Implementation of AES-CMAC-PRF-128 defined in RFC 4615 - */ -int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, - const unsigned char *input, size_t in_len, - unsigned char *output ) -{ - int ret; - const mbedtls_cipher_info_t *cipher_info; - unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE]; - unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE]; - - if( key == NULL || input == NULL || output == NULL ) - return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - - cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB ); - if( cipher_info == NULL ) - { - /* Failing at this point must be due to a build issue */ - ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; - goto exit; - } - - if( key_length == MBEDTLS_AES_BLOCK_SIZE ) - { - /* Use key as is */ - memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE ); - } - else - { - memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE ); - - ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key, - key_length, int_key ); - if( ret != 0 ) - goto exit; - } - - ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len, - output ); - -exit: - mbedtls_zeroize( int_key, sizeof( int_key ) ); - - return( ret ); -} -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_SELF_TEST) -/* - * CMAC test data for SP800-38B - * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf - * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf - * - * AES-CMAC-PRF-128 test data from RFC 4615 - * https://tools.ietf.org/html/rfc4615#page-4 - */ - -#define NB_CMAC_TESTS_PER_KEY 4 -#define NB_PRF_TESTS 3 - -#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) -/* All CMAC test inputs are truncated from the same 64 byte buffer. */ -static const unsigned char test_message[] = { - /* PT */ - 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, - 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, - 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, - 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, - 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, - 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 -}; -#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */ - -#if defined(MBEDTLS_AES_C) -/* Truncation point of message for AES CMAC tests */ -static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { - /* Mlen */ - 0, - 16, - 20, - 64 -}; - -/* CMAC-AES128 Test Data */ -static const unsigned char aes_128_key[16] = { - 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, - 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c -}; -static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { - { - /* K1 */ - 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, - 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde - }, - { - /* K2 */ - 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, - 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b - } -}; -static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { - { - /* Example #1 */ - 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, - 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 - }, - { - /* Example #2 */ - 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, - 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c - }, - { - /* Example #3 */ - 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8, - 0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde - }, - { - /* Example #4 */ - 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, - 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe - } -}; - -/* CMAC-AES192 Test Data */ -static const unsigned char aes_192_key[24] = { - 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, - 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, - 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b -}; -static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { - { - /* K1 */ - 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, - 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96 - }, - { - /* K2 */ - 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, - 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c - } -}; -static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { - { - /* Example #1 */ - 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, - 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67 - }, - { - /* Example #2 */ - 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, - 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84 - }, - { - /* Example #3 */ - 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04, - 0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8 - }, - { - /* Example #4 */ - 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, - 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11 - } -}; - -/* CMAC-AES256 Test Data */ -static const unsigned char aes_256_key[32] = { - 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, - 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, - 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, - 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 -}; -static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { - { - /* K1 */ - 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac, - 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f - }, - { - /* K2 */ - 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58, - 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9 - } -}; -static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { - { - /* Example #1 */ - 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, - 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83 - }, - { - /* Example #2 */ - 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, - 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c - }, - { - /* Example #3 */ - 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a, - 0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93 - }, - { - /* Example #4 */ - 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, - 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10 - } -}; -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_DES_C) -/* Truncation point of message for 3DES CMAC tests */ -static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { - 0, - 16, - 20, - 32 -}; - -/* CMAC-TDES (Generation) - 2 Key Test Data */ -static const unsigned char des3_2key_key[24] = { - /* Key1 */ - 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, - /* Key2 */ - 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01, - /* Key3 */ - 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef -}; -static const unsigned char des3_2key_subkeys[2][8] = { - { - /* K1 */ - 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9 - }, - { - /* K2 */ - 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2 - } -}; -static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { - { - /* Sample #1 */ - 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60 - }, - { - /* Sample #2 */ - 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b - }, - { - /* Sample #3 */ - 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69 - }, - { - /* Sample #4 */ - 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb - } -}; - -/* CMAC-TDES (Generation) - 3 Key Test Data */ -static const unsigned char des3_3key_key[24] = { - /* Key1 */ - 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef, - /* Key2 */ - 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, - /* Key3 */ - 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23 -}; -static const unsigned char des3_3key_subkeys[2][8] = { - { - /* K1 */ - 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0 - }, - { - /* K2 */ - 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b - } -}; -static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { - { - /* Sample #1 */ - 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50 - }, - { - /* Sample #2 */ - 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09 - }, - { - /* Sample #3 */ - 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2 - }, - { - /* Sample #4 */ - 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5 - } -}; - -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_AES_C) -/* AES AES-CMAC-PRF-128 Test Data */ -static const unsigned char PRFK[] = { - /* Key */ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0xed, 0xcb -}; - -/* Sizes in bytes */ -static const size_t PRFKlen[NB_PRF_TESTS] = { - 18, - 16, - 10 -}; - -/* Message */ -static const unsigned char PRFM[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13 -}; - -static const unsigned char PRFT[NB_PRF_TESTS][16] = { - { - 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b, - 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a - }, - { - 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52, - 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d - }, - { - 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee, - 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d - } -}; -#endif /* MBEDTLS_AES_C */ - -static int cmac_test_subkeys( int verbose, - const char* testname, - const unsigned char* key, - int keybits, - const unsigned char* subkeys, - mbedtls_cipher_type_t cipher_type, - int block_size, - int num_tests ) -{ - int i, ret; - mbedtls_cipher_context_t ctx; - const mbedtls_cipher_info_t *cipher_info; - unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; - unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; - - cipher_info = mbedtls_cipher_info_from_type( cipher_type ); - if( cipher_info == NULL ) - { - /* Failing at this point must be due to a build issue */ - return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); - } - - for( i = 0; i < num_tests; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 ); - - mbedtls_cipher_init( &ctx ); - - if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "test execution failed\n" ); - - goto cleanup; - } - - if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits, - MBEDTLS_ENCRYPT ) ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "test execution failed\n" ); - - goto cleanup; - } - - ret = cmac_generate_subkeys( &ctx, K1, K2 ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - goto cleanup; - } - - if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 || - ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - goto cleanup; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - mbedtls_cipher_free( &ctx ); - } - - goto exit; - -cleanup: - mbedtls_cipher_free( &ctx ); - -exit: - return( ret ); -} - -static int cmac_test_wth_cipher( int verbose, - const char* testname, - const unsigned char* key, - int keybits, - const unsigned char* messages, - const unsigned int message_lengths[4], - const unsigned char* expected_result, - mbedtls_cipher_type_t cipher_type, - int block_size, - int num_tests ) -{ - const mbedtls_cipher_info_t *cipher_info; - int i, ret; - unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX]; - - cipher_info = mbedtls_cipher_info_from_type( cipher_type ); - if( cipher_info == NULL ) - { - /* Failing at this point must be due to a build issue */ - ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; - goto exit; - } - - for( i = 0; i < num_tests; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 ); - - if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages, - message_lengths[i], output ) ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - goto exit; - } - - if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - -exit: - return( ret ); -} - -#if defined(MBEDTLS_AES_C) -static int test_aes128_cmac_prf( int verbose ) -{ - int i; - int ret; - unsigned char output[MBEDTLS_AES_BLOCK_SIZE]; - - for( i = 0; i < NB_PRF_TESTS; i++ ) - { - mbedtls_printf( " AES CMAC 128 PRF #%u: ", i ); - ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output ); - if( ret != 0 || - memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 ) - { - - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( ret ); - } - else if( verbose != 0 ) - { - mbedtls_printf( "passed\n" ); - } - } - return( ret ); -} -#endif /* MBEDTLS_AES_C */ - -int mbedtls_cmac_self_test( int verbose ) -{ - int ret; - -#if defined(MBEDTLS_AES_C) - /* AES-128 */ - if( ( ret = cmac_test_subkeys( verbose, - "AES 128", - aes_128_key, - 128, - (const unsigned char*)aes_128_subkeys, - MBEDTLS_CIPHER_AES_128_ECB, - MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = cmac_test_wth_cipher( verbose, - "AES 128", - aes_128_key, - 128, - test_message, - aes_message_lengths, - (const unsigned char*)aes_128_expected_result, - MBEDTLS_CIPHER_AES_128_ECB, - MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } - - /* AES-192 */ - if( ( ret = cmac_test_subkeys( verbose, - "AES 192", - aes_192_key, - 192, - (const unsigned char*)aes_192_subkeys, - MBEDTLS_CIPHER_AES_192_ECB, - MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = cmac_test_wth_cipher( verbose, - "AES 192", - aes_192_key, - 192, - test_message, - aes_message_lengths, - (const unsigned char*)aes_192_expected_result, - MBEDTLS_CIPHER_AES_192_ECB, - MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } - - /* AES-256 */ - if( ( ret = cmac_test_subkeys( verbose, - "AES 256", - aes_256_key, - 256, - (const unsigned char*)aes_256_subkeys, - MBEDTLS_CIPHER_AES_256_ECB, - MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = cmac_test_wth_cipher ( verbose, - "AES 256", - aes_256_key, - 256, - test_message, - aes_message_lengths, - (const unsigned char*)aes_256_expected_result, - MBEDTLS_CIPHER_AES_256_ECB, - MBEDTLS_AES_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_DES_C) - /* 3DES 2 key */ - if( ( ret = cmac_test_subkeys( verbose, - "3DES 2 key", - des3_2key_key, - 192, - (const unsigned char*)des3_2key_subkeys, - MBEDTLS_CIPHER_DES_EDE3_ECB, - MBEDTLS_DES3_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = cmac_test_wth_cipher( verbose, - "3DES 2 key", - des3_2key_key, - 192, - test_message, - des3_message_lengths, - (const unsigned char*)des3_2key_expected_result, - MBEDTLS_CIPHER_DES_EDE3_ECB, - MBEDTLS_DES3_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } - - /* 3DES 3 key */ - if( ( ret = cmac_test_subkeys( verbose, - "3DES 3 key", - des3_3key_key, - 192, - (const unsigned char*)des3_3key_subkeys, - MBEDTLS_CIPHER_DES_EDE3_ECB, - MBEDTLS_DES3_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = cmac_test_wth_cipher( verbose, - "3DES 3 key", - des3_3key_key, - 192, - test_message, - des3_message_lengths, - (const unsigned char*)des3_3key_expected_result, - MBEDTLS_CIPHER_DES_EDE3_ECB, - MBEDTLS_DES3_BLOCK_SIZE, - NB_CMAC_TESTS_PER_KEY ) ) != 0 ) - { - return( ret ); - } -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_AES_C) - if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 ) - return( ret ); -#endif /* MBEDTLS_AES_C */ - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_CMAC_C */ diff --git a/components/mbedtls/library/ctr_drbg.c b/components/mbedtls/library/ctr_drbg.c deleted file mode 100644 index 55612c7fc9..0000000000 --- a/components/mbedtls/library/ctr_drbg.c +++ /dev/null @@ -1,594 +0,0 @@ -/* - * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The NIST SP 800-90 DRBGs are described in the following publucation. - * - * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_CTR_DRBG_C) - -#include "mbedtls/ctr_drbg.h" - -#include - -#if defined(MBEDTLS_FS_IO) -#include -#endif - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * CTR_DRBG context initialization - */ -void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif -} - -/* - * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow - * NIST tests to succeed (which require known length fixed entropy) - */ -int mbedtls_ctr_drbg_seed_entropy_len( - mbedtls_ctr_drbg_context *ctx, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len, - size_t entropy_len ) -{ - int ret; - unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; - - memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); - - mbedtls_aes_init( &ctx->aes_ctx ); - - ctx->f_entropy = f_entropy; - ctx->p_entropy = p_entropy; - - ctx->entropy_len = entropy_len; - ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; - - /* - * Initialize with an empty key - */ - mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ); - - if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len ) -{ - return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len, - MBEDTLS_CTR_DRBG_ENTROPY_LEN ) ); -} - -void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) -{ - if( ctx == NULL ) - return; - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); -#endif - mbedtls_aes_free( &ctx->aes_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); -} - -void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance ) -{ - ctx->prediction_resistance = resistance; -} - -void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len ) -{ - ctx->entropy_len = len; -} - -void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval ) -{ - ctx->reseed_interval = interval; -} - -static int block_cipher_df( unsigned char *output, - const unsigned char *data, size_t data_len ) -{ - unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; - unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; - unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; - unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; - unsigned char *p, *iv; - mbedtls_aes_context aes_ctx; - - int i, j; - size_t buf_len, use_len; - - if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) - return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); - - memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 ); - mbedtls_aes_init( &aes_ctx ); - - /* - * Construct IV (16 bytes) and S in buffer - * IV = Counter (in 32-bits) padded to 16 with zeroes - * S = Length input string (in 32-bits) || Length of output (in 32-bits) || - * data || 0x80 - * (Total is padded to a multiple of 16-bytes with zeroes) - */ - p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; - *p++ = ( data_len >> 24 ) & 0xff; - *p++ = ( data_len >> 16 ) & 0xff; - *p++ = ( data_len >> 8 ) & 0xff; - *p++ = ( data_len ) & 0xff; - p += 3; - *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; - memcpy( p, data, data_len ); - p[data_len] = 0x80; - - buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; - - for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ ) - key[i] = i; - - mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ); - - /* - * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data - */ - for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) - { - p = buf; - memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE ); - use_len = buf_len; - - while( use_len > 0 ) - { - for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ ) - chain[i] ^= p[i]; - p += MBEDTLS_CTR_DRBG_BLOCKSIZE; - use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? - MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; - - mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ); - } - - memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); - - /* - * Update IV - */ - buf[3]++; - } - - /* - * Do final encryption with reduced data - */ - mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ); - iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; - p = output; - - for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) - { - mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); - memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); - p += MBEDTLS_CTR_DRBG_BLOCKSIZE; - } - - mbedtls_aes_free( &aes_ctx ); - - return( 0 ); -} - -static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, - const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) -{ - unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; - unsigned char *p = tmp; - int i, j; - - memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); - - for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) - { - /* - * Increase counter - */ - for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) - if( ++ctx->counter[i - 1] != 0 ) - break; - - /* - * Crypt counter block - */ - mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ); - - p += MBEDTLS_CTR_DRBG_BLOCKSIZE; - } - - for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) - tmp[i] ^= data[i]; - - /* - * Update key and counter - */ - mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ); - memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE ); - - return( 0 ); -} - -void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, size_t add_len ) -{ - unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; - - if( add_len > 0 ) - { - /* MAX_INPUT would be more logical here, but we have to match - * block_cipher_df()'s limits since we can't propagate errors */ - if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) - add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; - - block_cipher_df( add_input, additional, add_len ); - ctr_drbg_update_internal( ctx, add_input ); - } -} - -int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, - const unsigned char *additional, size_t len ) -{ - unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; - size_t seedlen = 0; - - if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT || - len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len ) - return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); - - memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); - - /* - * Gather entropy_len bytes of entropy to seed state - */ - if( 0 != ctx->f_entropy( ctx->p_entropy, seed, - ctx->entropy_len ) ) - { - return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); - } - - seedlen += ctx->entropy_len; - - /* - * Add additional data - */ - if( additional && len ) - { - memcpy( seed + seedlen, additional, len ); - seedlen += len; - } - - /* - * Reduce to 384 bits - */ - block_cipher_df( seed, seed, seedlen ); - - /* - * Update state - */ - ctr_drbg_update_internal( ctx, seed ); - ctx->reseed_counter = 1; - - return( 0 ); -} - -int mbedtls_ctr_drbg_random_with_add( void *p_rng, - unsigned char *output, size_t output_len, - const unsigned char *additional, size_t add_len ) -{ - int ret = 0; - mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; - unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; - unsigned char *p = output; - unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; - int i; - size_t use_len; - - if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST ) - return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG ); - - if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT ) - return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); - - memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); - - if( ctx->reseed_counter > ctx->reseed_interval || - ctx->prediction_resistance ) - { - if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) - return( ret ); - - add_len = 0; - } - - if( add_len > 0 ) - { - block_cipher_df( add_input, additional, add_len ); - ctr_drbg_update_internal( ctx, add_input ); - } - - while( output_len > 0 ) - { - /* - * Increase counter - */ - for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) - if( ++ctx->counter[i - 1] != 0 ) - break; - - /* - * Crypt counter block - */ - mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ); - - use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : - output_len; - /* - * Copy random block to destination - */ - memcpy( p, tmp, use_len ); - p += use_len; - output_len -= use_len; - } - - ctr_drbg_update_internal( ctx, add_input ); - - ctx->reseed_counter++; - - return( 0 ); -} - -int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len ) -{ - int ret; - mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 ); - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -#if defined(MBEDTLS_FS_IO) -int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) -{ - int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; - FILE *f; - unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; - - if( ( f = fopen( path, "wb" ) ) == NULL ) - return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); - - if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 ) - goto exit; - - if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT ) - { - ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; - goto exit; - } - - ret = 0; - -exit: - fclose( f ); - return( ret ); -} - -int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) -{ - FILE *f; - size_t n; - unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); - - fseek( f, 0, SEEK_END ); - n = (size_t) ftell( f ); - fseek( f, 0, SEEK_SET ); - - if( n > MBEDTLS_CTR_DRBG_MAX_INPUT ) - { - fclose( f ); - return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); - } - - if( fread( buf, 1, n, f ) != n ) - { - fclose( f ); - return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); - } - - fclose( f ); - - mbedtls_ctr_drbg_update( ctx, buf, n ); - - return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); -} -#endif /* MBEDTLS_FS_IO */ - -#if defined(MBEDTLS_SELF_TEST) - -static const unsigned char entropy_source_pr[96] = - { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16, - 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02, - 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b, - 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb, - 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9, - 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95, - 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63, - 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3, - 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31, - 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4, - 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56, - 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 }; - -static const unsigned char entropy_source_nopr[64] = - { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14, - 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe, - 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d, - 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20, - 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9, - 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46, - 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e, - 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e }; - -static const unsigned char nonce_pers_pr[16] = - { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2, - 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c }; - -static const unsigned char nonce_pers_nopr[16] = - { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5, - 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f }; - -static const unsigned char result_pr[16] = - { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f, - 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 }; - -static const unsigned char result_nopr[16] = - { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88, - 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f }; - -static size_t test_offset; -static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, - size_t len ) -{ - const unsigned char *p = data; - memcpy( buf, p + test_offset, len ); - test_offset += len; - return( 0 ); -} - -#define CHK( c ) if( (c) != 0 ) \ - { \ - if( verbose != 0 ) \ - mbedtls_printf( "failed\n" ); \ - return( 1 ); \ - } - -/* - * Checkup routine - */ -int mbedtls_ctr_drbg_self_test( int verbose ) -{ - mbedtls_ctr_drbg_context ctx; - unsigned char buf[16]; - - mbedtls_ctr_drbg_init( &ctx ); - - /* - * Based on a NIST CTR_DRBG test vector (PR = True) - */ - if( verbose != 0 ) - mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); - - test_offset = 0; - CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, - (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) ); - mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); - CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); - CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); - CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); - - mbedtls_ctr_drbg_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - /* - * Based on a NIST CTR_DRBG test vector (PR = FALSE) - */ - if( verbose != 0 ) - mbedtls_printf( " CTR_DRBG (PR = FALSE): " ); - - mbedtls_ctr_drbg_init( &ctx ); - - test_offset = 0; - CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, - (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) ); - CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); - CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); - CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); - CHK( memcmp( buf, result_nopr, 16 ) ); - - mbedtls_ctr_drbg_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_CTR_DRBG_C */ diff --git a/components/mbedtls/library/debug.c b/components/mbedtls/library/debug.c deleted file mode 100644 index f9229b3606..0000000000 --- a/components/mbedtls/library/debug.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Debugging routines - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_DEBUG_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#define mbedtls_time_t time_t -#define mbedtls_snprintf snprintf -#endif - -#include "mbedtls/debug.h" - -#include -#include -#include - -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -#define DEBUG_BUF_SIZE 512 - -static int debug_threshold = 0; - -void mbedtls_debug_set_threshold( int threshold ) -{ - debug_threshold = threshold; -} - -/* - * All calls to f_dbg must be made via this function - */ -static inline void debug_send_line( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *str ) -{ - /* - * If in a threaded environment, we need a thread identifier. - * Since there is no portable way to get one, use the address of the ssl - * context instead, as it shouldn't be shared between threads. - */ -#if defined(MBEDTLS_THREADING_C) - char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */ - mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", (void*)ssl, str ); - ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, idstr ); -#else - ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str ); -#endif -} - -void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *format, ... ) -{ - va_list argp; - char str[DEBUG_BUF_SIZE]; - int ret; - - if( NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold ) - return; - - va_start( argp, format ); -#if defined(_WIN32) -#if defined(_TRUNCATE) - ret = _vsnprintf_s( str, DEBUG_BUF_SIZE, _TRUNCATE, format, argp ); -#else - ret = _vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); - if( ret < 0 || (size_t) ret == DEBUG_BUF_SIZE ) - { - str[DEBUG_BUF_SIZE-1] = '\0'; - ret = -1; - } -#endif -#else - ret = vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); -#endif - va_end( argp ); - - if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 ) - { - str[ret] = '\n'; - str[ret + 1] = '\0'; - } - - debug_send_line( ssl, level, file, line, str ); -} - -void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, int ret ) -{ - char str[DEBUG_BUF_SIZE]; - - if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold ) - return; - - /* - * With non-blocking I/O and examples that just retry immediately, - * the logs would be quickly flooded with WANT_READ, so ignore that. - * Don't ignore WANT_WRITE however, since is is usually rare. - */ - if( ret == MBEDTLS_ERR_SSL_WANT_READ ) - return; - - mbedtls_snprintf( str, sizeof( str ), "%s() returned %d (-0x%04x)\n", - text, ret, -ret ); - - debug_send_line( ssl, level, file, line, str ); -} - -void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, const char *text, - const unsigned char *buf, size_t len ) -{ - char str[DEBUG_BUF_SIZE]; - char txt[17]; - size_t i, idx = 0; - - if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold ) - return; - - mbedtls_snprintf( str + idx, sizeof( str ) - idx, "dumping '%s' (%u bytes)\n", - text, (unsigned int) len ); - - debug_send_line( ssl, level, file, line, str ); - - idx = 0; - memset( txt, 0, sizeof( txt ) ); - for( i = 0; i < len; i++ ) - { - if( i >= 4096 ) - break; - - if( i % 16 == 0 ) - { - if( i > 0 ) - { - mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); - debug_send_line( ssl, level, file, line, str ); - - idx = 0; - memset( txt, 0, sizeof( txt ) ); - } - - idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "%04x: ", - (unsigned int) i ); - - } - - idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", - (unsigned int) buf[i] ); - txt[i % 16] = ( buf[i] > 31 && buf[i] < 127 ) ? buf[i] : '.' ; - } - - if( len > 0 ) - { - for( /* i = i */; i % 16 != 0; i++ ) - idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " " ); - - mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); - debug_send_line( ssl, level, file, line, str ); - } -} - -#if defined(MBEDTLS_ECP_C) -void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_ecp_point *X ) -{ - char str[DEBUG_BUF_SIZE]; - - if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold ) - return; - - mbedtls_snprintf( str, sizeof( str ), "%s(X)", text ); - mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->X ); - - mbedtls_snprintf( str, sizeof( str ), "%s(Y)", text ); - mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->Y ); -} -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_BIGNUM_C) -void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_mpi *X ) -{ - char str[DEBUG_BUF_SIZE]; - int j, k, zeros = 1; - size_t i, n, idx = 0; - - if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || X == NULL || level > debug_threshold ) - return; - - for( n = X->n - 1; n > 0; n-- ) - if( X->p[n] != 0 ) - break; - - for( j = ( sizeof(mbedtls_mpi_uint) << 3 ) - 1; j >= 0; j-- ) - if( ( ( X->p[n] >> j ) & 1 ) != 0 ) - break; - - mbedtls_snprintf( str + idx, sizeof( str ) - idx, "value of '%s' (%d bits) is:\n", - text, (int) ( ( n * ( sizeof(mbedtls_mpi_uint) << 3 ) ) + j + 1 ) ); - - debug_send_line( ssl, level, file, line, str ); - - idx = 0; - for( i = n + 1, j = 0; i > 0; i-- ) - { - if( zeros && X->p[i - 1] == 0 ) - continue; - - for( k = sizeof( mbedtls_mpi_uint ) - 1; k >= 0; k-- ) - { - if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 ) - continue; - else - zeros = 0; - - if( j % 16 == 0 ) - { - if( j > 0 ) - { - mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); - debug_send_line( ssl, level, file, line, str ); - idx = 0; - } - } - - idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", (unsigned int) - ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ); - - j++; - } - - } - - if( zeros == 1 ) - idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " 00" ); - - mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); - debug_send_line( ssl, level, file, line, str ); -} -#endif /* MBEDTLS_BIGNUM_C */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -static void debug_print_pk( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_pk_context *pk ) -{ - size_t i; - mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS]; - char name[16]; - - memset( items, 0, sizeof( items ) ); - - if( mbedtls_pk_debug( pk, items ) != 0 ) - { - debug_send_line( ssl, level, file, line, - "invalid PK context\n" ); - return; - } - - for( i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++ ) - { - if( items[i].type == MBEDTLS_PK_DEBUG_NONE ) - return; - - mbedtls_snprintf( name, sizeof( name ), "%s%s", text, items[i].name ); - name[sizeof( name ) - 1] = '\0'; - - if( items[i].type == MBEDTLS_PK_DEBUG_MPI ) - mbedtls_debug_print_mpi( ssl, level, file, line, name, items[i].value ); - else -#if defined(MBEDTLS_ECP_C) - if( items[i].type == MBEDTLS_PK_DEBUG_ECP ) - mbedtls_debug_print_ecp( ssl, level, file, line, name, items[i].value ); - else -#endif - debug_send_line( ssl, level, file, line, - "should not happen\n" ); - } -} - -static void debug_print_line_by_line( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, const char *text ) -{ - char str[DEBUG_BUF_SIZE]; - const char *start, *cur; - - start = text; - for( cur = text; *cur != '\0'; cur++ ) - { - if( *cur == '\n' ) - { - size_t len = cur - start + 1; - if( len > DEBUG_BUF_SIZE - 1 ) - len = DEBUG_BUF_SIZE - 1; - - memcpy( str, start, len ); - str[len] = '\0'; - - debug_send_line( ssl, level, file, line, str ); - - start = cur + 1; - } - } -} - -void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, - const char *file, int line, - const char *text, const mbedtls_x509_crt *crt ) -{ - char str[DEBUG_BUF_SIZE]; - int i = 0; - - if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || crt == NULL || level > debug_threshold ) - return; - - while( crt != NULL ) - { - char buf[1024]; - - mbedtls_snprintf( str, sizeof( str ), "%s #%d:\n", text, ++i ); - debug_send_line( ssl, level, file, line, str ); - - mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); - debug_print_line_by_line( ssl, level, file, line, buf ); - - debug_print_pk( ssl, level, file, line, "crt->", &crt->pk ); - - crt = crt->next; - } -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#endif /* MBEDTLS_DEBUG_C */ diff --git a/components/mbedtls/library/des.c b/components/mbedtls/library/des.c deleted file mode 100644 index 09f95cfc3b..0000000000 --- a/components/mbedtls/library/des.c +++ /dev/null @@ -1,1061 +0,0 @@ -/* - * FIPS-46-3 compliant Triple-DES implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * DES, on which TDES is based, was originally designed by Horst Feistel - * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). - * - * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_DES_C) - -#include "mbedtls/des.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_DES_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT32_BE -#define GET_UINT32_BE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ - | ( (uint32_t) (b)[(i) + 1] << 16 ) \ - | ( (uint32_t) (b)[(i) + 2] << 8 ) \ - | ( (uint32_t) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_UINT32_BE -#define PUT_UINT32_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -/* - * Expanded DES S-boxes - */ -static const uint32_t SB1[64] = -{ - 0x01010400, 0x00000000, 0x00010000, 0x01010404, - 0x01010004, 0x00010404, 0x00000004, 0x00010000, - 0x00000400, 0x01010400, 0x01010404, 0x00000400, - 0x01000404, 0x01010004, 0x01000000, 0x00000004, - 0x00000404, 0x01000400, 0x01000400, 0x00010400, - 0x00010400, 0x01010000, 0x01010000, 0x01000404, - 0x00010004, 0x01000004, 0x01000004, 0x00010004, - 0x00000000, 0x00000404, 0x00010404, 0x01000000, - 0x00010000, 0x01010404, 0x00000004, 0x01010000, - 0x01010400, 0x01000000, 0x01000000, 0x00000400, - 0x01010004, 0x00010000, 0x00010400, 0x01000004, - 0x00000400, 0x00000004, 0x01000404, 0x00010404, - 0x01010404, 0x00010004, 0x01010000, 0x01000404, - 0x01000004, 0x00000404, 0x00010404, 0x01010400, - 0x00000404, 0x01000400, 0x01000400, 0x00000000, - 0x00010004, 0x00010400, 0x00000000, 0x01010004 -}; - -static const uint32_t SB2[64] = -{ - 0x80108020, 0x80008000, 0x00008000, 0x00108020, - 0x00100000, 0x00000020, 0x80100020, 0x80008020, - 0x80000020, 0x80108020, 0x80108000, 0x80000000, - 0x80008000, 0x00100000, 0x00000020, 0x80100020, - 0x00108000, 0x00100020, 0x80008020, 0x00000000, - 0x80000000, 0x00008000, 0x00108020, 0x80100000, - 0x00100020, 0x80000020, 0x00000000, 0x00108000, - 0x00008020, 0x80108000, 0x80100000, 0x00008020, - 0x00000000, 0x00108020, 0x80100020, 0x00100000, - 0x80008020, 0x80100000, 0x80108000, 0x00008000, - 0x80100000, 0x80008000, 0x00000020, 0x80108020, - 0x00108020, 0x00000020, 0x00008000, 0x80000000, - 0x00008020, 0x80108000, 0x00100000, 0x80000020, - 0x00100020, 0x80008020, 0x80000020, 0x00100020, - 0x00108000, 0x00000000, 0x80008000, 0x00008020, - 0x80000000, 0x80100020, 0x80108020, 0x00108000 -}; - -static const uint32_t SB3[64] = -{ - 0x00000208, 0x08020200, 0x00000000, 0x08020008, - 0x08000200, 0x00000000, 0x00020208, 0x08000200, - 0x00020008, 0x08000008, 0x08000008, 0x00020000, - 0x08020208, 0x00020008, 0x08020000, 0x00000208, - 0x08000000, 0x00000008, 0x08020200, 0x00000200, - 0x00020200, 0x08020000, 0x08020008, 0x00020208, - 0x08000208, 0x00020200, 0x00020000, 0x08000208, - 0x00000008, 0x08020208, 0x00000200, 0x08000000, - 0x08020200, 0x08000000, 0x00020008, 0x00000208, - 0x00020000, 0x08020200, 0x08000200, 0x00000000, - 0x00000200, 0x00020008, 0x08020208, 0x08000200, - 0x08000008, 0x00000200, 0x00000000, 0x08020008, - 0x08000208, 0x00020000, 0x08000000, 0x08020208, - 0x00000008, 0x00020208, 0x00020200, 0x08000008, - 0x08020000, 0x08000208, 0x00000208, 0x08020000, - 0x00020208, 0x00000008, 0x08020008, 0x00020200 -}; - -static const uint32_t SB4[64] = -{ - 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802080, 0x00800081, 0x00800001, 0x00002001, - 0x00000000, 0x00802000, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00800080, 0x00800001, - 0x00000001, 0x00002000, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002001, 0x00002080, - 0x00800081, 0x00000001, 0x00002080, 0x00800080, - 0x00002000, 0x00802080, 0x00802081, 0x00000081, - 0x00800080, 0x00800001, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00000000, 0x00802000, - 0x00002080, 0x00800080, 0x00800081, 0x00000001, - 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802081, 0x00000081, 0x00000001, 0x00002000, - 0x00800001, 0x00002001, 0x00802080, 0x00800081, - 0x00002001, 0x00002080, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002000, 0x00802080 -}; - -static const uint32_t SB5[64] = -{ - 0x00000100, 0x02080100, 0x02080000, 0x42000100, - 0x00080000, 0x00000100, 0x40000000, 0x02080000, - 0x40080100, 0x00080000, 0x02000100, 0x40080100, - 0x42000100, 0x42080000, 0x00080100, 0x40000000, - 0x02000000, 0x40080000, 0x40080000, 0x00000000, - 0x40000100, 0x42080100, 0x42080100, 0x02000100, - 0x42080000, 0x40000100, 0x00000000, 0x42000000, - 0x02080100, 0x02000000, 0x42000000, 0x00080100, - 0x00080000, 0x42000100, 0x00000100, 0x02000000, - 0x40000000, 0x02080000, 0x42000100, 0x40080100, - 0x02000100, 0x40000000, 0x42080000, 0x02080100, - 0x40080100, 0x00000100, 0x02000000, 0x42080000, - 0x42080100, 0x00080100, 0x42000000, 0x42080100, - 0x02080000, 0x00000000, 0x40080000, 0x42000000, - 0x00080100, 0x02000100, 0x40000100, 0x00080000, - 0x00000000, 0x40080000, 0x02080100, 0x40000100 -}; - -static const uint32_t SB6[64] = -{ - 0x20000010, 0x20400000, 0x00004000, 0x20404010, - 0x20400000, 0x00000010, 0x20404010, 0x00400000, - 0x20004000, 0x00404010, 0x00400000, 0x20000010, - 0x00400010, 0x20004000, 0x20000000, 0x00004010, - 0x00000000, 0x00400010, 0x20004010, 0x00004000, - 0x00404000, 0x20004010, 0x00000010, 0x20400010, - 0x20400010, 0x00000000, 0x00404010, 0x20404000, - 0x00004010, 0x00404000, 0x20404000, 0x20000000, - 0x20004000, 0x00000010, 0x20400010, 0x00404000, - 0x20404010, 0x00400000, 0x00004010, 0x20000010, - 0x00400000, 0x20004000, 0x20000000, 0x00004010, - 0x20000010, 0x20404010, 0x00404000, 0x20400000, - 0x00404010, 0x20404000, 0x00000000, 0x20400010, - 0x00000010, 0x00004000, 0x20400000, 0x00404010, - 0x00004000, 0x00400010, 0x20004010, 0x00000000, - 0x20404000, 0x20000000, 0x00400010, 0x20004010 -}; - -static const uint32_t SB7[64] = -{ - 0x00200000, 0x04200002, 0x04000802, 0x00000000, - 0x00000800, 0x04000802, 0x00200802, 0x04200800, - 0x04200802, 0x00200000, 0x00000000, 0x04000002, - 0x00000002, 0x04000000, 0x04200002, 0x00000802, - 0x04000800, 0x00200802, 0x00200002, 0x04000800, - 0x04000002, 0x04200000, 0x04200800, 0x00200002, - 0x04200000, 0x00000800, 0x00000802, 0x04200802, - 0x00200800, 0x00000002, 0x04000000, 0x00200800, - 0x04000000, 0x00200800, 0x00200000, 0x04000802, - 0x04000802, 0x04200002, 0x04200002, 0x00000002, - 0x00200002, 0x04000000, 0x04000800, 0x00200000, - 0x04200800, 0x00000802, 0x00200802, 0x04200800, - 0x00000802, 0x04000002, 0x04200802, 0x04200000, - 0x00200800, 0x00000000, 0x00000002, 0x04200802, - 0x00000000, 0x00200802, 0x04200000, 0x00000800, - 0x04000002, 0x04000800, 0x00000800, 0x00200002 -}; - -static const uint32_t SB8[64] = -{ - 0x10001040, 0x00001000, 0x00040000, 0x10041040, - 0x10000000, 0x10001040, 0x00000040, 0x10000000, - 0x00040040, 0x10040000, 0x10041040, 0x00041000, - 0x10041000, 0x00041040, 0x00001000, 0x00000040, - 0x10040000, 0x10000040, 0x10001000, 0x00001040, - 0x00041000, 0x00040040, 0x10040040, 0x10041000, - 0x00001040, 0x00000000, 0x00000000, 0x10040040, - 0x10000040, 0x10001000, 0x00041040, 0x00040000, - 0x00041040, 0x00040000, 0x10041000, 0x00001000, - 0x00000040, 0x10040040, 0x00001000, 0x00041040, - 0x10001000, 0x00000040, 0x10000040, 0x10040000, - 0x10040040, 0x10000000, 0x00040000, 0x10001040, - 0x00000000, 0x10041040, 0x00040040, 0x10000040, - 0x10040000, 0x10001000, 0x10001040, 0x00000000, - 0x10041040, 0x00041000, 0x00041000, 0x00001040, - 0x00001040, 0x00040040, 0x10000000, 0x10041000 -}; - -/* - * PC1: left and right halves bit-swap - */ -static const uint32_t LHs[16] = -{ - 0x00000000, 0x00000001, 0x00000100, 0x00000101, - 0x00010000, 0x00010001, 0x00010100, 0x00010101, - 0x01000000, 0x01000001, 0x01000100, 0x01000101, - 0x01010000, 0x01010001, 0x01010100, 0x01010101 -}; - -static const uint32_t RHs[16] = -{ - 0x00000000, 0x01000000, 0x00010000, 0x01010000, - 0x00000100, 0x01000100, 0x00010100, 0x01010100, - 0x00000001, 0x01000001, 0x00010001, 0x01010001, - 0x00000101, 0x01000101, 0x00010101, 0x01010101, -}; - -/* - * Initial Permutation macro - */ -#define DES_IP(X,Y) \ -{ \ - T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ - T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ - T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ - T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ - Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \ - T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \ - X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \ -} - -/* - * Final Permutation macro - */ -#define DES_FP(X,Y) \ -{ \ - X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \ - T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \ - Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \ - T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ - T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ - T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ - T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ -} - -/* - * DES round macro - */ -#define DES_ROUND(X,Y) \ -{ \ - T = *SK++ ^ X; \ - Y ^= SB8[ (T ) & 0x3F ] ^ \ - SB6[ (T >> 8) & 0x3F ] ^ \ - SB4[ (T >> 16) & 0x3F ] ^ \ - SB2[ (T >> 24) & 0x3F ]; \ - \ - T = *SK++ ^ ((X << 28) | (X >> 4)); \ - Y ^= SB7[ (T ) & 0x3F ] ^ \ - SB5[ (T >> 8) & 0x3F ] ^ \ - SB3[ (T >> 16) & 0x3F ] ^ \ - SB1[ (T >> 24) & 0x3F ]; \ -} - -#define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 0; } - -void mbedtls_des_init( mbedtls_des_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_des_context ) ); -} - -void mbedtls_des_free( mbedtls_des_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_des_context ) ); -} - -void mbedtls_des3_init( mbedtls_des3_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_des3_context ) ); -} - -void mbedtls_des3_free( mbedtls_des3_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_des3_context ) ); -} - -static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, - 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, - 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, - 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, - 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, - 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, - 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, - 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, - 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, - 254 }; - -void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ) -{ - int i; - - for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) - key[i] = odd_parity_table[key[i] / 2]; -} - -/* - * Check the given key's parity, returns 1 on failure, 0 on SUCCESS - */ -int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) -{ - int i; - - for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) - if( key[i] != odd_parity_table[key[i] / 2] ) - return( 1 ); - - return( 0 ); -} - -/* - * Table of weak and semi-weak keys - * - * Source: http://en.wikipedia.org/wiki/Weak_key - * - * Weak: - * Alternating ones + zeros (0x0101010101010101) - * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE) - * '0xE0E0E0E0F1F1F1F1' - * '0x1F1F1F1F0E0E0E0E' - * - * Semi-weak: - * 0x011F011F010E010E and 0x1F011F010E010E01 - * 0x01E001E001F101F1 and 0xE001E001F101F101 - * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01 - * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E - * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E - * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1 - * - */ - -#define WEAK_KEY_COUNT 16 - -static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] = -{ - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, - { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, - { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 }, - - { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E }, - { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 }, - { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 }, - { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 }, - { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE }, - { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 }, - { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 }, - { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E }, - { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, - { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E }, - { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, - { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 } -}; - -int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) -{ - int i; - - for( i = 0; i < WEAK_KEY_COUNT; i++ ) - if( memcmp( weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0 ) - return( 1 ); - - return( 0 ); -} - -#if !defined(MBEDTLS_DES_SETKEY_ALT) -void mbedtls_des_setkey( uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) -{ - int i; - uint32_t X, Y, T; - - GET_UINT32_BE( X, key, 0 ); - GET_UINT32_BE( Y, key, 4 ); - - /* - * Permuted Choice 1 - */ - T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); - T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); - - X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) - | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) - | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) - | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); - - Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) - | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) - | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) - | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); - - X &= 0x0FFFFFFF; - Y &= 0x0FFFFFFF; - - /* - * calculate subkeys - */ - for( i = 0; i < 16; i++ ) - { - if( i < 2 || i == 8 || i == 15 ) - { - X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; - Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; - } - else - { - X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; - Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; - } - - *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) - | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) - | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) - | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) - | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) - | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) - | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) - | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) - | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) - | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) - | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); - - *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) - | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) - | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) - | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) - | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) - | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) - | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) - | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) - | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) - | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) - | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); - } -} -#endif /* !MBEDTLS_DES_SETKEY_ALT */ - -/* - * DES key schedule (56-bit, encryption) - */ -int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) -{ - mbedtls_des_setkey( ctx->sk, key ); - - return( 0 ); -} - -/* - * DES key schedule (56-bit, decryption) - */ -int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) -{ - int i; - - mbedtls_des_setkey( ctx->sk, key ); - - for( i = 0; i < 16; i += 2 ) - { - SWAP( ctx->sk[i ], ctx->sk[30 - i] ); - SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); - } - - return( 0 ); -} - -static void des3_set2key( uint32_t esk[96], - uint32_t dsk[96], - const unsigned char key[MBEDTLS_DES_KEY_SIZE*2] ) -{ - int i; - - mbedtls_des_setkey( esk, key ); - mbedtls_des_setkey( dsk + 32, key + 8 ); - - for( i = 0; i < 32; i += 2 ) - { - dsk[i ] = esk[30 - i]; - dsk[i + 1] = esk[31 - i]; - - esk[i + 32] = dsk[62 - i]; - esk[i + 33] = dsk[63 - i]; - - esk[i + 64] = esk[i ]; - esk[i + 65] = esk[i + 1]; - - dsk[i + 64] = dsk[i ]; - dsk[i + 65] = dsk[i + 1]; - } -} - -/* - * Triple-DES key schedule (112-bit, encryption) - */ -int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) -{ - uint32_t sk[96]; - - des3_set2key( ctx->sk, sk, key ); - mbedtls_zeroize( sk, sizeof( sk ) ); - - return( 0 ); -} - -/* - * Triple-DES key schedule (112-bit, decryption) - */ -int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) -{ - uint32_t sk[96]; - - des3_set2key( sk, ctx->sk, key ); - mbedtls_zeroize( sk, sizeof( sk ) ); - - return( 0 ); -} - -static void des3_set3key( uint32_t esk[96], - uint32_t dsk[96], - const unsigned char key[24] ) -{ - int i; - - mbedtls_des_setkey( esk, key ); - mbedtls_des_setkey( dsk + 32, key + 8 ); - mbedtls_des_setkey( esk + 64, key + 16 ); - - for( i = 0; i < 32; i += 2 ) - { - dsk[i ] = esk[94 - i]; - dsk[i + 1] = esk[95 - i]; - - esk[i + 32] = dsk[62 - i]; - esk[i + 33] = dsk[63 - i]; - - dsk[i + 64] = esk[30 - i]; - dsk[i + 65] = esk[31 - i]; - } -} - -/* - * Triple-DES key schedule (168-bit, encryption) - */ -int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) -{ - uint32_t sk[96]; - - des3_set3key( ctx->sk, sk, key ); - mbedtls_zeroize( sk, sizeof( sk ) ); - - return( 0 ); -} - -/* - * Triple-DES key schedule (168-bit, decryption) - */ -int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, - const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) -{ - uint32_t sk[96]; - - des3_set3key( sk, ctx->sk, key ); - mbedtls_zeroize( sk, sizeof( sk ) ); - - return( 0 ); -} - -/* - * DES-ECB block encryption/decryption - */ -#if !defined(MBEDTLS_DES_CRYPT_ECB_ALT) -int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, - const unsigned char input[8], - unsigned char output[8] ) -{ - int i; - uint32_t X, Y, T, *SK; - - SK = ctx->sk; - - GET_UINT32_BE( X, input, 0 ); - GET_UINT32_BE( Y, input, 4 ); - - DES_IP( X, Y ); - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( Y, X ); - DES_ROUND( X, Y ); - } - - DES_FP( Y, X ); - - PUT_UINT32_BE( Y, output, 0 ); - PUT_UINT32_BE( X, output, 4 ); - - return( 0 ); -} -#endif /* !MBEDTLS_DES_CRYPT_ECB_ALT */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/* - * DES-CBC buffer encryption/decryption - */ -int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[8]; - - if( length % 8 ) - return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); - - if( mode == MBEDTLS_DES_ENCRYPT ) - { - while( length > 0 ) - { - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - mbedtls_des_crypt_ecb( ctx, output, output ); - memcpy( iv, output, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - else /* MBEDTLS_DES_DECRYPT */ - { - while( length > 0 ) - { - memcpy( temp, input, 8 ); - mbedtls_des_crypt_ecb( ctx, input, output ); - - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -/* - * 3DES-ECB block encryption/decryption - */ -#if !defined(MBEDTLS_DES3_CRYPT_ECB_ALT) -int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, - const unsigned char input[8], - unsigned char output[8] ) -{ - int i; - uint32_t X, Y, T, *SK; - - SK = ctx->sk; - - GET_UINT32_BE( X, input, 0 ); - GET_UINT32_BE( Y, input, 4 ); - - DES_IP( X, Y ); - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( Y, X ); - DES_ROUND( X, Y ); - } - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( X, Y ); - DES_ROUND( Y, X ); - } - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( Y, X ); - DES_ROUND( X, Y ); - } - - DES_FP( Y, X ); - - PUT_UINT32_BE( Y, output, 0 ); - PUT_UINT32_BE( X, output, 4 ); - - return( 0 ); -} -#endif /* !MBEDTLS_DES3_CRYPT_ECB_ALT */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/* - * 3DES-CBC buffer encryption/decryption - */ -int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[8]; - - if( length % 8 ) - return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); - - if( mode == MBEDTLS_DES_ENCRYPT ) - { - while( length > 0 ) - { - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - mbedtls_des3_crypt_ecb( ctx, output, output ); - memcpy( iv, output, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - else /* MBEDTLS_DES_DECRYPT */ - { - while( length > 0 ) - { - memcpy( temp, input, 8 ); - mbedtls_des3_crypt_ecb( ctx, input, output ); - - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#endif /* !MBEDTLS_DES_ALT */ - -#if defined(MBEDTLS_SELF_TEST) -/* - * DES and 3DES test vectors from: - * - * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip - */ -static const unsigned char des3_test_keys[24] = -{ - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, - 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 -}; - -static const unsigned char des3_test_buf[8] = -{ - 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 -}; - -static const unsigned char des3_test_ecb_dec[3][8] = -{ - { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D }, - { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB }, - { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A } -}; - -static const unsigned char des3_test_ecb_enc[3][8] = -{ - { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B }, - { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 }, - { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 } -}; - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -static const unsigned char des3_test_iv[8] = -{ - 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, -}; - -static const unsigned char des3_test_cbc_dec[3][8] = -{ - { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 }, - { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 }, - { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C } -}; - -static const unsigned char des3_test_cbc_enc[3][8] = -{ - { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 }, - { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D }, - { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 } -}; -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -/* - * Checkup routine - */ -int mbedtls_des_self_test( int verbose ) -{ - int i, j, u, v, ret = 0; - mbedtls_des_context ctx; - mbedtls_des3_context ctx3; - unsigned char buf[8]; -#if defined(MBEDTLS_CIPHER_MODE_CBC) - unsigned char prv[8]; - unsigned char iv[8]; -#endif - - mbedtls_des_init( &ctx ); - mbedtls_des3_init( &ctx3 ); - /* - * ECB mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - mbedtls_printf( " DES%c-ECB-%3d (%s): ", - ( u == 0 ) ? ' ' : '3', 56 + u * 56, - ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); - - memcpy( buf, des3_test_buf, 8 ); - - switch( i ) - { - case 0: - mbedtls_des_setkey_dec( &ctx, des3_test_keys ); - break; - - case 1: - mbedtls_des_setkey_enc( &ctx, des3_test_keys ); - break; - - case 2: - mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); - break; - - case 3: - mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); - break; - - case 4: - mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); - break; - - case 5: - mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); - break; - - default: - return( 1 ); - } - - for( j = 0; j < 10000; j++ ) - { - if( u == 0 ) - mbedtls_des_crypt_ecb( &ctx, buf, buf ); - else - mbedtls_des3_crypt_ecb( &ctx3, buf, buf ); - } - - if( ( v == MBEDTLS_DES_DECRYPT && - memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) || - ( v != MBEDTLS_DES_DECRYPT && - memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - /* - * CBC mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - mbedtls_printf( " DES%c-CBC-%3d (%s): ", - ( u == 0 ) ? ' ' : '3', 56 + u * 56, - ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); - - memcpy( iv, des3_test_iv, 8 ); - memcpy( prv, des3_test_iv, 8 ); - memcpy( buf, des3_test_buf, 8 ); - - switch( i ) - { - case 0: - mbedtls_des_setkey_dec( &ctx, des3_test_keys ); - break; - - case 1: - mbedtls_des_setkey_enc( &ctx, des3_test_keys ); - break; - - case 2: - mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); - break; - - case 3: - mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); - break; - - case 4: - mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); - break; - - case 5: - mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); - break; - - default: - return( 1 ); - } - - if( v == MBEDTLS_DES_DECRYPT ) - { - for( j = 0; j < 10000; j++ ) - { - if( u == 0 ) - mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); - else - mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); - } - } - else - { - for( j = 0; j < 10000; j++ ) - { - unsigned char tmp[8]; - - if( u == 0 ) - mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); - else - mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); - - memcpy( tmp, prv, 8 ); - memcpy( prv, buf, 8 ); - memcpy( buf, tmp, 8 ); - } - - memcpy( buf, prv, 8 ); - } - - if( ( v == MBEDTLS_DES_DECRYPT && - memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) || - ( v != MBEDTLS_DES_DECRYPT && - memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -exit: - mbedtls_des_free( &ctx ); - mbedtls_des3_free( &ctx3 ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_DES_C */ diff --git a/components/mbedtls/library/dhm.c b/components/mbedtls/library/dhm.c deleted file mode 100644 index bec52a11df..0000000000 --- a/components/mbedtls/library/dhm.c +++ /dev/null @@ -1,627 +0,0 @@ -/* - * Diffie-Hellman-Merkle key exchange - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The following sources were referenced in the design of this implementation - * of the Diffie-Hellman-Merkle algorithm: - * - * [1] Handbook of Applied Cryptography - 1997, Chapter 12 - * Menezes, van Oorschot and Vanstone - * - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_DHM_C) - -#include "mbedtls/dhm.h" - -#include - -#if defined(MBEDTLS_PEM_PARSE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_ASN1_PARSE_C) -#include "mbedtls/asn1.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_printf printf -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * helper to validate the mbedtls_mpi size and import it - */ -static int dhm_read_bignum( mbedtls_mpi *X, - unsigned char **p, - const unsigned char *end ) -{ - int ret, n; - - if( end - *p < 2 ) - return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); - - n = ( (*p)[0] << 8 ) | (*p)[1]; - (*p) += 2; - - if( (int)( end - *p ) < n ) - return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 ) - return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret ); - - (*p) += n; - - return( 0 ); -} - -/* - * Verify sanity of parameter with regards to P - * - * Parameter should be: 2 <= public_param <= P - 2 - * - * For more information on the attack, see: - * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf - * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 - */ -static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P ) -{ - mbedtls_mpi L, U; - int ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; - - mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) ); - - if( mbedtls_mpi_cmp_mpi( param, &L ) >= 0 && - mbedtls_mpi_cmp_mpi( param, &U ) <= 0 ) - { - ret = 0; - } - -cleanup: - mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U ); - return( ret ); -} - -void mbedtls_dhm_init( mbedtls_dhm_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_dhm_context ) ); -} - -/* - * Parse the ServerKeyExchange parameters - */ -int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, - unsigned char **p, - const unsigned char *end ) -{ - int ret; - - if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 || - ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 || - ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 ) - return( ret ); - - if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) - return( ret ); - - ctx->len = mbedtls_mpi_size( &ctx->P ); - - return( 0 ); -} - -/* - * Setup and write the ServerKeyExchange parameters - */ -int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, - unsigned char *output, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret, count = 0; - size_t n1, n2, n3; - unsigned char *p; - - if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) - return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); - - /* - * Generate X as large as possible ( < P ) - */ - do - { - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); - - while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); - - if( count++ > 10 ) - return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ); - } - while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); - - /* - * Calculate GX = G^X mod P - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, - &ctx->P , &ctx->RP ) ); - - if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) - return( ret ); - - /* - * export P, G, GX - */ -#define DHM_MPI_EXPORT(X,n) \ - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, p + 2, n ) ); \ - *p++ = (unsigned char)( n >> 8 ); \ - *p++ = (unsigned char)( n ); p += n; - - n1 = mbedtls_mpi_size( &ctx->P ); - n2 = mbedtls_mpi_size( &ctx->G ); - n3 = mbedtls_mpi_size( &ctx->GX ); - - p = output; - DHM_MPI_EXPORT( &ctx->P , n1 ); - DHM_MPI_EXPORT( &ctx->G , n2 ); - DHM_MPI_EXPORT( &ctx->GX, n3 ); - - *olen = p - output; - - ctx->len = n1; - -cleanup: - - if( ret != 0 ) - return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret ); - - return( 0 ); -} - -/* - * Import the peer's public value G^Y - */ -int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, - const unsigned char *input, size_t ilen ) -{ - int ret; - - if( ctx == NULL || ilen < 1 || ilen > ctx->len ) - return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 ) - return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret ); - - return( 0 ); -} - -/* - * Create own private value X and export G^X - */ -int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, - unsigned char *output, size_t olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret, count = 0; - - if( ctx == NULL || olen < 1 || olen > ctx->len ) - return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); - - if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) - return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); - - /* - * generate X and calculate GX = G^X mod P - */ - do - { - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); - - while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); - - if( count++ > 10 ) - return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ); - } - while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, - &ctx->P , &ctx->RP ) ); - - if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) - return( ret ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) ); - -cleanup: - - if( ret != 0 ) - return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret ); - - return( 0 ); -} - -/* - * Use the blinding method and optimisation suggested in section 10 of: - * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, - * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer - * Berlin Heidelberg, 1996. p. 104-113. - */ -static int dhm_update_blinding( mbedtls_dhm_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - int ret, count; - - /* - * Don't use any blinding the first time a particular X is used, - * but remember it to use blinding next time. - */ - if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) ); - - return( 0 ); - } - - /* - * Ok, we need blinding. Can we re-use existing values? - * If yes, just update them by squaring them. - */ - if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); - - return( 0 ); - } - - /* - * We need to generate blinding values from scratch - */ - - /* Vi = random( 2, P-1 ) */ - count = 0; - do - { - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vi, mbedtls_mpi_size( &ctx->P ), f_rng, p_rng ) ); - - while( mbedtls_mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi, 1 ) ); - - if( count++ > 10 ) - return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); - } - while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) <= 0 ); - - /* Vf = Vi^-X mod P */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) ); - -cleanup: - return( ret ); -} - -/* - * Derive and export the shared secret (G^Y)^X mod P - */ -int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, - unsigned char *output, size_t output_size, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_mpi GYb; - - if( ctx == NULL || output_size < ctx->len ) - return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); - - if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) - return( ret ); - - mbedtls_mpi_init( &GYb ); - - /* Blind peer's value */ - if( f_rng != NULL ) - { - MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) ); - } - else - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) ); - - /* Do modular exponentiation */ - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X, - &ctx->P, &ctx->RP ) ); - - /* Unblind secret value */ - if( f_rng != NULL ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) ); - } - - *olen = mbedtls_mpi_size( &ctx->K ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) ); - -cleanup: - mbedtls_mpi_free( &GYb ); - - if( ret != 0 ) - return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret ); - - return( 0 ); -} - -/* - * Free the components of a DHM key - */ -void mbedtls_dhm_free( mbedtls_dhm_context *ctx ) -{ - mbedtls_mpi_free( &ctx->pX); mbedtls_mpi_free( &ctx->Vf ); mbedtls_mpi_free( &ctx->Vi ); - mbedtls_mpi_free( &ctx->RP ); mbedtls_mpi_free( &ctx->K ); mbedtls_mpi_free( &ctx->GY ); - mbedtls_mpi_free( &ctx->GX ); mbedtls_mpi_free( &ctx->X ); mbedtls_mpi_free( &ctx->G ); - mbedtls_mpi_free( &ctx->P ); - - mbedtls_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); -} - -#if defined(MBEDTLS_ASN1_PARSE_C) -/* - * Parse DHM parameters - */ -int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, - size_t dhminlen ) -{ - int ret; - size_t len; - unsigned char *p, *end; -#if defined(MBEDTLS_PEM_PARSE_C) - mbedtls_pem_context pem; - - mbedtls_pem_init( &pem ); - - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN DH PARAMETERS-----", - "-----END DH PARAMETERS-----", - dhmin, NULL, 0, &dhminlen ); - - if( ret == 0 ) - { - /* - * Was PEM encoded - */ - dhminlen = pem.buflen; - } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - goto exit; - - p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin; -#else - p = (unsigned char *) dhmin; -#endif /* MBEDTLS_PEM_PARSE_C */ - end = p + dhminlen; - - /* - * DHParams ::= SEQUENCE { - * prime INTEGER, -- P - * generator INTEGER, -- g - * privateValueLength INTEGER OPTIONAL - * } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; - goto exit; - } - - end = p + len; - - if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 ) - { - ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; - goto exit; - } - - if( p != end ) - { - /* This might be the optional privateValueLength. - * If so, we can cleanly discard it */ - mbedtls_mpi rec; - mbedtls_mpi_init( &rec ); - ret = mbedtls_asn1_get_mpi( &p, end, &rec ); - mbedtls_mpi_free( &rec ); - if ( ret != 0 ) - { - ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; - goto exit; - } - if ( p != end ) - { - ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; - goto exit; - } - } - - ret = 0; - - dhm->len = mbedtls_mpi_size( &dhm->P ); - -exit: -#if defined(MBEDTLS_PEM_PARSE_C) - mbedtls_pem_free( &pem ); -#endif - if( ret != 0 ) - mbedtls_dhm_free( dhm ); - - return( ret ); -} - -#if defined(MBEDTLS_FS_IO) -/* - * Load all data from a file into a given buffer. - * - * The file is expected to contain either PEM or DER encoded data. - * A terminating null byte is always appended. It is included in the announced - * length only if the data looks like it is PEM encoded. - */ -static int load_file( const char *path, unsigned char **buf, size_t *n ) -{ - FILE *f; - long size; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); - - fseek( f, 0, SEEK_END ); - if( ( size = ftell( f ) ) == -1 ) - { - fclose( f ); - return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); - } - fseek( f, 0, SEEK_SET ); - - *n = (size_t) size; - - if( *n + 1 == 0 || - ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) - { - fclose( f ); - return( MBEDTLS_ERR_DHM_ALLOC_FAILED ); - } - - if( fread( *buf, 1, *n, f ) != *n ) - { - fclose( f ); - mbedtls_free( *buf ); - return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); - } - - fclose( f ); - - (*buf)[*n] = '\0'; - - if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) - ++*n; - - return( 0 ); -} - -/* - * Load and parse DHM parameters - */ -int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ) -{ - int ret; - size_t n; - unsigned char *buf; - - if( ( ret = load_file( path, &buf, &n ) ) != 0 ) - return( ret ); - - ret = mbedtls_dhm_parse_dhm( dhm, buf, n ); - - mbedtls_zeroize( buf, n ); - mbedtls_free( buf ); - - return( ret ); -} -#endif /* MBEDTLS_FS_IO */ -#endif /* MBEDTLS_ASN1_PARSE_C */ - -#if defined(MBEDTLS_SELF_TEST) - -static const char mbedtls_test_dhm_params[] = -"-----BEGIN DH PARAMETERS-----\r\n" -"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n" -"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n" -"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n" -"-----END DH PARAMETERS-----\r\n"; - -static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params ); - -/* - * Checkup routine - */ -int mbedtls_dhm_self_test( int verbose ) -{ - int ret; - mbedtls_dhm_context dhm; - - mbedtls_dhm_init( &dhm ); - - if( verbose != 0 ) - mbedtls_printf( " DHM parameter load: " ); - - if( ( ret = mbedtls_dhm_parse_dhm( &dhm, - (const unsigned char *) mbedtls_test_dhm_params, - mbedtls_test_dhm_params_len ) ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n\n" ); - -exit: - mbedtls_dhm_free( &dhm ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_DHM_C */ diff --git a/components/mbedtls/library/ecdh.c b/components/mbedtls/library/ecdh.c deleted file mode 100644 index c0a8147312..0000000000 --- a/components/mbedtls/library/ecdh.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Elliptic curve Diffie-Hellman - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -/* - * References: - * - * SEC1 http://www.secg.org/index.php?action=secg,docs_secg - * RFC 4492 - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_ECDH_C) - -#include "mbedtls/ecdh.h" - -#include - -/* - * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair - */ -int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng ); -} - -/* - * Compute shared secret (SEC1 3.3.1) - */ -int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, - const mbedtls_ecp_point *Q, const mbedtls_mpi *d, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_ecp_point P; - - mbedtls_ecp_point_init( &P ); - - /* - * Make sure Q is a valid pubkey before using it - */ - MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); - - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &P, d, Q, f_rng, p_rng ) ); - - if( mbedtls_ecp_is_zero( &P ) ) - { - ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - goto cleanup; - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) ); - -cleanup: - mbedtls_ecp_point_free( &P ); - - return( ret ); -} - -/* - * Initialize context - */ -void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); -} - -/* - * Free context - */ -void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_ecp_group_free( &ctx->grp ); - mbedtls_ecp_point_free( &ctx->Q ); - mbedtls_ecp_point_free( &ctx->Qp ); - mbedtls_ecp_point_free( &ctx->Vi ); - mbedtls_ecp_point_free( &ctx->Vf ); - mbedtls_mpi_free( &ctx->d ); - mbedtls_mpi_free( &ctx->z ); - mbedtls_mpi_free( &ctx->_d ); -} - -/* - * Setup and write the ServerKeyExhange parameters (RFC 4492) - * struct { - * ECParameters curve_params; - * ECPoint public; - * } ServerECDHParams; - */ -int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - size_t grp_len, pt_len; - - if( ctx == NULL || ctx->grp.pbits == 0 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) - != 0 ) - return( ret ); - - if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) ) - != 0 ) - return( ret ); - - buf += grp_len; - blen -= grp_len; - - if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, - &pt_len, buf, blen ) ) != 0 ) - return( ret ); - - *olen = grp_len + pt_len; - return( 0 ); -} - -/* - * Read the ServerKeyExhange parameters (RFC 4492) - * struct { - * ECParameters curve_params; - * ECPoint public; - * } ServerECDHParams; - */ -int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, - const unsigned char **buf, const unsigned char *end ) -{ - int ret; - - if( ( ret = mbedtls_ecp_tls_read_group( &ctx->grp, buf, end - *buf ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, end - *buf ) ) - != 0 ) - return( ret ); - - return( 0 ); -} - -/* - * Get parameters from a keypair - */ -int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, - mbedtls_ecdh_side side ) -{ - int ret; - - if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ) - return( ret ); - - /* If it's not our key, just import the public part as Qp */ - if( side == MBEDTLS_ECDH_THEIRS ) - return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) ); - - /* Our key: import public (as Q) and private parts */ - if( side != MBEDTLS_ECDH_OURS ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 || - ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -/* - * Setup and export the client public value - */ -int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - - if( ctx == NULL || ctx->grp.pbits == 0 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) - != 0 ) - return( ret ); - - return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, - olen, buf, blen ); -} - -/* - * Parse and import the client's public value - */ -int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, - const unsigned char *buf, size_t blen ) -{ - int ret; - const unsigned char *p = buf; - - if( ctx == NULL ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, blen ) ) != 0 ) - return( ret ); - - if( (size_t)( p - buf ) != blen ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - return( 0 ); -} - -/* - * Derive and export the shared secret - */ -int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, - unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - - if( ctx == NULL ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, - f_rng, p_rng ) ) != 0 ) - { - return( ret ); - } - - if( mbedtls_mpi_size( &ctx->z ) > blen ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 ); - return mbedtls_mpi_write_binary( &ctx->z, buf, *olen ); -} - -#endif /* MBEDTLS_ECDH_C */ diff --git a/components/mbedtls/library/ecdsa.c b/components/mbedtls/library/ecdsa.c deleted file mode 100644 index 4156f3c3c4..0000000000 --- a/components/mbedtls/library/ecdsa.c +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Elliptic curve DSA - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -/* - * References: - * - * SEC1 http://www.secg.org/index.php?action=secg,docs_secg - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_ECDSA_C) - -#include "mbedtls/ecdsa.h" -#include "mbedtls/asn1write.h" - -#include - -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) -#include "mbedtls/hmac_drbg.h" -#endif - -/* - * Derive a suitable integer for group grp from a buffer of length len - * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 - */ -static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x, - const unsigned char *buf, size_t blen ) -{ - int ret; - size_t n_size = ( grp->nbits + 7 ) / 8; - size_t use_size = blen > n_size ? n_size : blen; - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) ); - if( use_size * 8 > grp->nbits ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) ); - - /* While at it, reduce modulo N */ - if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) ); - -cleanup: - return( ret ); -} - -/* - * Compute ECDSA signature of a hashed message (SEC1 4.1.3) - * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) - */ -int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - int ret, key_tries, sign_tries, blind_tries; - mbedtls_ecp_point R; - mbedtls_mpi k, e, t; - - /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ - if( grp->N.p == NULL ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - mbedtls_ecp_point_init( &R ); - mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); - - sign_tries = 0; - do - { - /* - * Steps 1-3: generate a suitable ephemeral keypair - * and set r = xR mod n - */ - key_tries = 0; - do - { - MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) ); - - if( key_tries++ > 10 ) - { - ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; - goto cleanup; - } - } - while( mbedtls_mpi_cmp_int( r, 0 ) == 0 ); - - /* - * Step 5: derive MPI from hashed message - */ - MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); - - /* - * Generate a random value to blind inv_mod in next step, - * avoiding a potential timing leak. - */ - blind_tries = 0; - do - { - size_t n_size = ( grp->nbits + 7 ) / 8; - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) ); - - /* See mbedtls_ecp_gen_keypair() */ - if( ++blind_tries > 30 ) - return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); - } - while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 || - mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 ); - - /* - * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); - - if( sign_tries++ > 10 ) - { - ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; - goto cleanup; - } - } - while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); - -cleanup: - mbedtls_ecp_point_free( &R ); - mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); - - return( ret ); -} - -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) -/* - * Deterministic signature wrapper - */ -int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, - const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - mbedtls_md_type_t md_alg ) -{ - int ret; - mbedtls_hmac_drbg_context rng_ctx; - unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; - size_t grp_len = ( grp->nbits + 7 ) / 8; - const mbedtls_md_info_t *md_info; - mbedtls_mpi h; - - if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &h ); - mbedtls_hmac_drbg_init( &rng_ctx ); - - /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); - MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); - mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len ); - - ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, - mbedtls_hmac_drbg_random, &rng_ctx ); - -cleanup: - mbedtls_hmac_drbg_free( &rng_ctx ); - mbedtls_mpi_free( &h ); - - return( ret ); -} -#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ - -/* - * Verify ECDSA signature of hashed message (SEC1 4.1.4) - * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) - */ -int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s) -{ - int ret; - mbedtls_mpi e, s_inv, u1, u2; - mbedtls_ecp_point R; - - mbedtls_ecp_point_init( &R ); - mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); - - /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ - if( grp->N.p == NULL ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - /* - * Step 1: make sure r and s are in range 1..n-1 - */ - if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 || - mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 ) - { - ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; - goto cleanup; - } - - /* - * Additional precaution: make sure Q is valid - */ - MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); - - /* - * Step 3: derive MPI from hashed message - */ - MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); - - /* - * Step 4: u1 = e / s mod n, u2 = r / s mod n - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) ); - - /* - * Step 5: R = u1 G + u2 Q - * - * Since we're not using any secret data, no need to pass a RNG to - * mbedtls_ecp_mul() for countermesures. - */ - MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) ); - - if( mbedtls_ecp_is_zero( &R ) ) - { - ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; - goto cleanup; - } - - /* - * Step 6: convert xR to an integer (no-op) - * Step 7: reduce xR mod n (gives v) - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) ); - - /* - * Step 8: check if v (that is, R.X) is equal to r - */ - if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 ) - { - ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; - goto cleanup; - } - -cleanup: - mbedtls_ecp_point_free( &R ); - mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); - - return( ret ); -} - -/* - * Convert a signature (given by context) to ASN.1 - */ -static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, - unsigned char *sig, size_t *slen ) -{ - int ret; - unsigned char buf[MBEDTLS_ECDSA_MAX_LEN]; - unsigned char *p = buf + sizeof( buf ); - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); - - memcpy( sig, p, len ); - *slen = len; - - return( 0 ); -} - -/* - * Compute and write signature - */ -int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t *slen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_mpi r, s; - - mbedtls_mpi_init( &r ); - mbedtls_mpi_init( &s ); - -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) - (void) f_rng; - (void) p_rng; - - MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d, - hash, hlen, md_alg ) ); -#else - (void) md_alg; - - MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, - hash, hlen, f_rng, p_rng ) ); -#endif - - MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); - -cleanup: - mbedtls_mpi_free( &r ); - mbedtls_mpi_free( &s ); - - return( ret ); -} - -#if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \ - defined(MBEDTLS_ECDSA_DETERMINISTIC) -int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, - const unsigned char *hash, size_t hlen, - unsigned char *sig, size_t *slen, - mbedtls_md_type_t md_alg ) -{ - return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen, - NULL, NULL ) ); -} -#endif - -/* - * Read and check signature - */ -int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, - const unsigned char *hash, size_t hlen, - const unsigned char *sig, size_t slen ) -{ - int ret; - unsigned char *p = (unsigned char *) sig; - const unsigned char *end = sig + slen; - size_t len; - mbedtls_mpi r, s; - - mbedtls_mpi_init( &r ); - mbedtls_mpi_init( &s ); - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - goto cleanup; - } - - if( p + len != end ) - { - ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; - goto cleanup; - } - - if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 ) - { - ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - goto cleanup; - } - - if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, - &ctx->Q, &r, &s ) ) != 0 ) - goto cleanup; - - if( p != end ) - ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; - -cleanup: - mbedtls_mpi_free( &r ); - mbedtls_mpi_free( &s ); - - return( ret ); -} - -/* - * Generate key pair - */ -int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - return( mbedtls_ecp_group_load( &ctx->grp, gid ) || - mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ); -} - -/* - * Set context from an mbedtls_ecp_keypair - */ -int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ) -{ - int ret; - - if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 || - ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 || - ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ) - { - mbedtls_ecdsa_free( ctx ); - } - - return( ret ); -} - -/* - * Initialize context - */ -void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ) -{ - mbedtls_ecp_keypair_init( ctx ); -} - -/* - * Free context - */ -void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) -{ - mbedtls_ecp_keypair_free( ctx ); -} - -#endif /* MBEDTLS_ECDSA_C */ diff --git a/components/mbedtls/library/ecjpake.c b/components/mbedtls/library/ecjpake.c deleted file mode 100644 index 1fa1c2d801..0000000000 --- a/components/mbedtls/library/ecjpake.c +++ /dev/null @@ -1,1103 +0,0 @@ -/* - * Elliptic curve J-PAKE - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -/* - * References in the code are to the Thread v1.0 Specification, - * available to members of the Thread Group http://threadgroup.org/ - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_ECJPAKE_C) - -#include "mbedtls/ecjpake.h" - -#include - -/* - * Convert a mbedtls_ecjpake_role to identifier string - */ -static const char * const ecjpake_id[] = { - "client", - "server" -}; - -#define ID_MINE ( ecjpake_id[ ctx->role ] ) -#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] ) - -/* - * Initialize context - */ -void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ) -{ - if( ctx == NULL ) - return; - - ctx->md_info = NULL; - mbedtls_ecp_group_init( &ctx->grp ); - ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; - - mbedtls_ecp_point_init( &ctx->Xm1 ); - mbedtls_ecp_point_init( &ctx->Xm2 ); - mbedtls_ecp_point_init( &ctx->Xp1 ); - mbedtls_ecp_point_init( &ctx->Xp2 ); - mbedtls_ecp_point_init( &ctx->Xp ); - - mbedtls_mpi_init( &ctx->xm1 ); - mbedtls_mpi_init( &ctx->xm2 ); - mbedtls_mpi_init( &ctx->s ); -} - -/* - * Free context - */ -void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ) -{ - if( ctx == NULL ) - return; - - ctx->md_info = NULL; - mbedtls_ecp_group_free( &ctx->grp ); - - mbedtls_ecp_point_free( &ctx->Xm1 ); - mbedtls_ecp_point_free( &ctx->Xm2 ); - mbedtls_ecp_point_free( &ctx->Xp1 ); - mbedtls_ecp_point_free( &ctx->Xp2 ); - mbedtls_ecp_point_free( &ctx->Xp ); - - mbedtls_mpi_free( &ctx->xm1 ); - mbedtls_mpi_free( &ctx->xm2 ); - mbedtls_mpi_free( &ctx->s ); -} - -/* - * Setup context - */ -int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, - mbedtls_ecjpake_role role, - mbedtls_md_type_t hash, - mbedtls_ecp_group_id curve, - const unsigned char *secret, - size_t len ) -{ - int ret; - - ctx->role = role; - - if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL ) - return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE ); - - MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) ); - -cleanup: - if( ret != 0 ) - mbedtls_ecjpake_free( ctx ); - - return( ret ); -} - -/* - * Check if context is ready for use - */ -int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ) -{ - if( ctx->md_info == NULL || - ctx->grp.id == MBEDTLS_ECP_DP_NONE || - ctx->s.p == NULL ) - { - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - } - - return( 0 ); -} - -/* - * Write a point plus its length to a buffer - */ -static int ecjpake_write_len_point( unsigned char **p, - const unsigned char *end, - const mbedtls_ecp_group *grp, - const int pf, - const mbedtls_ecp_point *P ) -{ - int ret; - size_t len; - - /* Need at least 4 for length plus 1 for point */ - if( end < *p || end - *p < 5 ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - ret = mbedtls_ecp_point_write_binary( grp, P, pf, - &len, *p + 4, end - ( *p + 4 ) ); - if( ret != 0 ) - return( ret ); - - (*p)[0] = (unsigned char)( ( len >> 24 ) & 0xFF ); - (*p)[1] = (unsigned char)( ( len >> 16 ) & 0xFF ); - (*p)[2] = (unsigned char)( ( len >> 8 ) & 0xFF ); - (*p)[3] = (unsigned char)( ( len ) & 0xFF ); - - *p += 4 + len; - - return( 0 ); -} - -/* - * Size of the temporary buffer for ecjpake_hash: - * 3 EC points plus their length, plus ID and its length (4 + 6 bytes) - */ -#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 ) - -/* - * Compute hash for ZKP (7.4.2.2.2.1) - */ -static int ecjpake_hash( const mbedtls_md_info_t *md_info, - const mbedtls_ecp_group *grp, - const int pf, - const mbedtls_ecp_point *G, - const mbedtls_ecp_point *V, - const mbedtls_ecp_point *X, - const char *id, - mbedtls_mpi *h ) -{ - int ret; - unsigned char buf[ECJPAKE_HASH_BUF_LEN]; - unsigned char *p = buf; - const unsigned char *end = buf + sizeof( buf ); - const size_t id_len = strlen( id ); - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; - - /* Write things to temporary buffer */ - MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) ); - MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) ); - MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) ); - - if( end - p < 4 ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - *p++ = (unsigned char)( ( id_len >> 24 ) & 0xFF ); - *p++ = (unsigned char)( ( id_len >> 16 ) & 0xFF ); - *p++ = (unsigned char)( ( id_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( id_len ) & 0xFF ); - - if( end < p || (size_t)( end - p ) < id_len ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - memcpy( p, id, id_len ); - p += id_len; - - /* Compute hash */ - mbedtls_md( md_info, buf, p - buf, hash ); - - /* Turn it into an integer mod n */ - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash, - mbedtls_md_get_size( md_info ) ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) ); - -cleanup: - return( ret ); -} - -/* - * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3) - */ -static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info, - const mbedtls_ecp_group *grp, - const int pf, - const mbedtls_ecp_point *G, - const mbedtls_ecp_point *X, - const char *id, - const unsigned char **p, - const unsigned char *end ) -{ - int ret; - mbedtls_ecp_point V, VV; - mbedtls_mpi r, h; - size_t r_len; - - mbedtls_ecp_point_init( &V ); - mbedtls_ecp_point_init( &VV ); - mbedtls_mpi_init( &r ); - mbedtls_mpi_init( &h ); - - /* - * struct { - * ECPoint V; - * opaque r<1..2^8-1>; - * } ECSchnorrZKP; - */ - if( end < *p ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) ); - - if( end < *p || (size_t)( end - *p ) < 1 ) - { - ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - goto cleanup; - } - - r_len = *(*p)++; - - if( end < *p || (size_t)( end - *p ) < r_len ) - { - ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - goto cleanup; - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) ); - *p += r_len; - - /* - * Verification - */ - MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp, - &VV, &h, X, &r, G ) ); - - if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 ) - { - ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; - goto cleanup; - } - -cleanup: - mbedtls_ecp_point_free( &V ); - mbedtls_ecp_point_free( &VV ); - mbedtls_mpi_free( &r ); - mbedtls_mpi_free( &h ); - - return( ret ); -} - -/* - * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2) - */ -static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info, - const mbedtls_ecp_group *grp, - const int pf, - const mbedtls_ecp_point *G, - const mbedtls_mpi *x, - const mbedtls_ecp_point *X, - const char *id, - unsigned char **p, - const unsigned char *end, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_ecp_point V; - mbedtls_mpi v; - mbedtls_mpi h; /* later recycled to hold r */ - size_t len; - - if( end < *p ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - mbedtls_ecp_point_init( &V ); - mbedtls_mpi_init( &v ); - mbedtls_mpi_init( &h ); - - /* Compute signature */ - MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, - G, &v, &V, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */ - - /* Write it out */ - MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V, - pf, &len, *p, end - *p ) ); - *p += len; - - len = mbedtls_mpi_size( &h ); /* actually r */ - if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 ) - { - ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; - goto cleanup; - } - - *(*p)++ = (unsigned char)( len & 0xFF ); - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */ - *p += len; - -cleanup: - mbedtls_ecp_point_free( &V ); - mbedtls_mpi_free( &v ); - mbedtls_mpi_free( &h ); - - return( ret ); -} - -/* - * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof - * Output: verified public key X - */ -static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info, - const mbedtls_ecp_group *grp, - const int pf, - const mbedtls_ecp_point *G, - mbedtls_ecp_point *X, - const char *id, - const unsigned char **p, - const unsigned char *end ) -{ - int ret; - - if( end < *p ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - /* - * struct { - * ECPoint X; - * ECSchnorrZKP zkp; - * } ECJPAKEKeyKP; - */ - MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) ); - if( mbedtls_ecp_is_zero( X ) ) - { - ret = MBEDTLS_ERR_ECP_INVALID_KEY; - goto cleanup; - } - - MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) ); - -cleanup: - return( ret ); -} - -/* - * Generate an ECJPAKEKeyKP - * Output: the serialized structure, plus private/public key pair - */ -static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info, - const mbedtls_ecp_group *grp, - const int pf, - const mbedtls_ecp_point *G, - mbedtls_mpi *x, - mbedtls_ecp_point *X, - const char *id, - unsigned char **p, - const unsigned char *end, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - size_t len; - - if( end < *p ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - /* Generate key (7.4.2.3.1) and write it out */ - MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X, - f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X, - pf, &len, *p, end - *p ) ); - *p += len; - - /* Generate and write proof */ - MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id, - p, end, f_rng, p_rng ) ); - -cleanup: - return( ret ); -} - -/* - * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs - * Ouputs: verified peer public keys Xa, Xb - */ -static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info, - const mbedtls_ecp_group *grp, - const int pf, - const mbedtls_ecp_point *G, - mbedtls_ecp_point *Xa, - mbedtls_ecp_point *Xb, - const char *id, - const unsigned char *buf, - size_t len ) -{ - int ret; - const unsigned char *p = buf; - const unsigned char *end = buf + len; - - /* - * struct { - * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2]; - * } ECJPAKEKeyKPPairList; - */ - MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) ); - MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) ); - - if( p != end ) - ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - -cleanup: - return( ret ); -} - -/* - * Generate a ECJPAKEKeyKPPairList - * Outputs: the serialized structure, plus two private/public key pairs - */ -static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info, - const mbedtls_ecp_group *grp, - const int pf, - const mbedtls_ecp_point *G, - mbedtls_mpi *xm1, - mbedtls_ecp_point *Xa, - mbedtls_mpi *xm2, - mbedtls_ecp_point *Xb, - const char *id, - unsigned char *buf, - size_t len, - size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - unsigned char *p = buf; - const unsigned char *end = buf + len; - - MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id, - &p, end, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id, - &p, end, f_rng, p_rng ) ); - - *olen = p - buf; - -cleanup: - return( ret ); -} - -/* - * Read and process the first round message - */ -int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, - const unsigned char *buf, - size_t len ) -{ - return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format, - &ctx->grp.G, - &ctx->Xp1, &ctx->Xp2, ID_PEER, - buf, len ) ); -} - -/* - * Generate and write the first round message - */ -int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, - unsigned char *buf, size_t len, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format, - &ctx->grp.G, - &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2, - ID_MINE, buf, len, olen, f_rng, p_rng ) ); -} - -/* - * Compute the sum of three points R = A + B + C - */ -static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point *A, - const mbedtls_ecp_point *B, - const mbedtls_ecp_point *C ) -{ - int ret; - mbedtls_mpi one; - - mbedtls_mpi_init( &one ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) ); - -cleanup: - mbedtls_mpi_free( &one ); - - return( ret ); -} - -/* - * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6) - */ -int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, - const unsigned char *buf, - size_t len ) -{ - int ret; - const unsigned char *p = buf; - const unsigned char *end = buf + len; - mbedtls_ecp_group grp; - mbedtls_ecp_point G; /* C: GB, S: GA */ - - mbedtls_ecp_group_init( &grp ); - mbedtls_ecp_point_init( &G ); - - /* - * Server: GA = X3 + X4 + X1 (7.4.2.6.1) - * Client: GB = X1 + X2 + X3 (7.4.2.5.1) - * Unified: G = Xm1 + Xm2 + Xp1 - * We need that before parsing in order to check Xp as we read it - */ - MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, - &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) ); - - /* - * struct { - * ECParameters curve_params; // only client reading server msg - * ECJPAKEKeyKP ecjpake_key_kp; - * } Client/ServerECJPAKEParams; - */ - if( ctx->role == MBEDTLS_ECJPAKE_CLIENT ) - { - MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) ); - if( grp.id != ctx->grp.id ) - { - ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - goto cleanup; - } - } - - MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp, - ctx->point_format, - &G, &ctx->Xp, ID_PEER, &p, end ) ); - - if( p != end ) - { - ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - goto cleanup; - } - -cleanup: - mbedtls_ecp_group_free( &grp ); - mbedtls_ecp_point_free( &G ); - - return( ret ); -} - -/* - * Compute R = +/- X * S mod N, taking care not to leak S - */ -static int ecjpake_mul_secret( mbedtls_mpi *R, int sign, - const mbedtls_mpi *X, - const mbedtls_mpi *S, - const mbedtls_mpi *N, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_mpi b; /* Blinding value, then s + N * blinding */ - - mbedtls_mpi_init( &b ); - - /* b = s + rnd-128-bit * N */ - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) ); - - /* R = sign * X * b mod N */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) ); - R->s *= sign; - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) ); - -cleanup: - mbedtls_mpi_free( &b ); - - return( ret ); -} - -/* - * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6) - */ -int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, - unsigned char *buf, size_t len, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_ecp_point G; /* C: GA, S: GB */ - mbedtls_ecp_point Xm; /* C: Xc, S: Xs */ - mbedtls_mpi xm; /* C: xc, S: xs */ - unsigned char *p = buf; - const unsigned char *end = buf + len; - size_t ec_len; - - mbedtls_ecp_point_init( &G ); - mbedtls_ecp_point_init( &Xm ); - mbedtls_mpi_init( &xm ); - - /* - * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1) - * - * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA - * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB - * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G - */ - MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, - &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) ); - MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s, - &ctx->grp.N, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) ); - - /* - * Now write things out - * - * struct { - * ECParameters curve_params; // only server writing its message - * ECJPAKEKeyKP ecjpake_key_kp; - * } Client/ServerECJPAKEParams; - */ - if( ctx->role == MBEDTLS_ECJPAKE_SERVER ) - { - if( end < p ) - { - ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; - goto cleanup; - } - MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len, - p, end - p ) ); - p += ec_len; - } - - if( end < p ) - { - ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; - goto cleanup; - } - MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm, - ctx->point_format, &ec_len, p, end - p ) ); - p += ec_len; - - MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp, - ctx->point_format, - &G, &xm, &Xm, ID_MINE, - &p, end, f_rng, p_rng ) ); - - *olen = p - buf; - -cleanup: - mbedtls_ecp_point_free( &G ); - mbedtls_ecp_point_free( &Xm ); - mbedtls_mpi_free( &xm ); - - return( ret ); -} - -/* - * Derive PMS (7.4.2.7 / 7.4.2.8) - */ -int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, - unsigned char *buf, size_t len, size_t *olen, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_ecp_point K; - mbedtls_mpi m_xm2_s, one; - unsigned char kx[MBEDTLS_ECP_MAX_BYTES]; - size_t x_bytes; - - *olen = mbedtls_md_get_size( ctx->md_info ); - if( len < *olen ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - mbedtls_ecp_point_init( &K ); - mbedtls_mpi_init( &m_xm2_s ); - mbedtls_mpi_init( &one ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); - - /* - * Client: K = ( Xs - X4 * x2 * s ) * x2 - * Server: K = ( Xc - X2 * x4 * s ) * x4 - * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2 - */ - MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s, - &ctx->grp.N, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K, - &one, &ctx->Xp, - &m_xm2_s, &ctx->Xp2 ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K, - f_rng, p_rng ) ); - - /* PMS = SHA-256( K.X ) */ - x_bytes = ( ctx->grp.pbits + 7 ) / 8; - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) ); - MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) ); - -cleanup: - mbedtls_ecp_point_free( &K ); - mbedtls_mpi_free( &m_xm2_s ); - mbedtls_mpi_free( &one ); - - return( ret ); -} - -#undef ID_MINE -#undef ID_PEER - - -#if defined(MBEDTLS_SELF_TEST) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif - -#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ - !defined(MBEDTLS_SHA256_C) -int mbedtls_ecjpake_self_test( int verbose ) -{ - (void) verbose; - return( 0 ); -} -#else - -static const unsigned char ecjpake_test_password[] = { - 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74, - 0x65, 0x73, 0x74 -}; - -static const unsigned char ecjpake_test_x1[] = { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, - 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21 -}; - -static const unsigned char ecjpake_test_x2[] = { - 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, - 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 -}; - -static const unsigned char ecjpake_test_x3[] = { - 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, - 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 -}; - -static const unsigned char ecjpake_test_x4[] = { - 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, - 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, - 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1 -}; - -static const unsigned char ecjpake_test_cli_one[] = { - 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19, - 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44, - 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad, - 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62, - 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9, - 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d, - 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e, - 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e, - 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73, - 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22, - 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce, - 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00, - 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b, - 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e, - 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62, - 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5, - 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb, - 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35, - 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0, - 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb, - 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47, - 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39, - 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97, - 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40, - 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d, - 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa, - 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d, - 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0 -}; - -static const unsigned char ecjpake_test_srv_one[] = { - 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, - 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, - 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, - 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, - 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, - 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d, - 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64, - 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36, - 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2, - 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec, - 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16, - 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96, - 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3, - 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19, - 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f, - 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8, - 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7, - 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea, - 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5, - 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6, - 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31, - 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d, - 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8, - 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee, - 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84, - 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f, - 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80, - 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12 -}; - -static const unsigned char ecjpake_test_srv_two[] = { - 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23, - 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c, - 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f, - 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca, - 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26, - 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55, - 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38, - 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6, - 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9, - 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4, - 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2, - 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8, - 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd, - 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c -}; - -static const unsigned char ecjpake_test_cli_two[] = { - 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46, - 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb, - 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72, - 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce, - 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98, - 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31, - 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15, - 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36, - 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8, - 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45, - 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d, - 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58, - 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82, - 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c -}; - -static const unsigned char ecjpake_test_pms[] = { - 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7, - 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9, - 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51 -}; - -/* Load my private keys and generate the correponding public keys */ -static int ecjpake_test_load( mbedtls_ecjpake_context *ctx, - const unsigned char *xm1, size_t len1, - const unsigned char *xm2, size_t len2 ) -{ - int ret; - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1, - &ctx->grp.G, NULL, NULL ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2, - &ctx->grp.G, NULL, NULL ) ); - -cleanup: - return( ret ); -} - -/* For tests we don't need a secure RNG; - * use the LGC from Numerical Recipes for simplicity */ -static int ecjpake_lgc( void *p, unsigned char *out, size_t len ) -{ - static uint32_t x = 42; - (void) p; - - while( len > 0 ) - { - size_t use_len = len > 4 ? 4 : len; - x = 1664525 * x + 1013904223; - memcpy( out, &x, use_len ); - out += use_len; - len -= use_len; - } - - return( 0 ); -} - -#define TEST_ASSERT( x ) \ - do { \ - if( x ) \ - ret = 0; \ - else \ - { \ - ret = 1; \ - goto cleanup; \ - } \ - } while( 0 ) - -/* - * Checkup routine - */ -int mbedtls_ecjpake_self_test( int verbose ) -{ - int ret; - mbedtls_ecjpake_context cli; - mbedtls_ecjpake_context srv; - unsigned char buf[512], pms[32]; - size_t len, pmslen; - - mbedtls_ecjpake_init( &cli ); - mbedtls_ecjpake_init( &srv ); - - if( verbose != 0 ) - mbedtls_printf( " ECJPAKE test #0 (setup): " ); - - TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT, - MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, - ecjpake_test_password, - sizeof( ecjpake_test_password ) ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER, - MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, - ecjpake_test_password, - sizeof( ecjpake_test_password ) ) == 0 ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " ECJPAKE test #1 (random handshake): " ); - - TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli, - buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv, - buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv, - buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, - pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli, - buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, - buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); - - TEST_ASSERT( len == pmslen ); - TEST_ASSERT( memcmp( buf, pms, len ) == 0 ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " ECJPAKE test #2 (reference handshake): " ); - - /* Simulate generation of round one */ - MBEDTLS_MPI_CHK( ecjpake_test_load( &cli, - ecjpake_test_x1, sizeof( ecjpake_test_x1 ), - ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) ); - - MBEDTLS_MPI_CHK( ecjpake_test_load( &srv, - ecjpake_test_x3, sizeof( ecjpake_test_x3 ), - ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) ); - - /* Read round one */ - TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, - ecjpake_test_cli_one, - sizeof( ecjpake_test_cli_one ) ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, - ecjpake_test_srv_one, - sizeof( ecjpake_test_srv_one ) ) == 0 ); - - /* Skip generation of round two, read round two */ - TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, - ecjpake_test_srv_two, - sizeof( ecjpake_test_srv_two ) ) == 0 ); - - TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, - ecjpake_test_cli_two, - sizeof( ecjpake_test_cli_two ) ) == 0 ); - - /* Server derives PMS */ - TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, - buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); - - TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); - TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); - - memset( buf, 0, len ); /* Avoid interferences with next step */ - - /* Client derives PMS */ - TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, - buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); - - TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); - TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - -cleanup: - mbedtls_ecjpake_free( &cli ); - mbedtls_ecjpake_free( &srv ); - - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( ret ); -} - -#undef TEST_ASSERT - -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */ - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_ECJPAKE_C */ diff --git a/components/mbedtls/library/ecp.c b/components/mbedtls/library/ecp.c deleted file mode 100644 index a9705388cb..0000000000 --- a/components/mbedtls/library/ecp.c +++ /dev/null @@ -1,2197 +0,0 @@ -/* - * Elliptic curves over GF(p): generic functions - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -/* - * References: - * - * SEC1 http://www.secg.org/index.php?action=secg,docs_secg - * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone - * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf - * RFC 4492 for the related TLS structures and constants - * - * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf - * - * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis - * for elliptic curve cryptosystems. In : Cryptographic Hardware and - * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. - * - * - * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to - * render ECC resistant against Side Channel Attacks. IACR Cryptology - * ePrint Archive, 2004, vol. 2004, p. 342. - * - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_ECP_C) - -#include "mbedtls/ecp.h" -#include "mbedtls/threading.h" - -#include - -#if !defined(MBEDTLS_ECP_ALT) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_printf printf -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include "mbedtls/ecp_internal.h" - -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -#if defined(MBEDTLS_SELF_TEST) -/* - * Counts of point addition and doubling, and field multiplications. - * Used to test resistance of point multiplication to simple timing attacks. - */ -static unsigned long add_count, dbl_count, mul_count; -#endif - -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -#define ECP_SHORTWEIERSTRASS -#endif - -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) -#define ECP_MONTGOMERY -#endif - -/* - * Curve types: internal for now, might be exposed later - */ -typedef enum -{ - ECP_TYPE_NONE = 0, - ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */ - ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */ -} ecp_curve_type; - -/* - * List of supported curves: - * - internal ID - * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2) - * - size in bits - * - readable name - * - * Curves are listed in order: largest curves first, and for a given size, - * fastest curves first. This provides the default order for the SSL module. - * - * Reminder: update profiles in x509_crt.c when adding a new curves! - */ -static const mbedtls_ecp_curve_info ecp_supported_curves[] = -{ -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) - { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" }, -#endif -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) - { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" }, -#endif -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) - { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" }, -#endif -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) - { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" }, -#endif -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) - { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" }, -#endif -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) - { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" }, -#endif -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) - { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" }, -#endif -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) - { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" }, -#endif -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) - { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" }, -#endif -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) - { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" }, -#endif -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) - { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, -#endif - { MBEDTLS_ECP_DP_NONE, 0, 0, NULL }, -}; - -#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \ - sizeof( ecp_supported_curves[0] ) - -static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES]; - -/* - * List of supported curves and associated info - */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ) -{ - return( ecp_supported_curves ); -} - -/* - * List of supported curves, group ID only - */ -const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ) -{ - static int init_done = 0; - - if( ! init_done ) - { - size_t i = 0; - const mbedtls_ecp_curve_info *curve_info; - - for( curve_info = mbedtls_ecp_curve_list(); - curve_info->grp_id != MBEDTLS_ECP_DP_NONE; - curve_info++ ) - { - ecp_supported_grp_id[i++] = curve_info->grp_id; - } - ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE; - - init_done = 1; - } - - return( ecp_supported_grp_id ); -} - -/* - * Get the curve info for the internal identifier - */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ) -{ - const mbedtls_ecp_curve_info *curve_info; - - for( curve_info = mbedtls_ecp_curve_list(); - curve_info->grp_id != MBEDTLS_ECP_DP_NONE; - curve_info++ ) - { - if( curve_info->grp_id == grp_id ) - return( curve_info ); - } - - return( NULL ); -} - -/* - * Get the curve info from the TLS identifier - */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ) -{ - const mbedtls_ecp_curve_info *curve_info; - - for( curve_info = mbedtls_ecp_curve_list(); - curve_info->grp_id != MBEDTLS_ECP_DP_NONE; - curve_info++ ) - { - if( curve_info->tls_id == tls_id ) - return( curve_info ); - } - - return( NULL ); -} - -/* - * Get the curve info from the name - */ -const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ) -{ - const mbedtls_ecp_curve_info *curve_info; - - for( curve_info = mbedtls_ecp_curve_list(); - curve_info->grp_id != MBEDTLS_ECP_DP_NONE; - curve_info++ ) - { - if( strcmp( curve_info->name, name ) == 0 ) - return( curve_info ); - } - - return( NULL ); -} - -/* - * Get the type of a curve - */ -static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp ) -{ - if( grp->G.X.p == NULL ) - return( ECP_TYPE_NONE ); - - if( grp->G.Y.p == NULL ) - return( ECP_TYPE_MONTGOMERY ); - else - return( ECP_TYPE_SHORT_WEIERSTRASS ); -} - -/* - * Initialize (the components of) a point - */ -void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ) -{ - if( pt == NULL ) - return; - - mbedtls_mpi_init( &pt->X ); - mbedtls_mpi_init( &pt->Y ); - mbedtls_mpi_init( &pt->Z ); -} - -/* - * Initialize (the components of) a group - */ -void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) -{ - if( grp == NULL ) - return; - - memset( grp, 0, sizeof( mbedtls_ecp_group ) ); -} - -/* - * Initialize (the components of) a key pair - */ -void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ) -{ - if( key == NULL ) - return; - - mbedtls_ecp_group_init( &key->grp ); - mbedtls_mpi_init( &key->d ); - mbedtls_ecp_point_init( &key->Q ); -} - -/* - * Unallocate (the components of) a point - */ -void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ) -{ - if( pt == NULL ) - return; - - mbedtls_mpi_free( &( pt->X ) ); - mbedtls_mpi_free( &( pt->Y ) ); - mbedtls_mpi_free( &( pt->Z ) ); -} - -/* - * Unallocate (the components of) a group - */ -void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ) -{ - size_t i; - - if( grp == NULL ) - return; - - if( grp->h != 1 ) - { - mbedtls_mpi_free( &grp->P ); - mbedtls_mpi_free( &grp->A ); - mbedtls_mpi_free( &grp->B ); - mbedtls_ecp_point_free( &grp->G ); - mbedtls_mpi_free( &grp->N ); - } - - if( grp->T != NULL ) - { - for( i = 0; i < grp->T_size; i++ ) - mbedtls_ecp_point_free( &grp->T[i] ); - mbedtls_free( grp->T ); - } - - mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) ); -} - -/* - * Unallocate (the components of) a key pair - */ -void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ) -{ - if( key == NULL ) - return; - - mbedtls_ecp_group_free( &key->grp ); - mbedtls_mpi_free( &key->d ); - mbedtls_ecp_point_free( &key->Q ); -} - -/* - * Copy the contents of a point - */ -int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) -{ - int ret; - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) ); - -cleanup: - return( ret ); -} - -/* - * Copy the contents of a group object - */ -int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ) -{ - return mbedtls_ecp_group_load( dst, src->id ); -} - -/* - * Set point to zero - */ -int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ) -{ - int ret; - - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) ); - -cleanup: - return( ret ); -} - -/* - * Tell if a point is zero - */ -int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ) -{ - return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ); -} - -/* - * Compare two points lazyly - */ -int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, - const mbedtls_ecp_point *Q ) -{ - if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 && - mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 && - mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 ) - { - return( 0 ); - } - - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); -} - -/* - * Import a non-zero point from ASCII strings - */ -int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, - const char *x, const char *y ) -{ - int ret; - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); - -cleanup: - return( ret ); -} - -/* - * Export a point into unsigned binary data (SEC1 2.3.3) - */ -int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, - int format, size_t *olen, - unsigned char *buf, size_t buflen ) -{ - int ret = 0; - size_t plen; - - if( format != MBEDTLS_ECP_PF_UNCOMPRESSED && - format != MBEDTLS_ECP_PF_COMPRESSED ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - /* - * Common case: P == 0 - */ - if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) - { - if( buflen < 1 ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - buf[0] = 0x00; - *olen = 1; - - return( 0 ); - } - - plen = mbedtls_mpi_size( &grp->P ); - - if( format == MBEDTLS_ECP_PF_UNCOMPRESSED ) - { - *olen = 2 * plen + 1; - - if( buflen < *olen ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - buf[0] = 0x04; - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) ); - } - else if( format == MBEDTLS_ECP_PF_COMPRESSED ) - { - *olen = plen + 1; - - if( buflen < *olen ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); - } - -cleanup: - return( ret ); -} - -/* - * Import a point from unsigned binary data (SEC1 2.3.4) - */ -int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, - const unsigned char *buf, size_t ilen ) -{ - int ret; - size_t plen; - - if( ilen < 1 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( buf[0] == 0x00 ) - { - if( ilen == 1 ) - return( mbedtls_ecp_set_zero( pt ) ); - else - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - } - - plen = mbedtls_mpi_size( &grp->P ); - - if( buf[0] != 0x04 ) - return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); - - if( ilen != 2 * plen + 1 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); - -cleanup: - return( ret ); -} - -/* - * Import a point from a TLS ECPoint record (RFC 4492) - * struct { - * opaque point <1..2^8-1>; - * } ECPoint; - */ -int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, - const unsigned char **buf, size_t buf_len ) -{ - unsigned char data_len; - const unsigned char *buf_start; - - /* - * We must have at least two bytes (1 for length, at least one for data) - */ - if( buf_len < 2 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - data_len = *(*buf)++; - if( data_len < 1 || data_len > buf_len - 1 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - /* - * Save buffer start for read_binary and update buf - */ - buf_start = *buf; - *buf += data_len; - - return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ); -} - -/* - * Export a point as a TLS ECPoint record (RFC 4492) - * struct { - * opaque point <1..2^8-1>; - * } ECPoint; - */ -int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, - int format, size_t *olen, - unsigned char *buf, size_t blen ) -{ - int ret; - - /* - * buffer length must be at least one, for our length byte - */ - if( blen < 1 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format, - olen, buf + 1, blen - 1) ) != 0 ) - return( ret ); - - /* - * write length to the first byte and update total length - */ - buf[0] = (unsigned char) *olen; - ++*olen; - - return( 0 ); -} - -/* - * Set a group from an ECParameters record (RFC 4492) - */ -int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ) -{ - uint16_t tls_id; - const mbedtls_ecp_curve_info *curve_info; - - /* - * We expect at least three bytes (see below) - */ - if( len < 3 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - /* - * First byte is curve_type; only named_curve is handled - */ - if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - /* - * Next two bytes are the namedcurve value - */ - tls_id = *(*buf)++; - tls_id <<= 8; - tls_id |= *(*buf)++; - - if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL ) - return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); - - return mbedtls_ecp_group_load( grp, curve_info->grp_id ); -} - -/* - * Write the ECParameters record corresponding to a group (RFC 4492) - */ -int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, - unsigned char *buf, size_t blen ) -{ - const mbedtls_ecp_curve_info *curve_info; - - if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - /* - * We are going to write 3 bytes (see below) - */ - *olen = 3; - if( blen < *olen ) - return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); - - /* - * First byte is curve_type, always named_curve - */ - *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE; - - /* - * Next two bytes are the namedcurve value - */ - buf[0] = curve_info->tls_id >> 8; - buf[1] = curve_info->tls_id & 0xFF; - - return( 0 ); -} - -/* - * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi. - * See the documentation of struct mbedtls_ecp_group. - * - * This function is in the critial loop for mbedtls_ecp_mul, so pay attention to perf. - */ -static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp ) -{ - int ret; - - if( grp->modp == NULL ) - return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) ); - - /* N->s < 0 is a much faster test, which fails only if N is 0 */ - if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) || - mbedtls_mpi_bitlen( N ) > 2 * grp->pbits ) - { - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - } - - MBEDTLS_MPI_CHK( grp->modp( N ) ); - - /* N->s < 0 is a much faster test, which fails only if N is 0 */ - while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) ); - - while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 ) - /* we known P, N and the result are positive */ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) ); - -cleanup: - return( ret ); -} - -/* - * Fast mod-p functions expect their argument to be in the 0..p^2 range. - * - * In order to guarantee that, we need to ensure that operands of - * mbedtls_mpi_mul_mpi are in the 0..p range. So, after each operation we will - * bring the result back to this range. - * - * The following macros are shortcuts for doing that. - */ - -/* - * Reduce a mbedtls_mpi mod p in-place, general case, to use after mbedtls_mpi_mul_mpi - */ -#if defined(MBEDTLS_SELF_TEST) -#define INC_MUL_COUNT mul_count++; -#else -#define INC_MUL_COUNT -#endif - -#define MOD_MUL( N ) do { MBEDTLS_MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \ - while( 0 ) - -/* - * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi - * N->s < 0 is a very fast test, which fails only if N is 0 - */ -#define MOD_SUB( N ) \ - while( N.s < 0 && mbedtls_mpi_cmp_int( &N, 0 ) != 0 ) \ - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &N, &N, &grp->P ) ) - -/* - * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int. - * We known P, N and the result are positive, so sub_abs is correct, and - * a bit faster. - */ -#define MOD_ADD( N ) \ - while( mbedtls_mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &N, &N, &grp->P ) ) - -#if defined(ECP_SHORTWEIERSTRASS) -/* - * For curves in short Weierstrass form, we do all the internal operations in - * Jacobian coordinates. - * - * For multiplication, we'll use a comb method with coutermeasueres against - * SPA, hence timing attacks. - */ - -/* - * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) - * Cost: 1N := 1I + 3M + 1S - */ -static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt ) -{ - int ret; - mbedtls_mpi Zi, ZZi; - - if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ) - return( 0 ); - -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_normalize_jac( grp, pt ); - } -#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ - mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); - - /* - * X = X / Z^2 mod p - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ZZi ) ); MOD_MUL( pt->X ); - - /* - * Y = Y / Z^3 mod p - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &Zi ) ); MOD_MUL( pt->Y ); - - /* - * Z = 1 - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); - -cleanup: - - mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); - - return( ret ); -} - -/* - * Normalize jacobian coordinates of an array of (pointers to) points, - * using Montgomery's trick to perform only one inversion mod P. - * (See for example Cohen's "A Course in Computational Algebraic Number - * Theory", Algorithm 10.3.4.) - * - * Warning: fails (returning an error) if one of the points is zero! - * This should never happen, see choice of w in ecp_mul_comb(). - * - * Cost: 1N(t) := 1I + (6t - 3)M + 1S - */ -static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *T[], size_t t_len ) -{ - int ret; - size_t i; - mbedtls_mpi *c, u, Zi, ZZi; - - if( t_len < 2 ) - return( ecp_normalize_jac( grp, *T ) ); - -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len); - } -#endif - - if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL ) - return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); - - mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); - - /* - * c[i] = Z_0 * ... * Z_i - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) ); - for( i = 1; i < t_len; i++ ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) ); - MOD_MUL( c[i] ); - } - - /* - * u = 1 / (Z_0 * ... * Z_n) mod P - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) ); - - for( i = t_len - 1; ; i-- ) - { - /* - * Zi = 1 / Z_i mod p - * u = 1 / (Z_0 * ... * Z_i) mod P - */ - if( i == 0 ) { - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) ); - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u ); - } - - /* - * proceed as in normalize() - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &Zi ) ); MOD_MUL( T[i]->Y ); - - /* - * Post-precessing: reclaim some memory by shrinking coordinates - * - not storing Z (always 1) - * - shrinking other coordinates, but still keeping the same number of - * limbs as P, as otherwise it will too likely be regrown too fast. - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) ); - mbedtls_mpi_free( &T[i]->Z ); - - if( i == 0 ) - break; - } - -cleanup: - - mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); - for( i = 0; i < t_len; i++ ) - mbedtls_mpi_free( &c[i] ); - mbedtls_free( c ); - - return( ret ); -} - -/* - * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak. - * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid - */ -static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *Q, - unsigned char inv ) -{ - int ret; - unsigned char nonzero; - mbedtls_mpi mQY; - - mbedtls_mpi_init( &mQY ); - - /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) ); - nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0; - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) ); - -cleanup: - mbedtls_mpi_free( &mQY ); - - return( ret ); -} - -/* - * Point doubling R = 2 P, Jacobian coordinates - * - * Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 . - * - * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR - * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring. - * - * Standard optimizations are applied when curve parameter A is one of { 0, -3 }. - * - * Cost: 1D := 3M + 4S (A == 0) - * 4M + 4S (A == -3) - * 3M + 6S + 1a otherwise - */ -static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point *P ) -{ - int ret; - mbedtls_mpi M, S, T, U; - -#if defined(MBEDTLS_SELF_TEST) - dbl_count++; -#endif - -#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_double_jac( grp, R, P ); - } -#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ - - mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U ); - - /* Special case for A = -3 */ - if( grp->A.p == NULL ) - { - /* M = 3(X + Z^2)(X - Z^2) */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); - } - else - { - /* M = 3.X^2 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); - - /* Optimize away for "koblitz" curves with A = 0 */ - if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 ) - { - /* M += A.Z^4 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M ); - } - } - - /* S = 4.X.Y^2 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S ); - - /* U = 8.Y^4 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); - - /* T = M^2 - 2.S */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); - - /* S = M(S - T) - U */ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S ); - - /* U = 2.Y.Z */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) ); - -cleanup: - mbedtls_mpi_free( &M ); mbedtls_mpi_free( &S ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &U ); - - return( ret ); -} - -/* - * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) - * - * The coordinates of Q must be normalized (= affine), - * but those of P don't need to. R is not normalized. - * - * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q. - * None of these cases can happen as intermediate step in ecp_mul_comb(): - * - at each step, P, Q and R are multiples of the base point, the factor - * being less than its order, so none of them is zero; - * - Q is an odd multiple of the base point, P an even multiple, - * due to the choice of precomputed points in the modified comb method. - * So branches for these cases do not leak secret information. - * - * We accept Q->Z being unset (saving memory in tables) as meaning 1. - * - * Cost: 1A := 8M + 3S - */ -static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) -{ - int ret; - mbedtls_mpi T1, T2, T3, T4, X, Y, Z; - -#if defined(MBEDTLS_SELF_TEST) - add_count++; -#endif - -#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_add_mixed( grp, R, P, Q ); - } -#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ - - /* - * Trivial cases: P == 0 or Q == 0 (case 1) - */ - if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) - return( mbedtls_ecp_copy( R, Q ) ); - - if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 ) - return( mbedtls_ecp_copy( R, P ) ); - - /* - * Make sure Q coordinates are normalized - */ - if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 ); - mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 ); - - /* Special cases (2) and (3) */ - if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 ) - { - if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 ) - { - ret = ecp_double_jac( grp, R, P ); - goto cleanup; - } - else - { - ret = mbedtls_ecp_set_zero( R ); - goto cleanup; - } - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) ); - -cleanup: - - mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 ); - mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); - - return( ret ); -} - -/* - * Randomize jacobian coordinates: - * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l - * This is sort of the reverse operation of ecp_normalize_jac(). - * - * This countermeasure was first suggested in [2]. - */ -static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - int ret; - mbedtls_mpi l, ll; - size_t p_size; - int count = 0; - -#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ); - } -#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ - - p_size = ( grp->pbits + 7 ) / 8; - mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll ); - - /* Generate l such that 1 < l < p */ - do - { - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); - - while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); - - if( count++ > 10 ) - return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); - } - while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); - - /* Z = l * Z */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Z, &pt->Z, &l ) ); MOD_MUL( pt->Z ); - - /* X = l^2 * X */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ll ) ); MOD_MUL( pt->X ); - - /* Y = l^3 * Y */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ll ) ); MOD_MUL( pt->Y ); - -cleanup: - mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll ); - - return( ret ); -} - -/* - * Check and define parameters used by the comb method (see below for details) - */ -#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7 -#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds" -#endif - -/* d = ceil( n / w ) */ -#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2 - -/* number of precomputed points */ -#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) - -/* - * Compute the representation of m that will be used with our comb method. - * - * The basic comb method is described in GECC 3.44 for example. We use a - * modified version that provides resistance to SPA by avoiding zero - * digits in the representation as in [3]. We modify the method further by - * requiring that all K_i be odd, which has the small cost that our - * representation uses one more K_i, due to carries. - * - * Also, for the sake of compactness, only the seven low-order bits of x[i] - * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in - * the paper): it is set if and only if if s_i == -1; - * - * Calling conventions: - * - x is an array of size d + 1 - * - w is the size, ie number of teeth, of the comb, and must be between - * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE) - * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d - * (the result will be incorrect if these assumptions are not satisfied) - */ -static void ecp_comb_fixed( unsigned char x[], size_t d, - unsigned char w, const mbedtls_mpi *m ) -{ - size_t i, j; - unsigned char c, cc, adjust; - - memset( x, 0, d+1 ); - - /* First get the classical comb values (except for x_d = 0) */ - for( i = 0; i < d; i++ ) - for( j = 0; j < w; j++ ) - x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j; - - /* Now make sure x_1 .. x_d are odd */ - c = 0; - for( i = 1; i <= d; i++ ) - { - /* Add carry and update it */ - cc = x[i] & c; - x[i] = x[i] ^ c; - c = cc; - - /* Adjust if needed, avoiding branches */ - adjust = 1 - ( x[i] & 0x01 ); - c |= x[i] & ( x[i-1] * adjust ); - x[i] = x[i] ^ ( x[i-1] * adjust ); - x[i-1] |= adjust << 7; - } -} - -/* - * Precompute points for the comb method - * - * If i = i_{w-1} ... i_1 is the binary representation of i, then - * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P - * - * T must be able to hold 2^{w - 1} elements - * - * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) - */ -static int ecp_precompute_comb( const mbedtls_ecp_group *grp, - mbedtls_ecp_point T[], const mbedtls_ecp_point *P, - unsigned char w, size_t d ) -{ - int ret; - unsigned char i, k; - size_t j; - mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; - - /* - * Set T[0] = P and - * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) - */ - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); - - k = 0; - for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) - { - cur = T + i; - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); - for( j = 0; j < d; j++ ) - MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); - - TT[k++] = cur; - } - - MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); - - /* - * Compute the remaining ones using the minimal number of additions - * Be careful to update T[2^l] only after using it! - */ - k = 0; - for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) - { - j = i; - while( j-- ) - { - MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); - TT[k++] = &T[i + j]; - } - } - - MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); - -cleanup: - - return( ret ); -} - -/* - * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] - */ -static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point T[], unsigned char t_len, - unsigned char i ) -{ - int ret; - unsigned char ii, j; - - /* Ignore the "sign" bit and scale down */ - ii = ( i & 0x7Fu ) >> 1; - - /* Read the whole table to thwart cache-based timing attacks */ - for( j = 0; j < t_len; j++ ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) ); - } - - /* Safely invert result if i is "negative" */ - MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) ); - -cleanup: - return( ret ); -} - -/* - * Core multiplication algorithm for the (modified) comb method. - * This part is actually common with the basic comb method (GECC 3.44) - * - * Cost: d A + d D + 1 R - */ -static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point T[], unsigned char t_len, - const unsigned char x[], size_t d, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - mbedtls_ecp_point Txi; - size_t i; - - mbedtls_ecp_point_init( &Txi ); - - /* Start with a non-zero point and randomize its coordinates */ - i = d; - MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); - if( f_rng != 0 ) - MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); - - while( i-- != 0 ) - { - MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); - MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) ); - MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); - } - -cleanup: - - mbedtls_ecp_point_free( &Txi ); - - return( ret ); -} - -/* - * Multiplication using the comb method, - * for curves in short Weierstrass form - */ -static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_mpi *m, const mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - unsigned char w, m_is_odd, p_eq_g, pre_len, i; - size_t d; - unsigned char k[COMB_MAX_D + 1]; - mbedtls_ecp_point *T; - mbedtls_mpi M, mm; - - mbedtls_mpi_init( &M ); - mbedtls_mpi_init( &mm ); - - /* we need N to be odd to trnaform m in an odd number, check now */ - if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - /* - * Minimize the number of multiplications, that is minimize - * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) - * (see costs of the various parts, with 1S = 1M) - */ - w = grp->nbits >= 384 ? 5 : 4; - - /* - * If P == G, pre-compute a bit more, since this may be re-used later. - * Just adding one avoids upping the cost of the first mul too much, - * and the memory cost too. - */ -#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 - p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && - mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); - if( p_eq_g ) - w++; -#else - p_eq_g = 0; -#endif - - /* - * Make sure w is within bounds. - * (The last test is useful only for very small curves in the test suite.) - */ - if( w > MBEDTLS_ECP_WINDOW_SIZE ) - w = MBEDTLS_ECP_WINDOW_SIZE; - if( w >= grp->nbits ) - w = 2; - - /* Other sizes that depend on w */ - pre_len = 1U << ( w - 1 ); - d = ( grp->nbits + w - 1 ) / w; - - /* - * Prepare precomputed points: if P == G we want to - * use grp->T if already initialized, or initialize it. - */ - T = p_eq_g ? grp->T : NULL; - - if( T == NULL ) - { - T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) ); - if( T == NULL ) - { - ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; - goto cleanup; - } - - MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) ); - - if( p_eq_g ) - { - grp->T = T; - grp->T_size = pre_len; - } - } - - /* - * Make sure M is odd (M = m or M = N - m, since N is odd) - * using the fact that m * P = - (N - m) * P - */ - m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) ); - - /* - * Go for comb multiplication, R = M * P - */ - ecp_comb_fixed( k, d, w, &M ); - MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) ); - - /* - * Now get m * P from M * P and normalize it - */ - MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) ); - MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); - -cleanup: - - if( T != NULL && T != grp->T ) - { - for( i = 0; i < pre_len; i++ ) - mbedtls_ecp_point_free( &T[i] ); - mbedtls_free( T ); - } - - mbedtls_mpi_free( &M ); - mbedtls_mpi_free( &mm ); - - if( ret != 0 ) - mbedtls_ecp_point_free( R ); - - return( ret ); -} - -#endif /* ECP_SHORTWEIERSTRASS */ - -#if defined(ECP_MONTGOMERY) -/* - * For Montgomery curves, we do all the internal arithmetic in projective - * coordinates. Import/export of points uses only the x coordinates, which is - * internaly represented as X / Z. - * - * For scalar multiplication, we'll use a Montgomery ladder. - */ - -/* - * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1 - * Cost: 1M + 1I - */ -static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P ) -{ - int ret; - -#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_normalize_mxz( grp, P ); - } -#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ - - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); - -cleanup: - return( ret ); -} - -/* - * Randomize projective x/z coordinates: - * (X, Z) -> (l X, l Z) for random l - * This is sort of the reverse operation of ecp_normalize_mxz(). - * - * This countermeasure was first suggested in [2]. - * Cost: 2M - */ -static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - int ret; - mbedtls_mpi l; - size_t p_size; - int count = 0; - -#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ); - } -#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ - - p_size = ( grp->pbits + 7 ) / 8; - mbedtls_mpi_init( &l ); - - /* Generate l such that 1 < l < p */ - do - { - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); - - while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); - - if( count++ > 10 ) - return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); - } - while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z ); - -cleanup: - mbedtls_mpi_free( &l ); - - return( ret ); -} - -/* - * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q), - * for Montgomery curves in x/z coordinates. - * - * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3 - * with - * d = X1 - * P = (X2, Z2) - * Q = (X3, Z3) - * R = (X4, Z4) - * S = (X5, Z5) - * and eliminating temporary variables tO, ..., t4. - * - * Cost: 5M + 4S - */ -static int ecp_double_add_mxz( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *R, mbedtls_ecp_point *S, - const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, - const mbedtls_mpi *d ) -{ - int ret; - mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB; - -#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ); - } -#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ - - mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B ); - mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C ); - mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &E, &R->Z ) ); MOD_MUL( R->Z ); - -cleanup: - mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B ); - mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C ); - mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB ); - - return( ret ); -} - -/* - * Multiplication with Montgomery ladder in x/z coordinates, - * for curves in Montgomery form - */ -static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_mpi *m, const mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - size_t i; - unsigned char b; - mbedtls_ecp_point RP; - mbedtls_mpi PX; - - mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX ); - - /* Save PX and read from P before writing to R, in case P == R */ - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) ); - - /* Set R to zero in modified x/z coordinates */ - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) ); - mbedtls_mpi_free( &R->Y ); - - /* RP.X might be sligtly larger than P, so reduce it */ - MOD_ADD( RP.X ); - - /* Randomize coordinates of the starting point */ - if( f_rng != NULL ) - MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) ); - - /* Loop invariant: R = result so far, RP = R + P */ - i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */ - while( i-- > 0 ) - { - b = mbedtls_mpi_get_bit( m, i ); - /* - * if (b) R = 2R + P else R = 2R, - * which is: - * if (b) double_add( RP, R, RP, R ) - * else double_add( R, RP, R, RP ) - * but using safe conditional swaps to avoid leaks - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); - MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); - } - - MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) ); - -cleanup: - mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX ); - - return( ret ); -} - -#endif /* ECP_MONTGOMERY */ - -/* - * Multiplication R = m * P - */ -int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_mpi *m, const mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; -#if defined(MBEDTLS_ECP_INTERNAL_ALT) - char is_grp_capable = 0; -#endif - - /* Common sanity checks */ - if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 || - ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 ) - return( ret ); - -#if defined(MBEDTLS_ECP_INTERNAL_ALT) - if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) - { - MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); - } - -#endif /* MBEDTLS_ECP_INTERNAL_ALT */ -#if defined(ECP_MONTGOMERY) - if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) - ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ); - -#endif -#if defined(ECP_SHORTWEIERSTRASS) - if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) - ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng ); - -#endif -#if defined(MBEDTLS_ECP_INTERNAL_ALT) -cleanup: - - if ( is_grp_capable ) - { - mbedtls_internal_ecp_free( grp ); - } - -#endif /* MBEDTLS_ECP_INTERNAL_ALT */ - return( ret ); -} - -#if defined(ECP_SHORTWEIERSTRASS) -/* - * Check that an affine point is valid as a public key, - * short weierstrass curves (SEC1 3.2.3.1) - */ -static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) -{ - int ret; - mbedtls_mpi YY, RHS; - - /* pt coordinates must be normalized for our checks */ - if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 || - mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 || - mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 || - mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 ) - return( MBEDTLS_ERR_ECP_INVALID_KEY ); - - mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS ); - - /* - * YY = Y^2 - * RHS = X (X^2 + A) + B = X^3 + A X + B - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS ); - - /* Special case for A = -3 */ - if( grp->A.p == NULL ) - { - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS ); - } - else - { - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS ); - } - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS ); - - if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 ) - ret = MBEDTLS_ERR_ECP_INVALID_KEY; - -cleanup: - - mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS ); - - return( ret ); -} -#endif /* ECP_SHORTWEIERSTRASS */ - -/* - * R = m * P with shortcuts for m == 1 and m == -1 - * NOT constant-time - ONLY for short Weierstrass! - */ -static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, - mbedtls_ecp_point *R, - const mbedtls_mpi *m, - const mbedtls_ecp_point *P ) -{ - int ret; - - if( mbedtls_mpi_cmp_int( m, 1 ) == 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); - } - else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 ) - { - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); - if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) ); - } - else - { - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) ); - } - -cleanup: - return( ret ); -} - -/* - * Linear combination - * NOT constant-time - */ -int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_mpi *m, const mbedtls_ecp_point *P, - const mbedtls_mpi *n, const mbedtls_ecp_point *Q ) -{ - int ret; - mbedtls_ecp_point mP; -#if defined(MBEDTLS_ECP_INTERNAL_ALT) - char is_grp_capable = 0; -#endif - - if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS ) - return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); - - mbedtls_ecp_point_init( &mP ); - - MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) ); - -#if defined(MBEDTLS_ECP_INTERNAL_ALT) - if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) - { - MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); - } - -#endif /* MBEDTLS_ECP_INTERNAL_ALT */ - MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) ); - MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); - -cleanup: - -#if defined(MBEDTLS_ECP_INTERNAL_ALT) - if ( is_grp_capable ) - { - mbedtls_internal_ecp_free( grp ); - } - -#endif /* MBEDTLS_ECP_INTERNAL_ALT */ - mbedtls_ecp_point_free( &mP ); - - return( ret ); -} - - -#if defined(ECP_MONTGOMERY) -/* - * Check validity of a public key for Montgomery curves with x-only schemes - */ -static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) -{ - /* [Curve25519 p. 5] Just check X is the correct number of bytes */ - if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 ) - return( MBEDTLS_ERR_ECP_INVALID_KEY ); - - return( 0 ); -} -#endif /* ECP_MONTGOMERY */ - -/* - * Check that a point is valid as a public key - */ -int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) -{ - /* Must use affine coordinates */ - if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 ) - return( MBEDTLS_ERR_ECP_INVALID_KEY ); - -#if defined(ECP_MONTGOMERY) - if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) - return( ecp_check_pubkey_mx( grp, pt ) ); -#endif -#if defined(ECP_SHORTWEIERSTRASS) - if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) - return( ecp_check_pubkey_sw( grp, pt ) ); -#endif - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); -} - -/* - * Check that an mbedtls_mpi is valid as a private key - */ -int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ) -{ -#if defined(ECP_MONTGOMERY) - if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) - { - /* see [Curve25519] page 5 */ - if( mbedtls_mpi_get_bit( d, 0 ) != 0 || - mbedtls_mpi_get_bit( d, 1 ) != 0 || - mbedtls_mpi_get_bit( d, 2 ) != 0 || - mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */ - return( MBEDTLS_ERR_ECP_INVALID_KEY ); - else - return( 0 ); - } -#endif /* ECP_MONTGOMERY */ -#if defined(ECP_SHORTWEIERSTRASS) - if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) - { - /* see SEC1 3.2 */ - if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || - mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) - return( MBEDTLS_ERR_ECP_INVALID_KEY ); - else - return( 0 ); - } -#endif /* ECP_SHORTWEIERSTRASS */ - - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); -} - -/* - * Generate a keypair with configurable base point - */ -int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, - const mbedtls_ecp_point *G, - mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - size_t n_size = ( grp->nbits + 7 ) / 8; - -#if defined(ECP_MONTGOMERY) - if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) - { - /* [M225] page 5 */ - size_t b; - - do { - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); - } while( mbedtls_mpi_bitlen( d ) == 0); - - /* Make sure the most significant bit is nbits */ - b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */ - if( b > grp->nbits ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) ); - else - MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) ); - - /* Make sure the last three bits are unset */ - MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); - } - else -#endif /* ECP_MONTGOMERY */ -#if defined(ECP_SHORTWEIERSTRASS) - if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) - { - /* SEC1 3.2.1: Generate d such that 1 <= n < N */ - int count = 0; - unsigned char rnd[MBEDTLS_ECP_MAX_BYTES]; - - /* - * Match the procedure given in RFC 6979 (deterministic ECDSA): - * - use the same byte ordering; - * - keep the leftmost nbits bits of the generated octet string; - * - try until result is in the desired range. - * This also avoids any biais, which is especially important for ECDSA. - */ - do - { - MBEDTLS_MPI_CHK( f_rng( p_rng, rnd, n_size ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( d, rnd, n_size ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) ); - - /* - * Each try has at worst a probability 1/2 of failing (the msb has - * a probability 1/2 of being 0, and then the result will be < N), - * so after 30 tries failure probability is a most 2**(-30). - * - * For most curves, 1 try is enough with overwhelming probability, - * since N starts with a lot of 1s in binary, but some curves - * such as secp224k1 are actually very close to the worst case. - */ - if( ++count > 30 ) - return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); - } - while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || - mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ); - } - else -#endif /* ECP_SHORTWEIERSTRASS */ - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - -cleanup: - if( ret != 0 ) - return( ret ); - - return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); -} - -/* - * Generate key pair, wrapper for conventional base point - */ -int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, - mbedtls_mpi *d, mbedtls_ecp_point *Q, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) ); -} - -/* - * Generate a keypair, prettier wrapper - */ -int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - int ret; - - if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 ) - return( ret ); - - return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) ); -} - -/* - * Check a public-private key pair - */ -int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ) -{ - int ret; - mbedtls_ecp_point Q; - mbedtls_ecp_group grp; - - if( pub->grp.id == MBEDTLS_ECP_DP_NONE || - pub->grp.id != prv->grp.id || - mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) || - mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) || - mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) ) - { - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - } - - mbedtls_ecp_point_init( &Q ); - mbedtls_ecp_group_init( &grp ); - - /* mbedtls_ecp_mul() needs a non-const group... */ - mbedtls_ecp_group_copy( &grp, &prv->grp ); - - /* Also checks d is valid */ - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) ); - - if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) || - mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) || - mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) ) - { - ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; - goto cleanup; - } - -cleanup: - mbedtls_ecp_point_free( &Q ); - mbedtls_ecp_group_free( &grp ); - - return( ret ); -} - -#if defined(MBEDTLS_SELF_TEST) - -/* - * Checkup routine - */ -int mbedtls_ecp_self_test( int verbose ) -{ - int ret; - size_t i; - mbedtls_ecp_group grp; - mbedtls_ecp_point R, P; - mbedtls_mpi m; - unsigned long add_c_prev, dbl_c_prev, mul_c_prev; - /* exponents especially adapted for secp192r1 */ - const char *exponents[] = - { - "000000000000000000000000000000000000000000000001", /* one */ - "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */ - "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */ - "400000000000000000000000000000000000000000000000", /* one and zeros */ - "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */ - "555555555555555555555555555555555555555555555555", /* 101010... */ - }; - - mbedtls_ecp_group_init( &grp ); - mbedtls_ecp_point_init( &R ); - mbedtls_ecp_point_init( &P ); - mbedtls_mpi_init( &m ); - - /* Use secp192r1 if available, or any available curve */ -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) - MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) ); -#else - MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) ); -#endif - - if( verbose != 0 ) - mbedtls_printf( " ECP test #1 (constant op_count, base point G): " ); - - /* Do a dummy multiplication first to trigger precomputation */ - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) ); - - add_count = 0; - dbl_count = 0; - mul_count = 0; - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); - - for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) - { - add_c_prev = add_count; - dbl_c_prev = dbl_count; - mul_c_prev = mul_count; - add_count = 0; - dbl_count = 0; - mul_count = 0; - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); - - if( add_count != add_c_prev || - dbl_count != dbl_c_prev || - mul_count != mul_c_prev ) - { - if( verbose != 0 ) - mbedtls_printf( "failed (%u)\n", (unsigned int) i ); - - ret = 1; - goto cleanup; - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " ECP test #2 (constant op_count, other point): " ); - /* We computed P = 2G last time, use it */ - - add_count = 0; - dbl_count = 0; - mul_count = 0; - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); - - for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) - { - add_c_prev = add_count; - dbl_c_prev = dbl_count; - mul_c_prev = mul_count; - add_count = 0; - dbl_count = 0; - mul_count = 0; - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); - - if( add_count != add_c_prev || - dbl_count != dbl_c_prev || - mul_count != mul_c_prev ) - { - if( verbose != 0 ) - mbedtls_printf( "failed (%u)\n", (unsigned int) i ); - - ret = 1; - goto cleanup; - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - -cleanup: - - if( ret < 0 && verbose != 0 ) - mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); - - mbedtls_ecp_group_free( &grp ); - mbedtls_ecp_point_free( &R ); - mbedtls_ecp_point_free( &P ); - mbedtls_mpi_free( &m ); - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* !MBEDTLS_ECP_ALT */ - -#endif /* MBEDTLS_ECP_C */ diff --git a/components/mbedtls/library/ecp_curves.c b/components/mbedtls/library/ecp_curves.c deleted file mode 100644 index df5ac3eea5..0000000000 --- a/components/mbedtls/library/ecp_curves.c +++ /dev/null @@ -1,1329 +0,0 @@ -/* - * Elliptic curves over GF(p): curve-specific data and functions - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_ECP_C) - -#include "mbedtls/ecp.h" - -#include - -#if !defined(MBEDTLS_ECP_ALT) - -#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ - !defined(inline) && !defined(__cplusplus) -#define inline __inline -#endif - -/* - * Conversion macros for embedded constants: - * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2 - */ -#if defined(MBEDTLS_HAVE_INT32) - -#define BYTES_TO_T_UINT_4( a, b, c, d ) \ - ( (mbedtls_mpi_uint) a << 0 ) | \ - ( (mbedtls_mpi_uint) b << 8 ) | \ - ( (mbedtls_mpi_uint) c << 16 ) | \ - ( (mbedtls_mpi_uint) d << 24 ) - -#define BYTES_TO_T_UINT_2( a, b ) \ - BYTES_TO_T_UINT_4( a, b, 0, 0 ) - -#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ - BYTES_TO_T_UINT_4( a, b, c, d ), \ - BYTES_TO_T_UINT_4( e, f, g, h ) - -#else /* 64-bits */ - -#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ - ( (mbedtls_mpi_uint) a << 0 ) | \ - ( (mbedtls_mpi_uint) b << 8 ) | \ - ( (mbedtls_mpi_uint) c << 16 ) | \ - ( (mbedtls_mpi_uint) d << 24 ) | \ - ( (mbedtls_mpi_uint) e << 32 ) | \ - ( (mbedtls_mpi_uint) f << 40 ) | \ - ( (mbedtls_mpi_uint) g << 48 ) | \ - ( (mbedtls_mpi_uint) h << 56 ) - -#define BYTES_TO_T_UINT_4( a, b, c, d ) \ - BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 ) - -#define BYTES_TO_T_UINT_2( a, b ) \ - BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 ) - -#endif /* bits in mbedtls_mpi_uint */ - -/* - * Note: the constants are in little-endian order - * to be directly usable in MPIs - */ - -/* - * Domain parameters for secp192r1 - */ -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) -static const mbedtls_mpi_uint secp192r1_p[] = { - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -static const mbedtls_mpi_uint secp192r1_b[] = { - BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ), - BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ), - BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ), -}; -static const mbedtls_mpi_uint secp192r1_gx[] = { - BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ), - BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ), - BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ), -}; -static const mbedtls_mpi_uint secp192r1_gy[] = { - BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ), - BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ), - BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ), -}; -static const mbedtls_mpi_uint secp192r1_n[] = { - BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ), - BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ - -/* - * Domain parameters for secp224r1 - */ -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) -static const mbedtls_mpi_uint secp224r1_p[] = { - BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), - BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), -}; -static const mbedtls_mpi_uint secp224r1_b[] = { - BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ), - BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ), - BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ), - BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ), -}; -static const mbedtls_mpi_uint secp224r1_gx[] = { - BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ), - BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ), - BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ), - BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ), -}; -static const mbedtls_mpi_uint secp224r1_gy[] = { - BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ), - BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ), - BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ), - BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ), -}; -static const mbedtls_mpi_uint secp224r1_n[] = { - BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ), - BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), -}; -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ - -/* - * Domain parameters for secp256r1 - */ -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) -static const mbedtls_mpi_uint secp256r1_p[] = { - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), - BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), - BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -static const mbedtls_mpi_uint secp256r1_b[] = { - BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ), - BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ), - BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ), - BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ), -}; -static const mbedtls_mpi_uint secp256r1_gx[] = { - BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ), - BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ), - BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ), - BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ), -}; -static const mbedtls_mpi_uint secp256r1_gy[] = { - BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ), - BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ), - BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ), - BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ), -}; -static const mbedtls_mpi_uint secp256r1_n[] = { - BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ), - BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ - -/* - * Domain parameters for secp384r1 - */ -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) -static const mbedtls_mpi_uint secp384r1_p[] = { - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), - BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -static const mbedtls_mpi_uint secp384r1_b[] = { - BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ), - BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ), - BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ), - BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ), - BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ), - BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ), -}; -static const mbedtls_mpi_uint secp384r1_gx[] = { - BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ), - BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ), - BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ), - BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ), - BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ), - BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ), -}; -static const mbedtls_mpi_uint secp384r1_gy[] = { - BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ), - BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ), - BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ), - BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ), - BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ), - BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ), -}; -static const mbedtls_mpi_uint secp384r1_n[] = { - BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ), - BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ), - BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ - -/* - * Domain parameters for secp521r1 - */ -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) -static const mbedtls_mpi_uint secp521r1_p[] = { - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_2( 0xFF, 0x01 ), -}; -static const mbedtls_mpi_uint secp521r1_b[] = { - BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ), - BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ), - BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ), - BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ), - BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ), - BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ), - BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ), - BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ), - BYTES_TO_T_UINT_2( 0x51, 0x00 ), -}; -static const mbedtls_mpi_uint secp521r1_gx[] = { - BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ), - BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ), - BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ), - BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ), - BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ), - BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ), - BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ), - BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ), - BYTES_TO_T_UINT_2( 0xC6, 0x00 ), -}; -static const mbedtls_mpi_uint secp521r1_gy[] = { - BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ), - BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ), - BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ), - BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ), - BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ), - BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ), - BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ), - BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ), - BYTES_TO_T_UINT_2( 0x18, 0x01 ), -}; -static const mbedtls_mpi_uint secp521r1_n[] = { - BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ), - BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ), - BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ), - BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ), - BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_2( 0xFF, 0x01 ), -}; -#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) -static const mbedtls_mpi_uint secp192k1_p[] = { - BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -static const mbedtls_mpi_uint secp192k1_a[] = { - BYTES_TO_T_UINT_2( 0x00, 0x00 ), -}; -static const mbedtls_mpi_uint secp192k1_b[] = { - BYTES_TO_T_UINT_2( 0x03, 0x00 ), -}; -static const mbedtls_mpi_uint secp192k1_gx[] = { - BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ), - BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ), - BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ), -}; -static const mbedtls_mpi_uint secp192k1_gy[] = { - BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ), - BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ), - BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ), -}; -static const mbedtls_mpi_uint secp192k1_n[] = { - BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ), - BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) -static const mbedtls_mpi_uint secp224k1_p[] = { - BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), -}; -static const mbedtls_mpi_uint secp224k1_a[] = { - BYTES_TO_T_UINT_2( 0x00, 0x00 ), -}; -static const mbedtls_mpi_uint secp224k1_b[] = { - BYTES_TO_T_UINT_2( 0x05, 0x00 ), -}; -static const mbedtls_mpi_uint secp224k1_gx[] = { - BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ), - BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ), - BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ), - BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ), -}; -static const mbedtls_mpi_uint secp224k1_gy[] = { - BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ), - BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ), - BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ), - BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ), -}; -static const mbedtls_mpi_uint secp224k1_n[] = { - BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ), - BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ), - BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), - BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ), -}; -#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -static const mbedtls_mpi_uint secp256k1_p[] = { - BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -static const mbedtls_mpi_uint secp256k1_a[] = { - BYTES_TO_T_UINT_2( 0x00, 0x00 ), -}; -static const mbedtls_mpi_uint secp256k1_b[] = { - BYTES_TO_T_UINT_2( 0x07, 0x00 ), -}; -static const mbedtls_mpi_uint secp256k1_gx[] = { - BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ), - BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ), - BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ), - BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ), -}; -static const mbedtls_mpi_uint secp256k1_gy[] = { - BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ), - BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ), - BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ), - BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ), -}; -static const mbedtls_mpi_uint secp256k1_n[] = { - BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ), - BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ), - BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), - BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), -}; -#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ - -/* - * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) - */ -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) -static const mbedtls_mpi_uint brainpoolP256r1_p[] = { - BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ), - BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ), - BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), - BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), -}; -static const mbedtls_mpi_uint brainpoolP256r1_a[] = { - BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ), - BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ), - BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ), - BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ), -}; -static const mbedtls_mpi_uint brainpoolP256r1_b[] = { - BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ), - BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ), - BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ), - BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ), -}; -static const mbedtls_mpi_uint brainpoolP256r1_gx[] = { - BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ), - BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ), - BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ), - BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ), -}; -static const mbedtls_mpi_uint brainpoolP256r1_gy[] = { - BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ), - BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ), - BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ), - BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ), -}; -static const mbedtls_mpi_uint brainpoolP256r1_n[] = { - BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ), - BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ), - BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), - BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), -}; -#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ - -/* - * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) - */ -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) -static const mbedtls_mpi_uint brainpoolP384r1_p[] = { - BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ), - BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ), - BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ), - BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), - BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), - BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), -}; -static const mbedtls_mpi_uint brainpoolP384r1_a[] = { - BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), - BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ), - BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ), - BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ), - BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ), - BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ), -}; -static const mbedtls_mpi_uint brainpoolP384r1_b[] = { - BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ), - BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ), - BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ), - BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ), - BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ), - BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), -}; -static const mbedtls_mpi_uint brainpoolP384r1_gx[] = { - BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ), - BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ), - BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ), - BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ), - BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ), - BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ), -}; -static const mbedtls_mpi_uint brainpoolP384r1_gy[] = { - BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ), - BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ), - BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ), - BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ), - BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ), - BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ), -}; -static const mbedtls_mpi_uint brainpoolP384r1_n[] = { - BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ), - BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ), - BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ), - BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), - BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), - BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), -}; -#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ - -/* - * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) - */ -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) -static const mbedtls_mpi_uint brainpoolP512r1_p[] = { - BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ), - BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ), - BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ), - BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ), - BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), - BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), - BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), - BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), -}; -static const mbedtls_mpi_uint brainpoolP512r1_a[] = { - BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ), - BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ), - BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ), - BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ), - BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ), - BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ), - BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ), - BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ), -}; -static const mbedtls_mpi_uint brainpoolP512r1_b[] = { - BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ), - BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ), - BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ), - BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ), - BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ), - BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ), - BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ), - BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ), -}; -static const mbedtls_mpi_uint brainpoolP512r1_gx[] = { - BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ), - BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ), - BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ), - BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ), - BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ), - BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ), - BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ), - BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ), -}; -static const mbedtls_mpi_uint brainpoolP512r1_gy[] = { - BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ), - BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ), - BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ), - BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ), - BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ), - BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ), - BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ), - BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ), -}; -static const mbedtls_mpi_uint brainpoolP512r1_n[] = { - BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ), - BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ), - BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ), - BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ), - BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), - BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), - BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), - BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), -}; -#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ - -/* - * Create an MPI from embedded constants - * (assumes len is an exact multiple of sizeof mbedtls_mpi_uint) - */ -static inline void ecp_mpi_load( mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len ) -{ - X->s = 1; - X->n = len / sizeof( mbedtls_mpi_uint ); - X->p = (mbedtls_mpi_uint *) p; -} - -/* - * Set an MPI to static value 1 - */ -static inline void ecp_mpi_set1( mbedtls_mpi *X ) -{ - static mbedtls_mpi_uint one[] = { 1 }; - X->s = 1; - X->n = 1; - X->p = one; -} - -/* - * Make group available from embedded constants - */ -static int ecp_group_load( mbedtls_ecp_group *grp, - const mbedtls_mpi_uint *p, size_t plen, - const mbedtls_mpi_uint *a, size_t alen, - const mbedtls_mpi_uint *b, size_t blen, - const mbedtls_mpi_uint *gx, size_t gxlen, - const mbedtls_mpi_uint *gy, size_t gylen, - const mbedtls_mpi_uint *n, size_t nlen) -{ - ecp_mpi_load( &grp->P, p, plen ); - if( a != NULL ) - ecp_mpi_load( &grp->A, a, alen ); - ecp_mpi_load( &grp->B, b, blen ); - ecp_mpi_load( &grp->N, n, nlen ); - - ecp_mpi_load( &grp->G.X, gx, gxlen ); - ecp_mpi_load( &grp->G.Y, gy, gylen ); - ecp_mpi_set1( &grp->G.Z ); - - grp->pbits = mbedtls_mpi_bitlen( &grp->P ); - grp->nbits = mbedtls_mpi_bitlen( &grp->N ); - - grp->h = 1; - - return( 0 ); -} - -#if defined(MBEDTLS_ECP_NIST_OPTIM) -/* Forward declarations */ -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) -static int ecp_mod_p192( mbedtls_mpi * ); -#endif -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) -static int ecp_mod_p224( mbedtls_mpi * ); -#endif -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) -static int ecp_mod_p256( mbedtls_mpi * ); -#endif -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) -static int ecp_mod_p384( mbedtls_mpi * ); -#endif -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) -static int ecp_mod_p521( mbedtls_mpi * ); -#endif - -#define NIST_MODP( P ) grp->modp = ecp_mod_ ## P; -#else -#define NIST_MODP( P ) -#endif /* MBEDTLS_ECP_NIST_OPTIM */ - -/* Additional forward declarations */ -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) -static int ecp_mod_p255( mbedtls_mpi * ); -#endif -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) -static int ecp_mod_p192k1( mbedtls_mpi * ); -#endif -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) -static int ecp_mod_p224k1( mbedtls_mpi * ); -#endif -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -static int ecp_mod_p256k1( mbedtls_mpi * ); -#endif - -#define LOAD_GROUP_A( G ) ecp_group_load( grp, \ - G ## _p, sizeof( G ## _p ), \ - G ## _a, sizeof( G ## _a ), \ - G ## _b, sizeof( G ## _b ), \ - G ## _gx, sizeof( G ## _gx ), \ - G ## _gy, sizeof( G ## _gy ), \ - G ## _n, sizeof( G ## _n ) ) - -#define LOAD_GROUP( G ) ecp_group_load( grp, \ - G ## _p, sizeof( G ## _p ), \ - NULL, 0, \ - G ## _b, sizeof( G ## _b ), \ - G ## _gx, sizeof( G ## _gx ), \ - G ## _gy, sizeof( G ## _gy ), \ - G ## _n, sizeof( G ## _n ) ) - -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) -/* - * Specialized function for creating the Curve25519 group - */ -static int ecp_use_curve25519( mbedtls_ecp_group *grp ) -{ - int ret; - - /* Actually ( A + 2 ) / 4 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "01DB42" ) ); - - /* P = 2^255 - 19 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 255 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 19 ) ); - grp->pbits = mbedtls_mpi_bitlen( &grp->P ); - - /* Y intentionaly not set, since we use x/z coordinates. - * This is used as a marker to identify Montgomery curves! */ - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 9 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); - mbedtls_mpi_free( &grp->G.Y ); - - /* Actually, the required msb for private keys */ - grp->nbits = 254; - -cleanup: - if( ret != 0 ) - mbedtls_ecp_group_free( grp ); - - return( ret ); -} -#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ - -/* - * Set a group using well-known domain parameters - */ -int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ) -{ - mbedtls_ecp_group_free( grp ); - - grp->id = id; - - switch( id ) - { -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) - case MBEDTLS_ECP_DP_SECP192R1: - NIST_MODP( p192 ); - return( LOAD_GROUP( secp192r1 ) ); -#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) - case MBEDTLS_ECP_DP_SECP224R1: - NIST_MODP( p224 ); - return( LOAD_GROUP( secp224r1 ) ); -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) - case MBEDTLS_ECP_DP_SECP256R1: - NIST_MODP( p256 ); - return( LOAD_GROUP( secp256r1 ) ); -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) - case MBEDTLS_ECP_DP_SECP384R1: - NIST_MODP( p384 ); - return( LOAD_GROUP( secp384r1 ) ); -#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) - case MBEDTLS_ECP_DP_SECP521R1: - NIST_MODP( p521 ); - return( LOAD_GROUP( secp521r1 ) ); -#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) - case MBEDTLS_ECP_DP_SECP192K1: - grp->modp = ecp_mod_p192k1; - return( LOAD_GROUP_A( secp192k1 ) ); -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) - case MBEDTLS_ECP_DP_SECP224K1: - grp->modp = ecp_mod_p224k1; - return( LOAD_GROUP_A( secp224k1 ) ); -#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) - case MBEDTLS_ECP_DP_SECP256K1: - grp->modp = ecp_mod_p256k1; - return( LOAD_GROUP_A( secp256k1 ) ); -#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) - case MBEDTLS_ECP_DP_BP256R1: - return( LOAD_GROUP_A( brainpoolP256r1 ) ); -#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) - case MBEDTLS_ECP_DP_BP384R1: - return( LOAD_GROUP_A( brainpoolP384r1 ) ); -#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) - case MBEDTLS_ECP_DP_BP512R1: - return( LOAD_GROUP_A( brainpoolP512r1 ) ); -#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) - case MBEDTLS_ECP_DP_CURVE25519: - grp->modp = ecp_mod_p255; - return( ecp_use_curve25519( grp ) ); -#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ - - default: - mbedtls_ecp_group_free( grp ); - return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); - } -} - -#if defined(MBEDTLS_ECP_NIST_OPTIM) -/* - * Fast reduction modulo the primes used by the NIST curves. - * - * These functions are critical for speed, but not needed for correct - * operations. So, we make the choice to heavily rely on the internals of our - * bignum library, which creates a tight coupling between these functions and - * our MPI implementation. However, the coupling between the ECP module and - * MPI remains loose, since these functions can be deactivated at will. - */ - -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) -/* - * Compared to the way things are presented in FIPS 186-3 D.2, - * we proceed in columns, from right (least significant chunk) to left, - * adding chunks to N in place, and keeping a carry for the next chunk. - * This avoids moving things around in memory, and uselessly adding zeros, - * compared to the more straightforward, line-oriented approach. - * - * For this prime we need to handle data in chunks of 64 bits. - * Since this is always a multiple of our basic mbedtls_mpi_uint, we can - * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it. - */ - -/* Add 64-bit chunks (dst += src) and update carry */ -static inline void add64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry ) -{ - unsigned char i; - mbedtls_mpi_uint c = 0; - for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++, src++ ) - { - *dst += c; c = ( *dst < c ); - *dst += *src; c += ( *dst < *src ); - } - *carry += c; -} - -/* Add carry to a 64-bit chunk and update carry */ -static inline void carry64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry ) -{ - unsigned char i; - for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++ ) - { - *dst += *carry; - *carry = ( *dst < *carry ); - } -} - -#define WIDTH 8 / sizeof( mbedtls_mpi_uint ) -#define A( i ) N->p + i * WIDTH -#define ADD( i ) add64( p, A( i ), &c ) -#define NEXT p += WIDTH; carry64( p, &c ) -#define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0 - -/* - * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) - */ -static int ecp_mod_p192( mbedtls_mpi *N ) -{ - int ret; - mbedtls_mpi_uint c = 0; - mbedtls_mpi_uint *p, *end; - - /* Make sure we have enough blocks so that A(5) is legal */ - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, 6 * WIDTH ) ); - - p = N->p; - end = p + N->n; - - ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5 - ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5 - ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5 - -cleanup: - return( ret ); -} - -#undef WIDTH -#undef A -#undef ADD -#undef NEXT -#undef LAST -#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) -/* - * The reader is advised to first understand ecp_mod_p192() since the same - * general structure is used here, but with additional complications: - * (1) chunks of 32 bits, and (2) subtractions. - */ - -/* - * For these primes, we need to handle data in chunks of 32 bits. - * This makes it more complicated if we use 64 bits limbs in MPI, - * which prevents us from using a uniform access method as for p192. - * - * So, we define a mini abstraction layer to access 32 bit chunks, - * load them in 'cur' for work, and store them back from 'cur' when done. - * - * While at it, also define the size of N in terms of 32-bit chunks. - */ -#define LOAD32 cur = A( i ); - -#if defined(MBEDTLS_HAVE_INT32) /* 32 bit */ - -#define MAX32 N->n -#define A( j ) N->p[j] -#define STORE32 N->p[i] = cur; - -#else /* 64-bit */ - -#define MAX32 N->n * 2 -#define A( j ) j % 2 ? (uint32_t)( N->p[j/2] >> 32 ) : (uint32_t)( N->p[j/2] ) -#define STORE32 \ - if( i % 2 ) { \ - N->p[i/2] &= 0x00000000FFFFFFFF; \ - N->p[i/2] |= ((mbedtls_mpi_uint) cur) << 32; \ - } else { \ - N->p[i/2] &= 0xFFFFFFFF00000000; \ - N->p[i/2] |= (mbedtls_mpi_uint) cur; \ - } - -#endif /* sizeof( mbedtls_mpi_uint ) */ - -/* - * Helpers for addition and subtraction of chunks, with signed carry. - */ -static inline void add32( uint32_t *dst, uint32_t src, signed char *carry ) -{ - *dst += src; - *carry += ( *dst < src ); -} - -static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry ) -{ - *carry -= ( *dst < src ); - *dst -= src; -} - -#define ADD( j ) add32( &cur, A( j ), &c ); -#define SUB( j ) sub32( &cur, A( j ), &c ); - -/* - * Helpers for the main 'loop' - * (see fix_negative for the motivation of C) - */ -#define INIT( b ) \ - int ret; \ - signed char c = 0, cc; \ - uint32_t cur; \ - size_t i = 0, bits = b; \ - mbedtls_mpi C; \ - mbedtls_mpi_uint Cp[ b / 8 / sizeof( mbedtls_mpi_uint) + 1 ]; \ - \ - C.s = 1; \ - C.n = b / 8 / sizeof( mbedtls_mpi_uint) + 1; \ - C.p = Cp; \ - memset( Cp, 0, C.n * sizeof( mbedtls_mpi_uint ) ); \ - \ - MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, b * 2 / 8 / sizeof( mbedtls_mpi_uint ) ) ); \ - LOAD32; - -#define NEXT \ - STORE32; i++; LOAD32; \ - cc = c; c = 0; \ - if( cc < 0 ) \ - sub32( &cur, -cc, &c ); \ - else \ - add32( &cur, cc, &c ); \ - -#define LAST \ - STORE32; i++; \ - cur = c > 0 ? c : 0; STORE32; \ - cur = 0; while( ++i < MAX32 ) { STORE32; } \ - if( c < 0 ) fix_negative( N, c, &C, bits ); - -/* - * If the result is negative, we get it in the form - * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits' - */ -static inline int fix_negative( mbedtls_mpi *N, signed char c, mbedtls_mpi *C, size_t bits ) -{ - int ret; - - /* C = - c * 2^(bits + 32) */ -#if !defined(MBEDTLS_HAVE_INT64) - ((void) bits); -#else - if( bits == 224 ) - C->p[ C->n - 1 ] = ((mbedtls_mpi_uint) -c) << 32; - else -#endif - C->p[ C->n - 1 ] = (mbedtls_mpi_uint) -c; - - /* N = - ( C - N ) */ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, C, N ) ); - N->s = -1; - -cleanup: - - return( ret ); -} - -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) -/* - * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) - */ -static int ecp_mod_p224( mbedtls_mpi *N ) -{ - INIT( 224 ); - - SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11 - SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12 - SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13 - SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11 - SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12 - SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13 - SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10 - -cleanup: - return( ret ); -} -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) -/* - * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) - */ -static int ecp_mod_p256( mbedtls_mpi *N ) -{ - INIT( 256 ); - - ADD( 8 ); ADD( 9 ); - SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0 - - ADD( 9 ); ADD( 10 ); - SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1 - - ADD( 10 ); ADD( 11 ); - SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2 - - ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 ); - SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3 - - ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 ); - SUB( 9 ); SUB( 10 ); NEXT; // A4 - - ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 ); - SUB( 10 ); SUB( 11 ); NEXT; // A5 - - ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 ); - SUB( 8 ); SUB( 9 ); NEXT; // A6 - - ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 ); - SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7 - -cleanup: - return( ret ); -} -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) -/* - * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) - */ -static int ecp_mod_p384( mbedtls_mpi *N ) -{ - INIT( 384 ); - - ADD( 12 ); ADD( 21 ); ADD( 20 ); - SUB( 23 ); NEXT; // A0 - - ADD( 13 ); ADD( 22 ); ADD( 23 ); - SUB( 12 ); SUB( 20 ); NEXT; // A2 - - ADD( 14 ); ADD( 23 ); - SUB( 13 ); SUB( 21 ); NEXT; // A2 - - ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 ); - SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3 - - ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 ); - SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4 - - ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 ); - SUB( 16 ); NEXT; // A5 - - ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 ); - SUB( 17 ); NEXT; // A6 - - ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 ); - SUB( 18 ); NEXT; // A7 - - ADD( 20 ); ADD( 17 ); ADD( 16 ); - SUB( 19 ); NEXT; // A8 - - ADD( 21 ); ADD( 18 ); ADD( 17 ); - SUB( 20 ); NEXT; // A9 - - ADD( 22 ); ADD( 19 ); ADD( 18 ); - SUB( 21 ); NEXT; // A10 - - ADD( 23 ); ADD( 20 ); ADD( 19 ); - SUB( 22 ); LAST; // A11 - -cleanup: - return( ret ); -} -#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ - -#undef A -#undef LOAD32 -#undef STORE32 -#undef MAX32 -#undef INIT -#undef NEXT -#undef LAST - -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || - MBEDTLS_ECP_DP_SECP256R1_ENABLED || - MBEDTLS_ECP_DP_SECP384R1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) -/* - * Here we have an actual Mersenne prime, so things are more straightforward. - * However, chunks are aligned on a 'weird' boundary (521 bits). - */ - -/* Size of p521 in terms of mbedtls_mpi_uint */ -#define P521_WIDTH ( 521 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) - -/* Bits to keep in the most significant mbedtls_mpi_uint */ -#define P521_MASK 0x01FF - -/* - * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5) - * Write N as A1 + 2^521 A0, return A0 + A1 - */ -static int ecp_mod_p521( mbedtls_mpi *N ) -{ - int ret; - size_t i; - mbedtls_mpi M; - mbedtls_mpi_uint Mp[P521_WIDTH + 1]; - /* Worst case for the size of M is when mbedtls_mpi_uint is 16 bits: - * we need to hold bits 513 to 1056, which is 34 limbs, that is - * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */ - - if( N->n < P521_WIDTH ) - return( 0 ); - - /* M = A1 */ - M.s = 1; - M.n = N->n - ( P521_WIDTH - 1 ); - if( M.n > P521_WIDTH + 1 ) - M.n = P521_WIDTH + 1; - M.p = Mp; - memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 521 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); - - /* N = A0 */ - N->p[P521_WIDTH - 1] &= P521_MASK; - for( i = P521_WIDTH; i < N->n; i++ ) - N->p[i] = 0; - - /* N = A0 + A1 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); - -cleanup: - return( ret ); -} - -#undef P521_WIDTH -#undef P521_MASK -#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ - -#endif /* MBEDTLS_ECP_NIST_OPTIM */ - -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) - -/* Size of p255 in terms of mbedtls_mpi_uint */ -#define P255_WIDTH ( 255 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) - -/* - * Fast quasi-reduction modulo p255 = 2^255 - 19 - * Write N as A0 + 2^255 A1, return A0 + 19 * A1 - */ -static int ecp_mod_p255( mbedtls_mpi *N ) -{ - int ret; - size_t i; - mbedtls_mpi M; - mbedtls_mpi_uint Mp[P255_WIDTH + 2]; - - if( N->n < P255_WIDTH ) - return( 0 ); - - /* M = A1 */ - M.s = 1; - M.n = N->n - ( P255_WIDTH - 1 ); - if( M.n > P255_WIDTH + 1 ) - M.n = P255_WIDTH + 1; - M.p = Mp; - memset( Mp, 0, sizeof Mp ); - memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 255 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); - M.n++; /* Make room for multiplication by 19 */ - - /* N = A0 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( N, 255, 0 ) ); - for( i = P255_WIDTH; i < N->n; i++ ) - N->p[i] = 0; - - /* N = A0 + 19 * A1 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &M, 19 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); - -cleanup: - return( ret ); -} -#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ - defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -/* - * Fast quasi-reduction modulo P = 2^s - R, - * with R about 33 bits, used by the Koblitz curves. - * - * Write N as A0 + 2^224 A1, return A0 + R * A1. - * Actually do two passes, since R is big. - */ -#define P_KOBLITZ_MAX ( 256 / 8 / sizeof( mbedtls_mpi_uint ) ) // Max limbs in P -#define P_KOBLITZ_R ( 8 / sizeof( mbedtls_mpi_uint ) ) // Limbs in R -static inline int ecp_mod_koblitz( mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs, - size_t adjust, size_t shift, mbedtls_mpi_uint mask ) -{ - int ret; - size_t i; - mbedtls_mpi M, R; - mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1]; - - if( N->n < p_limbs ) - return( 0 ); - - /* Init R */ - R.s = 1; - R.p = Rp; - R.n = P_KOBLITZ_R; - - /* Common setup for M */ - M.s = 1; - M.p = Mp; - - /* M = A1 */ - M.n = N->n - ( p_limbs - adjust ); - if( M.n > p_limbs + adjust ) - M.n = p_limbs + adjust; - memset( Mp, 0, sizeof Mp ); - memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); - if( shift != 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); - M.n += R.n; /* Make room for multiplication by R */ - - /* N = A0 */ - if( mask != 0 ) - N->p[p_limbs - 1] &= mask; - for( i = p_limbs; i < N->n; i++ ) - N->p[i] = 0; - - /* N = A0 + R * A1 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); - - /* Second pass */ - - /* M = A1 */ - M.n = N->n - ( p_limbs - adjust ); - if( M.n > p_limbs + adjust ) - M.n = p_limbs + adjust; - memset( Mp, 0, sizeof Mp ); - memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); - if( shift != 0 ) - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); - M.n += R.n; /* Make room for multiplication by R */ - - /* N = A0 */ - if( mask != 0 ) - N->p[p_limbs - 1] &= mask; - for( i = p_limbs; i < N->n; i++ ) - N->p[i] = 0; - - /* N = A0 + R * A1 */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); - -cleanup: - return( ret ); -} -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || - MBEDTLS_ECP_DP_SECP224K1_ENABLED) || - MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ - -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) -/* - * Fast quasi-reduction modulo p192k1 = 2^192 - R, - * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119 - */ -static int ecp_mod_p192k1( mbedtls_mpi *N ) -{ - static mbedtls_mpi_uint Rp[] = { - BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; - - return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); -} -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) -/* - * Fast quasi-reduction modulo p224k1 = 2^224 - R, - * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 - */ -static int ecp_mod_p224k1( mbedtls_mpi *N ) -{ - static mbedtls_mpi_uint Rp[] = { - BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; - -#if defined(MBEDTLS_HAVE_INT64) - return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) ); -#else - return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); -#endif -} - -#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ - -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) -/* - * Fast quasi-reduction modulo p256k1 = 2^256 - R, - * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 - */ -static int ecp_mod_p256k1( mbedtls_mpi *N ) -{ - static mbedtls_mpi_uint Rp[] = { - BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; - return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); -} -#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ - -#endif /* !MBEDTLS_ECP_ALT */ - -#endif /* MBEDTLS_ECP_C */ diff --git a/components/mbedtls/library/entropy.c b/components/mbedtls/library/entropy.c deleted file mode 100644 index 23de4062a4..0000000000 --- a/components/mbedtls/library/entropy.c +++ /dev/null @@ -1,655 +0,0 @@ -/* - * Entropy accumulator implementation - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_ENTROPY_C) - -#if defined(MBEDTLS_TEST_NULL_ENTROPY) -#warning "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined! " -#warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES " -#warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE " -#endif - -#include "mbedtls/entropy.h" -#include "mbedtls/entropy_poll.h" - -#include - -#if defined(MBEDTLS_FS_IO) -#include -#endif - -#if defined(MBEDTLS_ENTROPY_NV_SEED) -#include "mbedtls/platform.h" -#endif - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if defined(MBEDTLS_HAVEGE_C) -#include "mbedtls/havege.h" -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ - -void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) -{ - memset( ctx, 0, sizeof(mbedtls_entropy_context) ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif - -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - mbedtls_sha512_starts( &ctx->accumulator, 0 ); -#else - mbedtls_sha256_starts( &ctx->accumulator, 0 ); -#endif -#if defined(MBEDTLS_HAVEGE_C) - mbedtls_havege_init( &ctx->havege_data ); -#endif - -#if defined(MBEDTLS_TEST_NULL_ENTROPY) - mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL, - 1, MBEDTLS_ENTROPY_SOURCE_STRONG ); -#endif - -#if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) -#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) - mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL, - MBEDTLS_ENTROPY_MIN_PLATFORM, - MBEDTLS_ENTROPY_SOURCE_STRONG ); -#endif -#if defined(MBEDTLS_TIMING_C) - mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL, - MBEDTLS_ENTROPY_MIN_HARDCLOCK, - MBEDTLS_ENTROPY_SOURCE_WEAK ); -#endif -#if defined(MBEDTLS_HAVEGE_C) - mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data, - MBEDTLS_ENTROPY_MIN_HAVEGE, - MBEDTLS_ENTROPY_SOURCE_STRONG ); -#endif -#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) - mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL, - MBEDTLS_ENTROPY_MIN_HARDWARE, - MBEDTLS_ENTROPY_SOURCE_STRONG ); -#endif -#if defined(MBEDTLS_ENTROPY_NV_SEED) - mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, - MBEDTLS_ENTROPY_BLOCK_SIZE, - MBEDTLS_ENTROPY_SOURCE_STRONG ); -#endif -#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ -} - -void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) -{ -#if defined(MBEDTLS_HAVEGE_C) - mbedtls_havege_free( &ctx->havege_data ); -#endif -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); -#endif - mbedtls_zeroize( ctx, sizeof( mbedtls_entropy_context ) ); -} - -int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, - mbedtls_entropy_f_source_ptr f_source, void *p_source, - size_t threshold, int strong ) -{ - int idx, ret = 0; - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - idx = ctx->source_count; - if( idx >= MBEDTLS_ENTROPY_MAX_SOURCES ) - { - ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; - goto exit; - } - - ctx->source[idx].f_source = f_source; - ctx->source[idx].p_source = p_source; - ctx->source[idx].threshold = threshold; - ctx->source[idx].strong = strong; - - ctx->source_count++; - -exit: -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -/* - * Entropy accumulator update - */ -static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id, - const unsigned char *data, size_t len ) -{ - unsigned char header[2]; - unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; - size_t use_len = len; - const unsigned char *p = data; - - if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) - { -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - mbedtls_sha512( data, len, tmp, 0 ); -#else - mbedtls_sha256( data, len, tmp, 0 ); -#endif - p = tmp; - use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; - } - - header[0] = source_id; - header[1] = use_len & 0xFF; - -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - mbedtls_sha512_update( &ctx->accumulator, header, 2 ); - mbedtls_sha512_update( &ctx->accumulator, p, use_len ); -#else - mbedtls_sha256_update( &ctx->accumulator, header, 2 ); - mbedtls_sha256_update( &ctx->accumulator, p, use_len ); -#endif - - return( 0 ); -} - -int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, - const unsigned char *data, size_t len ) -{ - int ret; - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len ); - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -/* - * Run through the different sources to add entropy to our accumulator - */ -static int entropy_gather_internal( mbedtls_entropy_context *ctx ) -{ - int ret, i, have_one_strong = 0; - unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER]; - size_t olen; - - if( ctx->source_count == 0 ) - return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED ); - - /* - * Run through our entropy sources - */ - for( i = 0; i < ctx->source_count; i++ ) - { - if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG ) - have_one_strong = 1; - - olen = 0; - if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, - buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 ) - { - return( ret ); - } - - /* - * Add if we actually gathered something - */ - if( olen > 0 ) - { - entropy_update( ctx, (unsigned char) i, buf, olen ); - ctx->source[i].size += olen; - } - } - - if( have_one_strong == 0 ) - return( MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE ); - - return( 0 ); -} - -/* - * Thread-safe wrapper for entropy_gather_internal() - */ -int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ) -{ - int ret; - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - ret = entropy_gather_internal( ctx ); - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) -{ - int ret, count = 0, i, done; - mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; - unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; - - if( len > MBEDTLS_ENTROPY_BLOCK_SIZE ) - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - -#if defined(MBEDTLS_ENTROPY_NV_SEED) - /* Update the NV entropy seed before generating any entropy for outside - * use. - */ - if( ctx->initial_entropy_run == 0 ) - { - ctx->initial_entropy_run = 1; - if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 ) - return( ret ); - } -#endif - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - /* - * Always gather extra entropy before a call - */ - do - { - if( count++ > ENTROPY_MAX_LOOP ) - { - ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; - goto exit; - } - - if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) - goto exit; - - done = 1; - for( i = 0; i < ctx->source_count; i++ ) - if( ctx->source[i].size < ctx->source[i].threshold ) - done = 0; - } - while( ! done ); - - memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); - -#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) - mbedtls_sha512_finish( &ctx->accumulator, buf ); - - /* - * Reset accumulator and counters and recycle existing entropy - */ - memset( &ctx->accumulator, 0, sizeof( mbedtls_sha512_context ) ); - mbedtls_sha512_starts( &ctx->accumulator, 0 ); - mbedtls_sha512_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); - - /* - * Perform second SHA-512 on entropy - */ - mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); -#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ - mbedtls_sha256_finish( &ctx->accumulator, buf ); - - /* - * Reset accumulator and counters and recycle existing entropy - */ - memset( &ctx->accumulator, 0, sizeof( mbedtls_sha256_context ) ); - mbedtls_sha256_starts( &ctx->accumulator, 0 ); - mbedtls_sha256_update( &ctx->accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); - - /* - * Perform second SHA-256 on entropy - */ - mbedtls_sha256( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0 ); -#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ - - for( i = 0; i < ctx->source_count; i++ ) - ctx->source[i].size = 0; - - memcpy( output, buf, len ); - - ret = 0; - -exit: -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -#if defined(MBEDTLS_ENTROPY_NV_SEED) -int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ) -{ - int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; - unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; - - /* Read new seed and write it to NV */ - if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) - return( ret ); - - if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) - return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); - - /* Manually update the remaining stream with a separator value to diverge */ - memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); - mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); - - return( 0 ); -} -#endif /* MBEDTLS_ENTROPY_NV_SEED */ - -#if defined(MBEDTLS_FS_IO) -int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ) -{ - int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; - FILE *f; - unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; - - if( ( f = fopen( path, "wb" ) ) == NULL ) - return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); - - if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) - goto exit; - - if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE ) - { - ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; - goto exit; - } - - ret = 0; - -exit: - fclose( f ); - return( ret ); -} - -int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ) -{ - FILE *f; - size_t n; - unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); - - fseek( f, 0, SEEK_END ); - n = (size_t) ftell( f ); - fseek( f, 0, SEEK_SET ); - - if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) - n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; - - if( fread( buf, 1, n, f ) != n ) - { - fclose( f ); - return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); - } - - fclose( f ); - - mbedtls_entropy_update_manual( ctx, buf, n ); - - return( mbedtls_entropy_write_seed_file( ctx, path ) ); -} -#endif /* MBEDTLS_FS_IO */ - -#if defined(MBEDTLS_SELF_TEST) -#if !defined(MBEDTLS_TEST_NULL_ENTROPY) -/* - * Dummy source function - */ -static int entropy_dummy_source( void *data, unsigned char *output, - size_t len, size_t *olen ) -{ - ((void) data); - - memset( output, 0x2a, len ); - *olen = len; - - return( 0 ); -} -#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ - -#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) - -static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len ) -{ - int ret = 0; - size_t entropy_len = 0; - size_t olen = 0; - size_t attempts = buf_len; - - while( attempts > 0 && entropy_len < buf_len ) - { - if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len, - buf_len - entropy_len, &olen ) ) != 0 ) - return( ret ); - - entropy_len += olen; - attempts--; - } - - if( entropy_len < buf_len ) - { - ret = 1; - } - - return( ret ); -} - - -static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf, - size_t buf_len ) -{ - unsigned char set= 0xFF; - unsigned char unset = 0x00; - size_t i; - - for( i = 0; i < buf_len; i++ ) - { - set &= buf[i]; - unset |= buf[i]; - } - - return( set == 0xFF || unset == 0x00 ); -} - -/* - * A test to ensure hat the entropy sources are functioning correctly - * and there is no obvious failure. The test performs the following checks: - * - The entropy source is not providing only 0s (all bits unset) or 1s (all - * bits set). - * - The entropy source is not providing values in a pattern. Because the - * hardware could be providing data in an arbitrary length, this check polls - * the hardware entropy source twice and compares the result to ensure they - * are not equal. - * - The error code returned by the entropy source is not an error. - */ -int mbedtls_entropy_source_self_test( int verbose ) -{ - int ret = 0; - unsigned char buf0[2 * sizeof( unsigned long long int )]; - unsigned char buf1[2 * sizeof( unsigned long long int )]; - - if( verbose != 0 ) - mbedtls_printf( " ENTROPY_BIAS test: " ); - - memset( buf0, 0x00, sizeof( buf0 ) ); - memset( buf1, 0x00, sizeof( buf1 ) ); - - if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 ) - goto cleanup; - if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 ) - goto cleanup; - - /* Make sure that the returned values are not all 0 or 1 */ - if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 ) - goto cleanup; - if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 ) - goto cleanup; - - /* Make sure that the entropy source is not returning values in a - * pattern */ - ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0; - -cleanup: - if( verbose != 0 ) - { - if( ret != 0 ) - mbedtls_printf( "failed\n" ); - else - mbedtls_printf( "passed\n" ); - - mbedtls_printf( "\n" ); - } - - return( ret != 0 ); -} - -#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ - -/* - * The actual entropy quality is hard to test, but we can at least - * test that the functions don't cause errors and write the correct - * amount of data to buffers. - */ -int mbedtls_entropy_self_test( int verbose ) -{ - int ret = 1; -#if !defined(MBEDTLS_TEST_NULL_ENTROPY) - mbedtls_entropy_context ctx; - unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; - unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; - size_t i, j; -#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ - - if( verbose != 0 ) - mbedtls_printf( " ENTROPY test: " ); - -#if !defined(MBEDTLS_TEST_NULL_ENTROPY) - mbedtls_entropy_init( &ctx ); - - /* First do a gather to make sure we have default sources */ - if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 ) - goto cleanup; - - ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16, - MBEDTLS_ENTROPY_SOURCE_WEAK ); - if( ret != 0 ) - goto cleanup; - - if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) - goto cleanup; - - /* - * To test that mbedtls_entropy_func writes correct number of bytes: - * - use the whole buffer and rely on ASan to detect overruns - * - collect entropy 8 times and OR the result in an accumulator: - * any byte should then be 0 with probably 2^(-64), so requiring - * each of the 32 or 64 bytes to be non-zero has a false failure rate - * of at most 2^(-58) which is acceptable. - */ - for( i = 0; i < 8; i++ ) - { - if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 ) - goto cleanup; - - for( j = 0; j < sizeof( buf ); j++ ) - acc[j] |= buf[j]; - } - - for( j = 0; j < sizeof( buf ); j++ ) - { - if( acc[j] == 0 ) - { - ret = 1; - goto cleanup; - } - } - -#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) - if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 ) - goto cleanup; -#endif - -cleanup: - mbedtls_entropy_free( &ctx ); -#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ - - if( verbose != 0 ) - { - if( ret != 0 ) - mbedtls_printf( "failed\n" ); - else - mbedtls_printf( "passed\n" ); - - mbedtls_printf( "\n" ); - } - - return( ret != 0 ); -} -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_ENTROPY_C */ diff --git a/components/mbedtls/library/entropy_poll.c b/components/mbedtls/library/entropy_poll.c deleted file mode 100644 index a116e605d2..0000000000 --- a/components/mbedtls/library/entropy_poll.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Platform-specific and custom entropy polling functions - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_ENTROPY_C) - -#include "mbedtls/entropy.h" -#include "mbedtls/entropy_poll.h" - -#if defined(MBEDTLS_TIMING_C) -#include -#include "mbedtls/timing.h" -#endif -#if defined(MBEDTLS_HAVEGE_C) -#include "mbedtls/havege.h" -#endif -#if defined(MBEDTLS_ENTROPY_NV_SEED) -#include "mbedtls/platform.h" -#endif - -#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) - -#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ - !defined(__APPLE__) && !defined(_WIN32) -#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" -#endif - -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) - -#if !defined(_WIN32_WINNT) -#define _WIN32_WINNT 0x0400 -#endif -#include -#include - -int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len, - size_t *olen ) -{ - HCRYPTPROV provider; - ((void) data); - *olen = 0; - - if( CryptAcquireContext( &provider, NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) - { - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - } - - if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE ) - { - CryptReleaseContext( provider, 0 ); - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - } - - CryptReleaseContext( provider, 0 ); - *olen = len; - - return( 0 ); -} -#else /* _WIN32 && !EFIX64 && !EFI32 */ - -/* - * Test for Linux getrandom() support. - * Since there is no wrapper in the libc yet, use the generic syscall wrapper - * available in GNU libc and compatible libc's (eg uClibc). - */ -#if defined(__linux__) && defined(__GLIBC__) -#include -#include -#if defined(SYS_getrandom) -#define HAVE_GETRANDOM - -static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) -{ - /* MemSan cannot understand that the syscall writes to the buffer */ -#if defined(__has_feature) -#if __has_feature(memory_sanitizer) - memset( buf, 0, buflen ); -#endif -#endif - - return( syscall( SYS_getrandom, buf, buflen, flags ) ); -} - -#include -/* Check if version is at least 3.17.0 */ -static int check_version_3_17_plus( void ) -{ - int minor; - struct utsname un; - const char *ver; - - /* Get version information */ - uname(&un); - ver = un.release; - - /* Check major version; assume a single digit */ - if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' ) - return( -1 ); - - if( ver[0] - '0' > 3 ) - return( 0 ); - - /* Ok, so now we know major == 3, check minor. - * Assume 1 or 2 digits. */ - if( ver[2] < '0' || ver[2] > '9' ) - return( -1 ); - - minor = ver[2] - '0'; - - if( ver[3] >= '0' && ver[3] <= '9' ) - minor = 10 * minor + ver[3] - '0'; - else if( ver [3] != '.' ) - return( -1 ); - - if( minor < 17 ) - return( -1 ); - - return( 0 ); -} -static int has_getrandom = -1; -#endif /* SYS_getrandom */ -#endif /* __linux__ */ - -#include - -int mbedtls_platform_entropy_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - FILE *file; - size_t read_len; - ((void) data); - -#if defined(HAVE_GETRANDOM) - if( has_getrandom == -1 ) - has_getrandom = ( check_version_3_17_plus() == 0 ); - - if( has_getrandom ) - { - int ret; - - if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 ) - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - - *olen = ret; - return( 0 ); - } -#endif /* HAVE_GETRANDOM */ - - *olen = 0; - - file = fopen( "/dev/urandom", "rb" ); - if( file == NULL ) - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - - read_len = fread( output, 1, len, file ); - if( read_len != len ) - { - fclose( file ); - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - } - - fclose( file ); - *olen = len; - - return( 0 ); -} -#endif /* _WIN32 && !EFIX64 && !EFI32 */ -#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ - -#if defined(MBEDTLS_TEST_NULL_ENTROPY) -int mbedtls_null_entropy_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - ((void) data); - ((void) output); - *olen = 0; - - if( len < sizeof(unsigned char) ) - return( 0 ); - - *olen = sizeof(unsigned char); - - return( 0 ); -} -#endif - -#if defined(MBEDTLS_TIMING_C) -int mbedtls_hardclock_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - unsigned long timer = mbedtls_timing_hardclock(); - ((void) data); - *olen = 0; - - if( len < sizeof(unsigned long) ) - return( 0 ); - - memcpy( output, &timer, sizeof(unsigned long) ); - *olen = sizeof(unsigned long); - - return( 0 ); -} -#endif /* MBEDTLS_TIMING_C */ - -#if defined(MBEDTLS_HAVEGE_C) -int mbedtls_havege_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - mbedtls_havege_state *hs = (mbedtls_havege_state *) data; - *olen = 0; - - if( mbedtls_havege_random( hs, output, len ) != 0 ) - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - - *olen = len; - - return( 0 ); -} -#endif /* MBEDTLS_HAVEGE_C */ - -#if defined(MBEDTLS_ENTROPY_NV_SEED) -int mbedtls_nv_seed_poll( void *data, - unsigned char *output, size_t len, size_t *olen ) -{ - unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; - size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; - ((void) data); - - memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); - - if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) - return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); - - if( len < use_len ) - use_len = len; - - memcpy( output, buf, use_len ); - *olen = use_len; - - return( 0 ); -} -#endif /* MBEDTLS_ENTROPY_NV_SEED */ - -#endif /* MBEDTLS_ENTROPY_C */ diff --git a/components/mbedtls/library/error.c b/components/mbedtls/library/error.c deleted file mode 100644 index db42381c42..0000000000 --- a/components/mbedtls/library/error.c +++ /dev/null @@ -1,709 +0,0 @@ -/* - * Error message information - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) -#include "mbedtls/error.h" -#include -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#define mbedtls_snprintf snprintf -#define mbedtls_time_t time_t -#endif - -#if defined(MBEDTLS_ERROR_C) - -#include - -#if defined(MBEDTLS_AES_C) -#include "mbedtls/aes.h" -#endif - -#if defined(MBEDTLS_BASE64_C) -#include "mbedtls/base64.h" -#endif - -#if defined(MBEDTLS_BIGNUM_C) -#include "mbedtls/bignum.h" -#endif - -#if defined(MBEDTLS_BLOWFISH_C) -#include "mbedtls/blowfish.h" -#endif - -#if defined(MBEDTLS_CAMELLIA_C) -#include "mbedtls/camellia.h" -#endif - -#if defined(MBEDTLS_CCM_C) -#include "mbedtls/ccm.h" -#endif - -#if defined(MBEDTLS_CIPHER_C) -#include "mbedtls/cipher.h" -#endif - -#if defined(MBEDTLS_CTR_DRBG_C) -#include "mbedtls/ctr_drbg.h" -#endif - -#if defined(MBEDTLS_DES_C) -#include "mbedtls/des.h" -#endif - -#if defined(MBEDTLS_DHM_C) -#include "mbedtls/dhm.h" -#endif - -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif - -#if defined(MBEDTLS_ENTROPY_C) -#include "mbedtls/entropy.h" -#endif - -#if defined(MBEDTLS_GCM_C) -#include "mbedtls/gcm.h" -#endif - -#if defined(MBEDTLS_HMAC_DRBG_C) -#include "mbedtls/hmac_drbg.h" -#endif - -#if defined(MBEDTLS_MD_C) -#include "mbedtls/md.h" -#endif - -#if defined(MBEDTLS_NET_C) -#include "mbedtls/net_sockets.h" -#endif - -#if defined(MBEDTLS_OID_C) -#include "mbedtls/oid.h" -#endif - -#if defined(MBEDTLS_PADLOCK_C) -#include "mbedtls/padlock.h" -#endif - -#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_PK_C) -#include "mbedtls/pk.h" -#endif - -#if defined(MBEDTLS_PKCS12_C) -#include "mbedtls/pkcs12.h" -#endif - -#if defined(MBEDTLS_PKCS5_C) -#include "mbedtls/pkcs5.h" -#endif - -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif - -#if defined(MBEDTLS_SSL_TLS_C) -#include "mbedtls/ssl.h" -#endif - -#if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" -#endif - -#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) -#include "mbedtls/x509.h" -#endif - -#if defined(MBEDTLS_XTEA_C) -#include "mbedtls/xtea.h" -#endif - - -void mbedtls_strerror( int ret, char *buf, size_t buflen ) -{ - size_t len; - int use_ret; - - if( buflen == 0 ) - return; - - memset( buf, 0x00, buflen ); - - if( ret < 0 ) - ret = -ret; - - if( ret & 0xFF80 ) - { - use_ret = ret & 0xFF80; - - // High level error codes - // - // BEGIN generated code -#if defined(MBEDTLS_CIPHER_C) - if( use_ret == -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "CIPHER - The selected feature is not available" ); - if( use_ret == -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "CIPHER - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "CIPHER - Failed to allocate memory" ); - if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_PADDING) ) - mbedtls_snprintf( buf, buflen, "CIPHER - Input data contains invalid padding and is rejected" ); - if( use_ret == -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED) ) - mbedtls_snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" ); - if( use_ret == -(MBEDTLS_ERR_CIPHER_AUTH_FAILED) ) - mbedtls_snprintf( buf, buflen, "CIPHER - Authentication failed (for AEAD modes)" ); - if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT) ) - mbedtls_snprintf( buf, buflen, "CIPHER - The context is invalid, eg because it was free()ed" ); -#endif /* MBEDTLS_CIPHER_C */ - -#if defined(MBEDTLS_DHM_C) - if( use_ret == -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "DHM - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED) ) - mbedtls_snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" ); - if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) ) - mbedtls_snprintf( buf, buflen, "DHM - Making of the DHM parameters failed" ); - if( use_ret == -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED) ) - mbedtls_snprintf( buf, buflen, "DHM - Reading of the public values failed" ); - if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED) ) - mbedtls_snprintf( buf, buflen, "DHM - Making of the public value failed" ); - if( use_ret == -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED) ) - mbedtls_snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" ); - if( use_ret == -(MBEDTLS_ERR_DHM_INVALID_FORMAT) ) - mbedtls_snprintf( buf, buflen, "DHM - The ASN.1 data is not formatted correctly" ); - if( use_ret == -(MBEDTLS_ERR_DHM_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "DHM - Allocation of memory failed" ); - if( use_ret == -(MBEDTLS_ERR_DHM_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "DHM - Read/write of file failed" ); -#endif /* MBEDTLS_DHM_C */ - -#if defined(MBEDTLS_ECP_C) - if( use_ret == -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "ECP - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) ) - mbedtls_snprintf( buf, buflen, "ECP - The buffer is too small to write to" ); - if( use_ret == -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "ECP - Requested curve not available" ); - if( use_ret == -(MBEDTLS_ERR_ECP_VERIFY_FAILED) ) - mbedtls_snprintf( buf, buflen, "ECP - The signature is not valid" ); - if( use_ret == -(MBEDTLS_ERR_ECP_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "ECP - Memory allocation failed" ); - if( use_ret == -(MBEDTLS_ERR_ECP_RANDOM_FAILED) ) - mbedtls_snprintf( buf, buflen, "ECP - Generation of random value, such as (ephemeral) key, failed" ); - if( use_ret == -(MBEDTLS_ERR_ECP_INVALID_KEY) ) - mbedtls_snprintf( buf, buflen, "ECP - Invalid private or public key" ); - if( use_ret == -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "ECP - Signature is valid but shorter than the user-supplied length" ); -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_MD_C) - if( use_ret == -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "MD - The selected feature is not available" ); - if( use_ret == -(MBEDTLS_ERR_MD_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "MD - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_MD_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "MD - Failed to allocate memory" ); - if( use_ret == -(MBEDTLS_ERR_MD_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "MD - Opening or reading of file failed" ); -#endif /* MBEDTLS_MD_C */ - -#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) - if( use_ret == -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) ) - mbedtls_snprintf( buf, buflen, "PEM - No PEM header or footer found" ); - if( use_ret == -(MBEDTLS_ERR_PEM_INVALID_DATA) ) - mbedtls_snprintf( buf, buflen, "PEM - PEM string is not as expected" ); - if( use_ret == -(MBEDTLS_ERR_PEM_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "PEM - Failed to allocate memory" ); - if( use_ret == -(MBEDTLS_ERR_PEM_INVALID_ENC_IV) ) - mbedtls_snprintf( buf, buflen, "PEM - RSA IV is not in hex-format" ); - if( use_ret == -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG) ) - mbedtls_snprintf( buf, buflen, "PEM - Unsupported key encryption algorithm" ); - if( use_ret == -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) ) - mbedtls_snprintf( buf, buflen, "PEM - Private key password can't be empty" ); - if( use_ret == -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "PEM - Given private key password does not allow for correct decryption" ); - if( use_ret == -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" ); - if( use_ret == -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "PEM - Bad input parameters to function" ); -#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ - -#if defined(MBEDTLS_PK_C) - if( use_ret == -(MBEDTLS_ERR_PK_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "PK - Memory allocation failed" ); - if( use_ret == -(MBEDTLS_ERR_PK_TYPE_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" ); - if( use_ret == -(MBEDTLS_ERR_PK_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "PK - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_PK_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "PK - Read/write of file failed" ); - if( use_ret == -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION) ) - mbedtls_snprintf( buf, buflen, "PK - Unsupported key version" ); - if( use_ret == -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT) ) - mbedtls_snprintf( buf, buflen, "PK - Invalid key tag or value" ); - if( use_ret == -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG) ) - mbedtls_snprintf( buf, buflen, "PK - Key algorithm is unsupported (only RSA and EC are supported)" ); - if( use_ret == -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED) ) - mbedtls_snprintf( buf, buflen, "PK - Private key password can't be empty" ); - if( use_ret == -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "PK - Given private key password does not allow for correct decryption" ); - if( use_ret == -(MBEDTLS_ERR_PK_INVALID_PUBKEY) ) - mbedtls_snprintf( buf, buflen, "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" ); - if( use_ret == -(MBEDTLS_ERR_PK_INVALID_ALG) ) - mbedtls_snprintf( buf, buflen, "PK - The algorithm tag or value is invalid" ); - if( use_ret == -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE) ) - mbedtls_snprintf( buf, buflen, "PK - Elliptic curve is unsupported (only NIST curves are supported)" ); - if( use_ret == -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); - if( use_ret == -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "PK - The signature is valid but its length is less than expected" ); -#endif /* MBEDTLS_PK_C */ - -#if defined(MBEDTLS_PKCS12_C) - if( use_ret == -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "PKCS12 - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "PKCS12 - Feature not available, e.g. unsupported encryption scheme" ); - if( use_ret == -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT) ) - mbedtls_snprintf( buf, buflen, "PKCS12 - PBE ASN.1 data not as expected" ); - if( use_ret == -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "PKCS12 - Given private key password does not allow for correct decryption" ); -#endif /* MBEDTLS_PKCS12_C */ - -#if defined(MBEDTLS_PKCS5_C) - if( use_ret == -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "PKCS5 - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT) ) - mbedtls_snprintf( buf, buflen, "PKCS5 - Unexpected ASN.1 data" ); - if( use_ret == -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "PKCS5 - Requested encryption or digest alg not available" ); - if( use_ret == -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "PKCS5 - Given private key password does not allow for correct decryption" ); -#endif /* MBEDTLS_PKCS5_C */ - -#if defined(MBEDTLS_RSA_C) - if( use_ret == -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "RSA - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_RSA_INVALID_PADDING) ) - mbedtls_snprintf( buf, buflen, "RSA - Input data contains invalid padding and is rejected" ); - if( use_ret == -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED) ) - mbedtls_snprintf( buf, buflen, "RSA - Something failed during generation of a key" ); - if( use_ret == -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) ) - mbedtls_snprintf( buf, buflen, "RSA - Key failed to pass the library's validity check" ); - if( use_ret == -(MBEDTLS_ERR_RSA_PUBLIC_FAILED) ) - mbedtls_snprintf( buf, buflen, "RSA - The public key operation failed" ); - if( use_ret == -(MBEDTLS_ERR_RSA_PRIVATE_FAILED) ) - mbedtls_snprintf( buf, buflen, "RSA - The private key operation failed" ); - if( use_ret == -(MBEDTLS_ERR_RSA_VERIFY_FAILED) ) - mbedtls_snprintf( buf, buflen, "RSA - The PKCS#1 verification failed" ); - if( use_ret == -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE) ) - mbedtls_snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" ); - if( use_ret == -(MBEDTLS_ERR_RSA_RNG_FAILED) ) - mbedtls_snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" ); -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_SSL_TLS_C) - if( use_ret == -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "SSL - The requested feature is not available" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "SSL - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_MAC) ) - mbedtls_snprintf( buf, buflen, "SSL - Verification of the message MAC failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_RECORD) ) - mbedtls_snprintf( buf, buflen, "SSL - An invalid SSL record was received" ); - if( use_ret == -(MBEDTLS_ERR_SSL_CONN_EOF) ) - mbedtls_snprintf( buf, buflen, "SSL - The connection indicated an EOF" ); - if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER) ) - mbedtls_snprintf( buf, buflen, "SSL - An unknown cipher was received" ); - if( use_ret == -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN) ) - mbedtls_snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" ); - if( use_ret == -(MBEDTLS_ERR_SSL_NO_RNG) ) - mbedtls_snprintf( buf, buflen, "SSL - No RNG was provided to the SSL module" ); - if( use_ret == -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE) ) - mbedtls_snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" ); - if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE) ) - mbedtls_snprintf( buf, buflen, "SSL - Our own certificate(s) is/are too large to send in an SSL message" ); - if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED) ) - mbedtls_snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" ); - if( use_ret == -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) ) - mbedtls_snprintf( buf, buflen, "SSL - The own private key or pre-shared key is not set, but needed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED) ) - mbedtls_snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" ); - if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE) ) - mbedtls_snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" ); - if( use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE) ) - { - mbedtls_snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" ); - return; - } - if( use_ret == -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED) ) - mbedtls_snprintf( buf, buflen, "SSL - Verification of our peer failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) ) - mbedtls_snprintf( buf, buflen, "SSL - The peer notified us that the connection is going to be closed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "SSL - Memory allocation failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED) ) - mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function returned with error" ); - if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH) ) - mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function skipped / left alone data" ); - if( use_ret == -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the compression / decompression failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION) ) - mbedtls_snprintf( buf, buflen, "SSL - Handshake protocol not within min/max boundaries" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET) ) - mbedtls_snprintf( buf, buflen, "SSL - Processing of the NewSessionTicket handshake message failed" ); - if( use_ret == -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) ) - mbedtls_snprintf( buf, buflen, "SSL - Session ticket has expired" ); - if( use_ret == -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" ); - if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) ) - mbedtls_snprintf( buf, buflen, "SSL - Unknown identity received (eg, PSK identity)" ); - if( use_ret == -(MBEDTLS_ERR_SSL_INTERNAL_ERROR) ) - mbedtls_snprintf( buf, buflen, "SSL - Internal error (eg, unexpected failure in lower-level module)" ); - if( use_ret == -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING) ) - mbedtls_snprintf( buf, buflen, "SSL - A counter would wrap (eg, too many messages exchanged)" ); - if( use_ret == -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO) ) - mbedtls_snprintf( buf, buflen, "SSL - Unexpected message at ServerHello in renegotiation" ); - if( use_ret == -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) ) - mbedtls_snprintf( buf, buflen, "SSL - DTLS client must retry for hello verification" ); - if( use_ret == -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) ) - mbedtls_snprintf( buf, buflen, "SSL - A buffer is too small to receive or write a message" ); - if( use_ret == -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) ) - mbedtls_snprintf( buf, buflen, "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" ); - if( use_ret == -(MBEDTLS_ERR_SSL_WANT_READ) ) - mbedtls_snprintf( buf, buflen, "SSL - Connection requires a read call" ); - if( use_ret == -(MBEDTLS_ERR_SSL_WANT_WRITE) ) - mbedtls_snprintf( buf, buflen, "SSL - Connection requires a write call" ); - if( use_ret == -(MBEDTLS_ERR_SSL_TIMEOUT) ) - mbedtls_snprintf( buf, buflen, "SSL - The operation timed out" ); - if( use_ret == -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT) ) - mbedtls_snprintf( buf, buflen, "SSL - The client initiated a reconnect from the same port" ); - if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) ) - mbedtls_snprintf( buf, buflen, "SSL - Record header looks valid but is not expected" ); - if( use_ret == -(MBEDTLS_ERR_SSL_NON_FATAL) ) - mbedtls_snprintf( buf, buflen, "SSL - The alert message received indicates a non-fatal error" ); - if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH) ) - mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" ); -#endif /* MBEDTLS_SSL_TLS_C */ - -#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) - if( use_ret == -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" ); - if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_OID) ) - mbedtls_snprintf( buf, buflen, "X509 - Requested OID is unknown" ); - if( use_ret == -(MBEDTLS_ERR_X509_INVALID_FORMAT) ) - mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" ); - if( use_ret == -(MBEDTLS_ERR_X509_INVALID_VERSION) ) - mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR version element is invalid" ); - if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SERIAL) ) - mbedtls_snprintf( buf, buflen, "X509 - The serial tag or value is invalid" ); - if( use_ret == -(MBEDTLS_ERR_X509_INVALID_ALG) ) - mbedtls_snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" ); - if( use_ret == -(MBEDTLS_ERR_X509_INVALID_NAME) ) - mbedtls_snprintf( buf, buflen, "X509 - The name tag or value is invalid" ); - if( use_ret == -(MBEDTLS_ERR_X509_INVALID_DATE) ) - mbedtls_snprintf( buf, buflen, "X509 - The date tag or value is invalid" ); - if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SIGNATURE) ) - mbedtls_snprintf( buf, buflen, "X509 - The signature tag or value invalid" ); - if( use_ret == -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS) ) - mbedtls_snprintf( buf, buflen, "X509 - The extension tag or value is invalid" ); - if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_VERSION) ) - mbedtls_snprintf( buf, buflen, "X509 - CRT/CRL/CSR has an unsupported version number" ); - if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG) ) - mbedtls_snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" ); - if( use_ret == -(MBEDTLS_ERR_X509_SIG_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)" ); - if( use_ret == -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) ) - mbedtls_snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" ); - if( use_ret == -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT) ) - mbedtls_snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" ); - if( use_ret == -(MBEDTLS_ERR_X509_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "X509 - Input invalid" ); - if( use_ret == -(MBEDTLS_ERR_X509_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "X509 - Allocation of memory failed" ); - if( use_ret == -(MBEDTLS_ERR_X509_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "X509 - Read/write of file failed" ); - if( use_ret == -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL) ) - mbedtls_snprintf( buf, buflen, "X509 - Destination buffer is too small" ); - if( use_ret == -(MBEDTLS_ERR_X509_FATAL_ERROR) ) - mbedtls_snprintf( buf, buflen, "X509 - A fatal error occured, eg the chain is too long or the vrfy callback failed" ); -#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ - // END generated code - - if( strlen( buf ) == 0 ) - mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); - } - - use_ret = ret & ~0xFF80; - - if( use_ret == 0 ) - return; - - // If high level code is present, make a concatenation between both - // error strings. - // - len = strlen( buf ); - - if( len > 0 ) - { - if( buflen - len < 5 ) - return; - - mbedtls_snprintf( buf + len, buflen - len, " : " ); - - buf += len + 3; - buflen -= len + 3; - } - - // Low level error codes - // - // BEGIN generated code -#if defined(MBEDTLS_AES_C) - if( use_ret == -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH) ) - mbedtls_snprintf( buf, buflen, "AES - Invalid key length" ); - if( use_ret == -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH) ) - mbedtls_snprintf( buf, buflen, "AES - Invalid data input length" ); -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_ASN1_PARSE_C) - if( use_ret == -(MBEDTLS_ERR_ASN1_OUT_OF_DATA) ) - mbedtls_snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" ); - if( use_ret == -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) ) - mbedtls_snprintf( buf, buflen, "ASN1 - ASN1 tag was of an unexpected value" ); - if( use_ret == -(MBEDTLS_ERR_ASN1_INVALID_LENGTH) ) - mbedtls_snprintf( buf, buflen, "ASN1 - Error when trying to determine the length or invalid length" ); - if( use_ret == -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH) ) - mbedtls_snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" ); - if( use_ret == -(MBEDTLS_ERR_ASN1_INVALID_DATA) ) - mbedtls_snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" ); - if( use_ret == -(MBEDTLS_ERR_ASN1_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "ASN1 - Memory allocation failed" ); - if( use_ret == -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) ) - mbedtls_snprintf( buf, buflen, "ASN1 - Buffer too small when writing ASN.1 data structure" ); -#endif /* MBEDTLS_ASN1_PARSE_C */ - -#if defined(MBEDTLS_BASE64_C) - if( use_ret == -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) ) - mbedtls_snprintf( buf, buflen, "BASE64 - Output buffer too small" ); - if( use_ret == -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER) ) - mbedtls_snprintf( buf, buflen, "BASE64 - Invalid character in input" ); -#endif /* MBEDTLS_BASE64_C */ - -#if defined(MBEDTLS_BIGNUM_C) - if( use_ret == -(MBEDTLS_ERR_MPI_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "BIGNUM - An error occurred while reading from or writing to a file" ); - if( use_ret == -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "BIGNUM - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_MPI_INVALID_CHARACTER) ) - mbedtls_snprintf( buf, buflen, "BIGNUM - There is an invalid character in the digit string" ); - if( use_ret == -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL) ) - mbedtls_snprintf( buf, buflen, "BIGNUM - The buffer is too small to write to" ); - if( use_ret == -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE) ) - mbedtls_snprintf( buf, buflen, "BIGNUM - The input arguments are negative or result in illegal output" ); - if( use_ret == -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO) ) - mbedtls_snprintf( buf, buflen, "BIGNUM - The input argument for division is zero, which is not allowed" ); - if( use_ret == -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) ) - mbedtls_snprintf( buf, buflen, "BIGNUM - The input arguments are not acceptable" ); - if( use_ret == -(MBEDTLS_ERR_MPI_ALLOC_FAILED) ) - mbedtls_snprintf( buf, buflen, "BIGNUM - Memory allocation failed" ); -#endif /* MBEDTLS_BIGNUM_C */ - -#if defined(MBEDTLS_BLOWFISH_C) - if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH) ) - mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid key length" ); - if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH) ) - mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid data input length" ); -#endif /* MBEDTLS_BLOWFISH_C */ - -#if defined(MBEDTLS_CAMELLIA_C) - if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH) ) - mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid key length" ); - if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH) ) - mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid data input length" ); -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_CCM_C) - if( use_ret == -(MBEDTLS_ERR_CCM_BAD_INPUT) ) - mbedtls_snprintf( buf, buflen, "CCM - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_CCM_AUTH_FAILED) ) - mbedtls_snprintf( buf, buflen, "CCM - Authenticated decryption failed" ); -#endif /* MBEDTLS_CCM_C */ - -#if defined(MBEDTLS_CTR_DRBG_C) - if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) ) - mbedtls_snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" ); - if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG) ) - mbedtls_snprintf( buf, buflen, "CTR_DRBG - Too many random requested in single call" ); - if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG) ) - mbedtls_snprintf( buf, buflen, "CTR_DRBG - Input too large (Entropy + additional)" ); - if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "CTR_DRBG - Read/write error in file" ); -#endif /* MBEDTLS_CTR_DRBG_C */ - -#if defined(MBEDTLS_DES_C) - if( use_ret == -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH) ) - mbedtls_snprintf( buf, buflen, "DES - The data input has an invalid length" ); -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ENTROPY_C) - if( use_ret == -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED) ) - mbedtls_snprintf( buf, buflen, "ENTROPY - Critical entropy source failure" ); - if( use_ret == -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES) ) - mbedtls_snprintf( buf, buflen, "ENTROPY - No more sources can be added" ); - if( use_ret == -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED) ) - mbedtls_snprintf( buf, buflen, "ENTROPY - No sources have been added to poll" ); - if( use_ret == -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE) ) - mbedtls_snprintf( buf, buflen, "ENTROPY - No strong sources have been added to poll" ); - if( use_ret == -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "ENTROPY - Read/write error in file" ); -#endif /* MBEDTLS_ENTROPY_C */ - -#if defined(MBEDTLS_GCM_C) - if( use_ret == -(MBEDTLS_ERR_GCM_AUTH_FAILED) ) - mbedtls_snprintf( buf, buflen, "GCM - Authenticated decryption failed" ); - if( use_ret == -(MBEDTLS_ERR_GCM_BAD_INPUT) ) - mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" ); -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_HMAC_DRBG_C) - if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG) ) - mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" ); - if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG) ) - mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Input too large (Entropy + additional)" ); - if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR) ) - mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Read/write error in file" ); - if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED) ) - mbedtls_snprintf( buf, buflen, "HMAC_DRBG - The entropy source failed" ); -#endif /* MBEDTLS_HMAC_DRBG_C */ - -#if defined(MBEDTLS_NET_C) - if( use_ret == -(MBEDTLS_ERR_NET_SOCKET_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Failed to open a socket" ); - if( use_ret == -(MBEDTLS_ERR_NET_CONNECT_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - The connection to the given server / port failed" ); - if( use_ret == -(MBEDTLS_ERR_NET_BIND_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Binding of the socket failed" ); - if( use_ret == -(MBEDTLS_ERR_NET_LISTEN_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Could not listen on the socket" ); - if( use_ret == -(MBEDTLS_ERR_NET_ACCEPT_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Could not accept the incoming connection" ); - if( use_ret == -(MBEDTLS_ERR_NET_RECV_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Reading information from the socket failed" ); - if( use_ret == -(MBEDTLS_ERR_NET_SEND_FAILED) ) - mbedtls_snprintf( buf, buflen, "NET - Sending information through the socket failed" ); - if( use_ret == -(MBEDTLS_ERR_NET_CONN_RESET) ) - mbedtls_snprintf( buf, buflen, "NET - Connection was reset by peer" ); - if( use_ret == -(MBEDTLS_ERR_NET_UNKNOWN_HOST) ) - mbedtls_snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" ); - if( use_ret == -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL) ) - mbedtls_snprintf( buf, buflen, "NET - Buffer is too small to hold the data" ); - if( use_ret == -(MBEDTLS_ERR_NET_INVALID_CONTEXT) ) - mbedtls_snprintf( buf, buflen, "NET - The context is invalid, eg because it was free()ed" ); -#endif /* MBEDTLS_NET_C */ - -#if defined(MBEDTLS_OID_C) - if( use_ret == -(MBEDTLS_ERR_OID_NOT_FOUND) ) - mbedtls_snprintf( buf, buflen, "OID - OID is not found" ); - if( use_ret == -(MBEDTLS_ERR_OID_BUF_TOO_SMALL) ) - mbedtls_snprintf( buf, buflen, "OID - output buffer is too small" ); -#endif /* MBEDTLS_OID_C */ - -#if defined(MBEDTLS_PADLOCK_C) - if( use_ret == -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED) ) - mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" ); -#endif /* MBEDTLS_PADLOCK_C */ - -#if defined(MBEDTLS_THREADING_C) - if( use_ret == -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE) ) - mbedtls_snprintf( buf, buflen, "THREADING - The selected feature is not available" ); - if( use_ret == -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA) ) - mbedtls_snprintf( buf, buflen, "THREADING - Bad input parameters to function" ); - if( use_ret == -(MBEDTLS_ERR_THREADING_MUTEX_ERROR) ) - mbedtls_snprintf( buf, buflen, "THREADING - Locking / unlocking / free failed with error code" ); -#endif /* MBEDTLS_THREADING_C */ - -#if defined(MBEDTLS_XTEA_C) - if( use_ret == -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH) ) - mbedtls_snprintf( buf, buflen, "XTEA - The data input has an invalid length" ); -#endif /* MBEDTLS_XTEA_C */ - // END generated code - - if( strlen( buf ) != 0 ) - return; - - mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); -} - -#else /* MBEDTLS_ERROR_C */ - -#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) - -/* - * Provide an non-function in case MBEDTLS_ERROR_C is not defined - */ -void mbedtls_strerror( int ret, char *buf, size_t buflen ) -{ - ((void) ret); - - if( buflen > 0 ) - buf[0] = '\0'; -} - -#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ - -#endif /* MBEDTLS_ERROR_C */ diff --git a/components/mbedtls/library/gcm.c b/components/mbedtls/library/gcm.c deleted file mode 100644 index fccb092bdd..0000000000 --- a/components/mbedtls/library/gcm.c +++ /dev/null @@ -1,954 +0,0 @@ -/* - * NIST SP800-38D compliant GCM implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -/* - * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf - * - * See also: - * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf - * - * We use the algorithm described as Shoup's method with 4-bit tables in - * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory. - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_GCM_C) - -#include "mbedtls/gcm.h" - -#include - -#if defined(MBEDTLS_AESNI_C) -#include "mbedtls/aesni.h" -#endif - -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT32_BE -#define GET_UINT32_BE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ - | ( (uint32_t) (b)[(i) + 1] << 16 ) \ - | ( (uint32_t) (b)[(i) + 2] << 8 ) \ - | ( (uint32_t) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_UINT32_BE -#define PUT_UINT32_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * Initialize a context - */ -void mbedtls_gcm_init( mbedtls_gcm_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_gcm_context ) ); -} - -/* - * Precompute small multiples of H, that is set - * HH[i] || HL[i] = H times i, - * where i is seen as a field element as in [MGV], ie high-order bits - * correspond to low powers of P. The result is stored in the same way, that - * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL - * corresponds to P^127. - */ -static int gcm_gen_table( mbedtls_gcm_context *ctx ) -{ - int ret, i, j; - uint64_t hi, lo; - uint64_t vl, vh; - unsigned char h[16]; - size_t olen = 0; - - memset( h, 0, 16 ); - if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 ) - return( ret ); - - /* pack h as two 64-bits ints, big-endian */ - GET_UINT32_BE( hi, h, 0 ); - GET_UINT32_BE( lo, h, 4 ); - vh = (uint64_t) hi << 32 | lo; - - GET_UINT32_BE( hi, h, 8 ); - GET_UINT32_BE( lo, h, 12 ); - vl = (uint64_t) hi << 32 | lo; - - /* 8 = 1000 corresponds to 1 in GF(2^128) */ - ctx->HL[8] = vl; - ctx->HH[8] = vh; - -#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) - /* With CLMUL support, we need only h, not the rest of the table */ - if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) - return( 0 ); -#endif - - /* 0 corresponds to 0 in GF(2^128) */ - ctx->HH[0] = 0; - ctx->HL[0] = 0; - - for( i = 4; i > 0; i >>= 1 ) - { - uint32_t T = ( vl & 1 ) * 0xe1000000U; - vl = ( vh << 63 ) | ( vl >> 1 ); - vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32); - - ctx->HL[i] = vl; - ctx->HH[i] = vh; - } - - for( i = 2; i <= 8; i *= 2 ) - { - uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i; - vh = *HiH; - vl = *HiL; - for( j = 1; j < i; j++ ) - { - HiH[j] = vh ^ ctx->HH[j]; - HiL[j] = vl ^ ctx->HL[j]; - } - } - - return( 0 ); -} - -int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, - mbedtls_cipher_id_t cipher, - const unsigned char *key, - unsigned int keybits ) -{ - int ret; - const mbedtls_cipher_info_t *cipher_info; - - cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB ); - if( cipher_info == NULL ) - return( MBEDTLS_ERR_GCM_BAD_INPUT ); - - if( cipher_info->block_size != 16 ) - return( MBEDTLS_ERR_GCM_BAD_INPUT ); - - mbedtls_cipher_free( &ctx->cipher_ctx ); - - if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, - MBEDTLS_ENCRYPT ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = gcm_gen_table( ctx ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -/* - * Shoup's method for multiplication use this table with - * last4[x] = x times P^128 - * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] - */ -static const uint64_t last4[16] = -{ - 0x0000, 0x1c20, 0x3840, 0x2460, - 0x7080, 0x6ca0, 0x48c0, 0x54e0, - 0xe100, 0xfd20, 0xd940, 0xc560, - 0x9180, 0x8da0, 0xa9c0, 0xb5e0 -}; - -/* - * Sets output to x times H using the precomputed tables. - * x and output are seen as elements of GF(2^128) as in [MGV]. - */ -static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16], - unsigned char output[16] ) -{ - int i = 0; - unsigned char lo, hi, rem; - uint64_t zh, zl; - -#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) - if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) { - unsigned char h[16]; - - PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 ); - PUT_UINT32_BE( ctx->HH[8], h, 4 ); - PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 ); - PUT_UINT32_BE( ctx->HL[8], h, 12 ); - - mbedtls_aesni_gcm_mult( output, x, h ); - return; - } -#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */ - - lo = x[15] & 0xf; - - zh = ctx->HH[lo]; - zl = ctx->HL[lo]; - - for( i = 15; i >= 0; i-- ) - { - lo = x[i] & 0xf; - hi = x[i] >> 4; - - if( i != 15 ) - { - rem = (unsigned char) zl & 0xf; - zl = ( zh << 60 ) | ( zl >> 4 ); - zh = ( zh >> 4 ); - zh ^= (uint64_t) last4[rem] << 48; - zh ^= ctx->HH[lo]; - zl ^= ctx->HL[lo]; - - } - - rem = (unsigned char) zl & 0xf; - zl = ( zh << 60 ) | ( zl >> 4 ); - zh = ( zh >> 4 ); - zh ^= (uint64_t) last4[rem] << 48; - zh ^= ctx->HH[hi]; - zl ^= ctx->HL[hi]; - } - - PUT_UINT32_BE( zh >> 32, output, 0 ); - PUT_UINT32_BE( zh, output, 4 ); - PUT_UINT32_BE( zl >> 32, output, 8 ); - PUT_UINT32_BE( zl, output, 12 ); -} - -int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, - int mode, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len ) -{ - int ret; - unsigned char work_buf[16]; - size_t i; - const unsigned char *p; - size_t use_len, olen = 0; - - /* IV and AD are limited to 2^64 bits, so 2^61 bytes */ - /* IV is not allowed to be zero length */ - if( iv_len == 0 || - ( (uint64_t) iv_len ) >> 61 != 0 || - ( (uint64_t) add_len ) >> 61 != 0 ) - { - return( MBEDTLS_ERR_GCM_BAD_INPUT ); - } - - memset( ctx->y, 0x00, sizeof(ctx->y) ); - memset( ctx->buf, 0x00, sizeof(ctx->buf) ); - - ctx->mode = mode; - ctx->len = 0; - ctx->add_len = 0; - - if( iv_len == 12 ) - { - memcpy( ctx->y, iv, iv_len ); - ctx->y[15] = 1; - } - else - { - memset( work_buf, 0x00, 16 ); - PUT_UINT32_BE( iv_len * 8, work_buf, 12 ); - - p = iv; - while( iv_len > 0 ) - { - use_len = ( iv_len < 16 ) ? iv_len : 16; - - for( i = 0; i < use_len; i++ ) - ctx->y[i] ^= p[i]; - - gcm_mult( ctx, ctx->y, ctx->y ); - - iv_len -= use_len; - p += use_len; - } - - for( i = 0; i < 16; i++ ) - ctx->y[i] ^= work_buf[i]; - - gcm_mult( ctx, ctx->y, ctx->y ); - } - - if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, - &olen ) ) != 0 ) - { - return( ret ); - } - - ctx->add_len = add_len; - p = add; - while( add_len > 0 ) - { - use_len = ( add_len < 16 ) ? add_len : 16; - - for( i = 0; i < use_len; i++ ) - ctx->buf[i] ^= p[i]; - - gcm_mult( ctx, ctx->buf, ctx->buf ); - - add_len -= use_len; - p += use_len; - } - - return( 0 ); -} - -int mbedtls_gcm_update( mbedtls_gcm_context *ctx, - size_t length, - const unsigned char *input, - unsigned char *output ) -{ - int ret; - unsigned char ectr[16]; - size_t i; - const unsigned char *p; - unsigned char *out_p = output; - size_t use_len, olen = 0; - - if( output > input && (size_t) ( output - input ) < length ) - return( MBEDTLS_ERR_GCM_BAD_INPUT ); - - /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes - * Also check for possible overflow */ - if( ctx->len + length < ctx->len || - (uint64_t) ctx->len + length > 0xFFFFFFFE0ull ) - { - return( MBEDTLS_ERR_GCM_BAD_INPUT ); - } - - ctx->len += length; - - p = input; - while( length > 0 ) - { - use_len = ( length < 16 ) ? length : 16; - - for( i = 16; i > 12; i-- ) - if( ++ctx->y[i - 1] != 0 ) - break; - - if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr, - &olen ) ) != 0 ) - { - return( ret ); - } - - for( i = 0; i < use_len; i++ ) - { - if( ctx->mode == MBEDTLS_GCM_DECRYPT ) - ctx->buf[i] ^= p[i]; - out_p[i] = ectr[i] ^ p[i]; - if( ctx->mode == MBEDTLS_GCM_ENCRYPT ) - ctx->buf[i] ^= out_p[i]; - } - - gcm_mult( ctx, ctx->buf, ctx->buf ); - - length -= use_len; - p += use_len; - out_p += use_len; - } - - return( 0 ); -} - -int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, - unsigned char *tag, - size_t tag_len ) -{ - unsigned char work_buf[16]; - size_t i; - uint64_t orig_len = ctx->len * 8; - uint64_t orig_add_len = ctx->add_len * 8; - - if( tag_len > 16 || tag_len < 4 ) - return( MBEDTLS_ERR_GCM_BAD_INPUT ); - - memcpy( tag, ctx->base_ectr, tag_len ); - - if( orig_len || orig_add_len ) - { - memset( work_buf, 0x00, 16 ); - - PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 ); - PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 ); - PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 ); - PUT_UINT32_BE( ( orig_len ), work_buf, 12 ); - - for( i = 0; i < 16; i++ ) - ctx->buf[i] ^= work_buf[i]; - - gcm_mult( ctx, ctx->buf, ctx->buf ); - - for( i = 0; i < tag_len; i++ ) - tag[i] ^= ctx->buf[i]; - } - - return( 0 ); -} - -int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, - int mode, - size_t length, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len, - const unsigned char *input, - unsigned char *output, - size_t tag_len, - unsigned char *tag ) -{ - int ret; - - if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_gcm_update( ctx, length, input, output ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_gcm_finish( ctx, tag, tag_len ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, - size_t length, - const unsigned char *iv, - size_t iv_len, - const unsigned char *add, - size_t add_len, - const unsigned char *tag, - size_t tag_len, - const unsigned char *input, - unsigned char *output ) -{ - int ret; - unsigned char check_tag[16]; - size_t i; - int diff; - - if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length, - iv, iv_len, add, add_len, - input, output, tag_len, check_tag ) ) != 0 ) - { - return( ret ); - } - - /* Check tag in "constant-time" */ - for( diff = 0, i = 0; i < tag_len; i++ ) - diff |= tag[i] ^ check_tag[i]; - - if( diff != 0 ) - { - mbedtls_zeroize( output, length ); - return( MBEDTLS_ERR_GCM_AUTH_FAILED ); - } - - return( 0 ); -} - -void mbedtls_gcm_free( mbedtls_gcm_context *ctx ) -{ - mbedtls_cipher_free( &ctx->cipher_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); -} - -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) -/* - * AES-GCM test vectors from: - * - * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip - */ -#define MAX_TESTS 6 - -static const int key_index[MAX_TESTS] = - { 0, 0, 1, 1, 1, 1 }; - -static const unsigned char key[MAX_TESTS][32] = -{ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, - 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, - 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, - 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }, -}; - -static const size_t iv_len[MAX_TESTS] = - { 12, 12, 12, 12, 8, 60 }; - -static const int iv_index[MAX_TESTS] = - { 0, 0, 1, 1, 1, 2 }; - -static const unsigned char iv[MAX_TESTS][64] = -{ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, - 0xde, 0xca, 0xf8, 0x88 }, - { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, - 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, - 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, - 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, - 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, - 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, - 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, - 0xa6, 0x37, 0xb3, 0x9b }, -}; - -static const size_t add_len[MAX_TESTS] = - { 0, 0, 0, 20, 20, 20 }; - -static const int add_index[MAX_TESTS] = - { 0, 0, 0, 1, 1, 1 }; - -static const unsigned char additional[MAX_TESTS][64] = -{ - { 0x00 }, - { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, - 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, - 0xab, 0xad, 0xda, 0xd2 }, -}; - -static const size_t pt_len[MAX_TESTS] = - { 0, 16, 64, 60, 60, 60 }; - -static const int pt_index[MAX_TESTS] = - { 0, 0, 1, 1, 1, 1 }; - -static const unsigned char pt[MAX_TESTS][64] = -{ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, - 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, - 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, - 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, - 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, - 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, - 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, - 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }, -}; - -static const unsigned char ct[MAX_TESTS * 3][64] = -{ - { 0x00 }, - { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, - 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, - { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, - 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, - 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, - 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, - 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, - 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, - 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, - 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }, - { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, - 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, - 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, - 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, - 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, - 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, - 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, - 0x3d, 0x58, 0xe0, 0x91 }, - { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, - 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, - 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, - 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, - 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, - 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, - 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, - 0xc2, 0x3f, 0x45, 0x98 }, - { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, - 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, - 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, - 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, - 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, - 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, - 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, - 0x4c, 0x34, 0xae, 0xe5 }, - { 0x00 }, - { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, - 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 }, - { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, - 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, - 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, - 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, - 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, - 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, - 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, - 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 }, - { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, - 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, - 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, - 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, - 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, - 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, - 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, - 0xcc, 0xda, 0x27, 0x10 }, - { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, - 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, - 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, - 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, - 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, - 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, - 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, - 0xa0, 0xf0, 0x62, 0xf7 }, - { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, - 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, - 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, - 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, - 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, - 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, - 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, - 0xe9, 0xb7, 0x37, 0x3b }, - { 0x00 }, - { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, - 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 }, - { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, - 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, - 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, - 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, - 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, - 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, - 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, - 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad }, - { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, - 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, - 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, - 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, - 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, - 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, - 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, - 0xbc, 0xc9, 0xf6, 0x62 }, - { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, - 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, - 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, - 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, - 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, - 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, - 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, - 0xf4, 0x7c, 0x9b, 0x1f }, - { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, - 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, - 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, - 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, - 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, - 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, - 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, - 0x44, 0xae, 0x7e, 0x3f }, -}; - -static const unsigned char tag[MAX_TESTS * 3][16] = -{ - { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, - 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }, - { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, - 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }, - { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, - 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }, - { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, - 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 }, - { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, - 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb }, - { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, - 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 }, - { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, - 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 }, - { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, - 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb }, - { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, - 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 }, - { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, - 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c }, - { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, - 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 }, - { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, - 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }, - { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, - 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b }, - { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, - 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 }, - { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, - 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c }, - { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, - 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }, - { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, - 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 }, - { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, - 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a }, -}; - -int mbedtls_gcm_self_test( int verbose ) -{ - mbedtls_gcm_context ctx; - unsigned char buf[64]; - unsigned char tag_buf[16]; - int i, j, ret; - mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; - - mbedtls_gcm_init( &ctx ); - - for( j = 0; j < 3; j++ ) - { - int key_len = 128 + 64 * j; - - for( i = 0; i < MAX_TESTS; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " AES-GCM-%3d #%d (%s): ", - key_len, i, "enc" ); - - mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); - - ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT, - pt_len[i], - iv[iv_index[i]], iv_len[i], - additional[add_index[i]], add_len[i], - pt[pt_index[i]], buf, 16, tag_buf ); - - if( ret != 0 || - memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || - memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - mbedtls_gcm_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " AES-GCM-%3d #%d (%s): ", - key_len, i, "dec" ); - - mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); - - ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT, - pt_len[i], - iv[iv_index[i]], iv_len[i], - additional[add_index[i]], add_len[i], - ct[j * 6 + i], buf, 16, tag_buf ); - - if( ret != 0 || - memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || - memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - mbedtls_gcm_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", - key_len, i, "enc" ); - - mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); - - ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT, - iv[iv_index[i]], iv_len[i], - additional[add_index[i]], add_len[i] ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( pt_len[i] > 32 ) - { - size_t rest_len = pt_len[i] - 32; - ret = mbedtls_gcm_update( &ctx, 32, pt[pt_index[i]], buf ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - ret = mbedtls_gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32, - buf + 32 ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - else - { - ret = mbedtls_gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - - ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); - if( ret != 0 || - memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 || - memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - mbedtls_gcm_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", - key_len, i, "dec" ); - - mbedtls_gcm_setkey( &ctx, cipher, key[key_index[i]], key_len ); - - ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT, - iv[iv_index[i]], iv_len[i], - additional[add_index[i]], add_len[i] ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( pt_len[i] > 32 ) - { - size_t rest_len = pt_len[i] - 32; - ret = mbedtls_gcm_update( &ctx, 32, ct[j * 6 + i], buf ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - ret = mbedtls_gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32, - buf + 32 ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - else - { - ret = mbedtls_gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - - ret = mbedtls_gcm_finish( &ctx, tag_buf, 16 ); - if( ret != 0 || - memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 || - memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - mbedtls_gcm_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - } - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ - -#endif /* MBEDTLS_GCM_C */ diff --git a/components/mbedtls/library/havege.c b/components/mbedtls/library/havege.c deleted file mode 100644 index 2b75ef7bd8..0000000000 --- a/components/mbedtls/library/havege.c +++ /dev/null @@ -1,245 +0,0 @@ -/** - * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The HAVEGE RNG was designed by Andre Seznec in 2002. - * - * http://www.irisa.fr/caps/projects/hipsor/publi.php - * - * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_HAVEGE_C) - -#include "mbedtls/havege.h" -#include "mbedtls/timing.h" - -#include - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* ------------------------------------------------------------------------ - * On average, one iteration accesses two 8-word blocks in the havege WALK - * table, and generates 16 words in the RES array. - * - * The data read in the WALK table is updated and permuted after each use. - * The result of the hardware clock counter read is used for this update. - * - * 25 conditional tests are present. The conditional tests are grouped in - * two nested groups of 12 conditional tests and 1 test that controls the - * permutation; on average, there should be 6 tests executed and 3 of them - * should be mispredicted. - * ------------------------------------------------------------------------ - */ - -#define SWAP(X,Y) { int *T = X; X = Y; Y = T; } - -#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; -#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; - -#define TST1_LEAVE U1++; } -#define TST2_LEAVE U2++; } - -#define ONE_ITERATION \ - \ - PTEST = PT1 >> 20; \ - \ - TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ - TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ - TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ - \ - TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ - TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ - TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ - \ - PTX = (PT1 >> 18) & 7; \ - PT1 &= 0x1FFF; \ - PT2 &= 0x1FFF; \ - CLK = (int) mbedtls_timing_hardclock(); \ - \ - i = 0; \ - A = &WALK[PT1 ]; RES[i++] ^= *A; \ - B = &WALK[PT2 ]; RES[i++] ^= *B; \ - C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \ - D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \ - \ - IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \ - *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \ - *B = IN ^ U1; \ - *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \ - *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \ - \ - A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \ - B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \ - C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \ - D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \ - \ - if( PTEST & 1 ) SWAP( A, C ); \ - \ - IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \ - *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \ - *B = IN; CLK = (int) mbedtls_timing_hardclock(); \ - *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \ - *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \ - \ - A = &WALK[PT1 ^ 4]; \ - B = &WALK[PT2 ^ 1]; \ - \ - PTEST = PT2 >> 1; \ - \ - PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \ - PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \ - PTY = (PT2 >> 10) & 7; \ - \ - TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ - TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ - TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ - \ - TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ - TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ - TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ - \ - C = &WALK[PT1 ^ 5]; \ - D = &WALK[PT2 ^ 5]; \ - \ - RES[i++] ^= *A; \ - RES[i++] ^= *B; \ - RES[i++] ^= *C; \ - RES[i++] ^= *D; \ - \ - IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \ - *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \ - *B = IN ^ U2; \ - *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \ - *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \ - \ - A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \ - B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \ - C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \ - D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \ - \ - IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \ - *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \ - *B = IN; \ - *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \ - *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \ - \ - PT1 = ( RES[( i - 8 ) ^ PTX] ^ \ - WALK[PT1 ^ PTX ^ 7] ) & (~1); \ - PT1 ^= (PT2 ^ 0x10) & 0x10; \ - \ - for( n++, i = 0; i < 16; i++ ) \ - hs->pool[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i]; - -/* - * Entropy gathering function - */ -static void havege_fill( mbedtls_havege_state *hs ) -{ - int i, n = 0; - int U1, U2, *A, *B, *C, *D; - int PT1, PT2, *WALK, RES[16]; - int PTX, PTY, CLK, PTEST, IN; - - WALK = hs->WALK; - PT1 = hs->PT1; - PT2 = hs->PT2; - - PTX = U1 = 0; - PTY = U2 = 0; - - (void)PTX; - - memset( RES, 0, sizeof( RES ) ); - - while( n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4 ) - { - ONE_ITERATION - ONE_ITERATION - ONE_ITERATION - ONE_ITERATION - } - - hs->PT1 = PT1; - hs->PT2 = PT2; - - hs->offset[0] = 0; - hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2; -} - -/* - * HAVEGE initialization - */ -void mbedtls_havege_init( mbedtls_havege_state *hs ) -{ - memset( hs, 0, sizeof( mbedtls_havege_state ) ); - - havege_fill( hs ); -} - -void mbedtls_havege_free( mbedtls_havege_state *hs ) -{ - if( hs == NULL ) - return; - - mbedtls_zeroize( hs, sizeof( mbedtls_havege_state ) ); -} - -/* - * HAVEGE rand function - */ -int mbedtls_havege_random( void *p_rng, unsigned char *buf, size_t len ) -{ - int val; - size_t use_len; - mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng; - unsigned char *p = buf; - - while( len > 0 ) - { - use_len = len; - if( use_len > sizeof(int) ) - use_len = sizeof(int); - - if( hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE ) - havege_fill( hs ); - - val = hs->pool[hs->offset[0]++]; - val ^= hs->pool[hs->offset[1]++]; - - memcpy( p, &val, use_len ); - - len -= use_len; - p += use_len; - } - - return( 0 ); -} - -#endif /* MBEDTLS_HAVEGE_C */ diff --git a/components/mbedtls/library/hmac_drbg.c b/components/mbedtls/library/hmac_drbg.c deleted file mode 100644 index bf5f9b5bd3..0000000000 --- a/components/mbedtls/library/hmac_drbg.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - * HMAC_DRBG implementation (NIST SP 800-90) - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -/* - * The NIST SP 800-90A DRBGs are described in the following publication. - * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf - * References below are based on rev. 1 (January 2012). - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_HMAC_DRBG_C) - -#include "mbedtls/hmac_drbg.h" - -#include - -#if defined(MBEDTLS_FS_IO) -#include -#endif - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_SELF_TEST */ -#endif /* MBEDTLS_PLATFORM_C */ - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * HMAC_DRBG context initialization - */ -void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif -} - -/* - * HMAC_DRBG update, using optional additional data (10.1.2.2) - */ -void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, - const unsigned char *additional, size_t add_len ) -{ - size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); - unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; - unsigned char sep[1]; - unsigned char K[MBEDTLS_MD_MAX_SIZE]; - - for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) - { - /* Step 1 or 4 */ - mbedtls_md_hmac_reset( &ctx->md_ctx ); - mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); - mbedtls_md_hmac_update( &ctx->md_ctx, sep, 1 ); - if( rounds == 2 ) - mbedtls_md_hmac_update( &ctx->md_ctx, additional, add_len ); - mbedtls_md_hmac_finish( &ctx->md_ctx, K ); - - /* Step 2 or 5 */ - mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ); - mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); - mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); - } -} - -/* - * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) - */ -int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, - const mbedtls_md_info_t * md_info, - const unsigned char *data, size_t data_len ) -{ - int ret; - - if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) - return( ret ); - - /* - * Set initial working state. - * Use the V memory location, which is currently all 0, to initialize the - * MD context with an all-zero key. Then set V to its initial value. - */ - mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, mbedtls_md_get_size( md_info ) ); - memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) ); - - mbedtls_hmac_drbg_update( ctx, data, data_len ); - - return( 0 ); -} - -/* - * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman) - */ -int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, - const unsigned char *additional, size_t len ) -{ - unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; - size_t seedlen; - - /* III. Check input length */ - if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || - ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ) - { - return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); - } - - memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); - - /* IV. Gather entropy_len bytes of entropy for the seed */ - if( ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) != 0 ) - return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); - - seedlen = ctx->entropy_len; - - /* 1. Concatenate entropy and additional data if any */ - if( additional != NULL && len != 0 ) - { - memcpy( seed + seedlen, additional, len ); - seedlen += len; - } - - /* 2. Update state */ - mbedtls_hmac_drbg_update( ctx, seed, seedlen ); - - /* 3. Reset reseed_counter */ - ctx->reseed_counter = 1; - - /* 4. Done */ - return( 0 ); -} - -/* - * HMAC_DRBG initialisation (10.1.2.3 + 9.1) - */ -int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, - const mbedtls_md_info_t * md_info, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len ) -{ - int ret; - size_t entropy_len, md_size; - - if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) - return( ret ); - - md_size = mbedtls_md_get_size( md_info ); - - /* - * Set initial working state. - * Use the V memory location, which is currently all 0, to initialize the - * MD context with an all-zero key. Then set V to its initial value. - */ - mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ); - memset( ctx->V, 0x01, md_size ); - - ctx->f_entropy = f_entropy; - ctx->p_entropy = p_entropy; - - ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; - - /* - * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by - * each hash function, then according to SP800-90A rev1 10.1 table 2, - * min_entropy_len (in bits) is security_strength. - * - * (This also matches the sizes used in the NIST test vectors.) - */ - entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ - md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ - 32; /* better (256+) -> 256 bits */ - - /* - * For initialisation, use more entropy to emulate a nonce - * (Again, matches test vectors.) - */ - ctx->entropy_len = entropy_len * 3 / 2; - - if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 ) - return( ret ); - - ctx->entropy_len = entropy_len; - - return( 0 ); -} - -/* - * Set prediction resistance - */ -void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, - int resistance ) -{ - ctx->prediction_resistance = resistance; -} - -/* - * Set entropy length grabbed for reseeds - */ -void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len ) -{ - ctx->entropy_len = len; -} - -/* - * Set reseed interval - */ -void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval ) -{ - ctx->reseed_interval = interval; -} - -/* - * HMAC_DRBG random function with optional additional data: - * 10.1.2.5 (arabic) + 9.3 (Roman) - */ -int mbedtls_hmac_drbg_random_with_add( void *p_rng, - unsigned char *output, size_t out_len, - const unsigned char *additional, size_t add_len ) -{ - int ret; - mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; - size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); - size_t left = out_len; - unsigned char *out = output; - - /* II. Check request length */ - if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST ) - return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG ); - - /* III. Check input length */ - if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT ) - return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); - - /* 1. (aka VII and IX) Check reseed counter and PR */ - if( ctx->f_entropy != NULL && /* For no-reseeding instances */ - ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON || - ctx->reseed_counter > ctx->reseed_interval ) ) - { - if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 ) - return( ret ); - - add_len = 0; /* VII.4 */ - } - - /* 2. Use additional data if any */ - if( additional != NULL && add_len != 0 ) - mbedtls_hmac_drbg_update( ctx, additional, add_len ); - - /* 3, 4, 5. Generate bytes */ - while( left != 0 ) - { - size_t use_len = left > md_len ? md_len : left; - - mbedtls_md_hmac_reset( &ctx->md_ctx ); - mbedtls_md_hmac_update( &ctx->md_ctx, ctx->V, md_len ); - mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ); - - memcpy( out, ctx->V, use_len ); - out += use_len; - left -= use_len; - } - - /* 6. Update */ - mbedtls_hmac_drbg_update( ctx, additional, add_len ); - - /* 7. Update reseed counter */ - ctx->reseed_counter++; - - /* 8. Done */ - return( 0 ); -} - -/* - * HMAC_DRBG random function - */ -int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ) -{ - int ret; - mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 ); - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -/* - * Free an HMAC_DRBG context - */ -void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) -{ - if( ctx == NULL ) - return; - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); -#endif - mbedtls_md_free( &ctx->md_ctx ); - mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); -} - -#if defined(MBEDTLS_FS_IO) -int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) -{ - int ret; - FILE *f; - unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; - - if( ( f = fopen( path, "wb" ) ) == NULL ) - return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); - - if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 ) - goto exit; - - if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) ) - { - ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; - goto exit; - } - - ret = 0; - -exit: - fclose( f ); - return( ret ); -} - -int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) -{ - FILE *f; - size_t n; - unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); - - fseek( f, 0, SEEK_END ); - n = (size_t) ftell( f ); - fseek( f, 0, SEEK_SET ); - - if( n > MBEDTLS_HMAC_DRBG_MAX_INPUT ) - { - fclose( f ); - return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); - } - - if( fread( buf, 1, n, f ) != n ) - { - fclose( f ); - return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); - } - - fclose( f ); - - mbedtls_hmac_drbg_update( ctx, buf, n ); - - return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) ); -} -#endif /* MBEDTLS_FS_IO */ - - -#if defined(MBEDTLS_SELF_TEST) - -#if !defined(MBEDTLS_SHA1_C) -/* Dummy checkup routine */ -int mbedtls_hmac_drbg_self_test( int verbose ) -{ - (void) verbose; - return( 0 ); -} -#else - -#define OUTPUT_LEN 80 - -/* From a NIST PR=true test vector */ -static const unsigned char entropy_pr[] = { - 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f, - 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11, - 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42, - 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3, - 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 }; -static const unsigned char result_pr[OUTPUT_LEN] = { - 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39, - 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94, - 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54, - 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e, - 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab, - 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3, - 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 }; - -/* From a NIST PR=false test vector */ -static const unsigned char entropy_nopr[] = { - 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66, - 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8, - 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3, - 0xe9, 0x9d, 0xfe, 0xdf }; -static const unsigned char result_nopr[OUTPUT_LEN] = { - 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f, - 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6, - 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a, - 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec, - 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd, - 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49, - 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 }; - -/* "Entropy" from buffer */ -static size_t test_offset; -static int hmac_drbg_self_test_entropy( void *data, - unsigned char *buf, size_t len ) -{ - const unsigned char *p = data; - memcpy( buf, p + test_offset, len ); - test_offset += len; - return( 0 ); -} - -#define CHK( c ) if( (c) != 0 ) \ - { \ - if( verbose != 0 ) \ - mbedtls_printf( "failed\n" ); \ - return( 1 ); \ - } - -/* - * Checkup routine for HMAC_DRBG with SHA-1 - */ -int mbedtls_hmac_drbg_self_test( int verbose ) -{ - mbedtls_hmac_drbg_context ctx; - unsigned char buf[OUTPUT_LEN]; - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); - - mbedtls_hmac_drbg_init( &ctx ); - - /* - * PR = True - */ - if( verbose != 0 ) - mbedtls_printf( " HMAC_DRBG (PR = True) : " ); - - test_offset = 0; - CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, - hmac_drbg_self_test_entropy, (void *) entropy_pr, - NULL, 0 ) ); - mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON ); - CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); - CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); - CHK( memcmp( buf, result_pr, OUTPUT_LEN ) ); - mbedtls_hmac_drbg_free( &ctx ); - - mbedtls_hmac_drbg_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - /* - * PR = False - */ - if( verbose != 0 ) - mbedtls_printf( " HMAC_DRBG (PR = False) : " ); - - mbedtls_hmac_drbg_init( &ctx ); - - test_offset = 0; - CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, - hmac_drbg_self_test_entropy, (void *) entropy_nopr, - NULL, 0 ) ); - CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) ); - CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); - CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); - CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) ); - mbedtls_hmac_drbg_free( &ctx ); - - mbedtls_hmac_drbg_free( &ctx ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_HMAC_DRBG_C */ diff --git a/components/mbedtls/library/md.c b/components/mbedtls/library/md.c deleted file mode 100644 index eda98f6361..0000000000 --- a/components/mbedtls/library/md.c +++ /dev/null @@ -1,471 +0,0 @@ -/** - * \file mbedtls_md.c - * - * \brief Generic message digest wrapper for mbed TLS - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_MD_C) - -#include "mbedtls/md.h" -#include "mbedtls/md_internal.h" - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include - -#if defined(MBEDTLS_FS_IO) -#include -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * Reminder: update profiles in x509_crt.c when adding a new hash! - */ -static const int supported_digests[] = { - -#if defined(MBEDTLS_SHA512_C) - MBEDTLS_MD_SHA512, - MBEDTLS_MD_SHA384, -#endif - -#if defined(MBEDTLS_SHA256_C) - MBEDTLS_MD_SHA256, - MBEDTLS_MD_SHA224, -#endif - -#if defined(MBEDTLS_SHA1_C) - MBEDTLS_MD_SHA1, -#endif - -#if defined(MBEDTLS_RIPEMD160_C) - MBEDTLS_MD_RIPEMD160, -#endif - -#if defined(MBEDTLS_MD5_C) - MBEDTLS_MD_MD5, -#endif - -#if defined(MBEDTLS_MD4_C) - MBEDTLS_MD_MD4, -#endif - -#if defined(MBEDTLS_MD2_C) - MBEDTLS_MD_MD2, -#endif - - MBEDTLS_MD_NONE -}; - -const int *mbedtls_md_list( void ) -{ - return( supported_digests ); -} - -const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ) -{ - if( NULL == md_name ) - return( NULL ); - - /* Get the appropriate digest information */ -#if defined(MBEDTLS_MD2_C) - if( !strcmp( "MD2", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_MD2 ); -#endif -#if defined(MBEDTLS_MD4_C) - if( !strcmp( "MD4", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_MD4 ); -#endif -#if defined(MBEDTLS_MD5_C) - if( !strcmp( "MD5", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ); -#endif -#if defined(MBEDTLS_RIPEMD160_C) - if( !strcmp( "RIPEMD160", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_RIPEMD160 ); -#endif -#if defined(MBEDTLS_SHA1_C) - if( !strcmp( "SHA1", md_name ) || !strcmp( "SHA", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); -#endif -#if defined(MBEDTLS_SHA256_C) - if( !strcmp( "SHA224", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_SHA224 ); - if( !strcmp( "SHA256", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ); -#endif -#if defined(MBEDTLS_SHA512_C) - if( !strcmp( "SHA384", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 ); - if( !strcmp( "SHA512", md_name ) ) - return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 ); -#endif - return( NULL ); -} - -const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ) -{ - switch( md_type ) - { -#if defined(MBEDTLS_MD2_C) - case MBEDTLS_MD_MD2: - return( &mbedtls_md2_info ); -#endif -#if defined(MBEDTLS_MD4_C) - case MBEDTLS_MD_MD4: - return( &mbedtls_md4_info ); -#endif -#if defined(MBEDTLS_MD5_C) - case MBEDTLS_MD_MD5: - return( &mbedtls_md5_info ); -#endif -#if defined(MBEDTLS_RIPEMD160_C) - case MBEDTLS_MD_RIPEMD160: - return( &mbedtls_ripemd160_info ); -#endif -#if defined(MBEDTLS_SHA1_C) - case MBEDTLS_MD_SHA1: - return( &mbedtls_sha1_info ); -#endif -#if defined(MBEDTLS_SHA256_C) - case MBEDTLS_MD_SHA224: - return( &mbedtls_sha224_info ); - case MBEDTLS_MD_SHA256: - return( &mbedtls_sha256_info ); -#endif -#if defined(MBEDTLS_SHA512_C) - case MBEDTLS_MD_SHA384: - return( &mbedtls_sha384_info ); - case MBEDTLS_MD_SHA512: - return( &mbedtls_sha512_info ); -#endif - default: - return( NULL ); - } -} - -void mbedtls_md_init( mbedtls_md_context_t *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_md_context_t ) ); -} - -void mbedtls_md_free( mbedtls_md_context_t *ctx ) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return; - - if( ctx->md_ctx != NULL ) - ctx->md_info->ctx_free_func( ctx->md_ctx ); - - if( ctx->hmac_ctx != NULL ) - { - mbedtls_zeroize( ctx->hmac_ctx, 2 * ctx->md_info->block_size ); - mbedtls_free( ctx->hmac_ctx ); - } - - mbedtls_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); -} - -int mbedtls_md_clone( mbedtls_md_context_t *dst, - const mbedtls_md_context_t *src ) -{ - if( dst == NULL || dst->md_info == NULL || - src == NULL || src->md_info == NULL || - dst->md_info != src->md_info ) - { - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - } - - dst->md_info->clone_func( dst->md_ctx, src->md_ctx ); - - return( 0 ); -} - -#if ! defined(MBEDTLS_DEPRECATED_REMOVED) -int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) -{ - return mbedtls_md_setup( ctx, md_info, 1 ); -} -#endif - -int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ) -{ - if( md_info == NULL || ctx == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL ) - return( MBEDTLS_ERR_MD_ALLOC_FAILED ); - - if( hmac != 0 ) - { - ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size ); - if( ctx->hmac_ctx == NULL ) - { - md_info->ctx_free_func( ctx->md_ctx ); - return( MBEDTLS_ERR_MD_ALLOC_FAILED ); - } - } - - ctx->md_info = md_info; - - return( 0 ); -} - -int mbedtls_md_starts( mbedtls_md_context_t *ctx ) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - ctx->md_info->starts_func( ctx->md_ctx ); - - return( 0 ); -} - -int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - ctx->md_info->update_func( ctx->md_ctx, input, ilen ); - - return( 0 ); -} - -int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - ctx->md_info->finish_func( ctx->md_ctx, output ); - - return( 0 ); -} - -int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - if( md_info == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - md_info->digest_func( input, ilen, output ); - - return( 0 ); -} - -#if defined(MBEDTLS_FS_IO) -int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output ) -{ - int ret; - FILE *f; - size_t n; - mbedtls_md_context_t ctx; - unsigned char buf[1024]; - - if( md_info == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( MBEDTLS_ERR_MD_FILE_IO_ERROR ); - - mbedtls_md_init( &ctx ); - - if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) - goto cleanup; - - md_info->starts_func( ctx.md_ctx ); - - while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) - md_info->update_func( ctx.md_ctx, buf, n ); - - if( ferror( f ) != 0 ) - { - ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; - goto cleanup; - } - - md_info->finish_func( ctx.md_ctx, output ); - -cleanup: - fclose( f ); - mbedtls_md_free( &ctx ); - - return( ret ); -} -#endif /* MBEDTLS_FS_IO */ - -int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ) -{ - unsigned char sum[MBEDTLS_MD_MAX_SIZE]; - unsigned char *ipad, *opad; - size_t i; - - if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - if( keylen > (size_t) ctx->md_info->block_size ) - { - ctx->md_info->starts_func( ctx->md_ctx ); - ctx->md_info->update_func( ctx->md_ctx, key, keylen ); - ctx->md_info->finish_func( ctx->md_ctx, sum ); - - keylen = ctx->md_info->size; - key = sum; - } - - ipad = (unsigned char *) ctx->hmac_ctx; - opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; - - memset( ipad, 0x36, ctx->md_info->block_size ); - memset( opad, 0x5C, ctx->md_info->block_size ); - - for( i = 0; i < keylen; i++ ) - { - ipad[i] = (unsigned char)( ipad[i] ^ key[i] ); - opad[i] = (unsigned char)( opad[i] ^ key[i] ); - } - - mbedtls_zeroize( sum, sizeof( sum ) ); - - ctx->md_info->starts_func( ctx->md_ctx ); - ctx->md_info->update_func( ctx->md_ctx, ipad, ctx->md_info->block_size ); - - return( 0 ); -} - -int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) -{ - if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - ctx->md_info->update_func( ctx->md_ctx, input, ilen ); - - return( 0 ); -} - -int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) -{ - unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; - unsigned char *opad; - - if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; - - ctx->md_info->finish_func( ctx->md_ctx, tmp ); - ctx->md_info->starts_func( ctx->md_ctx ); - ctx->md_info->update_func( ctx->md_ctx, opad, ctx->md_info->block_size ); - ctx->md_info->update_func( ctx->md_ctx, tmp, ctx->md_info->size ); - ctx->md_info->finish_func( ctx->md_ctx, output ); - - return( 0 ); -} - -int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) -{ - unsigned char *ipad; - - if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - ipad = (unsigned char *) ctx->hmac_ctx; - - ctx->md_info->starts_func( ctx->md_ctx ); - ctx->md_info->update_func( ctx->md_ctx, ipad, ctx->md_info->block_size ); - - return( 0 ); -} - -int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - mbedtls_md_context_t ctx; - int ret; - - if( md_info == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - mbedtls_md_init( &ctx ); - - if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 ) - return( ret ); - - mbedtls_md_hmac_starts( &ctx, key, keylen ); - mbedtls_md_hmac_update( &ctx, input, ilen ); - mbedtls_md_hmac_finish( &ctx, output ); - - mbedtls_md_free( &ctx ); - - return( 0 ); -} - -int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) -{ - if( ctx == NULL || ctx->md_info == NULL ) - return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - - ctx->md_info->process_func( ctx->md_ctx, data ); - - return( 0 ); -} - -unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ) -{ - if( md_info == NULL ) - return( 0 ); - - return md_info->size; -} - -mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ) -{ - if( md_info == NULL ) - return( MBEDTLS_MD_NONE ); - - return md_info->type; -} - -const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ) -{ - if( md_info == NULL ) - return( NULL ); - - return md_info->name; -} - -#endif /* MBEDTLS_MD_C */ diff --git a/components/mbedtls/library/md2.c b/components/mbedtls/library/md2.c deleted file mode 100644 index 95cbcce658..0000000000 --- a/components/mbedtls/library/md2.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * RFC 1115/1319 compliant MD2 implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The MD2 algorithm was designed by Ron Rivest in 1989. - * - * http://www.ietf.org/rfc/rfc1115.txt - * http://www.ietf.org/rfc/rfc1319.txt - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_MD2_C) - -#include "mbedtls/md2.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_MD2_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -static const unsigned char PI_SUBST[256] = -{ - 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, - 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3, - 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, - 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, - 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E, - 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, - 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, - 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21, - 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, - 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3, - 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, - 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, - 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D, - 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, - 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, - 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F, - 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, - 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E, - 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, - 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, - 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88, - 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, - 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, - 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A, - 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, - 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14 -}; - -void mbedtls_md2_init( mbedtls_md2_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_md2_context ) ); -} - -void mbedtls_md2_free( mbedtls_md2_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_md2_context ) ); -} - -void mbedtls_md2_clone( mbedtls_md2_context *dst, - const mbedtls_md2_context *src ) -{ - *dst = *src; -} - -/* - * MD2 context setup - */ -void mbedtls_md2_starts( mbedtls_md2_context *ctx ) -{ - memset( ctx->cksum, 0, 16 ); - memset( ctx->state, 0, 46 ); - memset( ctx->buffer, 0, 16 ); - ctx->left = 0; -} - -#if !defined(MBEDTLS_MD2_PROCESS_ALT) -void mbedtls_md2_process( mbedtls_md2_context *ctx ) -{ - int i, j; - unsigned char t = 0; - - for( i = 0; i < 16; i++ ) - { - ctx->state[i + 16] = ctx->buffer[i]; - ctx->state[i + 32] = - (unsigned char)( ctx->buffer[i] ^ ctx->state[i]); - } - - for( i = 0; i < 18; i++ ) - { - for( j = 0; j < 48; j++ ) - { - ctx->state[j] = (unsigned char) - ( ctx->state[j] ^ PI_SUBST[t] ); - t = ctx->state[j]; - } - - t = (unsigned char)( t + i ); - } - - t = ctx->cksum[15]; - - for( i = 0; i < 16; i++ ) - { - ctx->cksum[i] = (unsigned char) - ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] ); - t = ctx->cksum[i]; - } -} -#endif /* !MBEDTLS_MD2_PROCESS_ALT */ - -/* - * MD2 process buffer - */ -void mbedtls_md2_update( mbedtls_md2_context *ctx, const unsigned char *input, size_t ilen ) -{ - size_t fill; - - while( ilen > 0 ) - { - if( ilen > 16 - ctx->left ) - fill = 16 - ctx->left; - else - fill = ilen; - - memcpy( ctx->buffer + ctx->left, input, fill ); - - ctx->left += fill; - input += fill; - ilen -= fill; - - if( ctx->left == 16 ) - { - ctx->left = 0; - mbedtls_md2_process( ctx ); - } - } -} - -/* - * MD2 final digest - */ -void mbedtls_md2_finish( mbedtls_md2_context *ctx, unsigned char output[16] ) -{ - size_t i; - unsigned char x; - - x = (unsigned char)( 16 - ctx->left ); - - for( i = ctx->left; i < 16; i++ ) - ctx->buffer[i] = x; - - mbedtls_md2_process( ctx ); - - memcpy( ctx->buffer, ctx->cksum, 16 ); - mbedtls_md2_process( ctx ); - - memcpy( output, ctx->state, 16 ); -} - -#endif /* !MBEDTLS_MD2_ALT */ - -/* - * output = MD2( input buffer ) - */ -void mbedtls_md2( const unsigned char *input, size_t ilen, unsigned char output[16] ) -{ - mbedtls_md2_context ctx; - - mbedtls_md2_init( &ctx ); - mbedtls_md2_starts( &ctx ); - mbedtls_md2_update( &ctx, input, ilen ); - mbedtls_md2_finish( &ctx, output ); - mbedtls_md2_free( &ctx ); -} - -#if defined(MBEDTLS_SELF_TEST) - -/* - * RFC 1319 test vectors - */ -static const char md2_test_str[7][81] = -{ - { "" }, - { "a" }, - { "abc" }, - { "message digest" }, - { "abcdefghijklmnopqrstuvwxyz" }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, - { "12345678901234567890123456789012345678901234567890123456789012" \ - "345678901234567890" } -}; - -static const unsigned char md2_test_sum[7][16] = -{ - { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D, - 0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 }, - { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72, - 0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 }, - { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B, - 0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB }, - { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B, - 0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 }, - { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB, - 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B }, - { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39, - 0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD }, - { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D, - 0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 } -}; - -/* - * Checkup routine - */ -int mbedtls_md2_self_test( int verbose ) -{ - int i; - unsigned char md2sum[16]; - - for( i = 0; i < 7; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " MD2 test #%d: ", i + 1 ); - - mbedtls_md2( (unsigned char *) md2_test_str[i], - strlen( md2_test_str[i] ), md2sum ); - - if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_MD2_C */ diff --git a/components/mbedtls/library/md4.c b/components/mbedtls/library/md4.c deleted file mode 100644 index 11a77e3ae4..0000000000 --- a/components/mbedtls/library/md4.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * RFC 1186/1320 compliant MD4 implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The MD4 algorithm was designed by Ron Rivest in 1990. - * - * http://www.ietf.org/rfc/rfc1186.txt - * http://www.ietf.org/rfc/rfc1320.txt - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_MD4_C) - -#include "mbedtls/md4.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_MD4_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_UINT32_LE -#define GET_UINT32_LE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] ) \ - | ( (uint32_t) (b)[(i) + 1] << 8 ) \ - | ( (uint32_t) (b)[(i) + 2] << 16 ) \ - | ( (uint32_t) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_UINT32_LE -#define PUT_UINT32_LE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ - (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ - (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ - (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ -} -#endif - -void mbedtls_md4_init( mbedtls_md4_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_md4_context ) ); -} - -void mbedtls_md4_free( mbedtls_md4_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_md4_context ) ); -} - -void mbedtls_md4_clone( mbedtls_md4_context *dst, - const mbedtls_md4_context *src ) -{ - *dst = *src; -} - -/* - * MD4 context setup - */ -void mbedtls_md4_starts( mbedtls_md4_context *ctx ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; -} - -#if !defined(MBEDTLS_MD4_PROCESS_ALT) -void mbedtls_md4_process( mbedtls_md4_context *ctx, const unsigned char data[64] ) -{ - uint32_t X[16], A, B, C, D; - - GET_UINT32_LE( X[ 0], data, 0 ); - GET_UINT32_LE( X[ 1], data, 4 ); - GET_UINT32_LE( X[ 2], data, 8 ); - GET_UINT32_LE( X[ 3], data, 12 ); - GET_UINT32_LE( X[ 4], data, 16 ); - GET_UINT32_LE( X[ 5], data, 20 ); - GET_UINT32_LE( X[ 6], data, 24 ); - GET_UINT32_LE( X[ 7], data, 28 ); - GET_UINT32_LE( X[ 8], data, 32 ); - GET_UINT32_LE( X[ 9], data, 36 ); - GET_UINT32_LE( X[10], data, 40 ); - GET_UINT32_LE( X[11], data, 44 ); - GET_UINT32_LE( X[12], data, 48 ); - GET_UINT32_LE( X[13], data, 52 ); - GET_UINT32_LE( X[14], data, 56 ); - GET_UINT32_LE( X[15], data, 60 ); - -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - -#define F(x, y, z) ((x & y) | ((~x) & z)) -#define P(a,b,c,d,x,s) { a += F(b,c,d) + x; a = S(a,s); } - - P( A, B, C, D, X[ 0], 3 ); - P( D, A, B, C, X[ 1], 7 ); - P( C, D, A, B, X[ 2], 11 ); - P( B, C, D, A, X[ 3], 19 ); - P( A, B, C, D, X[ 4], 3 ); - P( D, A, B, C, X[ 5], 7 ); - P( C, D, A, B, X[ 6], 11 ); - P( B, C, D, A, X[ 7], 19 ); - P( A, B, C, D, X[ 8], 3 ); - P( D, A, B, C, X[ 9], 7 ); - P( C, D, A, B, X[10], 11 ); - P( B, C, D, A, X[11], 19 ); - P( A, B, C, D, X[12], 3 ); - P( D, A, B, C, X[13], 7 ); - P( C, D, A, B, X[14], 11 ); - P( B, C, D, A, X[15], 19 ); - -#undef P -#undef F - -#define F(x,y,z) ((x & y) | (x & z) | (y & z)) -#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x5A827999; a = S(a,s); } - - P( A, B, C, D, X[ 0], 3 ); - P( D, A, B, C, X[ 4], 5 ); - P( C, D, A, B, X[ 8], 9 ); - P( B, C, D, A, X[12], 13 ); - P( A, B, C, D, X[ 1], 3 ); - P( D, A, B, C, X[ 5], 5 ); - P( C, D, A, B, X[ 9], 9 ); - P( B, C, D, A, X[13], 13 ); - P( A, B, C, D, X[ 2], 3 ); - P( D, A, B, C, X[ 6], 5 ); - P( C, D, A, B, X[10], 9 ); - P( B, C, D, A, X[14], 13 ); - P( A, B, C, D, X[ 3], 3 ); - P( D, A, B, C, X[ 7], 5 ); - P( C, D, A, B, X[11], 9 ); - P( B, C, D, A, X[15], 13 ); - -#undef P -#undef F - -#define F(x,y,z) (x ^ y ^ z) -#define P(a,b,c,d,x,s) { a += F(b,c,d) + x + 0x6ED9EBA1; a = S(a,s); } - - P( A, B, C, D, X[ 0], 3 ); - P( D, A, B, C, X[ 8], 9 ); - P( C, D, A, B, X[ 4], 11 ); - P( B, C, D, A, X[12], 15 ); - P( A, B, C, D, X[ 2], 3 ); - P( D, A, B, C, X[10], 9 ); - P( C, D, A, B, X[ 6], 11 ); - P( B, C, D, A, X[14], 15 ); - P( A, B, C, D, X[ 1], 3 ); - P( D, A, B, C, X[ 9], 9 ); - P( C, D, A, B, X[ 5], 11 ); - P( B, C, D, A, X[13], 15 ); - P( A, B, C, D, X[ 3], 3 ); - P( D, A, B, C, X[11], 9 ); - P( C, D, A, B, X[ 7], 11 ); - P( B, C, D, A, X[15], 15 ); - -#undef F -#undef P - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; -} -#endif /* !MBEDTLS_MD4_PROCESS_ALT */ - -/* - * MD4 process buffer - */ -void mbedtls_md4_update( mbedtls_md4_context *ctx, const unsigned char *input, size_t ilen ) -{ - size_t fill; - uint32_t left; - - if( ilen == 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += (uint32_t) ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (uint32_t) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), - (void *) input, fill ); - mbedtls_md4_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - mbedtls_md4_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - { - memcpy( (void *) (ctx->buffer + left), - (void *) input, ilen ); - } -} - -static const unsigned char md4_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * MD4 final digest - */ -void mbedtls_md4_finish( mbedtls_md4_context *ctx, unsigned char output[16] ) -{ - uint32_t last, padn; - uint32_t high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_UINT32_LE( low, msglen, 0 ); - PUT_UINT32_LE( high, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - mbedtls_md4_update( ctx, (unsigned char *) md4_padding, padn ); - mbedtls_md4_update( ctx, msglen, 8 ); - - PUT_UINT32_LE( ctx->state[0], output, 0 ); - PUT_UINT32_LE( ctx->state[1], output, 4 ); - PUT_UINT32_LE( ctx->state[2], output, 8 ); - PUT_UINT32_LE( ctx->state[3], output, 12 ); -} - -#endif /* !MBEDTLS_MD4_ALT */ - -/* - * output = MD4( input buffer ) - */ -void mbedtls_md4( const unsigned char *input, size_t ilen, unsigned char output[16] ) -{ - mbedtls_md4_context ctx; - - mbedtls_md4_init( &ctx ); - mbedtls_md4_starts( &ctx ); - mbedtls_md4_update( &ctx, input, ilen ); - mbedtls_md4_finish( &ctx, output ); - mbedtls_md4_free( &ctx ); -} - -#if defined(MBEDTLS_SELF_TEST) - -/* - * RFC 1320 test vectors - */ -static const char md4_test_str[7][81] = -{ - { "" }, - { "a" }, - { "abc" }, - { "message digest" }, - { "abcdefghijklmnopqrstuvwxyz" }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, - { "12345678901234567890123456789012345678901234567890123456789012" \ - "345678901234567890" } -}; - -static const unsigned char md4_test_sum[7][16] = -{ - { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31, - 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 }, - { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46, - 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 }, - { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52, - 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D }, - { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8, - 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B }, - { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD, - 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 }, - { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35, - 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 }, - { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19, - 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 } -}; - -/* - * Checkup routine - */ -int mbedtls_md4_self_test( int verbose ) -{ - int i; - unsigned char md4sum[16]; - - for( i = 0; i < 7; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " MD4 test #%d: ", i + 1 ); - - mbedtls_md4( (unsigned char *) md4_test_str[i], - strlen( md4_test_str[i] ), md4sum ); - - if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_MD4_C */ diff --git a/components/mbedtls/library/md5.c b/components/mbedtls/library/md5.c deleted file mode 100644 index 5d972dc9dd..0000000000 --- a/components/mbedtls/library/md5.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - * RFC 1321 compliant MD5 implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The MD5 algorithm was designed by Ron Rivest in 1991. - * - * http://www.ietf.org/rfc/rfc1321.txt - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_MD5_C) - -#include "mbedtls/md5.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_MD5_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_UINT32_LE -#define GET_UINT32_LE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] ) \ - | ( (uint32_t) (b)[(i) + 1] << 8 ) \ - | ( (uint32_t) (b)[(i) + 2] << 16 ) \ - | ( (uint32_t) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_UINT32_LE -#define PUT_UINT32_LE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ - (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ - (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ - (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ -} -#endif - -void mbedtls_md5_init( mbedtls_md5_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_md5_context ) ); -} - -void mbedtls_md5_free( mbedtls_md5_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_md5_context ) ); -} - -void mbedtls_md5_clone( mbedtls_md5_context *dst, - const mbedtls_md5_context *src ) -{ - *dst = *src; -} - -/* - * MD5 context setup - */ -void mbedtls_md5_starts( mbedtls_md5_context *ctx ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; -} - -#if !defined(MBEDTLS_MD5_PROCESS_ALT) -void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] ) -{ - uint32_t X[16], A, B, C, D; - - GET_UINT32_LE( X[ 0], data, 0 ); - GET_UINT32_LE( X[ 1], data, 4 ); - GET_UINT32_LE( X[ 2], data, 8 ); - GET_UINT32_LE( X[ 3], data, 12 ); - GET_UINT32_LE( X[ 4], data, 16 ); - GET_UINT32_LE( X[ 5], data, 20 ); - GET_UINT32_LE( X[ 6], data, 24 ); - GET_UINT32_LE( X[ 7], data, 28 ); - GET_UINT32_LE( X[ 8], data, 32 ); - GET_UINT32_LE( X[ 9], data, 36 ); - GET_UINT32_LE( X[10], data, 40 ); - GET_UINT32_LE( X[11], data, 44 ); - GET_UINT32_LE( X[12], data, 48 ); - GET_UINT32_LE( X[13], data, 52 ); - GET_UINT32_LE( X[14], data, 56 ); - GET_UINT32_LE( X[15], data, 60 ); - -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - -#define P(a,b,c,d,k,s,t) \ -{ \ - a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ -} - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - -#define F(x,y,z) (z ^ (x & (y ^ z))) - - P( A, B, C, D, 0, 7, 0xD76AA478 ); - P( D, A, B, C, 1, 12, 0xE8C7B756 ); - P( C, D, A, B, 2, 17, 0x242070DB ); - P( B, C, D, A, 3, 22, 0xC1BDCEEE ); - P( A, B, C, D, 4, 7, 0xF57C0FAF ); - P( D, A, B, C, 5, 12, 0x4787C62A ); - P( C, D, A, B, 6, 17, 0xA8304613 ); - P( B, C, D, A, 7, 22, 0xFD469501 ); - P( A, B, C, D, 8, 7, 0x698098D8 ); - P( D, A, B, C, 9, 12, 0x8B44F7AF ); - P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); - P( B, C, D, A, 11, 22, 0x895CD7BE ); - P( A, B, C, D, 12, 7, 0x6B901122 ); - P( D, A, B, C, 13, 12, 0xFD987193 ); - P( C, D, A, B, 14, 17, 0xA679438E ); - P( B, C, D, A, 15, 22, 0x49B40821 ); - -#undef F - -#define F(x,y,z) (y ^ (z & (x ^ y))) - - P( A, B, C, D, 1, 5, 0xF61E2562 ); - P( D, A, B, C, 6, 9, 0xC040B340 ); - P( C, D, A, B, 11, 14, 0x265E5A51 ); - P( B, C, D, A, 0, 20, 0xE9B6C7AA ); - P( A, B, C, D, 5, 5, 0xD62F105D ); - P( D, A, B, C, 10, 9, 0x02441453 ); - P( C, D, A, B, 15, 14, 0xD8A1E681 ); - P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); - P( A, B, C, D, 9, 5, 0x21E1CDE6 ); - P( D, A, B, C, 14, 9, 0xC33707D6 ); - P( C, D, A, B, 3, 14, 0xF4D50D87 ); - P( B, C, D, A, 8, 20, 0x455A14ED ); - P( A, B, C, D, 13, 5, 0xA9E3E905 ); - P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); - P( C, D, A, B, 7, 14, 0x676F02D9 ); - P( B, C, D, A, 12, 20, 0x8D2A4C8A ); - -#undef F - -#define F(x,y,z) (x ^ y ^ z) - - P( A, B, C, D, 5, 4, 0xFFFA3942 ); - P( D, A, B, C, 8, 11, 0x8771F681 ); - P( C, D, A, B, 11, 16, 0x6D9D6122 ); - P( B, C, D, A, 14, 23, 0xFDE5380C ); - P( A, B, C, D, 1, 4, 0xA4BEEA44 ); - P( D, A, B, C, 4, 11, 0x4BDECFA9 ); - P( C, D, A, B, 7, 16, 0xF6BB4B60 ); - P( B, C, D, A, 10, 23, 0xBEBFBC70 ); - P( A, B, C, D, 13, 4, 0x289B7EC6 ); - P( D, A, B, C, 0, 11, 0xEAA127FA ); - P( C, D, A, B, 3, 16, 0xD4EF3085 ); - P( B, C, D, A, 6, 23, 0x04881D05 ); - P( A, B, C, D, 9, 4, 0xD9D4D039 ); - P( D, A, B, C, 12, 11, 0xE6DB99E5 ); - P( C, D, A, B, 15, 16, 0x1FA27CF8 ); - P( B, C, D, A, 2, 23, 0xC4AC5665 ); - -#undef F - -#define F(x,y,z) (y ^ (x | ~z)) - - P( A, B, C, D, 0, 6, 0xF4292244 ); - P( D, A, B, C, 7, 10, 0x432AFF97 ); - P( C, D, A, B, 14, 15, 0xAB9423A7 ); - P( B, C, D, A, 5, 21, 0xFC93A039 ); - P( A, B, C, D, 12, 6, 0x655B59C3 ); - P( D, A, B, C, 3, 10, 0x8F0CCC92 ); - P( C, D, A, B, 10, 15, 0xFFEFF47D ); - P( B, C, D, A, 1, 21, 0x85845DD1 ); - P( A, B, C, D, 8, 6, 0x6FA87E4F ); - P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); - P( C, D, A, B, 6, 15, 0xA3014314 ); - P( B, C, D, A, 13, 21, 0x4E0811A1 ); - P( A, B, C, D, 4, 6, 0xF7537E82 ); - P( D, A, B, C, 11, 10, 0xBD3AF235 ); - P( C, D, A, B, 2, 15, 0x2AD7D2BB ); - P( B, C, D, A, 9, 21, 0xEB86D391 ); - -#undef F - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; -} -#endif /* !MBEDTLS_MD5_PROCESS_ALT */ - -/* - * MD5 process buffer - */ -void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen ) -{ - size_t fill; - uint32_t left; - - if( ilen == 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += (uint32_t) ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (uint32_t) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_md5_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - mbedtls_md5_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - { - memcpy( (void *) (ctx->buffer + left), input, ilen ); - } -} - -static const unsigned char md5_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * MD5 final digest - */ -void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ) -{ - uint32_t last, padn; - uint32_t high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_UINT32_LE( low, msglen, 0 ); - PUT_UINT32_LE( high, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - mbedtls_md5_update( ctx, md5_padding, padn ); - mbedtls_md5_update( ctx, msglen, 8 ); - - PUT_UINT32_LE( ctx->state[0], output, 0 ); - PUT_UINT32_LE( ctx->state[1], output, 4 ); - PUT_UINT32_LE( ctx->state[2], output, 8 ); - PUT_UINT32_LE( ctx->state[3], output, 12 ); -} - -#endif /* !MBEDTLS_MD5_ALT */ - -/* - * output = MD5( input buffer ) - */ -void mbedtls_md5( const unsigned char *input, size_t ilen, unsigned char output[16] ) -{ - mbedtls_md5_context ctx; - - mbedtls_md5_init( &ctx ); - mbedtls_md5_starts( &ctx ); - mbedtls_md5_update( &ctx, input, ilen ); - mbedtls_md5_finish( &ctx, output ); - mbedtls_md5_free( &ctx ); -} - -#if defined(MBEDTLS_SELF_TEST) -/* - * RFC 1321 test vectors - */ -static const unsigned char md5_test_buf[7][81] = -{ - { "" }, - { "a" }, - { "abc" }, - { "message digest" }, - { "abcdefghijklmnopqrstuvwxyz" }, - { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, - { "12345678901234567890123456789012345678901234567890123456789012" \ - "345678901234567890" } -}; - -static const int md5_test_buflen[7] = -{ - 0, 1, 3, 14, 26, 62, 80 -}; - -static const unsigned char md5_test_sum[7][16] = -{ - { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, - 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, - { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, - 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, - { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, - 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, - { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, - 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, - { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, - 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, - { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, - 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, - { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, - 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } -}; - -/* - * Checkup routine - */ -int mbedtls_md5_self_test( int verbose ) -{ - int i; - unsigned char md5sum[16]; - - for( i = 0; i < 7; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " MD5 test #%d: ", i + 1 ); - - mbedtls_md5( md5_test_buf[i], md5_test_buflen[i], md5sum ); - - if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_MD5_C */ diff --git a/components/mbedtls/library/md_wrap.c b/components/mbedtls/library/md_wrap.c deleted file mode 100644 index 2cfcae200e..0000000000 --- a/components/mbedtls/library/md_wrap.c +++ /dev/null @@ -1,575 +0,0 @@ -/** - * \file md_wrap.c - * - * \brief Generic message digest wrapper for mbed TLS - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_MD_C) - -#include "mbedtls/md_internal.h" - -#if defined(MBEDTLS_MD2_C) -#include "mbedtls/md2.h" -#endif - -#if defined(MBEDTLS_MD4_C) -#include "mbedtls/md4.h" -#endif - -#if defined(MBEDTLS_MD5_C) -#include "mbedtls/md5.h" -#endif - -#if defined(MBEDTLS_RIPEMD160_C) -#include "mbedtls/ripemd160.h" -#endif - -#if defined(MBEDTLS_SHA1_C) -#include "mbedtls/sha1.h" -#endif - -#if defined(MBEDTLS_SHA256_C) -#include "mbedtls/sha256.h" -#endif - -#if defined(MBEDTLS_SHA512_C) -#include "mbedtls/sha512.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#if defined(MBEDTLS_MD2_C) - -static void md2_starts_wrap( void *ctx ) -{ - mbedtls_md2_starts( (mbedtls_md2_context *) ctx ); -} - -static void md2_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) -{ - mbedtls_md2_update( (mbedtls_md2_context *) ctx, input, ilen ); -} - -static void md2_finish_wrap( void *ctx, unsigned char *output ) -{ - mbedtls_md2_finish( (mbedtls_md2_context *) ctx, output ); -} - -static void *md2_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md2_context ) ); - - if( ctx != NULL ) - mbedtls_md2_init( (mbedtls_md2_context *) ctx ); - - return( ctx ); -} - -static void md2_ctx_free( void *ctx ) -{ - mbedtls_md2_free( (mbedtls_md2_context *) ctx ); - mbedtls_free( ctx ); -} - -static void md2_clone_wrap( void *dst, const void *src ) -{ - mbedtls_md2_clone( (mbedtls_md2_context *) dst, - (const mbedtls_md2_context *) src ); -} - -static void md2_process_wrap( void *ctx, const unsigned char *data ) -{ - ((void) data); - - mbedtls_md2_process( (mbedtls_md2_context *) ctx ); -} - -const mbedtls_md_info_t mbedtls_md2_info = { - MBEDTLS_MD_MD2, - "MD2", - 16, - 16, - md2_starts_wrap, - md2_update_wrap, - md2_finish_wrap, - mbedtls_md2, - md2_ctx_alloc, - md2_ctx_free, - md2_clone_wrap, - md2_process_wrap, -}; - -#endif /* MBEDTLS_MD2_C */ - -#if defined(MBEDTLS_MD4_C) - -static void md4_starts_wrap( void *ctx ) -{ - mbedtls_md4_starts( (mbedtls_md4_context *) ctx ); -} - -static void md4_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) -{ - mbedtls_md4_update( (mbedtls_md4_context *) ctx, input, ilen ); -} - -static void md4_finish_wrap( void *ctx, unsigned char *output ) -{ - mbedtls_md4_finish( (mbedtls_md4_context *) ctx, output ); -} - -static void *md4_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md4_context ) ); - - if( ctx != NULL ) - mbedtls_md4_init( (mbedtls_md4_context *) ctx ); - - return( ctx ); -} - -static void md4_ctx_free( void *ctx ) -{ - mbedtls_md4_free( (mbedtls_md4_context *) ctx ); - mbedtls_free( ctx ); -} - -static void md4_clone_wrap( void *dst, const void *src ) -{ - mbedtls_md4_clone( (mbedtls_md4_context *) dst, - (const mbedtls_md4_context *) src ); -} - -static void md4_process_wrap( void *ctx, const unsigned char *data ) -{ - mbedtls_md4_process( (mbedtls_md4_context *) ctx, data ); -} - -const mbedtls_md_info_t mbedtls_md4_info = { - MBEDTLS_MD_MD4, - "MD4", - 16, - 64, - md4_starts_wrap, - md4_update_wrap, - md4_finish_wrap, - mbedtls_md4, - md4_ctx_alloc, - md4_ctx_free, - md4_clone_wrap, - md4_process_wrap, -}; - -#endif /* MBEDTLS_MD4_C */ - -#if defined(MBEDTLS_MD5_C) - -static void md5_starts_wrap( void *ctx ) -{ - mbedtls_md5_starts( (mbedtls_md5_context *) ctx ); -} - -static void md5_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) -{ - mbedtls_md5_update( (mbedtls_md5_context *) ctx, input, ilen ); -} - -static void md5_finish_wrap( void *ctx, unsigned char *output ) -{ - mbedtls_md5_finish( (mbedtls_md5_context *) ctx, output ); -} - -static void *md5_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md5_context ) ); - - if( ctx != NULL ) - mbedtls_md5_init( (mbedtls_md5_context *) ctx ); - - return( ctx ); -} - -static void md5_ctx_free( void *ctx ) -{ - mbedtls_md5_free( (mbedtls_md5_context *) ctx ); - mbedtls_free( ctx ); -} - -static void md5_clone_wrap( void *dst, const void *src ) -{ - mbedtls_md5_clone( (mbedtls_md5_context *) dst, - (const mbedtls_md5_context *) src ); -} - -static void md5_process_wrap( void *ctx, const unsigned char *data ) -{ - mbedtls_md5_process( (mbedtls_md5_context *) ctx, data ); -} - -const mbedtls_md_info_t mbedtls_md5_info = { - MBEDTLS_MD_MD5, - "MD5", - 16, - 64, - md5_starts_wrap, - md5_update_wrap, - md5_finish_wrap, - mbedtls_md5, - md5_ctx_alloc, - md5_ctx_free, - md5_clone_wrap, - md5_process_wrap, -}; - -#endif /* MBEDTLS_MD5_C */ - -#if defined(MBEDTLS_RIPEMD160_C) - -static void ripemd160_starts_wrap( void *ctx ) -{ - mbedtls_ripemd160_starts( (mbedtls_ripemd160_context *) ctx ); -} - -static void ripemd160_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) -{ - mbedtls_ripemd160_update( (mbedtls_ripemd160_context *) ctx, input, ilen ); -} - -static void ripemd160_finish_wrap( void *ctx, unsigned char *output ) -{ - mbedtls_ripemd160_finish( (mbedtls_ripemd160_context *) ctx, output ); -} - -static void *ripemd160_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ripemd160_context ) ); - - if( ctx != NULL ) - mbedtls_ripemd160_init( (mbedtls_ripemd160_context *) ctx ); - - return( ctx ); -} - -static void ripemd160_ctx_free( void *ctx ) -{ - mbedtls_ripemd160_free( (mbedtls_ripemd160_context *) ctx ); - mbedtls_free( ctx ); -} - -static void ripemd160_clone_wrap( void *dst, const void *src ) -{ - mbedtls_ripemd160_clone( (mbedtls_ripemd160_context *) dst, - (const mbedtls_ripemd160_context *) src ); -} - -static void ripemd160_process_wrap( void *ctx, const unsigned char *data ) -{ - mbedtls_ripemd160_process( (mbedtls_ripemd160_context *) ctx, data ); -} - -const mbedtls_md_info_t mbedtls_ripemd160_info = { - MBEDTLS_MD_RIPEMD160, - "RIPEMD160", - 20, - 64, - ripemd160_starts_wrap, - ripemd160_update_wrap, - ripemd160_finish_wrap, - mbedtls_ripemd160, - ripemd160_ctx_alloc, - ripemd160_ctx_free, - ripemd160_clone_wrap, - ripemd160_process_wrap, -}; - -#endif /* MBEDTLS_RIPEMD160_C */ - -#if defined(MBEDTLS_SHA1_C) - -static void sha1_starts_wrap( void *ctx ) -{ - mbedtls_sha1_starts( (mbedtls_sha1_context *) ctx ); -} - -static void sha1_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) -{ - mbedtls_sha1_update( (mbedtls_sha1_context *) ctx, input, ilen ); -} - -static void sha1_finish_wrap( void *ctx, unsigned char *output ) -{ - mbedtls_sha1_finish( (mbedtls_sha1_context *) ctx, output ); -} - -static void *sha1_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha1_context ) ); - - if( ctx != NULL ) - mbedtls_sha1_init( (mbedtls_sha1_context *) ctx ); - - return( ctx ); -} - -static void sha1_clone_wrap( void *dst, const void *src ) -{ - mbedtls_sha1_clone( (mbedtls_sha1_context *) dst, - (const mbedtls_sha1_context *) src ); -} - -static void sha1_ctx_free( void *ctx ) -{ - mbedtls_sha1_free( (mbedtls_sha1_context *) ctx ); - mbedtls_free( ctx ); -} - -static void sha1_process_wrap( void *ctx, const unsigned char *data ) -{ - mbedtls_sha1_process( (mbedtls_sha1_context *) ctx, data ); -} - -const mbedtls_md_info_t mbedtls_sha1_info = { - MBEDTLS_MD_SHA1, - "SHA1", - 20, - 64, - sha1_starts_wrap, - sha1_update_wrap, - sha1_finish_wrap, - mbedtls_sha1, - sha1_ctx_alloc, - sha1_ctx_free, - sha1_clone_wrap, - sha1_process_wrap, -}; - -#endif /* MBEDTLS_SHA1_C */ - -/* - * Wrappers for generic message digests - */ -#if defined(MBEDTLS_SHA256_C) - -static void sha224_starts_wrap( void *ctx ) -{ - mbedtls_sha256_starts( (mbedtls_sha256_context *) ctx, 1 ); -} - -static void sha224_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) -{ - mbedtls_sha256_update( (mbedtls_sha256_context *) ctx, input, ilen ); -} - -static void sha224_finish_wrap( void *ctx, unsigned char *output ) -{ - mbedtls_sha256_finish( (mbedtls_sha256_context *) ctx, output ); -} - -static void sha224_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - mbedtls_sha256( input, ilen, output, 1 ); -} - -static void *sha224_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha256_context ) ); - - if( ctx != NULL ) - mbedtls_sha256_init( (mbedtls_sha256_context *) ctx ); - - return( ctx ); -} - -static void sha224_ctx_free( void *ctx ) -{ - mbedtls_sha256_free( (mbedtls_sha256_context *) ctx ); - mbedtls_free( ctx ); -} - -static void sha224_clone_wrap( void *dst, const void *src ) -{ - mbedtls_sha256_clone( (mbedtls_sha256_context *) dst, - (const mbedtls_sha256_context *) src ); -} - -static void sha224_process_wrap( void *ctx, const unsigned char *data ) -{ - mbedtls_sha256_process( (mbedtls_sha256_context *) ctx, data ); -} - -const mbedtls_md_info_t mbedtls_sha224_info = { - MBEDTLS_MD_SHA224, - "SHA224", - 28, - 64, - sha224_starts_wrap, - sha224_update_wrap, - sha224_finish_wrap, - sha224_wrap, - sha224_ctx_alloc, - sha224_ctx_free, - sha224_clone_wrap, - sha224_process_wrap, -}; - -static void sha256_starts_wrap( void *ctx ) -{ - mbedtls_sha256_starts( (mbedtls_sha256_context *) ctx, 0 ); -} - -static void sha256_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - mbedtls_sha256( input, ilen, output, 0 ); -} - -const mbedtls_md_info_t mbedtls_sha256_info = { - MBEDTLS_MD_SHA256, - "SHA256", - 32, - 64, - sha256_starts_wrap, - sha224_update_wrap, - sha224_finish_wrap, - sha256_wrap, - sha224_ctx_alloc, - sha224_ctx_free, - sha224_clone_wrap, - sha224_process_wrap, -}; - -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - -static void sha384_starts_wrap( void *ctx ) -{ - mbedtls_sha512_starts( (mbedtls_sha512_context *) ctx, 1 ); -} - -static void sha384_update_wrap( void *ctx, const unsigned char *input, - size_t ilen ) -{ - mbedtls_sha512_update( (mbedtls_sha512_context *) ctx, input, ilen ); -} - -static void sha384_finish_wrap( void *ctx, unsigned char *output ) -{ - mbedtls_sha512_finish( (mbedtls_sha512_context *) ctx, output ); -} - -static void sha384_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - mbedtls_sha512( input, ilen, output, 1 ); -} - -static void *sha384_ctx_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha512_context ) ); - - if( ctx != NULL ) - mbedtls_sha512_init( (mbedtls_sha512_context *) ctx ); - - return( ctx ); -} - -static void sha384_ctx_free( void *ctx ) -{ - mbedtls_sha512_free( (mbedtls_sha512_context *) ctx ); - mbedtls_free( ctx ); -} - -static void sha384_clone_wrap( void *dst, const void *src ) -{ - mbedtls_sha512_clone( (mbedtls_sha512_context *) dst, - (const mbedtls_sha512_context *) src ); -} - -static void sha384_process_wrap( void *ctx, const unsigned char *data ) -{ - mbedtls_sha512_process( (mbedtls_sha512_context *) ctx, data ); -} - -const mbedtls_md_info_t mbedtls_sha384_info = { - MBEDTLS_MD_SHA384, - "SHA384", - 48, - 128, - sha384_starts_wrap, - sha384_update_wrap, - sha384_finish_wrap, - sha384_wrap, - sha384_ctx_alloc, - sha384_ctx_free, - sha384_clone_wrap, - sha384_process_wrap, -}; - -static void sha512_starts_wrap( void *ctx ) -{ - mbedtls_sha512_starts( (mbedtls_sha512_context *) ctx, 0 ); -} - -static void sha512_wrap( const unsigned char *input, size_t ilen, - unsigned char *output ) -{ - mbedtls_sha512( input, ilen, output, 0 ); -} - -const mbedtls_md_info_t mbedtls_sha512_info = { - MBEDTLS_MD_SHA512, - "SHA512", - 64, - 128, - sha512_starts_wrap, - sha384_update_wrap, - sha384_finish_wrap, - sha512_wrap, - sha384_ctx_alloc, - sha384_ctx_free, - sha384_clone_wrap, - sha384_process_wrap, -}; - -#endif /* MBEDTLS_SHA512_C */ - -#endif /* MBEDTLS_MD_C */ diff --git a/components/mbedtls/library/memory_buffer_alloc.c b/components/mbedtls/library/memory_buffer_alloc.c deleted file mode 100644 index 545d5a2c32..0000000000 --- a/components/mbedtls/library/memory_buffer_alloc.c +++ /dev/null @@ -1,745 +0,0 @@ -/* - * Buffer-based memory allocator - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) -#include "mbedtls/memory_buffer_alloc.h" - -/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C - is dependent upon MBEDTLS_PLATFORM_C */ -#include "mbedtls/platform.h" - -#include - -#if defined(MBEDTLS_MEMORY_BACKTRACE) -#include -#endif - -#if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -#define MAGIC1 0xFF00AA55 -#define MAGIC2 0xEE119966 -#define MAX_BT 20 - -typedef struct _memory_header memory_header; -struct _memory_header -{ - size_t magic1; - size_t size; - size_t alloc; - memory_header *prev; - memory_header *next; - memory_header *prev_free; - memory_header *next_free; -#if defined(MBEDTLS_MEMORY_BACKTRACE) - char **trace; - size_t trace_count; -#endif - size_t magic2; -}; - -typedef struct -{ - unsigned char *buf; - size_t len; - memory_header *first; - memory_header *first_free; - int verify; -#if defined(MBEDTLS_MEMORY_DEBUG) - size_t alloc_count; - size_t free_count; - size_t total_used; - size_t maximum_used; - size_t header_count; - size_t maximum_header_count; -#endif -#if defined(MBEDTLS_THREADING_C) - mbedtls_threading_mutex_t mutex; -#endif -} -buffer_alloc_ctx; - -static buffer_alloc_ctx heap; - -#if defined(MBEDTLS_MEMORY_DEBUG) -static void debug_header( memory_header *hdr ) -{ -#if defined(MBEDTLS_MEMORY_BACKTRACE) - size_t i; -#endif - - mbedtls_fprintf( stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), " - "ALLOC(%zu), SIZE(%10zu)\n", - (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next, - hdr->alloc, hdr->size ); - mbedtls_fprintf( stderr, " FPREV(%10zu), FNEXT(%10zu)\n", - (size_t) hdr->prev_free, (size_t) hdr->next_free ); - -#if defined(MBEDTLS_MEMORY_BACKTRACE) - mbedtls_fprintf( stderr, "TRACE: \n" ); - for( i = 0; i < hdr->trace_count; i++ ) - mbedtls_fprintf( stderr, "%s\n", hdr->trace[i] ); - mbedtls_fprintf( stderr, "\n" ); -#endif -} - -static void debug_chain() -{ - memory_header *cur = heap.first; - - mbedtls_fprintf( stderr, "\nBlock list\n" ); - while( cur != NULL ) - { - debug_header( cur ); - cur = cur->next; - } - - mbedtls_fprintf( stderr, "Free list\n" ); - cur = heap.first_free; - - while( cur != NULL ) - { - debug_header( cur ); - cur = cur->next_free; - } -} -#endif /* MBEDTLS_MEMORY_DEBUG */ - -static int verify_header( memory_header *hdr ) -{ - if( hdr->magic1 != MAGIC1 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" ); -#endif - return( 1 ); - } - - if( hdr->magic2 != MAGIC2 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" ); -#endif - return( 1 ); - } - - if( hdr->alloc > 1 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: alloc has illegal value\n" ); -#endif - return( 1 ); - } - - if( hdr->prev != NULL && hdr->prev == hdr->next ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: prev == next\n" ); -#endif - return( 1 ); - } - - if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: prev_free == next_free\n" ); -#endif - return( 1 ); - } - - return( 0 ); -} - -static int verify_chain() -{ - memory_header *prv = heap.first, *cur = heap.first->next; - - if( verify_header( heap.first ) != 0 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: verification of first header " - "failed\n" ); -#endif - return( 1 ); - } - - if( heap.first->prev != NULL ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: verification failed: " - "first->prev != NULL\n" ); -#endif - return( 1 ); - } - - while( cur != NULL ) - { - if( verify_header( cur ) != 0 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: verification of header " - "failed\n" ); -#endif - return( 1 ); - } - - if( cur->prev != prv ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: verification failed: " - "cur->prev != prv\n" ); -#endif - return( 1 ); - } - - prv = cur; - cur = cur->next; - } - - return( 0 ); -} - -static void *buffer_alloc_calloc( size_t n, size_t size ) -{ - memory_header *new, *cur = heap.first_free; - unsigned char *p; - void *ret; - size_t original_len, len; -#if defined(MBEDTLS_MEMORY_BACKTRACE) - void *trace_buffer[MAX_BT]; - size_t trace_cnt; -#endif - - if( heap.buf == NULL || heap.first == NULL ) - return( NULL ); - - original_len = len = n * size; - - if( n != 0 && len / n != size ) - return( NULL ); - - if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) - { - len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE; - len += MBEDTLS_MEMORY_ALIGN_MULTIPLE; - } - - // Find block that fits - // - while( cur != NULL ) - { - if( cur->size >= len ) - break; - - cur = cur->next_free; - } - - if( cur == NULL ) - return( NULL ); - - if( cur->alloc != 0 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: block in free_list but allocated " - "data\n" ); -#endif - mbedtls_exit( 1 ); - } - -#if defined(MBEDTLS_MEMORY_DEBUG) - heap.alloc_count++; -#endif - - // Found location, split block if > memory_header + 4 room left - // - if( cur->size - len < sizeof(memory_header) + - MBEDTLS_MEMORY_ALIGN_MULTIPLE ) - { - cur->alloc = 1; - - // Remove from free_list - // - if( cur->prev_free != NULL ) - cur->prev_free->next_free = cur->next_free; - else - heap.first_free = cur->next_free; - - if( cur->next_free != NULL ) - cur->next_free->prev_free = cur->prev_free; - - cur->prev_free = NULL; - cur->next_free = NULL; - -#if defined(MBEDTLS_MEMORY_DEBUG) - heap.total_used += cur->size; - if( heap.total_used > heap.maximum_used ) - heap.maximum_used = heap.total_used; -#endif -#if defined(MBEDTLS_MEMORY_BACKTRACE) - trace_cnt = backtrace( trace_buffer, MAX_BT ); - cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); - cur->trace_count = trace_cnt; -#endif - - if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) - mbedtls_exit( 1 ); - - ret = (unsigned char *) cur + sizeof( memory_header ); - memset( ret, 0, original_len ); - - return( ret ); - } - - p = ( (unsigned char *) cur ) + sizeof(memory_header) + len; - new = (memory_header *) p; - - new->size = cur->size - len - sizeof(memory_header); - new->alloc = 0; - new->prev = cur; - new->next = cur->next; -#if defined(MBEDTLS_MEMORY_BACKTRACE) - new->trace = NULL; - new->trace_count = 0; -#endif - new->magic1 = MAGIC1; - new->magic2 = MAGIC2; - - if( new->next != NULL ) - new->next->prev = new; - - // Replace cur with new in free_list - // - new->prev_free = cur->prev_free; - new->next_free = cur->next_free; - if( new->prev_free != NULL ) - new->prev_free->next_free = new; - else - heap.first_free = new; - - if( new->next_free != NULL ) - new->next_free->prev_free = new; - - cur->alloc = 1; - cur->size = len; - cur->next = new; - cur->prev_free = NULL; - cur->next_free = NULL; - -#if defined(MBEDTLS_MEMORY_DEBUG) - heap.header_count++; - if( heap.header_count > heap.maximum_header_count ) - heap.maximum_header_count = heap.header_count; - heap.total_used += cur->size; - if( heap.total_used > heap.maximum_used ) - heap.maximum_used = heap.total_used; -#endif -#if defined(MBEDTLS_MEMORY_BACKTRACE) - trace_cnt = backtrace( trace_buffer, MAX_BT ); - cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); - cur->trace_count = trace_cnt; -#endif - - if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) - mbedtls_exit( 1 ); - - ret = (unsigned char *) cur + sizeof( memory_header ); - memset( ret, 0, original_len ); - - return( ret ); -} - -static void buffer_alloc_free( void *ptr ) -{ - memory_header *hdr, *old = NULL; - unsigned char *p = (unsigned char *) ptr; - - if( ptr == NULL || heap.buf == NULL || heap.first == NULL ) - return; - - if( p < heap.buf || p > heap.buf + heap.len ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed " - "space\n" ); -#endif - mbedtls_exit( 1 ); - } - - p -= sizeof(memory_header); - hdr = (memory_header *) p; - - if( verify_header( hdr ) != 0 ) - mbedtls_exit( 1 ); - - if( hdr->alloc != 1 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - mbedtls_fprintf( stderr, "FATAL: mbedtls_free() on unallocated " - "data\n" ); -#endif - mbedtls_exit( 1 ); - } - - hdr->alloc = 0; - -#if defined(MBEDTLS_MEMORY_DEBUG) - heap.free_count++; - heap.total_used -= hdr->size; -#endif - -#if defined(MBEDTLS_MEMORY_BACKTRACE) - free( hdr->trace ); - hdr->trace = NULL; - hdr->trace_count = 0; -#endif - - // Regroup with block before - // - if( hdr->prev != NULL && hdr->prev->alloc == 0 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - heap.header_count--; -#endif - hdr->prev->size += sizeof(memory_header) + hdr->size; - hdr->prev->next = hdr->next; - old = hdr; - hdr = hdr->prev; - - if( hdr->next != NULL ) - hdr->next->prev = hdr; - - memset( old, 0, sizeof(memory_header) ); - } - - // Regroup with block after - // - if( hdr->next != NULL && hdr->next->alloc == 0 ) - { -#if defined(MBEDTLS_MEMORY_DEBUG) - heap.header_count--; -#endif - hdr->size += sizeof(memory_header) + hdr->next->size; - old = hdr->next; - hdr->next = hdr->next->next; - - if( hdr->prev_free != NULL || hdr->next_free != NULL ) - { - if( hdr->prev_free != NULL ) - hdr->prev_free->next_free = hdr->next_free; - else - heap.first_free = hdr->next_free; - - if( hdr->next_free != NULL ) - hdr->next_free->prev_free = hdr->prev_free; - } - - hdr->prev_free = old->prev_free; - hdr->next_free = old->next_free; - - if( hdr->prev_free != NULL ) - hdr->prev_free->next_free = hdr; - else - heap.first_free = hdr; - - if( hdr->next_free != NULL ) - hdr->next_free->prev_free = hdr; - - if( hdr->next != NULL ) - hdr->next->prev = hdr; - - memset( old, 0, sizeof(memory_header) ); - } - - // Prepend to free_list if we have not merged - // (Does not have to stay in same order as prev / next list) - // - if( old == NULL ) - { - hdr->next_free = heap.first_free; - if( heap.first_free != NULL ) - heap.first_free->prev_free = hdr; - heap.first_free = hdr; - } - - if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_FREE ) && verify_chain() != 0 ) - mbedtls_exit( 1 ); -} - -void mbedtls_memory_buffer_set_verify( int verify ) -{ - heap.verify = verify; -} - -int mbedtls_memory_buffer_alloc_verify() -{ - return verify_chain(); -} - -#if defined(MBEDTLS_MEMORY_DEBUG) -void mbedtls_memory_buffer_alloc_status() -{ - mbedtls_fprintf( stderr, - "Current use: %zu blocks / %zu bytes, max: %zu blocks / " - "%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n", - heap.header_count, heap.total_used, - heap.maximum_header_count, heap.maximum_used, - heap.maximum_header_count * sizeof( memory_header ) - + heap.maximum_used, - heap.alloc_count, heap.free_count ); - - if( heap.first->next == NULL ) - mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" ); - else - { - mbedtls_fprintf( stderr, "Memory currently allocated:\n" ); - debug_chain(); - } -} - -void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ) -{ - *max_used = heap.maximum_used; - *max_blocks = heap.maximum_header_count; -} - -void mbedtls_memory_buffer_alloc_max_reset( void ) -{ - heap.maximum_used = 0; - heap.maximum_header_count = 0; -} - -void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ) -{ - *cur_used = heap.total_used; - *cur_blocks = heap.header_count; -} -#endif /* MBEDTLS_MEMORY_DEBUG */ - -#if defined(MBEDTLS_THREADING_C) -static void *buffer_alloc_calloc_mutexed( size_t n, size_t size ) -{ - void *buf; - if( mbedtls_mutex_lock( &heap.mutex ) != 0 ) - return( NULL ); - buf = buffer_alloc_calloc( n, size ); - if( mbedtls_mutex_unlock( &heap.mutex ) ) - return( NULL ); - return( buf ); -} - -static void buffer_alloc_free_mutexed( void *ptr ) -{ - /* We have to good option here, but corrupting the heap seems - * worse than loosing memory. */ - if( mbedtls_mutex_lock( &heap.mutex ) ) - return; - buffer_alloc_free( ptr ); - (void) mbedtls_mutex_unlock( &heap.mutex ); -} -#endif /* MBEDTLS_THREADING_C */ - -void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ) -{ - memset( &heap, 0, sizeof(buffer_alloc_ctx) ); - memset( buf, 0, len ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &heap.mutex ); - mbedtls_platform_set_calloc_free( buffer_alloc_calloc_mutexed, - buffer_alloc_free_mutexed ); -#else - mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free ); -#endif - - if( (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) - { - /* Adjust len first since buf is used in the computation */ - len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE - - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; - buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE - - (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; - } - - heap.buf = buf; - heap.len = len; - - heap.first = (memory_header *) buf; - heap.first->size = len - sizeof(memory_header); - heap.first->magic1 = MAGIC1; - heap.first->magic2 = MAGIC2; - heap.first_free = heap.first; -} - -void mbedtls_memory_buffer_alloc_free() -{ -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &heap.mutex ); -#endif - mbedtls_zeroize( &heap, sizeof(buffer_alloc_ctx) ); -} - -#if defined(MBEDTLS_SELF_TEST) -static int check_pointer( void *p ) -{ - if( p == NULL ) - return( -1 ); - - if( (size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0 ) - return( -1 ); - - return( 0 ); -} - -static int check_all_free( ) -{ - if( -#if defined(MBEDTLS_MEMORY_DEBUG) - heap.total_used != 0 || -#endif - heap.first != heap.first_free || - (void *) heap.first != (void *) heap.buf ) - { - return( -1 ); - } - - return( 0 ); -} - -#define TEST_ASSERT( condition ) \ - if( ! (condition) ) \ - { \ - if( verbose != 0 ) \ - mbedtls_printf( "failed\n" ); \ - \ - ret = 1; \ - goto cleanup; \ - } - -int mbedtls_memory_buffer_alloc_self_test( int verbose ) -{ - unsigned char buf[1024]; - unsigned char *p, *q, *r, *end; - int ret = 0; - - if( verbose != 0 ) - mbedtls_printf( " MBA test #1 (basic alloc-free cycle): " ); - - mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); - - p = mbedtls_calloc( 1, 1 ); - q = mbedtls_calloc( 1, 128 ); - r = mbedtls_calloc( 1, 16 ); - - TEST_ASSERT( check_pointer( p ) == 0 && - check_pointer( q ) == 0 && - check_pointer( r ) == 0 ); - - mbedtls_free( r ); - mbedtls_free( q ); - mbedtls_free( p ); - - TEST_ASSERT( check_all_free( ) == 0 ); - - /* Memorize end to compare with the next test */ - end = heap.buf + heap.len; - - mbedtls_memory_buffer_alloc_free( ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " MBA test #2 (buf not aligned): " ); - - mbedtls_memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 ); - - TEST_ASSERT( heap.buf + heap.len == end ); - - p = mbedtls_calloc( 1, 1 ); - q = mbedtls_calloc( 1, 128 ); - r = mbedtls_calloc( 1, 16 ); - - TEST_ASSERT( check_pointer( p ) == 0 && - check_pointer( q ) == 0 && - check_pointer( r ) == 0 ); - - mbedtls_free( r ); - mbedtls_free( q ); - mbedtls_free( p ); - - TEST_ASSERT( check_all_free( ) == 0 ); - - mbedtls_memory_buffer_alloc_free( ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " MBA test #3 (full): " ); - - mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); - - p = mbedtls_calloc( 1, sizeof( buf ) - sizeof( memory_header ) ); - - TEST_ASSERT( check_pointer( p ) == 0 ); - TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); - - mbedtls_free( p ); - - p = mbedtls_calloc( 1, sizeof( buf ) - 2 * sizeof( memory_header ) - 16 ); - q = mbedtls_calloc( 1, 16 ); - - TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 ); - TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); - - mbedtls_free( q ); - - TEST_ASSERT( mbedtls_calloc( 1, 17 ) == NULL ); - - mbedtls_free( p ); - - TEST_ASSERT( check_all_free( ) == 0 ); - - mbedtls_memory_buffer_alloc_free( ); - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - -cleanup: - mbedtls_memory_buffer_alloc_free( ); - - return( ret ); -} -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ diff --git a/components/mbedtls/library/oid.c b/components/mbedtls/library/oid.c deleted file mode 100644 index f13826ed74..0000000000 --- a/components/mbedtls/library/oid.c +++ /dev/null @@ -1,710 +0,0 @@ -/** - * \file oid.c - * - * \brief Object Identifier (OID) database - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_OID_C) - -#include "mbedtls/oid.h" -#include "mbedtls/rsa.h" - -#include -#include - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#define mbedtls_snprintf snprintf -#endif - -#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) -#include "mbedtls/x509.h" -#endif - -/* - * Macro to automatically add the size of #define'd OIDs - */ -#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) - -/* - * Macro to generate an internal function for oid_XXX_from_asn1() (used by - * the other functions) - */ -#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \ -static const TYPE_T * oid_ ## NAME ## _from_asn1( const mbedtls_asn1_buf *oid ) \ -{ \ - const TYPE_T *p = LIST; \ - const mbedtls_oid_descriptor_t *cur = (const mbedtls_oid_descriptor_t *) p; \ - if( p == NULL || oid == NULL ) return( NULL ); \ - while( cur->asn1 != NULL ) { \ - if( cur->asn1_len == oid->len && \ - memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \ - return( p ); \ - } \ - p++; \ - cur = (const mbedtls_oid_descriptor_t *) p; \ - } \ - return( NULL ); \ -} - -/* - * Macro to generate a function for retrieving a single attribute from the - * descriptor of an mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ -int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ -{ \ - const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ - if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ - *ATTR1 = data->descriptor.ATTR1; \ - return( 0 ); \ -} - -/* - * Macro to generate a function for retrieving a single attribute from an - * mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ -int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ -{ \ - const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ - if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ - *ATTR1 = data->ATTR1; \ - return( 0 ); \ -} - -/* - * Macro to generate a function for retrieving two attributes from an - * mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ - ATTR2_TYPE, ATTR2) \ -int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, ATTR2_TYPE * ATTR2 ) \ -{ \ - const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ - if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ - *ATTR1 = data->ATTR1; \ - *ATTR2 = data->ATTR2; \ - return( 0 ); \ -} - -/* - * Macro to generate a function for retrieving the OID based on a single - * attribute from a mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ -int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \ -{ \ - const TYPE_T *cur = LIST; \ - while( cur->descriptor.asn1 != NULL ) { \ - if( cur->ATTR1 == ATTR1 ) { \ - *oid = cur->descriptor.asn1; \ - *olen = cur->descriptor.asn1_len; \ - return( 0 ); \ - } \ - cur++; \ - } \ - return( MBEDTLS_ERR_OID_NOT_FOUND ); \ -} - -/* - * Macro to generate a function for retrieving the OID based on two - * attributes from a mbedtls_oid_descriptor_t wrapper. - */ -#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ - ATTR2_TYPE, ATTR2) \ -int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \ - size_t *olen ) \ -{ \ - const TYPE_T *cur = LIST; \ - while( cur->descriptor.asn1 != NULL ) { \ - if( cur->ATTR1 == ATTR1 && cur->ATTR2 == ATTR2 ) { \ - *oid = cur->descriptor.asn1; \ - *olen = cur->descriptor.asn1_len; \ - return( 0 ); \ - } \ - cur++; \ - } \ - return( MBEDTLS_ERR_OID_NOT_FOUND ); \ -} - -#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) -/* - * For X520 attribute types - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - const char *short_name; -} oid_x520_attr_t; - -static const oid_x520_attr_t oid_x520_attr_type[] = -{ - { - { ADD_LEN( MBEDTLS_OID_AT_CN ), "id-at-commonName", "Common Name" }, - "CN", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_COUNTRY ), "id-at-countryName", "Country" }, - "C", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_LOCALITY ), "id-at-locality", "Locality" }, - "L", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_STATE ), "id-at-state", "State" }, - "ST", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_ORGANIZATION ),"id-at-organizationName", "Organization" }, - "O", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_ORG_UNIT ), "id-at-organizationalUnitName", "Org Unit" }, - "OU", - }, - { - { ADD_LEN( MBEDTLS_OID_PKCS9_EMAIL ), "emailAddress", "E-mail address" }, - "emailAddress", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_SERIAL_NUMBER ),"id-at-serialNumber", "Serial number" }, - "serialNumber", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress", "Postal address" }, - "postalAddress", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_POSTAL_CODE ), "id-at-postalCode", "Postal code" }, - "postalCode", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_SUR_NAME ), "id-at-surName", "Surname" }, - "SN", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_GIVEN_NAME ), "id-at-givenName", "Given name" }, - "GN", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_INITIALS ), "id-at-initials", "Initials" }, - "initials", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" }, - "generationQualifier", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_TITLE ), "id-at-title", "Title" }, - "title", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_DN_QUALIFIER ),"id-at-dnQualifier", "Distinguished Name qualifier" }, - "dnQualifier", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_PSEUDONYM ), "id-at-pseudonym", "Pseudonym" }, - "pseudonym", - }, - { - { ADD_LEN( MBEDTLS_OID_DOMAIN_COMPONENT ), "id-domainComponent", "Domain component" }, - "DC", - }, - { - { ADD_LEN( MBEDTLS_OID_AT_UNIQUE_IDENTIFIER ), "id-at-uniqueIdentifier", "Unique Identifier" }, - "uniqueIdentifier", - }, - { - { NULL, 0, NULL, NULL }, - NULL, - } -}; - -FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) -FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name) - -/* - * For X509 extensions - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - int ext_type; -} oid_x509_ext_t; - -static const oid_x509_ext_t oid_x509_ext[] = -{ - { - { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" }, - MBEDTLS_X509_EXT_BASIC_CONSTRAINTS, - }, - { - { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" }, - MBEDTLS_X509_EXT_KEY_USAGE, - }, - { - { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" }, - MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE, - }, - { - { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" }, - MBEDTLS_X509_EXT_SUBJECT_ALT_NAME, - }, - { - { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" }, - MBEDTLS_X509_EXT_NS_CERT_TYPE, - }, - { - { NULL, 0, NULL, NULL }, - 0, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) -FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) - -static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = -{ - { ADD_LEN( MBEDTLS_OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" }, - { ADD_LEN( MBEDTLS_OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" }, - { ADD_LEN( MBEDTLS_OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" }, - { ADD_LEN( MBEDTLS_OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" }, - { ADD_LEN( MBEDTLS_OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" }, - { ADD_LEN( MBEDTLS_OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" }, - { NULL, 0, NULL, NULL }, -}; - -FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) -FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description) -#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ - -#if defined(MBEDTLS_MD_C) -/* - * For SignatureAlgorithmIdentifier - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_md_type_t md_alg; - mbedtls_pk_type_t pk_alg; -} oid_sig_alg_t; - -static const oid_sig_alg_t oid_sig_alg[] = -{ -#if defined(MBEDTLS_RSA_C) -#if defined(MBEDTLS_MD2_C) - { - { ADD_LEN( MBEDTLS_OID_PKCS1_MD2 ), "md2WithRSAEncryption", "RSA with MD2" }, - MBEDTLS_MD_MD2, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD2_C */ -#if defined(MBEDTLS_MD4_C) - { - { ADD_LEN( MBEDTLS_OID_PKCS1_MD4 ), "md4WithRSAEncryption", "RSA with MD4" }, - MBEDTLS_MD_MD4, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD4_C */ -#if defined(MBEDTLS_MD5_C) - { - { ADD_LEN( MBEDTLS_OID_PKCS1_MD5 ), "md5WithRSAEncryption", "RSA with MD5" }, - MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_MD5_C */ -#if defined(MBEDTLS_SHA1_C) - { - { ADD_LEN( MBEDTLS_OID_PKCS1_SHA1 ), "sha-1WithRSAEncryption", "RSA with SHA1" }, - MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) - { - { ADD_LEN( MBEDTLS_OID_PKCS1_SHA224 ), "sha224WithRSAEncryption", "RSA with SHA-224" }, - MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, - }, - { - { ADD_LEN( MBEDTLS_OID_PKCS1_SHA256 ), "sha256WithRSAEncryption", "RSA with SHA-256" }, - MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { - { ADD_LEN( MBEDTLS_OID_PKCS1_SHA384 ), "sha384WithRSAEncryption", "RSA with SHA-384" }, - MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, - }, - { - { ADD_LEN( MBEDTLS_OID_PKCS1_SHA512 ), "sha512WithRSAEncryption", "RSA with SHA-512" }, - MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_SHA512_C */ -#if defined(MBEDTLS_SHA1_C) - { - { ADD_LEN( MBEDTLS_OID_RSA_SHA_OBS ), "sha-1WithRSAEncryption", "RSA with SHA1" }, - MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, - }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECDSA_C) -#if defined(MBEDTLS_SHA1_C) - { - { ADD_LEN( MBEDTLS_OID_ECDSA_SHA1 ), "ecdsa-with-SHA1", "ECDSA with SHA1" }, - MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, - }, -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) - { - { ADD_LEN( MBEDTLS_OID_ECDSA_SHA224 ), "ecdsa-with-SHA224", "ECDSA with SHA224" }, - MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, - }, - { - { ADD_LEN( MBEDTLS_OID_ECDSA_SHA256 ), "ecdsa-with-SHA256", "ECDSA with SHA256" }, - MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, - }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { - { ADD_LEN( MBEDTLS_OID_ECDSA_SHA384 ), "ecdsa-with-SHA384", "ECDSA with SHA384" }, - MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, - }, - { - { ADD_LEN( MBEDTLS_OID_ECDSA_SHA512 ), "ecdsa-with-SHA512", "ECDSA with SHA512" }, - MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, - }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_ECDSA_C */ -#if defined(MBEDTLS_RSA_C) - { - { ADD_LEN( MBEDTLS_OID_RSASSA_PSS ), "RSASSA-PSS", "RSASSA-PSS" }, - MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, - }, -#endif /* MBEDTLS_RSA_C */ - { - { NULL, 0, NULL, NULL }, - MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) -FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description) -FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg) -FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedtls_pk_type_t, pk_alg, mbedtls_md_type_t, md_alg) -#endif /* MBEDTLS_MD_C */ - -/* - * For PublicKeyInfo (PKCS1, RFC 5480) - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_pk_type_t pk_alg; -} oid_pk_alg_t; - -static const oid_pk_alg_t oid_pk_alg[] = -{ - { - { ADD_LEN( MBEDTLS_OID_PKCS1_RSA ), "rsaEncryption", "RSA" }, - MBEDTLS_PK_RSA, - }, - { - { ADD_LEN( MBEDTLS_OID_EC_ALG_UNRESTRICTED ), "id-ecPublicKey", "Generic EC key" }, - MBEDTLS_PK_ECKEY, - }, - { - { ADD_LEN( MBEDTLS_OID_EC_ALG_ECDH ), "id-ecDH", "EC key for ECDH" }, - MBEDTLS_PK_ECKEY_DH, - }, - { - { NULL, 0, NULL, NULL }, - MBEDTLS_PK_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) -FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) -FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg) - -#if defined(MBEDTLS_ECP_C) -/* - * For namedCurve (RFC 5480) - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_ecp_group_id grp_id; -} oid_ecp_grp_t; - -static const oid_ecp_grp_t oid_ecp_grp[] = -{ -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192R1 ), "secp192r1", "secp192r1" }, - MBEDTLS_ECP_DP_SECP192R1, - }, -#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224R1 ), "secp224r1", "secp224r1" }, - MBEDTLS_ECP_DP_SECP224R1, - }, -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256R1 ), "secp256r1", "secp256r1" }, - MBEDTLS_ECP_DP_SECP256R1, - }, -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP384R1 ), "secp384r1", "secp384r1" }, - MBEDTLS_ECP_DP_SECP384R1, - }, -#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" }, - MBEDTLS_ECP_DP_SECP521R1, - }, -#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" }, - MBEDTLS_ECP_DP_SECP192K1, - }, -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" }, - MBEDTLS_ECP_DP_SECP224K1, - }, -#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" }, - MBEDTLS_ECP_DP_SECP256K1, - }, -#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" }, - MBEDTLS_ECP_DP_BP256R1, - }, -#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_BP384R1 ), "brainpoolP384r1","brainpool384r1" }, - MBEDTLS_ECP_DP_BP384R1, - }, -#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) - { - { ADD_LEN( MBEDTLS_OID_EC_GRP_BP512R1 ), "brainpoolP512r1","brainpool512r1" }, - MBEDTLS_ECP_DP_BP512R1, - }, -#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ - { - { NULL, 0, NULL, NULL }, - MBEDTLS_ECP_DP_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) -FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) -FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id) -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_CIPHER_C) -/* - * For PKCS#5 PBES2 encryption algorithm - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_cipher_type_t cipher_alg; -} oid_cipher_alg_t; - -static const oid_cipher_alg_t oid_cipher_alg[] = -{ - { - { ADD_LEN( MBEDTLS_OID_DES_CBC ), "desCBC", "DES-CBC" }, - MBEDTLS_CIPHER_DES_CBC, - }, - { - { ADD_LEN( MBEDTLS_OID_DES_EDE3_CBC ), "des-ede3-cbc", "DES-EDE3-CBC" }, - MBEDTLS_CIPHER_DES_EDE3_CBC, - }, - { - { NULL, 0, NULL, NULL }, - MBEDTLS_CIPHER_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) -FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg) -#endif /* MBEDTLS_CIPHER_C */ - -#if defined(MBEDTLS_MD_C) -/* - * For digestAlgorithm - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_md_type_t md_alg; -} oid_md_alg_t; - -static const oid_md_alg_t oid_md_alg[] = -{ -#if defined(MBEDTLS_MD2_C) - { - { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD2 ), "id-md2", "MD2" }, - MBEDTLS_MD_MD2, - }, -#endif /* MBEDTLS_MD2_C */ -#if defined(MBEDTLS_MD4_C) - { - { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD4 ), "id-md4", "MD4" }, - MBEDTLS_MD_MD4, - }, -#endif /* MBEDTLS_MD4_C */ -#if defined(MBEDTLS_MD5_C) - { - { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD5 ), "id-md5", "MD5" }, - MBEDTLS_MD_MD5, - }, -#endif /* MBEDTLS_MD5_C */ -#if defined(MBEDTLS_SHA1_C) - { - { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA1 ), "id-sha1", "SHA-1" }, - MBEDTLS_MD_SHA1, - }, -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) - { - { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA224 ), "id-sha224", "SHA-224" }, - MBEDTLS_MD_SHA224, - }, - { - { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA256 ), "id-sha256", "SHA-256" }, - MBEDTLS_MD_SHA256, - }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { - { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA384 ), "id-sha384", "SHA-384" }, - MBEDTLS_MD_SHA384, - }, - { - { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA512 ), "id-sha512", "SHA-512" }, - MBEDTLS_MD_SHA512, - }, -#endif /* MBEDTLS_SHA512_C */ - { - { NULL, 0, NULL, NULL }, - MBEDTLS_MD_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) -FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) -FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg) -#endif /* MBEDTLS_MD_C */ - -#if defined(MBEDTLS_PKCS12_C) -/* - * For PKCS#12 PBEs - */ -typedef struct { - mbedtls_oid_descriptor_t descriptor; - mbedtls_md_type_t md_alg; - mbedtls_cipher_type_t cipher_alg; -} oid_pkcs12_pbe_alg_t; - -static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = -{ - { - { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" }, - MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, - }, - { - { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" }, - MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, - }, - { - { NULL, 0, NULL, NULL }, - MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, - }, -}; - -FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) -FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, mbedtls_cipher_type_t, cipher_alg) -#endif /* MBEDTLS_PKCS12_C */ - -#define OID_SAFE_SNPRINTF \ - do { \ - if( ret < 0 || (size_t) ret >= n ) \ - return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); \ - \ - n -= (size_t) ret; \ - p += (size_t) ret; \ - } while( 0 ) - -/* Return the x.y.z.... style numeric string for the given OID */ -int mbedtls_oid_get_numeric_string( char *buf, size_t size, - const mbedtls_asn1_buf *oid ) -{ - int ret; - size_t i, n; - unsigned int value; - char *p; - - p = buf; - n = size; - - /* First byte contains first two dots */ - if( oid->len > 0 ) - { - ret = mbedtls_snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 ); - OID_SAFE_SNPRINTF; - } - - value = 0; - for( i = 1; i < oid->len; i++ ) - { - /* Prevent overflow in value. */ - if( ( ( value << 7 ) >> 7 ) != value ) - return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); - - value <<= 7; - value += oid->p[i] & 0x7F; - - if( !( oid->p[i] & 0x80 ) ) - { - /* Last byte */ - ret = mbedtls_snprintf( p, n, ".%d", value ); - OID_SAFE_SNPRINTF; - value = 0; - } - } - - return( (int) ( size - n ) ); -} - -#endif /* MBEDTLS_OID_C */ diff --git a/components/mbedtls/library/padlock.c b/components/mbedtls/library/padlock.c deleted file mode 100644 index b85ff9cd2c..0000000000 --- a/components/mbedtls/library/padlock.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * VIA PadLock support functions - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * This implementation is based on the VIA PadLock Programming Guide: - * - * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/ - * programming_guide.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PADLOCK_C) - -#include "mbedtls/padlock.h" - -#include - -#ifndef asm -#define asm __asm -#endif - -#if defined(MBEDTLS_HAVE_X86) - -/* - * PadLock detection routine - */ -int mbedtls_padlock_has_support( int feature ) -{ - static int flags = -1; - int ebx = 0, edx = 0; - - if( flags == -1 ) - { - asm( "movl %%ebx, %0 \n\t" - "movl $0xC0000000, %%eax \n\t" - "cpuid \n\t" - "cmpl $0xC0000001, %%eax \n\t" - "movl $0, %%edx \n\t" - "jb unsupported \n\t" - "movl $0xC0000001, %%eax \n\t" - "cpuid \n\t" - "unsupported: \n\t" - "movl %%edx, %1 \n\t" - "movl %2, %%ebx \n\t" - : "=m" (ebx), "=m" (edx) - : "m" (ebx) - : "eax", "ecx", "edx" ); - - flags = edx; - } - - return( flags & feature ); -} - -/* - * PadLock AES-ECB block en(de)cryption - */ -int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ) -{ - int ebx = 0; - uint32_t *rk; - uint32_t *blk; - uint32_t *ctrl; - unsigned char buf[256]; - - rk = ctx->rk; - blk = MBEDTLS_PADLOCK_ALIGN16( buf ); - memcpy( blk, input, 16 ); - - ctrl = blk + 4; - *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 ); - - asm( "pushfl \n\t" - "popfl \n\t" - "movl %%ebx, %0 \n\t" - "movl $1, %%ecx \n\t" - "movl %2, %%edx \n\t" - "movl %3, %%ebx \n\t" - "movl %4, %%esi \n\t" - "movl %4, %%edi \n\t" - ".byte 0xf3,0x0f,0xa7,0xc8 \n\t" - "movl %1, %%ebx \n\t" - : "=m" (ebx) - : "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk) - : "memory", "ecx", "edx", "esi", "edi" ); - - memcpy( output, blk, 16 ); - - return( 0 ); -} - -/* - * PadLock AES-CBC buffer en(de)cryption - */ -int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int ebx = 0; - size_t count; - uint32_t *rk; - uint32_t *iw; - uint32_t *ctrl; - unsigned char buf[256]; - - if( ( (long) input & 15 ) != 0 || - ( (long) output & 15 ) != 0 ) - return( MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED ); - - rk = ctx->rk; - iw = MBEDTLS_PADLOCK_ALIGN16( buf ); - memcpy( iw, iv, 16 ); - - ctrl = iw + 4; - *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode ^ 1 ) - 10 ) << 9 ); - - count = ( length + 15 ) >> 4; - - asm( "pushfl \n\t" - "popfl \n\t" - "movl %%ebx, %0 \n\t" - "movl %2, %%ecx \n\t" - "movl %3, %%edx \n\t" - "movl %4, %%ebx \n\t" - "movl %5, %%esi \n\t" - "movl %6, %%edi \n\t" - "movl %7, %%eax \n\t" - ".byte 0xf3,0x0f,0xa7,0xd0 \n\t" - "movl %1, %%ebx \n\t" - : "=m" (ebx) - : "m" (ebx), "m" (count), "m" (ctrl), - "m" (rk), "m" (input), "m" (output), "m" (iw) - : "memory", "eax", "ecx", "edx", "esi", "edi" ); - - memcpy( iv, iw, 16 ); - - return( 0 ); -} - -#endif /* MBEDTLS_HAVE_X86 */ - -#endif /* MBEDTLS_PADLOCK_C */ diff --git a/components/mbedtls/library/pem.c b/components/mbedtls/library/pem.c deleted file mode 100644 index 8dd86a4ac9..0000000000 --- a/components/mbedtls/library/pem.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Privacy Enhanced Mail (PEM) decoding - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) - -#include "mbedtls/pem.h" -#include "mbedtls/base64.h" -#include "mbedtls/des.h" -#include "mbedtls/aes.h" -#include "mbedtls/md5.h" -#include "mbedtls/cipher.h" - -#include - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#if defined(MBEDTLS_PEM_PARSE_C) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -void mbedtls_pem_init( mbedtls_pem_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_pem_context ) ); -} - -#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) -/* - * Read a 16-byte hex string and convert it to binary - */ -static int pem_get_iv( const unsigned char *s, unsigned char *iv, - size_t iv_len ) -{ - size_t i, j, k; - - memset( iv, 0, iv_len ); - - for( i = 0; i < iv_len * 2; i++, s++ ) - { - if( *s >= '0' && *s <= '9' ) j = *s - '0'; else - if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else - if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else - return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); - - k = ( ( i & 1 ) != 0 ) ? j : j << 4; - - iv[i >> 1] = (unsigned char)( iv[i >> 1] | k ); - } - - return( 0 ); -} - -static void pem_pbkdf1( unsigned char *key, size_t keylen, - unsigned char *iv, - const unsigned char *pwd, size_t pwdlen ) -{ - mbedtls_md5_context md5_ctx; - unsigned char md5sum[16]; - size_t use_len; - - mbedtls_md5_init( &md5_ctx ); - - /* - * key[ 0..15] = MD5(pwd || IV) - */ - mbedtls_md5_starts( &md5_ctx ); - mbedtls_md5_update( &md5_ctx, pwd, pwdlen ); - mbedtls_md5_update( &md5_ctx, iv, 8 ); - mbedtls_md5_finish( &md5_ctx, md5sum ); - - if( keylen <= 16 ) - { - memcpy( key, md5sum, keylen ); - - mbedtls_md5_free( &md5_ctx ); - mbedtls_zeroize( md5sum, 16 ); - return; - } - - memcpy( key, md5sum, 16 ); - - /* - * key[16..23] = MD5(key[ 0..15] || pwd || IV]) - */ - mbedtls_md5_starts( &md5_ctx ); - mbedtls_md5_update( &md5_ctx, md5sum, 16 ); - mbedtls_md5_update( &md5_ctx, pwd, pwdlen ); - mbedtls_md5_update( &md5_ctx, iv, 8 ); - mbedtls_md5_finish( &md5_ctx, md5sum ); - - use_len = 16; - if( keylen < 32 ) - use_len = keylen - 16; - - memcpy( key + 16, md5sum, use_len ); - - mbedtls_md5_free( &md5_ctx ); - mbedtls_zeroize( md5sum, 16 ); -} - -#if defined(MBEDTLS_DES_C) -/* - * Decrypt with DES-CBC, using PBKDF1 for key derivation - */ -static void pem_des_decrypt( unsigned char des_iv[8], - unsigned char *buf, size_t buflen, - const unsigned char *pwd, size_t pwdlen ) -{ - mbedtls_des_context des_ctx; - unsigned char des_key[8]; - - mbedtls_des_init( &des_ctx ); - - pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ); - - mbedtls_des_setkey_dec( &des_ctx, des_key ); - mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen, - des_iv, buf, buf ); - - mbedtls_des_free( &des_ctx ); - mbedtls_zeroize( des_key, 8 ); -} - -/* - * Decrypt with 3DES-CBC, using PBKDF1 for key derivation - */ -static void pem_des3_decrypt( unsigned char des3_iv[8], - unsigned char *buf, size_t buflen, - const unsigned char *pwd, size_t pwdlen ) -{ - mbedtls_des3_context des3_ctx; - unsigned char des3_key[24]; - - mbedtls_des3_init( &des3_ctx ); - - pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ); - - mbedtls_des3_set3key_dec( &des3_ctx, des3_key ); - mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen, - des3_iv, buf, buf ); - - mbedtls_des3_free( &des3_ctx ); - mbedtls_zeroize( des3_key, 24 ); -} -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_AES_C) -/* - * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation - */ -static void pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, - unsigned char *buf, size_t buflen, - const unsigned char *pwd, size_t pwdlen ) -{ - mbedtls_aes_context aes_ctx; - unsigned char aes_key[32]; - - mbedtls_aes_init( &aes_ctx ); - - pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ); - - mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ); - mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, - aes_iv, buf, buf ); - - mbedtls_aes_free( &aes_ctx ); - mbedtls_zeroize( aes_key, keylen ); -} -#endif /* MBEDTLS_AES_C */ - -#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ - -int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, - const unsigned char *data, const unsigned char *pwd, - size_t pwdlen, size_t *use_len ) -{ - int ret, enc; - size_t len; - unsigned char *buf; - const unsigned char *s1, *s2, *end; -#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) - unsigned char pem_iv[16]; - mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE; -#else - ((void) pwd); - ((void) pwdlen); -#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ - - if( ctx == NULL ) - return( MBEDTLS_ERR_PEM_BAD_INPUT_DATA ); - - s1 = (unsigned char *) strstr( (const char *) data, header ); - - if( s1 == NULL ) - return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); - - s2 = (unsigned char *) strstr( (const char *) data, footer ); - - if( s2 == NULL || s2 <= s1 ) - return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); - - s1 += strlen( header ); - if( *s1 == ' ' ) s1++; - if( *s1 == '\r' ) s1++; - if( *s1 == '\n' ) s1++; - else return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); - - end = s2; - end += strlen( footer ); - if( *end == ' ' ) end++; - if( *end == '\r' ) end++; - if( *end == '\n' ) end++; - *use_len = end - data; - - enc = 0; - - if( s2 - s1 >= 22 && memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) - { -#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) - enc++; - - s1 += 22; - if( *s1 == '\r' ) s1++; - if( *s1 == '\n' ) s1++; - else return( MBEDTLS_ERR_PEM_INVALID_DATA ); - - -#if defined(MBEDTLS_DES_C) - if( s2 - s1 >= 23 && memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) - { - enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; - - s1 += 23; - if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8 ) != 0 ) - return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); - - s1 += 16; - } - else if( s2 - s1 >= 18 && memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) - { - enc_alg = MBEDTLS_CIPHER_DES_CBC; - - s1 += 18; - if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8) != 0 ) - return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); - - s1 += 16; - } -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_AES_C) - if( s2 - s1 >= 14 && memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) - { - if( s2 - s1 < 22 ) - return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); - else if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) - enc_alg = MBEDTLS_CIPHER_AES_128_CBC; - else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 ) - enc_alg = MBEDTLS_CIPHER_AES_192_CBC; - else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 ) - enc_alg = MBEDTLS_CIPHER_AES_256_CBC; - else - return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); - - s1 += 22; - if( s2 - s1 < 32 || pem_get_iv( s1, pem_iv, 16 ) != 0 ) - return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); - - s1 += 32; - } -#endif /* MBEDTLS_AES_C */ - - if( enc_alg == MBEDTLS_CIPHER_NONE ) - return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); - - if( *s1 == '\r' ) s1++; - if( *s1 == '\n' ) s1++; - else return( MBEDTLS_ERR_PEM_INVALID_DATA ); -#else - return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); -#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ - } - - if( s1 >= s2 ) - return( MBEDTLS_ERR_PEM_INVALID_DATA ); - - ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 ); - - if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER ) - return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); - - if( ( buf = mbedtls_calloc( 1, len ) ) == NULL ) - return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); - - if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 ) - { - mbedtls_free( buf ); - return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); - } - - if( enc != 0 ) - { -#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) - if( pwd == NULL ) - { - mbedtls_free( buf ); - return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ); - } - -#if defined(MBEDTLS_DES_C) - if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC ) - pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); - else if( enc_alg == MBEDTLS_CIPHER_DES_CBC ) - pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_AES_C) - if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC ) - pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); - else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC ) - pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); - else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC ) - pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); -#endif /* MBEDTLS_AES_C */ - - /* - * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 - * length bytes (allow 4 to be sure) in all known use cases. - * - * Use that as heurisitic to try detecting password mismatchs. - */ - if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) - { - mbedtls_free( buf ); - return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ); - } -#else - mbedtls_free( buf ); - return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); -#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ - } - - ctx->buf = buf; - ctx->buflen = len; - - return( 0 ); -} - -void mbedtls_pem_free( mbedtls_pem_context *ctx ) -{ - mbedtls_free( ctx->buf ); - mbedtls_free( ctx->info ); - - mbedtls_zeroize( ctx, sizeof( mbedtls_pem_context ) ); -} -#endif /* MBEDTLS_PEM_PARSE_C */ - -#if defined(MBEDTLS_PEM_WRITE_C) -int mbedtls_pem_write_buffer( const char *header, const char *footer, - const unsigned char *der_data, size_t der_len, - unsigned char *buf, size_t buf_len, size_t *olen ) -{ - int ret; - unsigned char *encode_buf, *c, *p = buf; - size_t len = 0, use_len, add_len = 0; - - mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len ); - add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1; - - if( use_len + add_len > buf_len ) - { - *olen = use_len + add_len; - return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); - } - - if( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL ) - return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); - - if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data, - der_len ) ) != 0 ) - { - mbedtls_free( encode_buf ); - return( ret ); - } - - memcpy( p, header, strlen( header ) ); - p += strlen( header ); - c = encode_buf; - - while( use_len ) - { - len = ( use_len > 64 ) ? 64 : use_len; - memcpy( p, c, len ); - use_len -= len; - p += len; - c += len; - *p++ = '\n'; - } - - memcpy( p, footer, strlen( footer ) ); - p += strlen( footer ); - - *p++ = '\0'; - *olen = p - buf; - - mbedtls_free( encode_buf ); - return( 0 ); -} -#endif /* MBEDTLS_PEM_WRITE_C */ -#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ diff --git a/components/mbedtls/library/pk.c b/components/mbedtls/library/pk.c deleted file mode 100644 index 8d13bc5ce3..0000000000 --- a/components/mbedtls/library/pk.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Public Key abstraction layer - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PK_C) -#include "mbedtls/pk.h" -#include "mbedtls/pk_internal.h" - -#include "mbedtls/bignum.h" - -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif - -#include - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * Initialise a mbedtls_pk_context - */ -void mbedtls_pk_init( mbedtls_pk_context *ctx ) -{ - if( ctx == NULL ) - return; - - ctx->pk_info = NULL; - ctx->pk_ctx = NULL; -} - -/* - * Free (the components of) a mbedtls_pk_context - */ -void mbedtls_pk_free( mbedtls_pk_context *ctx ) -{ - if( ctx == NULL || ctx->pk_info == NULL ) - return; - - ctx->pk_info->ctx_free_func( ctx->pk_ctx ); - - mbedtls_zeroize( ctx, sizeof( mbedtls_pk_context ) ); -} - -/* - * Get pk_info structure from type - */ -const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ) -{ - switch( pk_type ) { -#if defined(MBEDTLS_RSA_C) - case MBEDTLS_PK_RSA: - return( &mbedtls_rsa_info ); -#endif -#if defined(MBEDTLS_ECP_C) - case MBEDTLS_PK_ECKEY: - return( &mbedtls_eckey_info ); - case MBEDTLS_PK_ECKEY_DH: - return( &mbedtls_eckeydh_info ); -#endif -#if defined(MBEDTLS_ECDSA_C) - case MBEDTLS_PK_ECDSA: - return( &mbedtls_ecdsa_info ); -#endif - /* MBEDTLS_PK_RSA_ALT omitted on purpose */ - default: - return( NULL ); - } -} - -/* - * Initialise context - */ -int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ) -{ - if( ctx == NULL || info == NULL || ctx->pk_info != NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) - return( MBEDTLS_ERR_PK_ALLOC_FAILED ); - - ctx->pk_info = info; - - return( 0 ); -} - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/* - * Initialize an RSA-alt context - */ -int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, - mbedtls_pk_rsa_alt_decrypt_func decrypt_func, - mbedtls_pk_rsa_alt_sign_func sign_func, - mbedtls_pk_rsa_alt_key_len_func key_len_func ) -{ - mbedtls_rsa_alt_context *rsa_alt; - const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; - - if( ctx == NULL || ctx->pk_info != NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) - return( MBEDTLS_ERR_PK_ALLOC_FAILED ); - - ctx->pk_info = info; - - rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx; - - rsa_alt->key = key; - rsa_alt->decrypt_func = decrypt_func; - rsa_alt->sign_func = sign_func; - rsa_alt->key_len_func = key_len_func; - - return( 0 ); -} -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - -/* - * Tell if a PK can do the operations of the given type - */ -int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ) -{ - /* null or NONE context can't do anything */ - if( ctx == NULL || ctx->pk_info == NULL ) - return( 0 ); - - return( ctx->pk_info->can_do( type ) ); -} - -/* - * Helper for mbedtls_pk_sign and mbedtls_pk_verify - */ -static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len ) -{ - const mbedtls_md_info_t *md_info; - - if( *hash_len != 0 ) - return( 0 ); - - if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) - return( -1 ); - - *hash_len = mbedtls_md_get_size( md_info ); - return( 0 ); -} - -/* - * Verify a signature - */ -int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ) -{ - if( ctx == NULL || ctx->pk_info == NULL || - pk_hashlen_helper( md_alg, &hash_len ) != 0 ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ctx->pk_info->verify_func == NULL ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len, - sig, sig_len ) ); -} - -/* - * Verify a signature with options - */ -int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, - mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ) -{ - if( ctx == NULL || ctx->pk_info == NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ! mbedtls_pk_can_do( ctx, type ) ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - if( type == MBEDTLS_PK_RSASSA_PSS ) - { -#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) - int ret; - const mbedtls_pk_rsassa_pss_options *pss_opts; - -#if defined(MBEDTLS_HAVE_INT64) - if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); -#endif /* MBEDTLS_HAVE_INT64 */ - - if( options == NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; - - if( sig_len < mbedtls_pk_get_len( ctx ) ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ), - NULL, NULL, MBEDTLS_RSA_PUBLIC, - md_alg, (unsigned int) hash_len, hash, - pss_opts->mgf1_hash_id, - pss_opts->expected_salt_len, - sig ); - if( ret != 0 ) - return( ret ); - - if( sig_len > mbedtls_pk_get_len( ctx ) ) - return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); - - return( 0 ); -#else - return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); -#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ - } - - /* General case: no options */ - if( options != NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); -} - -/* - * Make a signature - */ -int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - if( ctx == NULL || ctx->pk_info == NULL || - pk_hashlen_helper( md_alg, &hash_len ) != 0 ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ctx->pk_info->sign_func == NULL ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len, - sig, sig_len, f_rng, p_rng ) ); -} - -/* - * Decrypt message - */ -int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - if( ctx == NULL || ctx->pk_info == NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ctx->pk_info->decrypt_func == NULL ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen, - output, olen, osize, f_rng, p_rng ) ); -} - -/* - * Encrypt message - */ -int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - if( ctx == NULL || ctx->pk_info == NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ctx->pk_info->encrypt_func == NULL ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen, - output, olen, osize, f_rng, p_rng ) ); -} - -/* - * Check public-private key pair - */ -int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ) -{ - if( pub == NULL || pub->pk_info == NULL || - prv == NULL || prv->pk_info == NULL || - prv->pk_info->check_pair_func == NULL ) - { - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - } - - if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT ) - { - if( pub->pk_info->type != MBEDTLS_PK_RSA ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - } - else - { - if( pub->pk_info != prv->pk_info ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - } - - return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) ); -} - -/* - * Get key size in bits - */ -size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) -{ - if( ctx == NULL || ctx->pk_info == NULL ) - return( 0 ); - - return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) ); -} - -/* - * Export debug information - */ -int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ) -{ - if( ctx == NULL || ctx->pk_info == NULL ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - if( ctx->pk_info->debug_func == NULL ) - return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - - ctx->pk_info->debug_func( ctx->pk_ctx, items ); - return( 0 ); -} - -/* - * Access the PK type name - */ -const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx ) -{ - if( ctx == NULL || ctx->pk_info == NULL ) - return( "invalid PK" ); - - return( ctx->pk_info->name ); -} - -/* - * Access the PK type - */ -mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ) -{ - if( ctx == NULL || ctx->pk_info == NULL ) - return( MBEDTLS_PK_NONE ); - - return( ctx->pk_info->type ); -} - -#endif /* MBEDTLS_PK_C */ diff --git a/components/mbedtls/library/pk_wrap.c b/components/mbedtls/library/pk_wrap.c deleted file mode 100644 index db6274cbf9..0000000000 --- a/components/mbedtls/library/pk_wrap.c +++ /dev/null @@ -1,513 +0,0 @@ -/* - * Public Key abstraction layer: wrapper functions - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PK_C) -#include "mbedtls/pk_internal.h" - -/* Even if RSA not activated, for the sake of RSA-alt */ -#include "mbedtls/rsa.h" -#include "mbedtls/bignum.h" - -#include - -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif - -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} -#endif - -#if defined(MBEDTLS_RSA_C) -static int rsa_can_do( mbedtls_pk_type_t type ) -{ - return( type == MBEDTLS_PK_RSA || - type == MBEDTLS_PK_RSASSA_PSS ); -} - -static size_t rsa_get_bitlen( const void *ctx ) -{ - return( 8 * ((const mbedtls_rsa_context *) ctx)->len ); -} - -static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ) -{ - int ret; - -#if defined(MBEDTLS_HAVE_INT64) - if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); -#endif /* MBEDTLS_HAVE_INT64 */ - - if( sig_len < ((mbedtls_rsa_context *) ctx)->len ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - if( ( ret = mbedtls_rsa_pkcs1_verify( (mbedtls_rsa_context *) ctx, NULL, NULL, - MBEDTLS_RSA_PUBLIC, md_alg, - (unsigned int) hash_len, hash, sig ) ) != 0 ) - return( ret ); - - if( sig_len > ((mbedtls_rsa_context *) ctx)->len ) - return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); - - return( 0 ); -} - -static int rsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ -#if defined(MBEDTLS_HAVE_INT64) - if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); -#endif /* MBEDTLS_HAVE_INT64 */ - - *sig_len = ((mbedtls_rsa_context *) ctx)->len; - - return( mbedtls_rsa_pkcs1_sign( (mbedtls_rsa_context *) ctx, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, - md_alg, (unsigned int) hash_len, hash, sig ) ); -} - -static int rsa_decrypt_wrap( void *ctx, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - if( ilen != ((mbedtls_rsa_context *) ctx)->len ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - return( mbedtls_rsa_pkcs1_decrypt( (mbedtls_rsa_context *) ctx, f_rng, p_rng, - MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); -} - -static int rsa_encrypt_wrap( void *ctx, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - *olen = ((mbedtls_rsa_context *) ctx)->len; - - if( *olen > osize ) - return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); - - return( mbedtls_rsa_pkcs1_encrypt( (mbedtls_rsa_context *) ctx, - f_rng, p_rng, MBEDTLS_RSA_PUBLIC, ilen, input, output ) ); -} - -static int rsa_check_pair_wrap( const void *pub, const void *prv ) -{ - return( mbedtls_rsa_check_pub_priv( (const mbedtls_rsa_context *) pub, - (const mbedtls_rsa_context *) prv ) ); -} - -static void *rsa_alloc_wrap( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_context ) ); - - if( ctx != NULL ) - mbedtls_rsa_init( (mbedtls_rsa_context *) ctx, 0, 0 ); - - return( ctx ); -} - -static void rsa_free_wrap( void *ctx ) -{ - mbedtls_rsa_free( (mbedtls_rsa_context *) ctx ); - mbedtls_free( ctx ); -} - -static void rsa_debug( const void *ctx, mbedtls_pk_debug_item *items ) -{ - items->type = MBEDTLS_PK_DEBUG_MPI; - items->name = "rsa.N"; - items->value = &( ((mbedtls_rsa_context *) ctx)->N ); - - items++; - - items->type = MBEDTLS_PK_DEBUG_MPI; - items->name = "rsa.E"; - items->value = &( ((mbedtls_rsa_context *) ctx)->E ); -} - -const mbedtls_pk_info_t mbedtls_rsa_info = { - MBEDTLS_PK_RSA, - "RSA", - rsa_get_bitlen, - rsa_can_do, - rsa_verify_wrap, - rsa_sign_wrap, - rsa_decrypt_wrap, - rsa_encrypt_wrap, - rsa_check_pair_wrap, - rsa_alloc_wrap, - rsa_free_wrap, - rsa_debug, -}; -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) -/* - * Generic EC key - */ -static int eckey_can_do( mbedtls_pk_type_t type ) -{ - return( type == MBEDTLS_PK_ECKEY || - type == MBEDTLS_PK_ECKEY_DH || - type == MBEDTLS_PK_ECDSA ); -} - -static size_t eckey_get_bitlen( const void *ctx ) -{ - return( ((mbedtls_ecp_keypair *) ctx)->grp.pbits ); -} - -#if defined(MBEDTLS_ECDSA_C) -/* Forward declarations */ -static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ); - -static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); - -static int eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ) -{ - int ret; - mbedtls_ecdsa_context ecdsa; - - mbedtls_ecdsa_init( &ecdsa ); - - if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) - ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len ); - - mbedtls_ecdsa_free( &ecdsa ); - - return( ret ); -} - -static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - int ret; - mbedtls_ecdsa_context ecdsa; - - mbedtls_ecdsa_init( &ecdsa ); - - if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) - ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len, - f_rng, p_rng ); - - mbedtls_ecdsa_free( &ecdsa ); - - return( ret ); -} - -#endif /* MBEDTLS_ECDSA_C */ - -static int eckey_check_pair( const void *pub, const void *prv ) -{ - return( mbedtls_ecp_check_pub_priv( (const mbedtls_ecp_keypair *) pub, - (const mbedtls_ecp_keypair *) prv ) ); -} - -static void *eckey_alloc_wrap( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); - - if( ctx != NULL ) - mbedtls_ecp_keypair_init( ctx ); - - return( ctx ); -} - -static void eckey_free_wrap( void *ctx ) -{ - mbedtls_ecp_keypair_free( (mbedtls_ecp_keypair *) ctx ); - mbedtls_free( ctx ); -} - -static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items ) -{ - items->type = MBEDTLS_PK_DEBUG_ECP; - items->name = "eckey.Q"; - items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q ); -} - -const mbedtls_pk_info_t mbedtls_eckey_info = { - MBEDTLS_PK_ECKEY, - "EC", - eckey_get_bitlen, - eckey_can_do, -#if defined(MBEDTLS_ECDSA_C) - eckey_verify_wrap, - eckey_sign_wrap, -#else - NULL, - NULL, -#endif - NULL, - NULL, - eckey_check_pair, - eckey_alloc_wrap, - eckey_free_wrap, - eckey_debug, -}; - -/* - * EC key restricted to ECDH - */ -static int eckeydh_can_do( mbedtls_pk_type_t type ) -{ - return( type == MBEDTLS_PK_ECKEY || - type == MBEDTLS_PK_ECKEY_DH ); -} - -const mbedtls_pk_info_t mbedtls_eckeydh_info = { - MBEDTLS_PK_ECKEY_DH, - "EC_DH", - eckey_get_bitlen, /* Same underlying key structure */ - eckeydh_can_do, - NULL, - NULL, - NULL, - NULL, - eckey_check_pair, - eckey_alloc_wrap, /* Same underlying key structure */ - eckey_free_wrap, /* Same underlying key structure */ - eckey_debug, /* Same underlying key structure */ -}; -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_ECDSA_C) -static int ecdsa_can_do( mbedtls_pk_type_t type ) -{ - return( type == MBEDTLS_PK_ECDSA ); -} - -static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ) -{ - int ret; - ((void) md_alg); - - ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx, - hash, hash_len, sig, sig_len ); - - if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) - return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); - - return( ret ); -} - -static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - return( mbedtls_ecdsa_write_signature( (mbedtls_ecdsa_context *) ctx, - md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) ); -} - -static void *ecdsa_alloc_wrap( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) ); - - if( ctx != NULL ) - mbedtls_ecdsa_init( (mbedtls_ecdsa_context *) ctx ); - - return( ctx ); -} - -static void ecdsa_free_wrap( void *ctx ) -{ - mbedtls_ecdsa_free( (mbedtls_ecdsa_context *) ctx ); - mbedtls_free( ctx ); -} - -const mbedtls_pk_info_t mbedtls_ecdsa_info = { - MBEDTLS_PK_ECDSA, - "ECDSA", - eckey_get_bitlen, /* Compatible key structures */ - ecdsa_can_do, - ecdsa_verify_wrap, - ecdsa_sign_wrap, - NULL, - NULL, - eckey_check_pair, /* Compatible key structures */ - ecdsa_alloc_wrap, - ecdsa_free_wrap, - eckey_debug, /* Compatible key structures */ -}; -#endif /* MBEDTLS_ECDSA_C */ - -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) -/* - * Support for alternative RSA-private implementations - */ - -static int rsa_alt_can_do( mbedtls_pk_type_t type ) -{ - return( type == MBEDTLS_PK_RSA ); -} - -static size_t rsa_alt_get_bitlen( const void *ctx ) -{ - const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx; - - return( 8 * rsa_alt->key_len_func( rsa_alt->key ) ); -} - -static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, - const unsigned char *hash, size_t hash_len, - unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; - -#if defined(MBEDTLS_HAVE_INT64) - if( UINT_MAX < hash_len ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); -#endif /* MBEDTLS_HAVE_INT64 */ - - *sig_len = rsa_alt->key_len_func( rsa_alt->key ); - - return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, - md_alg, (unsigned int) hash_len, hash, sig ) ); -} - -static int rsa_alt_decrypt_wrap( void *ctx, - const unsigned char *input, size_t ilen, - unsigned char *output, size_t *olen, size_t osize, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; - - ((void) f_rng); - ((void) p_rng); - - if( ilen != rsa_alt->key_len_func( rsa_alt->key ) ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - return( rsa_alt->decrypt_func( rsa_alt->key, - MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); -} - -#if defined(MBEDTLS_RSA_C) -static int rsa_alt_check_pair( const void *pub, const void *prv ) -{ - unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; - unsigned char hash[32]; - size_t sig_len = 0; - int ret; - - if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) ) - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - - memset( hash, 0x2a, sizeof( hash ) ); - - if( ( ret = rsa_alt_sign_wrap( (void *) prv, MBEDTLS_MD_NONE, - hash, sizeof( hash ), - sig, &sig_len, NULL, NULL ) ) != 0 ) - { - return( ret ); - } - - if( rsa_verify_wrap( (void *) pub, MBEDTLS_MD_NONE, - hash, sizeof( hash ), sig, sig_len ) != 0 ) - { - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - } - - return( 0 ); -} -#endif /* MBEDTLS_RSA_C */ - -static void *rsa_alt_alloc_wrap( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_alt_context ) ); - - if( ctx != NULL ) - memset( ctx, 0, sizeof( mbedtls_rsa_alt_context ) ); - - return( ctx ); -} - -static void rsa_alt_free_wrap( void *ctx ) -{ - mbedtls_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) ); - mbedtls_free( ctx ); -} - -const mbedtls_pk_info_t mbedtls_rsa_alt_info = { - MBEDTLS_PK_RSA_ALT, - "RSA-alt", - rsa_alt_get_bitlen, - rsa_alt_can_do, - NULL, - rsa_alt_sign_wrap, - rsa_alt_decrypt_wrap, - NULL, -#if defined(MBEDTLS_RSA_C) - rsa_alt_check_pair, -#else - NULL, -#endif - rsa_alt_alloc_wrap, - rsa_alt_free_wrap, - NULL, -}; - -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - -#endif /* MBEDTLS_PK_C */ diff --git a/components/mbedtls/library/pkcs11.c b/components/mbedtls/library/pkcs11.c deleted file mode 100644 index 0ea64252ee..0000000000 --- a/components/mbedtls/library/pkcs11.c +++ /dev/null @@ -1,240 +0,0 @@ -/** - * \file pkcs11.c - * - * \brief Wrapper for PKCS#11 library libpkcs11-helper - * - * \author Adriaan de Jong - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#include "mbedtls/pkcs11.h" - -#if defined(MBEDTLS_PKCS11_C) - -#include "mbedtls/md.h" -#include "mbedtls/oid.h" -#include "mbedtls/x509_crt.h" - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include - -void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_pkcs11_context ) ); -} - -int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11_cert ) -{ - int ret = 1; - unsigned char *cert_blob = NULL; - size_t cert_blob_size = 0; - - if( cert == NULL ) - { - ret = 2; - goto cleanup; - } - - if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL, - &cert_blob_size ) != CKR_OK ) - { - ret = 3; - goto cleanup; - } - - cert_blob = mbedtls_calloc( 1, cert_blob_size ); - if( NULL == cert_blob ) - { - ret = 4; - goto cleanup; - } - - if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob, - &cert_blob_size ) != CKR_OK ) - { - ret = 5; - goto cleanup; - } - - if( 0 != mbedtls_x509_crt_parse( cert, cert_blob, cert_blob_size ) ) - { - ret = 6; - goto cleanup; - } - - ret = 0; - -cleanup: - if( NULL != cert_blob ) - mbedtls_free( cert_blob ); - - return( ret ); -} - - -int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key, - pkcs11h_certificate_t pkcs11_cert ) -{ - int ret = 1; - mbedtls_x509_crt cert; - - mbedtls_x509_crt_init( &cert ); - - if( priv_key == NULL ) - goto cleanup; - - if( 0 != mbedtls_pkcs11_x509_cert_bind( &cert, pkcs11_cert ) ) - goto cleanup; - - priv_key->len = mbedtls_pk_get_len( &cert.pk ); - priv_key->pkcs11h_cert = pkcs11_cert; - - ret = 0; - -cleanup: - mbedtls_x509_crt_free( &cert ); - - return( ret ); -} - -void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key ) -{ - if( NULL != priv_key ) - pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert ); -} - -int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ) -{ - size_t input_len, output_len; - - if( NULL == ctx ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - if( MBEDTLS_RSA_PRIVATE != mode ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - output_len = input_len = ctx->len; - - if( input_len < 16 || input_len > output_max_len ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - /* Determine size of output buffer */ - if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, - input_len, NULL, &output_len ) != CKR_OK ) - { - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - } - - if( output_len > output_max_len ) - return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); - - if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input, - input_len, output, &output_len ) != CKR_OK ) - { - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - } - *olen = output_len; - return( 0 ); -} - -int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - size_t sig_len = 0, asn_len = 0, oid_size = 0; - unsigned char *p = sig; - const char *oid; - - if( NULL == ctx ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - if( MBEDTLS_RSA_PRIVATE != mode ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - if( md_alg != MBEDTLS_MD_NONE ) - { - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - hashlen = mbedtls_md_get_size( md_info ); - asn_len = 10 + oid_size; - } - - sig_len = ctx->len; - if( hashlen > sig_len || asn_len > sig_len || - hashlen + asn_len > sig_len ) - { - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - } - - if( md_alg != MBEDTLS_MD_NONE ) - { - /* - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithmIdentifier, - * digest Digest } - * - * DigestAlgorithmIdentifier ::= AlgorithmIdentifier - * - * Digest ::= OCTET STRING - */ - *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; - *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); - *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; - *p++ = (unsigned char) ( 0x04 + oid_size ); - *p++ = MBEDTLS_ASN1_OID; - *p++ = oid_size & 0xFF; - memcpy( p, oid, oid_size ); - p += oid_size; - *p++ = MBEDTLS_ASN1_NULL; - *p++ = 0x00; - *p++ = MBEDTLS_ASN1_OCTET_STRING; - *p++ = hashlen; - } - - memcpy( p, hash, hashlen ); - - if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig, - asn_len + hashlen, sig, &sig_len ) != CKR_OK ) - { - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - } - - return( 0 ); -} - -#endif /* defined(MBEDTLS_PKCS11_C) */ diff --git a/components/mbedtls/library/pkcs12.c b/components/mbedtls/library/pkcs12.c deleted file mode 100644 index c603a13577..0000000000 --- a/components/mbedtls/library/pkcs12.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - * PKCS#12 Personal Information Exchange Syntax - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The PKCS #12 Personal Information Exchange Syntax Standard v1.1 - * - * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf - * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PKCS12_C) - -#include "mbedtls/pkcs12.h" -#include "mbedtls/asn1.h" -#include "mbedtls/cipher.h" - -#include - -#if defined(MBEDTLS_ARC4_C) -#include "mbedtls/arc4.h" -#endif - -#if defined(MBEDTLS_DES_C) -#include "mbedtls/des.h" -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, - mbedtls_asn1_buf *salt, int *iterations ) -{ - int ret; - unsigned char **p = ¶ms->p; - const unsigned char *end = params->p + params->len; - - /* - * pkcs-12PbeParams ::= SEQUENCE { - * salt OCTET STRING, - * iterations INTEGER - * } - * - */ - if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) - return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - if( ( ret = mbedtls_asn1_get_tag( p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); - - salt->p = *p; - *p += salt->len; - - if( ( ret = mbedtls_asn1_get_int( p, end, iterations ) ) != 0 ) - return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); - - if( *p != end ) - return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -#define PKCS12_MAX_PWDLEN 128 - -static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type, - const unsigned char *pwd, size_t pwdlen, - unsigned char *key, size_t keylen, - unsigned char *iv, size_t ivlen ) -{ - int ret, iterations = 0; - mbedtls_asn1_buf salt; - size_t i; - unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2]; - - if( pwdlen > PKCS12_MAX_PWDLEN ) - return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); - - memset( &salt, 0, sizeof(mbedtls_asn1_buf) ); - memset( &unipwd, 0, sizeof(unipwd) ); - - if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt, - &iterations ) ) != 0 ) - return( ret ); - - for( i = 0; i < pwdlen; i++ ) - unipwd[i * 2 + 1] = pwd[i]; - - if( ( ret = mbedtls_pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2, - salt.p, salt.len, md_type, - MBEDTLS_PKCS12_DERIVE_KEY, iterations ) ) != 0 ) - { - return( ret ); - } - - if( iv == NULL || ivlen == 0 ) - return( 0 ); - - if( ( ret = mbedtls_pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2, - salt.p, salt.len, md_type, - MBEDTLS_PKCS12_DERIVE_IV, iterations ) ) != 0 ) - { - return( ret ); - } - return( 0 ); -} - -#undef PKCS12_MAX_PWDLEN - -int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *data, size_t len, - unsigned char *output ) -{ -#if !defined(MBEDTLS_ARC4_C) - ((void) pbe_params); - ((void) mode); - ((void) pwd); - ((void) pwdlen); - ((void) data); - ((void) len); - ((void) output); - return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); -#else - int ret; - unsigned char key[16]; - mbedtls_arc4_context ctx; - ((void) mode); - - mbedtls_arc4_init( &ctx ); - - if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, MBEDTLS_MD_SHA1, - pwd, pwdlen, - key, 16, NULL, 0 ) ) != 0 ) - { - return( ret ); - } - - mbedtls_arc4_setup( &ctx, key, 16 ); - if( ( ret = mbedtls_arc4_crypt( &ctx, len, data, output ) ) != 0 ) - goto exit; - -exit: - mbedtls_zeroize( key, sizeof( key ) ); - mbedtls_arc4_free( &ctx ); - - return( ret ); -#endif /* MBEDTLS_ARC4_C */ -} - -int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, - mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *data, size_t len, - unsigned char *output ) -{ - int ret, keylen = 0; - unsigned char key[32]; - unsigned char iv[16]; - const mbedtls_cipher_info_t *cipher_info; - mbedtls_cipher_context_t cipher_ctx; - size_t olen = 0; - - cipher_info = mbedtls_cipher_info_from_type( cipher_type ); - if( cipher_info == NULL ) - return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); - - keylen = cipher_info->key_bitlen / 8; - - if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen, - key, keylen, - iv, cipher_info->iv_size ) ) != 0 ) - { - return( ret ); - } - - mbedtls_cipher_init( &cipher_ctx ); - - if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_cipher_reset( &cipher_ctx ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_cipher_update( &cipher_ctx, data, len, - output, &olen ) ) != 0 ) - { - goto exit; - } - - if( ( ret = mbedtls_cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) - ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; - -exit: - mbedtls_zeroize( key, sizeof( key ) ); - mbedtls_zeroize( iv, sizeof( iv ) ); - mbedtls_cipher_free( &cipher_ctx ); - - return( ret ); -} - -static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, - const unsigned char *filler, size_t fill_len ) -{ - unsigned char *p = data; - size_t use_len; - - while( data_len > 0 ) - { - use_len = ( data_len > fill_len ) ? fill_len : data_len; - memcpy( p, filler, use_len ); - p += use_len; - data_len -= use_len; - } -} - -int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *salt, size_t saltlen, - mbedtls_md_type_t md_type, int id, int iterations ) -{ - int ret; - unsigned int j; - - unsigned char diversifier[128]; - unsigned char salt_block[128], pwd_block[128], hash_block[128]; - unsigned char hash_output[MBEDTLS_MD_MAX_SIZE]; - unsigned char *p; - unsigned char c; - - size_t hlen, use_len, v, i; - - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - - // This version only allows max of 64 bytes of password or salt - if( datalen > 128 || pwdlen > 64 || saltlen > 64 ) - return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); - - md_info = mbedtls_md_info_from_type( md_type ); - if( md_info == NULL ) - return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); - - mbedtls_md_init( &md_ctx ); - - if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) - return( ret ); - hlen = mbedtls_md_get_size( md_info ); - - if( hlen <= 32 ) - v = 64; - else - v = 128; - - memset( diversifier, (unsigned char) id, v ); - - pkcs12_fill_buffer( salt_block, v, salt, saltlen ); - pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen ); - - p = data; - while( datalen > 0 ) - { - // Calculate hash( diversifier || salt_block || pwd_block ) - if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 ) - goto exit; - - // Perform remaining ( iterations - 1 ) recursive hash calculations - for( i = 1; i < (size_t) iterations; i++ ) - { - if( ( ret = mbedtls_md( md_info, hash_output, hlen, hash_output ) ) != 0 ) - goto exit; - } - - use_len = ( datalen > hlen ) ? hlen : datalen; - memcpy( p, hash_output, use_len ); - datalen -= use_len; - p += use_len; - - if( datalen == 0 ) - break; - - // Concatenating copies of hash_output into hash_block (B) - pkcs12_fill_buffer( hash_block, v, hash_output, hlen ); - - // B += 1 - for( i = v; i > 0; i-- ) - if( ++hash_block[i - 1] != 0 ) - break; - - // salt_block += B - c = 0; - for( i = v; i > 0; i-- ) - { - j = salt_block[i - 1] + hash_block[i - 1] + c; - c = (unsigned char) (j >> 8); - salt_block[i - 1] = j & 0xFF; - } - - // pwd_block += B - c = 0; - for( i = v; i > 0; i-- ) - { - j = pwd_block[i - 1] + hash_block[i - 1] + c; - c = (unsigned char) (j >> 8); - pwd_block[i - 1] = j & 0xFF; - } - } - - ret = 0; - -exit: - mbedtls_zeroize( salt_block, sizeof( salt_block ) ); - mbedtls_zeroize( pwd_block, sizeof( pwd_block ) ); - mbedtls_zeroize( hash_block, sizeof( hash_block ) ); - mbedtls_zeroize( hash_output, sizeof( hash_output ) ); - - mbedtls_md_free( &md_ctx ); - - return( ret ); -} - -#endif /* MBEDTLS_PKCS12_C */ diff --git a/components/mbedtls/library/pkcs5.c b/components/mbedtls/library/pkcs5.c deleted file mode 100644 index e28d5a8473..0000000000 --- a/components/mbedtls/library/pkcs5.c +++ /dev/null @@ -1,406 +0,0 @@ -/** - * \file pkcs5.c - * - * \brief PKCS#5 functions - * - * \author Mathias Olsson - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * PKCS#5 includes PBKDF2 and more - * - * http://tools.ietf.org/html/rfc2898 (Specification) - * http://tools.ietf.org/html/rfc6070 (Test vectors) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PKCS5_C) - -#include "mbedtls/pkcs5.h" -#include "mbedtls/asn1.h" -#include "mbedtls/cipher.h" -#include "mbedtls/oid.h" - -#include - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif - -static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, - mbedtls_asn1_buf *salt, int *iterations, - int *keylen, mbedtls_md_type_t *md_type ) -{ - int ret; - mbedtls_asn1_buf prf_alg_oid; - unsigned char *p = params->p; - const unsigned char *end = params->p + params->len; - - if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - /* - * PBKDF2-params ::= SEQUENCE { - * salt OCTET STRING, - * iterationCount INTEGER, - * keyLength INTEGER OPTIONAL - * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 - * } - * - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); - - salt->p = p; - p += salt->len; - - if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 ) - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); - - if( p == end ) - return( 0 ); - - if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 ) - { - if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); - } - - if( p == end ) - return( 0 ); - - if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); - - if( MBEDTLS_OID_CMP( MBEDTLS_OID_HMAC_SHA1, &prf_alg_oid ) != 0 ) - return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); - - *md_type = MBEDTLS_MD_SHA1; - - if( p != end ) - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, - const unsigned char *pwd, size_t pwdlen, - const unsigned char *data, size_t datalen, - unsigned char *output ) -{ - int ret, iterations = 0, keylen = 0; - unsigned char *p, *end; - mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; - mbedtls_asn1_buf salt; - mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; - unsigned char key[32], iv[32]; - size_t olen = 0; - const mbedtls_md_info_t *md_info; - const mbedtls_cipher_info_t *cipher_info; - mbedtls_md_context_t md_ctx; - mbedtls_cipher_type_t cipher_alg; - mbedtls_cipher_context_t cipher_ctx; - - p = pbe_params->p; - end = p + pbe_params->len; - - /* - * PBES2-params ::= SEQUENCE { - * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, - * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} - * } - */ - if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 ) - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); - - // Only PBKDF2 supported at the moment - // - if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 ) - return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); - - if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, - &salt, &iterations, &keylen, - &md_type ) ) != 0 ) - { - return( ret ); - } - - md_info = mbedtls_md_info_from_type( md_type ); - if( md_info == NULL ) - return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); - - if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid, - &enc_scheme_params ) ) != 0 ) - { - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); - } - - if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) - return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); - - cipher_info = mbedtls_cipher_info_from_type( cipher_alg ); - if( cipher_info == NULL ) - return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); - - /* - * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored - * since it is optional and we don't know if it was set or not - */ - keylen = cipher_info->key_bitlen / 8; - - if( enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || - enc_scheme_params.len != cipher_info->iv_size ) - { - return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT ); - } - - mbedtls_md_init( &md_ctx ); - mbedtls_cipher_init( &cipher_ctx ); - - memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); - - if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, - iterations, keylen, key ) ) != 0 ) - { - goto exit; - } - - if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) - goto exit; - - if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len, - data, datalen, output, &olen ) ) != 0 ) - ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH; - -exit: - mbedtls_md_free( &md_ctx ); - mbedtls_cipher_free( &cipher_ctx ); - - return( ret ); -} - -int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, - size_t plen, const unsigned char *salt, size_t slen, - unsigned int iteration_count, - uint32_t key_length, unsigned char *output ) -{ - int ret, j; - unsigned int i; - unsigned char md1[MBEDTLS_MD_MAX_SIZE]; - unsigned char work[MBEDTLS_MD_MAX_SIZE]; - unsigned char md_size = mbedtls_md_get_size( ctx->md_info ); - size_t use_len; - unsigned char *out_p = output; - unsigned char counter[4]; - - memset( counter, 0, 4 ); - counter[3] = 1; - - if( iteration_count > 0xFFFFFFFF ) - return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); - - while( key_length ) - { - // U1 ends up in work - // - if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 ) - return( ret ); - - memcpy( md1, work, md_size ); - - for( i = 1; i < iteration_count; i++ ) - { - // U2 ends up in md1 - // - if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 ) - return( ret ); - - // U1 xor U2 - // - for( j = 0; j < md_size; j++ ) - work[j] ^= md1[j]; - } - - use_len = ( key_length < md_size ) ? key_length : md_size; - memcpy( out_p, work, use_len ); - - key_length -= (uint32_t) use_len; - out_p += use_len; - - for( i = 4; i > 0; i-- ) - if( ++counter[i - 1] != 0 ) - break; - } - - return( 0 ); -} - -#if defined(MBEDTLS_SELF_TEST) - -#if !defined(MBEDTLS_SHA1_C) -int mbedtls_pkcs5_self_test( int verbose ) -{ - if( verbose != 0 ) - mbedtls_printf( " PBKDF2 (SHA1): skipped\n\n" ); - - return( 0 ); -} -#else - -#define MAX_TESTS 6 - -static const size_t plen[MAX_TESTS] = - { 8, 8, 8, 24, 9 }; - -static const unsigned char password[MAX_TESTS][32] = -{ - "password", - "password", - "password", - "passwordPASSWORDpassword", - "pass\0word", -}; - -static const size_t slen[MAX_TESTS] = - { 4, 4, 4, 36, 5 }; - -static const unsigned char salt[MAX_TESTS][40] = -{ - "salt", - "salt", - "salt", - "saltSALTsaltSALTsaltSALTsaltSALTsalt", - "sa\0lt", -}; - -static const uint32_t it_cnt[MAX_TESTS] = - { 1, 2, 4096, 4096, 4096 }; - -static const uint32_t key_len[MAX_TESTS] = - { 20, 20, 20, 25, 16 }; - -static const unsigned char result_key[MAX_TESTS][32] = -{ - { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, - 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, - 0x2f, 0xe0, 0x37, 0xa6 }, - { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, - 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, - 0xd8, 0xde, 0x89, 0x57 }, - { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, - 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, - 0x65, 0xa4, 0x29, 0xc1 }, - { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, - 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, - 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, - 0x38 }, - { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, - 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, -}; - -int mbedtls_pkcs5_self_test( int verbose ) -{ - mbedtls_md_context_t sha1_ctx; - const mbedtls_md_info_t *info_sha1; - int ret, i; - unsigned char key[64]; - - mbedtls_md_init( &sha1_ctx ); - - info_sha1 = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); - if( info_sha1 == NULL ) - { - ret = 1; - goto exit; - } - - if( ( ret = mbedtls_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 ) - { - ret = 1; - goto exit; - } - - for( i = 0; i < MAX_TESTS; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " PBKDF2 (SHA1) #%d: ", i ); - - ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i], - slen[i], it_cnt[i], key_len[i], key ); - if( ret != 0 || - memcmp( result_key[i], key, key_len[i] ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -exit: - mbedtls_md_free( &sha1_ctx ); - - return( ret ); -} -#endif /* MBEDTLS_SHA1_C */ - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_PKCS5_C */ diff --git a/components/mbedtls/library/pkparse.c b/components/mbedtls/library/pkparse.c deleted file mode 100644 index efdf437466..0000000000 --- a/components/mbedtls/library/pkparse.c +++ /dev/null @@ -1,1293 +0,0 @@ -/* - * Public Key layer for parsing key files and structures - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PK_PARSE_C) - -#include "mbedtls/pk.h" -#include "mbedtls/asn1.h" -#include "mbedtls/oid.h" - -#include - -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif -#if defined(MBEDTLS_PEM_PARSE_C) -#include "mbedtls/pem.h" -#endif -#if defined(MBEDTLS_PKCS5_C) -#include "mbedtls/pkcs5.h" -#endif -#if defined(MBEDTLS_PKCS12_C) -#include "mbedtls/pkcs12.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#if defined(MBEDTLS_FS_IO) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * Load all data from a file into a given buffer. - * - * The file is expected to contain either PEM or DER encoded data. - * A terminating null byte is always appended. It is included in the announced - * length only if the data looks like it is PEM encoded. - */ -int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) -{ - FILE *f; - long size; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); - - fseek( f, 0, SEEK_END ); - if( ( size = ftell( f ) ) == -1 ) - { - fclose( f ); - return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); - } - fseek( f, 0, SEEK_SET ); - - *n = (size_t) size; - - if( *n + 1 == 0 || - ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) - { - fclose( f ); - return( MBEDTLS_ERR_PK_ALLOC_FAILED ); - } - - if( fread( *buf, 1, *n, f ) != *n ) - { - fclose( f ); - mbedtls_free( *buf ); - return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); - } - - fclose( f ); - - (*buf)[*n] = '\0'; - - if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) - ++*n; - - return( 0 ); -} - -/* - * Load and parse a private key - */ -int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, - const char *path, const char *pwd ) -{ - int ret; - size_t n; - unsigned char *buf; - - if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) - return( ret ); - - if( pwd == NULL ) - ret = mbedtls_pk_parse_key( ctx, buf, n, NULL, 0 ); - else - ret = mbedtls_pk_parse_key( ctx, buf, n, - (const unsigned char *) pwd, strlen( pwd ) ); - - mbedtls_zeroize( buf, n ); - mbedtls_free( buf ); - - return( ret ); -} - -/* - * Load and parse a public key - */ -int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) -{ - int ret; - size_t n; - unsigned char *buf; - - if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) - return( ret ); - - ret = mbedtls_pk_parse_public_key( ctx, buf, n ); - - mbedtls_zeroize( buf, n ); - mbedtls_free( buf ); - - return( ret ); -} -#endif /* MBEDTLS_FS_IO */ - -#if defined(MBEDTLS_ECP_C) -/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf - * - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } - * -- implicitCurve NULL - * } - */ -static int pk_get_ecparams( unsigned char **p, const unsigned char *end, - mbedtls_asn1_buf *params ) -{ - int ret; - - /* Tag may be either OID or SEQUENCE */ - params->tag = **p; - if( params->tag != MBEDTLS_ASN1_OID -#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) - && params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) -#endif - ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - } - - if( ( ret = mbedtls_asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - params->p = *p; - *p += params->len; - - if( *p != end ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) -/* - * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. - * WARNING: the resulting group should only be used with - * pk_group_id_from_specified(), since its base point may not be set correctly - * if it was encoded compressed. - * - * SpecifiedECDomain ::= SEQUENCE { - * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), - * fieldID FieldID {{FieldTypes}}, - * curve Curve, - * base ECPoint, - * order INTEGER, - * cofactor INTEGER OPTIONAL, - * hash HashAlgorithm OPTIONAL, - * ... - * } - * - * We only support prime-field as field type, and ignore hash and cofactor. - */ -static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) -{ - int ret; - unsigned char *p = params->p; - const unsigned char * const end = params->p + params->len; - const unsigned char *end_field, *end_curve; - size_t len; - int ver; - - /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ - if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( ver < 1 || ver > 3 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); - - /* - * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field - * fieldType FIELD-ID.&id({IOSet}), - * parameters FIELD-ID.&Type({IOSet}{@fieldType}) - * } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( ret ); - - end_field = p + len; - - /* - * FIELD-ID ::= TYPE-IDENTIFIER - * FieldTypes FIELD-ID ::= { - * { Prime-p IDENTIFIED BY prime-field } | - * { Characteristic-two IDENTIFIED BY characteristic-two-field } - * } - * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 ) - return( ret ); - - if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) || - memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) - { - return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); - } - - p += len; - - /* Prime-p ::= INTEGER -- Field of size p. */ - if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - grp->pbits = mbedtls_mpi_bitlen( &grp->P ); - - if( p != end_field ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - /* - * Curve ::= SEQUENCE { - * a FieldElement, - * b FieldElement, - * seed BIT STRING OPTIONAL - * -- Shall be present if used in SpecifiedECDomain - * -- with version equal to ecdpVer2 or ecdpVer3 - * } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( ret ); - - end_curve = p + len; - - /* - * FieldElement ::= OCTET STRING - * containing an integer in the case of a prime field - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || - ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - p += len; - - if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || - ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - p += len; - - /* Ignore seed BIT STRING OPTIONAL */ - if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 ) - p += len; - - if( p != end_curve ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - /* - * ECPoint ::= OCTET STRING - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G, - ( const unsigned char *) p, len ) ) != 0 ) - { - /* - * If we can't read the point because it's compressed, cheat by - * reading only the X coordinate and the parity bit of Y. - */ - if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || - ( p[0] != 0x02 && p[0] != 0x03 ) || - len != mbedtls_mpi_size( &grp->P ) + 1 || - mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || - mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || - mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); - } - } - - p += len; - - /* - * order INTEGER - */ - if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - grp->nbits = mbedtls_mpi_bitlen( &grp->N ); - - /* - * Allow optional elements by purposefully not enforcing p == end here. - */ - - return( 0 ); -} - -/* - * Find the group id associated with an (almost filled) group as generated by - * pk_group_from_specified(), or return an error if unknown. - */ -static int pk_group_id_from_group( const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id ) -{ - int ret = 0; - mbedtls_ecp_group ref; - const mbedtls_ecp_group_id *id; - - mbedtls_ecp_group_init( &ref ); - - for( id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++ ) - { - /* Load the group associated to that id */ - mbedtls_ecp_group_free( &ref ); - MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ref, *id ) ); - - /* Compare to the group we were given, starting with easy tests */ - if( grp->pbits == ref.pbits && grp->nbits == ref.nbits && - mbedtls_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 && - mbedtls_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 && - mbedtls_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 && - mbedtls_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 && - mbedtls_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 && - mbedtls_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 && - /* For Y we may only know the parity bit, so compare only that */ - mbedtls_mpi_get_bit( &grp->G.Y, 0 ) == mbedtls_mpi_get_bit( &ref.G.Y, 0 ) ) - { - break; - } - - } - -cleanup: - mbedtls_ecp_group_free( &ref ); - - *grp_id = *id; - - if( ret == 0 && *id == MBEDTLS_ECP_DP_NONE ) - ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; - - return( ret ); -} - -/* - * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID - */ -static int pk_group_id_from_specified( const mbedtls_asn1_buf *params, - mbedtls_ecp_group_id *grp_id ) -{ - int ret; - mbedtls_ecp_group grp; - - mbedtls_ecp_group_init( &grp ); - - if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 ) - goto cleanup; - - ret = pk_group_id_from_group( &grp, grp_id ); - -cleanup: - mbedtls_ecp_group_free( &grp ); - - return( ret ); -} -#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ - -/* - * Use EC parameters to initialise an EC group - * - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } - * -- implicitCurve NULL - */ -static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) -{ - int ret; - mbedtls_ecp_group_id grp_id; - - if( params->tag == MBEDTLS_ASN1_OID ) - { - if( mbedtls_oid_get_ec_grp( params, &grp_id ) != 0 ) - return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ); - } - else - { -#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) - if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 ) - return( ret ); -#else - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); -#endif - } - - /* - * grp may already be initilialized; if so, make sure IDs match - */ - if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); - - if( ( ret = mbedtls_ecp_group_load( grp, grp_id ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -/* - * EC public key is an EC point - * - * The caller is responsible for clearing the structure upon failure if - * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE - * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. - */ -static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end, - mbedtls_ecp_keypair *key ) -{ - int ret; - - if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q, - (const unsigned char *) *p, end - *p ) ) == 0 ) - { - ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q ); - } - - /* - * We know mbedtls_ecp_point_read_binary consumed all bytes or failed - */ - *p = (unsigned char *) end; - - return( ret ); -} -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_RSA_C) -/* - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER -- e - * } - */ -static int pk_get_rsapubkey( unsigned char **p, - const unsigned char *end, - mbedtls_rsa_context *rsa ) -{ - int ret; - size_t len; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); - - if( *p + len != end ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - if( ( ret = mbedtls_asn1_get_mpi( p, end, &rsa->N ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( p, end, &rsa->E ) ) != 0 ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); - - if( *p != end ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - if( ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); - - rsa->len = mbedtls_mpi_size( &rsa->N ); - - return( 0 ); -} -#endif /* MBEDTLS_RSA_C */ - -/* Get a PK algorithm identifier - * - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL } - */ -static int pk_get_pk_alg( unsigned char **p, - const unsigned char *end, - mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params ) -{ - int ret; - mbedtls_asn1_buf alg_oid; - - memset( params, 0, sizeof(mbedtls_asn1_buf) ); - - if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) - return( MBEDTLS_ERR_PK_INVALID_ALG + ret ); - - if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - - /* - * No parameters with RSA (only for EC) - */ - if( *pk_alg == MBEDTLS_PK_RSA && - ( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) || - params->len != 0 ) ) - { - return( MBEDTLS_ERR_PK_INVALID_ALG ); - } - - return( 0 ); -} - -/* - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } - */ -int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, - mbedtls_pk_context *pk ) -{ - int ret; - size_t len; - mbedtls_asn1_buf alg_params; - mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; - const mbedtls_pk_info_t *pk_info; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - end = *p + len; - - if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); - - if( *p + len != end ) - return( MBEDTLS_ERR_PK_INVALID_PUBKEY + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) - return( ret ); - -#if defined(MBEDTLS_RSA_C) - if( pk_alg == MBEDTLS_PK_RSA ) - { - ret = pk_get_rsapubkey( p, end, mbedtls_pk_rsa( *pk ) ); - } else -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) - if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY ) - { - ret = pk_use_ecparams( &alg_params, &mbedtls_pk_ec( *pk )->grp ); - if( ret == 0 ) - ret = pk_get_ecpubkey( p, end, mbedtls_pk_ec( *pk ) ); - } else -#endif /* MBEDTLS_ECP_C */ - ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; - - if( ret == 0 && *p != end ) - ret = MBEDTLS_ERR_PK_INVALID_PUBKEY - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; - - if( ret != 0 ) - mbedtls_pk_free( pk ); - - return( ret ); -} - -#if defined(MBEDTLS_RSA_C) -/* - * Parse a PKCS#1 encoded private RSA key - */ -static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, - const unsigned char *key, - size_t keylen ) -{ - int ret; - size_t len; - unsigned char *p, *end; - - p = (unsigned char *) key; - end = p + keylen; - - /* - * This function parses the RSAPrivateKey (PKCS#1) - * - * RSAPrivateKey ::= SEQUENCE { - * version Version, - * modulus INTEGER, -- n - * publicExponent INTEGER, -- e - * privateExponent INTEGER, -- d - * prime1 INTEGER, -- p - * prime2 INTEGER, -- q - * exponent1 INTEGER, -- d mod (p-1) - * exponent2 INTEGER, -- d mod (q-1) - * coefficient INTEGER, -- (inverse of q) mod p - * otherPrimeInfos OtherPrimeInfos OPTIONAL - * } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - end = p + len; - - if( ( ret = mbedtls_asn1_get_int( &p, end, &rsa->ver ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - if( rsa->ver != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); - } - - if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->N ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->E ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->D ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->P ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->Q ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DP ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0 || - ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->QP ) ) != 0 ) - { - mbedtls_rsa_free( rsa ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - rsa->len = mbedtls_mpi_size( &rsa->N ); - - if( p != end ) - { - mbedtls_rsa_free( rsa ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - - if( ( ret = mbedtls_rsa_check_privkey( rsa ) ) != 0 ) - { - mbedtls_rsa_free( rsa ); - return( ret ); - } - - return( 0 ); -} -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) -/* - * Parse a SEC1 encoded private EC key - */ -static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, - const unsigned char *key, - size_t keylen ) -{ - int ret; - int version, pubkey_done; - size_t len; - mbedtls_asn1_buf params; - unsigned char *p = (unsigned char *) key; - unsigned char *end = p + keylen; - unsigned char *end2; - - /* - * RFC 5915, or SEC1 Appendix C.4 - * - * ECPrivateKey ::= SEQUENCE { - * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - * privateKey OCTET STRING, - * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - * publicKey [1] BIT STRING OPTIONAL - * } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - end = p + len; - - if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( version != 1 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( ( ret = mbedtls_mpi_read_binary( &eck->d, p, len ) ) != 0 ) - { - mbedtls_ecp_keypair_free( eck ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - p += len; - - pubkey_done = 0; - if( p != end ) - { - /* - * Is 'parameters' present? - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) - { - if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 || - ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) - { - mbedtls_ecp_keypair_free( eck ); - return( ret ); - } - } - else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - { - mbedtls_ecp_keypair_free( eck ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - /* - * Is 'publickey' present? If not, or if we can't read it (eg because it - * is compressed), create it from the private key. - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) - { - end2 = p + len; - - if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( p + len != end2 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 ) - pubkey_done = 1; - else - { - /* - * The only acceptable failure mode of pk_get_ecpubkey() above - * is if the point format is not recognized. - */ - if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); - } - } - else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - { - mbedtls_ecp_keypair_free( eck ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - } - - if( ! pubkey_done && - ( ret = mbedtls_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G, - NULL, NULL ) ) != 0 ) - { - mbedtls_ecp_keypair_free( eck ); - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) - { - mbedtls_ecp_keypair_free( eck ); - return( ret ); - } - - return( 0 ); -} -#endif /* MBEDTLS_ECP_C */ - -/* - * Parse an unencrypted PKCS#8 encoded private key - */ -static int pk_parse_key_pkcs8_unencrypted_der( - mbedtls_pk_context *pk, - const unsigned char* key, - size_t keylen ) -{ - int ret, version; - size_t len; - mbedtls_asn1_buf params; - unsigned char *p = (unsigned char *) key; - unsigned char *end = p + keylen; - mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; - const mbedtls_pk_info_t *pk_info; - - /* - * This function parses the PrivatKeyInfo object (PKCS#8 v1.2 = RFC 5208) - * - * PrivateKeyInfo ::= SEQUENCE { - * version Version, - * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - * privateKey PrivateKey, - * attributes [0] IMPLICIT Attributes OPTIONAL } - * - * Version ::= INTEGER - * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier - * PrivateKey ::= OCTET STRING - * - * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey - */ - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - end = p + len; - - if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( version != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION + ret ); - - if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( len < 1 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) - return( ret ); - -#if defined(MBEDTLS_RSA_C) - if( pk_alg == MBEDTLS_PK_RSA ) - { - if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 ) - { - mbedtls_pk_free( pk ); - return( ret ); - } - } else -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) - if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH ) - { - if( ( ret = pk_use_ecparams( ¶ms, &mbedtls_pk_ec( *pk )->grp ) ) != 0 || - ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len ) ) != 0 ) - { - mbedtls_pk_free( pk ); - return( ret ); - } - } else -#endif /* MBEDTLS_ECP_C */ - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - - return( 0 ); -} - -/* - * Parse an encrypted PKCS#8 encoded private key - */ -#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) -static int pk_parse_key_pkcs8_encrypted_der( - mbedtls_pk_context *pk, - const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen ) -{ - int ret, decrypted = 0; - size_t len; - unsigned char buf[2048]; - unsigned char *p, *end; - mbedtls_asn1_buf pbe_alg_oid, pbe_params; -#if defined(MBEDTLS_PKCS12_C) - mbedtls_cipher_type_t cipher_alg; - mbedtls_md_type_t md_alg; -#endif - - memset( buf, 0, sizeof( buf ) ); - - p = (unsigned char *) key; - end = p + keylen; - - if( pwdlen == 0 ) - return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); - - /* - * This function parses the EncryptedPrivatKeyInfo object (PKCS#8) - * - * EncryptedPrivateKeyInfo ::= SEQUENCE { - * encryptionAlgorithm EncryptionAlgorithmIdentifier, - * encryptedData EncryptedData - * } - * - * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier - * - * EncryptedData ::= OCTET STRING - * - * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - } - - end = p + len; - - if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); - - if( len > sizeof( buf ) ) - return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - - /* - * Decrypt EncryptedData with appropriate PDE - */ -#if defined(MBEDTLS_PKCS12_C) - if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) - { - if( ( ret = mbedtls_pkcs12_pbe( &pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, - cipher_alg, md_alg, - pwd, pwdlen, p, len, buf ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH ) - return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); - - return( ret ); - } - - decrypted = 1; - } - else if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) == 0 ) - { - if( ( ret = mbedtls_pkcs12_pbe_sha1_rc4_128( &pbe_params, - MBEDTLS_PKCS12_PBE_DECRYPT, - pwd, pwdlen, - p, len, buf ) ) != 0 ) - { - return( ret ); - } - - // Best guess for password mismatch when using RC4. If first tag is - // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE - // - if( *buf != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) - return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); - - decrypted = 1; - } - else -#endif /* MBEDTLS_PKCS12_C */ -#if defined(MBEDTLS_PKCS5_C) - if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 ) - { - if( ( ret = mbedtls_pkcs5_pbes2( &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, - p, len, buf ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH ) - return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); - - return( ret ); - } - - decrypted = 1; - } - else -#endif /* MBEDTLS_PKCS5_C */ - { - ((void) pwd); - } - - if( decrypted == 0 ) - return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); - - return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) ); -} -#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ - -/* - * Parse a private key - */ -int mbedtls_pk_parse_key( mbedtls_pk_context *pk, - const unsigned char *key, size_t keylen, - const unsigned char *pwd, size_t pwdlen ) -{ - int ret; - const mbedtls_pk_info_t *pk_info; - -#if defined(MBEDTLS_PEM_PARSE_C) - size_t len; - mbedtls_pem_context pem; - - mbedtls_pem_init( &pem ); - -#if defined(MBEDTLS_RSA_C) - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN RSA PRIVATE KEY-----", - "-----END RSA PRIVATE KEY-----", - key, pwd, pwdlen, &len ); - - if( ret == 0 ) - { - if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || - ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), - pem.buf, pem.buflen ) ) != 0 ) - { - mbedtls_pk_free( pk ); - } - - mbedtls_pem_free( &pem ); - return( ret ); - } - else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) - return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); - else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) - return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - return( ret ); -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN EC PRIVATE KEY-----", - "-----END EC PRIVATE KEY-----", - key, pwd, pwdlen, &len ); - if( ret == 0 ) - { - if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || - ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), - pem.buf, pem.buflen ) ) != 0 ) - { - mbedtls_pk_free( pk ); - } - - mbedtls_pem_free( &pem ); - return( ret ); - } - else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) - return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); - else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) - return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - return( ret ); -#endif /* MBEDTLS_ECP_C */ - - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN PRIVATE KEY-----", - "-----END PRIVATE KEY-----", - key, NULL, 0, &len ); - if( ret == 0 ) - { - if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, - pem.buf, pem.buflen ) ) != 0 ) - { - mbedtls_pk_free( pk ); - } - - mbedtls_pem_free( &pem ); - return( ret ); - } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - return( ret ); - -#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN ENCRYPTED PRIVATE KEY-----", - "-----END ENCRYPTED PRIVATE KEY-----", - key, NULL, 0, &len ); - if( ret == 0 ) - { - if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, - pem.buf, pem.buflen, - pwd, pwdlen ) ) != 0 ) - { - mbedtls_pk_free( pk ); - } - - mbedtls_pem_free( &pem ); - return( ret ); - } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - return( ret ); -#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ -#else - ((void) ret); - ((void) pwd); - ((void) pwdlen); -#endif /* MBEDTLS_PEM_PARSE_C */ - - /* - * At this point we only know it's not a PEM formatted key. Could be any - * of the known DER encoded private key formats - * - * We try the different DER format parsers to see if one passes without - * error - */ -#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) - if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, key, keylen, - pwd, pwdlen ) ) == 0 ) - { - return( 0 ); - } - - mbedtls_pk_free( pk ); - - if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) - { - return( ret ); - } -#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ - - if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 ) - return( 0 ); - - mbedtls_pk_free( pk ); - -#if defined(MBEDTLS_RSA_C) - if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || - ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) ) == 0 ) - { - return( 0 ); - } - - mbedtls_pk_free( pk ); -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) - if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ) ) == NULL ) - return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); - - if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || - ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), key, keylen ) ) == 0 ) - { - return( 0 ); - } - - mbedtls_pk_free( pk ); -#endif /* MBEDTLS_ECP_C */ - - return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); -} - -/* - * Parse a public key - */ -int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, - const unsigned char *key, size_t keylen ) -{ - int ret; - unsigned char *p; -#if defined(MBEDTLS_PEM_PARSE_C) - size_t len; - mbedtls_pem_context pem; - - mbedtls_pem_init( &pem ); - - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( keylen == 0 || key[keylen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN PUBLIC KEY-----", - "-----END PUBLIC KEY-----", - key, NULL, 0, &len ); - - if( ret == 0 ) - { - /* - * Was PEM encoded - */ - key = pem.buf; - keylen = pem.buflen; - } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - { - mbedtls_pem_free( &pem ); - return( ret ); - } -#endif /* MBEDTLS_PEM_PARSE_C */ - p = (unsigned char *) key; - - ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); - -#if defined(MBEDTLS_PEM_PARSE_C) - mbedtls_pem_free( &pem ); -#endif - - return( ret ); -} - -#endif /* MBEDTLS_PK_PARSE_C */ diff --git a/components/mbedtls/library/pkwrite.c b/components/mbedtls/library/pkwrite.c deleted file mode 100644 index 83b798c119..0000000000 --- a/components/mbedtls/library/pkwrite.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Public Key layer for writing key files and structures - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PK_WRITE_C) - -#include "mbedtls/pk.h" -#include "mbedtls/asn1write.h" -#include "mbedtls/oid.h" - -#include - -#if defined(MBEDTLS_RSA_C) -#include "mbedtls/rsa.h" -#endif -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif -#if defined(MBEDTLS_ECDSA_C) -#include "mbedtls/ecdsa.h" -#endif -#if defined(MBEDTLS_PEM_WRITE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#if defined(MBEDTLS_RSA_C) -/* - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER -- e - * } - */ -static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, - mbedtls_rsa_context *rsa ) -{ - int ret; - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( p, start, &rsa->E ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( p, start, &rsa->N ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - return( (int) len ); -} -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) -/* - * EC public key is an EC point - */ -static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, - mbedtls_ecp_keypair *ec ) -{ - int ret; - size_t len = 0; - unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; - - if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q, - MBEDTLS_ECP_PF_UNCOMPRESSED, - &len, buf, sizeof( buf ) ) ) != 0 ) - { - return( ret ); - } - - if( *p < start || (size_t)( *p - start ) < len ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *p -= len; - memcpy( *p, buf, len ); - - return( (int) len ); -} - -/* - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * } - */ -static int pk_write_ec_param( unsigned char **p, unsigned char *start, - mbedtls_ecp_keypair *ec ) -{ - int ret; - size_t len = 0; - const char *oid; - size_t oid_len; - - if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 ) - return( ret ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); - - return( (int) len ); -} -#endif /* MBEDTLS_ECP_C */ - -int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, - const mbedtls_pk_context *key ) -{ - int ret; - size_t len = 0; - -#if defined(MBEDTLS_RSA_C) - if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) - MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) ); - else -#endif -#if defined(MBEDTLS_ECP_C) - if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) - MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) ); - else -#endif - return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); - - return( (int) len ); -} - -int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) -{ - int ret; - unsigned char *c; - size_t len = 0, par_len = 0, oid_len; - const char *oid; - - c = buf + size; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) ); - - if( c - buf < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - /* - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } - */ - *--c = 0; - len += 1; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); - - if( ( ret = mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_get_type( key ), - &oid, &oid_len ) ) != 0 ) - { - return( ret ); - } - -#if defined(MBEDTLS_ECP_C) - if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) - { - MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) ); - } -#endif - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len, - par_len ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - return( (int) len ); -} - -int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) -{ - int ret; - unsigned char *c = buf + size; - size_t len = 0; - -#if defined(MBEDTLS_RSA_C) - if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) - { - mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->QP ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DQ ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->DP ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->Q ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->P ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->D ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->E ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &rsa->N ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - } - else -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) - if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) - { - mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key ); - size_t pub_len = 0, par_len = 0; - - /* - * RFC 5915, or SEC1 Appendix C.4 - * - * ECPrivateKey ::= SEQUENCE { - * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), - * privateKey OCTET STRING, - * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, - * publicKey [1] BIT STRING OPTIONAL - * } - */ - - /* publicKey */ - MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) ); - - if( c - buf < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - *--c = 0; - pub_len += 1; - - MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); - MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); - - MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); - MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ); - len += pub_len; - - /* parameters */ - MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) ); - - MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) ); - MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); - len += par_len; - - /* privateKey: write as MPI then fix tag */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &ec->d ) ); - *c = MBEDTLS_ASN1_OCTET_STRING; - - /* version */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - } - else -#endif /* MBEDTLS_ECP_C */ - return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); - - return( (int) len ); -} - -#if defined(MBEDTLS_PEM_WRITE_C) - -#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" -#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" - -#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" -#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" -#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" -#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" - -/* - * Max sizes of key per types. Shown as tag + len (+ content). - */ - -#if defined(MBEDTLS_RSA_C) -/* - * RSA public keys: - * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 - * algorithm AlgorithmIdentifier, 1 + 1 (sequence) - * + 1 + 1 + 9 (rsa oid) - * + 1 + 1 (params null) - * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) - * RSAPublicKey ::= SEQUENCE { 1 + 3 - * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 - * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 - * } - */ -#define RSA_PUB_DER_MAX_BYTES 38 + 2 * MBEDTLS_MPI_MAX_SIZE - -/* - * RSA private keys: - * RSAPrivateKey ::= SEQUENCE { 1 + 3 - * version Version, 1 + 1 + 1 - * modulus INTEGER, 1 + 3 + MPI_MAX + 1 - * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 - * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 - * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 - * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) - * } - */ -#define MPI_MAX_SIZE_2 MBEDTLS_MPI_MAX_SIZE / 2 + \ - MBEDTLS_MPI_MAX_SIZE % 2 -#define RSA_PRV_DER_MAX_BYTES 47 + 3 * MBEDTLS_MPI_MAX_SIZE \ - + 5 * MPI_MAX_SIZE_2 - -#else /* MBEDTLS_RSA_C */ - -#define RSA_PUB_DER_MAX_BYTES 0 -#define RSA_PRV_DER_MAX_BYTES 0 - -#endif /* MBEDTLS_RSA_C */ - -#if defined(MBEDTLS_ECP_C) -/* - * EC public keys: - * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 - * algorithm AlgorithmIdentifier, 1 + 1 (sequence) - * + 1 + 1 + 7 (ec oid) - * + 1 + 1 + 9 (namedCurve oid) - * subjectPublicKey BIT STRING 1 + 2 + 1 [1] - * + 1 (point format) [1] - * + 2 * ECP_MAX (coords) [1] - * } - */ -#define ECP_PUB_DER_MAX_BYTES 30 + 2 * MBEDTLS_ECP_MAX_BYTES - -/* - * EC private keys: - * ECPrivateKey ::= SEQUENCE { 1 + 2 - * version INTEGER , 1 + 1 + 1 - * privateKey OCTET STRING, 1 + 1 + ECP_MAX - * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) - * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above - * } - */ -#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES - -#else /* MBEDTLS_ECP_C */ - -#define ECP_PUB_DER_MAX_BYTES 0 -#define ECP_PRV_DER_MAX_BYTES 0 - -#endif /* MBEDTLS_ECP_C */ - -#define PUB_DER_MAX_BYTES RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ - RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES -#define PRV_DER_MAX_BYTES RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ - RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES - -int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) -{ - int ret; - unsigned char output_buf[PUB_DER_MAX_BYTES]; - size_t olen = 0; - - if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf, - sizeof(output_buf) ) ) < 0 ) - { - return( ret ); - } - - if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, - output_buf + sizeof(output_buf) - ret, - ret, buf, size, &olen ) ) != 0 ) - { - return( ret ); - } - - return( 0 ); -} - -int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) -{ - int ret; - unsigned char output_buf[PRV_DER_MAX_BYTES]; - const char *begin, *end; - size_t olen = 0; - - if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) - return( ret ); - -#if defined(MBEDTLS_RSA_C) - if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) - { - begin = PEM_BEGIN_PRIVATE_KEY_RSA; - end = PEM_END_PRIVATE_KEY_RSA; - } - else -#endif -#if defined(MBEDTLS_ECP_C) - if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) - { - begin = PEM_BEGIN_PRIVATE_KEY_EC; - end = PEM_END_PRIVATE_KEY_EC; - } - else -#endif - return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); - - if( ( ret = mbedtls_pem_write_buffer( begin, end, - output_buf + sizeof(output_buf) - ret, - ret, buf, size, &olen ) ) != 0 ) - { - return( ret ); - } - - return( 0 ); -} -#endif /* MBEDTLS_PEM_WRITE_C */ - -#endif /* MBEDTLS_PK_WRITE_C */ diff --git a/components/mbedtls/library/platform.c b/components/mbedtls/library/platform.c deleted file mode 100644 index af3b2f15ec..0000000000 --- a/components/mbedtls/library/platform.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Platform abstraction layer - * - * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_PLATFORM_C) - -#include "mbedtls/platform.h" - -#if defined(MBEDTLS_PLATFORM_MEMORY) -#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) -static void *platform_calloc_uninit( size_t n, size_t size ) -{ - ((void) n); - ((void) size); - return( NULL ); -} - -#define MBEDTLS_PLATFORM_STD_CALLOC platform_calloc_uninit -#endif /* !MBEDTLS_PLATFORM_STD_CALLOC */ - -#if !defined(MBEDTLS_PLATFORM_STD_FREE) -static void platform_free_uninit( void *ptr ) -{ - ((void) ptr); -} - -#define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit -#endif /* !MBEDTLS_PLATFORM_STD_FREE */ - -void * (*mbedtls_calloc)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; -void (*mbedtls_free)( void * ) = MBEDTLS_PLATFORM_STD_FREE; - -int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), - void (*free_func)( void * ) ) -{ - mbedtls_calloc = calloc_func; - mbedtls_free = free_func; - return( 0 ); -} -#endif /* MBEDTLS_PLATFORM_MEMORY */ - -#if defined(_WIN32) -#include -int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ) -{ - int ret; - va_list argp; - - /* Avoid calling the invalid parameter handler by checking ourselves */ - if( s == NULL || n == 0 || fmt == NULL ) - return( -1 ); - - va_start( argp, fmt ); -#if defined(_TRUNCATE) - ret = _vsnprintf_s( s, n, _TRUNCATE, fmt, argp ); -#else - ret = _vsnprintf( s, n, fmt, argp ); - if( ret < 0 || (size_t) ret == n ) - { - s[n-1] = '\0'; - ret = -1; - } -#endif - va_end( argp ); - - return( ret ); -} -#endif - -#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) -#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) -/* - * Make dummy function to prevent NULL pointer dereferences - */ -static int platform_snprintf_uninit( char * s, size_t n, - const char * format, ... ) -{ - ((void) s); - ((void) n); - ((void) format); - return( 0 ); -} - -#define MBEDTLS_PLATFORM_STD_SNPRINTF platform_snprintf_uninit -#endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */ - -int (*mbedtls_snprintf)( char * s, size_t n, - const char * format, - ... ) = MBEDTLS_PLATFORM_STD_SNPRINTF; - -int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, - const char * format, - ... ) ) -{ - mbedtls_snprintf = snprintf_func; - return( 0 ); -} -#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ - -#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) -#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) -/* - * Make dummy function to prevent NULL pointer dereferences - */ -static int platform_printf_uninit( const char *format, ... ) -{ - ((void) format); - return( 0 ); -} - -#define MBEDTLS_PLATFORM_STD_PRINTF platform_printf_uninit -#endif /* !MBEDTLS_PLATFORM_STD_PRINTF */ - -int (*mbedtls_printf)( const char *, ... ) = MBEDTLS_PLATFORM_STD_PRINTF; - -int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ) -{ - mbedtls_printf = printf_func; - return( 0 ); -} -#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ - -#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) -#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) -/* - * Make dummy function to prevent NULL pointer dereferences - */ -static int platform_fprintf_uninit( FILE *stream, const char *format, ... ) -{ - ((void) stream); - ((void) format); - return( 0 ); -} - -#define MBEDTLS_PLATFORM_STD_FPRINTF platform_fprintf_uninit -#endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */ - -int (*mbedtls_fprintf)( FILE *, const char *, ... ) = - MBEDTLS_PLATFORM_STD_FPRINTF; - -int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) ) -{ - mbedtls_fprintf = fprintf_func; - return( 0 ); -} -#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ - -#if defined(MBEDTLS_PLATFORM_EXIT_ALT) -#if !defined(MBEDTLS_PLATFORM_STD_EXIT) -/* - * Make dummy function to prevent NULL pointer dereferences - */ -static void platform_exit_uninit( int status ) -{ - ((void) status); -} - -#define MBEDTLS_PLATFORM_STD_EXIT platform_exit_uninit -#endif /* !MBEDTLS_PLATFORM_STD_EXIT */ - -void (*mbedtls_exit)( int status ) = MBEDTLS_PLATFORM_STD_EXIT; - -int mbedtls_platform_set_exit( void (*exit_func)( int status ) ) -{ - mbedtls_exit = exit_func; - return( 0 ); -} -#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ - -#if defined(MBEDTLS_HAVE_TIME) - -#if defined(MBEDTLS_PLATFORM_TIME_ALT) -#if !defined(MBEDTLS_PLATFORM_STD_TIME) -/* - * Make dummy function to prevent NULL pointer dereferences - */ -static mbedtls_time_t platform_time_uninit( mbedtls_time_t* timer ) -{ - ((void) timer); - return( 0 ); -} - -#define MBEDTLS_PLATFORM_STD_TIME platform_time_uninit -#endif /* !MBEDTLS_PLATFORM_STD_TIME */ - -mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* timer ) = MBEDTLS_PLATFORM_STD_TIME; - -int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* timer ) ) -{ - mbedtls_time = time_func; - return( 0 ); -} -#endif /* MBEDTLS_PLATFORM_TIME_ALT */ - -#endif /* MBEDTLS_HAVE_TIME */ - -#if defined(MBEDTLS_ENTROPY_NV_SEED) -#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) -/* Default implementations for the platform independent seed functions use - * standard libc file functions to read from and write to a pre-defined filename - */ -int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ) -{ - FILE *file; - size_t n; - - if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL ) - return -1; - - if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len ) - { - fclose( file ); - return -1; - } - - fclose( file ); - return( (int)n ); -} - -int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ) -{ - FILE *file; - size_t n; - - if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL ) - return -1; - - if( ( n = fwrite( buf, 1, buf_len, file ) ) != buf_len ) - { - fclose( file ); - return -1; - } - - fclose( file ); - return( (int)n ); -} -#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ - -#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) -#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) -/* - * Make dummy function to prevent NULL pointer dereferences - */ -static int platform_nv_seed_read_uninit( unsigned char *buf, size_t buf_len ) -{ - ((void) buf); - ((void) buf_len); - return( -1 ); -} - -#define MBEDTLS_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit -#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */ - -#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) -/* - * Make dummy function to prevent NULL pointer dereferences - */ -static int platform_nv_seed_write_uninit( unsigned char *buf, size_t buf_len ) -{ - ((void) buf); - ((void) buf_len); - return( -1 ); -} - -#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit -#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */ - -int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ) = - MBEDTLS_PLATFORM_STD_NV_SEED_READ; -int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ) = - MBEDTLS_PLATFORM_STD_NV_SEED_WRITE; - -int mbedtls_platform_set_nv_seed( - int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), - int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) ) -{ - mbedtls_nv_seed_read = nv_seed_read_func; - mbedtls_nv_seed_write = nv_seed_write_func; - return( 0 ); -} -#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ -#endif /* MBEDTLS_ENTROPY_NV_SEED */ - -#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) -/* - * Placeholder platform setup that does nothing by default - */ -int mbedtls_platform_setup( mbedtls_platform_context *ctx ) -{ - (void)ctx; - - return( 0 ); -} - -/* - * Placeholder platform teardown that does nothing by default - */ -void mbedtls_platform_teardown( mbedtls_platform_context *ctx ) -{ - (void)ctx; -} -#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ - -#endif /* MBEDTLS_PLATFORM_C */ diff --git a/components/mbedtls/library/ripemd160.c b/components/mbedtls/library/ripemd160.c deleted file mode 100644 index cdb0a63c0f..0000000000 --- a/components/mbedtls/library/ripemd160.c +++ /dev/null @@ -1,467 +0,0 @@ -/* - * RIPE MD-160 implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -/* - * The RIPEMD-160 algorithm was designed by RIPE in 1996 - * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html - * http://ehash.iaik.tugraz.at/wiki/RIPEMD-160 - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_RIPEMD160_C) - -#include "mbedtls/ripemd160.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_UINT32_LE -#define GET_UINT32_LE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] ) \ - | ( (uint32_t) (b)[(i) + 1] << 8 ) \ - | ( (uint32_t) (b)[(i) + 2] << 16 ) \ - | ( (uint32_t) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_UINT32_LE -#define PUT_UINT32_LE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ - (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ - (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ - (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ -} -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_ripemd160_context ) ); -} - -void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_ripemd160_context ) ); -} - -void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, - const mbedtls_ripemd160_context *src ) -{ - *dst = *src; -} - -/* - * RIPEMD-160 context setup - */ -void mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; - ctx->state[4] = 0xC3D2E1F0; -} - -#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) -/* - * Process one block - */ -void mbedtls_ripemd160_process( mbedtls_ripemd160_context *ctx, const unsigned char data[64] ) -{ - uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; - - GET_UINT32_LE( X[ 0], data, 0 ); - GET_UINT32_LE( X[ 1], data, 4 ); - GET_UINT32_LE( X[ 2], data, 8 ); - GET_UINT32_LE( X[ 3], data, 12 ); - GET_UINT32_LE( X[ 4], data, 16 ); - GET_UINT32_LE( X[ 5], data, 20 ); - GET_UINT32_LE( X[ 6], data, 24 ); - GET_UINT32_LE( X[ 7], data, 28 ); - GET_UINT32_LE( X[ 8], data, 32 ); - GET_UINT32_LE( X[ 9], data, 36 ); - GET_UINT32_LE( X[10], data, 40 ); - GET_UINT32_LE( X[11], data, 44 ); - GET_UINT32_LE( X[12], data, 48 ); - GET_UINT32_LE( X[13], data, 52 ); - GET_UINT32_LE( X[14], data, 56 ); - GET_UINT32_LE( X[15], data, 60 ); - - A = Ap = ctx->state[0]; - B = Bp = ctx->state[1]; - C = Cp = ctx->state[2]; - D = Dp = ctx->state[3]; - E = Ep = ctx->state[4]; - -#define F1( x, y, z ) ( x ^ y ^ z ) -#define F2( x, y, z ) ( ( x & y ) | ( ~x & z ) ) -#define F3( x, y, z ) ( ( x | ~y ) ^ z ) -#define F4( x, y, z ) ( ( x & z ) | ( y & ~z ) ) -#define F5( x, y, z ) ( x ^ ( y | ~z ) ) - -#define S( x, n ) ( ( x << n ) | ( x >> (32 - n) ) ) - -#define P( a, b, c, d, e, r, s, f, k ) \ - a += f( b, c, d ) + X[r] + k; \ - a = S( a, s ) + e; \ - c = S( c, 10 ); - -#define P2( a, b, c, d, e, r, s, rp, sp ) \ - P( a, b, c, d, e, r, s, F, K ); \ - P( a ## p, b ## p, c ## p, d ## p, e ## p, rp, sp, Fp, Kp ); - -#define F F1 -#define K 0x00000000 -#define Fp F5 -#define Kp 0x50A28BE6 - P2( A, B, C, D, E, 0, 11, 5, 8 ); - P2( E, A, B, C, D, 1, 14, 14, 9 ); - P2( D, E, A, B, C, 2, 15, 7, 9 ); - P2( C, D, E, A, B, 3, 12, 0, 11 ); - P2( B, C, D, E, A, 4, 5, 9, 13 ); - P2( A, B, C, D, E, 5, 8, 2, 15 ); - P2( E, A, B, C, D, 6, 7, 11, 15 ); - P2( D, E, A, B, C, 7, 9, 4, 5 ); - P2( C, D, E, A, B, 8, 11, 13, 7 ); - P2( B, C, D, E, A, 9, 13, 6, 7 ); - P2( A, B, C, D, E, 10, 14, 15, 8 ); - P2( E, A, B, C, D, 11, 15, 8, 11 ); - P2( D, E, A, B, C, 12, 6, 1, 14 ); - P2( C, D, E, A, B, 13, 7, 10, 14 ); - P2( B, C, D, E, A, 14, 9, 3, 12 ); - P2( A, B, C, D, E, 15, 8, 12, 6 ); -#undef F -#undef K -#undef Fp -#undef Kp - -#define F F2 -#define K 0x5A827999 -#define Fp F4 -#define Kp 0x5C4DD124 - P2( E, A, B, C, D, 7, 7, 6, 9 ); - P2( D, E, A, B, C, 4, 6, 11, 13 ); - P2( C, D, E, A, B, 13, 8, 3, 15 ); - P2( B, C, D, E, A, 1, 13, 7, 7 ); - P2( A, B, C, D, E, 10, 11, 0, 12 ); - P2( E, A, B, C, D, 6, 9, 13, 8 ); - P2( D, E, A, B, C, 15, 7, 5, 9 ); - P2( C, D, E, A, B, 3, 15, 10, 11 ); - P2( B, C, D, E, A, 12, 7, 14, 7 ); - P2( A, B, C, D, E, 0, 12, 15, 7 ); - P2( E, A, B, C, D, 9, 15, 8, 12 ); - P2( D, E, A, B, C, 5, 9, 12, 7 ); - P2( C, D, E, A, B, 2, 11, 4, 6 ); - P2( B, C, D, E, A, 14, 7, 9, 15 ); - P2( A, B, C, D, E, 11, 13, 1, 13 ); - P2( E, A, B, C, D, 8, 12, 2, 11 ); -#undef F -#undef K -#undef Fp -#undef Kp - -#define F F3 -#define K 0x6ED9EBA1 -#define Fp F3 -#define Kp 0x6D703EF3 - P2( D, E, A, B, C, 3, 11, 15, 9 ); - P2( C, D, E, A, B, 10, 13, 5, 7 ); - P2( B, C, D, E, A, 14, 6, 1, 15 ); - P2( A, B, C, D, E, 4, 7, 3, 11 ); - P2( E, A, B, C, D, 9, 14, 7, 8 ); - P2( D, E, A, B, C, 15, 9, 14, 6 ); - P2( C, D, E, A, B, 8, 13, 6, 6 ); - P2( B, C, D, E, A, 1, 15, 9, 14 ); - P2( A, B, C, D, E, 2, 14, 11, 12 ); - P2( E, A, B, C, D, 7, 8, 8, 13 ); - P2( D, E, A, B, C, 0, 13, 12, 5 ); - P2( C, D, E, A, B, 6, 6, 2, 14 ); - P2( B, C, D, E, A, 13, 5, 10, 13 ); - P2( A, B, C, D, E, 11, 12, 0, 13 ); - P2( E, A, B, C, D, 5, 7, 4, 7 ); - P2( D, E, A, B, C, 12, 5, 13, 5 ); -#undef F -#undef K -#undef Fp -#undef Kp - -#define F F4 -#define K 0x8F1BBCDC -#define Fp F2 -#define Kp 0x7A6D76E9 - P2( C, D, E, A, B, 1, 11, 8, 15 ); - P2( B, C, D, E, A, 9, 12, 6, 5 ); - P2( A, B, C, D, E, 11, 14, 4, 8 ); - P2( E, A, B, C, D, 10, 15, 1, 11 ); - P2( D, E, A, B, C, 0, 14, 3, 14 ); - P2( C, D, E, A, B, 8, 15, 11, 14 ); - P2( B, C, D, E, A, 12, 9, 15, 6 ); - P2( A, B, C, D, E, 4, 8, 0, 14 ); - P2( E, A, B, C, D, 13, 9, 5, 6 ); - P2( D, E, A, B, C, 3, 14, 12, 9 ); - P2( C, D, E, A, B, 7, 5, 2, 12 ); - P2( B, C, D, E, A, 15, 6, 13, 9 ); - P2( A, B, C, D, E, 14, 8, 9, 12 ); - P2( E, A, B, C, D, 5, 6, 7, 5 ); - P2( D, E, A, B, C, 6, 5, 10, 15 ); - P2( C, D, E, A, B, 2, 12, 14, 8 ); -#undef F -#undef K -#undef Fp -#undef Kp - -#define F F5 -#define K 0xA953FD4E -#define Fp F1 -#define Kp 0x00000000 - P2( B, C, D, E, A, 4, 9, 12, 8 ); - P2( A, B, C, D, E, 0, 15, 15, 5 ); - P2( E, A, B, C, D, 5, 5, 10, 12 ); - P2( D, E, A, B, C, 9, 11, 4, 9 ); - P2( C, D, E, A, B, 7, 6, 1, 12 ); - P2( B, C, D, E, A, 12, 8, 5, 5 ); - P2( A, B, C, D, E, 2, 13, 8, 14 ); - P2( E, A, B, C, D, 10, 12, 7, 6 ); - P2( D, E, A, B, C, 14, 5, 6, 8 ); - P2( C, D, E, A, B, 1, 12, 2, 13 ); - P2( B, C, D, E, A, 3, 13, 13, 6 ); - P2( A, B, C, D, E, 8, 14, 14, 5 ); - P2( E, A, B, C, D, 11, 11, 0, 15 ); - P2( D, E, A, B, C, 6, 8, 3, 13 ); - P2( C, D, E, A, B, 15, 5, 9, 11 ); - P2( B, C, D, E, A, 13, 6, 11, 11 ); -#undef F -#undef K -#undef Fp -#undef Kp - - C = ctx->state[1] + C + Dp; - ctx->state[1] = ctx->state[2] + D + Ep; - ctx->state[2] = ctx->state[3] + E + Ap; - ctx->state[3] = ctx->state[4] + A + Bp; - ctx->state[4] = ctx->state[0] + B + Cp; - ctx->state[0] = C; -} -#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ - -/* - * RIPEMD-160 process buffer - */ -void mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, - const unsigned char *input, size_t ilen ) -{ - size_t fill; - uint32_t left; - - if( ilen == 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += (uint32_t) ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (uint32_t) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_ripemd160_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - mbedtls_ripemd160_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - { - memcpy( (void *) (ctx->buffer + left), input, ilen ); - } -} - -static const unsigned char ripemd160_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * RIPEMD-160 final digest - */ -void mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, unsigned char output[20] ) -{ - uint32_t last, padn; - uint32_t high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_UINT32_LE( low, msglen, 0 ); - PUT_UINT32_LE( high, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - mbedtls_ripemd160_update( ctx, ripemd160_padding, padn ); - mbedtls_ripemd160_update( ctx, msglen, 8 ); - - PUT_UINT32_LE( ctx->state[0], output, 0 ); - PUT_UINT32_LE( ctx->state[1], output, 4 ); - PUT_UINT32_LE( ctx->state[2], output, 8 ); - PUT_UINT32_LE( ctx->state[3], output, 12 ); - PUT_UINT32_LE( ctx->state[4], output, 16 ); -} - -/* - * output = RIPEMD-160( input buffer ) - */ -void mbedtls_ripemd160( const unsigned char *input, size_t ilen, - unsigned char output[20] ) -{ - mbedtls_ripemd160_context ctx; - - mbedtls_ripemd160_init( &ctx ); - mbedtls_ripemd160_starts( &ctx ); - mbedtls_ripemd160_update( &ctx, input, ilen ); - mbedtls_ripemd160_finish( &ctx, output ); - mbedtls_ripemd160_free( &ctx ); -} - -#if defined(MBEDTLS_SELF_TEST) -/* - * Test vectors from the RIPEMD-160 paper and - * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html#HMAC - */ -#define TESTS 8 -#define KEYS 2 -static const char *ripemd160_test_input[TESTS] = -{ - "", - "a", - "abc", - "message digest", - "abcdefghijklmnopqrstuvwxyz", - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - "1234567890123456789012345678901234567890" - "1234567890123456789012345678901234567890", -}; - -static const unsigned char ripemd160_test_md[TESTS][20] = -{ - { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, - 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 }, - { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, - 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe }, - { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, - 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc }, - { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, - 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 }, - { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, - 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc }, - { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, - 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b }, - { 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed, - 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 }, - { 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb, - 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb }, -}; - -/* - * Checkup routine - */ -int mbedtls_ripemd160_self_test( int verbose ) -{ - int i; - unsigned char output[20]; - - memset( output, 0, sizeof output ); - - for( i = 0; i < TESTS; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " RIPEMD-160 test #%d: ", i + 1 ); - - mbedtls_ripemd160( (const unsigned char *) ripemd160_test_input[i], - strlen( ripemd160_test_input[i] ), - output ); - - if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_RIPEMD160_C */ diff --git a/components/mbedtls/library/rsa.c b/components/mbedtls/library/rsa.c deleted file mode 100644 index bdd2538c3a..0000000000 --- a/components/mbedtls/library/rsa.c +++ /dev/null @@ -1,1872 +0,0 @@ -/* - * The RSA public-key cryptosystem - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The following sources were referenced in the design of this implementation - * of the RSA algorithm: - * - * [1] A method for obtaining digital signatures and public-key cryptosystems - * R Rivest, A Shamir, and L Adleman - * http://people.csail.mit.edu/rivest/pubs.html#RSA78 - * - * [2] Handbook of Applied Cryptography - 1997, Chapter 8 - * Menezes, van Oorschot and Vanstone - * - * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks - * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and - * Stefan Mangard - * https://arxiv.org/abs/1702.08719v2 - * - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_RSA_C) - -#include "mbedtls/rsa.h" -#include "mbedtls/oid.h" - -#include - -#if defined(MBEDTLS_PKCS1_V21) -#include "mbedtls/md.h" -#endif - -#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) -#include -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -/* - * Initialize an RSA context - */ -void mbedtls_rsa_init( mbedtls_rsa_context *ctx, - int padding, - int hash_id ) -{ - memset( ctx, 0, sizeof( mbedtls_rsa_context ) ); - - mbedtls_rsa_set_padding( ctx, padding, hash_id ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif -} - -/* - * Set padding for an existing RSA context - */ -void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id ) -{ - ctx->padding = padding; - ctx->hash_id = hash_id; -} - -#if defined(MBEDTLS_GENPRIME) - -/* - * Generate an RSA keypair - */ -int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - unsigned int nbits, int exponent ) -{ - int ret; - mbedtls_mpi P1, Q1, H, G; - - if( f_rng == NULL || nbits < 128 || exponent < 3 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - if( nbits % 2 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); - mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G ); - - /* - * find primes P and Q with Q < P so that: - * GCD( E, (P-1)*(Q-1) ) == 1 - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); - - do - { - MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, 0, - f_rng, p_rng ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0, - f_rng, p_rng ) ); - - if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) - continue; - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); - if( mbedtls_mpi_bitlen( &ctx->N ) != nbits ) - continue; - - if( mbedtls_mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) - mbedtls_mpi_swap( &ctx->P, &ctx->Q ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); - } - while( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ); - - /* - * D = E^-1 mod ((P-1)*(Q-1)) - * DP = D mod (P - 1) - * DQ = D mod (Q - 1) - * QP = Q^-1 mod P - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); - - ctx->len = ( mbedtls_mpi_bitlen( &ctx->N ) + 7 ) >> 3; - -cleanup: - - mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G ); - - if( ret != 0 ) - { - mbedtls_rsa_free( ctx ); - return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret ); - } - - return( 0 ); -} - -#endif /* MBEDTLS_GENPRIME */ - -/* - * Check a public RSA key - */ -int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) -{ - if( !ctx->N.p || !ctx->E.p ) - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - - if( ( ctx->N.p[0] & 1 ) == 0 || - ( ctx->E.p[0] & 1 ) == 0 ) - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - - if( mbedtls_mpi_bitlen( &ctx->N ) < 128 || - mbedtls_mpi_bitlen( &ctx->N ) > MBEDTLS_MPI_MAX_BITS ) - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - - if( mbedtls_mpi_bitlen( &ctx->E ) < 2 || - mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - - return( 0 ); -} - -/* - * Check a private RSA key - */ -int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) -{ - int ret; - mbedtls_mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP; - - if( ( ret = mbedtls_rsa_check_pubkey( ctx ) ) != 0 ) - return( ret ); - - if( !ctx->P.p || !ctx->Q.p || !ctx->D.p ) - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - - mbedtls_mpi_init( &PQ ); mbedtls_mpi_init( &DE ); mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); - mbedtls_mpi_init( &H ); mbedtls_mpi_init( &I ); mbedtls_mpi_init( &G ); mbedtls_mpi_init( &G2 ); - mbedtls_mpi_init( &L1 ); mbedtls_mpi_init( &L2 ); mbedtls_mpi_init( &DP ); mbedtls_mpi_init( &DQ ); - mbedtls_mpi_init( &QP ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &P1, &Q1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G2, &P1, &Q1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L1, &L2, &H, &G2 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &I, &DE, &L1 ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DP, &ctx->D, &P1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) ); - /* - * Check for a valid PKCS1v2 private key - */ - if( mbedtls_mpi_cmp_mpi( &PQ, &ctx->N ) != 0 || - mbedtls_mpi_cmp_mpi( &DP, &ctx->DP ) != 0 || - mbedtls_mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 || - mbedtls_mpi_cmp_mpi( &QP, &ctx->QP ) != 0 || - mbedtls_mpi_cmp_int( &L2, 0 ) != 0 || - mbedtls_mpi_cmp_int( &I, 1 ) != 0 || - mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) - { - ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; - } - -cleanup: - mbedtls_mpi_free( &PQ ); mbedtls_mpi_free( &DE ); mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); - mbedtls_mpi_free( &H ); mbedtls_mpi_free( &I ); mbedtls_mpi_free( &G ); mbedtls_mpi_free( &G2 ); - mbedtls_mpi_free( &L1 ); mbedtls_mpi_free( &L2 ); mbedtls_mpi_free( &DP ); mbedtls_mpi_free( &DQ ); - mbedtls_mpi_free( &QP ); - - if( ret == MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) - return( ret ); - - if( ret != 0 ) - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED + ret ); - - return( 0 ); -} - -/* - * Check if contexts holding a public and private key match - */ -int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, const mbedtls_rsa_context *prv ) -{ - if( mbedtls_rsa_check_pubkey( pub ) != 0 || - mbedtls_rsa_check_privkey( prv ) != 0 ) - { - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - } - - if( mbedtls_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 || - mbedtls_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 ) - { - return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - } - - return( 0 ); -} - -/* - * Do an RSA public key operation - */ -int mbedtls_rsa_public( mbedtls_rsa_context *ctx, - const unsigned char *input, - unsigned char *output ) -{ - int ret; - size_t olen; - mbedtls_mpi T; - - mbedtls_mpi_init( &T ); - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); - - if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) - { - ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - goto cleanup; - } - - olen = ctx->len; - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); - -cleanup: -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - mbedtls_mpi_free( &T ); - - if( ret != 0 ) - return( MBEDTLS_ERR_RSA_PUBLIC_FAILED + ret ); - - return( 0 ); -} - -/* - * Generate or update blinding values, see section 10 of: - * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, - * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer - * Berlin Heidelberg, 1996. p. 104-113. - */ -static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) -{ - int ret, count = 0; - - if( ctx->Vf.p != NULL ) - { - /* We already have blinding values, just update them by squaring */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); - - goto cleanup; - } - - /* Unblinding value: Vf = random number, invertible mod N */ - do { - if( count++ > 10 ) - return( MBEDTLS_ERR_RSA_RNG_FAILED ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) ); - } while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ); - - /* Blinding value: Vi = Vf^(-e) mod N */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); - - -cleanup: - return( ret ); -} - -/* - * Exponent blinding supposed to prevent side-channel attacks using multiple - * traces of measurements to recover the RSA key. The more collisions are there, - * the more bits of the key can be recovered. See [3]. - * - * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) - * observations on avarage. - * - * For example with 28 byte blinding to achieve 2 collisions the adversary has - * to make 2^112 observations on avarage. - * - * (With the currently (as of 2017 April) known best algorithms breaking 2048 - * bit RSA requires approximately as much time as trying out 2^112 random keys. - * Thus in this sense with 28 byte blinding the security is not reduced by - * side-channel attacks like the one in [3]) - * - * This countermeasure does not help if the key recovery is possible with a - * single trace. - */ -#define RSA_EXPONENT_BLINDING 28 - -/* - * Do an RSA private key operation - */ -int mbedtls_rsa_private( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - const unsigned char *input, - unsigned char *output ) -{ - int ret; - size_t olen; - mbedtls_mpi T, T1, T2; - mbedtls_mpi P1, Q1, R; -#if defined(MBEDTLS_RSA_NO_CRT) - mbedtls_mpi D_blind; - mbedtls_mpi *D = &ctx->D; -#else - mbedtls_mpi DP_blind, DQ_blind; - mbedtls_mpi *DP = &ctx->DP; - mbedtls_mpi *DQ = &ctx->DQ; -#endif - - /* Make sure we have private key info, prevent possible misuse */ - if( ctx->P.p == NULL || ctx->Q.p == NULL || ctx->D.p == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - mbedtls_mpi_init( &T ); mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); - mbedtls_mpi_init( &P1 ); mbedtls_mpi_init( &Q1 ); mbedtls_mpi_init( &R ); - - - if( f_rng != NULL ) - { -#if defined(MBEDTLS_RSA_NO_CRT) - mbedtls_mpi_init( &D_blind ); -#else - mbedtls_mpi_init( &DP_blind ); - mbedtls_mpi_init( &DQ_blind ); -#endif - } - - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); - if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) - { - ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - goto cleanup; - } - - if( f_rng != NULL ) - { - /* - * Blinding - * T = T * Vi mod N - */ - MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); - - /* - * Exponent blinding - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); - -#if defined(MBEDTLS_RSA_NO_CRT) - /* - * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, - f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); - - D = &D_blind; -#else - /* - * DP_blind = ( P - 1 ) * R + DP - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, - f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind, - &ctx->DP ) ); - - DP = &DP_blind; - - /* - * DQ_blind = ( Q - 1 ) * R + DQ - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, - f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind, - &ctx->DQ ) ); - - DQ = &DQ_blind; -#endif /* MBEDTLS_RSA_NO_CRT */ - } - -#if defined(MBEDTLS_RSA_NO_CRT) - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) ); -#else - /* - * Faster decryption using the CRT - * - * T1 = input ^ dP mod P - * T2 = input ^ dQ mod Q - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T1, &T, DP, &ctx->P, &ctx->RP ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T2, &T, DQ, &ctx->Q, &ctx->RQ ) ); - - /* - * T = (T1 - T2) * (Q^-1 mod P) mod P - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T1, &T2 ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->QP ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T1, &ctx->P ) ); - - /* - * T = T2 + T * Q - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T, &ctx->Q ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &T2, &T1 ) ); -#endif /* MBEDTLS_RSA_NO_CRT */ - - if( f_rng != NULL ) - { - /* - * Unblind - * T = T * Vf mod N - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); - } - - olen = ctx->len; - MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); - -cleanup: -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - mbedtls_mpi_free( &T ); mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); - mbedtls_mpi_free( &P1 ); mbedtls_mpi_free( &Q1 ); mbedtls_mpi_free( &R ); - - if( f_rng != NULL ) - { -#if defined(MBEDTLS_RSA_NO_CRT) - mbedtls_mpi_free( &D_blind ); -#else - mbedtls_mpi_free( &DP_blind ); - mbedtls_mpi_free( &DQ_blind ); -#endif - } - - if( ret != 0 ) - return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); - - return( 0 ); -} - -#if defined(MBEDTLS_PKCS1_V21) -/** - * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. - * - * \param dst buffer to mask - * \param dlen length of destination buffer - * \param src source of the mask generation - * \param slen length of the source buffer - * \param md_ctx message digest context to use - */ -static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, - size_t slen, mbedtls_md_context_t *md_ctx ) -{ - unsigned char mask[MBEDTLS_MD_MAX_SIZE]; - unsigned char counter[4]; - unsigned char *p; - unsigned int hlen; - size_t i, use_len; - - memset( mask, 0, MBEDTLS_MD_MAX_SIZE ); - memset( counter, 0, 4 ); - - hlen = mbedtls_md_get_size( md_ctx->md_info ); - - /* Generate and apply dbMask */ - p = dst; - - while( dlen > 0 ) - { - use_len = hlen; - if( dlen < hlen ) - use_len = dlen; - - mbedtls_md_starts( md_ctx ); - mbedtls_md_update( md_ctx, src, slen ); - mbedtls_md_update( md_ctx, counter, 4 ); - mbedtls_md_finish( md_ctx, mask ); - - for( i = 0; i < use_len; ++i ) - *p++ ^= mask[i]; - - counter[3]++; - - dlen -= use_len; - } - - mbedtls_zeroize( mask, sizeof( mask ) ); -} -#endif /* MBEDTLS_PKCS1_V21 */ - -#if defined(MBEDTLS_PKCS1_V21) -/* - * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function - */ -int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - const unsigned char *label, size_t label_len, - size_t ilen, - const unsigned char *input, - unsigned char *output ) -{ - size_t olen; - int ret; - unsigned char *p = output; - unsigned int hlen; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - if( f_rng == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - olen = ctx->len; - hlen = mbedtls_md_get_size( md_info ); - - /* first comparison checks for overflow */ - if( ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - memset( output, 0, olen ); - - *p++ = 0; - - /* Generate a random octet string seed */ - if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) - return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); - - p += hlen; - - /* Construct DB */ - mbedtls_md( md_info, label, label_len, p ); - p += hlen; - p += olen - 2 * hlen - 2 - ilen; - *p++ = 1; - memcpy( p, input, ilen ); - - mbedtls_md_init( &md_ctx ); - if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) - { - mbedtls_md_free( &md_ctx ); - return( ret ); - } - - /* maskedDB: Apply dbMask to DB */ - mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, - &md_ctx ); - - /* maskedSeed: Apply seedMask to seed */ - mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, - &md_ctx ); - - mbedtls_md_free( &md_ctx ); - - return( ( mode == MBEDTLS_RSA_PUBLIC ) - ? mbedtls_rsa_public( ctx, output, output ) - : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); -} -#endif /* MBEDTLS_PKCS1_V21 */ - -#if defined(MBEDTLS_PKCS1_V15) -/* - * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function - */ -int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t ilen, - const unsigned char *input, - unsigned char *output ) -{ - size_t nb_pad, olen; - int ret; - unsigned char *p = output; - - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - // We don't check p_rng because it won't be dereferenced here - if( f_rng == NULL || input == NULL || output == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - olen = ctx->len; - - /* first comparison checks for overflow */ - if( ilen + 11 < ilen || olen < ilen + 11 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - nb_pad = olen - 3 - ilen; - - *p++ = 0; - if( mode == MBEDTLS_RSA_PUBLIC ) - { - *p++ = MBEDTLS_RSA_CRYPT; - - while( nb_pad-- > 0 ) - { - int rng_dl = 100; - - do { - ret = f_rng( p_rng, p, 1 ); - } while( *p == 0 && --rng_dl && ret == 0 ); - - /* Check if RNG failed to generate data */ - if( rng_dl == 0 || ret != 0 ) - return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); - - p++; - } - } - else - { - *p++ = MBEDTLS_RSA_SIGN; - - while( nb_pad-- > 0 ) - *p++ = 0xFF; - } - - *p++ = 0; - memcpy( p, input, ilen ); - - return( ( mode == MBEDTLS_RSA_PUBLIC ) - ? mbedtls_rsa_public( ctx, output, output ) - : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); -} -#endif /* MBEDTLS_PKCS1_V15 */ - -/* - * Add the message padding, then do an RSA operation - */ -int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t ilen, - const unsigned char *input, - unsigned char *output ) -{ - switch( ctx->padding ) - { -#if defined(MBEDTLS_PKCS1_V15) - case MBEDTLS_RSA_PKCS_V15: - return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen, - input, output ); -#endif - -#if defined(MBEDTLS_PKCS1_V21) - case MBEDTLS_RSA_PKCS_V21: - return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0, - ilen, input, output ); -#endif - - default: - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - } -} - -#if defined(MBEDTLS_PKCS1_V21) -/* - * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function - */ -int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - const unsigned char *label, size_t label_len, - size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ) -{ - int ret; - size_t ilen, i, pad_len; - unsigned char *p, bad, pad_done; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; - unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; - unsigned int hlen; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - - /* - * Parameters sanity checks - */ - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - ilen = ctx->len; - - if( ilen < 16 || ilen > sizeof( buf ) ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - hlen = mbedtls_md_get_size( md_info ); - - // checking for integer underflow - if( 2 * hlen + 2 > ilen ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - /* - * RSA operation - */ - ret = ( mode == MBEDTLS_RSA_PUBLIC ) - ? mbedtls_rsa_public( ctx, input, buf ) - : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); - - if( ret != 0 ) - goto cleanup; - - /* - * Unmask data and generate lHash - */ - mbedtls_md_init( &md_ctx ); - if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) - { - mbedtls_md_free( &md_ctx ); - goto cleanup; - } - - - /* Generate lHash */ - mbedtls_md( md_info, label, label_len, lhash ); - - /* seed: Apply seedMask to maskedSeed */ - mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, - &md_ctx ); - - /* DB: Apply dbMask to maskedDB */ - mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, - &md_ctx ); - - mbedtls_md_free( &md_ctx ); - - /* - * Check contents, in "constant-time" - */ - p = buf; - bad = 0; - - bad |= *p++; /* First byte must be 0 */ - - p += hlen; /* Skip seed */ - - /* Check lHash */ - for( i = 0; i < hlen; i++ ) - bad |= lhash[i] ^ *p++; - - /* Get zero-padding len, but always read till end of buffer - * (minus one, for the 01 byte) */ - pad_len = 0; - pad_done = 0; - for( i = 0; i < ilen - 2 * hlen - 2; i++ ) - { - pad_done |= p[i]; - pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; - } - - p += pad_len; - bad |= *p++ ^ 0x01; - - /* - * The only information "leaked" is whether the padding was correct or not - * (eg, no data is copied if it was not correct). This meets the - * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between - * the different error conditions. - */ - if( bad != 0 ) - { - ret = MBEDTLS_ERR_RSA_INVALID_PADDING; - goto cleanup; - } - - if( ilen - ( p - buf ) > output_max_len ) - { - ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; - goto cleanup; - } - - *olen = ilen - (p - buf); - memcpy( output, p, *olen ); - ret = 0; - -cleanup: - mbedtls_zeroize( buf, sizeof( buf ) ); - mbedtls_zeroize( lhash, sizeof( lhash ) ); - - return( ret ); -} -#endif /* MBEDTLS_PKCS1_V21 */ - -#if defined(MBEDTLS_PKCS1_V15) -/* - * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function - */ -int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len) -{ - int ret; - size_t ilen, pad_count = 0, i; - unsigned char *p, bad, pad_done = 0; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; - - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - ilen = ctx->len; - - if( ilen < 16 || ilen > sizeof( buf ) ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - ret = ( mode == MBEDTLS_RSA_PUBLIC ) - ? mbedtls_rsa_public( ctx, input, buf ) - : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); - - if( ret != 0 ) - goto cleanup; - - p = buf; - bad = 0; - - /* - * Check and get padding len in "constant-time" - */ - bad |= *p++; /* First byte must be 0 */ - - /* This test does not depend on secret data */ - if( mode == MBEDTLS_RSA_PRIVATE ) - { - bad |= *p++ ^ MBEDTLS_RSA_CRYPT; - - /* Get padding len, but always read till end of buffer - * (minus one, for the 00 byte) */ - for( i = 0; i < ilen - 3; i++ ) - { - pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1; - pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; - } - - p += pad_count; - bad |= *p++; /* Must be zero */ - } - else - { - bad |= *p++ ^ MBEDTLS_RSA_SIGN; - - /* Get padding len, but always read till end of buffer - * (minus one, for the 00 byte) */ - for( i = 0; i < ilen - 3; i++ ) - { - pad_done |= ( p[i] != 0xFF ); - pad_count += ( pad_done == 0 ); - } - - p += pad_count; - bad |= *p++; /* Must be zero */ - } - - bad |= ( pad_count < 8 ); - - if( bad ) - { - ret = MBEDTLS_ERR_RSA_INVALID_PADDING; - goto cleanup; - } - - if( ilen - ( p - buf ) > output_max_len ) - { - ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; - goto cleanup; - } - - *olen = ilen - (p - buf); - memcpy( output, p, *olen ); - ret = 0; - -cleanup: - mbedtls_zeroize( buf, sizeof( buf ) ); - - return( ret ); -} -#endif /* MBEDTLS_PKCS1_V15 */ - -/* - * Do an RSA operation, then remove the message padding - */ -int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len) -{ - switch( ctx->padding ) - { -#if defined(MBEDTLS_PKCS1_V15) - case MBEDTLS_RSA_PKCS_V15: - return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen, - input, output, output_max_len ); -#endif - -#if defined(MBEDTLS_PKCS1_V21) - case MBEDTLS_RSA_PKCS_V21: - return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0, - olen, input, output, - output_max_len ); -#endif - - default: - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - } -} - -#if defined(MBEDTLS_PKCS1_V21) -/* - * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function - */ -int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - size_t olen; - unsigned char *p = sig; - unsigned char salt[MBEDTLS_MD_MAX_SIZE]; - unsigned int slen, hlen, offset = 0; - int ret; - size_t msb; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - if( f_rng == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - olen = ctx->len; - - if( md_alg != MBEDTLS_MD_NONE ) - { - /* Gather length of hash to sign */ - md_info = mbedtls_md_info_from_type( md_alg ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - hashlen = mbedtls_md_get_size( md_info ); - } - - md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - hlen = mbedtls_md_get_size( md_info ); - slen = hlen; - - if( olen < hlen + slen + 2 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - memset( sig, 0, olen ); - - /* Generate salt of length slen */ - if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) - return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); - - /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ - msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; - p += olen - hlen * 2 - 2; - *p++ = 0x01; - memcpy( p, salt, slen ); - p += slen; - - mbedtls_md_init( &md_ctx ); - if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) - { - mbedtls_md_free( &md_ctx ); - /* No need to zeroize salt: we didn't use it. */ - return( ret ); - } - - /* Generate H = Hash( M' ) */ - mbedtls_md_starts( &md_ctx ); - mbedtls_md_update( &md_ctx, p, 8 ); - mbedtls_md_update( &md_ctx, hash, hashlen ); - mbedtls_md_update( &md_ctx, salt, slen ); - mbedtls_md_finish( &md_ctx, p ); - mbedtls_zeroize( salt, sizeof( salt ) ); - - /* Compensate for boundary condition when applying mask */ - if( msb % 8 == 0 ) - offset = 1; - - /* maskedDB: Apply dbMask to DB */ - mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx ); - - mbedtls_md_free( &md_ctx ); - - msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; - sig[0] &= 0xFF >> ( olen * 8 - msb ); - - p += hlen; - *p++ = 0xBC; - - return( ( mode == MBEDTLS_RSA_PUBLIC ) - ? mbedtls_rsa_public( ctx, sig, sig ) - : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) ); -} -#endif /* MBEDTLS_PKCS1_V21 */ - -#if defined(MBEDTLS_PKCS1_V15) -/* - * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function - */ -/* - * Do an RSA operation to sign the message digest - */ -int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - size_t nb_pad, olen, oid_size = 0; - unsigned char *p = sig; - const char *oid = NULL; - unsigned char *sig_try = NULL, *verif = NULL; - size_t i; - unsigned char diff; - volatile unsigned char diff_no_optimize; - int ret; - - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - olen = ctx->len; - nb_pad = olen - 3; - - if( md_alg != MBEDTLS_MD_NONE ) - { - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - nb_pad -= 10 + oid_size; - - hashlen = mbedtls_md_get_size( md_info ); - } - - nb_pad -= hashlen; - - if( ( nb_pad < 8 ) || ( nb_pad > olen ) ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - *p++ = 0; - *p++ = MBEDTLS_RSA_SIGN; - memset( p, 0xFF, nb_pad ); - p += nb_pad; - *p++ = 0; - - if( md_alg == MBEDTLS_MD_NONE ) - { - memcpy( p, hash, hashlen ); - } - else - { - /* - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithmIdentifier, - * digest Digest } - * - * DigestAlgorithmIdentifier ::= AlgorithmIdentifier - * - * Digest ::= OCTET STRING - */ - *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; - *p++ = (unsigned char) ( 0x08 + oid_size + hashlen ); - *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; - *p++ = (unsigned char) ( 0x04 + oid_size ); - *p++ = MBEDTLS_ASN1_OID; - *p++ = oid_size & 0xFF; - memcpy( p, oid, oid_size ); - p += oid_size; - *p++ = MBEDTLS_ASN1_NULL; - *p++ = 0x00; - *p++ = MBEDTLS_ASN1_OCTET_STRING; - *p++ = hashlen; - memcpy( p, hash, hashlen ); - } - - if( mode == MBEDTLS_RSA_PUBLIC ) - return( mbedtls_rsa_public( ctx, sig, sig ) ); - - /* - * In order to prevent Lenstra's attack, make the signature in a - * temporary buffer and check it before returning it. - */ - sig_try = mbedtls_calloc( 1, ctx->len ); - if( sig_try == NULL ) - return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); - - verif = mbedtls_calloc( 1, ctx->len ); - if( verif == NULL ) - { - mbedtls_free( sig_try ); - return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); - } - - MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) ); - MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) ); - - /* Compare in constant time just in case */ - for( diff = 0, i = 0; i < ctx->len; i++ ) - diff |= verif[i] ^ sig[i]; - diff_no_optimize = diff; - - if( diff_no_optimize != 0 ) - { - ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; - goto cleanup; - } - - memcpy( sig, sig_try, ctx->len ); - -cleanup: - mbedtls_free( sig_try ); - mbedtls_free( verif ); - - return( ret ); -} -#endif /* MBEDTLS_PKCS1_V15 */ - -/* - * Do an RSA operation to sign the message digest - */ -int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - switch( ctx->padding ) - { -#if defined(MBEDTLS_PKCS1_V15) - case MBEDTLS_RSA_PKCS_V15: - return mbedtls_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg, - hashlen, hash, sig ); -#endif - -#if defined(MBEDTLS_PKCS1_V21) - case MBEDTLS_RSA_PKCS_V21: - return mbedtls_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg, - hashlen, hash, sig ); -#endif - - default: - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - } -} - -#if defined(MBEDTLS_PKCS1_V21) -/* - * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function - */ -int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - mbedtls_md_type_t mgf1_hash_id, - int expected_salt_len, - const unsigned char *sig ) -{ - int ret; - size_t siglen; - unsigned char *p; - unsigned char result[MBEDTLS_MD_MAX_SIZE]; - unsigned char zeros[8]; - unsigned int hlen; - size_t slen, msb; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; - - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - siglen = ctx->len; - - if( siglen < 16 || siglen > sizeof( buf ) ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - ret = ( mode == MBEDTLS_RSA_PUBLIC ) - ? mbedtls_rsa_public( ctx, sig, buf ) - : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); - - if( ret != 0 ) - return( ret ); - - p = buf; - - if( buf[siglen - 1] != 0xBC ) - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - - if( md_alg != MBEDTLS_MD_NONE ) - { - /* Gather length of hash to sign */ - md_info = mbedtls_md_info_from_type( md_alg ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - hashlen = mbedtls_md_get_size( md_info ); - } - - md_info = mbedtls_md_info_from_type( mgf1_hash_id ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - hlen = mbedtls_md_get_size( md_info ); - slen = siglen - hlen - 1; /* Currently length of salt + padding */ - - memset( zeros, 0, 8 ); - - /* - * Note: EMSA-PSS verification is over the length of N - 1 bits - */ - msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; - - /* Compensate for boundary condition when applying mask */ - if( msb % 8 == 0 ) - { - p++; - siglen -= 1; - } - if( buf[0] >> ( 8 - siglen * 8 + msb ) ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - mbedtls_md_init( &md_ctx ); - if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) - { - mbedtls_md_free( &md_ctx ); - return( ret ); - } - - mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); - - buf[0] &= 0xFF >> ( siglen * 8 - msb ); - - while( p < buf + siglen && *p == 0 ) - p++; - - if( p == buf + siglen || - *p++ != 0x01 ) - { - mbedtls_md_free( &md_ctx ); - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - } - - /* Actual salt len */ - slen -= p - buf; - - if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && - slen != (size_t) expected_salt_len ) - { - mbedtls_md_free( &md_ctx ); - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - } - - /* - * Generate H = Hash( M' ) - */ - mbedtls_md_starts( &md_ctx ); - mbedtls_md_update( &md_ctx, zeros, 8 ); - mbedtls_md_update( &md_ctx, hash, hashlen ); - mbedtls_md_update( &md_ctx, p, slen ); - mbedtls_md_finish( &md_ctx, result ); - - mbedtls_md_free( &md_ctx ); - - if( memcmp( p + slen, result, hlen ) == 0 ) - return( 0 ); - else - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); -} - -/* - * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function - */ -int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - const unsigned char *sig ) -{ - mbedtls_md_type_t mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) - ? (mbedtls_md_type_t) ctx->hash_id - : md_alg; - - return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode, - md_alg, hashlen, hash, - mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY, - sig ) ); - -} -#endif /* MBEDTLS_PKCS1_V21 */ - -#if defined(MBEDTLS_PKCS1_V15) -/* - * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function - */ -int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - const unsigned char *sig ) -{ - int ret; - size_t len, siglen, asn1_len; - unsigned char *p, *p0, *end; - mbedtls_md_type_t msg_md_alg; - const mbedtls_md_info_t *md_info; - mbedtls_asn1_buf oid; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; - - if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - siglen = ctx->len; - - if( siglen < 16 || siglen > sizeof( buf ) ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - - ret = ( mode == MBEDTLS_RSA_PUBLIC ) - ? mbedtls_rsa_public( ctx, sig, buf ) - : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); - - if( ret != 0 ) - return( ret ); - - p = buf; - - if( *p++ != 0 || *p++ != MBEDTLS_RSA_SIGN ) - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - - while( *p != 0 ) - { - if( p >= buf + siglen - 1 || *p != 0xFF ) - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - p++; - } - p++; /* skip 00 byte */ - - /* We've read: 00 01 PS 00 where PS must be at least 8 bytes */ - if( p - buf < 11 ) - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - - len = siglen - ( p - buf ); - - if( len == hashlen && md_alg == MBEDTLS_MD_NONE ) - { - if( memcmp( p, hash, hashlen ) == 0 ) - return( 0 ); - else - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - } - - md_info = mbedtls_md_info_from_type( md_alg ); - if( md_info == NULL ) - return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - hashlen = mbedtls_md_get_size( md_info ); - - end = p + len; - - /* - * Parse the ASN.1 structure inside the PKCS#1 v1.5 structure. - * Insist on 2-byte length tags, to protect against variants of - * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification. - */ - p0 = p; - if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - if( p != p0 + 2 || asn1_len + 2 != len ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - p0 = p; - if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - if( p != p0 + 2 || asn1_len + 6 + hashlen != len ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - p0 = p; - if( ( ret = mbedtls_asn1_get_tag( &p, end, &oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - if( p != p0 + 2 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - oid.p = p; - p += oid.len; - - if( mbedtls_oid_get_md_alg( &oid, &msg_md_alg ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - if( md_alg != msg_md_alg ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - /* - * assume the algorithm parameters must be NULL - */ - p0 = p; - if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_NULL ) ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - if( p != p0 + 2 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - p0 = p; - if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - if( p != p0 + 2 || asn1_len != hashlen ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - if( memcmp( p, hash, hashlen ) != 0 ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - p += hashlen; - - if( p != end ) - return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - - return( 0 ); -} -#endif /* MBEDTLS_PKCS1_V15 */ - -/* - * Do an RSA operation and check the message digest - */ -int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - mbedtls_md_type_t md_alg, - unsigned int hashlen, - const unsigned char *hash, - const unsigned char *sig ) -{ - switch( ctx->padding ) - { -#if defined(MBEDTLS_PKCS1_V15) - case MBEDTLS_RSA_PKCS_V15: - return mbedtls_rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg, - hashlen, hash, sig ); -#endif - -#if defined(MBEDTLS_PKCS1_V21) - case MBEDTLS_RSA_PKCS_V21: - return mbedtls_rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg, - hashlen, hash, sig ); -#endif - - default: - return( MBEDTLS_ERR_RSA_INVALID_PADDING ); - } -} - -/* - * Copy the components of an RSA key - */ -int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) -{ - int ret; - - dst->ver = src->ver; - dst->len = src->len; - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->E, &src->E ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) ); - - dst->padding = src->padding; - dst->hash_id = src->hash_id; - -cleanup: - if( ret != 0 ) - mbedtls_rsa_free( dst ); - - return( ret ); -} - -/* - * Free the components of an RSA key - */ -void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) -{ - mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->Vf ); - mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP ); mbedtls_mpi_free( &ctx->RN ); - mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ ); mbedtls_mpi_free( &ctx->DP ); - mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P ); mbedtls_mpi_free( &ctx->D ); - mbedtls_mpi_free( &ctx->E ); mbedtls_mpi_free( &ctx->N ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); -#endif -} - -#if defined(MBEDTLS_SELF_TEST) - -#include "mbedtls/sha1.h" - -/* - * Example RSA-1024 keypair, for test purposes - */ -#define KEY_LEN 128 - -#define RSA_N "9292758453063D803DD603D5E777D788" \ - "8ED1D5BF35786190FA2F23EBC0848AEA" \ - "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ - "7130B9CED7ACDF54CFC7555AC14EEBAB" \ - "93A89813FBF3C4F8066D2D800F7C38A8" \ - "1AE31942917403FF4946B0A83D3D3E05" \ - "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ - "5E94BB77B07507233A0BC7BAC8F90F79" - -#define RSA_E "10001" - -#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ - "66CA472BC44D253102F8B4A9D3BFA750" \ - "91386C0077937FE33FA3252D28855837" \ - "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ - "DF79C5CE07EE72C7F123142198164234" \ - "CABB724CF78B8173B9F880FC86322407" \ - "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ - "071513A1E85B5DFA031F21ECAE91A34D" - -#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ - "2C01CAD19EA484A87EA4377637E75500" \ - "FCB2005C5C7DD6EC4AC023CDA285D796" \ - "C3D9E75E1EFC42488BB4F1D13AC30A57" - -#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ - "E211C2B9E5DB1ED0BF61D0D9899620F4" \ - "910E4168387E3C30AA1E00C339A79508" \ - "8452DD96A9A5EA5D9DCA68DA636032AF" - -#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \ - "3C94D22288ACD763FD8E5600ED4A702D" \ - "F84198A5F06C2E72236AE490C93F07F8" \ - "3CC559CD27BC2D1CA488811730BB5725" - -#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \ - "D8AAEA56749EA28623272E4F7D0592AF" \ - "7C1F1313CAC9471B5C523BFE592F517B" \ - "407A1BD76C164B93DA2D32A383E58357" - -#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \ - "F38D18D2B2F0E2DD275AA977E2BF4411" \ - "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ - "A74206CEC169D74BF5A8C50D6F48EA08" - -#define PT_LEN 24 -#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ - "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" - -#if defined(MBEDTLS_PKCS1_V15) -static int myrand( void *rng_state, unsigned char *output, size_t len ) -{ -#if !defined(__OpenBSD__) - size_t i; - - if( rng_state != NULL ) - rng_state = NULL; - - for( i = 0; i < len; ++i ) - output[i] = rand(); -#else - if( rng_state != NULL ) - rng_state = NULL; - - arc4random_buf( output, len ); -#endif /* !OpenBSD */ - - return( 0 ); -} -#endif /* MBEDTLS_PKCS1_V15 */ - -/* - * Checkup routine - */ -int mbedtls_rsa_self_test( int verbose ) -{ - int ret = 0; -#if defined(MBEDTLS_PKCS1_V15) - size_t len; - mbedtls_rsa_context rsa; - unsigned char rsa_plaintext[PT_LEN]; - unsigned char rsa_decrypted[PT_LEN]; - unsigned char rsa_ciphertext[KEY_LEN]; -#if defined(MBEDTLS_SHA1_C) - unsigned char sha1sum[20]; -#endif - - mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); - - rsa.len = KEY_LEN; - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.N , 16, RSA_N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.E , 16, RSA_E ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.D , 16, RSA_D ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.P , 16, RSA_P ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.Q , 16, RSA_Q ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DP, 16, RSA_DP ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.DQ, 16, RSA_DQ ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP ) ); - - if( verbose != 0 ) - mbedtls_printf( " RSA key validation: " ); - - if( mbedtls_rsa_check_pubkey( &rsa ) != 0 || - mbedtls_rsa_check_privkey( &rsa ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n PKCS#1 encryption : " ); - - memcpy( rsa_plaintext, RSA_PT, PT_LEN ); - - if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, PT_LEN, - rsa_plaintext, rsa_ciphertext ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n PKCS#1 decryption : " ); - - if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, &len, - rsa_ciphertext, rsa_decrypted, - sizeof(rsa_decrypted) ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - -#if defined(MBEDTLS_SHA1_C) - if( verbose != 0 ) - mbedtls_printf( " PKCS#1 data sign : " ); - - mbedtls_sha1( rsa_plaintext, PT_LEN, sha1sum ); - - if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0, - sha1sum, rsa_ciphertext ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); - - if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0, - sha1sum, rsa_ciphertext ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); -#endif /* MBEDTLS_SHA1_C */ - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -cleanup: - mbedtls_rsa_free( &rsa ); -#else /* MBEDTLS_PKCS1_V15 */ - ((void) verbose); -#endif /* MBEDTLS_PKCS1_V15 */ - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_RSA_C */ diff --git a/components/mbedtls/library/sha1.c b/components/mbedtls/library/sha1.c deleted file mode 100644 index 2ccf2a2f52..0000000000 --- a/components/mbedtls/library/sha1.c +++ /dev/null @@ -1,448 +0,0 @@ -/* - * FIPS-180-1 compliant SHA-1 implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The SHA-1 standard was published by NIST in 1993. - * - * http://www.itl.nist.gov/fipspubs/fip180-1.htm - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_SHA1_C) - -#include "mbedtls/sha1.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_SHA1_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; -} - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT32_BE -#define GET_UINT32_BE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ - | ( (uint32_t) (b)[(i) + 1] << 16 ) \ - | ( (uint32_t) (b)[(i) + 2] << 8 ) \ - | ( (uint32_t) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_UINT32_BE -#define PUT_UINT32_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); -} - -void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); -} - -void mbedtls_sha1_clone( mbedtls_sha1_context *dst, - const mbedtls_sha1_context *src ) -{ - *dst = *src; -} - -/* - * SHA-1 context setup - */ -void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - ctx->state[0] = 0x67452301; - ctx->state[1] = 0xEFCDAB89; - ctx->state[2] = 0x98BADCFE; - ctx->state[3] = 0x10325476; - ctx->state[4] = 0xC3D2E1F0; -} - -#if !defined(MBEDTLS_SHA1_PROCESS_ALT) -void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) -{ - uint32_t temp, W[16], A, B, C, D, E; - - GET_UINT32_BE( W[ 0], data, 0 ); - GET_UINT32_BE( W[ 1], data, 4 ); - GET_UINT32_BE( W[ 2], data, 8 ); - GET_UINT32_BE( W[ 3], data, 12 ); - GET_UINT32_BE( W[ 4], data, 16 ); - GET_UINT32_BE( W[ 5], data, 20 ); - GET_UINT32_BE( W[ 6], data, 24 ); - GET_UINT32_BE( W[ 7], data, 28 ); - GET_UINT32_BE( W[ 8], data, 32 ); - GET_UINT32_BE( W[ 9], data, 36 ); - GET_UINT32_BE( W[10], data, 40 ); - GET_UINT32_BE( W[11], data, 44 ); - GET_UINT32_BE( W[12], data, 48 ); - GET_UINT32_BE( W[13], data, 52 ); - GET_UINT32_BE( W[14], data, 56 ); - GET_UINT32_BE( W[15], data, 60 ); - -#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) - -#define R(t) \ -( \ - temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \ - W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \ - ( W[t & 0x0F] = S(temp,1) ) \ -) - -#define P(a,b,c,d,e,x) \ -{ \ - e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ -} - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - E = ctx->state[4]; - -#define F(x,y,z) (z ^ (x & (y ^ z))) -#define K 0x5A827999 - - P( A, B, C, D, E, W[0] ); - P( E, A, B, C, D, W[1] ); - P( D, E, A, B, C, W[2] ); - P( C, D, E, A, B, W[3] ); - P( B, C, D, E, A, W[4] ); - P( A, B, C, D, E, W[5] ); - P( E, A, B, C, D, W[6] ); - P( D, E, A, B, C, W[7] ); - P( C, D, E, A, B, W[8] ); - P( B, C, D, E, A, W[9] ); - P( A, B, C, D, E, W[10] ); - P( E, A, B, C, D, W[11] ); - P( D, E, A, B, C, W[12] ); - P( C, D, E, A, B, W[13] ); - P( B, C, D, E, A, W[14] ); - P( A, B, C, D, E, W[15] ); - P( E, A, B, C, D, R(16) ); - P( D, E, A, B, C, R(17) ); - P( C, D, E, A, B, R(18) ); - P( B, C, D, E, A, R(19) ); - -#undef K -#undef F - -#define F(x,y,z) (x ^ y ^ z) -#define K 0x6ED9EBA1 - - P( A, B, C, D, E, R(20) ); - P( E, A, B, C, D, R(21) ); - P( D, E, A, B, C, R(22) ); - P( C, D, E, A, B, R(23) ); - P( B, C, D, E, A, R(24) ); - P( A, B, C, D, E, R(25) ); - P( E, A, B, C, D, R(26) ); - P( D, E, A, B, C, R(27) ); - P( C, D, E, A, B, R(28) ); - P( B, C, D, E, A, R(29) ); - P( A, B, C, D, E, R(30) ); - P( E, A, B, C, D, R(31) ); - P( D, E, A, B, C, R(32) ); - P( C, D, E, A, B, R(33) ); - P( B, C, D, E, A, R(34) ); - P( A, B, C, D, E, R(35) ); - P( E, A, B, C, D, R(36) ); - P( D, E, A, B, C, R(37) ); - P( C, D, E, A, B, R(38) ); - P( B, C, D, E, A, R(39) ); - -#undef K -#undef F - -#define F(x,y,z) ((x & y) | (z & (x | y))) -#define K 0x8F1BBCDC - - P( A, B, C, D, E, R(40) ); - P( E, A, B, C, D, R(41) ); - P( D, E, A, B, C, R(42) ); - P( C, D, E, A, B, R(43) ); - P( B, C, D, E, A, R(44) ); - P( A, B, C, D, E, R(45) ); - P( E, A, B, C, D, R(46) ); - P( D, E, A, B, C, R(47) ); - P( C, D, E, A, B, R(48) ); - P( B, C, D, E, A, R(49) ); - P( A, B, C, D, E, R(50) ); - P( E, A, B, C, D, R(51) ); - P( D, E, A, B, C, R(52) ); - P( C, D, E, A, B, R(53) ); - P( B, C, D, E, A, R(54) ); - P( A, B, C, D, E, R(55) ); - P( E, A, B, C, D, R(56) ); - P( D, E, A, B, C, R(57) ); - P( C, D, E, A, B, R(58) ); - P( B, C, D, E, A, R(59) ); - -#undef K -#undef F - -#define F(x,y,z) (x ^ y ^ z) -#define K 0xCA62C1D6 - - P( A, B, C, D, E, R(60) ); - P( E, A, B, C, D, R(61) ); - P( D, E, A, B, C, R(62) ); - P( C, D, E, A, B, R(63) ); - P( B, C, D, E, A, R(64) ); - P( A, B, C, D, E, R(65) ); - P( E, A, B, C, D, R(66) ); - P( D, E, A, B, C, R(67) ); - P( C, D, E, A, B, R(68) ); - P( B, C, D, E, A, R(69) ); - P( A, B, C, D, E, R(70) ); - P( E, A, B, C, D, R(71) ); - P( D, E, A, B, C, R(72) ); - P( C, D, E, A, B, R(73) ); - P( B, C, D, E, A, R(74) ); - P( A, B, C, D, E, R(75) ); - P( E, A, B, C, D, R(76) ); - P( D, E, A, B, C, R(77) ); - P( C, D, E, A, B, R(78) ); - P( B, C, D, E, A, R(79) ); - -#undef K -#undef F - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; - ctx->state[4] += E; -} -#endif /* !MBEDTLS_SHA1_PROCESS_ALT */ - -/* - * SHA-1 process buffer - */ -void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ) -{ - size_t fill; - uint32_t left; - - if( ilen == 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += (uint32_t) ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (uint32_t) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_sha1_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - mbedtls_sha1_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - memcpy( (void *) (ctx->buffer + left), input, ilen ); -} - -static const unsigned char sha1_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * SHA-1 final digest - */ -void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ) -{ - uint32_t last, padn; - uint32_t high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_UINT32_BE( high, msglen, 0 ); - PUT_UINT32_BE( low, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - mbedtls_sha1_update( ctx, sha1_padding, padn ); - mbedtls_sha1_update( ctx, msglen, 8 ); - - PUT_UINT32_BE( ctx->state[0], output, 0 ); - PUT_UINT32_BE( ctx->state[1], output, 4 ); - PUT_UINT32_BE( ctx->state[2], output, 8 ); - PUT_UINT32_BE( ctx->state[3], output, 12 ); - PUT_UINT32_BE( ctx->state[4], output, 16 ); -} - -#endif /* !MBEDTLS_SHA1_ALT */ - -/* - * output = SHA-1( input buffer ) - */ -void mbedtls_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) -{ - mbedtls_sha1_context ctx; - - mbedtls_sha1_init( &ctx ); - mbedtls_sha1_starts( &ctx ); - mbedtls_sha1_update( &ctx, input, ilen ); - mbedtls_sha1_finish( &ctx, output ); - mbedtls_sha1_free( &ctx ); -} - -#if defined(MBEDTLS_SELF_TEST) -/* - * FIPS-180-1 test vectors - */ -static const unsigned char sha1_test_buf[3][57] = -{ - { "abc" }, - { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, - { "" } -}; - -static const int sha1_test_buflen[3] = -{ - 3, 56, 1000 -}; - -static const unsigned char sha1_test_sum[3][20] = -{ - { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, - 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, - { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, - 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, - { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, - 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } -}; - -/* - * Checkup routine - */ -int mbedtls_sha1_self_test( int verbose ) -{ - int i, j, buflen, ret = 0; - unsigned char buf[1024]; - unsigned char sha1sum[20]; - mbedtls_sha1_context ctx; - - mbedtls_sha1_init( &ctx ); - - /* - * SHA-1 - */ - for( i = 0; i < 3; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " SHA-1 test #%d: ", i + 1 ); - - mbedtls_sha1_starts( &ctx ); - - if( i == 2 ) - { - memset( buf, 'a', buflen = 1000 ); - - for( j = 0; j < 1000; j++ ) - mbedtls_sha1_update( &ctx, buf, buflen ); - } - else - mbedtls_sha1_update( &ctx, sha1_test_buf[i], - sha1_test_buflen[i] ); - - mbedtls_sha1_finish( &ctx, sha1sum ); - - if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -exit: - mbedtls_sha1_free( &ctx ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_SHA1_C */ diff --git a/components/mbedtls/library/sha256.c b/components/mbedtls/library/sha256.c deleted file mode 100644 index ad25d38333..0000000000 --- a/components/mbedtls/library/sha256.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * FIPS-180-2 compliant SHA-256 implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The SHA-256 Secure Hash Standard was published by NIST in 2002. - * - * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_SHA256_C) - -#include "mbedtls/sha256.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_printf printf -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_SHA256_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT32_BE -#define GET_UINT32_BE(n,b,i) \ -do { \ - (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ - | ( (uint32_t) (b)[(i) + 1] << 16 ) \ - | ( (uint32_t) (b)[(i) + 2] << 8 ) \ - | ( (uint32_t) (b)[(i) + 3] ); \ -} while( 0 ) -#endif - -#ifndef PUT_UINT32_BE -#define PUT_UINT32_BE(n,b,i) \ -do { \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} while( 0 ) -#endif - -void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); -} - -void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); -} - -void mbedtls_sha256_clone( mbedtls_sha256_context *dst, - const mbedtls_sha256_context *src ) -{ - *dst = *src; -} - -/* - * SHA-256 context setup - */ -void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - if( is224 == 0 ) - { - /* SHA-256 */ - ctx->state[0] = 0x6A09E667; - ctx->state[1] = 0xBB67AE85; - ctx->state[2] = 0x3C6EF372; - ctx->state[3] = 0xA54FF53A; - ctx->state[4] = 0x510E527F; - ctx->state[5] = 0x9B05688C; - ctx->state[6] = 0x1F83D9AB; - ctx->state[7] = 0x5BE0CD19; - } - else - { - /* SHA-224 */ - ctx->state[0] = 0xC1059ED8; - ctx->state[1] = 0x367CD507; - ctx->state[2] = 0x3070DD17; - ctx->state[3] = 0xF70E5939; - ctx->state[4] = 0xFFC00B31; - ctx->state[5] = 0x68581511; - ctx->state[6] = 0x64F98FA7; - ctx->state[7] = 0xBEFA4FA4; - } - - ctx->is224 = is224; -} - -#if !defined(MBEDTLS_SHA256_PROCESS_ALT) -static const uint32_t K[] = -{ - 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, - 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, - 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, - 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, - 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, - 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, - 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, - 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, - 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, - 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, - 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, - 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, - 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, - 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, - 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, - 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, -}; - -#define SHR(x,n) ((x & 0xFFFFFFFF) >> n) -#define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) - -#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) -#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) - -#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) -#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) - -#define F0(x,y,z) ((x & y) | (z & (x | y))) -#define F1(x,y,z) (z ^ (x & (y ^ z))) - -#define R(t) \ -( \ - W[t] = S1(W[t - 2]) + W[t - 7] + \ - S0(W[t - 15]) + W[t - 16] \ -) - -#define P(a,b,c,d,e,f,g,h,x,K) \ -{ \ - temp1 = h + S3(e) + F1(e,f,g) + K + x; \ - temp2 = S2(a) + F0(a,b,c); \ - d += temp1; h = temp1 + temp2; \ -} - -void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) -{ - uint32_t temp1, temp2, W[64]; - uint32_t A[8]; - unsigned int i; - - for( i = 0; i < 8; i++ ) - A[i] = ctx->state[i]; - -#if defined(MBEDTLS_SHA256_SMALLER) - for( i = 0; i < 64; i++ ) - { - if( i < 16 ) - GET_UINT32_BE( W[i], data, 4 * i ); - else - R( i ); - - P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); - - temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3]; - A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1; - } -#else /* MBEDTLS_SHA256_SMALLER */ - for( i = 0; i < 16; i++ ) - GET_UINT32_BE( W[i], data, 4 * i ); - - for( i = 0; i < 16; i += 8 ) - { - P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] ); - P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] ); - P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] ); - P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] ); - P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] ); - P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] ); - P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] ); - P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] ); - } - - for( i = 16; i < 64; i += 8 ) - { - P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] ); - P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] ); - P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] ); - P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] ); - P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] ); - P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] ); - P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] ); - P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] ); - } -#endif /* MBEDTLS_SHA256_SMALLER */ - - for( i = 0; i < 8; i++ ) - ctx->state[i] += A[i]; -} -#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ - -/* - * SHA-256 process buffer - */ -void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, - size_t ilen ) -{ - size_t fill; - uint32_t left; - - if( ilen == 0 ) - return; - - left = ctx->total[0] & 0x3F; - fill = 64 - left; - - ctx->total[0] += (uint32_t) ilen; - ctx->total[0] &= 0xFFFFFFFF; - - if( ctx->total[0] < (uint32_t) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_sha256_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - mbedtls_sha256_process( ctx, input ); - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - memcpy( (void *) (ctx->buffer + left), input, ilen ); -} - -static const unsigned char sha256_padding[64] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * SHA-256 final digest - */ -void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ) -{ - uint32_t last, padn; - uint32_t high, low; - unsigned char msglen[8]; - - high = ( ctx->total[0] >> 29 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_UINT32_BE( high, msglen, 0 ); - PUT_UINT32_BE( low, msglen, 4 ); - - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - mbedtls_sha256_update( ctx, sha256_padding, padn ); - mbedtls_sha256_update( ctx, msglen, 8 ); - - PUT_UINT32_BE( ctx->state[0], output, 0 ); - PUT_UINT32_BE( ctx->state[1], output, 4 ); - PUT_UINT32_BE( ctx->state[2], output, 8 ); - PUT_UINT32_BE( ctx->state[3], output, 12 ); - PUT_UINT32_BE( ctx->state[4], output, 16 ); - PUT_UINT32_BE( ctx->state[5], output, 20 ); - PUT_UINT32_BE( ctx->state[6], output, 24 ); - - if( ctx->is224 == 0 ) - PUT_UINT32_BE( ctx->state[7], output, 28 ); -} - -#endif /* !MBEDTLS_SHA256_ALT */ - -/* - * output = SHA-256( input buffer ) - */ -void mbedtls_sha256( const unsigned char *input, size_t ilen, - unsigned char output[32], int is224 ) -{ - mbedtls_sha256_context ctx; - - mbedtls_sha256_init( &ctx ); - mbedtls_sha256_starts( &ctx, is224 ); - mbedtls_sha256_update( &ctx, input, ilen ); - mbedtls_sha256_finish( &ctx, output ); - mbedtls_sha256_free( &ctx ); -} - -#if defined(MBEDTLS_SELF_TEST) -/* - * FIPS-180-2 test vectors - */ -static const unsigned char sha256_test_buf[3][57] = -{ - { "abc" }, - { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, - { "" } -}; - -static const int sha256_test_buflen[3] = -{ - 3, 56, 1000 -}; - -static const unsigned char sha256_test_sum[6][32] = -{ - /* - * SHA-224 test vectors - */ - { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, - 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, - 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, - 0xE3, 0x6C, 0x9D, 0xA7 }, - { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, - 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, - 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, - 0x52, 0x52, 0x25, 0x25 }, - { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, - 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, - 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, - 0x4E, 0xE7, 0xAD, 0x67 }, - - /* - * SHA-256 test vectors - */ - { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, - 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, - 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, - 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, - { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, - 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, - 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, - 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, - { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, - 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, - 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, - 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } -}; - -/* - * Checkup routine - */ -int mbedtls_sha256_self_test( int verbose ) -{ - int i, j, k, buflen, ret = 0; - unsigned char *buf; - unsigned char sha256sum[32]; - mbedtls_sha256_context ctx; - - buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); - if( NULL == buf ) - { - if( verbose != 0 ) - mbedtls_printf( "Buffer allocation failed\n" ); - - return( 1 ); - } - - mbedtls_sha256_init( &ctx ); - - for( i = 0; i < 6; i++ ) - { - j = i % 3; - k = i < 3; - - if( verbose != 0 ) - mbedtls_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); - - mbedtls_sha256_starts( &ctx, k ); - - if( j == 2 ) - { - memset( buf, 'a', buflen = 1000 ); - - for( j = 0; j < 1000; j++ ) - mbedtls_sha256_update( &ctx, buf, buflen ); - } - else - mbedtls_sha256_update( &ctx, sha256_test_buf[j], - sha256_test_buflen[j] ); - - mbedtls_sha256_finish( &ctx, sha256sum ); - - if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -exit: - mbedtls_sha256_free( &ctx ); - mbedtls_free( buf ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_SHA256_C */ diff --git a/components/mbedtls/library/sha512.c b/components/mbedtls/library/sha512.c deleted file mode 100644 index 724522ac68..0000000000 --- a/components/mbedtls/library/sha512.c +++ /dev/null @@ -1,514 +0,0 @@ -/* - * FIPS-180-2 compliant SHA-384/512 implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The SHA-512 Secure Hash Standard was published by NIST in 2002. - * - * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_SHA512_C) - -#include "mbedtls/sha512.h" - -#if defined(_MSC_VER) || defined(__WATCOMC__) - #define UL64(x) x##ui64 -#else - #define UL64(x) x##ULL -#endif - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_printf printf -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_SHA512_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * 64-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT64_BE -#define GET_UINT64_BE(n,b,i) \ -{ \ - (n) = ( (uint64_t) (b)[(i) ] << 56 ) \ - | ( (uint64_t) (b)[(i) + 1] << 48 ) \ - | ( (uint64_t) (b)[(i) + 2] << 40 ) \ - | ( (uint64_t) (b)[(i) + 3] << 32 ) \ - | ( (uint64_t) (b)[(i) + 4] << 24 ) \ - | ( (uint64_t) (b)[(i) + 5] << 16 ) \ - | ( (uint64_t) (b)[(i) + 6] << 8 ) \ - | ( (uint64_t) (b)[(i) + 7] ); \ -} -#endif /* GET_UINT64_BE */ - -#ifndef PUT_UINT64_BE -#define PUT_UINT64_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ - (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 7] = (unsigned char) ( (n) ); \ -} -#endif /* PUT_UINT64_BE */ - -void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); -} - -void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); -} - -void mbedtls_sha512_clone( mbedtls_sha512_context *dst, - const mbedtls_sha512_context *src ) -{ - *dst = *src; -} - -/* - * SHA-512 context setup - */ -void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ) -{ - ctx->total[0] = 0; - ctx->total[1] = 0; - - if( is384 == 0 ) - { - /* SHA-512 */ - ctx->state[0] = UL64(0x6A09E667F3BCC908); - ctx->state[1] = UL64(0xBB67AE8584CAA73B); - ctx->state[2] = UL64(0x3C6EF372FE94F82B); - ctx->state[3] = UL64(0xA54FF53A5F1D36F1); - ctx->state[4] = UL64(0x510E527FADE682D1); - ctx->state[5] = UL64(0x9B05688C2B3E6C1F); - ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); - ctx->state[7] = UL64(0x5BE0CD19137E2179); - } - else - { - /* SHA-384 */ - ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); - ctx->state[1] = UL64(0x629A292A367CD507); - ctx->state[2] = UL64(0x9159015A3070DD17); - ctx->state[3] = UL64(0x152FECD8F70E5939); - ctx->state[4] = UL64(0x67332667FFC00B31); - ctx->state[5] = UL64(0x8EB44A8768581511); - ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); - ctx->state[7] = UL64(0x47B5481DBEFA4FA4); - } - - ctx->is384 = is384; -} - -#if !defined(MBEDTLS_SHA512_PROCESS_ALT) - -/* - * Round constants - */ -static const uint64_t K[80] = -{ - UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), - UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), - UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), - UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), - UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), - UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), - UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), - UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), - UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), - UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), - UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), - UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), - UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), - UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), - UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), - UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), - UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), - UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), - UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), - UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), - UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), - UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), - UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), - UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), - UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), - UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), - UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), - UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), - UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), - UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), - UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), - UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), - UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), - UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), - UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), - UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), - UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), - UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), - UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), - UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) -}; - -void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ) -{ - int i; - uint64_t temp1, temp2, W[80]; - uint64_t A, B, C, D, E, F, G, H; - -#define SHR(x,n) (x >> n) -#define ROTR(x,n) (SHR(x,n) | (x << (64 - n))) - -#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) -#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) - -#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) -#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) - -#define F0(x,y,z) ((x & y) | (z & (x | y))) -#define F1(x,y,z) (z ^ (x & (y ^ z))) - -#define P(a,b,c,d,e,f,g,h,x,K) \ -{ \ - temp1 = h + S3(e) + F1(e,f,g) + K + x; \ - temp2 = S2(a) + F0(a,b,c); \ - d += temp1; h = temp1 + temp2; \ -} - - for( i = 0; i < 16; i++ ) - { - GET_UINT64_BE( W[i], data, i << 3 ); - } - - for( ; i < 80; i++ ) - { - W[i] = S1(W[i - 2]) + W[i - 7] + - S0(W[i - 15]) + W[i - 16]; - } - - A = ctx->state[0]; - B = ctx->state[1]; - C = ctx->state[2]; - D = ctx->state[3]; - E = ctx->state[4]; - F = ctx->state[5]; - G = ctx->state[6]; - H = ctx->state[7]; - i = 0; - - do - { - P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++; - P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++; - P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++; - P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++; - P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++; - P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++; - P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++; - P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++; - } - while( i < 80 ); - - ctx->state[0] += A; - ctx->state[1] += B; - ctx->state[2] += C; - ctx->state[3] += D; - ctx->state[4] += E; - ctx->state[5] += F; - ctx->state[6] += G; - ctx->state[7] += H; -} -#endif /* !MBEDTLS_SHA512_PROCESS_ALT */ - -/* - * SHA-512 process buffer - */ -void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input, - size_t ilen ) -{ - size_t fill; - unsigned int left; - - if( ilen == 0 ) - return; - - left = (unsigned int) (ctx->total[0] & 0x7F); - fill = 128 - left; - - ctx->total[0] += (uint64_t) ilen; - - if( ctx->total[0] < (uint64_t) ilen ) - ctx->total[1]++; - - if( left && ilen >= fill ) - { - memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_sha512_process( ctx, ctx->buffer ); - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 128 ) - { - mbedtls_sha512_process( ctx, input ); - input += 128; - ilen -= 128; - } - - if( ilen > 0 ) - memcpy( (void *) (ctx->buffer + left), input, ilen ); -} - -static const unsigned char sha512_padding[128] = -{ - 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* - * SHA-512 final digest - */ -void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] ) -{ - size_t last, padn; - uint64_t high, low; - unsigned char msglen[16]; - - high = ( ctx->total[0] >> 61 ) - | ( ctx->total[1] << 3 ); - low = ( ctx->total[0] << 3 ); - - PUT_UINT64_BE( high, msglen, 0 ); - PUT_UINT64_BE( low, msglen, 8 ); - - last = (size_t)( ctx->total[0] & 0x7F ); - padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last ); - - mbedtls_sha512_update( ctx, sha512_padding, padn ); - mbedtls_sha512_update( ctx, msglen, 16 ); - - PUT_UINT64_BE( ctx->state[0], output, 0 ); - PUT_UINT64_BE( ctx->state[1], output, 8 ); - PUT_UINT64_BE( ctx->state[2], output, 16 ); - PUT_UINT64_BE( ctx->state[3], output, 24 ); - PUT_UINT64_BE( ctx->state[4], output, 32 ); - PUT_UINT64_BE( ctx->state[5], output, 40 ); - - if( ctx->is384 == 0 ) - { - PUT_UINT64_BE( ctx->state[6], output, 48 ); - PUT_UINT64_BE( ctx->state[7], output, 56 ); - } -} - -#endif /* !MBEDTLS_SHA512_ALT */ - -/* - * output = SHA-512( input buffer ) - */ -void mbedtls_sha512( const unsigned char *input, size_t ilen, - unsigned char output[64], int is384 ) -{ - mbedtls_sha512_context ctx; - - mbedtls_sha512_init( &ctx ); - mbedtls_sha512_starts( &ctx, is384 ); - mbedtls_sha512_update( &ctx, input, ilen ); - mbedtls_sha512_finish( &ctx, output ); - mbedtls_sha512_free( &ctx ); -} - -#if defined(MBEDTLS_SELF_TEST) - -/* - * FIPS-180-2 test vectors - */ -static const unsigned char sha512_test_buf[3][113] = -{ - { "abc" }, - { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" - "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, - { "" } -}; - -static const int sha512_test_buflen[3] = -{ - 3, 112, 1000 -}; - -static const unsigned char sha512_test_sum[6][64] = -{ - /* - * SHA-384 test vectors - */ - { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, - 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, - 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, - 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED, - 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, - 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 }, - { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, - 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, - 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, - 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12, - 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, - 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 }, - { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB, - 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C, - 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, - 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, - 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, - 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }, - - /* - * SHA-512 test vectors - */ - { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, - 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, - 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, - 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, - 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, - 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, - 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, - 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F }, - { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, - 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, - 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, - 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, - 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, - 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, - 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, - 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 }, - { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64, - 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63, - 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28, - 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB, - 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A, - 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B, - 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E, - 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } -}; - -/* - * Checkup routine - */ -int mbedtls_sha512_self_test( int verbose ) -{ - int i, j, k, buflen, ret = 0; - unsigned char *buf; - unsigned char sha512sum[64]; - mbedtls_sha512_context ctx; - - buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); - if( NULL == buf ) - { - if( verbose != 0 ) - mbedtls_printf( "Buffer allocation failed\n" ); - - return( 1 ); - } - - mbedtls_sha512_init( &ctx ); - - for( i = 0; i < 6; i++ ) - { - j = i % 3; - k = i < 3; - - if( verbose != 0 ) - mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 ); - - mbedtls_sha512_starts( &ctx, k ); - - if( j == 2 ) - { - memset( buf, 'a', buflen = 1000 ); - - for( j = 0; j < 1000; j++ ) - mbedtls_sha512_update( &ctx, buf, buflen ); - } - else - mbedtls_sha512_update( &ctx, sha512_test_buf[j], - sha512_test_buflen[j] ); - - mbedtls_sha512_finish( &ctx, sha512sum ); - - if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -exit: - mbedtls_sha512_free( &ctx ); - mbedtls_free( buf ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_SHA512_C */ diff --git a/components/mbedtls/library/ssl_cache.c b/components/mbedtls/library/ssl_cache.c deleted file mode 100644 index c771d7fe2a..0000000000 --- a/components/mbedtls/library/ssl_cache.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * SSL session cache implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * These session callbacks use a simple chained list - * to store and retrieve the session information. - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_SSL_CACHE_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include "mbedtls/ssl_cache.h" - -#include - -void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ) -{ - memset( cache, 0, sizeof( mbedtls_ssl_cache_context ) ); - - cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT; - cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES; - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &cache->mutex ); -#endif -} - -int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session ) -{ - int ret = 1; -#if defined(MBEDTLS_HAVE_TIME) - mbedtls_time_t t = mbedtls_time( NULL ); -#endif - mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; - mbedtls_ssl_cache_entry *cur, *entry; - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_lock( &cache->mutex ) != 0 ) - return( 1 ); -#endif - - cur = cache->chain; - entry = NULL; - - while( cur != NULL ) - { - entry = cur; - cur = cur->next; - -#if defined(MBEDTLS_HAVE_TIME) - if( cache->timeout != 0 && - (int) ( t - entry->timestamp ) > cache->timeout ) - continue; -#endif - - if( session->ciphersuite != entry->session.ciphersuite || - session->compression != entry->session.compression || - session->id_len != entry->session.id_len ) - continue; - - if( memcmp( session->id, entry->session.id, - entry->session.id_len ) != 0 ) - continue; - - memcpy( session->master, entry->session.master, 48 ); - - session->verify_result = entry->session.verify_result; - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - /* - * Restore peer certificate (without rest of the original chain) - */ - if( entry->peer_cert.p != NULL ) - { - if( ( session->peer_cert = mbedtls_calloc( 1, - sizeof(mbedtls_x509_crt) ) ) == NULL ) - { - ret = 1; - goto exit; - } - - mbedtls_x509_crt_init( session->peer_cert ); - if( mbedtls_x509_crt_parse( session->peer_cert, entry->peer_cert.p, - entry->peer_cert.len ) != 0 ) - { - mbedtls_free( session->peer_cert ); - session->peer_cert = NULL; - ret = 1; - goto exit; - } - } -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - ret = 0; - goto exit; - } - -exit: -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) - ret = 1; -#endif - - return( ret ); -} - -int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session ) -{ - int ret = 1; -#if defined(MBEDTLS_HAVE_TIME) - mbedtls_time_t t = mbedtls_time( NULL ), oldest = 0; - mbedtls_ssl_cache_entry *old = NULL; -#endif - mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; - mbedtls_ssl_cache_entry *cur, *prv; - int count = 0; - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &cache->mutex ) ) != 0 ) - return( ret ); -#endif - - cur = cache->chain; - prv = NULL; - - while( cur != NULL ) - { - count++; - -#if defined(MBEDTLS_HAVE_TIME) - if( cache->timeout != 0 && - (int) ( t - cur->timestamp ) > cache->timeout ) - { - cur->timestamp = t; - break; /* expired, reuse this slot, update timestamp */ - } -#endif - - if( memcmp( session->id, cur->session.id, cur->session.id_len ) == 0 ) - break; /* client reconnected, keep timestamp for session id */ - -#if defined(MBEDTLS_HAVE_TIME) - if( oldest == 0 || cur->timestamp < oldest ) - { - oldest = cur->timestamp; - old = cur; - } -#endif - - prv = cur; - cur = cur->next; - } - - if( cur == NULL ) - { -#if defined(MBEDTLS_HAVE_TIME) - /* - * Reuse oldest entry if max_entries reached - */ - if( count >= cache->max_entries ) - { - if( old == NULL ) - { - ret = 1; - goto exit; - } - - cur = old; - } -#else /* MBEDTLS_HAVE_TIME */ - /* - * Reuse first entry in chain if max_entries reached, - * but move to last place - */ - if( count >= cache->max_entries ) - { - if( cache->chain == NULL ) - { - ret = 1; - goto exit; - } - - cur = cache->chain; - cache->chain = cur->next; - cur->next = NULL; - prv->next = cur; - } -#endif /* MBEDTLS_HAVE_TIME */ - else - { - /* - * max_entries not reached, create new entry - */ - cur = mbedtls_calloc( 1, sizeof(mbedtls_ssl_cache_entry) ); - if( cur == NULL ) - { - ret = 1; - goto exit; - } - - if( prv == NULL ) - cache->chain = cur; - else - prv->next = cur; - } - -#if defined(MBEDTLS_HAVE_TIME) - cur->timestamp = t; -#endif - } - - memcpy( &cur->session, session, sizeof( mbedtls_ssl_session ) ); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - /* - * If we're reusing an entry, free its certificate first - */ - if( cur->peer_cert.p != NULL ) - { - mbedtls_free( cur->peer_cert.p ); - memset( &cur->peer_cert, 0, sizeof(mbedtls_x509_buf) ); - } - - /* - * Store peer certificate - */ - if( session->peer_cert != NULL ) - { - cur->peer_cert.p = mbedtls_calloc( 1, session->peer_cert->raw.len ); - if( cur->peer_cert.p == NULL ) - { - ret = 1; - goto exit; - } - - memcpy( cur->peer_cert.p, session->peer_cert->raw.p, - session->peer_cert->raw.len ); - cur->peer_cert.len = session->peer_cert->raw.len; - - cur->session.peer_cert = NULL; - } -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - ret = 0; - -exit: -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) - ret = 1; -#endif - - return( ret ); -} - -#if defined(MBEDTLS_HAVE_TIME) -void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ) -{ - if( timeout < 0 ) timeout = 0; - - cache->timeout = timeout; -} -#endif /* MBEDTLS_HAVE_TIME */ - -void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ) -{ - if( max < 0 ) max = 0; - - cache->max_entries = max; -} - -void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ) -{ - mbedtls_ssl_cache_entry *cur, *prv; - - cur = cache->chain; - - while( cur != NULL ) - { - prv = cur; - cur = cur->next; - - mbedtls_ssl_session_free( &prv->session ); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - mbedtls_free( prv->peer_cert.p ); -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - mbedtls_free( prv ); - } - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &cache->mutex ); -#endif -} - -#endif /* MBEDTLS_SSL_CACHE_C */ diff --git a/components/mbedtls/library/ssl_ciphersuites.c b/components/mbedtls/library/ssl_ciphersuites.c deleted file mode 100644 index 95e6163ccc..0000000000 --- a/components/mbedtls/library/ssl_ciphersuites.c +++ /dev/null @@ -1,1875 +0,0 @@ -/** - * \file ssl_ciphersuites.c - * - * \brief SSL ciphersuites for mbed TLS - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_SSL_TLS_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#endif - -#include "mbedtls/ssl_ciphersuites.h" -#include "mbedtls/ssl.h" - -#include - -/* - * Ordered from most preferred to least preferred in terms of security. - * - * Current rule (except rc4, weak and null which come last): - * 1. By key exchange: - * Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK - * 2. By key length and cipher: - * AES-256 > Camellia-256 > AES-128 > Camellia-128 > 3DES - * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8 - * 4. By hash function used when relevant - * 5. By key exchange/auth again: EC > non-EC - */ -static const int ciphersuite_preference[] = -{ -#if defined(MBEDTLS_SSL_CIPHERSUITES) - MBEDTLS_SSL_CIPHERSUITES, -#else - /* All AES-256 ephemeral suites */ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, - MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, - MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, - - /* All CAMELLIA-256 ephemeral suites */ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, - MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, - MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, - MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, - - /* All AES-128 ephemeral suites */ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, - MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, - MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, - - /* All CAMELLIA-128 ephemeral suites */ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, - MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, - MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, - MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, - - /* All remaining >= 128-bit ephemeral suites */ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, - - /* The PSK ephemeral suites */ - MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, - MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, - MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, - MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, - - MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, - MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, - MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, - MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, - - MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, - - /* The ECJPAKE suite */ - MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, - - /* All AES-256 suites */ - MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_RSA_WITH_AES_256_CCM, - MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, - MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, - - /* All CAMELLIA-256 suites */ - MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, - MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, - MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, - MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, - - /* All AES-128 suites */ - MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_RSA_WITH_AES_128_CCM, - MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, - - /* All CAMELLIA-128 suites */ - MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, - MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, - MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, - MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, - - /* All remaining >= 128-bit suites */ - MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, - MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, - - /* The RSA PSK suites */ - MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, - - MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, - - MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, - - /* The PSK suites */ - MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, - MBEDTLS_TLS_PSK_WITH_AES_256_CCM, - MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, - MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, - MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, - MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, - MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, - - MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_PSK_WITH_AES_128_CCM, - MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, - MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, - MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, - MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, - MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, - - MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, - - /* RC4 suites */ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, - MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, - MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, - MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, - MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, - MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, - MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, - MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, - MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, - - /* Weak suites */ - MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, - MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, - - /* NULL suites */ - MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, - MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, - MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, - MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, - MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, - MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, - MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, - MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, - - MBEDTLS_TLS_RSA_WITH_NULL_SHA256, - MBEDTLS_TLS_RSA_WITH_NULL_SHA, - MBEDTLS_TLS_RSA_WITH_NULL_MD5, - MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, - MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, - MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, - MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, - MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, - MBEDTLS_TLS_PSK_WITH_NULL_SHA384, - MBEDTLS_TLS_PSK_WITH_NULL_SHA256, - MBEDTLS_TLS_PSK_WITH_NULL_SHA, - -#endif /* MBEDTLS_SSL_CIPHERSUITES */ - 0 -}; - -static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = -{ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_SHA1_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA512_C */ -#if defined(MBEDTLS_CCM_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS-ECDHE-ECDSA-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ - -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_SHA1_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-RSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS-ECDHE-RSA-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ - -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_CCM_C) - { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, - { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-RSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C && MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA1_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_CCM_C) - { MBEDTLS_TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, - { MBEDTLS_TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_MD5_C) - { MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, "TLS-RSA-WITH-RC4-128-MD5", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, "TLS-RSA-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif -#endif /* MBEDTLS_ARC4_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_SHA1_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-RSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA, "TLS-ECDH-RSA-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ - -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ -#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_SHA1_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_GCM_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS-ECDH-ECDSA-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "TLS-ECDH-ECDSA-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ - -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ -#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_CCM_C) - { MBEDTLS_TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, - { MBEDTLS_TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-PSK-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, "TLS-PSK-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_CCM_C) - { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8", - MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, - { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-DHE-PSK-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, "TLS-DHE-PSK-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) -#if defined(MBEDTLS_AES_C) - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-ECDHE-PSK-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA, "TLS-ECDHE-PSK-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256", - MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384", - MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA", - MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, - - { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA", - MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_AES_C */ - -#if defined(MBEDTLS_CAMELLIA_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - -#if defined(MBEDTLS_GCM_C) -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256", - MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384", - MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_GCM_C */ -#endif /* MBEDTLS_CAMELLIA_C */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, "TLS-RSA-PSK-WITH-3DES-EDE-CBC-SHA", - MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - 0 }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ - -#if defined(MBEDTLS_ARC4_C) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, "TLS-RSA-PSK-WITH-RC4-128-SHA", - MBEDTLS_CIPHER_ARC4_128, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_NODTLS }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_ARC4_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_CCM_C) - { MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, "TLS-ECJPAKE-WITH-AES-128-CCM-8", - MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECJPAKE, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_SHORT_TAG }, -#endif /* MBEDTLS_CCM_C */ -#endif /* MBEDTLS_AES_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) -#if defined(MBEDTLS_MD5_C) - { MBEDTLS_TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif - -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif - -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ - -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif -#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ - -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ - -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ - -#if defined(MBEDTLS_SHA256_C) - { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif - -#if defined(MBEDTLS_SHA512_C) - { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384", - MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ -#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ - -#if defined(MBEDTLS_DES_C) -#if defined(MBEDTLS_CIPHER_MODE_CBC) -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA, "TLS-DHE-RSA-WITH-DES-CBC-SHA", - MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) -#if defined(MBEDTLS_SHA1_C) - { MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA, "TLS-RSA-WITH-DES-CBC-SHA", - MBEDTLS_CIPHER_DES_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0, - MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, - MBEDTLS_CIPHERSUITE_WEAK }, -#endif /* MBEDTLS_SHA1_C */ -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* MBEDTLS_DES_C */ -#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ - - { 0, "", - MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE, - 0, 0, 0, 0, 0 } -}; - -#if defined(MBEDTLS_SSL_CIPHERSUITES) -const int *mbedtls_ssl_list_ciphersuites( void ) -{ - return( ciphersuite_preference ); -} -#else -#define MAX_CIPHERSUITES sizeof( ciphersuite_definitions ) / \ - sizeof( ciphersuite_definitions[0] ) -static int supported_ciphersuites[MAX_CIPHERSUITES]; -static int supported_init = 0; - -const int *mbedtls_ssl_list_ciphersuites( void ) -{ - /* - * On initial call filter out all ciphersuites not supported by current - * build based on presence in the ciphersuite_definitions. - */ - if( supported_init == 0 ) - { - const int *p; - int *q; - - for( p = ciphersuite_preference, q = supported_ciphersuites; - *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1; - p++ ) - { -#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) - const mbedtls_ssl_ciphersuite_t *cs_info; - if( ( cs_info = mbedtls_ssl_ciphersuite_from_id( *p ) ) != NULL && - cs_info->cipher != MBEDTLS_CIPHER_ARC4_128 ) -#else - if( mbedtls_ssl_ciphersuite_from_id( *p ) != NULL ) -#endif - *(q++) = *p; - } - *q = 0; - - supported_init = 1; - } - - return( supported_ciphersuites ); -} -#endif /* MBEDTLS_SSL_CIPHERSUITES */ - -const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( - const char *ciphersuite_name ) -{ - const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; - - if( NULL == ciphersuite_name ) - return( NULL ); - - while( cur->id != 0 ) - { - if( 0 == strcmp( cur->name, ciphersuite_name ) ) - return( cur ); - - cur++; - } - - return( NULL ); -} - -const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite ) -{ - const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; - - while( cur->id != 0 ) - { - if( cur->id == ciphersuite ) - return( cur ); - - cur++; - } - - return( NULL ); -} - -const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ) -{ - const mbedtls_ssl_ciphersuite_t *cur; - - cur = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id ); - - if( cur == NULL ) - return( "unknown" ); - - return( cur->name ); -} - -int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ) -{ - const mbedtls_ssl_ciphersuite_t *cur; - - cur = mbedtls_ssl_ciphersuite_from_string( ciphersuite_name ); - - if( cur == NULL ) - return( 0 ); - - return( cur->id ); -} - -#if defined(MBEDTLS_PK_C) -mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ) -{ - switch( info->key_exchange ) - { - case MBEDTLS_KEY_EXCHANGE_RSA: - case MBEDTLS_KEY_EXCHANGE_DHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: - case MBEDTLS_KEY_EXCHANGE_RSA_PSK: - return( MBEDTLS_PK_RSA ); - - case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: - return( MBEDTLS_PK_ECDSA ); - - case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: - return( MBEDTLS_PK_ECKEY ); - - default: - return( MBEDTLS_PK_NONE ); - } -} - -mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ) -{ - switch( info->key_exchange ) - { - case MBEDTLS_KEY_EXCHANGE_RSA: - case MBEDTLS_KEY_EXCHANGE_DHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: - return( MBEDTLS_PK_RSA ); - - case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: - return( MBEDTLS_PK_ECDSA ); - - default: - return( MBEDTLS_PK_NONE ); - } -} - -#endif /* MBEDTLS_PK_C */ - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) -int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ) -{ - switch( info->key_exchange ) - { - case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: - case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: - return( 1 ); - - default: - return( 0 ); - } -} -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ) -{ - switch( info->key_exchange ) - { - case MBEDTLS_KEY_EXCHANGE_PSK: - case MBEDTLS_KEY_EXCHANGE_RSA_PSK: - case MBEDTLS_KEY_EXCHANGE_DHE_PSK: - case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: - return( 1 ); - - default: - return( 0 ); - } -} -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ - -#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/components/mbedtls/library/ssl_cli.c b/components/mbedtls/library/ssl_cli.c deleted file mode 100644 index a2b9f8cfe1..0000000000 --- a/components/mbedtls/library/ssl_cli.c +++ /dev/null @@ -1,3489 +0,0 @@ -/* - * SSLv3/TLSv1 client-side functions - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_SSL_CLI_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include "mbedtls/debug.h" -#include "mbedtls/ssl.h" -#include "mbedtls/ssl_internal.h" - -#include - -#include - -#if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" -#endif - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} -#endif - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) -static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - size_t hostname_len; - - *olen = 0; - - if( ssl->hostname == NULL ) - return; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding server name extension: %s", - ssl->hostname ) ); - - hostname_len = strlen( ssl->hostname ); - - if( end < p || (size_t)( end - p ) < hostname_len + 9 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - /* - * struct { - * NameType name_type; - * select (name_type) { - * case host_name: HostName; - * } name; - * } ServerName; - * - * enum { - * host_name(0), (255) - * } NameType; - * - * opaque HostName<1..2^16-1>; - * - * struct { - * ServerName server_name_list<1..2^16-1> - * } ServerNameList; - */ - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME ) & 0xFF ); - - *p++ = (unsigned char)( ( (hostname_len + 5) >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( (hostname_len + 5) ) & 0xFF ); - - *p++ = (unsigned char)( ( (hostname_len + 3) >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( (hostname_len + 3) ) & 0xFF ); - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) & 0xFF ); - *p++ = (unsigned char)( ( hostname_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( hostname_len ) & 0xFF ); - - memcpy( p, ssl->hostname, hostname_len ); - - *olen = hostname_len + 9; -} -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - -#if defined(MBEDTLS_SSL_RENEGOTIATION) -static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - - *olen = 0; - - if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - return; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding renegotiation extension" ) ); - - if( end < p || (size_t)( end - p ) < 5 + ssl->verify_data_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - /* - * Secure renegotiation - */ - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); - - *p++ = 0x00; - *p++ = ( ssl->verify_data_len + 1 ) & 0xFF; - *p++ = ssl->verify_data_len & 0xFF; - - memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); - - *olen = 5 + ssl->verify_data_len; -} -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - -/* - * Only if we handle at least one key exchange that needs signatures. - */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -static void ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - size_t sig_alg_len = 0; - const int *md; -#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) - unsigned char *sig_alg_list = buf + 6; -#endif - - *olen = 0; - - if( ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) - return; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding signature_algorithms extension" ) ); - - for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) - { -#if defined(MBEDTLS_ECDSA_C) - sig_alg_len += 2; -#endif -#if defined(MBEDTLS_RSA_C) - sig_alg_len += 2; -#endif - } - - if( end < p || (size_t)( end - p ) < sig_alg_len + 6 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - /* - * Prepare signature_algorithms extension (TLS 1.2) - */ - sig_alg_len = 0; - - for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) - { -#if defined(MBEDTLS_ECDSA_C) - sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); - sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA; -#endif -#if defined(MBEDTLS_RSA_C) - sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); - sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA; -#endif - } - - /* - * enum { - * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), - * sha512(6), (255) - * } HashAlgorithm; - * - * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } - * SignatureAlgorithm; - * - * struct { - * HashAlgorithm hash; - * SignatureAlgorithm signature; - * } SignatureAndHashAlgorithm; - * - * SignatureAndHashAlgorithm - * supported_signature_algorithms<2..2^16-2>; - */ - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SIG_ALG ) & 0xFF ); - - *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( ( sig_alg_len + 2 ) ) & 0xFF ); - - *p++ = (unsigned char)( ( sig_alg_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( sig_alg_len ) & 0xFF ); - - *olen = 6 + sig_alg_len; -} -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static void ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - unsigned char *elliptic_curve_list = p + 6; - size_t elliptic_curve_len = 0; - const mbedtls_ecp_curve_info *info; -#if defined(MBEDTLS_ECP_C) - const mbedtls_ecp_group_id *grp_id; -#else - ((void) ssl); -#endif - - *olen = 0; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_elliptic_curves extension" ) ); - -#if defined(MBEDTLS_ECP_C) - for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) -#else - for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) -#endif - { -#if defined(MBEDTLS_ECP_C) - info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); -#endif - if( info == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid curve in ssl configuration" ) ); - return; - } - - elliptic_curve_len += 2; - } - - if( end < p || (size_t)( end - p ) < 6 + elliptic_curve_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - elliptic_curve_len = 0; - -#if defined(MBEDTLS_ECP_C) - for( grp_id = ssl->conf->curve_list; *grp_id != MBEDTLS_ECP_DP_NONE; grp_id++ ) -#else - for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ ) -#endif - { -#if defined(MBEDTLS_ECP_C) - info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); -#endif - elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8; - elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF; - } - - if( elliptic_curve_len == 0 ) - return; - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES ) & 0xFF ); - - *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( ( elliptic_curve_len + 2 ) ) & 0xFF ); - - *p++ = (unsigned char)( ( ( elliptic_curve_len ) >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( ( elliptic_curve_len ) ) & 0xFF ); - - *olen = 6 + elliptic_curve_len; -} - -static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - - *olen = 0; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_point_formats extension" ) ); - - if( end < p || (size_t)( end - p ) < 6 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); - - *p++ = 0x00; - *p++ = 2; - - *p++ = 1; - *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; - - *olen = 6; -} -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || - MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - int ret; - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - size_t kkpp_len; - - *olen = 0; - - /* Skip costly extension if we can't use EC J-PAKE anyway */ - if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) - return; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding ecjpake_kkpp extension" ) ); - - if( end - p < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF ); - - /* - * We may need to send ClientHello multiple times for Hello verification. - * We don't want to compute fresh values every time (both for performance - * and consistency reasons), so cache the extension content. - */ - if( ssl->handshake->ecjpake_cache == NULL || - ssl->handshake->ecjpake_cache_len == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "generating new ecjpake parameters" ) ); - - ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, - p + 2, end - p - 2, &kkpp_len, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret ); - return; - } - - ssl->handshake->ecjpake_cache = mbedtls_calloc( 1, kkpp_len ); - if( ssl->handshake->ecjpake_cache == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "allocation failed" ) ); - return; - } - - memcpy( ssl->handshake->ecjpake_cache, p + 2, kkpp_len ); - ssl->handshake->ecjpake_cache_len = kkpp_len; - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "re-using cached ecjpake parameters" ) ); - - kkpp_len = ssl->handshake->ecjpake_cache_len; - - if( (size_t)( end - p - 2 ) < kkpp_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - memcpy( p + 2, ssl->handshake->ecjpake_cache, kkpp_len ); - } - - *p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( kkpp_len ) & 0xFF ); - - *olen = kkpp_len + 4; -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - - *olen = 0; - - if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) { - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding max_fragment_length extension" ) ); - - if( end < p || (size_t)( end - p ) < 5 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); - - *p++ = 0x00; - *p++ = 1; - - *p++ = ssl->conf->mfl_code; - - *olen = 5; -} -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - - *olen = 0; - - if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) - { - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding truncated_hmac extension" ) ); - - if( end < p || (size_t)( end - p ) < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); - - *p++ = 0x00; - *p++ = 0x00; - - *olen = 4; -} -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) -static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - - *olen = 0; - - if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || - ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding encrypt_then_mac " - "extension" ) ); - - if( end < p || (size_t)( end - p ) < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); - - *p++ = 0x00; - *p++ = 0x00; - - *olen = 4; -} -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) -static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - - *olen = 0; - - if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || - ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding extended_master_secret " - "extension" ) ); - - if( end < p || (size_t)( end - p ) < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); - - *p++ = 0x00; - *p++ = 0x00; - - *olen = 4; -} -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - size_t tlen = ssl->session_negotiate->ticket_len; - - *olen = 0; - - if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ) - { - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding session ticket extension" ) ); - - if( end < p || (size_t)( end - p ) < 4 + tlen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF ); - - *p++ = (unsigned char)( ( tlen >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( tlen ) & 0xFF ); - - *olen = 4; - - if( ssl->session_negotiate->ticket == NULL || tlen == 0 ) - { - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "sending session ticket of length %d", tlen ) ); - - memcpy( p, ssl->session_negotiate->ticket, tlen ); - - *olen += tlen; -} -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -#if defined(MBEDTLS_SSL_ALPN) -static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen ) -{ - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - size_t alpnlen = 0; - const char **cur; - - *olen = 0; - - if( ssl->conf->alpn_list == NULL ) - { - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) ); - - for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) - alpnlen += (unsigned char)( strlen( *cur ) & 0xFF ) + 1; - - if( end < p || (size_t)( end - p ) < 6 + alpnlen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF ); - - /* - * opaque ProtocolName<1..2^8-1>; - * - * struct { - * ProtocolName protocol_name_list<2..2^16-1> - * } ProtocolNameList; - */ - - /* Skip writing extension and list length for now */ - p += 4; - - for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) - { - *p = (unsigned char)( strlen( *cur ) & 0xFF ); - memcpy( p + 1, *cur, *p ); - p += 1 + *p; - } - - *olen = p - buf; - - /* List length = olen - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */ - buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF ); - buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF ); - - /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */ - buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); - buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); -} -#endif /* MBEDTLS_SSL_ALPN */ - -/* - * Generate random bytes for ClientHello - */ -static int ssl_generate_random( mbedtls_ssl_context *ssl ) -{ - int ret; - unsigned char *p = ssl->handshake->randbytes; -#if defined(MBEDTLS_HAVE_TIME) - mbedtls_time_t t; -#endif - - /* - * When responding to a verify request, MUST reuse random (RFC 6347 4.2.1) - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake->verify_cookie != NULL ) - { - return( 0 ); - } -#endif - -#if defined(MBEDTLS_HAVE_TIME) - t = mbedtls_time( NULL ); - *p++ = (unsigned char)( t >> 24 ); - *p++ = (unsigned char)( t >> 16 ); - *p++ = (unsigned char)( t >> 8 ); - *p++ = (unsigned char)( t ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %lu", t ) ); -#else - if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) - return( ret ); - - p += 4; -#endif /* MBEDTLS_HAVE_TIME */ - - if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) -{ - int ret; - size_t i, n, olen, ext_len = 0; - unsigned char *buf; - unsigned char *p, *q; - unsigned char offer_compress; - const int *ciphersuites; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); - - if( ssl->conf->f_rng == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); - return( MBEDTLS_ERR_SSL_NO_RNG ); - } - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) -#endif - { - ssl->major_ver = ssl->conf->min_major_ver; - ssl->minor_ver = ssl->conf->min_minor_ver; - } - - if( ssl->conf->max_major_ver == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "configured max major version is invalid, " - "consider using mbedtls_ssl_config_defaults()" ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - /* - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 5 highest version supported - * 6 . 9 current UNIX time - * 10 . 37 random bytes - */ - buf = ssl->out_msg; - p = buf + 4; - - mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver, - ssl->conf->transport, p ); - p += 2; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]", - buf[4], buf[5] ) ); - - if( ( ret = ssl_generate_random( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_generate_random", ret ); - return( ret ); - } - - memcpy( p, ssl->handshake->randbytes, 32 ); - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", p, 32 ); - p += 32; - - /* - * 38 . 38 session id length - * 39 . 39+n session id - * 39+n . 39+n DTLS only: cookie length (1 byte) - * 40+n . .. DTSL only: cookie - * .. . .. ciphersuitelist length (2 bytes) - * .. . .. ciphersuitelist - * .. . .. compression methods length (1 byte) - * .. . .. compression methods - * .. . .. extensions length (2 bytes) - * .. . .. extensions - */ - n = ssl->session_negotiate->id_len; - - if( n < 16 || n > 32 || -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || -#endif - ssl->handshake->resume == 0 ) - { - n = 0; - } - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - /* - * RFC 5077 section 3.4: "When presenting a ticket, the client MAY - * generate and include a Session ID in the TLS ClientHello." - */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) -#endif - { - if( ssl->session_negotiate->ticket != NULL && - ssl->session_negotiate->ticket_len != 0 ) - { - ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, 32 ); - - if( ret != 0 ) - return( ret ); - - ssl->session_negotiate->id_len = n = 32; - } - } -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - - *p++ = (unsigned char) n; - - for( i = 0; i < n; i++ ) - *p++ = ssl->session_negotiate->id[i]; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %d", n ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n ); - - /* - * DTLS cookie - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - if( ssl->handshake->verify_cookie == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "no verify cookie to send" ) ); - *p++ = 0; - } - else - { - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", - ssl->handshake->verify_cookie, - ssl->handshake->verify_cookie_len ); - - *p++ = ssl->handshake->verify_cookie_len; - memcpy( p, ssl->handshake->verify_cookie, - ssl->handshake->verify_cookie_len ); - p += ssl->handshake->verify_cookie_len; - } - } -#endif - - /* - * Ciphersuite list - */ - ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; - - /* Skip writing ciphersuite length for now */ - n = 0; - q = p; - p += 2; - - for( i = 0; ciphersuites[i] != 0; i++ ) - { - ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] ); - - if( ciphersuite_info == NULL ) - continue; - - if( ciphersuite_info->min_minor_ver > ssl->conf->max_minor_ver || - ciphersuite_info->max_minor_ver < ssl->conf->min_minor_ver ) - continue; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ( ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) - continue; -#endif - -#if defined(MBEDTLS_ARC4_C) - if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && - ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) - continue; -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && - mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) - continue; -#endif - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x", - ciphersuites[i] ) ); - - n++; - *p++ = (unsigned char)( ciphersuites[i] >> 8 ); - *p++ = (unsigned char)( ciphersuites[i] ); - } - - /* - * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV - */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) -#endif - { - *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO >> 8 ); - *p++ = (unsigned char)( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ); - n++; - } - - /* Some versions of OpenSSL don't handle it correctly if not at end */ -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) - if( ssl->conf->fallback == MBEDTLS_SSL_IS_FALLBACK ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding FALLBACK_SCSV" ) ); - *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ); - *p++ = (unsigned char)( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ); - n++; - } -#endif - - *q++ = (unsigned char)( n >> 7 ); - *q++ = (unsigned char)( n << 1 ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, got %d ciphersuites", n ) ); - -#if defined(MBEDTLS_ZLIB_SUPPORT) - offer_compress = 1; -#else - offer_compress = 0; -#endif - - /* - * We don't support compression with DTLS right now: is many records come - * in the same datagram, uncompressing one could overwrite the next one. - * We don't want to add complexity for handling that case unless there is - * an actual need for it. - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - offer_compress = 0; -#endif - - if( offer_compress ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 2 ) ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d %d", - MBEDTLS_SSL_COMPRESS_DEFLATE, MBEDTLS_SSL_COMPRESS_NULL ) ); - - *p++ = 2; - *p++ = MBEDTLS_SSL_COMPRESS_DEFLATE; - *p++ = MBEDTLS_SSL_COMPRESS_NULL; - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", - MBEDTLS_SSL_COMPRESS_NULL ) ); - - *p++ = 1; - *p++ = MBEDTLS_SSL_COMPRESS_NULL; - } - - // First write extensions, then the total length - // -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - ssl_write_hostname_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; - - ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_ALPN) - ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - - /* olen unused if all extensions are disabled */ - ((void) olen); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %d", - ext_len ) ); - - if( ext_len > 0 ) - { - *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( ext_len ) & 0xFF ); - p += ext_len; - } - - ssl->out_msglen = p - buf; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_HELLO; - - ssl->state++; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - mbedtls_ssl_send_flight_completed( ssl ); -#endif - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); - - return( 0 ); -} - -static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) - { - /* Check verify-data in constant-time. The length OTOH is no secret */ - if( len != 1 + ssl->verify_data_len * 2 || - buf[0] != ssl->verify_data_len * 2 || - mbedtls_ssl_safer_memcmp( buf + 1, - ssl->own_verify_data, ssl->verify_data_len ) != 0 || - mbedtls_ssl_safer_memcmp( buf + 1 + ssl->verify_data_len, - ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - } - else -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - { - if( len != 1 || buf[0] != 0x00 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; - } - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - /* - * server should use the extension only if we did, - * and if so the server's value should match ours (and len is always 1) - */ - if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE || - len != 1 || - buf[0] != ssl->conf->mfl_code ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching max fragment length extension" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - return( 0 ); -} -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED || - len != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching truncated HMAC extension" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - ((void) buf); - - ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) -static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || - len != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching encrypt-then-MAC extension" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - ((void) buf); - - ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) -static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || - len != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching extended master secret extension" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - ((void) buf); - - ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED || - len != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching session ticket extension" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - ((void) buf); - - ssl->handshake->new_session_ticket = 1; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - size_t list_size; - const unsigned char *p; - - list_size = buf[0]; - if( list_size + 1 != len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - p = buf + 1; - while( list_size > 0 ) - { - if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || - p[0] == MBEDTLS_ECP_PF_COMPRESSED ) - { -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) - ssl->handshake->ecdh_ctx.point_format = p[0]; -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl->handshake->ecjpake_ctx.point_format = p[0]; -#endif - MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); - return( 0 ); - } - - list_size--; - p++; - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "no point format in common" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); -} -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || - MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - int ret; - - if( ssl->transform_negotiate->ciphersuite_info->key_exchange != - MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); - return( 0 ); - } - - /* If we got here, we no longer need our cached extension */ - mbedtls_free( ssl->handshake->ecjpake_cache ); - ssl->handshake->ecjpake_cache = NULL; - ssl->handshake->ecjpake_cache_len = 0; - - if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, - buf, len ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( ret ); - } - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_SSL_ALPN) -static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ - size_t list_len, name_len; - const char **p; - - /* If we didn't send it, the server shouldn't send it */ - if( ssl->conf->alpn_list == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching ALPN extension" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - /* - * opaque ProtocolName<1..2^8-1>; - * - * struct { - * ProtocolName protocol_name_list<2..2^16-1> - * } ProtocolNameList; - * - * the "ProtocolNameList" MUST contain exactly one "ProtocolName" - */ - - /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ - if( len < 4 ) - { - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - list_len = ( buf[0] << 8 ) | buf[1]; - if( list_len != len - 2 ) - { - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - name_len = buf[2]; - if( name_len != list_len - 1 ) - { - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - /* Check that the server chosen protocol was in our list and save it */ - for( p = ssl->conf->alpn_list; *p != NULL; p++ ) - { - if( name_len == strlen( *p ) && - memcmp( buf + 3, *p, name_len ) == 0 ) - { - ssl->alpn_chosen = *p; - return( 0 ); - } - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "ALPN extension: no matching protocol" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); -} -#endif /* MBEDTLS_SSL_ALPN */ - -/* - * Parse HelloVerifyRequest. Only called after verifying the HS type. - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) -static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl ) -{ - const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); - int major_ver, minor_ver; - unsigned char cookie_len; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse hello verify request" ) ); - - /* - * struct { - * ProtocolVersion server_version; - * opaque cookie<0..2^8-1>; - * } HelloVerifyRequest; - */ - MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); - mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, p ); - p += 2; - - /* - * Since the RFC is not clear on this point, accept DTLS 1.0 (TLS 1.1) - * even is lower than our min version. - */ - if( major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 || - minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 || - major_ver > ssl->conf->max_major_ver || - minor_ver > ssl->conf->max_minor_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server version" ) ); - - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); - - return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); - } - - cookie_len = *p++; - MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len ); - - if( ( ssl->in_msg + ssl->in_msglen ) - p < cookie_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, - ( "cookie length does not match incoming message size" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - mbedtls_free( ssl->handshake->verify_cookie ); - - ssl->handshake->verify_cookie = mbedtls_calloc( 1, cookie_len ); - if( ssl->handshake->verify_cookie == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", cookie_len ) ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - memcpy( ssl->handshake->verify_cookie, p, cookie_len ); - ssl->handshake->verify_cookie_len = cookie_len; - - /* Start over at ClientHello */ - ssl->state = MBEDTLS_SSL_CLIENT_HELLO; - mbedtls_ssl_reset_checksum( ssl ); - - mbedtls_ssl_recv_flight_completed( ssl ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse hello verify request" ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) -{ - int ret, i; - size_t n; - size_t ext_len; - unsigned char *buf, *ext; - unsigned char comp; -#if defined(MBEDTLS_ZLIB_SUPPORT) - int accept_comp; -#endif -#if defined(MBEDTLS_SSL_RENEGOTIATION) - int renegotiation_info_seen = 0; -#endif - int handshake_failure = 0; - const mbedtls_ssl_ciphersuite_t *suite_info; -#if defined(MBEDTLS_DEBUG_C) - uint32_t t; -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) ); - - buf = ssl->in_msg; - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - /* No alert on a read error. */ - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - { - ssl->renego_records_seen++; - - if( ssl->conf->renego_max_records >= 0 && - ssl->renego_records_seen > ssl->conf->renego_max_records ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " - "but not honored by server" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-handshake message during renego" ) ); - - ssl->keep_current_message = 1; - return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ); - } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - if( buf[0] == MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "received hello verify request" ) ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); - return( ssl_parse_hello_verify_request( ssl ) ); - } - else - { - /* We made it through the verification process */ - mbedtls_free( ssl->handshake->verify_cookie ); - ssl->handshake->verify_cookie = NULL; - ssl->handshake->verify_cookie_len = 0; - } - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - if( ssl->in_hslen < 38 + mbedtls_ssl_hs_hdr_len( ssl ) || - buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - /* - * 0 . 1 server_version - * 2 . 33 random (maybe including 4 bytes of Unix time) - * 34 . 34 session_id length = n - * 35 . 34+n session_id - * 35+n . 36+n cipher_suite - * 37+n . 37+n compression_method - * - * 38+n . 39+n extensions length (optional) - * 40+n . .. extensions - */ - buf += mbedtls_ssl_hs_hdr_len( ssl ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, version", buf + 0, 2 ); - mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, - ssl->conf->transport, buf + 0 ); - - if( ssl->major_ver < ssl->conf->min_major_ver || - ssl->minor_ver < ssl->conf->min_minor_ver || - ssl->major_ver > ssl->conf->max_major_ver || - ssl->minor_ver > ssl->conf->max_minor_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server version out of bounds - " - " min: [%d:%d], server: [%d:%d], max: [%d:%d]", - ssl->conf->min_major_ver, ssl->conf->min_minor_ver, - ssl->major_ver, ssl->minor_ver, - ssl->conf->max_major_ver, ssl->conf->max_minor_ver ) ); - - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); - - return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); - } - -#if defined(MBEDTLS_DEBUG_C) - t = ( (uint32_t) buf[2] << 24 ) - | ( (uint32_t) buf[3] << 16 ) - | ( (uint32_t) buf[4] << 8 ) - | ( (uint32_t) buf[5] ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); -#endif - - memcpy( ssl->handshake->randbytes + 32, buf + 2, 32 ); - - n = buf[34]; - - MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 2, 32 ); - - if( n > 32 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - if( ssl->in_hslen > mbedtls_ssl_hs_hdr_len( ssl ) + 39 + n ) - { - ext_len = ( ( buf[38 + n] << 8 ) - | ( buf[39 + n] ) ); - - if( ( ext_len > 0 && ext_len < 4 ) || - ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - } - else if( ssl->in_hslen == mbedtls_ssl_hs_hdr_len( ssl ) + 38 + n ) - { - ext_len = 0; - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - /* ciphersuite (used later) */ - i = ( buf[35 + n] << 8 ) | buf[36 + n]; - - /* - * Read and check compression - */ - comp = buf[37 + n]; - -#if defined(MBEDTLS_ZLIB_SUPPORT) - /* See comments in ssl_write_client_hello() */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - accept_comp = 0; - else -#endif - accept_comp = 1; - - if( comp != MBEDTLS_SSL_COMPRESS_NULL && - ( comp != MBEDTLS_SSL_COMPRESS_DEFLATE || accept_comp == 0 ) ) -#else /* MBEDTLS_ZLIB_SUPPORT */ - if( comp != MBEDTLS_SSL_COMPRESS_NULL ) -#endif/* MBEDTLS_ZLIB_SUPPORT */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server hello, bad compression: %d", comp ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - /* - * Initialize update checksum functions - */ - ssl->transform_negotiate->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( i ); - - if( ssl->transform_negotiate->ciphersuite_info == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %04x not found", i ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - mbedtls_ssl_optimize_checksum( ssl, ssl->transform_negotiate->ciphersuite_info ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 35, n ); - - /* - * Check if the session can be resumed - */ - if( ssl->handshake->resume == 0 || n == 0 || -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || -#endif - ssl->session_negotiate->ciphersuite != i || - ssl->session_negotiate->compression != comp || - ssl->session_negotiate->id_len != n || - memcmp( ssl->session_negotiate->id, buf + 35, n ) != 0 ) - { - ssl->state++; - ssl->handshake->resume = 0; -#if defined(MBEDTLS_HAVE_TIME) - ssl->session_negotiate->start = mbedtls_time( NULL ); -#endif - ssl->session_negotiate->ciphersuite = i; - ssl->session_negotiate->compression = comp; - ssl->session_negotiate->id_len = n; - memcpy( ssl->session_negotiate->id, buf + 35, n ); - } - else - { - ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; - - if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); - return( ret ); - } - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", - ssl->handshake->resume ? "a" : "no" ) ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", i ) ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", buf[37 + n] ) ); - - suite_info = mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ); - if( suite_info == NULL -#if defined(MBEDTLS_ARC4_C) - || ( ssl->conf->arc4_disabled && - suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) -#endif - ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); - - i = 0; - while( 1 ) - { - if( ssl->conf->ciphersuite_list[ssl->minor_ver][i] == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - if( ssl->conf->ciphersuite_list[ssl->minor_ver][i++] == - ssl->session_negotiate->ciphersuite ) - { - break; - } - } - - if( comp != MBEDTLS_SSL_COMPRESS_NULL -#if defined(MBEDTLS_ZLIB_SUPPORT) - && comp != MBEDTLS_SSL_COMPRESS_DEFLATE -#endif - ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - ssl->session_negotiate->compression = comp; - - ext = buf + 40 + n; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "server hello, total extension length: %d", ext_len ) ); - - while( ext_len ) - { - unsigned int ext_id = ( ( ext[0] << 8 ) - | ( ext[1] ) ); - unsigned int ext_size = ( ( ext[2] << 8 ) - | ( ext[3] ) ); - - if( ext_size + 4 > ext_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - switch( ext_id ) - { - case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); -#if defined(MBEDTLS_SSL_RENEGOTIATION) - renegotiation_info_seen = 1; -#endif - - if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4, - ext_size ) ) != 0 ) - return( ret ); - - break; - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max_fragment_length extension" ) ); - - if( ( ret = ssl_parse_max_fragment_length_ext( ssl, - ext + 4, ext_size ) ) != 0 ) - { - return( ret ); - } - - break; -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated_hmac extension" ) ); - - if( ( ret = ssl_parse_truncated_hmac_ext( ssl, - ext + 4, ext_size ) ) != 0 ) - { - return( ret ); - } - - break; -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt_then_mac extension" ) ); - - if( ( ret = ssl_parse_encrypt_then_mac_ext( ssl, - ext + 4, ext_size ) ) != 0 ) - { - return( ret ); - } - - break; -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended_master_secret extension" ) ); - - if( ( ret = ssl_parse_extended_ms_ext( ssl, - ext + 4, ext_size ) ) != 0 ) - { - return( ret ); - } - - break; -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - case MBEDTLS_TLS_EXT_SESSION_TICKET: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session_ticket extension" ) ); - - if( ( ret = ssl_parse_session_ticket_ext( ssl, - ext + 4, ext_size ) ) != 0 ) - { - return( ret ); - } - - break; -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported_point_formats extension" ) ); - - if( ( ret = ssl_parse_supported_point_formats_ext( ssl, - ext + 4, ext_size ) ) != 0 ) - { - return( ret ); - } - - break; -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || - MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake_kkpp extension" ) ); - - if( ( ret = ssl_parse_ecjpake_kkpp( ssl, - ext + 4, ext_size ) ) != 0 ) - { - return( ret ); - } - - break; -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_SSL_ALPN) - case MBEDTLS_TLS_EXT_ALPN: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); - - if( ( ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ) ) != 0 ) - return( ret ); - - break; -#endif /* MBEDTLS_SSL_ALPN */ - - default: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", - ext_id ) ); - } - - ext_len -= 4 + ext_size; - ext += 4 + ext_size; - - if( ext_len > 0 && ext_len < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - } - - /* - * Renegotiation security checks - */ - if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); - handshake_failure = 1; - } -#if defined(MBEDTLS_SSL_RENEGOTIATION) - else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && - ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && - renegotiation_info_seen == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); - handshake_failure = 1; - } - else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && - ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); - handshake_failure = 1; - } - else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && - ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - renegotiation_info_seen == 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); - handshake_failure = 1; - } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - - if( handshake_failure == 1 ) - { - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); - - return( 0 ); -} - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) -static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, unsigned char **p, - unsigned char *end ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - - /* - * Ephemeral DH parameters: - * - * struct { - * opaque dh_p<1..2^16-1>; - * opaque dh_g<1..2^16-1>; - * opaque dh_Ys<1..2^16-1>; - * } ServerDHParams; - */ - if( ( ret = mbedtls_dhm_read_params( &ssl->handshake->dhm_ctx, p, end ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 2, ( "mbedtls_dhm_read_params" ), ret ); - return( ret ); - } - - if( ssl->handshake->dhm_ctx.len * 8 < ssl->conf->dhm_min_bitlen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %d < %d", - ssl->handshake->dhm_ctx.len * 8, - ssl->conf->dhm_min_bitlen ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); - - return( ret ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl ) -{ - const mbedtls_ecp_curve_info *curve_info; - - curve_info = mbedtls_ecp_curve_info_from_grp_id( ssl->handshake->ecdh_ctx.grp.id ); - if( curve_info == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) ); - -#if defined(MBEDTLS_ECP_C) - if( mbedtls_ssl_check_curve( ssl, ssl->handshake->ecdh_ctx.grp.id ) != 0 ) -#else - if( ssl->handshake->ecdh_ctx.grp.nbits < 163 || - ssl->handshake->ecdh_ctx.grp.nbits > 521 ) -#endif - return( -1 ); - - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp", &ssl->handshake->ecdh_ctx.Qp ); - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) -static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, - unsigned char **p, - unsigned char *end ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - - /* - * Ephemeral ECDH parameters: - * - * struct { - * ECParameters curve_params; - * ECPoint public; - * } ServerECDHParams; - */ - if( ( ret = mbedtls_ecdh_read_params( &ssl->handshake->ecdh_ctx, - (const unsigned char **) p, end ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret ); - return( ret ); - } - - if( ssl_check_server_ecdh_params( ssl ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message (ECDHE curve)" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - return( ret ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, - unsigned char **p, - unsigned char *end ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - size_t len; - ((void) ssl); - - /* - * PSK parameters: - * - * opaque psk_identity_hint<0..2^16-1>; - */ - len = (*p)[0] << 8 | (*p)[1]; - *p += 2; - - if( (*p) + len > end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message " - "(psk_identity_hint length)" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - /* - * Note: we currently ignore the PKS identity hint, as we only allow one - * PSK to be provisionned on the client. This could be changed later if - * someone needs that feature. - */ - *p += len; - ret = 0; - - return( ret ); -} -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) -/* - * Generate a pre-master secret and encrypt it with the server's RSA key - */ -static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, - size_t offset, size_t *olen, - size_t pms_offset ) -{ - int ret; - size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2; - unsigned char *p = ssl->handshake->premaster + pms_offset; - - if( offset + len_bytes > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) ); - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - } - - /* - * Generate (part of) the pre-master as - * struct { - * ProtocolVersion client_version; - * opaque random[46]; - * } PreMasterSecret; - */ - mbedtls_ssl_write_version( ssl->conf->max_major_ver, ssl->conf->max_minor_ver, - ssl->conf->transport, p ); - - if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p + 2, 46 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret ); - return( ret ); - } - - ssl->handshake->pmslen = 48; - - if( ssl->session_negotiate->peer_cert == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - /* - * Now write it out, encrypted - */ - if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, - MBEDTLS_PK_RSA ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) ); - return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); - } - - if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk, - p, ssl->handshake->pmslen, - ssl->out_msg + offset + len_bytes, olen, - MBEDTLS_SSL_MAX_CONTENT_LEN - offset - len_bytes, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret ); - return( ret ); - } - -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( len_bytes == 2 ) - { - ssl->out_msg[offset+0] = (unsigned char)( *olen >> 8 ); - ssl->out_msg[offset+1] = (unsigned char)( *olen ); - *olen += 2; - } -#endif - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl, - unsigned char **p, - unsigned char *end, - mbedtls_md_type_t *md_alg, - mbedtls_pk_type_t *pk_alg ) -{ - ((void) ssl); - *md_alg = MBEDTLS_MD_NONE; - *pk_alg = MBEDTLS_PK_NONE; - - /* Only in TLS 1.2 */ - if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) - { - return( 0 ); - } - - if( (*p) + 2 > end ) - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - - /* - * Get hash algorithm - */ - if( ( *md_alg = mbedtls_ssl_md_alg_from_hash( (*p)[0] ) ) == MBEDTLS_MD_NONE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Server used unsupported " - "HashAlgorithm %d", *(p)[0] ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - /* - * Get signature algorithm - */ - if( ( *pk_alg = mbedtls_ssl_pk_alg_from_sig( (*p)[1] ) ) == MBEDTLS_PK_NONE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used unsupported " - "SignatureAlgorithm %d", (*p)[1] ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - /* - * Check if the hash is acceptable - */ - if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server used HashAlgorithm %d that was not offered", - *(p)[0] ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", (*p)[1] ) ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", (*p)[0] ) ); - *p += 2; - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) -{ - int ret; - const mbedtls_ecp_keypair *peer_key; - - if( ssl->session_negotiate->peer_cert == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, - MBEDTLS_PK_ECKEY ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); - return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); - } - - peer_key = mbedtls_pk_ec( ssl->session_negotiate->peer_cert->pk ); - - if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key, - MBEDTLS_ECDH_THEIRS ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); - return( ret ); - } - - if( ssl_check_server_ecdh_params( ssl ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server certificate (ECDH curve)" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - return( ret ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || - MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ - -static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) -{ - int ret; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->transform_negotiate->ciphersuite_info; - unsigned char *p, *end; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); - ssl->state++; - return( 0 ); - } - ((void) p); - ((void) end); -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) - { - if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); - ssl->state++; - return( 0 ); - } - ((void) p); - ((void) end); -#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - /* - * ServerKeyExchange may be skipped with PSK and RSA-PSK when the server - * doesn't use a psk_identity_hint - */ - if( ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE ) - { - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) - { - /* Current message is probably either - * CertificateRequest or ServerHelloDone */ - ssl->keep_current_message = 1; - goto exit; - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key exchange message must " - "not be skipped" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); - - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); - end = ssl->in_msg + ssl->in_hslen; - MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p ); - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) - { - if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - } /* FALLTROUGH */ -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) - ; /* nothing more to do */ - else -#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED || - MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) - { - if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) - { - if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, - p, end - p ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) - if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) - { - size_t sig_len, hashlen; - unsigned char hash[64]; - mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; - mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; - unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); - size_t params_len = p - params; - - /* - * Handle the digitally-signed structure - */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - if( ssl_parse_signature_algorithm( ssl, &p, end, - &md_alg, &pk_alg ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - if( pk_alg != mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) - { - pk_alg = mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); - - /* Default hash for ECDSA is SHA-1 */ - if( pk_alg == MBEDTLS_PK_ECDSA && md_alg == MBEDTLS_MD_NONE ) - md_alg = MBEDTLS_MD_SHA1; - } - else -#endif - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* - * Read signature - */ - sig_len = ( p[0] << 8 ) | p[1]; - p += 2; - - if( end != p + sig_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "signature", p, sig_len ); - - /* - * Compute the hash that has been signed - */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( md_alg == MBEDTLS_MD_NONE ) - { - mbedtls_md5_context mbedtls_md5; - mbedtls_sha1_context mbedtls_sha1; - - mbedtls_md5_init( &mbedtls_md5 ); - mbedtls_sha1_init( &mbedtls_sha1 ); - - hashlen = 36; - - /* - * digitally-signed struct { - * opaque md5_hash[16]; - * opaque sha_hash[20]; - * }; - * - * md5_hash - * MD5(ClientHello.random + ServerHello.random - * + ServerParams); - * sha_hash - * SHA(ClientHello.random + ServerHello.random - * + ServerParams); - */ - mbedtls_md5_starts( &mbedtls_md5 ); - mbedtls_md5_update( &mbedtls_md5, ssl->handshake->randbytes, 64 ); - mbedtls_md5_update( &mbedtls_md5, params, params_len ); - mbedtls_md5_finish( &mbedtls_md5, hash ); - - mbedtls_sha1_starts( &mbedtls_sha1 ); - mbedtls_sha1_update( &mbedtls_sha1, ssl->handshake->randbytes, 64 ); - mbedtls_sha1_update( &mbedtls_sha1, params, params_len ); - mbedtls_sha1_finish( &mbedtls_sha1, hash + 16 ); - - mbedtls_md5_free( &mbedtls_md5 ); - mbedtls_sha1_free( &mbedtls_sha1 ); - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ - MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( md_alg != MBEDTLS_MD_NONE ) - { - mbedtls_md_context_t ctx; - - mbedtls_md_init( &ctx ); - - /* Info from md_alg will be used instead */ - hashlen = 0; - - /* - * digitally-signed struct { - * opaque client_random[32]; - * opaque server_random[32]; - * ServerDHParams params; - * }; - */ - if( ( ret = mbedtls_md_setup( &ctx, - mbedtls_md_info_from_type( md_alg ), 0 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); - return( ret ); - } - - mbedtls_md_starts( &ctx ); - mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ); - mbedtls_md_update( &ctx, params, params_len ); - mbedtls_md_finish( &ctx, hash ); - mbedtls_md_free( &ctx ); - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : - (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); - - if( ssl->session_negotiate->peer_cert == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - /* - * Verify signature - */ - if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); - } - - if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, - md_alg, hash, hashlen, p, sig_len ) ) != 0 ) - { - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); - return( ret ); - } - } -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ - -exit: - ssl->state++; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) ); - - return( 0 ); -} - -#if ! defined(MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED) -static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) -{ - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); - - if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); - ssl->state++; - return( 0 ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); -} -#else /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ -static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) -{ - int ret; - unsigned char *buf; - size_t n = 0; - size_t cert_type_len = 0, dn_len = 0; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); - - if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); - ssl->state++; - return( 0 ); - } - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - ssl->state++; - ssl->client_auth = ( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request", - ssl->client_auth ? "a" : "no" ) ); - - if( ssl->client_auth == 0 ) - { - /* Current message is probably the ServerHelloDone */ - ssl->keep_current_message = 1; - goto exit; - } - - /* - * struct { - * ClientCertificateType certificate_types<1..2^8-1>; - * SignatureAndHashAlgorithm - * supported_signature_algorithms<2^16-1>; -- TLS 1.2 only - * DistinguishedName certificate_authorities<0..2^16-1>; - * } CertificateRequest; - * - * Since we only support a single certificate on clients, let's just - * ignore all the information that's supposed to help us pick a - * certificate. - * - * We could check that our certificate matches the request, and bail out - * if it doesn't, but it's simpler to just send the certificate anyway, - * and give the server the opportunity to decide if it should terminate - * the connection when it doesn't like our certificate. - * - * Same goes for the hash in TLS 1.2's signature_algorithms: at this - * point we only have one hash available (see comments in - * write_certificate_verify), so let's just use what we have. - * - * However, we still minimally parse the message to check it is at least - * superficially sane. - */ - buf = ssl->in_msg; - - /* certificate_types */ - cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )]; - n = cert_type_len; - - if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); - } - - /* supported_signature_algorithms */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - size_t sig_alg_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) - | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); -#if defined(MBEDTLS_DEBUG_C) - unsigned char* sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n; - size_t i; - - for( i = 0; i < sig_alg_len; i += 2 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "Supported Signature Algorithm found: %d" - ",%d", sig_alg[i], sig_alg[i + 1] ) ); - } -#endif - - n += 2 + sig_alg_len; - - if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); - } - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - - /* certificate_authorities */ - dn_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) - | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); - - n += dn_len; - if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST ); - } - -exit: - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) ); - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */ - -static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) -{ - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) || - ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE ); - } - - ssl->state++; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - mbedtls_ssl_recv_flight_completed( ssl ); -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) ); - - return( 0 ); -} - -static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) -{ - int ret; - size_t i, n; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) ); - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) - { - /* - * DHM key exchange -- send G^X mod P - */ - n = ssl->handshake->dhm_ctx.len; - - ssl->out_msg[4] = (unsigned char)( n >> 8 ); - ssl->out_msg[5] = (unsigned char)( n ); - i = 6; - - ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, - (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), - &ssl->out_msg[i], n, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); - - if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, - ssl->handshake->premaster, - MBEDTLS_PREMASTER_SIZE, - &ssl->handshake->pmslen, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) - { - /* - * ECDH key exchange -- send client public value - */ - i = 4; - - ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, - &n, - &ssl->out_msg[i], 1000, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); - - if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, - &ssl->handshake->pmslen, - ssl->handshake->premaster, - MBEDTLS_MPI_MAX_SIZE, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - if( mbedtls_ssl_ciphersuite_uses_psk( ciphersuite_info ) ) - { - /* - * opaque psk_identity<0..2^16-1>; - */ - if( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for PSK" ) ); - return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); - } - - i = 4; - n = ssl->conf->psk_identity_len; - - if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity too long or " - "SSL buffer too short" ) ); - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - } - - ssl->out_msg[i++] = (unsigned char)( n >> 8 ); - ssl->out_msg[i++] = (unsigned char)( n ); - - memcpy( ssl->out_msg + i, ssl->conf->psk_identity, ssl->conf->psk_identity_len ); - i += ssl->conf->psk_identity_len; - -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) - { - n = 0; - } - else -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) - { - if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 2 ) ) != 0 ) - return( ret ); - } - else -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) - { - /* - * ClientDiffieHellmanPublic public (DHM send G^X mod P) - */ - n = ssl->handshake->dhm_ctx.len; - - if( i + 2 + n > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "psk identity or DHM size too long" - " or SSL buffer too short" ) ); - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - } - - ssl->out_msg[i++] = (unsigned char)( n >> 8 ); - ssl->out_msg[i++] = (unsigned char)( n ); - - ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, - (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), - &ssl->out_msg[i], n, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) - { - /* - * ClientECDiffieHellmanPublic public; - */ - ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n, - &ssl->out_msg[i], MBEDTLS_SSL_MAX_CONTENT_LEN - i, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, - ciphersuite_info->key_exchange ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) - { - i = 4; - if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 0 ) ) != 0 ) - return( ret ); - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - i = 4; - - ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, - ssl->out_msg + i, MBEDTLS_SSL_MAX_CONTENT_LEN - i, &n, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); - return( ret ); - } - - ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, - ssl->handshake->premaster, 32, &ssl->handshake->pmslen, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ - { - ((void) ciphersuite_info); - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - ssl->out_msglen = i + n; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE; - - ssl->state++; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) ); - - return( 0 ); -} - -#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) -{ - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->transform_negotiate->ciphersuite_info; - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); - - if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); - return( ret ); - } - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); - ssl->state++; - return( 0 ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); -} -#else -static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->transform_negotiate->ciphersuite_info; - size_t n = 0, offset = 0; - unsigned char hash[48]; - unsigned char *hash_start = hash; - mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; - unsigned int hashlen; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); - - if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); - return( ret ); - } - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); - ssl->state++; - return( 0 ); - } - - if( ssl->client_auth == 0 || mbedtls_ssl_own_cert( ssl ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); - ssl->state++; - return( 0 ); - } - - if( mbedtls_ssl_own_key( ssl ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for certificate" ) ); - return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); - } - - /* - * Make an RSA signature of the handshake digests - */ - ssl->handshake->calc_verify( ssl, hash ); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) - { - /* - * digitally-signed struct { - * opaque md5_hash[16]; - * opaque sha_hash[20]; - * }; - * - * md5_hash - * MD5(handshake_messages); - * - * sha_hash - * SHA(handshake_messages); - */ - hashlen = 36; - md_alg = MBEDTLS_MD_NONE; - - /* - * For ECDSA, default hash is SHA-1 only - */ - if( mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECDSA ) ) - { - hash_start += 16; - hashlen -= 16; - md_alg = MBEDTLS_MD_SHA1; - } - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ - MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - /* - * digitally-signed struct { - * opaque handshake_messages[handshake_messages_length]; - * }; - * - * Taking shortcut here. We assume that the server always allows the - * PRF Hash function and has sent it in the allowed signature - * algorithms list received in the Certificate Request message. - * - * Until we encounter a server that does not, we will take this - * shortcut. - * - * Reason: Otherwise we should have running hashes for SHA512 and SHA224 - * in order to satisfy 'weird' needs from the server side. - */ - if( ssl->transform_negotiate->ciphersuite_info->mac == - MBEDTLS_MD_SHA384 ) - { - md_alg = MBEDTLS_MD_SHA384; - ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384; - } - else - { - md_alg = MBEDTLS_MD_SHA256; - ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256; - } - ssl->out_msg[5] = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) ); - - /* Info from md_alg will be used instead */ - hashlen = 0; - offset = 2; - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash_start, hashlen, - ssl->out_msg + 6 + offset, &n, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); - return( ret ); - } - - ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 ); - ssl->out_msg[5 + offset] = (unsigned char)( n ); - - ssl->out_msglen = 6 + n + offset; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY; - - ssl->state++; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) ); - - return( ret ); -} -#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) -{ - int ret; - uint32_t lifetime; - size_t ticket_len; - unsigned char *ticket; - const unsigned char *msg; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) ); - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - /* - * struct { - * uint32 ticket_lifetime_hint; - * opaque ticket<0..2^16-1>; - * } NewSessionTicket; - * - * 0 . 3 ticket_lifetime_hint - * 4 . 5 ticket_len (n) - * 6 . 5+n ticket content - */ - if( ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET || - ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len( ssl ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); - } - - msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); - - lifetime = ( msg[0] << 24 ) | ( msg[1] << 16 ) | - ( msg[2] << 8 ) | ( msg[3] ); - - ticket_len = ( msg[4] << 8 ) | ( msg[5] ); - - if( ticket_len + 6 + mbedtls_ssl_hs_hdr_len( ssl ) != ssl->in_hslen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET ); - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", ticket_len ) ); - - /* We're not waiting for a NewSessionTicket message any more */ - ssl->handshake->new_session_ticket = 0; - ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; - - /* - * Zero-length ticket means the server changed his mind and doesn't want - * to send a ticket after all, so just forget it - */ - if( ticket_len == 0 ) - return( 0 ); - - mbedtls_zeroize( ssl->session_negotiate->ticket, - ssl->session_negotiate->ticket_len ); - mbedtls_free( ssl->session_negotiate->ticket ); - ssl->session_negotiate->ticket = NULL; - ssl->session_negotiate->ticket_len = 0; - - if( ( ticket = mbedtls_calloc( 1, ticket_len ) ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "ticket alloc failed" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - memcpy( ticket, msg + 6, ticket_len ); - - ssl->session_negotiate->ticket = ticket; - ssl->session_negotiate->ticket_len = ticket_len; - ssl->session_negotiate->ticket_lifetime = lifetime; - - /* - * RFC 5077 section 3.4: - * "If the client receives a session ticket from the server, then it - * discards any Session ID that was sent in the ServerHello." - */ - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket in use, discarding session id" ) ); - ssl->session_negotiate->id_len = 0; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse new session ticket" ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -/* - * SSL handshake -- client side -- single step - */ -int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) -{ - int ret = 0; - - if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) ); - - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) - return( ret ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) - { - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) - return( ret ); - } -#endif - - /* Change state now, so that it is right in mbedtls_ssl_read_record(), used - * by DTLS for dropping out-of-sequence ChangeCipherSpec records */ -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - if( ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC && - ssl->handshake->new_session_ticket != 0 ) - { - ssl->state = MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET; - } -#endif - - switch( ssl->state ) - { - case MBEDTLS_SSL_HELLO_REQUEST: - ssl->state = MBEDTLS_SSL_CLIENT_HELLO; - break; - - /* - * ==> ClientHello - */ - case MBEDTLS_SSL_CLIENT_HELLO: - ret = ssl_write_client_hello( ssl ); - break; - - /* - * <== ServerHello - * Certificate - * ( ServerKeyExchange ) - * ( CertificateRequest ) - * ServerHelloDone - */ - case MBEDTLS_SSL_SERVER_HELLO: - ret = ssl_parse_server_hello( ssl ); - break; - - case MBEDTLS_SSL_SERVER_CERTIFICATE: - ret = mbedtls_ssl_parse_certificate( ssl ); - break; - - case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: - ret = ssl_parse_server_key_exchange( ssl ); - break; - - case MBEDTLS_SSL_CERTIFICATE_REQUEST: - ret = ssl_parse_certificate_request( ssl ); - break; - - case MBEDTLS_SSL_SERVER_HELLO_DONE: - ret = ssl_parse_server_hello_done( ssl ); - break; - - /* - * ==> ( Certificate/Alert ) - * ClientKeyExchange - * ( CertificateVerify ) - * ChangeCipherSpec - * Finished - */ - case MBEDTLS_SSL_CLIENT_CERTIFICATE: - ret = mbedtls_ssl_write_certificate( ssl ); - break; - - case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: - ret = ssl_write_client_key_exchange( ssl ); - break; - - case MBEDTLS_SSL_CERTIFICATE_VERIFY: - ret = ssl_write_certificate_verify( ssl ); - break; - - case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: - ret = mbedtls_ssl_write_change_cipher_spec( ssl ); - break; - - case MBEDTLS_SSL_CLIENT_FINISHED: - ret = mbedtls_ssl_write_finished( ssl ); - break; - - /* - * <== ( NewSessionTicket ) - * ChangeCipherSpec - * Finished - */ -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET: - ret = ssl_parse_new_session_ticket( ssl ); - break; -#endif - - case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: - ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); - break; - - case MBEDTLS_SSL_SERVER_FINISHED: - ret = mbedtls_ssl_parse_finished( ssl ); - break; - - case MBEDTLS_SSL_FLUSH_BUFFERS: - MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); - ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; - break; - - case MBEDTLS_SSL_HANDSHAKE_WRAPUP: - mbedtls_ssl_handshake_wrapup( ssl ); - break; - - default: - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - return( ret ); -} -#endif /* MBEDTLS_SSL_CLI_C */ diff --git a/components/mbedtls/library/ssl_cookie.c b/components/mbedtls/library/ssl_cookie.c deleted file mode 100644 index caf119990d..0000000000 --- a/components/mbedtls/library/ssl_cookie.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * DTLS cookie callbacks implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * These session callbacks use a simple chained list - * to store and retrieve the session information. - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_SSL_COOKIE_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include "mbedtls/ssl_cookie.h" -#include "mbedtls/ssl_internal.h" - -#include - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is - * available. Try SHA-256 first, 512 wastes resources since we need to stay - * with max 32 bytes of cookie for DTLS 1.0 - */ -#if defined(MBEDTLS_SHA256_C) -#define COOKIE_MD MBEDTLS_MD_SHA224 -#define COOKIE_MD_OUTLEN 32 -#define COOKIE_HMAC_LEN 28 -#elif defined(MBEDTLS_SHA512_C) -#define COOKIE_MD MBEDTLS_MD_SHA384 -#define COOKIE_MD_OUTLEN 48 -#define COOKIE_HMAC_LEN 28 -#elif defined(MBEDTLS_SHA1_C) -#define COOKIE_MD MBEDTLS_MD_SHA1 -#define COOKIE_MD_OUTLEN 20 -#define COOKIE_HMAC_LEN 20 -#else -#error "DTLS hello verify needs SHA-1 or SHA-2" -#endif - -/* - * Cookies are formed of a 4-bytes timestamp (or serial number) and - * an HMAC of timestemp and client ID. - */ -#define COOKIE_LEN ( 4 + COOKIE_HMAC_LEN ) - -void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ) -{ - mbedtls_md_init( &ctx->hmac_ctx ); -#if !defined(MBEDTLS_HAVE_TIME) - ctx->serial = 0; -#endif - ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT; - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif -} - -void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ) -{ - ctx->timeout = delay; -} - -void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ) -{ - mbedtls_md_free( &ctx->hmac_ctx ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); -#endif - - mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) ); -} - -int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - unsigned char key[COOKIE_MD_OUTLEN]; - - if( ( ret = f_rng( p_rng, key, sizeof( key ) ) ) != 0 ) - return( ret ); - - ret = mbedtls_md_setup( &ctx->hmac_ctx, mbedtls_md_info_from_type( COOKIE_MD ), 1 ); - if( ret != 0 ) - return( ret ); - - ret = mbedtls_md_hmac_starts( &ctx->hmac_ctx, key, sizeof( key ) ); - if( ret != 0 ) - return( ret ); - - mbedtls_zeroize( key, sizeof( key ) ); - - return( 0 ); -} - -/* - * Generate the HMAC part of a cookie - */ -static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx, - const unsigned char time[4], - unsigned char **p, unsigned char *end, - const unsigned char *cli_id, size_t cli_id_len ) -{ - unsigned char hmac_out[COOKIE_MD_OUTLEN]; - - if( (size_t)( end - *p ) < COOKIE_HMAC_LEN ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - - if( mbedtls_md_hmac_reset( hmac_ctx ) != 0 || - mbedtls_md_hmac_update( hmac_ctx, time, 4 ) != 0 || - mbedtls_md_hmac_update( hmac_ctx, cli_id, cli_id_len ) != 0 || - mbedtls_md_hmac_finish( hmac_ctx, hmac_out ) != 0 ) - { - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - memcpy( *p, hmac_out, COOKIE_HMAC_LEN ); - *p += COOKIE_HMAC_LEN; - - return( 0 ); -} - -/* - * Generate cookie for DTLS ClientHello verification - */ -int mbedtls_ssl_cookie_write( void *p_ctx, - unsigned char **p, unsigned char *end, - const unsigned char *cli_id, size_t cli_id_len ) -{ - int ret; - mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; - unsigned long t; - - if( ctx == NULL || cli_id == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( (size_t)( end - *p ) < COOKIE_LEN ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - -#if defined(MBEDTLS_HAVE_TIME) - t = (unsigned long) mbedtls_time( NULL ); -#else - t = ctx->serial++; -#endif - - (*p)[0] = (unsigned char)( t >> 24 ); - (*p)[1] = (unsigned char)( t >> 16 ); - (*p)[2] = (unsigned char)( t >> 8 ); - (*p)[3] = (unsigned char)( t ); - *p += 4; - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret ); -#endif - - ret = ssl_cookie_hmac( &ctx->hmac_ctx, *p - 4, - p, end, cli_id, cli_id_len ); - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + - MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -/* - * Check a cookie - */ -int mbedtls_ssl_cookie_check( void *p_ctx, - const unsigned char *cookie, size_t cookie_len, - const unsigned char *cli_id, size_t cli_id_len ) -{ - unsigned char ref_hmac[COOKIE_HMAC_LEN]; - int ret = 0; - unsigned char *p = ref_hmac; - mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; - unsigned long cur_time, cookie_time; - - if( ctx == NULL || cli_id == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( cookie_len != COOKIE_LEN ) - return( -1 ); - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + ret ); -#endif - - if( ssl_cookie_hmac( &ctx->hmac_ctx, cookie, - &p, p + sizeof( ref_hmac ), - cli_id, cli_id_len ) != 0 ) - ret = -1; - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR + - MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - if( ret != 0 ) - return( ret ); - - if( mbedtls_ssl_safer_memcmp( cookie + 4, ref_hmac, sizeof( ref_hmac ) ) != 0 ) - return( -1 ); - -#if defined(MBEDTLS_HAVE_TIME) - cur_time = (unsigned long) mbedtls_time( NULL ); -#else - cur_time = ctx->serial; -#endif - - cookie_time = ( (unsigned long) cookie[0] << 24 ) | - ( (unsigned long) cookie[1] << 16 ) | - ( (unsigned long) cookie[2] << 8 ) | - ( (unsigned long) cookie[3] ); - - if( ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout ) - return( -1 ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_COOKIE_C */ diff --git a/components/mbedtls/library/ssl_srv.c b/components/mbedtls/library/ssl_srv.c deleted file mode 100644 index f137c3dce6..0000000000 --- a/components/mbedtls/library/ssl_srv.c +++ /dev/null @@ -1,4136 +0,0 @@ -/* - * SSLv3/TLSv1 server-side functions - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_SSL_SRV_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include "mbedtls/debug.h" -#include "mbedtls/ssl.h" -#include "mbedtls/ssl_internal.h" - -#include - -#if defined(MBEDTLS_ECP_C) -#include "mbedtls/ecp.h" -#endif - -#if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" -#endif - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} -#endif - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) -int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, - const unsigned char *info, - size_t ilen ) -{ - if( ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - mbedtls_free( ssl->cli_id ); - - if( ( ssl->cli_id = mbedtls_calloc( 1, ilen ) ) == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - memcpy( ssl->cli_id, info, ilen ); - ssl->cli_id_len = ilen; - - return( 0 ); -} - -void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, - mbedtls_ssl_cookie_write_t *f_cookie_write, - mbedtls_ssl_cookie_check_t *f_cookie_check, - void *p_cookie ) -{ - conf->f_cookie_write = f_cookie_write; - conf->f_cookie_check = f_cookie_check; - conf->p_cookie = p_cookie; -} -#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) -static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - int ret; - size_t servername_list_size, hostname_len; - const unsigned char *p; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) ); - - servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); - if( servername_list_size + 2 != len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - p = buf + 2; - while( servername_list_size > 0 ) - { - hostname_len = ( ( p[1] << 8 ) | p[2] ); - if( hostname_len + 3 > servername_list_size ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - if( p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) - { - ret = ssl->conf->f_sni( ssl->conf->p_sni, - ssl, p + 3, hostname_len ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - return( 0 ); - } - - servername_list_size -= hostname_len + 3; - p += hostname_len + 3; - } - - if( servername_list_size != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - return( 0 ); -} -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - -static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) - { - /* Check verify-data in constant-time. The length OTOH is no secret */ - if( len != 1 + ssl->verify_data_len || - buf[0] != ssl->verify_data_len || - mbedtls_ssl_safer_memcmp( buf + 1, ssl->peer_verify_data, - ssl->verify_data_len ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - } - else -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - { - if( len != 1 || buf[0] != 0x0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; - } - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - -/* - * Status of the implementation of signature-algorithms extension: - * - * Currently, we are only considering the signature-algorithm extension - * to pick a ciphersuite which allows us to send the ServerKeyExchange - * message with a signature-hash combination that the user allows. - * - * We do *not* check whether all certificates in our certificate - * chain are signed with an allowed signature-hash pair. - * This needs to be done at a later stage. - * - */ -static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - size_t sig_alg_list_size; - - const unsigned char *p; - const unsigned char *end = buf + len; - - mbedtls_md_type_t md_cur; - mbedtls_pk_type_t sig_cur; - - sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); - if( sig_alg_list_size + 2 != len || - sig_alg_list_size % 2 != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - /* Currently we only guarantee signing the ServerKeyExchange message according - * to the constraints specified in this extension (see above), so it suffices - * to remember only one suitable hash for each possible signature algorithm. - * - * This will change when we also consider certificate signatures, - * in which case we will need to remember the whole signature-hash - * pair list from the extension. - */ - - for( p = buf + 2; p < end; p += 2 ) - { - /* Silently ignore unknown signature or hash algorithms. */ - - if( ( sig_cur = mbedtls_ssl_pk_alg_from_sig( p[1] ) ) == MBEDTLS_PK_NONE ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext" - " unknown sig alg encoding %d", p[1] ) ); - continue; - } - - /* Check if we support the hash the user proposes */ - md_cur = mbedtls_ssl_md_alg_from_hash( p[0] ); - if( md_cur == MBEDTLS_MD_NONE ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" - " unknown hash alg encoding %d", p[0] ) ); - continue; - } - - if( mbedtls_ssl_check_sig_hash( ssl, md_cur ) == 0 ) - { - mbedtls_ssl_sig_hash_set_add( &ssl->handshake->hash_algs, sig_cur, md_cur ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" - " match sig %d and hash %d", - sig_cur, md_cur ) ); - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: " - "hash alg %d not supported", md_cur ) ); - } - } - - return( 0 ); -} -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - size_t list_size, our_size; - const unsigned char *p; - const mbedtls_ecp_curve_info *curve_info, **curves; - - list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); - if( list_size + 2 != len || - list_size % 2 != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - /* Should never happen unless client duplicates the extension */ - if( ssl->handshake->curves != NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - /* Don't allow our peer to make us allocate too much memory, - * and leave room for a final 0 */ - our_size = list_size / 2 + 1; - if( our_size > MBEDTLS_ECP_DP_MAX ) - our_size = MBEDTLS_ECP_DP_MAX; - - if( ( curves = mbedtls_calloc( our_size, sizeof( *curves ) ) ) == NULL ) - { - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - ssl->handshake->curves = curves; - - p = buf + 2; - while( list_size > 0 && our_size > 1 ) - { - curve_info = mbedtls_ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] ); - - if( curve_info != NULL ) - { - *curves++ = curve_info; - our_size--; - } - - list_size -= 2; - p += 2; - } - - return( 0 ); -} - -static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - size_t list_size; - const unsigned char *p; - - list_size = buf[0]; - if( list_size + 1 != len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - p = buf + 1; - while( list_size > 0 ) - { - if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || - p[0] == MBEDTLS_ECP_PF_COMPRESSED ) - { -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) - ssl->handshake->ecdh_ctx.point_format = p[0]; -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl->handshake->ecjpake_ctx.point_format = p[0]; -#endif - MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); - return( 0 ); - } - - list_size--; - p++; - } - - return( 0 ); -} -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || - MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - int ret; - - if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); - return( 0 ); - } - - if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, - buf, len ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( ret ); - } - - /* Only mark the extension as OK when we're sure it is */ - ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK; - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - if( len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ssl->session_negotiate->mfl_code = buf[0]; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - if( len != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ((void) buf); - - if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) - ssl->session_negotiate->trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) -static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - if( len != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ((void) buf); - - if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED && - ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) - { - ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; - } - - return( 0 ); -} -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) -static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, - size_t len ) -{ - if( len != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ((void) buf); - - if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED && - ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) - { - ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; - } - - return( 0 ); -} -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t len ) -{ - int ret; - mbedtls_ssl_session session; - - mbedtls_ssl_session_init( &session ); - - if( ssl->conf->f_ticket_parse == NULL || - ssl->conf->f_ticket_write == NULL ) - { - return( 0 ); - } - - /* Remember the client asked us to send a new ticket */ - ssl->handshake->new_session_ticket = 1; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %d", len ) ); - - if( len == 0 ) - return( 0 ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket rejected: renegotiating" ) ); - return( 0 ); - } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - - /* - * Failures are ok: just ignore the ticket and proceed. - */ - if( ( ret = ssl->conf->f_ticket_parse( ssl->conf->p_ticket, &session, - buf, len ) ) != 0 ) - { - mbedtls_ssl_session_free( &session ); - - if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is not authentic" ) ); - else if( ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED ) - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is expired" ) ); - else - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_parse", ret ); - - return( 0 ); - } - - /* - * Keep the session ID sent by the client, since we MUST send it back to - * inform them we're accepting the ticket (RFC 5077 section 3.4) - */ - session.id_len = ssl->session_negotiate->id_len; - memcpy( &session.id, ssl->session_negotiate->id, session.id_len ); - - mbedtls_ssl_session_free( ssl->session_negotiate ); - memcpy( ssl->session_negotiate, &session, sizeof( mbedtls_ssl_session ) ); - - /* Zeroize instead of free as we copied the content */ - mbedtls_zeroize( &session, sizeof( mbedtls_ssl_session ) ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from ticket" ) ); - - ssl->handshake->resume = 1; - - /* Don't send a new ticket after all, this one is OK */ - ssl->handshake->new_session_ticket = 0; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -#if defined(MBEDTLS_SSL_ALPN) -static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ - size_t list_len, cur_len, ours_len; - const unsigned char *theirs, *start, *end; - const char **ours; - - /* If ALPN not configured, just ignore the extension */ - if( ssl->conf->alpn_list == NULL ) - return( 0 ); - - /* - * opaque ProtocolName<1..2^8-1>; - * - * struct { - * ProtocolName protocol_name_list<2..2^16-1> - * } ProtocolNameList; - */ - - /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ - if( len < 4 ) - { - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - list_len = ( buf[0] << 8 ) | buf[1]; - if( list_len != len - 2 ) - { - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - /* - * Use our order of preference - */ - start = buf + 2; - end = buf + len; - for( ours = ssl->conf->alpn_list; *ours != NULL; ours++ ) - { - ours_len = strlen( *ours ); - for( theirs = start; theirs != end; theirs += cur_len ) - { - /* If the list is well formed, we should get equality first */ - if( theirs > end ) - { - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - cur_len = *theirs++; - - /* Empty strings MUST NOT be included */ - if( cur_len == 0 ) - { - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - if( cur_len == ours_len && - memcmp( theirs, *ours, cur_len ) == 0 ) - { - ssl->alpn_chosen = *ours; - return( 0 ); - } - } - } - - /* If we get there, no match was found */ - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); -} -#endif /* MBEDTLS_SSL_ALPN */ - -/* - * Auxiliary functions for ServerHello parsing and related actions - */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -/* - * Return 0 if the given key uses one of the acceptable curves, -1 otherwise - */ -#if defined(MBEDTLS_ECDSA_C) -static int ssl_check_key_curve( mbedtls_pk_context *pk, - const mbedtls_ecp_curve_info **curves ) -{ - const mbedtls_ecp_curve_info **crv = curves; - mbedtls_ecp_group_id grp_id = mbedtls_pk_ec( *pk )->grp.id; - - while( *crv != NULL ) - { - if( (*crv)->grp_id == grp_id ) - return( 0 ); - crv++; - } - - return( -1 ); -} -#endif /* MBEDTLS_ECDSA_C */ - -/* - * Try picking a certificate for this ciphersuite, - * return 0 on success and -1 on failure. - */ -static int ssl_pick_cert( mbedtls_ssl_context *ssl, - const mbedtls_ssl_ciphersuite_t * ciphersuite_info ) -{ - mbedtls_ssl_key_cert *cur, *list, *fallback = NULL; - mbedtls_pk_type_t pk_alg = - mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); - uint32_t flags; - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if( ssl->handshake->sni_key_cert != NULL ) - list = ssl->handshake->sni_key_cert; - else -#endif - list = ssl->conf->key_cert; - - if( pk_alg == MBEDTLS_PK_NONE ) - return( 0 ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite requires certificate" ) ); - - if( list == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server has no certificate" ) ); - return( -1 ); - } - - for( cur = list; cur != NULL; cur = cur->next ) - { - MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate", - cur->cert ); - - if( ! mbedtls_pk_can_do( cur->key, pk_alg ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) ); - continue; - } - - /* - * This avoids sending the client a cert it'll reject based on - * keyUsage or other extensions. - * - * It also allows the user to provision different certificates for - * different uses based on keyUsage, eg if they want to avoid signing - * and decrypting with the same RSA key. - */ - if( mbedtls_ssl_check_cert_usage( cur->cert, ciphersuite_info, - MBEDTLS_SSL_IS_SERVER, &flags ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: " - "(extended) key usage extension" ) ); - continue; - } - -#if defined(MBEDTLS_ECDSA_C) - if( pk_alg == MBEDTLS_PK_ECDSA && - ssl_check_key_curve( cur->key, ssl->handshake->curves ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) ); - continue; - } -#endif - - /* - * Try to select a SHA-1 certificate for pre-1.2 clients, but still - * present them a SHA-higher cert rather than failing if it's the only - * one we got that satisfies the other conditions. - */ - if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 && - cur->cert->sig_md != MBEDTLS_MD_SHA1 ) - { - if( fallback == NULL ) - fallback = cur; - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate not preferred: " - "sha-2 with pre-TLS 1.2 client" ) ); - continue; - } - } - - /* If we get there, we got a winner */ - break; - } - - if( cur == NULL ) - cur = fallback; - - /* Do not update ssl->handshake->key_cert unless there is a match */ - if( cur != NULL ) - { - ssl->handshake->key_cert = cur; - MBEDTLS_SSL_DEBUG_CRT( 3, "selected certificate chain, certificate", - ssl->handshake->key_cert->cert ); - return( 0 ); - } - - return( -1 ); -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -/* - * Check if a given ciphersuite is suitable for use with our config/keys/etc - * Sets ciphersuite_info only if the suite matches. - */ -static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, - const mbedtls_ssl_ciphersuite_t **ciphersuite_info ) -{ - const mbedtls_ssl_ciphersuite_t *suite_info; - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - mbedtls_pk_type_t sig_type; -#endif - - suite_info = mbedtls_ssl_ciphersuite_from_id( suite_id ); - if( suite_info == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "trying ciphersuite: %s", suite_info->name ) ); - - if( suite_info->min_minor_ver > ssl->minor_ver || - suite_info->max_minor_ver < ssl->minor_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: version" ) ); - return( 0 ); - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) - return( 0 ); -#endif - -#if defined(MBEDTLS_ARC4_C) - if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && - suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: rc4" ) ); - return( 0 ); - } -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && - ( ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK ) == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: ecjpake " - "not configured or ext missing" ) ); - return( 0 ); - } -#endif - - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) - if( mbedtls_ssl_ciphersuite_uses_ec( suite_info ) && - ( ssl->handshake->curves == NULL || - ssl->handshake->curves[0] == NULL ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " - "no common elliptic curve" ) ); - return( 0 ); - } -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - /* If the ciphersuite requires a pre-shared key and we don't - * have one, skip it now rather than failing later */ - if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && - ssl->conf->f_psk == NULL && - ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL || - ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) ); - return( 0 ); - } -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - /* If the ciphersuite requires signing, check whether - * a suitable hash algorithm is present. */ - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - sig_type = mbedtls_ssl_get_ciphersuite_sig_alg( suite_info ); - if( sig_type != MBEDTLS_PK_NONE && - mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, sig_type ) == MBEDTLS_MD_NONE ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no suitable hash algorithm " - "for signature algorithm %d", sig_type ) ); - return( 0 ); - } - } - -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - /* - * Final check: if ciphersuite requires us to have a - * certificate/key of a particular type: - * - select the appropriate certificate if we have one, or - * - try the next ciphersuite if we don't - * This must be done last since we modify the key_cert list. - */ - if( ssl_pick_cert( ssl, suite_info ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " - "no suitable certificate" ) ); - return( 0 ); - } -#endif - - *ciphersuite_info = suite_info; - return( 0 ); -} - -#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) -static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl ) -{ - int ret, got_common_suite; - unsigned int i, j; - size_t n; - unsigned int ciph_len, sess_len, chal_len; - unsigned char *buf, *p; - const int *ciphersuites; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello v2" ) ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "client hello v2 illegal for renegotiation" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - - buf = ssl->in_hdr; - - MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, 5 ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message type: %d", - buf[2] ) ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, message len.: %d", - ( ( buf[0] & 0x7F ) << 8 ) | buf[1] ) ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v2, max. version: [%d:%d]", - buf[3], buf[4] ) ); - - /* - * SSLv2 Client Hello - * - * Record layer: - * 0 . 1 message length - * - * SSL layer: - * 2 . 2 message type - * 3 . 4 protocol version - */ - if( buf[2] != MBEDTLS_SSL_HS_CLIENT_HELLO || - buf[3] != MBEDTLS_SSL_MAJOR_VERSION_3 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - n = ( ( buf[0] << 8 ) | buf[1] ) & 0x7FFF; - - if( n < 17 || n > 512 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; - ssl->minor_ver = ( buf[4] <= ssl->conf->max_minor_ver ) - ? buf[4] : ssl->conf->max_minor_ver; - - if( ssl->minor_ver < ssl->conf->min_minor_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" - " [%d:%d] < [%d:%d]", - ssl->major_ver, ssl->minor_ver, - ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); - - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); - return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); - } - - ssl->handshake->max_major_ver = buf[3]; - ssl->handshake->max_minor_ver = buf[4]; - - if( ( ret = mbedtls_ssl_fetch_input( ssl, 2 + n ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); - return( ret ); - } - - ssl->handshake->update_checksum( ssl, buf + 2, n ); - - buf = ssl->in_msg; - n = ssl->in_left - 5; - - /* - * 0 . 1 ciphersuitelist length - * 2 . 3 session id length - * 4 . 5 challenge length - * 6 . .. ciphersuitelist - * .. . .. session id - * .. . .. challenge - */ - MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, n ); - - ciph_len = ( buf[0] << 8 ) | buf[1]; - sess_len = ( buf[2] << 8 ) | buf[3]; - chal_len = ( buf[4] << 8 ) | buf[5]; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciph_len: %d, sess_len: %d, chal_len: %d", - ciph_len, sess_len, chal_len ) ); - - /* - * Make sure each parameter length is valid - */ - if( ciph_len < 3 || ( ciph_len % 3 ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - if( sess_len > 32 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - if( chal_len < 8 || chal_len > 32 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - if( n != 6 + ciph_len + sess_len + chal_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", - buf + 6, ciph_len ); - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", - buf + 6 + ciph_len, sess_len ); - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, challenge", - buf + 6 + ciph_len + sess_len, chal_len ); - - p = buf + 6 + ciph_len; - ssl->session_negotiate->id_len = sess_len; - memset( ssl->session_negotiate->id, 0, - sizeof( ssl->session_negotiate->id ) ); - memcpy( ssl->session_negotiate->id, p, ssl->session_negotiate->id_len ); - - p += sess_len; - memset( ssl->handshake->randbytes, 0, 64 ); - memcpy( ssl->handshake->randbytes + 32 - chal_len, p, chal_len ); - - /* - * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV - */ - for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) - { - if( p[0] == 0 && p[1] == 0 && p[2] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " - "during renegotiation" ) ); - - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; - break; - } - } - -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) - for( i = 0, p = buf + 6; i < ciph_len; i += 3, p += 3 ) - { - if( p[0] == 0 && - p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && - p[2] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "received FALLBACK_SCSV" ) ); - - if( ssl->minor_ver < ssl->conf->max_minor_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); - - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); - - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - break; - } - } -#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ - - got_common_suite = 0; - ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; - ciphersuite_info = NULL; -#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) - for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) - for( i = 0; ciphersuites[i] != 0; i++ ) -#else - for( i = 0; ciphersuites[i] != 0; i++ ) - for( j = 0, p = buf + 6; j < ciph_len; j += 3, p += 3 ) -#endif - { - if( p[0] != 0 || - p[1] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || - p[2] != ( ( ciphersuites[i] ) & 0xFF ) ) - continue; - - got_common_suite = 1; - - if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], - &ciphersuite_info ) ) != 0 ) - return( ret ); - - if( ciphersuite_info != NULL ) - goto have_ciphersuite_v2; - } - - if( got_common_suite ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " - "but none of them usable" ) ); - return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); - return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); - } - -have_ciphersuite_v2: - MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); - - ssl->session_negotiate->ciphersuite = ciphersuites[i]; - ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; - - /* - * SSLv2 Client Hello relevant renegotiation security checks - */ - if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ssl->in_left = 0; - ssl->state++; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello v2" ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ - -/* This function doesn't alert on errors that happen early during - ClientHello parsing because they might indicate that the client is - not talking SSL/TLS at all and would not understand our alert. */ -static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) -{ - int ret, got_common_suite; - size_t i, j; - size_t ciph_offset, comp_offset, ext_offset; - size_t msg_len, ciph_len, sess_len, comp_len, ext_len; -#if defined(MBEDTLS_SSL_PROTO_DTLS) - size_t cookie_offset, cookie_len; -#endif - unsigned char *buf, *p, *ext; -#if defined(MBEDTLS_SSL_RENEGOTIATION) - int renegotiation_info_seen = 0; -#endif - int handshake_failure = 0; - const int *ciphersuites; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info; - int major, minor; - - /* If there is no signature-algorithm extension present, - * we need to fall back to the default values for allowed - * signature-hash pairs. */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - int sig_hash_alg_ext_present = 0; -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -read_record_header: -#endif - /* - * If renegotiating, then the input was read with mbedtls_ssl_read_record(), - * otherwise read it ourselves manually in order to support SSLv2 - * ClientHello, which doesn't use the same record layer format. - */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) -#endif - { - if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 ) - { - /* No alert on a read error. */ - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); - return( ret ); - } - } - - buf = ssl->in_hdr; - -#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM ) -#endif - if( ( buf[0] & 0x80 ) != 0 ) - return( ssl_parse_client_hello_v2( ssl ) ); -#endif - - MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_hdr_len( ssl ) ); - - /* - * SSLv3/TLS Client Hello - * - * Record layer: - * 0 . 0 message type - * 1 . 2 protocol version - * 3 . 11 DTLS: epoch + record sequence number - * 3 . 4 message length - */ - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message type: %d", - buf[0] ) ); - - if( buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, message len.: %d", - ( ssl->in_len[0] << 8 ) | ssl->in_len[1] ) ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, protocol version: [%d:%d]", - buf[1], buf[2] ) ); - - mbedtls_ssl_read_version( &major, &minor, ssl->conf->transport, buf + 1 ); - - /* According to RFC 5246 Appendix E.1, the version here is typically - * "{03,00}, the lowest version number supported by the client, [or] the - * value of ClientHello.client_version", so the only meaningful check here - * is the major version shouldn't be less than 3 */ - if( major < MBEDTLS_SSL_MAJOR_VERSION_3 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - /* For DTLS if this is the initial handshake, remember the client sequence - * number to use it in our next message (RFC 6347 4.2.1) */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM -#if defined(MBEDTLS_SSL_RENEGOTIATION) - && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE -#endif - ) - { - /* Epoch should be 0 for initial handshakes */ - if( ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - memcpy( ssl->out_ctr + 2, ssl->in_ctr + 2, 6 ); - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record, discarding" ) ); - ssl->next_record_offset = 0; - ssl->in_left = 0; - goto read_record_header; - } - - /* No MAC to check yet, so we can update right now */ - mbedtls_ssl_dtls_replay_update( ssl ); -#endif - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - msg_len = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) - { - /* Set by mbedtls_ssl_read_record() */ - msg_len = ssl->in_hslen; - } - else -#endif - { - if( msg_len > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - if( ( ret = mbedtls_ssl_fetch_input( ssl, - mbedtls_ssl_hdr_len( ssl ) + msg_len ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); - return( ret ); - } - - /* Done reading this record, get ready for the next one */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - ssl->next_record_offset = msg_len + mbedtls_ssl_hdr_len( ssl ); - else -#endif - ssl->in_left = 0; - } - - buf = ssl->in_msg; - - MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, msg_len ); - - ssl->handshake->update_checksum( ssl, buf, msg_len ); - - /* - * Handshake layer: - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 5 DTLS only: message seqence number - * 6 . 8 DTLS only: fragment offset - * 9 . 11 DTLS only: fragment length - */ - if( msg_len < mbedtls_ssl_hs_hdr_len( ssl ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d", buf[0] ) ); - - if( buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d", - ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) ); - - /* We don't support fragmentation of ClientHello (yet?) */ - if( buf[1] != 0 || - msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - /* - * Copy the client's handshake message_seq on initial handshakes, - * check sequence number on renego. - */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - { - /* This couldn't be done in ssl_prepare_handshake_record() */ - unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | - ssl->in_msg[5]; - - if( cli_msg_seq != ssl->handshake->in_msg_seq ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message_seq: " - "%d (expected %d)", cli_msg_seq, - ssl->handshake->in_msg_seq ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ssl->handshake->in_msg_seq++; - } - else -#endif - { - unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | - ssl->in_msg[5]; - ssl->handshake->out_msg_seq = cli_msg_seq; - ssl->handshake->in_msg_seq = cli_msg_seq + 1; - } - - /* - * For now we don't support fragmentation, so make sure - * fragment_offset == 0 and fragment_length == length - */ - if( ssl->in_msg[6] != 0 || ssl->in_msg[7] != 0 || ssl->in_msg[8] != 0 || - memcmp( ssl->in_msg + 1, ssl->in_msg + 9, 3 ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "ClientHello fragmentation not supported" ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - buf += mbedtls_ssl_hs_hdr_len( ssl ); - msg_len -= mbedtls_ssl_hs_hdr_len( ssl ); - - /* - * ClientHello layer: - * 0 . 1 protocol version - * 2 . 33 random bytes (starting with 4 bytes of Unix time) - * 34 . 35 session id length (1 byte) - * 35 . 34+x session id - * 35+x . 35+x DTLS only: cookie length (1 byte) - * 36+x . .. DTLS only: cookie - * .. . .. ciphersuite list length (2 bytes) - * .. . .. ciphersuite list - * .. . .. compression alg. list length (1 byte) - * .. . .. compression alg. list - * .. . .. extensions length (2 bytes, optional) - * .. . .. extensions (optional) - */ - - /* - * Minimal length (with everything empty and extensions ommitted) is - * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can - * read at least up to session id length without worrying. - */ - if( msg_len < 38 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - /* - * Check and save the protocol version - */ - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, version", buf, 2 ); - - mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, - ssl->conf->transport, buf ); - - ssl->handshake->max_major_ver = ssl->major_ver; - ssl->handshake->max_minor_ver = ssl->minor_ver; - - if( ssl->major_ver < ssl->conf->min_major_ver || - ssl->minor_ver < ssl->conf->min_minor_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" - " [%d:%d] < [%d:%d]", - ssl->major_ver, ssl->minor_ver, - ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); - return( MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION ); - } - - if( ssl->major_ver > ssl->conf->max_major_ver ) - { - ssl->major_ver = ssl->conf->max_major_ver; - ssl->minor_ver = ssl->conf->max_minor_ver; - } - else if( ssl->minor_ver > ssl->conf->max_minor_ver ) - ssl->minor_ver = ssl->conf->max_minor_ver; - - /* - * Save client random (inc. Unix time) - */ - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 2, 32 ); - - memcpy( ssl->handshake->randbytes, buf + 2, 32 ); - - /* - * Check the session ID length and save session ID - */ - sess_len = buf[34]; - - if( sess_len > sizeof( ssl->session_negotiate->id ) || - sess_len + 34 + 2 > msg_len ) /* 2 for cipherlist length field */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 35, sess_len ); - - ssl->session_negotiate->id_len = sess_len; - memset( ssl->session_negotiate->id, 0, - sizeof( ssl->session_negotiate->id ) ); - memcpy( ssl->session_negotiate->id, buf + 35, - ssl->session_negotiate->id_len ); - - /* - * Check the cookie length and content - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - cookie_offset = 35 + sess_len; - cookie_len = buf[cookie_offset]; - - if( cookie_offset + 1 + cookie_len + 2 > msg_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", - buf + cookie_offset + 1, cookie_len ); - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) - if( ssl->conf->f_cookie_check != NULL -#if defined(MBEDTLS_SSL_RENEGOTIATION) - && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE -#endif - ) - { - if( ssl->conf->f_cookie_check( ssl->conf->p_cookie, - buf + cookie_offset + 1, cookie_len, - ssl->cli_id, ssl->cli_id_len ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification failed" ) ); - ssl->handshake->verify_cookie_len = 1; - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification passed" ) ); - ssl->handshake->verify_cookie_len = 0; - } - } - else -#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ - { - /* We know we didn't send a cookie, so it should be empty */ - if( cookie_len != 0 ) - { - /* This may be an attacker's probe, so don't send an alert */ - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification skipped" ) ); - } - - /* - * Check the ciphersuitelist length (will be parsed later) - */ - ciph_offset = cookie_offset + 1 + cookie_len; - } - else -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - ciph_offset = 35 + sess_len; - - ciph_len = ( buf[ciph_offset + 0] << 8 ) - | ( buf[ciph_offset + 1] ); - - if( ciph_len < 2 || - ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */ - ( ciph_len % 2 ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", - buf + ciph_offset + 2, ciph_len ); - - /* - * Check the compression algorithms length and pick one - */ - comp_offset = ciph_offset + 2 + ciph_len; - - comp_len = buf[comp_offset]; - - if( comp_len < 1 || - comp_len > 16 || - comp_len + comp_offset + 1 > msg_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, compression", - buf + comp_offset + 1, comp_len ); - - ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; -#if defined(MBEDTLS_ZLIB_SUPPORT) - for( i = 0; i < comp_len; ++i ) - { - if( buf[comp_offset + 1 + i] == MBEDTLS_SSL_COMPRESS_DEFLATE ) - { - ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_DEFLATE; - break; - } - } -#endif - - /* See comments in ssl_write_client_hello() */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; -#endif - - /* Do not parse the extensions if the protocol is SSLv3 */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) - { -#endif - /* - * Check the extension length - */ - ext_offset = comp_offset + 1 + comp_len; - if( msg_len > ext_offset ) - { - if( msg_len < ext_offset + 2 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - ext_len = ( buf[ext_offset + 0] << 8 ) - | ( buf[ext_offset + 1] ); - - if( ( ext_len > 0 && ext_len < 4 ) || - msg_len != ext_offset + 2 + ext_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - } - else - ext_len = 0; - - ext = buf + ext_offset + 2; - MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", ext, ext_len ); - - while( ext_len != 0 ) - { - unsigned int ext_id = ( ( ext[0] << 8 ) - | ( ext[1] ) ); - unsigned int ext_size = ( ( ext[2] << 8 ) - | ( ext[3] ) ); - - if( ext_size + 4 > ext_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - switch( ext_id ) - { -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - case MBEDTLS_TLS_EXT_SERVERNAME: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) ); - if( ssl->conf->f_sni == NULL ) - break; - - ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - - case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); -#if defined(MBEDTLS_SSL_RENEGOTIATION) - renegotiation_info_seen = 1; -#endif - - ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - case MBEDTLS_TLS_EXT_SIG_ALG: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) ); -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - break; -#endif - ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - - sig_hash_alg_ext_present = 1; - break; -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - case MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) ); - - ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; - - case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) ); - ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT; - - ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || - MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake kkpp extension" ) ); - - ret = ssl_parse_ecjpake_kkpp( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) ); - - ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - case MBEDTLS_TLS_EXT_TRUNCATED_HMAC: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found truncated hmac extension" ) ); - - ret = ssl_parse_truncated_hmac_ext( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) ); - - ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) ); - - ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - case MBEDTLS_TLS_EXT_SESSION_TICKET: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) ); - - ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -#if defined(MBEDTLS_SSL_ALPN) - case MBEDTLS_TLS_EXT_ALPN: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); - - ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ); - if( ret != 0 ) - return( ret ); - break; -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - - default: - MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %d (ignoring)", - ext_id ) ); - } - - ext_len -= 4 + ext_size; - ext += 4 + ext_size; - - if( ext_len > 0 && ext_len < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - } -#if defined(MBEDTLS_SSL_PROTO_SSL3) - } -#endif - -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) - for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) - { - if( p[0] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE >> 8 ) & 0xff ) && - p[1] == (unsigned char)( ( MBEDTLS_SSL_FALLBACK_SCSV_VALUE ) & 0xff ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "received FALLBACK_SCSV" ) ); - - if( ssl->minor_ver < ssl->conf->max_minor_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "inapropriate fallback" ) ); - - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK ); - - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - break; - } - } -#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - - /* - * Try to fall back to default hash SHA1 if the client - * hasn't provided any preferred signature-hash combinations. - */ - if( sig_hash_alg_ext_present == 0 ) - { - mbedtls_md_type_t md_default = MBEDTLS_MD_SHA1; - - if( mbedtls_ssl_check_sig_hash( ssl, md_default ) != 0 ) - md_default = MBEDTLS_MD_NONE; - - mbedtls_ssl_sig_hash_set_const_hash( &ssl->handshake->hash_algs, md_default ); - } - -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ - - /* - * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV - */ - for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) - { - if( p[0] == 0 && p[1] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " - "during renegotiation" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } -#endif - ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; - break; - } - } - - /* - * Renegotiation security checks - */ - if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); - handshake_failure = 1; - } -#if defined(MBEDTLS_SSL_RENEGOTIATION) - else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && - ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && - renegotiation_info_seen == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); - handshake_failure = 1; - } - else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && - ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); - handshake_failure = 1; - } - else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && - ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - renegotiation_info_seen == 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); - handshake_failure = 1; - } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - - if( handshake_failure == 1 ) - { - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - /* - * Search for a matching ciphersuite - * (At the end because we need information from the EC-based extensions - * and certificate from the SNI callback triggered by the SNI extension.) - */ - got_common_suite = 0; - ciphersuites = ssl->conf->ciphersuite_list[ssl->minor_ver]; - ciphersuite_info = NULL; -#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) - for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) - for( i = 0; ciphersuites[i] != 0; i++ ) -#else - for( i = 0; ciphersuites[i] != 0; i++ ) - for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) -#endif - { - if( p[0] != ( ( ciphersuites[i] >> 8 ) & 0xFF ) || - p[1] != ( ( ciphersuites[i] ) & 0xFF ) ) - continue; - - got_common_suite = 1; - - if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], - &ciphersuite_info ) ) != 0 ) - return( ret ); - - if( ciphersuite_info != NULL ) - goto have_ciphersuite; - } - - if( got_common_suite ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " - "but none of them usable" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE ); - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); - return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); - } - -have_ciphersuite: - MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); - - ssl->session_negotiate->ciphersuite = ciphersuites[i]; - ssl->transform_negotiate->ciphersuite_info = ciphersuite_info; - - ssl->state++; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - mbedtls_ssl_recv_flight_completed( ssl ); -#endif - - /* Debugging-only output for testsuite */ -#if defined(MBEDTLS_DEBUG_C) && \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg( ciphersuite_info ); - if( sig_alg != MBEDTLS_PK_NONE ) - { - mbedtls_md_type_t md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, - sig_alg ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d", - mbedtls_ssl_hash_from_md_alg( md_alg ) ) ); - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "no hash algorithm for signature algorithm " - "%d - should not happen", sig_alg ) ); - } - } -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) ); - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -static void ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - - if( ssl->session_negotiate->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) - { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding truncated hmac extension" ) ); - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_TRUNCATED_HMAC ) & 0xFF ); - - *p++ = 0x00; - *p++ = 0x00; - - *olen = 4; -} -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) -static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - const mbedtls_ssl_ciphersuite_t *suite = NULL; - const mbedtls_cipher_info_t *cipher = NULL; - - if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_EXTENDED_MS_DISABLED || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - *olen = 0; - return; - } - - /* - * RFC 7366: "If a server receives an encrypt-then-MAC request extension - * from a client and then selects a stream or Authenticated Encryption - * with Associated Data (AEAD) ciphersuite, it MUST NOT send an - * encrypt-then-MAC response extension back to the client." - */ - if( ( suite = mbedtls_ssl_ciphersuite_from_id( - ssl->session_negotiate->ciphersuite ) ) == NULL || - ( cipher = mbedtls_cipher_info_from_type( suite->cipher ) ) == NULL || - cipher->mode != MBEDTLS_MODE_CBC ) - { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding encrypt then mac extension" ) ); - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC ) & 0xFF ); - - *p++ = 0x00; - *p++ = 0x00; - - *olen = 4; -} -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) -static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - - if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding extended master secret " - "extension" ) ); - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET ) & 0xFF ); - - *p++ = 0x00; - *p++ = 0x00; - - *olen = 4; -} -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - - if( ssl->handshake->new_session_ticket == 0 ) - { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding session ticket extension" ) ); - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SESSION_TICKET ) & 0xFF ); - - *p++ = 0x00; - *p++ = 0x00; - - *olen = 4; -} -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - - if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION ) - { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) ); - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO ) & 0xFF ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) - { - *p++ = 0x00; - *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF; - *p++ = ssl->verify_data_len * 2 & 0xFF; - - memcpy( p, ssl->peer_verify_data, ssl->verify_data_len ); - p += ssl->verify_data_len; - memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); - p += ssl->verify_data_len; - } - else -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - { - *p++ = 0x00; - *p++ = 0x01; - *p++ = 0x00; - } - - *olen = p - buf; -} - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - - if( ssl->session_negotiate->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) - { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) ); - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH ) & 0xFF ); - - *p++ = 0x00; - *p++ = 1; - - *p++ = ssl->session_negotiate->mfl_code; - - *olen = 5; -} -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - unsigned char *p = buf; - ((void) ssl); - - if( ( ssl->handshake->cli_exts & - MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT ) == 0 ) - { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, supported_point_formats extension" ) ); - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS ) & 0xFF ); - - *p++ = 0x00; - *p++ = 2; - - *p++ = 1; - *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; - - *olen = 6; -} -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, - size_t *olen ) -{ - int ret; - unsigned char *p = buf; - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - size_t kkpp_len; - - *olen = 0; - - /* Skip costly computation if not needed */ - if( ssl->transform_negotiate->ciphersuite_info->key_exchange != - MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - return; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, ecjpake kkpp extension" ) ); - - if( end - p < 4 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); - return; - } - - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( MBEDTLS_TLS_EXT_ECJPAKE_KKPP ) & 0xFF ); - - ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, - p + 2, end - p - 2, &kkpp_len, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret ); - return; - } - - *p++ = (unsigned char)( ( kkpp_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( kkpp_len ) & 0xFF ); - - *olen = kkpp_len + 4; -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_SSL_ALPN ) -static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, - unsigned char *buf, size_t *olen ) -{ - if( ssl->alpn_chosen == NULL ) - { - *olen = 0; - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding alpn extension" ) ); - - /* - * 0 . 1 ext identifier - * 2 . 3 ext length - * 4 . 5 protocol list length - * 6 . 6 protocol name length - * 7 . 7+n protocol name - */ - buf[0] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN >> 8 ) & 0xFF ); - buf[1] = (unsigned char)( ( MBEDTLS_TLS_EXT_ALPN ) & 0xFF ); - - *olen = 7 + strlen( ssl->alpn_chosen ); - - buf[2] = (unsigned char)( ( ( *olen - 4 ) >> 8 ) & 0xFF ); - buf[3] = (unsigned char)( ( ( *olen - 4 ) ) & 0xFF ); - - buf[4] = (unsigned char)( ( ( *olen - 6 ) >> 8 ) & 0xFF ); - buf[5] = (unsigned char)( ( ( *olen - 6 ) ) & 0xFF ); - - buf[6] = (unsigned char)( ( ( *olen - 7 ) ) & 0xFF ); - - memcpy( buf + 7, ssl->alpn_chosen, *olen - 7 ); -} -#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) -static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl ) -{ - int ret; - unsigned char *p = ssl->out_msg + 4; - unsigned char *cookie_len_byte; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello verify request" ) ); - - /* - * struct { - * ProtocolVersion server_version; - * opaque cookie<0..2^8-1>; - * } HelloVerifyRequest; - */ - - /* The RFC is not clear on this point, but sending the actual negotiated - * version looks like the most interoperable thing to do. */ - mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, - ssl->conf->transport, p ); - MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); - p += 2; - - /* If we get here, f_cookie_check is not null */ - if( ssl->conf->f_cookie_write == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "inconsistent cookie callbacks" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* Skip length byte until we know the length */ - cookie_len_byte = p++; - - if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie, - &p, ssl->out_buf + MBEDTLS_SSL_BUFFER_LEN, - ssl->cli_id, ssl->cli_id_len ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret ); - return( ret ); - } - - *cookie_len_byte = (unsigned char)( p - ( cookie_len_byte + 1 ) ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte ); - - ssl->out_msglen = p - ssl->out_msg; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; - - ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ - -static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) -{ -#if defined(MBEDTLS_HAVE_TIME) - mbedtls_time_t t; -#endif - int ret; - size_t olen, ext_len = 0, n; - unsigned char *buf, *p; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello" ) ); - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake->verify_cookie_len != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "client hello was not authenticated" ) ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); - - return( ssl_write_hello_verify_request( ssl ) ); - } -#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ - - if( ssl->conf->f_rng == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); - return( MBEDTLS_ERR_SSL_NO_RNG ); - } - - /* - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 5 protocol version - * 6 . 9 UNIX time() - * 10 . 37 random bytes - */ - buf = ssl->out_msg; - p = buf + 4; - - mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, - ssl->conf->transport, p ); - p += 2; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]", - buf[4], buf[5] ) ); - -#if defined(MBEDTLS_HAVE_TIME) - t = mbedtls_time( NULL ); - *p++ = (unsigned char)( t >> 24 ); - *p++ = (unsigned char)( t >> 16 ); - *p++ = (unsigned char)( t >> 8 ); - *p++ = (unsigned char)( t ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", t ) ); -#else - if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) - return( ret ); - - p += 4; -#endif /* MBEDTLS_HAVE_TIME */ - - if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) - return( ret ); - - p += 28; - - memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); - - /* - * Resume is 0 by default, see ssl_handshake_init(). - * It may be already set to 1 by ssl_parse_session_ticket_ext(). - * If not, try looking up session ID in our cache. - */ - if( ssl->handshake->resume == 0 && -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE && -#endif - ssl->session_negotiate->id_len != 0 && - ssl->conf->f_get_cache != NULL && - ssl->conf->f_get_cache( ssl->conf->p_cache, ssl->session_negotiate ) == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) ); - ssl->handshake->resume = 1; - } - - if( ssl->handshake->resume == 0 ) - { - /* - * New session, create a new session id, - * unless we're about to issue a session ticket - */ - ssl->state++; - -#if defined(MBEDTLS_HAVE_TIME) - ssl->session_negotiate->start = mbedtls_time( NULL ); -#endif - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - if( ssl->handshake->new_session_ticket != 0 ) - { - ssl->session_negotiate->id_len = n = 0; - memset( ssl->session_negotiate->id, 0, 32 ); - } - else -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - { - ssl->session_negotiate->id_len = n = 32; - if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, - n ) ) != 0 ) - return( ret ); - } - } - else - { - /* - * Resuming a session - */ - n = ssl->session_negotiate->id_len; - ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; - - if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); - return( ret ); - } - } - - /* - * 38 . 38 session id length - * 39 . 38+n session id - * 39+n . 40+n chosen ciphersuite - * 41+n . 41+n chosen compression alg. - * 42+n . 43+n extensions length - * 44+n . 43+n+m extensions - */ - *p++ = (unsigned char) ssl->session_negotiate->id_len; - memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len ); - p += ssl->session_negotiate->id_len; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %d", n ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", - ssl->handshake->resume ? "a" : "no" ) ); - - *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite >> 8 ); - *p++ = (unsigned char)( ssl->session_negotiate->ciphersuite ); - *p++ = (unsigned char)( ssl->session_negotiate->compression ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", - mbedtls_ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite ) ) ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X", - ssl->session_negotiate->compression ) ); - - /* Do not write the extensions if the protocol is SSLv3 */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ( ssl->major_ver != 3 ) || ( ssl->minor_ver != 0 ) ) - { -#endif - - /* - * First write extensions, then the total length - */ - ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - -#if defined(MBEDTLS_SSL_ALPN) - ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); - ext_len += olen; -#endif - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %d", ext_len ) ); - - if( ext_len > 0 ) - { - *p++ = (unsigned char)( ( ext_len >> 8 ) & 0xFF ); - *p++ = (unsigned char)( ( ext_len ) & 0xFF ); - p += ext_len; - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - } -#endif - - ssl->out_msglen = p - buf; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO; - - ret = mbedtls_ssl_write_record( ssl ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); - - return( ret ); -} - -#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) -{ - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); - ssl->state++; - return( 0 ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); -} -#else -static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->transform_negotiate->ciphersuite_info; - size_t dn_size, total_dn_size; /* excluding length bytes */ - size_t ct_len, sa_len; /* including length bytes */ - unsigned char *buf, *p; - const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - const mbedtls_x509_crt *crt; - int authmode; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); - - ssl->state++; - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) - authmode = ssl->handshake->sni_authmode; - else -#endif - authmode = ssl->conf->authmode; - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE || - authmode == MBEDTLS_SSL_VERIFY_NONE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); - return( 0 ); - } - - /* - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 4 cert type count - * 5 .. m-1 cert types - * m .. m+1 sig alg length (TLS 1.2 only) - * m+1 .. n-1 SignatureAndHashAlgorithms (TLS 1.2 only) - * n .. n+1 length of all DNs - * n+2 .. n+3 length of DN 1 - * n+4 .. ... Distinguished Name #1 - * ... .. ... length of DN 2, etc. - */ - buf = ssl->out_msg; - p = buf + 4; - - /* - * Supported certificate types - * - * ClientCertificateType certificate_types<1..2^8-1>; - * enum { (255) } ClientCertificateType; - */ - ct_len = 0; - -#if defined(MBEDTLS_RSA_C) - p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN; -#endif -#if defined(MBEDTLS_ECDSA_C) - p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN; -#endif - - p[0] = (unsigned char) ct_len++; - p += ct_len; - - sa_len = 0; -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - /* - * Add signature_algorithms for verify (TLS 1.2) - * - * SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>; - * - * struct { - * HashAlgorithm hash; - * SignatureAlgorithm signature; - * } SignatureAndHashAlgorithm; - * - * enum { (255) } HashAlgorithm; - * enum { (255) } SignatureAlgorithm; - */ - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - const int *cur; - - /* - * Supported signature algorithms - */ - for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) - { - unsigned char hash = mbedtls_ssl_hash_from_md_alg( *cur ); - - if( MBEDTLS_SSL_HASH_NONE == hash || mbedtls_ssl_set_calc_verify_md( ssl, hash ) ) - continue; - -#if defined(MBEDTLS_RSA_C) - p[2 + sa_len++] = hash; - p[2 + sa_len++] = MBEDTLS_SSL_SIG_RSA; -#endif -#if defined(MBEDTLS_ECDSA_C) - p[2 + sa_len++] = hash; - p[2 + sa_len++] = MBEDTLS_SSL_SIG_ECDSA; -#endif - } - - p[0] = (unsigned char)( sa_len >> 8 ); - p[1] = (unsigned char)( sa_len ); - sa_len += 2; - p += sa_len; - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - - /* - * DistinguishedName certificate_authorities<0..2^16-1>; - * opaque DistinguishedName<1..2^16-1>; - */ - p += 2; - - total_dn_size = 0; - - if( ssl->conf->cert_req_ca_list == MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED ) - { -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if( ssl->handshake->sni_ca_chain != NULL ) - crt = ssl->handshake->sni_ca_chain; - else -#endif - crt = ssl->conf->ca_chain; - - while( crt != NULL && crt->version != 0 ) - { - dn_size = crt->subject_raw.len; - - if( end < p || - (size_t)( end - p ) < dn_size || - (size_t)( end - p ) < 2 + dn_size ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) ); - break; - } - - *p++ = (unsigned char)( dn_size >> 8 ); - *p++ = (unsigned char)( dn_size ); - memcpy( p, crt->subject_raw.p, dn_size ); - p += dn_size; - - MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size ); - - total_dn_size += 2 + dn_size; - crt = crt->next; - } - } - - ssl->out_msglen = p - buf; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST; - ssl->out_msg[4 + ct_len + sa_len] = (unsigned char)( total_dn_size >> 8 ); - ssl->out_msg[5 + ct_len + sa_len] = (unsigned char)( total_dn_size ); - - ret = mbedtls_ssl_write_record( ssl ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) ); - - return( ret ); -} -#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) -{ - int ret; - - if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECKEY ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); - return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); - } - - if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, - mbedtls_pk_ec( *mbedtls_ssl_own_key( ssl ) ), - MBEDTLS_ECDH_OURS ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); - return( ret ); - } - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || - MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ - -static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) -{ - int ret; - size_t n = 0; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->transform_negotiate->ciphersuite_info; - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED) - unsigned char *p = ssl->out_msg + 4; - size_t len; -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) - unsigned char *dig_signed = p; - size_t dig_signed_len = 0; -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ -#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */ - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); - - /* - * - * Part 1: Extract static ECDH parameters and abort - * if ServerKeyExchange not needed. - * - */ - - /* For suites involving ECDH, extract DH parameters - * from certificate at this point. */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED) - if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) ) - { - ssl_get_ecdh_params_from_cert( ssl ); - } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */ - - /* Key exchanges not involving ephemeral keys don't use - * ServerKeyExchange, so end here. */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED) - if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); - ssl->state++; - return( 0 ); - } -#endif /* MBEDTLS_KEY_EXCHANGE__NON_PFS__ENABLED */ - - /* - * - * Part 2: Provide key exchange parameters for chosen ciphersuite. - * - */ - - /* - * - ECJPAKE key exchanges - */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN; - - ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, - p, end - p, &len, ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); - return( ret ); - } - - p += len; - n += len; - } -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - - /* - * For (EC)DHE key exchanges with PSK, parameters are prefixed by support - * identity hint (RFC 4279, Sec. 3). Until someone needs this feature, - * we use empty support identity hints here. - **/ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) - { - *(p++) = 0x00; - *(p++) = 0x00; - - n += 2; - } -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ - - /* - * - DHE key exchanges - */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED) - if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) ) - { - if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - /* - * Ephemeral DH parameters: - * - * struct { - * opaque dh_p<1..2^16-1>; - * opaque dh_g<1..2^16-1>; - * opaque dh_Ys<1..2^16-1>; - * } ServerDHParams; - */ - if( ( ret = mbedtls_mpi_copy( &ssl->handshake->dhm_ctx.P, &ssl->conf->dhm_P ) ) != 0 || - ( ret = mbedtls_mpi_copy( &ssl->handshake->dhm_ctx.G, &ssl->conf->dhm_G ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_mpi_copy", ret ); - return( ret ); - } - - if( ( ret = mbedtls_dhm_make_params( &ssl->handshake->dhm_ctx, - (int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ), - p, &len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret ); - return( ret ); - } - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) - dig_signed = p; - dig_signed_len = len; -#endif - - p += len; - n += len; - - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); - } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED */ - - /* - * - ECDHE key exchanges - */ -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED) - if( mbedtls_ssl_ciphersuite_uses_ecdhe( ciphersuite_info ) ) - { - /* - * Ephemeral ECDH parameters: - * - * struct { - * ECParameters curve_params; - * ECPoint public; - * } ServerECDHParams; - */ - const mbedtls_ecp_curve_info **curve = NULL; - const mbedtls_ecp_group_id *gid; - - /* Match our preference list against the offered curves */ - for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) - for( curve = ssl->handshake->curves; *curve != NULL; curve++ ) - if( (*curve)->grp_id == *gid ) - goto curve_matching_done; - -curve_matching_done: - if( curve == NULL || *curve == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "no matching curve for ECDHE" ) ); - return( MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) ); - - if( ( ret = mbedtls_ecp_group_load( &ssl->handshake->ecdh_ctx.grp, - (*curve)->grp_id ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret ); - return( ret ); - } - - if( ( ret = mbedtls_ecdh_make_params( &ssl->handshake->ecdh_ctx, &len, - p, MBEDTLS_SSL_MAX_CONTENT_LEN - n, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret ); - return( ret ); - } - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) - dig_signed = p; - dig_signed_len = len; -#endif - - p += len; - n += len; - - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q ); - } -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED */ - - /* - * - * Part 3: For key exchanges involving the server signing the - * exchange parameters, compute and add the signature here. - * - */ -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) - if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) - { - size_t signature_len = 0; - unsigned int hashlen = 0; - unsigned char hash[64]; - - /* - * 3.1: Choose hash algorithm: - * A: For TLS 1.2, obey signature-hash-algorithm extension - * to choose appropriate hash. - * B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1 - * (RFC 4492, Sec. 5.4) - * C: Otherwise, use MD5 + SHA1 (RFC 4346, Sec. 7.4.3) - */ - - mbedtls_md_type_t md_alg; - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - mbedtls_pk_type_t sig_alg = - mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - /* A: For TLS 1.2, obey signature-hash-algorithm extension - * (RFC 5246, Sec. 7.4.1.4.1). */ - if( sig_alg == MBEDTLS_PK_NONE || - ( md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, - sig_alg ) ) == MBEDTLS_MD_NONE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - /* (... because we choose a cipher suite - * only if there is a matching hash.) */ - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) - { - /* B: Default hash SHA1 */ - md_alg = MBEDTLS_MD_SHA1; - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ - MBEDTLS_SSL_PROTO_TLS1_1 */ - { - /* C: MD5 + SHA1 */ - md_alg = MBEDTLS_MD_NONE; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %d for signing", md_alg ) ); - - /* - * 3.2: Compute the hash to be signed - */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( md_alg == MBEDTLS_MD_NONE ) - { - mbedtls_md5_context mbedtls_md5; - mbedtls_sha1_context mbedtls_sha1; - - mbedtls_md5_init( &mbedtls_md5 ); - mbedtls_sha1_init( &mbedtls_sha1 ); - - /* - * digitally-signed struct { - * opaque md5_hash[16]; - * opaque sha_hash[20]; - * }; - * - * md5_hash - * MD5(ClientHello.random + ServerHello.random - * + ServerParams); - * sha_hash - * SHA(ClientHello.random + ServerHello.random - * + ServerParams); - */ - - mbedtls_md5_starts( &mbedtls_md5 ); - mbedtls_md5_update( &mbedtls_md5, ssl->handshake->randbytes, 64 ); - mbedtls_md5_update( &mbedtls_md5, dig_signed, dig_signed_len ); - mbedtls_md5_finish( &mbedtls_md5, hash ); - - mbedtls_sha1_starts( &mbedtls_sha1 ); - mbedtls_sha1_update( &mbedtls_sha1, ssl->handshake->randbytes, 64 ); - mbedtls_sha1_update( &mbedtls_sha1, dig_signed, dig_signed_len ); - mbedtls_sha1_finish( &mbedtls_sha1, hash + 16 ); - - hashlen = 36; - - mbedtls_md5_free( &mbedtls_md5 ); - mbedtls_sha1_free( &mbedtls_sha1 ); - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || \ - MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( md_alg != MBEDTLS_MD_NONE ) - { - mbedtls_md_context_t ctx; - const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); - - mbedtls_md_init( &ctx ); - - /* Info from md_alg will be used instead */ - hashlen = 0; - - /* - * digitally-signed struct { - * opaque client_random[32]; - * opaque server_random[32]; - * ServerDHParams params; - * }; - */ - if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); - return( ret ); - } - - mbedtls_md_starts( &ctx ); - mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ); - mbedtls_md_update( &ctx, dig_signed, dig_signed_len ); - mbedtls_md_finish( &ctx, hash ); - mbedtls_md_free( &ctx ); - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen : - (unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) ); - - /* - * 3.3: Compute and add the signature - */ - if( mbedtls_ssl_own_key( ssl ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) ); - return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); - } - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - /* - * For TLS 1.2, we need to specify signature and hash algorithm - * explicitly through a prefix to the signature. - * - * struct { - * HashAlgorithm hash; - * SignatureAlgorithm signature; - * } SignatureAndHashAlgorithm; - * - * struct { - * SignatureAndHashAlgorithm algorithm; - * opaque signature<0..2^16-1>; - * } DigitallySigned; - * - */ - - *(p++) = mbedtls_ssl_hash_from_md_alg( md_alg ); - *(p++) = mbedtls_ssl_sig_from_pk_alg( sig_alg ); - - n += 2; - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - - if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash, hashlen, - p + 2 , &signature_len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); - return( ret ); - } - - *(p++) = (unsigned char)( signature_len >> 8 ); - *(p++) = (unsigned char)( signature_len ); - n += 2; - - MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", p, signature_len ); - - n += signature_len; - } -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ - - /* Done with actual work; add header and send. */ - - ssl->out_msglen = 4 + n; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE; - - ssl->state++; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) ); - - return( 0 ); -} - -static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl ) -{ - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) ); - - ssl->out_msglen = 4; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO_DONE; - - ssl->state++; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - mbedtls_ssl_send_flight_completed( ssl ); -#endif - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) ); - - return( 0 ); -} - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) -static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char **p, - const unsigned char *end ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - size_t n; - - /* - * Receive G^Y mod P, premaster = (G^Y)^X mod P - */ - if( *p + 2 > end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - n = ( (*p)[0] << 8 ) | (*p)[1]; - *p += 2; - - if( *p + n > end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - if( ( ret = mbedtls_dhm_read_public( &ssl->handshake->dhm_ctx, *p, n ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_read_public", ret ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); - } - - *p += n; - - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); - - return( ret ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) -static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, - const unsigned char *p, - const unsigned char *end, - size_t pms_offset ) -{ - int ret; - size_t len = mbedtls_pk_get_len( mbedtls_ssl_own_key( ssl ) ); - unsigned char *pms = ssl->handshake->premaster + pms_offset; - unsigned char ver[2]; - unsigned char fake_pms[48], peer_pms[48]; - unsigned char mask; - size_t i, peer_pmslen; - unsigned int diff; - - if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); - return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); - } - - /* - * Decrypt the premaster using own private RSA key - */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) - { - if( *p++ != ( ( len >> 8 ) & 0xFF ) || - *p++ != ( ( len ) & 0xFF ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - } -#endif - - if( p + len != end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - mbedtls_ssl_write_version( ssl->handshake->max_major_ver, - ssl->handshake->max_minor_ver, - ssl->conf->transport, ver ); - - /* - * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding - * must not cause the connection to end immediately; instead, send a - * bad_record_mac later in the handshake. - * Also, avoid data-dependant branches here to protect against - * timing-based variants. - */ - ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) ); - if( ret != 0 ) - return( ret ); - - ret = mbedtls_pk_decrypt( mbedtls_ssl_own_key( ssl ), p, len, - peer_pms, &peer_pmslen, - sizeof( peer_pms ), - ssl->conf->f_rng, ssl->conf->p_rng ); - - diff = (unsigned int) ret; - diff |= peer_pmslen ^ 48; - diff |= peer_pms[0] ^ ver[0]; - diff |= peer_pms[1] ^ ver[1]; - -#if defined(MBEDTLS_SSL_DEBUG_ALL) - if( diff != 0 ) - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); -#endif - - if( sizeof( ssl->handshake->premaster ) < pms_offset || - sizeof( ssl->handshake->premaster ) - pms_offset < 48 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - ssl->handshake->pmslen = 48; - - /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */ - /* MSVC has a warning about unary minus on unsigned, but this is - * well-defined and precisely what we want to do here */ -#if defined(_MSC_VER) -#pragma warning( push ) -#pragma warning( disable : 4146 ) -#endif - mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) ); -#if defined(_MSC_VER) -#pragma warning( pop ) -#endif - - for( i = 0; i < ssl->handshake->pmslen; i++ ) - pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] ); - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned char **p, - const unsigned char *end ) -{ - int ret = 0; - size_t n; - - if( ssl->conf->f_psk == NULL && - ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL || - ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) ); - return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); - } - - /* - * Receive client pre-shared key identity name - */ - if( *p + 2 > end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - n = ( (*p)[0] << 8 ) | (*p)[1]; - *p += 2; - - if( n < 1 || n > 65535 || *p + n > end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - if( ssl->conf->f_psk != NULL ) - { - if( ssl->conf->f_psk( ssl->conf->p_psk, ssl, *p, n ) != 0 ) - ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; - } - else - { - /* Identity is not a big secret since clients send it in the clear, - * but treat it carefully anyway, just in case */ - if( n != ssl->conf->psk_identity_len || - mbedtls_ssl_safer_memcmp( ssl->conf->psk_identity, *p, n ) != 0 ) - { - ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; - } - } - - if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ) - { - MBEDTLS_SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ); - return( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ); - } - - *p += n; - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ - -static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) -{ - int ret; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info; - unsigned char *p, *end; - - ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) ); - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); - end = ssl->in_msg + ssl->in_hslen; - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) - { - if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); - return( ret ); - } - - if( p != end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, - ssl->handshake->premaster, - MBEDTLS_PREMASTER_SIZE, - &ssl->handshake->pmslen, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); - } - - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) - { - if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, - p, end - p) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); - } - - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); - - if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, - &ssl->handshake->pmslen, - ssl->handshake->premaster, - MBEDTLS_MPI_MAX_SIZE, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS ); - } - - MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z ", &ssl->handshake->ecdh_ctx.z ); - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || - MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) - { - if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); - return( ret ); - } - - if( p != end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, - ciphersuite_info->key_exchange ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) - { - if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); - return( ret ); - } - - if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret ); - return( ret ); - } - - if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, - ciphersuite_info->key_exchange ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) - { - if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); - return( ret ); - } - if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); - return( ret ); - } - - if( p != end ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); - } - - if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, - ciphersuite_info->key_exchange ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) - { - if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); - return( ret ); - } - - if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, - p, end - p ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); - } - - MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); - - if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, - ciphersuite_info->key_exchange ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) - { - if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 0 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_parse_encrypted_pms_secret" ), ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, - p, end - p ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); - return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE ); - } - - ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, - ssl->handshake->premaster, 32, &ssl->handshake->pmslen, - ssl->conf->f_rng, ssl->conf->p_rng ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); - return( ret ); - } - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); - return( ret ); - } - - ssl->state++; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) ); - - return( 0 ); -} - -#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) -static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) -{ - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); - ssl->state++; - return( 0 ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); -} -#else -static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - size_t i, sig_len; - unsigned char hash[48]; - unsigned char *hash_start = hash; - size_t hashlen; -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - mbedtls_pk_type_t pk_alg; -#endif - mbedtls_md_type_t md_alg; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = - ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE || - ssl->session_negotiate->peer_cert == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); - ssl->state++; - return( 0 ); - } - - /* Read the message without adding it to the checksum */ - do { - - if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); - return( ret ); - } - - ret = mbedtls_ssl_handle_message_type( ssl ); - - } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ); - - if( 0 != ret ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); - return( ret ); - } - - ssl->state++; - - /* Process the message contents */ - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || - ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); - } - - i = mbedtls_ssl_hs_hdr_len( ssl ); - - /* - * struct { - * SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only - * opaque signature<0..2^16-1>; - * } DigitallySigned; - */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) - { - md_alg = MBEDTLS_MD_NONE; - hashlen = 36; - - /* For ECDSA, use SHA-1, not MD-5 + SHA-1 */ - if( mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, - MBEDTLS_PK_ECDSA ) ) - { - hash_start += 16; - hashlen -= 16; - md_alg = MBEDTLS_MD_SHA1; - } - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 || MBEDTLS_SSL_PROTO_TLS1 || - MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - if( i + 2 > ssl->in_hslen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); - } - - /* - * Hash - */ - md_alg = mbedtls_ssl_md_alg_from_hash( ssl->in_msg[i] ); - - if( md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md( ssl, ssl->in_msg[i] ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" - " for verify message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); - } - -#if !defined(MBEDTLS_MD_SHA1) - if( MBEDTLS_MD_SHA1 == md_alg ) - hash_start += 16; -#endif - - /* Info from md_alg will be used instead */ - hashlen = 0; - - i++; - - /* - * Signature - */ - if( ( pk_alg = mbedtls_ssl_pk_alg_from_sig( ssl->in_msg[i] ) ) - == MBEDTLS_PK_NONE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" - " for verify message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); - } - - /* - * Check the certificate's key type matches the signature alg - */ - if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); - } - - i++; - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - if( i + 2 > ssl->in_hslen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); - } - - sig_len = ( ssl->in_msg[i] << 8 ) | ssl->in_msg[i+1]; - i += 2; - - if( i + sig_len != ssl->in_hslen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY ); - } - - /* Calculate hash and verify signature */ - ssl->handshake->calc_verify( ssl, hash ); - - if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, - md_alg, hash_start, hashlen, - ssl->in_msg + i, sig_len ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); - return( ret ); - } - - mbedtls_ssl_update_handshake_status( ssl ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) ); - - return( ret ); -} -#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED && - !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) -{ - int ret; - size_t tlen; - uint32_t lifetime; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write new session ticket" ) ); - - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_NEW_SESSION_TICKET; - - /* - * struct { - * uint32 ticket_lifetime_hint; - * opaque ticket<0..2^16-1>; - * } NewSessionTicket; - * - * 4 . 7 ticket_lifetime_hint (0 = unspecified) - * 8 . 9 ticket_len (n) - * 10 . 9+n ticket content - */ - - if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket, - ssl->session_negotiate, - ssl->out_msg + 10, - ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN, - &tlen, &lifetime ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret ); - tlen = 0; - } - - ssl->out_msg[4] = ( lifetime >> 24 ) & 0xFF; - ssl->out_msg[5] = ( lifetime >> 16 ) & 0xFF; - ssl->out_msg[6] = ( lifetime >> 8 ) & 0xFF; - ssl->out_msg[7] = ( lifetime ) & 0xFF; - - ssl->out_msg[8] = (unsigned char)( ( tlen >> 8 ) & 0xFF ); - ssl->out_msg[9] = (unsigned char)( ( tlen ) & 0xFF ); - - ssl->out_msglen = 10 + tlen; - - /* - * Morally equivalent to updating ssl->state, but NewSessionTicket and - * ChangeCipherSpec share the same state. - */ - ssl->handshake->new_session_ticket = 0; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -/* - * SSL handshake -- server side -- single step - */ -int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ) -{ - int ret = 0; - - if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER || ssl->handshake == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) ); - - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) - return( ret ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) - { - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) - return( ret ); - } -#endif - - switch( ssl->state ) - { - case MBEDTLS_SSL_HELLO_REQUEST: - ssl->state = MBEDTLS_SSL_CLIENT_HELLO; - break; - - /* - * <== ClientHello - */ - case MBEDTLS_SSL_CLIENT_HELLO: - ret = ssl_parse_client_hello( ssl ); - break; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: - return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); -#endif - - /* - * ==> ServerHello - * Certificate - * ( ServerKeyExchange ) - * ( CertificateRequest ) - * ServerHelloDone - */ - case MBEDTLS_SSL_SERVER_HELLO: - ret = ssl_write_server_hello( ssl ); - break; - - case MBEDTLS_SSL_SERVER_CERTIFICATE: - ret = mbedtls_ssl_write_certificate( ssl ); - break; - - case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: - ret = ssl_write_server_key_exchange( ssl ); - break; - - case MBEDTLS_SSL_CERTIFICATE_REQUEST: - ret = ssl_write_certificate_request( ssl ); - break; - - case MBEDTLS_SSL_SERVER_HELLO_DONE: - ret = ssl_write_server_hello_done( ssl ); - break; - - /* - * <== ( Certificate/Alert ) - * ClientKeyExchange - * ( CertificateVerify ) - * ChangeCipherSpec - * Finished - */ - case MBEDTLS_SSL_CLIENT_CERTIFICATE: - ret = mbedtls_ssl_parse_certificate( ssl ); - break; - - case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: - ret = ssl_parse_client_key_exchange( ssl ); - break; - - case MBEDTLS_SSL_CERTIFICATE_VERIFY: - ret = ssl_parse_certificate_verify( ssl ); - break; - - case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: - ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); - break; - - case MBEDTLS_SSL_CLIENT_FINISHED: - ret = mbedtls_ssl_parse_finished( ssl ); - break; - - /* - * ==> ( NewSessionTicket ) - * ChangeCipherSpec - * Finished - */ - case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - if( ssl->handshake->new_session_ticket != 0 ) - ret = ssl_write_new_session_ticket( ssl ); - else -#endif - ret = mbedtls_ssl_write_change_cipher_spec( ssl ); - break; - - case MBEDTLS_SSL_SERVER_FINISHED: - ret = mbedtls_ssl_write_finished( ssl ); - break; - - case MBEDTLS_SSL_FLUSH_BUFFERS: - MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); - ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; - break; - - case MBEDTLS_SSL_HANDSHAKE_WRAPUP: - mbedtls_ssl_handshake_wrapup( ssl ); - break; - - default: - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - return( ret ); -} -#endif /* MBEDTLS_SSL_SRV_C */ diff --git a/components/mbedtls/library/ssl_ticket.c b/components/mbedtls/library/ssl_ticket.c deleted file mode 100644 index 4d9116d214..0000000000 --- a/components/mbedtls/library/ssl_ticket.c +++ /dev/null @@ -1,489 +0,0 @@ -/* - * TLS server tickets callbacks implementation - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_SSL_TICKET_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include "mbedtls/ssl_ticket.h" - -#include - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * Initialze context - */ -void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_ssl_ticket_context ) ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_init( &ctx->mutex ); -#endif -} - -#define MAX_KEY_BYTES 32 /* 256 bits */ - -/* - * Generate/update a key - */ -static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, - unsigned char index ) -{ - int ret; - unsigned char buf[MAX_KEY_BYTES]; - mbedtls_ssl_ticket_key *key = ctx->keys + index; - -#if defined(MBEDTLS_HAVE_TIME) - key->generation_time = (uint32_t) mbedtls_time( NULL ); -#endif - - if( ( ret = ctx->f_rng( ctx->p_rng, key->name, sizeof( key->name ) ) ) != 0 ) - return( ret ); - - if( ( ret = ctx->f_rng( ctx->p_rng, buf, sizeof( buf ) ) ) != 0 ) - return( ret ); - - /* With GCM and CCM, same context can encrypt & decrypt */ - ret = mbedtls_cipher_setkey( &key->ctx, buf, - mbedtls_cipher_get_key_bitlen( &key->ctx ), - MBEDTLS_ENCRYPT ); - - mbedtls_zeroize( buf, sizeof( buf ) ); - - return( ret ); -} - -/* - * Rotate/generate keys if necessary - */ -static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) -{ -#if !defined(MBEDTLS_HAVE_TIME) - ((void) ctx); -#else - if( ctx->ticket_lifetime != 0 ) - { - uint32_t current_time = (uint32_t) mbedtls_time( NULL ); - uint32_t key_time = ctx->keys[ctx->active].generation_time; - - if( current_time > key_time && - current_time - key_time < ctx->ticket_lifetime ) - { - return( 0 ); - } - - ctx->active = 1 - ctx->active; - - return( ssl_ticket_gen_key( ctx, ctx->active ) ); - } - else -#endif /* MBEDTLS_HAVE_TIME */ - return( 0 ); -} - -/* - * Setup context for actual use - */ -int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - mbedtls_cipher_type_t cipher, - uint32_t lifetime ) -{ - int ret; - const mbedtls_cipher_info_t *cipher_info; - - ctx->f_rng = f_rng; - ctx->p_rng = p_rng; - - ctx->ticket_lifetime = lifetime; - - cipher_info = mbedtls_cipher_info_from_type( cipher); - if( cipher_info == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( cipher_info->mode != MBEDTLS_MODE_GCM && - cipher_info->mode != MBEDTLS_MODE_CCM ) - { - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - if( cipher_info->key_bitlen > 8 * MAX_KEY_BYTES ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 || - ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 || - ( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 ) - { - return( ret ); - } - - return( 0 ); -} - -/* - * Serialize a session in the following format: - * 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session) - * n . n+2 peer_cert length = m (0 if no certificate) - * n+3 . n+2+m peer cert ASN.1 - */ -static int ssl_save_session( const mbedtls_ssl_session *session, - unsigned char *buf, size_t buf_len, - size_t *olen ) -{ - unsigned char *p = buf; - size_t left = buf_len; -#if defined(MBEDTLS_X509_CRT_PARSE_C) - size_t cert_len; -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - if( left < sizeof( mbedtls_ssl_session ) ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - - memcpy( p, session, sizeof( mbedtls_ssl_session ) ); - p += sizeof( mbedtls_ssl_session ); - left -= sizeof( mbedtls_ssl_session ); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - if( session->peer_cert == NULL ) - cert_len = 0; - else - cert_len = session->peer_cert->raw.len; - - if( left < 3 + cert_len ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - - *p++ = (unsigned char)( cert_len >> 16 & 0xFF ); - *p++ = (unsigned char)( cert_len >> 8 & 0xFF ); - *p++ = (unsigned char)( cert_len & 0xFF ); - - if( session->peer_cert != NULL ) - memcpy( p, session->peer_cert->raw.p, cert_len ); - - p += cert_len; -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - *olen = p - buf; - - return( 0 ); -} - -/* - * Unserialise session, see ssl_save_session() - */ -static int ssl_load_session( mbedtls_ssl_session *session, - const unsigned char *buf, size_t len ) -{ - const unsigned char *p = buf; - const unsigned char * const end = buf + len; -#if defined(MBEDTLS_X509_CRT_PARSE_C) - size_t cert_len; -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - if( p + sizeof( mbedtls_ssl_session ) > end ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - memcpy( session, p, sizeof( mbedtls_ssl_session ) ); - p += sizeof( mbedtls_ssl_session ); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - if( p + 3 > end ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; - p += 3; - - if( cert_len == 0 ) - { - session->peer_cert = NULL; - } - else - { - int ret; - - if( p + cert_len > end ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); - - if( session->peer_cert == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - mbedtls_x509_crt_init( session->peer_cert ); - - if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert, - p, cert_len ) ) != 0 ) - { - mbedtls_x509_crt_free( session->peer_cert ); - mbedtls_free( session->peer_cert ); - session->peer_cert = NULL; - return( ret ); - } - - p += cert_len; - } -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - - if( p != end ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - return( 0 ); -} - -/* - * Create session ticket, with the following structure: - * - * struct { - * opaque key_name[4]; - * opaque iv[12]; - * opaque encrypted_state<0..2^16-1>; - * opaque tag[16]; - * } ticket; - * - * The key_name, iv, and length of encrypted_state are the additional - * authenticated data. - */ -int mbedtls_ssl_ticket_write( void *p_ticket, - const mbedtls_ssl_session *session, - unsigned char *start, - const unsigned char *end, - size_t *tlen, - uint32_t *ticket_lifetime ) -{ - int ret; - mbedtls_ssl_ticket_context *ctx = p_ticket; - mbedtls_ssl_ticket_key *key; - unsigned char *key_name = start; - unsigned char *iv = start + 4; - unsigned char *state_len_bytes = iv + 12; - unsigned char *state = state_len_bytes + 2; - unsigned char *tag; - size_t clear_len, ciph_len; - - *tlen = 0; - - if( ctx == NULL || ctx->f_rng == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag, - * in addition to session itself, that will be checked when writing it. */ - if( end - start < 4 + 12 + 2 + 16 ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) - goto cleanup; - - key = &ctx->keys[ctx->active]; - - *ticket_lifetime = ctx->ticket_lifetime; - - memcpy( key_name, key->name, 4 ); - - if( ( ret = ctx->f_rng( ctx->p_rng, iv, 12 ) ) != 0 ) - goto cleanup; - - /* Dump session state */ - if( ( ret = ssl_save_session( session, - state, end - state, &clear_len ) ) != 0 || - (unsigned long) clear_len > 65535 ) - { - goto cleanup; - } - state_len_bytes[0] = ( clear_len >> 8 ) & 0xff; - state_len_bytes[1] = ( clear_len ) & 0xff; - - /* Encrypt and authenticate */ - tag = state + clear_len; - if( ( ret = mbedtls_cipher_auth_encrypt( &key->ctx, - iv, 12, key_name, 4 + 12 + 2, - state, clear_len, state, &ciph_len, tag, 16 ) ) != 0 ) - { - goto cleanup; - } - if( ciph_len != clear_len ) - { - ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; - goto cleanup; - } - - *tlen = 4 + 12 + 2 + 16 + ciph_len; - -cleanup: -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -/* - * Select key based on name - */ -static mbedtls_ssl_ticket_key *ssl_ticket_select_key( - mbedtls_ssl_ticket_context *ctx, - const unsigned char name[4] ) -{ - unsigned char i; - - for( i = 0; i < sizeof( ctx->keys ) / sizeof( *ctx->keys ); i++ ) - if( memcmp( name, ctx->keys[i].name, 4 ) == 0 ) - return( &ctx->keys[i] ); - - return( NULL ); -} - -/* - * Load session ticket (see mbedtls_ssl_ticket_write for structure) - */ -int mbedtls_ssl_ticket_parse( void *p_ticket, - mbedtls_ssl_session *session, - unsigned char *buf, - size_t len ) -{ - int ret; - mbedtls_ssl_ticket_context *ctx = p_ticket; - mbedtls_ssl_ticket_key *key; - unsigned char *key_name = buf; - unsigned char *iv = buf + 4; - unsigned char *enc_len_p = iv + 12; - unsigned char *ticket = enc_len_p + 2; - unsigned char *tag; - size_t enc_len, clear_len; - - if( ctx == NULL || ctx->f_rng == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - /* See mbedtls_ssl_ticket_write() */ - if( len < 4 + 12 + 2 + 16 ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) - return( ret ); -#endif - - if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) - goto cleanup; - - enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1]; - tag = ticket + enc_len; - - if( len != 4 + 12 + 2 + enc_len + 16 ) - { - ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; - goto cleanup; - } - - /* Select key */ - if( ( key = ssl_ticket_select_key( ctx, key_name ) ) == NULL ) - { - /* We can't know for sure but this is a likely option unless we're - * under attack - this is only informative anyway */ - ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; - goto cleanup; - } - - /* Decrypt and authenticate */ - if( ( ret = mbedtls_cipher_auth_decrypt( &key->ctx, iv, 12, - key_name, 4 + 12 + 2, ticket, enc_len, - ticket, &clear_len, tag, 16 ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) - ret = MBEDTLS_ERR_SSL_INVALID_MAC; - - goto cleanup; - } - if( clear_len != enc_len ) - { - ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; - goto cleanup; - } - - /* Actually load session */ - if( ( ret = ssl_load_session( session, ticket, clear_len ) ) != 0 ) - goto cleanup; - -#if defined(MBEDTLS_HAVE_TIME) - { - /* Check for expiration */ - mbedtls_time_t current_time = mbedtls_time( NULL ); - - if( current_time < session->start || - (uint32_t)( current_time - session->start ) > ctx->ticket_lifetime ) - { - ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; - goto cleanup; - } - } -#endif - -cleanup: -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} - -/* - * Free context - */ -void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ) -{ - mbedtls_cipher_free( &ctx->keys[0].ctx ); - mbedtls_cipher_free( &ctx->keys[1].ctx ); - -#if defined(MBEDTLS_THREADING_C) - mbedtls_mutex_free( &ctx->mutex ); -#endif - - mbedtls_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) ); -} - -#endif /* MBEDTLS_SSL_TICKET_C */ diff --git a/components/mbedtls/library/ssl_tls.c b/components/mbedtls/library/ssl_tls.c deleted file mode 100644 index 661ae7065b..0000000000 --- a/components/mbedtls/library/ssl_tls.c +++ /dev/null @@ -1,8035 +0,0 @@ -/* - * SSLv3/TLSv1 shared functions - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The SSL 3.0 specification was drafted by Netscape in 1996, - * and became an IETF standard in 1999. - * - * http://wp.netscape.com/eng/ssl3/ - * http://www.ietf.org/rfc/rfc2246.txt - * http://www.ietf.org/rfc/rfc4346.txt - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_SSL_TLS_C) - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - -#include "mbedtls/debug.h" -#include "mbedtls/ssl.h" -#include "mbedtls/ssl_internal.h" - -#include - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -#include "mbedtls/oid.h" -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* Length of the "epoch" field in the record header */ -static inline size_t ssl_ep_len( const mbedtls_ssl_context *ssl ) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( 2 ); -#else - ((void) ssl); -#endif - return( 0 ); -} - -/* - * Start a timer. - * Passing millisecs = 0 cancels a running timer. - */ -static void ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs ) -{ - if( ssl->f_set_timer == NULL ) - return; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "set_timer to %d ms", (int) millisecs ) ); - ssl->f_set_timer( ssl->p_timer, millisecs / 4, millisecs ); -} - -/* - * Return -1 is timer is expired, 0 if it isn't. - */ -static int ssl_check_timer( mbedtls_ssl_context *ssl ) -{ - if( ssl->f_get_timer == NULL ) - return( 0 ); - - if( ssl->f_get_timer( ssl->p_timer ) == 2 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "timer expired" ) ); - return( -1 ); - } - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -/* - * Double the retransmit timeout value, within the allowed range, - * returning -1 if the maximum value has already been reached. - */ -static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl ) -{ - uint32_t new_timeout; - - if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max ) - return( -1 ); - - new_timeout = 2 * ssl->handshake->retransmit_timeout; - - /* Avoid arithmetic overflow and range overflow */ - if( new_timeout < ssl->handshake->retransmit_timeout || - new_timeout > ssl->conf->hs_timeout_max ) - { - new_timeout = ssl->conf->hs_timeout_max; - } - - ssl->handshake->retransmit_timeout = new_timeout; - MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", - ssl->handshake->retransmit_timeout ) ); - - return( 0 ); -} - -static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl ) -{ - ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min; - MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %d millisecs", - ssl->handshake->retransmit_timeout ) ); -} -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -/* - * Convert max_fragment_length codes to length. - * RFC 6066 says: - * enum{ - * 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255) - * } MaxFragmentLength; - * and we add 0 -> extension unused - */ -static unsigned int mfl_code_to_length[MBEDTLS_SSL_MAX_FRAG_LEN_INVALID] = -{ - MBEDTLS_SSL_MAX_CONTENT_LEN, /* MBEDTLS_SSL_MAX_FRAG_LEN_NONE */ - 512, /* MBEDTLS_SSL_MAX_FRAG_LEN_512 */ - 1024, /* MBEDTLS_SSL_MAX_FRAG_LEN_1024 */ - 2048, /* MBEDTLS_SSL_MAX_FRAG_LEN_2048 */ - 4096, /* MBEDTLS_SSL_MAX_FRAG_LEN_4096 */ -}; -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_CLI_C) -static int ssl_session_copy( mbedtls_ssl_session *dst, const mbedtls_ssl_session *src ) -{ - mbedtls_ssl_session_free( dst ); - memcpy( dst, src, sizeof( mbedtls_ssl_session ) ); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - if( src->peer_cert != NULL ) - { - int ret; - - dst->peer_cert = mbedtls_calloc( 1, sizeof(mbedtls_x509_crt) ); - if( dst->peer_cert == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - mbedtls_x509_crt_init( dst->peer_cert ); - - if( ( ret = mbedtls_x509_crt_parse_der( dst->peer_cert, src->peer_cert->raw.p, - src->peer_cert->raw.len ) ) != 0 ) - { - mbedtls_free( dst->peer_cert ); - dst->peer_cert = NULL; - return( ret ); - } - } -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) - if( src->ticket != NULL ) - { - dst->ticket = mbedtls_calloc( 1, src->ticket_len ); - if( dst->ticket == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - memcpy( dst->ticket, src->ticket, src->ticket_len ); - } -#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ - - return( 0 ); -} -#endif /* MBEDTLS_SSL_CLI_C */ - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) -int (*mbedtls_ssl_hw_record_init)( mbedtls_ssl_context *ssl, - const unsigned char *key_enc, const unsigned char *key_dec, - size_t keylen, - const unsigned char *iv_enc, const unsigned char *iv_dec, - size_t ivlen, - const unsigned char *mac_enc, const unsigned char *mac_dec, - size_t maclen ) = NULL; -int (*mbedtls_ssl_hw_record_activate)( mbedtls_ssl_context *ssl, int direction) = NULL; -int (*mbedtls_ssl_hw_record_reset)( mbedtls_ssl_context *ssl ) = NULL; -int (*mbedtls_ssl_hw_record_write)( mbedtls_ssl_context *ssl ) = NULL; -int (*mbedtls_ssl_hw_record_read)( mbedtls_ssl_context *ssl ) = NULL; -int (*mbedtls_ssl_hw_record_finish)( mbedtls_ssl_context *ssl ) = NULL; -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ - -/* - * Key material generation - */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) -static int ssl3_prf( const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen ) -{ - size_t i; - mbedtls_md5_context md5; - mbedtls_sha1_context sha1; - unsigned char padding[16]; - unsigned char sha1sum[20]; - ((void)label); - - mbedtls_md5_init( &md5 ); - mbedtls_sha1_init( &sha1 ); - - /* - * SSLv3: - * block = - * MD5( secret + SHA1( 'A' + secret + random ) ) + - * MD5( secret + SHA1( 'BB' + secret + random ) ) + - * MD5( secret + SHA1( 'CCC' + secret + random ) ) + - * ... - */ - for( i = 0; i < dlen / 16; i++ ) - { - memset( padding, (unsigned char) ('A' + i), 1 + i ); - - mbedtls_sha1_starts( &sha1 ); - mbedtls_sha1_update( &sha1, padding, 1 + i ); - mbedtls_sha1_update( &sha1, secret, slen ); - mbedtls_sha1_update( &sha1, random, rlen ); - mbedtls_sha1_finish( &sha1, sha1sum ); - - mbedtls_md5_starts( &md5 ); - mbedtls_md5_update( &md5, secret, slen ); - mbedtls_md5_update( &md5, sha1sum, 20 ); - mbedtls_md5_finish( &md5, dstbuf + i * 16 ); - } - - mbedtls_md5_free( &md5 ); - mbedtls_sha1_free( &sha1 ); - - mbedtls_zeroize( padding, sizeof( padding ) ); - mbedtls_zeroize( sha1sum, sizeof( sha1sum ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -static int tls1_prf( const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen ) -{ - size_t nb, hs; - size_t i, j, k; - const unsigned char *S1, *S2; - unsigned char tmp[128]; - unsigned char h_i[20]; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - int ret; - - mbedtls_md_init( &md_ctx ); - - if( sizeof( tmp ) < 20 + strlen( label ) + rlen ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - hs = ( slen + 1 ) / 2; - S1 = secret; - S2 = secret + slen - hs; - - nb = strlen( label ); - memcpy( tmp + 20, label, nb ); - memcpy( tmp + 20 + nb, random, rlen ); - nb += rlen; - - /* - * First compute P_md5(secret,label+random)[0..dlen] - */ - if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ) ) == NULL ) - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - - if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) - return( ret ); - - mbedtls_md_hmac_starts( &md_ctx, S1, hs ); - mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); - mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); - - for( i = 0; i < dlen; i += 16 ) - { - mbedtls_md_hmac_reset ( &md_ctx ); - mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 + nb ); - mbedtls_md_hmac_finish( &md_ctx, h_i ); - - mbedtls_md_hmac_reset ( &md_ctx ); - mbedtls_md_hmac_update( &md_ctx, 4 + tmp, 16 ); - mbedtls_md_hmac_finish( &md_ctx, 4 + tmp ); - - k = ( i + 16 > dlen ) ? dlen % 16 : 16; - - for( j = 0; j < k; j++ ) - dstbuf[i + j] = h_i[j]; - } - - mbedtls_md_free( &md_ctx ); - - /* - * XOR out with P_sha1(secret,label+random)[0..dlen] - */ - if( ( md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ) ) == NULL ) - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - - if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) - return( ret ); - - mbedtls_md_hmac_starts( &md_ctx, S2, hs ); - mbedtls_md_hmac_update( &md_ctx, tmp + 20, nb ); - mbedtls_md_hmac_finish( &md_ctx, tmp ); - - for( i = 0; i < dlen; i += 20 ) - { - mbedtls_md_hmac_reset ( &md_ctx ); - mbedtls_md_hmac_update( &md_ctx, tmp, 20 + nb ); - mbedtls_md_hmac_finish( &md_ctx, h_i ); - - mbedtls_md_hmac_reset ( &md_ctx ); - mbedtls_md_hmac_update( &md_ctx, tmp, 20 ); - mbedtls_md_hmac_finish( &md_ctx, tmp ); - - k = ( i + 20 > dlen ) ? dlen % 20 : 20; - - for( j = 0; j < k; j++ ) - dstbuf[i + j] = (unsigned char)( dstbuf[i + j] ^ h_i[j] ); - } - - mbedtls_md_free( &md_ctx ); - - mbedtls_zeroize( tmp, sizeof( tmp ) ); - mbedtls_zeroize( h_i, sizeof( h_i ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_PROTO_TLS1) || MBEDTLS_SSL_PROTO_TLS1_1 */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -static int tls_prf_generic( mbedtls_md_type_t md_type, - const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen ) -{ - size_t nb; - size_t i, j, k, md_len; - unsigned char tmp[128]; - unsigned char h_i[MBEDTLS_MD_MAX_SIZE]; - const mbedtls_md_info_t *md_info; - mbedtls_md_context_t md_ctx; - int ret; - - mbedtls_md_init( &md_ctx ); - - if( ( md_info = mbedtls_md_info_from_type( md_type ) ) == NULL ) - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - - md_len = mbedtls_md_get_size( md_info ); - - if( sizeof( tmp ) < md_len + strlen( label ) + rlen ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - nb = strlen( label ); - memcpy( tmp + md_len, label, nb ); - memcpy( tmp + md_len + nb, random, rlen ); - nb += rlen; - - /* - * Compute P_(secret, label + random)[0..dlen] - */ - if ( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) - return( ret ); - - mbedtls_md_hmac_starts( &md_ctx, secret, slen ); - mbedtls_md_hmac_update( &md_ctx, tmp + md_len, nb ); - mbedtls_md_hmac_finish( &md_ctx, tmp ); - - for( i = 0; i < dlen; i += md_len ) - { - mbedtls_md_hmac_reset ( &md_ctx ); - mbedtls_md_hmac_update( &md_ctx, tmp, md_len + nb ); - mbedtls_md_hmac_finish( &md_ctx, h_i ); - - mbedtls_md_hmac_reset ( &md_ctx ); - mbedtls_md_hmac_update( &md_ctx, tmp, md_len ); - mbedtls_md_hmac_finish( &md_ctx, tmp ); - - k = ( i + md_len > dlen ) ? dlen % md_len : md_len; - - for( j = 0; j < k; j++ ) - dstbuf[i + j] = h_i[j]; - } - - mbedtls_md_free( &md_ctx ); - - mbedtls_zeroize( tmp, sizeof( tmp ) ); - mbedtls_zeroize( h_i, sizeof( h_i ) ); - - return( 0 ); -} - -#if defined(MBEDTLS_SHA256_C) -static int tls_prf_sha256( const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen ) -{ - return( tls_prf_generic( MBEDTLS_MD_SHA256, secret, slen, - label, random, rlen, dstbuf, dlen ) ); -} -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) -static int tls_prf_sha384( const unsigned char *secret, size_t slen, - const char *label, - const unsigned char *random, size_t rlen, - unsigned char *dstbuf, size_t dlen ) -{ - return( tls_prf_generic( MBEDTLS_MD_SHA384, secret, slen, - label, random, rlen, dstbuf, dlen ) ); -} -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -static void ssl_update_checksum_start( mbedtls_ssl_context *, const unsigned char *, size_t ); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) -static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *, const unsigned char *, size_t ); -#endif - -#if defined(MBEDTLS_SSL_PROTO_SSL3) -static void ssl_calc_verify_ssl( mbedtls_ssl_context *, unsigned char * ); -static void ssl_calc_finished_ssl( mbedtls_ssl_context *, unsigned char *, int ); -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -static void ssl_calc_verify_tls( mbedtls_ssl_context *, unsigned char * ); -static void ssl_calc_finished_tls( mbedtls_ssl_context *, unsigned char *, int ); -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -static void ssl_update_checksum_sha256( mbedtls_ssl_context *, const unsigned char *, size_t ); -static void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *,unsigned char * ); -static void ssl_calc_finished_tls_sha256( mbedtls_ssl_context *,unsigned char *, int ); -#endif - -#if defined(MBEDTLS_SHA512_C) -static void ssl_update_checksum_sha384( mbedtls_ssl_context *, const unsigned char *, size_t ); -static void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *, unsigned char * ); -static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *, int ); -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) -{ - int ret = 0; - unsigned char tmp[64]; - unsigned char keyblk[256]; - unsigned char *key1; - unsigned char *key2; - unsigned char *mac_enc; - unsigned char *mac_dec; - size_t iv_copy_len; - const mbedtls_cipher_info_t *cipher_info; - const mbedtls_md_info_t *md_info; - - mbedtls_ssl_session *session = ssl->session_negotiate; - mbedtls_ssl_transform *transform = ssl->transform_negotiate; - mbedtls_ssl_handshake_params *handshake = ssl->handshake; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> derive keys" ) ); - - cipher_info = mbedtls_cipher_info_from_type( transform->ciphersuite_info->cipher ); - if( cipher_info == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %d not found", - transform->ciphersuite_info->cipher ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - md_info = mbedtls_md_info_from_type( transform->ciphersuite_info->mac ); - if( md_info == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "mbedtls_md info for %d not found", - transform->ciphersuite_info->mac ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - /* - * Set appropriate PRF function and other SSL / TLS / TLS1.2 functions - */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - handshake->tls_prf = ssl3_prf; - handshake->calc_verify = ssl_calc_verify_ssl; - handshake->calc_finished = ssl_calc_finished_ssl; - } - else -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) - { - handshake->tls_prf = tls1_prf; - handshake->calc_verify = ssl_calc_verify_tls; - handshake->calc_finished = ssl_calc_finished_tls; - } - else -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA512_C) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && - transform->ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) - { - handshake->tls_prf = tls_prf_sha384; - handshake->calc_verify = ssl_calc_verify_tls_sha384; - handshake->calc_finished = ssl_calc_finished_tls_sha384; - } - else -#endif -#if defined(MBEDTLS_SHA256_C) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - handshake->tls_prf = tls_prf_sha256; - handshake->calc_verify = ssl_calc_verify_tls_sha256; - handshake->calc_finished = ssl_calc_finished_tls_sha256; - } - else -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* - * SSLv3: - * master = - * MD5( premaster + SHA1( 'A' + premaster + randbytes ) ) + - * MD5( premaster + SHA1( 'BB' + premaster + randbytes ) ) + - * MD5( premaster + SHA1( 'CCC' + premaster + randbytes ) ) - * - * TLSv1+: - * master = PRF( premaster, "master secret", randbytes )[0..47] - */ - if( handshake->resume == 0 ) - { - MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster, - handshake->pmslen ); - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) - { - unsigned char session_hash[48]; - size_t hash_len; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); - - ssl->handshake->calc_verify( ssl, session_hash ); - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { -#if defined(MBEDTLS_SHA512_C) - if( ssl->transform_negotiate->ciphersuite_info->mac == - MBEDTLS_MD_SHA384 ) - { - hash_len = 48; - } - else -#endif - hash_len = 32; - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - hash_len = 36; - - MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, hash_len ); - - ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, - "extended master secret", - session_hash, hash_len, - session->master, 48 ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); - return( ret ); - } - - } - else -#endif - ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, - "master secret", - handshake->randbytes, 64, - session->master, 48 ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); - return( ret ); - } - - mbedtls_zeroize( handshake->premaster, sizeof(handshake->premaster) ); - } - else - MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); - - /* - * Swap the client and server random values. - */ - memcpy( tmp, handshake->randbytes, 64 ); - memcpy( handshake->randbytes, tmp + 32, 32 ); - memcpy( handshake->randbytes + 32, tmp, 32 ); - mbedtls_zeroize( tmp, sizeof( tmp ) ); - - /* - * SSLv3: - * key block = - * MD5( master + SHA1( 'A' + master + randbytes ) ) + - * MD5( master + SHA1( 'BB' + master + randbytes ) ) + - * MD5( master + SHA1( 'CCC' + master + randbytes ) ) + - * MD5( master + SHA1( 'DDDD' + master + randbytes ) ) + - * ... - * - * TLSv1: - * key block = PRF( master, "key expansion", randbytes ) - */ - ret = handshake->tls_prf( session->master, 48, "key expansion", - handshake->randbytes, 64, keyblk, 256 ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", - mbedtls_ssl_get_ciphersuite_name( session->ciphersuite ) ) ); - MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", session->master, 48 ); - MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", handshake->randbytes, 64 ); - MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); - - mbedtls_zeroize( handshake->randbytes, sizeof( handshake->randbytes ) ); - - /* - * Determine the appropriate key, IV and MAC length. - */ - - transform->keylen = cipher_info->key_bitlen / 8; - - if( cipher_info->mode == MBEDTLS_MODE_GCM || - cipher_info->mode == MBEDTLS_MODE_CCM ) - { - transform->maclen = 0; - - transform->ivlen = 12; - transform->fixed_ivlen = 4; - - /* Minimum length is expicit IV + tag */ - transform->minlen = transform->ivlen - transform->fixed_ivlen - + ( transform->ciphersuite_info->flags & - MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16 ); - } - else - { - /* Initialize HMAC contexts */ - if( ( ret = mbedtls_md_setup( &transform->md_ctx_enc, md_info, 1 ) ) != 0 || - ( ret = mbedtls_md_setup( &transform->md_ctx_dec, md_info, 1 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); - return( ret ); - } - - /* Get MAC length */ - transform->maclen = mbedtls_md_get_size( md_info ); - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - /* - * If HMAC is to be truncated, we shall keep the leftmost bytes, - * (rfc 6066 page 13 or rfc 2104 section 4), - * so we only need to adjust the length here. - */ - if( session->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_ENABLED ) - transform->maclen = MBEDTLS_SSL_TRUNCATED_HMAC_LEN; -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - - /* IV length */ - transform->ivlen = cipher_info->iv_size; - - /* Minimum length */ - if( cipher_info->mode == MBEDTLS_MODE_STREAM ) - transform->minlen = transform->maclen; - else - { - /* - * GenericBlockCipher: - * 1. if EtM is in use: one block plus MAC - * otherwise: * first multiple of blocklen greater than maclen - * 2. IV except for SSL3 and TLS 1.0 - */ -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - if( session->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) - { - transform->minlen = transform->maclen - + cipher_info->block_size; - } - else -#endif - { - transform->minlen = transform->maclen - + cipher_info->block_size - - transform->maclen % cipher_info->block_size; - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_1 ) - ; /* No need to adjust minlen */ - else -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_2 || - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - transform->minlen += transform->ivlen; - } - else -#endif - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "keylen: %d, minlen: %d, ivlen: %d, maclen: %d", - transform->keylen, transform->minlen, transform->ivlen, - transform->maclen ) ); - - /* - * Finally setup the cipher contexts, IVs and MAC secrets. - */ -#if defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - { - key1 = keyblk + transform->maclen * 2; - key2 = keyblk + transform->maclen * 2 + transform->keylen; - - mac_enc = keyblk; - mac_dec = keyblk + transform->maclen; - - /* - * This is not used in TLS v1.1. - */ - iv_copy_len = ( transform->fixed_ivlen ) ? - transform->fixed_ivlen : transform->ivlen; - memcpy( transform->iv_enc, key2 + transform->keylen, iv_copy_len ); - memcpy( transform->iv_dec, key2 + transform->keylen + iv_copy_len, - iv_copy_len ); - } - else -#endif /* MBEDTLS_SSL_CLI_C */ -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - { - key1 = keyblk + transform->maclen * 2 + transform->keylen; - key2 = keyblk + transform->maclen * 2; - - mac_enc = keyblk + transform->maclen; - mac_dec = keyblk; - - /* - * This is not used in TLS v1.1. - */ - iv_copy_len = ( transform->fixed_ivlen ) ? - transform->fixed_ivlen : transform->ivlen; - memcpy( transform->iv_dec, key1 + transform->keylen, iv_copy_len ); - memcpy( transform->iv_enc, key1 + transform->keylen + iv_copy_len, - iv_copy_len ); - } - else -#endif /* MBEDTLS_SSL_SRV_C */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - if( transform->maclen > sizeof transform->mac_enc ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - memcpy( transform->mac_enc, mac_enc, transform->maclen ); - memcpy( transform->mac_dec, mac_dec, transform->maclen ); - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) - { - mbedtls_md_hmac_starts( &transform->md_ctx_enc, mac_enc, transform->maclen ); - mbedtls_md_hmac_starts( &transform->md_ctx_dec, mac_dec, transform->maclen ); - } - else -#endif - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_init != NULL ) - { - int ret = 0; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_init()" ) ); - - if( ( ret = mbedtls_ssl_hw_record_init( ssl, key1, key2, transform->keylen, - transform->iv_enc, transform->iv_dec, - iv_copy_len, - mac_enc, mac_dec, - transform->maclen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_init", ret ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - } -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ - -#if defined(MBEDTLS_SSL_EXPORT_KEYS) - if( ssl->conf->f_export_keys != NULL ) - { - ssl->conf->f_export_keys( ssl->conf->p_export_keys, - session->master, keyblk, - transform->maclen, transform->keylen, - iv_copy_len ); - } -#endif - - if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc, - cipher_info ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); - return( ret ); - } - - if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec, - cipher_info ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); - return( ret ); - } - - if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_enc, key1, - cipher_info->key_bitlen, - MBEDTLS_ENCRYPT ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); - return( ret ); - } - - if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_dec, key2, - cipher_info->key_bitlen, - MBEDTLS_DECRYPT ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); - return( ret ); - } - -#if defined(MBEDTLS_CIPHER_MODE_CBC) - if( cipher_info->mode == MBEDTLS_MODE_CBC ) - { - if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_enc, - MBEDTLS_PADDING_NONE ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); - return( ret ); - } - - if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_dec, - MBEDTLS_PADDING_NONE ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); - return( ret ); - } - } -#endif /* MBEDTLS_CIPHER_MODE_CBC */ - - mbedtls_zeroize( keyblk, sizeof( keyblk ) ); - -#if defined(MBEDTLS_ZLIB_SUPPORT) - // Initialize compression - // - if( session->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) - { - if( ssl->compress_buf == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "Allocating compression buffer" ) ); - ssl->compress_buf = mbedtls_calloc( 1, MBEDTLS_SSL_BUFFER_LEN ); - if( ssl->compress_buf == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", - MBEDTLS_SSL_BUFFER_LEN ) ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "Initializing zlib states" ) ); - - memset( &transform->ctx_deflate, 0, sizeof( transform->ctx_deflate ) ); - memset( &transform->ctx_inflate, 0, sizeof( transform->ctx_inflate ) ); - - if( deflateInit( &transform->ctx_deflate, - Z_DEFAULT_COMPRESSION ) != Z_OK || - inflateInit( &transform->ctx_inflate ) != Z_OK ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to initialize compression" ) ); - return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); - } - } -#endif /* MBEDTLS_ZLIB_SUPPORT */ - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= derive keys" ) ); - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_PROTO_SSL3) -void ssl_calc_verify_ssl( mbedtls_ssl_context *ssl, unsigned char hash[36] ) -{ - mbedtls_md5_context md5; - mbedtls_sha1_context sha1; - unsigned char pad_1[48]; - unsigned char pad_2[48]; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify ssl" ) ); - - mbedtls_md5_init( &md5 ); - mbedtls_sha1_init( &sha1 ); - - mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); - mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); - - memset( pad_1, 0x36, 48 ); - memset( pad_2, 0x5C, 48 ); - - mbedtls_md5_update( &md5, ssl->session_negotiate->master, 48 ); - mbedtls_md5_update( &md5, pad_1, 48 ); - mbedtls_md5_finish( &md5, hash ); - - mbedtls_md5_starts( &md5 ); - mbedtls_md5_update( &md5, ssl->session_negotiate->master, 48 ); - mbedtls_md5_update( &md5, pad_2, 48 ); - mbedtls_md5_update( &md5, hash, 16 ); - mbedtls_md5_finish( &md5, hash ); - - mbedtls_sha1_update( &sha1, ssl->session_negotiate->master, 48 ); - mbedtls_sha1_update( &sha1, pad_1, 40 ); - mbedtls_sha1_finish( &sha1, hash + 16 ); - - mbedtls_sha1_starts( &sha1 ); - mbedtls_sha1_update( &sha1, ssl->session_negotiate->master, 48 ); - mbedtls_sha1_update( &sha1, pad_2, 40 ); - mbedtls_sha1_update( &sha1, hash + 16, 20 ); - mbedtls_sha1_finish( &sha1, hash + 16 ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); - - mbedtls_md5_free( &md5 ); - mbedtls_sha1_free( &sha1 ); - - return; -} -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -void ssl_calc_verify_tls( mbedtls_ssl_context *ssl, unsigned char hash[36] ) -{ - mbedtls_md5_context md5; - mbedtls_sha1_context sha1; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify tls" ) ); - - mbedtls_md5_init( &md5 ); - mbedtls_sha1_init( &sha1 ); - - mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); - mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); - - mbedtls_md5_finish( &md5, hash ); - mbedtls_sha1_finish( &sha1, hash + 16 ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 36 ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); - - mbedtls_md5_free( &md5 ); - mbedtls_sha1_free( &sha1 ); - - return; -} -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -void ssl_calc_verify_tls_sha256( mbedtls_ssl_context *ssl, unsigned char hash[32] ) -{ - mbedtls_sha256_context sha256; - - mbedtls_sha256_init( &sha256 ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) ); - - mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); - mbedtls_sha256_finish( &sha256, hash ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 32 ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); - - mbedtls_sha256_free( &sha256 ); - - return; -} -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) -void ssl_calc_verify_tls_sha384( mbedtls_ssl_context *ssl, unsigned char hash[48] ) -{ - mbedtls_sha512_context sha512; - - mbedtls_sha512_init( &sha512 ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) ); - - mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); - mbedtls_sha512_finish( &sha512, hash ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, 48 ); - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); - - mbedtls_sha512_free( &sha512 ); - - return; -} -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ) -{ - unsigned char *p = ssl->handshake->premaster; - unsigned char *end = p + sizeof( ssl->handshake->premaster ); - const unsigned char *psk = ssl->conf->psk; - size_t psk_len = ssl->conf->psk_len; - - /* If the psk callback was called, use its result */ - if( ssl->handshake->psk != NULL ) - { - psk = ssl->handshake->psk; - psk_len = ssl->handshake->psk_len; - } - - /* - * PMS = struct { - * opaque other_secret<0..2^16-1>; - * opaque psk<0..2^16-1>; - * }; - * with "other_secret" depending on the particular key exchange - */ -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - if( key_ex == MBEDTLS_KEY_EXCHANGE_PSK ) - { - if( end - p < 2 ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - *(p++) = (unsigned char)( psk_len >> 8 ); - *(p++) = (unsigned char)( psk_len ); - - if( end < p || (size_t)( end - p ) < psk_len ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - memset( p, 0, psk_len ); - p += psk_len; - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) - if( key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) - { - /* - * other_secret already set by the ClientKeyExchange message, - * and is 48 bytes long - */ - *p++ = 0; - *p++ = 48; - p += 48; - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) - if( key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) - { - int ret; - size_t len; - - /* Write length only when we know the actual value */ - if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, - p + 2, end - ( p + 2 ), &len, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); - return( ret ); - } - *(p++) = (unsigned char)( len >> 8 ); - *(p++) = (unsigned char)( len ); - p += len; - - MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) - if( key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) - { - int ret; - size_t zlen; - - if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen, - p + 2, end - ( p + 2 ), - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); - return( ret ); - } - - *(p++) = (unsigned char)( zlen >> 8 ); - *(p++) = (unsigned char)( zlen ); - p += zlen; - - MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); - } - else -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* opaque psk<0..2^16-1>; */ - if( end - p < 2 ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - *(p++) = (unsigned char)( psk_len >> 8 ); - *(p++) = (unsigned char)( psk_len ); - - if( end < p || (size_t)( end - p ) < psk_len ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - memcpy( p, psk, psk_len ); - p += psk_len; - - ssl->handshake->pmslen = p - ssl->handshake->premaster; - - return( 0 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ - -#if defined(MBEDTLS_SSL_PROTO_SSL3) -/* - * SSLv3.0 MAC functions - */ -static void ssl_mac( mbedtls_md_context_t *md_ctx, unsigned char *secret, - unsigned char *buf, size_t len, - unsigned char *ctr, int type ) -{ - unsigned char header[11]; - unsigned char padding[48]; - int padlen; - int md_size = mbedtls_md_get_size( md_ctx->md_info ); - int md_type = mbedtls_md_get_type( md_ctx->md_info ); - - /* Only MD5 and SHA-1 supported */ - if( md_type == MBEDTLS_MD_MD5 ) - padlen = 48; - else - padlen = 40; - - memcpy( header, ctr, 8 ); - header[ 8] = (unsigned char) type; - header[ 9] = (unsigned char)( len >> 8 ); - header[10] = (unsigned char)( len ); - - memset( padding, 0x36, padlen ); - mbedtls_md_starts( md_ctx ); - mbedtls_md_update( md_ctx, secret, md_size ); - mbedtls_md_update( md_ctx, padding, padlen ); - mbedtls_md_update( md_ctx, header, 11 ); - mbedtls_md_update( md_ctx, buf, len ); - mbedtls_md_finish( md_ctx, buf + len ); - - memset( padding, 0x5C, padlen ); - mbedtls_md_starts( md_ctx ); - mbedtls_md_update( md_ctx, secret, md_size ); - mbedtls_md_update( md_ctx, padding, padlen ); - mbedtls_md_update( md_ctx, buf + len, md_size ); - mbedtls_md_finish( md_ctx, buf + len ); -} -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ - ( defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) ) -#define SSL_SOME_MODES_USE_MAC -#endif - -/* - * Encryption/decryption functions - */ -static int ssl_encrypt_buf( mbedtls_ssl_context *ssl ) -{ - mbedtls_cipher_mode_t mode; - int auth_done = 0; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); - - if( ssl->session_out == NULL || ssl->transform_out == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - mode = mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload", - ssl->out_msg, ssl->out_msglen ); - - /* - * Add MAC before if needed - */ -#if defined(SSL_SOME_MODES_USE_MAC) - if( mode == MBEDTLS_MODE_STREAM || - ( mode == MBEDTLS_MODE_CBC -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - && ssl->session_out->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED -#endif - ) ) - { -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - ssl_mac( &ssl->transform_out->md_ctx_enc, - ssl->transform_out->mac_enc, - ssl->out_msg, ssl->out_msglen, - ssl->out_ctr, ssl->out_msgtype ); - } - else -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) - { - mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_ctr, 8 ); - mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_hdr, 3 ); - mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, ssl->out_len, 2 ); - mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, - ssl->out_msg, ssl->out_msglen ); - mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, - ssl->out_msg + ssl->out_msglen ); - mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); - } - else -#endif - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", - ssl->out_msg + ssl->out_msglen, - ssl->transform_out->maclen ); - - ssl->out_msglen += ssl->transform_out->maclen; - auth_done++; - } -#endif /* AEAD not the only option */ - - /* - * Encrypt - */ -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) - if( mode == MBEDTLS_MODE_STREAM ) - { - int ret; - size_t olen = 0; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " - "including %d bytes of padding", - ssl->out_msglen, 0 ) ); - - if( ( ret = mbedtls_cipher_crypt( &ssl->transform_out->cipher_ctx_enc, - ssl->transform_out->iv_enc, - ssl->transform_out->ivlen, - ssl->out_msg, ssl->out_msglen, - ssl->out_msg, &olen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); - return( ret ); - } - - if( ssl->out_msglen != olen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } - else -#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ -#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) - if( mode == MBEDTLS_MODE_GCM || - mode == MBEDTLS_MODE_CCM ) - { - int ret; - size_t enc_msglen, olen; - unsigned char *enc_msg; - unsigned char add_data[13]; - unsigned char taglen = ssl->transform_out->ciphersuite_info->flags & - MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; - - memcpy( add_data, ssl->out_ctr, 8 ); - add_data[8] = ssl->out_msgtype; - mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, - ssl->conf->transport, add_data + 9 ); - add_data[11] = ( ssl->out_msglen >> 8 ) & 0xFF; - add_data[12] = ssl->out_msglen & 0xFF; - - MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", - add_data, 13 ); - - /* - * Generate IV - */ - if( ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen != 8 ) - { - /* Reminder if we ever add an AEAD mode with a different size */ - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - memcpy( ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen, - ssl->out_ctr, 8 ); - memcpy( ssl->out_iv, ssl->out_ctr, 8 ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv, - ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen ); - - /* - * Fix pointer positions and message length with added IV - */ - enc_msg = ssl->out_msg; - enc_msglen = ssl->out_msglen; - ssl->out_msglen += ssl->transform_out->ivlen - - ssl->transform_out->fixed_ivlen; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " - "including %d bytes of padding", - ssl->out_msglen, 0 ) ); - - /* - * Encrypt and authenticate - */ - if( ( ret = mbedtls_cipher_auth_encrypt( &ssl->transform_out->cipher_ctx_enc, - ssl->transform_out->iv_enc, - ssl->transform_out->ivlen, - add_data, 13, - enc_msg, enc_msglen, - enc_msg, &olen, - enc_msg + enc_msglen, taglen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt", ret ); - return( ret ); - } - - if( olen != enc_msglen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - ssl->out_msglen += taglen; - auth_done++; - - MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag", enc_msg + enc_msglen, taglen ); - } - else -#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ -#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) - if( mode == MBEDTLS_MODE_CBC ) - { - int ret; - unsigned char *enc_msg; - size_t enc_msglen, padlen, olen = 0, i; - - padlen = ssl->transform_out->ivlen - ( ssl->out_msglen + 1 ) % - ssl->transform_out->ivlen; - if( padlen == ssl->transform_out->ivlen ) - padlen = 0; - - for( i = 0; i <= padlen; i++ ) - ssl->out_msg[ssl->out_msglen + i] = (unsigned char) padlen; - - ssl->out_msglen += padlen + 1; - - enc_msglen = ssl->out_msglen; - enc_msg = ssl->out_msg; - -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) - /* - * Prepend per-record IV for block cipher in TLS v1.1 and up as per - * Method 1 (6.2.3.2. in RFC4346 and RFC5246) - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - /* - * Generate IV - */ - ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->transform_out->iv_enc, - ssl->transform_out->ivlen ); - if( ret != 0 ) - return( ret ); - - memcpy( ssl->out_iv, ssl->transform_out->iv_enc, - ssl->transform_out->ivlen ); - - /* - * Fix pointer positions and message length with added IV - */ - enc_msg = ssl->out_msg; - enc_msglen = ssl->out_msglen; - ssl->out_msglen += ssl->transform_out->ivlen; - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, " - "including %d bytes of IV and %d bytes of padding", - ssl->out_msglen, ssl->transform_out->ivlen, - padlen + 1 ) ); - - if( ( ret = mbedtls_cipher_crypt( &ssl->transform_out->cipher_ctx_enc, - ssl->transform_out->iv_enc, - ssl->transform_out->ivlen, - enc_msg, enc_msglen, - enc_msg, &olen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); - return( ret ); - } - - if( enc_msglen != olen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) - if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) - { - /* - * Save IV in SSL3 and TLS1 - */ - memcpy( ssl->transform_out->iv_enc, - ssl->transform_out->cipher_ctx_enc.iv, - ssl->transform_out->ivlen ); - } -#endif - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - if( auth_done == 0 ) - { - /* - * MAC(MAC_write_key, seq_num + - * TLSCipherText.type + - * TLSCipherText.version + - * length_of( (IV +) ENC(...) ) + - * IV + // except for TLS 1.0 - * ENC(content + padding + padding_length)); - */ - unsigned char pseudo_hdr[13]; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); - - memcpy( pseudo_hdr + 0, ssl->out_ctr, 8 ); - memcpy( pseudo_hdr + 8, ssl->out_hdr, 3 ); - pseudo_hdr[11] = (unsigned char)( ( ssl->out_msglen >> 8 ) & 0xFF ); - pseudo_hdr[12] = (unsigned char)( ( ssl->out_msglen ) & 0xFF ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 ); - - mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, pseudo_hdr, 13 ); - mbedtls_md_hmac_update( &ssl->transform_out->md_ctx_enc, - ssl->out_iv, ssl->out_msglen ); - mbedtls_md_hmac_finish( &ssl->transform_out->md_ctx_enc, - ssl->out_iv + ssl->out_msglen ); - mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); - - ssl->out_msglen += ssl->transform_out->maclen; - auth_done++; - } -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - } - else -#endif /* MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C ) */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* Make extra sure authentication was performed, exactly once */ - if( auth_done != 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) ); - - return( 0 ); -} - -#define SSL_MAX_MAC_SIZE 48 - -static int ssl_decrypt_buf( mbedtls_ssl_context *ssl ) -{ - size_t i; - mbedtls_cipher_mode_t mode; - int auth_done = 0; -#if defined(SSL_SOME_MODES_USE_MAC) - size_t padlen = 0, correct = 1; -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) ); - - if( ssl->session_in == NULL || ssl->transform_in == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - mode = mbedtls_cipher_get_cipher_mode( &ssl->transform_in->cipher_ctx_dec ); - - if( ssl->in_msglen < ssl->transform_in->minlen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "in_msglen (%d) < minlen (%d)", - ssl->in_msglen, ssl->transform_in->minlen ) ); - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } - -#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) - if( mode == MBEDTLS_MODE_STREAM ) - { - int ret; - size_t olen = 0; - - padlen = 0; - - if( ( ret = mbedtls_cipher_crypt( &ssl->transform_in->cipher_ctx_dec, - ssl->transform_in->iv_dec, - ssl->transform_in->ivlen, - ssl->in_msg, ssl->in_msglen, - ssl->in_msg, &olen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); - return( ret ); - } - - if( ssl->in_msglen != olen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } - else -#endif /* MBEDTLS_ARC4_C || MBEDTLS_CIPHER_NULL_CIPHER */ -#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) - if( mode == MBEDTLS_MODE_GCM || - mode == MBEDTLS_MODE_CCM ) - { - int ret; - size_t dec_msglen, olen; - unsigned char *dec_msg; - unsigned char *dec_msg_result; - unsigned char add_data[13]; - unsigned char taglen = ssl->transform_in->ciphersuite_info->flags & - MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; - size_t explicit_iv_len = ssl->transform_in->ivlen - - ssl->transform_in->fixed_ivlen; - - if( ssl->in_msglen < explicit_iv_len + taglen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) " - "+ taglen (%d)", ssl->in_msglen, - explicit_iv_len, taglen ) ); - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } - dec_msglen = ssl->in_msglen - explicit_iv_len - taglen; - - dec_msg = ssl->in_msg; - dec_msg_result = ssl->in_msg; - ssl->in_msglen = dec_msglen; - - memcpy( add_data, ssl->in_ctr, 8 ); - add_data[8] = ssl->in_msgtype; - mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, - ssl->conf->transport, add_data + 9 ); - add_data[11] = ( ssl->in_msglen >> 8 ) & 0xFF; - add_data[12] = ssl->in_msglen & 0xFF; - - MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", - add_data, 13 ); - - memcpy( ssl->transform_in->iv_dec + ssl->transform_in->fixed_ivlen, - ssl->in_iv, - ssl->transform_in->ivlen - ssl->transform_in->fixed_ivlen ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", ssl->transform_in->iv_dec, - ssl->transform_in->ivlen ); - MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, taglen ); - - /* - * Decrypt and authenticate - */ - if( ( ret = mbedtls_cipher_auth_decrypt( &ssl->transform_in->cipher_ctx_dec, - ssl->transform_in->iv_dec, - ssl->transform_in->ivlen, - add_data, 13, - dec_msg, dec_msglen, - dec_msg_result, &olen, - dec_msg + dec_msglen, taglen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_decrypt", ret ); - - if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - - return( ret ); - } - auth_done++; - - if( olen != dec_msglen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } - else -#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ -#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ - ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_CAMELLIA_C) ) - if( mode == MBEDTLS_MODE_CBC ) - { - /* - * Decrypt and check the padding - */ - int ret; - unsigned char *dec_msg; - unsigned char *dec_msg_result; - size_t dec_msglen; - size_t minlen = 0; - size_t olen = 0; - - /* - * Check immediate ciphertext sanity - */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - minlen += ssl->transform_in->ivlen; -#endif - - if( ssl->in_msglen < minlen + ssl->transform_in->ivlen || - ssl->in_msglen < minlen + ssl->transform_in->maclen + 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < max( ivlen(%d), maclen (%d) " - "+ 1 ) ( + expl IV )", ssl->in_msglen, - ssl->transform_in->ivlen, - ssl->transform_in->maclen ) ); - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } - - dec_msglen = ssl->in_msglen; - dec_msg = ssl->in_msg; - dec_msg_result = ssl->in_msg; - - /* - * Authenticate before decrypt if enabled - */ -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - if( ssl->session_in->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) - { - unsigned char computed_mac[SSL_MAX_MAC_SIZE]; - unsigned char pseudo_hdr[13]; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); - - dec_msglen -= ssl->transform_in->maclen; - ssl->in_msglen -= ssl->transform_in->maclen; - - memcpy( pseudo_hdr + 0, ssl->in_ctr, 8 ); - memcpy( pseudo_hdr + 8, ssl->in_hdr, 3 ); - pseudo_hdr[11] = (unsigned char)( ( ssl->in_msglen >> 8 ) & 0xFF ); - pseudo_hdr[12] = (unsigned char)( ( ssl->in_msglen ) & 0xFF ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", pseudo_hdr, 13 ); - - mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, pseudo_hdr, 13 ); - mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, - ssl->in_iv, ssl->in_msglen ); - mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, computed_mac ); - mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", ssl->in_iv + ssl->in_msglen, - ssl->transform_in->maclen ); - MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", computed_mac, - ssl->transform_in->maclen ); - - if( mbedtls_ssl_safer_memcmp( ssl->in_iv + ssl->in_msglen, computed_mac, - ssl->transform_in->maclen ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); - - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } - auth_done++; - } -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ - - /* - * Check length sanity - */ - if( ssl->in_msglen % ssl->transform_in->ivlen != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0", - ssl->in_msglen, ssl->transform_in->ivlen ) ); - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } - -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) - /* - * Initialize for prepended IV for block cipher in TLS v1.1 and up - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - dec_msglen -= ssl->transform_in->ivlen; - ssl->in_msglen -= ssl->transform_in->ivlen; - - for( i = 0; i < ssl->transform_in->ivlen; i++ ) - ssl->transform_in->iv_dec[i] = ssl->in_iv[i]; - } -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ - - if( ( ret = mbedtls_cipher_crypt( &ssl->transform_in->cipher_ctx_dec, - ssl->transform_in->iv_dec, - ssl->transform_in->ivlen, - dec_msg, dec_msglen, - dec_msg_result, &olen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); - return( ret ); - } - - if( dec_msglen != olen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) - if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 ) - { - /* - * Save IV in SSL3 and TLS1 - */ - memcpy( ssl->transform_in->iv_dec, - ssl->transform_in->cipher_ctx_dec.iv, - ssl->transform_in->ivlen ); - } -#endif - - padlen = 1 + ssl->in_msg[ssl->in_msglen - 1]; - - if( ssl->in_msglen < ssl->transform_in->maclen + padlen && - auth_done == 0 ) - { -#if defined(MBEDTLS_SSL_DEBUG_ALL) - MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < maclen (%d) + padlen (%d)", - ssl->in_msglen, ssl->transform_in->maclen, padlen ) ); -#endif - padlen = 0; - correct = 0; - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - if( padlen > ssl->transform_in->ivlen ) - { -#if defined(MBEDTLS_SSL_DEBUG_ALL) - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding length: is %d, " - "should be no more than %d", - padlen, ssl->transform_in->ivlen ) ); -#endif - correct = 0; - } - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) - { - /* - * TLSv1+: always check the padding up to the first failure - * and fake check up to 256 bytes of padding - */ - size_t pad_count = 0, real_count = 1; - size_t padding_idx = ssl->in_msglen - padlen - 1; - - /* - * Padding is guaranteed to be incorrect if: - * 1. padlen >= ssl->in_msglen - * - * 2. padding_idx >= MBEDTLS_SSL_MAX_CONTENT_LEN + - * ssl->transform_in->maclen - * - * In both cases we reset padding_idx to a safe value (0) to - * prevent out-of-buffer reads. - */ - correct &= ( ssl->in_msglen >= padlen + 1 ); - correct &= ( padding_idx < MBEDTLS_SSL_MAX_CONTENT_LEN + - ssl->transform_in->maclen ); - - padding_idx *= correct; - - for( i = 1; i <= 256; i++ ) - { - real_count &= ( i <= padlen ); - pad_count += real_count * - ( ssl->in_msg[padding_idx + i] == padlen - 1 ); - } - - correct &= ( pad_count == padlen ); /* Only 1 on correct padding */ - -#if defined(MBEDTLS_SSL_DEBUG_ALL) - if( padlen > 0 && correct == 0 ) - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) ); -#endif - padlen &= correct * 0x1FF; - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - ssl->in_msglen -= padlen; - } - else -#endif /* MBEDTLS_CIPHER_MODE_CBC && - ( MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C ) */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption", - ssl->in_msg, ssl->in_msglen ); - - /* - * Authenticate if not done yet. - * Compute the MAC regardless of the padding result (RFC4346, CBCTIME). - */ -#if defined(SSL_SOME_MODES_USE_MAC) - if( auth_done == 0 ) - { - unsigned char tmp[SSL_MAX_MAC_SIZE]; - - ssl->in_msglen -= ssl->transform_in->maclen; - - ssl->in_len[0] = (unsigned char)( ssl->in_msglen >> 8 ); - ssl->in_len[1] = (unsigned char)( ssl->in_msglen ); - - memcpy( tmp, ssl->in_msg + ssl->in_msglen, ssl->transform_in->maclen ); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - ssl_mac( &ssl->transform_in->md_ctx_dec, - ssl->transform_in->mac_dec, - ssl->in_msg, ssl->in_msglen, - ssl->in_ctr, ssl->in_msgtype ); - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_0 ) - { - /* - * Process MAC and always update for padlen afterwards to make - * total time independent of padlen - * - * extra_run compensates MAC check for padlen - * - * Known timing attacks: - * - Lucky Thirteen (http://www.isg.rhul.ac.uk/tls/TLStiming.pdf) - * - * We use ( ( Lx + 8 ) / 64 ) to handle 'negative Lx' values - * correctly. (We round down instead of up, so -56 is the correct - * value for our calculations instead of -55) - */ - size_t j, extra_run = 0; - extra_run = ( 13 + ssl->in_msglen + padlen + 8 ) / 64 - - ( 13 + ssl->in_msglen + 8 ) / 64; - - extra_run &= correct * 0xFF; - - mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_ctr, 8 ); - mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_hdr, 3 ); - mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_len, 2 ); - mbedtls_md_hmac_update( &ssl->transform_in->md_ctx_dec, ssl->in_msg, - ssl->in_msglen ); - mbedtls_md_hmac_finish( &ssl->transform_in->md_ctx_dec, - ssl->in_msg + ssl->in_msglen ); - /* Call mbedtls_md_process at least once due to cache attacks */ - for( j = 0; j < extra_run + 1; j++ ) - mbedtls_md_process( &ssl->transform_in->md_ctx_dec, ssl->in_msg ); - - mbedtls_md_hmac_reset( &ssl->transform_in->md_ctx_dec ); - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", tmp, ssl->transform_in->maclen ); - MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", ssl->in_msg + ssl->in_msglen, - ssl->transform_in->maclen ); - - if( mbedtls_ssl_safer_memcmp( tmp, ssl->in_msg + ssl->in_msglen, - ssl->transform_in->maclen ) != 0 ) - { -#if defined(MBEDTLS_SSL_DEBUG_ALL) - MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); -#endif - correct = 0; - } - auth_done++; - - /* - * Finally check the correct flag - */ - if( correct == 0 ) - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } -#endif /* SSL_SOME_MODES_USE_MAC */ - - /* Make extra sure authentication was performed, exactly once */ - if( auth_done != 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - if( ssl->in_msglen == 0 ) - { - ssl->nb_zero++; - - /* - * Three or more empty messages may be a DoS attack - * (excessive CPU consumption). - */ - if( ssl->nb_zero > 3 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "received four consecutive empty " - "messages, possible DoS attack" ) ); - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } - } - else - ssl->nb_zero = 0; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - ; /* in_ctr read from peer, not maintained internally */ - } - else -#endif - { - for( i = 8; i > ssl_ep_len( ssl ); i-- ) - if( ++ssl->in_ctr[i - 1] != 0 ) - break; - - /* The loop goes to its end iff the counter is wrapping */ - if( i == ssl_ep_len( ssl ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) ); - return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); - } - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) ); - - return( 0 ); -} - -#undef MAC_NONE -#undef MAC_PLAINTEXT -#undef MAC_CIPHERTEXT - -#if defined(MBEDTLS_ZLIB_SUPPORT) -/* - * Compression/decompression functions - */ -static int ssl_compress_buf( mbedtls_ssl_context *ssl ) -{ - int ret; - unsigned char *msg_post = ssl->out_msg; - size_t len_pre = ssl->out_msglen; - unsigned char *msg_pre = ssl->compress_buf; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> compress buf" ) ); - - if( len_pre == 0 ) - return( 0 ); - - memcpy( msg_pre, ssl->out_msg, len_pre ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "before compression: msglen = %d, ", - ssl->out_msglen ) ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "before compression: output payload", - ssl->out_msg, ssl->out_msglen ); - - ssl->transform_out->ctx_deflate.next_in = msg_pre; - ssl->transform_out->ctx_deflate.avail_in = len_pre; - ssl->transform_out->ctx_deflate.next_out = msg_post; - ssl->transform_out->ctx_deflate.avail_out = MBEDTLS_SSL_BUFFER_LEN; - - ret = deflate( &ssl->transform_out->ctx_deflate, Z_SYNC_FLUSH ); - if( ret != Z_OK ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform compression (%d)", ret ) ); - return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); - } - - ssl->out_msglen = MBEDTLS_SSL_BUFFER_LEN - - ssl->transform_out->ctx_deflate.avail_out; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "after compression: msglen = %d, ", - ssl->out_msglen ) ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "after compression: output payload", - ssl->out_msg, ssl->out_msglen ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= compress buf" ) ); - - return( 0 ); -} - -static int ssl_decompress_buf( mbedtls_ssl_context *ssl ) -{ - int ret; - unsigned char *msg_post = ssl->in_msg; - size_t len_pre = ssl->in_msglen; - unsigned char *msg_pre = ssl->compress_buf; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decompress buf" ) ); - - if( len_pre == 0 ) - return( 0 ); - - memcpy( msg_pre, ssl->in_msg, len_pre ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "before decompression: msglen = %d, ", - ssl->in_msglen ) ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "before decompression: input payload", - ssl->in_msg, ssl->in_msglen ); - - ssl->transform_in->ctx_inflate.next_in = msg_pre; - ssl->transform_in->ctx_inflate.avail_in = len_pre; - ssl->transform_in->ctx_inflate.next_out = msg_post; - ssl->transform_in->ctx_inflate.avail_out = MBEDTLS_SSL_MAX_CONTENT_LEN; - - ret = inflate( &ssl->transform_in->ctx_inflate, Z_SYNC_FLUSH ); - if( ret != Z_OK ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "failed to perform decompression (%d)", ret ) ); - return( MBEDTLS_ERR_SSL_COMPRESSION_FAILED ); - } - - ssl->in_msglen = MBEDTLS_SSL_MAX_CONTENT_LEN - - ssl->transform_in->ctx_inflate.avail_out; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "after decompression: msglen = %d, ", - ssl->in_msglen ) ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "after decompression: input payload", - ssl->in_msg, ssl->in_msglen ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decompress buf" ) ); - - return( 0 ); -} -#endif /* MBEDTLS_ZLIB_SUPPORT */ - -#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) -static int ssl_write_hello_request( mbedtls_ssl_context *ssl ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -static int ssl_resend_hello_request( mbedtls_ssl_context *ssl ) -{ - /* If renegotiation is not enforced, retransmit until we would reach max - * timeout if we were using the usual handshake doubling scheme */ - if( ssl->conf->renego_max_records < 0 ) - { - uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1; - unsigned char doublings = 1; - - while( ratio != 0 ) - { - ++doublings; - ratio >>= 1; - } - - if( ++ssl->renego_records_seen > doublings ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "no longer retransmitting hello request" ) ); - return( 0 ); - } - } - - return( ssl_write_hello_request( ssl ) ); -} -#endif -#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ - -/* - * Fill the input message buffer by appending data to it. - * The amount of data already fetched is in ssl->in_left. - * - * If we return 0, is it guaranteed that (at least) nb_want bytes are - * available (from this read and/or a previous one). Otherwise, an error code - * is returned (possibly EOF or WANT_READ). - * - * With stream transport (TLS) on success ssl->in_left == nb_want, but - * with datagram transport (DTLS) on success ssl->in_left >= nb_want, - * since we always read a whole datagram at once. - * - * For DTLS, it is up to the caller to set ssl->next_record_offset when - * they're done reading a record. - */ -int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) -{ - int ret; - size_t len; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) ); - - if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " - "or mbedtls_ssl_set_bio()" ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - if( nb_want > MBEDTLS_SSL_BUFFER_LEN - (size_t)( ssl->in_hdr - ssl->in_buf ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - uint32_t timeout; - - /* Just to be sure */ - if( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use " - "mbedtls_ssl_set_timer_cb() for DTLS" ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - /* - * The point is, we need to always read a full datagram at once, so we - * sometimes read more then requested, and handle the additional data. - * It could be the rest of the current record (while fetching the - * header) and/or some other records in the same datagram. - */ - - /* - * Move to the next record in the already read datagram if applicable - */ - if( ssl->next_record_offset != 0 ) - { - if( ssl->in_left < ssl->next_record_offset ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - ssl->in_left -= ssl->next_record_offset; - - if( ssl->in_left != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %d", - ssl->next_record_offset ) ); - memmove( ssl->in_hdr, - ssl->in_hdr + ssl->next_record_offset, - ssl->in_left ); - } - - ssl->next_record_offset = 0; - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", - ssl->in_left, nb_want ) ); - - /* - * Done if we already have enough data. - */ - if( nb_want <= ssl->in_left) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); - return( 0 ); - } - - /* - * A record can't be split accross datagrams. If we need to read but - * are not at the beginning of a new record, the caller did something - * wrong. - */ - if( ssl->in_left != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* - * Don't even try to read if time's out already. - * This avoids by-passing the timer when repeatedly receiving messages - * that will end up being dropped. - */ - if( ssl_check_timer( ssl ) != 0 ) - ret = MBEDTLS_ERR_SSL_TIMEOUT; - else - { - len = MBEDTLS_SSL_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf ); - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - timeout = ssl->handshake->retransmit_timeout; - else - timeout = ssl->conf->read_timeout; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %u ms", timeout ) ); - - if( ssl->f_recv_timeout != NULL ) - ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len, - timeout ); - else - ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len ); - - MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); - - if( ret == 0 ) - return( MBEDTLS_ERR_SSL_CONN_EOF ); - } - - if( ret == MBEDTLS_ERR_SSL_TIMEOUT ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) ); - ssl_set_timer( ssl, 0 ); - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - { - if( ssl_double_retransmit_timeout( ssl ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) ); - return( MBEDTLS_ERR_SSL_TIMEOUT ); - } - - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); - return( ret ); - } - - return( MBEDTLS_ERR_SSL_WANT_READ ); - } -#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) - else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) - { - if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret ); - return( ret ); - } - - return( MBEDTLS_ERR_SSL_WANT_READ ); - } -#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ - } - - if( ret < 0 ) - return( ret ); - - ssl->in_left = ret; - } - else -#endif - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", - ssl->in_left, nb_want ) ); - - while( ssl->in_left < nb_want ) - { - len = nb_want - ssl->in_left; - - if( ssl_check_timer( ssl ) != 0 ) - ret = MBEDTLS_ERR_SSL_TIMEOUT; - else - { - if( ssl->f_recv_timeout != NULL ) - { - ret = ssl->f_recv_timeout( ssl->p_bio, - ssl->in_hdr + ssl->in_left, len, - ssl->conf->read_timeout ); - } - else - { - ret = ssl->f_recv( ssl->p_bio, - ssl->in_hdr + ssl->in_left, len ); - } - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %d, nb_want: %d", - ssl->in_left, nb_want ) ); - MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); - - if( ret == 0 ) - return( MBEDTLS_ERR_SSL_CONN_EOF ); - - if( ret < 0 ) - return( ret ); - - ssl->in_left += ret; - } - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); - - return( 0 ); -} - -/* - * Flush any data not yet written - */ -int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) -{ - int ret; - unsigned char *buf, i; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); - - if( ssl->f_send == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " - "or mbedtls_ssl_set_bio()" ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - /* Avoid incrementing counter if data is flushed */ - if( ssl->out_left == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); - return( 0 ); - } - - while( ssl->out_left > 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %d, out_left: %d", - mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) ); - - buf = ssl->out_hdr + mbedtls_ssl_hdr_len( ssl ) + - ssl->out_msglen - ssl->out_left; - ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left ); - - MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret ); - - if( ret <= 0 ) - return( ret ); - - ssl->out_left -= ret; - } - - for( i = 8; i > ssl_ep_len( ssl ); i-- ) - if( ++ssl->out_ctr[i - 1] != 0 ) - break; - - /* The loop goes to its end iff the counter is wrapping */ - if( i == ssl_ep_len( ssl ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); - return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); - - return( 0 ); -} - -/* - * Functions to handle the DTLS retransmission state machine - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) -/* - * Append current handshake message to current outgoing flight - */ -static int ssl_flight_append( mbedtls_ssl_context *ssl ) -{ - mbedtls_ssl_flight_item *msg; - - /* Allocate space for current message */ - if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", - sizeof( mbedtls_ssl_flight_item ) ) ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %d bytes failed", ssl->out_msglen ) ); - mbedtls_free( msg ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - /* Copy current handshake message with headers */ - memcpy( msg->p, ssl->out_msg, ssl->out_msglen ); - msg->len = ssl->out_msglen; - msg->type = ssl->out_msgtype; - msg->next = NULL; - - /* Append to the current flight */ - if( ssl->handshake->flight == NULL ) - ssl->handshake->flight = msg; - else - { - mbedtls_ssl_flight_item *cur = ssl->handshake->flight; - while( cur->next != NULL ) - cur = cur->next; - cur->next = msg; - } - - return( 0 ); -} - -/* - * Free the current flight of handshake messages - */ -static void ssl_flight_free( mbedtls_ssl_flight_item *flight ) -{ - mbedtls_ssl_flight_item *cur = flight; - mbedtls_ssl_flight_item *next; - - while( cur != NULL ) - { - next = cur->next; - - mbedtls_free( cur->p ); - mbedtls_free( cur ); - - cur = next; - } -} - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ); -#endif - -/* - * Swap transform_out and out_ctr with the alternative ones - */ -static void ssl_swap_epochs( mbedtls_ssl_context *ssl ) -{ - mbedtls_ssl_transform *tmp_transform; - unsigned char tmp_out_ctr[8]; - - if( ssl->transform_out == ssl->handshake->alt_transform_out ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) ); - return; - } - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) ); - - /* Swap transforms */ - tmp_transform = ssl->transform_out; - ssl->transform_out = ssl->handshake->alt_transform_out; - ssl->handshake->alt_transform_out = tmp_transform; - - /* Swap epoch + sequence_number */ - memcpy( tmp_out_ctr, ssl->out_ctr, 8 ); - memcpy( ssl->out_ctr, ssl->handshake->alt_out_ctr, 8 ); - memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, 8 ); - - /* Adjust to the newly activated transform */ - if( ssl->transform_out != NULL && - ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - ssl->out_msg = ssl->out_iv + ssl->transform_out->ivlen - - ssl->transform_out->fixed_ivlen; - } - else - ssl->out_msg = ssl->out_iv; - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_activate != NULL ) - { - if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - } -#endif -} - -/* - * Retransmit the current flight of messages. - * - * Need to remember the current message in case flush_output returns - * WANT_WRITE, causing us to exit this function and come back later. - * This function must be called until state is no longer SENDING. - */ -int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) -{ - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) ); - - if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise resending" ) ); - - ssl->handshake->cur_msg = ssl->handshake->flight; - ssl_swap_epochs( ssl ); - - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; - } - - while( ssl->handshake->cur_msg != NULL ) - { - int ret; - mbedtls_ssl_flight_item *cur = ssl->handshake->cur_msg; - - /* Swap epochs before sending Finished: we can't do it after - * sending ChangeCipherSpec, in case write returns WANT_READ. - * Must be done before copying, may change out_msg pointer */ - if( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && - cur->p[0] == MBEDTLS_SSL_HS_FINISHED ) - { - ssl_swap_epochs( ssl ); - } - - memcpy( ssl->out_msg, cur->p, cur->len ); - ssl->out_msglen = cur->len; - ssl->out_msgtype = cur->type; - - ssl->handshake->cur_msg = cur->next; - - MBEDTLS_SSL_DEBUG_BUF( 3, "resent handshake message header", ssl->out_msg, 12 ); - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - } - - if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; - else - { - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; - ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) ); - - return( 0 ); -} - -/* - * To be called when the last message of an incoming flight is received. - */ -void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ) -{ - /* We won't need to resend that one any more */ - ssl_flight_free( ssl->handshake->flight ); - ssl->handshake->flight = NULL; - ssl->handshake->cur_msg = NULL; - - /* The next incoming flight will start with this msg_seq */ - ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq; - - /* Cancel timer */ - ssl_set_timer( ssl, 0 ); - - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) - { - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; - } - else - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; -} - -/* - * To be called when the last message of an outgoing flight is send. - */ -void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ) -{ - ssl_reset_retransmit_timeout( ssl ); - ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); - - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) - { - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; - } - else - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; -} -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -/* - * Record layer functions - */ - -/* - * Write current record. - * Uses ssl->out_msgtype, ssl->out_msglen and bytes at ssl->out_msg. - */ -int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl ) -{ - int ret, done = 0, out_msg_type; - size_t len = ssl->out_msglen; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake != NULL && - ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) - { - ; /* Skip special handshake treatment when resending */ - } - else -#endif - if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) - { - out_msg_type = ssl->out_msg[0]; - - if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST && - ssl->handshake == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - ssl->out_msg[1] = (unsigned char)( ( len - 4 ) >> 16 ); - ssl->out_msg[2] = (unsigned char)( ( len - 4 ) >> 8 ); - ssl->out_msg[3] = (unsigned char)( ( len - 4 ) ); - - /* - * DTLS has additional fields in the Handshake layer, - * between the length field and the actual payload: - * uint16 message_seq; - * uint24 fragment_offset; - * uint24 fragment_length; - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - /* Make room for the additional DTLS fields */ - memmove( ssl->out_msg + 12, ssl->out_msg + 4, len - 4 ); - ssl->out_msglen += 8; - len += 8; - - /* Write message_seq and update it, except for HelloRequest */ - if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) - { - ssl->out_msg[4] = ( ssl->handshake->out_msg_seq >> 8 ) & 0xFF; - ssl->out_msg[5] = ( ssl->handshake->out_msg_seq ) & 0xFF; - ++( ssl->handshake->out_msg_seq ); - } - else - { - ssl->out_msg[4] = 0; - ssl->out_msg[5] = 0; - } - - /* We don't fragment, so frag_offset = 0 and frag_len = len */ - memset( ssl->out_msg + 6, 0x00, 3 ); - memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 ); - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - if( out_msg_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) - ssl->handshake->update_checksum( ssl, ssl->out_msg, len ); - } - - /* Save handshake and CCS messages for resending */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake != NULL && - ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING && - ( ssl->out_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC || - ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) ) - { - if( ( ret = ssl_flight_append( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret ); - return( ret ); - } - } -#endif - -#if defined(MBEDTLS_ZLIB_SUPPORT) - if( ssl->transform_out != NULL && - ssl->session_out->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) - { - if( ( ret = ssl_compress_buf( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compress_buf", ret ); - return( ret ); - } - - len = ssl->out_msglen; - } -#endif /*MBEDTLS_ZLIB_SUPPORT */ - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_write != NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_write()" ) ); - - ret = mbedtls_ssl_hw_record_write( ssl ); - if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_write", ret ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - - if( ret == 0 ) - done = 1; - } -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ - if( !done ) - { - ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; - mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, - ssl->conf->transport, ssl->out_hdr + 1 ); - - ssl->out_len[0] = (unsigned char)( len >> 8 ); - ssl->out_len[1] = (unsigned char)( len ); - - if( ssl->transform_out != NULL ) - { - if( ( ret = ssl_encrypt_buf( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret ); - return( ret ); - } - - len = ssl->out_msglen; - ssl->out_len[0] = (unsigned char)( len >> 8 ); - ssl->out_len[1] = (unsigned char)( len ); - } - - ssl->out_left = mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %d, " - "version = [%d:%d], msglen = %d", - ssl->out_hdr[0], ssl->out_hdr[1], ssl->out_hdr[2], - ( ssl->out_len[0] << 8 ) | ssl->out_len[1] ) ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", - ssl->out_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->out_msglen ); - } - - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) ); - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -/* - * Mark bits in bitmask (used for DTLS HS reassembly) - */ -static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len ) -{ - unsigned int start_bits, end_bits; - - start_bits = 8 - ( offset % 8 ); - if( start_bits != 8 ) - { - size_t first_byte_idx = offset / 8; - - /* Special case */ - if( len <= start_bits ) - { - for( ; len != 0; len-- ) - mask[first_byte_idx] |= 1 << ( start_bits - len ); - - /* Avoid potential issues with offset or len becoming invalid */ - return; - } - - offset += start_bits; /* Now offset % 8 == 0 */ - len -= start_bits; - - for( ; start_bits != 0; start_bits-- ) - mask[first_byte_idx] |= 1 << ( start_bits - 1 ); - } - - end_bits = len % 8; - if( end_bits != 0 ) - { - size_t last_byte_idx = ( offset + len ) / 8; - - len -= end_bits; /* Now len % 8 == 0 */ - - for( ; end_bits != 0; end_bits-- ) - mask[last_byte_idx] |= 1 << ( 8 - end_bits ); - } - - memset( mask + offset / 8, 0xFF, len / 8 ); -} - -/* - * Check that bitmask is full - */ -static int ssl_bitmask_check( unsigned char *mask, size_t len ) -{ - size_t i; - - for( i = 0; i < len / 8; i++ ) - if( mask[i] != 0xFF ) - return( -1 ); - - for( i = 0; i < len % 8; i++ ) - if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 ) - return( -1 ); - - return( 0 ); -} - -/* - * Reassemble fragmented DTLS handshake messages. - * - * Use a temporary buffer for reassembly, divided in two parts: - * - the first holds the reassembled message (including handshake header), - * - the second holds a bitmask indicating which parts of the message - * (excluding headers) have been received so far. - */ -static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl ) -{ - unsigned char *msg, *bitmask; - size_t frag_len, frag_off; - size_t msg_len = ssl->in_hslen - 12; /* Without headers */ - - if( ssl->handshake == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "not supported outside handshake (for now)" ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - /* - * For first fragment, check size and allocate buffer - */ - if( ssl->handshake->hs_msg == NULL ) - { - size_t alloc_len; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %d", - msg_len ) ); - - if( ssl->in_hslen > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too large" ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - /* The bitmask needs one bit per byte of message excluding header */ - alloc_len = 12 + msg_len + msg_len / 8 + ( msg_len % 8 != 0 ); - - ssl->handshake->hs_msg = mbedtls_calloc( 1, alloc_len ); - if( ssl->handshake->hs_msg == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", alloc_len ) ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - /* Prepare final header: copy msg_type, length and message_seq, - * then add standardised fragment_offset and fragment_length */ - memcpy( ssl->handshake->hs_msg, ssl->in_msg, 6 ); - memset( ssl->handshake->hs_msg + 6, 0, 3 ); - memcpy( ssl->handshake->hs_msg + 9, - ssl->handshake->hs_msg + 1, 3 ); - } - else - { - /* Make sure msg_type and length are consistent */ - if( memcmp( ssl->handshake->hs_msg, ssl->in_msg, 4 ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment header mismatch" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - } - - msg = ssl->handshake->hs_msg + 12; - bitmask = msg + msg_len; - - /* - * Check and copy current fragment - */ - frag_off = ( ssl->in_msg[6] << 16 ) | - ( ssl->in_msg[7] << 8 ) | - ssl->in_msg[8]; - frag_len = ( ssl->in_msg[9] << 16 ) | - ( ssl->in_msg[10] << 8 ) | - ssl->in_msg[11]; - - if( frag_off + frag_len > msg_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment offset/len: %d + %d > %d", - frag_off, frag_len, msg_len ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - if( frag_len + 12 > ssl->in_msglen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid fragment length: %d + 12 > %d", - frag_len, ssl->in_msglen ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %d, length = %d", - frag_off, frag_len ) ); - - memcpy( msg + frag_off, ssl->in_msg + 12, frag_len ); - ssl_bitmask_set( bitmask, frag_off, frag_len ); - - /* - * Do we have the complete message by now? - * If yes, finalize it, else ask to read the next record. - */ - if( ssl_bitmask_check( bitmask, msg_len ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "message is not complete yet" ) ); - return( MBEDTLS_ERR_SSL_WANT_READ ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake message completed" ) ); - - if( frag_len + 12 < ssl->in_msglen ) - { - /* - * We'got more handshake messages in the same record. - * This case is not handled now because no know implementation does - * that and it's hard to test, so we prefer to fail cleanly for now. - */ - MBEDTLS_SSL_DEBUG_MSG( 1, ( "last fragment not alone in its record" ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - if( ssl->in_left > ssl->next_record_offset ) - { - /* - * We've got more data in the buffer after the current record, - * that we don't want to overwrite. Move it before writing the - * reassembled message, and adjust in_left and next_record_offset. - */ - unsigned char *cur_remain = ssl->in_hdr + ssl->next_record_offset; - unsigned char *new_remain = ssl->in_msg + ssl->in_hslen; - size_t remain_len = ssl->in_left - ssl->next_record_offset; - - /* First compute and check new lengths */ - ssl->next_record_offset = new_remain - ssl->in_hdr; - ssl->in_left = ssl->next_record_offset + remain_len; - - if( ssl->in_left > MBEDTLS_SSL_BUFFER_LEN - - (size_t)( ssl->in_hdr - ssl->in_buf ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "reassembled message too large for buffer" ) ); - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - } - - memmove( new_remain, cur_remain, remain_len ); - } - - memcpy( ssl->in_msg, ssl->handshake->hs_msg, ssl->in_hslen ); - - mbedtls_free( ssl->handshake->hs_msg ); - ssl->handshake->hs_msg = NULL; - - MBEDTLS_SSL_DEBUG_BUF( 3, "reassembled handshake message", - ssl->in_msg, ssl->in_hslen ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - -int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) -{ - if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %d", - ssl->in_msglen ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ( - ( ssl->in_msg[1] << 16 ) | - ( ssl->in_msg[2] << 8 ) | - ssl->in_msg[3] ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" - " %d, type = %d, hslen = %d", - ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - int ret; - unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; - - /* ssl->handshake is NULL when receiving ClientHello for renego */ - if( ssl->handshake != NULL && - recv_msg_seq != ssl->handshake->in_msg_seq ) - { - /* Retransmit only on last message from previous flight, to avoid - * too many retransmissions. - * Besides, No sane server ever retransmits HelloVerifyRequest */ - if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 && - ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, " - "message_seq = %d, start_of_flight = %d", - recv_msg_seq, - ssl->handshake->in_flight_start_seq ) ); - - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); - return( ret ); - } - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: " - "message_seq = %d, expected = %d", - recv_msg_seq, - ssl->handshake->in_msg_seq ) ); - } - - return( MBEDTLS_ERR_SSL_WANT_READ ); - } - /* Wait until message completion to increment in_msg_seq */ - - /* Reassemble if current message is fragmented or reassembly is - * already in progress */ - if( ssl->in_msglen < ssl->in_hslen || - memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 || - memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 || - ( ssl->handshake != NULL && ssl->handshake->hs_msg != NULL ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) ); - - if( ( ret = ssl_reassemble_dtls_handshake( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_reassemble_dtls_handshake", ret ); - return( ret ); - } - } - } - else -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - /* With TLS we don't handle fragmentation (for now) */ - if( ssl->in_msglen < ssl->in_hslen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) ); - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - } - - return( 0 ); -} - -void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ) -{ - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && - ssl->handshake != NULL ) - { - ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); - } - - /* Handshake message is complete, increment counter */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake != NULL ) - { - ssl->handshake->in_msg_seq++; - } -#endif -} - -/* - * DTLS anti-replay: RFC 6347 4.1.2.6 - * - * in_window is a field of bits numbered from 0 (lsb) to 63 (msb). - * Bit n is set iff record number in_window_top - n has been seen. - * - * Usually, in_window_top is the last record number seen and the lsb of - * in_window is set. The only exception is the initial state (record number 0 - * not seen yet). - */ -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -static void ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ) -{ - ssl->in_window_top = 0; - ssl->in_window = 0; -} - -static inline uint64_t ssl_load_six_bytes( unsigned char *buf ) -{ - return( ( (uint64_t) buf[0] << 40 ) | - ( (uint64_t) buf[1] << 32 ) | - ( (uint64_t) buf[2] << 24 ) | - ( (uint64_t) buf[3] << 16 ) | - ( (uint64_t) buf[4] << 8 ) | - ( (uint64_t) buf[5] ) ); -} - -/* - * Return 0 if sequence number is acceptable, -1 otherwise - */ -int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl ) -{ - uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); - uint64_t bit; - - if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) - return( 0 ); - - if( rec_seqnum > ssl->in_window_top ) - return( 0 ); - - bit = ssl->in_window_top - rec_seqnum; - - if( bit >= 64 ) - return( -1 ); - - if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 ) - return( -1 ); - - return( 0 ); -} - -/* - * Update replay window on new validated record - */ -void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ) -{ - uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); - - if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) - return; - - if( rec_seqnum > ssl->in_window_top ) - { - /* Update window_top and the contents of the window */ - uint64_t shift = rec_seqnum - ssl->in_window_top; - - if( shift >= 64 ) - ssl->in_window = 1; - else - { - ssl->in_window <<= shift; - ssl->in_window |= 1; - } - - ssl->in_window_top = rec_seqnum; - } - else - { - /* Mark that number as seen in the current window */ - uint64_t bit = ssl->in_window_top - rec_seqnum; - - if( bit < 64 ) /* Always true, but be extra sure */ - ssl->in_window |= (uint64_t) 1 << bit; - } -} -#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ - -#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) -/* Forward declaration */ -static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ); - -/* - * Without any SSL context, check if a datagram looks like a ClientHello with - * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message. - * Both input and output include full DTLS headers. - * - * - if cookie is valid, return 0 - * - if ClientHello looks superficially valid but cookie is not, - * fill obuf and set olen, then - * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED - * - otherwise return a specific error code - */ -static int ssl_check_dtls_clihlo_cookie( - mbedtls_ssl_cookie_write_t *f_cookie_write, - mbedtls_ssl_cookie_check_t *f_cookie_check, - void *p_cookie, - const unsigned char *cli_id, size_t cli_id_len, - const unsigned char *in, size_t in_len, - unsigned char *obuf, size_t buf_len, size_t *olen ) -{ - size_t sid_len, cookie_len; - unsigned char *p; - - if( f_cookie_write == NULL || f_cookie_check == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - /* - * Structure of ClientHello with record and handshake headers, - * and expected values. We don't need to check a lot, more checks will be - * done when actually parsing the ClientHello - skipping those checks - * avoids code duplication and does not make cookie forging any easier. - * - * 0-0 ContentType type; copied, must be handshake - * 1-2 ProtocolVersion version; copied - * 3-4 uint16 epoch; copied, must be 0 - * 5-10 uint48 sequence_number; copied - * 11-12 uint16 length; (ignored) - * - * 13-13 HandshakeType msg_type; (ignored) - * 14-16 uint24 length; (ignored) - * 17-18 uint16 message_seq; copied - * 19-21 uint24 fragment_offset; copied, must be 0 - * 22-24 uint24 fragment_length; (ignored) - * - * 25-26 ProtocolVersion client_version; (ignored) - * 27-58 Random random; (ignored) - * 59-xx SessionID session_id; 1 byte len + sid_len content - * 60+ opaque cookie<0..2^8-1>; 1 byte len + content - * ... - * - * Minimum length is 61 bytes. - */ - if( in_len < 61 || - in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || - in[3] != 0 || in[4] != 0 || - in[19] != 0 || in[20] != 0 || in[21] != 0 ) - { - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - sid_len = in[59]; - if( sid_len > in_len - 61 ) - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - - cookie_len = in[60 + sid_len]; - if( cookie_len > in_len - 60 ) - return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO ); - - if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len, - cli_id, cli_id_len ) == 0 ) - { - /* Valid cookie */ - return( 0 ); - } - - /* - * If we get here, we've got an invalid cookie, let's prepare HVR. - * - * 0-0 ContentType type; copied - * 1-2 ProtocolVersion version; copied - * 3-4 uint16 epoch; copied - * 5-10 uint48 sequence_number; copied - * 11-12 uint16 length; olen - 13 - * - * 13-13 HandshakeType msg_type; hello_verify_request - * 14-16 uint24 length; olen - 25 - * 17-18 uint16 message_seq; copied - * 19-21 uint24 fragment_offset; copied - * 22-24 uint24 fragment_length; olen - 25 - * - * 25-26 ProtocolVersion server_version; 0xfe 0xff - * 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie - * - * Minimum length is 28. - */ - if( buf_len < 28 ) - return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); - - /* Copy most fields and adapt others */ - memcpy( obuf, in, 25 ); - obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; - obuf[25] = 0xfe; - obuf[26] = 0xff; - - /* Generate and write actual cookie */ - p = obuf + 28; - if( f_cookie_write( p_cookie, - &p, obuf + buf_len, cli_id, cli_id_len ) != 0 ) - { - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - *olen = p - obuf; - - /* Go back and fill length fields */ - obuf[27] = (unsigned char)( *olen - 28 ); - - obuf[14] = obuf[22] = (unsigned char)( ( *olen - 25 ) >> 16 ); - obuf[15] = obuf[23] = (unsigned char)( ( *olen - 25 ) >> 8 ); - obuf[16] = obuf[24] = (unsigned char)( ( *olen - 25 ) ); - - obuf[11] = (unsigned char)( ( *olen - 13 ) >> 8 ); - obuf[12] = (unsigned char)( ( *olen - 13 ) ); - - return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); -} - -/* - * Handle possible client reconnect with the same UDP quadruplet - * (RFC 6347 Section 4.2.8). - * - * Called by ssl_parse_record_header() in case we receive an epoch 0 record - * that looks like a ClientHello. - * - * - if the input looks like a ClientHello without cookies, - * send back HelloVerifyRequest, then - * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED - * - if the input looks like a ClientHello with a valid cookie, - * reset the session of the current context, and - * return MBEDTLS_ERR_SSL_CLIENT_RECONNECT - * - if anything goes wrong, return a specific error code - * - * mbedtls_ssl_read_record() will ignore the record if anything else than - * MBEDTLS_ERR_SSL_CLIENT_RECONNECT or 0 is returned, although this function - * cannot not return 0. - */ -static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) -{ - int ret; - size_t len; - - ret = ssl_check_dtls_clihlo_cookie( - ssl->conf->f_cookie_write, - ssl->conf->f_cookie_check, - ssl->conf->p_cookie, - ssl->cli_id, ssl->cli_id_len, - ssl->in_buf, ssl->in_left, - ssl->out_buf, MBEDTLS_SSL_MAX_CONTENT_LEN, &len ); - - MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret ); - - if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) - { - /* Don't check write errors as we can't do anything here. - * If the error is permanent we'll catch it later, - * if it's not, then hopefully it'll work next time. */ - (void) ssl->f_send( ssl->p_bio, ssl->out_buf, len ); - - return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); - } - - if( ret == 0 ) - { - /* Got a valid cookie, partially reset context */ - if( ( ret = ssl_session_reset_int( ssl, 1 ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret ); - return( ret ); - } - - return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT ); - } - - return( ret ); -} -#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ - -/* - * ContentType type; - * ProtocolVersion version; - * uint16 epoch; // DTLS only - * uint48 sequence_number; // DTLS only - * uint16 length; - * - * Return 0 if header looks sane (and, for DTLS, the record is expected) - * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad, - * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected. - * - * With DTLS, mbedtls_ssl_read_record() will: - * 1. proceed with the record if this function returns 0 - * 2. drop only the current record if this function returns UNEXPECTED_RECORD - * 3. return CLIENT_RECONNECT if this function return that value - * 4. drop the whole datagram if this function returns anything else. - * Point 2 is needed when the peer is resending, and we have already received - * the first record from a datagram but are still waiting for the others. - */ -static int ssl_parse_record_header( mbedtls_ssl_context *ssl ) -{ - int major_ver, minor_ver; - - MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) ); - - ssl->in_msgtype = ssl->in_hdr[0]; - ssl->in_msglen = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; - mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, ssl->in_hdr + 1 ); - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, " - "version = [%d:%d], msglen = %d", - ssl->in_msgtype, - major_ver, minor_ver, ssl->in_msglen ) ); - - /* Check record type */ - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_msgtype != MBEDTLS_SSL_MSG_ALERT && - ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && - ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - /* Check version */ - if( major_ver != ssl->major_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - if( minor_ver > ssl->conf->max_minor_ver ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - /* Check length against the size of our buffer */ - if( ssl->in_msglen > MBEDTLS_SSL_BUFFER_LEN - - (size_t)( ssl->in_msg - ssl->in_buf ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - - /* Check length against bounds of the current transform and version */ - if( ssl->transform_in == NULL ) - { - if( ssl->in_msglen < 1 || - ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - } - else - { - if( ssl->in_msglen < ssl->transform_in->minlen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && - ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - /* - * TLS encrypted messages can have up to 256 bytes of padding - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 && - ssl->in_msglen > ssl->transform_in->minlen + - MBEDTLS_SSL_MAX_CONTENT_LEN + 256 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } -#endif - } - - /* - * DTLS-related tests done last, because most of them may result in - * silently dropping the record (but not the whole datagram), and we only - * want to consider that after ensuring that the "basic" fields (type, - * version, length) are sane. - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1]; - - /* Drop unexpected ChangeCipherSpec messages */ - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && - ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && - ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); - } - - /* Drop unexpected ApplicationData records, - * except at the beginning of renegotiations */ - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && - ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER -#if defined(MBEDTLS_SSL_RENEGOTIATION) - && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && - ssl->state == MBEDTLS_SSL_SERVER_HELLO ) -#endif - ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); - } - - /* Check epoch (and sequence number) with DTLS */ - if( rec_epoch != ssl->in_epoch ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: " - "expected %d, received %d", - ssl->in_epoch, rec_epoch ) ); - -#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) - /* - * Check for an epoch 0 ClientHello. We can't use in_msg here to - * access the first byte of record content (handshake type), as we - * have an active transform (possibly iv_len != 0), so use the - * fact that the record header len is 13 instead. - */ - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && - rec_epoch == 0 && - ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_left > 13 && - ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect " - "from the same port" ) ); - return( ssl_handle_possible_reconnect( ssl ) ); - } - else -#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ - return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); - } - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - /* Replay detection only works for the current epoch */ - if( rec_epoch == ssl->in_epoch && - mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); - } -#endif - } -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - - return( 0 ); -} - -/* - * If applicable, decrypt (and decompress) record content - */ -static int ssl_prepare_record_content( mbedtls_ssl_context *ssl ) -{ - int ret, done = 0; - - MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network", - ssl->in_hdr, mbedtls_ssl_hdr_len( ssl ) + ssl->in_msglen ); - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_read != NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_read()" ) ); - - ret = mbedtls_ssl_hw_record_read( ssl ); - if( ret != 0 && ret != MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_read", ret ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - - if( ret == 0 ) - done = 1; - } -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ - if( !done && ssl->transform_in != NULL ) - { - if( ( ret = ssl_decrypt_buf( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt", - ssl->in_msg, ssl->in_msglen ); - - if( ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); - return( MBEDTLS_ERR_SSL_INVALID_RECORD ); - } - } - -#if defined(MBEDTLS_ZLIB_SUPPORT) - if( ssl->transform_in != NULL && - ssl->session_in->compression == MBEDTLS_SSL_COMPRESS_DEFLATE ) - { - if( ( ret = ssl_decompress_buf( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decompress_buf", ret ); - return( ret ); - } - } -#endif /* MBEDTLS_ZLIB_SUPPORT */ - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - mbedtls_ssl_dtls_replay_update( ssl ); - } -#endif - - return( 0 ); -} - -static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ); - -/* - * Read a record. - * - * Silently ignore non-fatal alert (and for DTLS, invalid records as well, - * RFC 6347 4.1.2.7) and continue reading until a valid record is found. - * - */ -int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl ) -{ - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) ); - - if( ssl->keep_current_message == 0 ) - { - do { - - if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); - return( ret ); - } - - ret = mbedtls_ssl_handle_message_type( ssl ); - - } while( MBEDTLS_ERR_SSL_NON_FATAL == ret ); - - if( 0 != ret ) - { - MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret ); - return( ret ); - } - - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) - { - mbedtls_ssl_update_handshake_status( ssl ); - } - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= reuse previously read message" ) ); - ssl->keep_current_message = 0; - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) ); - - return( 0 ); -} - -int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl ) -{ - int ret; - - /* - * Step A - * - * Consume last content-layer message and potentially - * update in_msglen which keeps track of the contents' - * consumption state. - * - * (1) Handshake messages: - * Remove last handshake message, move content - * and adapt in_msglen. - * - * (2) Alert messages: - * Consume whole record content, in_msglen = 0. - * - * NOTE: This needs to be fixed, since like for - * handshake messages it is allowed to have - * multiple alerts witin a single record. - * Internal reference IOTSSL-1321. - * - * (3) Change cipher spec: - * Consume whole record content, in_msglen = 0. - * - * (4) Application data: - * Don't do anything - the record layer provides - * the application data as a stream transport - * and consumes through mbedtls_ssl_read only. - * - */ - - /* Case (1): Handshake messages */ - if( ssl->in_hslen != 0 ) - { - /* Hard assertion to be sure that no application data - * is in flight, as corrupting ssl->in_msglen during - * ssl->in_offt != NULL is fatal. */ - if( ssl->in_offt != NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - /* - * Get next Handshake message in the current record - */ - - /* Notes: - * (1) in_hslen is *NOT* necessarily the size of the - * current handshake content: If DTLS handshake - * fragmentation is used, that's the fragment - * size instead. Using the total handshake message - * size here is FAULTY and should be changed at - * some point. Internal reference IOTSSL-1414. - * (2) While it doesn't seem to cause problems, one - * has to be very careful not to assume that in_hslen - * is always <= in_msglen in a sensible communication. - * Again, it's wrong for DTLS handshake fragmentation. - * The following check is therefore mandatory, and - * should not be treated as a silently corrected assertion. - * Additionally, ssl->in_hslen might be arbitrarily out of - * bounds after handling a DTLS message with an unexpected - * sequence number, see mbedtls_ssl_prepare_handshake_record. - */ - if( ssl->in_hslen < ssl->in_msglen ) - { - ssl->in_msglen -= ssl->in_hslen; - memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, - ssl->in_msglen ); - - MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record", - ssl->in_msg, ssl->in_msglen ); - } - else - { - ssl->in_msglen = 0; - } - - ssl->in_hslen = 0; - } - /* Case (4): Application data */ - else if( ssl->in_offt != NULL ) - { - return( 0 ); - } - /* Everything else (CCS & Alerts) */ - else - { - ssl->in_msglen = 0; - } - - /* - * Step B - * - * Fetch and decode new record if current one is fully consumed. - * - */ - - if( ssl->in_msglen > 0 ) - { - /* There's something left to be processed in the current record. */ - return( 0 ); - } - - /* Need to fetch a new record */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -read_record_header: -#endif - - /* Current record either fully processed or to be discarded. */ - - if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); - return( ret ); - } - - if( ( ret = ssl_parse_record_header( ssl ) ) != 0 ) - { -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT ) - { - if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ) - { - /* Skip unexpected record (but not whole datagram) */ - ssl->next_record_offset = ssl->in_msglen - + mbedtls_ssl_hdr_len( ssl ); - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record " - "(header)" ) ); - } - else - { - /* Skip invalid record and the rest of the datagram */ - ssl->next_record_offset = 0; - ssl->in_left = 0; - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record " - "(header)" ) ); - } - - /* Get next record */ - goto read_record_header; - } -#endif - return( ret ); - } - - /* - * Read and optionally decrypt the message contents - */ - if( ( ret = mbedtls_ssl_fetch_input( ssl, - mbedtls_ssl_hdr_len( ssl ) + ssl->in_msglen ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); - return( ret ); - } - - /* Done reading this record, get ready for the next one */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - ssl->next_record_offset = ssl->in_msglen + mbedtls_ssl_hdr_len( ssl ); - else -#endif - ssl->in_left = 0; - - if( ( ret = ssl_prepare_record_content( ssl ) ) != 0 ) - { -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - /* Silently discard invalid records */ - if( ret == MBEDTLS_ERR_SSL_INVALID_RECORD || - ret == MBEDTLS_ERR_SSL_INVALID_MAC ) - { - /* Except when waiting for Finished as a bad mac here - * probably means something went wrong in the handshake - * (eg wrong psk used, mitm downgrade attempt, etc.) */ - if( ssl->state == MBEDTLS_SSL_CLIENT_FINISHED || - ssl->state == MBEDTLS_SSL_SERVER_FINISHED ) - { -#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) - if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) - { - mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); - } -#endif - return( ret ); - } - -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) - if( ssl->conf->badmac_limit != 0 && - ++ssl->badmac_seen >= ssl->conf->badmac_limit ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) ); - return( MBEDTLS_ERR_SSL_INVALID_MAC ); - } -#endif - - /* As above, invalid records cause - * dismissal of the whole datagram. */ - - ssl->next_record_offset = 0; - ssl->in_left = 0; - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) ); - goto read_record_header; - } - - return( ret ); - } - else -#endif - { - /* Error out (and send alert) on invalid records */ -#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) - if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) - { - mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); - } -#endif - return( ret ); - } - } - - /* - * When we sent the last flight of the handshake, we MUST respond to a - * retransmit of the peer's previous flight with a retransmit. (In - * practice, only the Finished message will make it, other messages - * including CCS use the old transform so they're dropped as invalid.) - * - * If the record we received is not a handshake message, however, it - * means the peer received our last flight so we can clean up - * handshake info. - * - * This check needs to be done before prepare_handshake() due to an edge - * case: if the client immediately requests renegotiation, this - * finishes the current handshake first, avoiding the new ClientHello - * being mistaken for an ancient message in the current handshake. - */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake != NULL && - ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) - { - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "received retransmit of last flight" ) ); - - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); - return( ret ); - } - - return( MBEDTLS_ERR_SSL_WANT_READ ); - } - else - { - ssl_handshake_wrapup_free_hs_transform( ssl ); - } - } -#endif - - return( 0 ); -} - -int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) -{ - int ret; - - /* - * Handle particular types of records - */ - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) - { - if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 ) - { - return( ret ); - } - } - - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%d:%d]", - ssl->in_msg[0], ssl->in_msg[1] ) ); - - /* - * Ignore non-fatal alerts, except close_notify and no_renegotiation - */ - if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)", - ssl->in_msg[1] ) ); - return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE ); - } - - if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && - ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a close notify message" ) ); - return( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ); - } - -#if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED) - if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && - ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); - /* Will be handled when trying to parse ServerHello */ - return( 0 ); - } -#endif - -#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_SRV_C) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 && - ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && - ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) ); - /* Will be handled in mbedtls_ssl_parse_certificate() */ - return( 0 ); - } -#endif /* MBEDTLS_SSL_PROTO_SSL3 && MBEDTLS_SSL_SRV_C */ - - /* Silently ignore: fetch new message */ - return MBEDTLS_ERR_SSL_NON_FATAL; - } - - return( 0 ); -} - -int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ) -{ - int ret; - - if( ( ret = mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ) != 0 ) - { - return( ret ); - } - - return( 0 ); -} - -int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, - unsigned char level, - unsigned char message ) -{ - int ret; - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); - MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message )); - - ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; - ssl->out_msglen = 2; - ssl->out_msg[0] = level; - ssl->out_msg[1] = message; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); - - return( 0 ); -} - -/* - * Handshake functions - */ -#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ - !defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) -/* No certificate support -> dummy functions */ -int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) -{ - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); - ssl->state++; - return( 0 ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); -} - -int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) -{ - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - ssl->state++; - return( 0 ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); -} - -#else -/* Some certificate support -> implement write and parse */ - -int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - size_t i, n; - const mbedtls_x509_crt *crt; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); - ssl->state++; - return( 0 ); - } - -#if defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - { - if( ssl->client_auth == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); - ssl->state++; - return( 0 ); - } - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - /* - * If using SSLv3 and got no cert, send an Alert message - * (otherwise an empty Certificate message will be sent). - */ - if( mbedtls_ssl_own_cert( ssl ) == NULL && - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - ssl->out_msglen = 2; - ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; - ssl->out_msg[0] = MBEDTLS_SSL_ALERT_LEVEL_WARNING; - ssl->out_msg[1] = MBEDTLS_SSL_ALERT_MSG_NO_CERT; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "got no certificate to send" ) ); - goto write_msg; - } -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - } -#endif /* MBEDTLS_SSL_CLI_C */ -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - { - if( mbedtls_ssl_own_cert( ssl ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no certificate to send" ) ); - return( MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED ); - } - } -#endif - - MBEDTLS_SSL_DEBUG_CRT( 3, "own certificate", mbedtls_ssl_own_cert( ssl ) ); - - /* - * 0 . 0 handshake type - * 1 . 3 handshake length - * 4 . 6 length of all certs - * 7 . 9 length of cert. 1 - * 10 . n-1 peer certificate - * n . n+2 length of cert. 2 - * n+3 . ... upper level cert, etc. - */ - i = 7; - crt = mbedtls_ssl_own_cert( ssl ); - - while( crt != NULL ) - { - n = crt->raw.len; - if( n > MBEDTLS_SSL_MAX_CONTENT_LEN - 3 - i ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %d > %d", - i + 3 + n, MBEDTLS_SSL_MAX_CONTENT_LEN ) ); - return( MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE ); - } - - ssl->out_msg[i ] = (unsigned char)( n >> 16 ); - ssl->out_msg[i + 1] = (unsigned char)( n >> 8 ); - ssl->out_msg[i + 2] = (unsigned char)( n ); - - i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n ); - i += n; crt = crt->next; - } - - ssl->out_msg[4] = (unsigned char)( ( i - 7 ) >> 16 ); - ssl->out_msg[5] = (unsigned char)( ( i - 7 ) >> 8 ); - ssl->out_msg[6] = (unsigned char)( ( i - 7 ) ); - - ssl->out_msglen = i; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; - -#if defined(MBEDTLS_SSL_PROTO_SSL3) && defined(MBEDTLS_SSL_CLI_C) -write_msg: -#endif - - ssl->state++; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate" ) ); - - return( ret ); -} - -int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - size_t i, n; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - int authmode = ssl->conf->authmode; - uint8_t alert; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - ssl->state++; - return( 0 ); - } - -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - ssl->state++; - return( 0 ); - } - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) - authmode = ssl->handshake->sni_authmode; -#endif - - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - authmode == MBEDTLS_SSL_VERIFY_NONE ) - { - ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - ssl->state++; - return( 0 ); - } -#endif - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - /* mbedtls_ssl_read_record may have sent an alert already. We - let it decide whether to alert. */ - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - ssl->state++; - -#if defined(MBEDTLS_SSL_SRV_C) -#if defined(MBEDTLS_SSL_PROTO_SSL3) - /* - * Check if the client sent an empty certificate - */ - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - if( ssl->in_msglen == 2 && - ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT && - ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && - ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) ); - - /* The client was asked for a certificate but didn't send - one. The client should know what's going on, so we - don't send an alert. */ - ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; - if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) - return( 0 ); - else - return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); - } - } -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 ) - { - if( ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len( ssl ) && - ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && - ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE && - memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) ); - - /* The client was asked for a certificate but didn't send - one. The client should know what's going on, so we - don't send an alert. */ - ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; - if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) - return( 0 ); - else - return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); - } - } -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ - MBEDTLS_SSL_PROTO_TLS1_2 */ -#endif /* MBEDTLS_SSL_SRV_C */ - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE || - ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - i = mbedtls_ssl_hs_hdr_len( ssl ); - - /* - * Same message structure as in mbedtls_ssl_write_certificate() - */ - n = ( ssl->in_msg[i+1] << 8 ) | ssl->in_msg[i+2]; - - if( ssl->in_msg[i] != 0 || - ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - /* In case we tried to reuse a session but it failed */ - if( ssl->session_negotiate->peer_cert != NULL ) - { - mbedtls_x509_crt_free( ssl->session_negotiate->peer_cert ); - mbedtls_free( ssl->session_negotiate->peer_cert ); - } - - if( ( ssl->session_negotiate->peer_cert = mbedtls_calloc( 1, - sizeof( mbedtls_x509_crt ) ) ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", - sizeof( mbedtls_x509_crt ) ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert ); - - i += 3; - - while( i < ssl->in_hslen ) - { - if( ssl->in_msg[i] != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - n = ( (unsigned int) ssl->in_msg[i + 1] << 8 ) - | (unsigned int) ssl->in_msg[i + 2]; - i += 3; - - if( n < 128 || i + n > ssl->in_hslen ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert, - ssl->in_msg + i, n ); - switch( ret ) - { - case 0: /*ok*/ - case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: - /* Ignore certificate with an unknown algorithm: maybe a - prior certificate was already trusted. */ - break; - - case MBEDTLS_ERR_X509_ALLOC_FAILED: - alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR; - goto crt_parse_der_failed; - - case MBEDTLS_ERR_X509_UNKNOWN_VERSION: - alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; - goto crt_parse_der_failed; - - default: - alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; - crt_parse_der_failed: - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert ); - MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret ); - return( ret ); - } - - i += n; - } - - MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert ); - - /* - * On client, make sure the server cert doesn't change during renego to - * avoid "triple handshake" attack: https://secure-resumption.com/ - */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && - ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - { - if( ssl->session->peer_cert == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - - if( ssl->session->peer_cert->raw.len != - ssl->session_negotiate->peer_cert->raw.len || - memcmp( ssl->session->peer_cert->raw.p, - ssl->session_negotiate->peer_cert->raw.p, - ssl->session->peer_cert->raw.len ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "server cert changed during renegotiation" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED ); - return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ); - } - } -#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ - - if( authmode != MBEDTLS_SSL_VERIFY_NONE ) - { - mbedtls_x509_crt *ca_chain; - mbedtls_x509_crl *ca_crl; - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if( ssl->handshake->sni_ca_chain != NULL ) - { - ca_chain = ssl->handshake->sni_ca_chain; - ca_crl = ssl->handshake->sni_ca_crl; - } - else -#endif - { - ca_chain = ssl->conf->ca_chain; - ca_crl = ssl->conf->ca_crl; - } - - /* - * Main check: verify certificate - */ - ret = mbedtls_x509_crt_verify_with_profile( - ssl->session_negotiate->peer_cert, - ca_chain, ca_crl, - ssl->conf->cert_profile, - ssl->hostname, - &ssl->session_negotiate->verify_result, - ssl->conf->f_vrfy, ssl->conf->p_vrfy ); - - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); - } - - /* - * Secondary checks: always done, but change 'ret' only if it was 0 - */ - -#if defined(MBEDTLS_ECP_C) - { - const mbedtls_pk_context *pk = &ssl->session_negotiate->peer_cert->pk; - - /* If certificate uses an EC key, make sure the curve is OK */ - if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) && - mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 ) - { - ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY; - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) ); - if( ret == 0 ) - ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; - } - } -#endif /* MBEDTLS_ECP_C */ - - if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert, - ciphersuite_info, - ! ssl->conf->endpoint, - &ssl->session_negotiate->verify_result ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) ); - if( ret == 0 ) - ret = MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE; - } - - /* mbedtls_x509_crt_verify_with_profile is supposed to report a - * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED, - * with details encoded in the verification flags. All other kinds - * of error codes, including those from the user provided f_vrfy - * functions, are treated as fatal and lead to a failure of - * ssl_parse_certificate even if verification was optional. */ - if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL && - ( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED || - ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) ) - { - ret = 0; - } - - if( ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); - ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; - } - - if( ret != 0 ) - { - /* The certificate may have been rejected for several reasons. - Pick one and send the corresponding alert. Which alert to send - may be a subject of debate in some cases. */ - if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER ) - alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED; - else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH ) - alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; - else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE ) - alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; - else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE ) - alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; - else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE ) - alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; - else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK ) - alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; - else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY ) - alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; - else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED ) - alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED; - else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED ) - alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED; - else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED ) - alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA; - else - alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN; - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - alert ); - } - -#if defined(MBEDTLS_DEBUG_C) - if( ssl->session_negotiate->verify_result != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %x", - ssl->session_negotiate->verify_result ) ); - } - else - { - MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) ); - } -#endif /* MBEDTLS_DEBUG_C */ - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); - - return( ret ); -} -#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED - !MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED - !MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED - !MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED - !MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - !MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED - !MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ - -int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ) -{ - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) ); - - ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; - ssl->out_msglen = 1; - ssl->out_msg[0] = 1; - - ssl->state++; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) ); - - return( 0 ); -} - -int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) -{ - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - if( ssl->in_msglen != 1 || ssl->in_msg[0] != 1 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC ); - } - - /* - * Switch to our negotiated transform and session parameters for inbound - * data. - */ - MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) ); - ssl->transform_in = ssl->transform_negotiate; - ssl->session_in = ssl->session_negotiate; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - ssl_dtls_replay_reset( ssl ); -#endif - - /* Increment epoch */ - if( ++ssl->in_epoch == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); - /* This is highly unlikely to happen for legitimate reasons, so - treat it as an attack and don't send an alert. */ - return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); - } - } - else -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - memset( ssl->in_ctr, 0, 8 ); - - /* - * Set the in_msg pointer to the correct location based on IV length - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - ssl->in_msg = ssl->in_iv + ssl->transform_negotiate->ivlen - - ssl->transform_negotiate->fixed_ivlen; - } - else - ssl->in_msg = ssl->in_iv; - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_activate != NULL ) - { - if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_INBOUND ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - } -#endif - - ssl->state++; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) ); - - return( 0 ); -} - -void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, - const mbedtls_ssl_ciphersuite_t *ciphersuite_info ) -{ - ((void) ciphersuite_info); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) - ssl->handshake->update_checksum = ssl_update_checksum_md5sha1; - else -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA512_C) - if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) - ssl->handshake->update_checksum = ssl_update_checksum_sha384; - else -#endif -#if defined(MBEDTLS_SHA256_C) - if( ciphersuite_info->mac != MBEDTLS_MD_SHA384 ) - ssl->handshake->update_checksum = ssl_update_checksum_sha256; - else -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return; - } -} - -void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ) -{ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_starts( &ssl->handshake->fin_md5 ); - mbedtls_sha1_starts( &ssl->handshake->fin_sha1 ); -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) - mbedtls_sha256_starts( &ssl->handshake->fin_sha256, 0 ); -#endif -#if defined(MBEDTLS_SHA512_C) - mbedtls_sha512_starts( &ssl->handshake->fin_sha512, 1 ); -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -} - -static void ssl_update_checksum_start( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_update( &ssl->handshake->fin_md5 , buf, len ); - mbedtls_sha1_update( &ssl->handshake->fin_sha1, buf, len ); -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) - mbedtls_sha256_update( &ssl->handshake->fin_sha256, buf, len ); -#endif -#if defined(MBEDTLS_SHA512_C) - mbedtls_sha512_update( &ssl->handshake->fin_sha512, buf, len ); -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -} - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) -static void ssl_update_checksum_md5sha1( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ - mbedtls_md5_update( &ssl->handshake->fin_md5 , buf, len ); - mbedtls_sha1_update( &ssl->handshake->fin_sha1, buf, len ); -} -#endif - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -static void ssl_update_checksum_sha256( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ - mbedtls_sha256_update( &ssl->handshake->fin_sha256, buf, len ); -} -#endif - -#if defined(MBEDTLS_SHA512_C) -static void ssl_update_checksum_sha384( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ - mbedtls_sha512_update( &ssl->handshake->fin_sha512, buf, len ); -} -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -#if defined(MBEDTLS_SSL_PROTO_SSL3) -static void ssl_calc_finished_ssl( - mbedtls_ssl_context *ssl, unsigned char *buf, int from ) -{ - const char *sender; - mbedtls_md5_context md5; - mbedtls_sha1_context sha1; - - unsigned char padbuf[48]; - unsigned char md5sum[16]; - unsigned char sha1sum[20]; - - mbedtls_ssl_session *session = ssl->session_negotiate; - if( !session ) - session = ssl->session; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished ssl" ) ); - - mbedtls_md5_init( &md5 ); - mbedtls_sha1_init( &sha1 ); - - mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); - mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); - - /* - * SSLv3: - * hash = - * MD5( master + pad2 + - * MD5( handshake + sender + master + pad1 ) ) - * + SHA1( master + pad2 + - * SHA1( handshake + sender + master + pad1 ) ) - */ - -#if !defined(MBEDTLS_MD5_ALT) - MBEDTLS_SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) - md5.state, sizeof( md5.state ) ); -#endif - -#if !defined(MBEDTLS_SHA1_ALT) - MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) - sha1.state, sizeof( sha1.state ) ); -#endif - - sender = ( from == MBEDTLS_SSL_IS_CLIENT ) ? "CLNT" - : "SRVR"; - - memset( padbuf, 0x36, 48 ); - - mbedtls_md5_update( &md5, (const unsigned char *) sender, 4 ); - mbedtls_md5_update( &md5, session->master, 48 ); - mbedtls_md5_update( &md5, padbuf, 48 ); - mbedtls_md5_finish( &md5, md5sum ); - - mbedtls_sha1_update( &sha1, (const unsigned char *) sender, 4 ); - mbedtls_sha1_update( &sha1, session->master, 48 ); - mbedtls_sha1_update( &sha1, padbuf, 40 ); - mbedtls_sha1_finish( &sha1, sha1sum ); - - memset( padbuf, 0x5C, 48 ); - - mbedtls_md5_starts( &md5 ); - mbedtls_md5_update( &md5, session->master, 48 ); - mbedtls_md5_update( &md5, padbuf, 48 ); - mbedtls_md5_update( &md5, md5sum, 16 ); - mbedtls_md5_finish( &md5, buf ); - - mbedtls_sha1_starts( &sha1 ); - mbedtls_sha1_update( &sha1, session->master, 48 ); - mbedtls_sha1_update( &sha1, padbuf , 40 ); - mbedtls_sha1_update( &sha1, sha1sum, 20 ); - mbedtls_sha1_finish( &sha1, buf + 16 ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, 36 ); - - mbedtls_md5_free( &md5 ); - mbedtls_sha1_free( &sha1 ); - - mbedtls_zeroize( padbuf, sizeof( padbuf ) ); - mbedtls_zeroize( md5sum, sizeof( md5sum ) ); - mbedtls_zeroize( sha1sum, sizeof( sha1sum ) ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); -} -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -static void ssl_calc_finished_tls( - mbedtls_ssl_context *ssl, unsigned char *buf, int from ) -{ - int len = 12; - const char *sender; - mbedtls_md5_context md5; - mbedtls_sha1_context sha1; - unsigned char padbuf[36]; - - mbedtls_ssl_session *session = ssl->session_negotiate; - if( !session ) - session = ssl->session; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls" ) ); - - mbedtls_md5_init( &md5 ); - mbedtls_sha1_init( &sha1 ); - - mbedtls_md5_clone( &md5, &ssl->handshake->fin_md5 ); - mbedtls_sha1_clone( &sha1, &ssl->handshake->fin_sha1 ); - - /* - * TLSv1: - * hash = PRF( master, finished_label, - * MD5( handshake ) + SHA1( handshake ) )[0..11] - */ - -#if !defined(MBEDTLS_MD5_ALT) - MBEDTLS_SSL_DEBUG_BUF( 4, "finished md5 state", (unsigned char *) - md5.state, sizeof( md5.state ) ); -#endif - -#if !defined(MBEDTLS_SHA1_ALT) - MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha1 state", (unsigned char *) - sha1.state, sizeof( sha1.state ) ); -#endif - - sender = ( from == MBEDTLS_SSL_IS_CLIENT ) - ? "client finished" - : "server finished"; - - mbedtls_md5_finish( &md5, padbuf ); - mbedtls_sha1_finish( &sha1, padbuf + 16 ); - - ssl->handshake->tls_prf( session->master, 48, sender, - padbuf, 36, buf, len ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); - - mbedtls_md5_free( &md5 ); - mbedtls_sha1_free( &sha1 ); - - mbedtls_zeroize( padbuf, sizeof( padbuf ) ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); -} -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) -static void ssl_calc_finished_tls_sha256( - mbedtls_ssl_context *ssl, unsigned char *buf, int from ) -{ - int len = 12; - const char *sender; - mbedtls_sha256_context sha256; - unsigned char padbuf[32]; - - mbedtls_ssl_session *session = ssl->session_negotiate; - if( !session ) - session = ssl->session; - - mbedtls_sha256_init( &sha256 ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) ); - - mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); - - /* - * TLSv1.2: - * hash = PRF( master, finished_label, - * Hash( handshake ) )[0.11] - */ - -#if !defined(MBEDTLS_SHA256_ALT) - MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *) - sha256.state, sizeof( sha256.state ) ); -#endif - - sender = ( from == MBEDTLS_SSL_IS_CLIENT ) - ? "client finished" - : "server finished"; - - mbedtls_sha256_finish( &sha256, padbuf ); - - ssl->handshake->tls_prf( session->master, 48, sender, - padbuf, 32, buf, len ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); - - mbedtls_sha256_free( &sha256 ); - - mbedtls_zeroize( padbuf, sizeof( padbuf ) ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); -} -#endif /* MBEDTLS_SHA256_C */ - -#if defined(MBEDTLS_SHA512_C) -static void ssl_calc_finished_tls_sha384( - mbedtls_ssl_context *ssl, unsigned char *buf, int from ) -{ - int len = 12; - const char *sender; - mbedtls_sha512_context sha512; - unsigned char padbuf[48]; - - mbedtls_ssl_session *session = ssl->session_negotiate; - if( !session ) - session = ssl->session; - - mbedtls_sha512_init( &sha512 ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha384" ) ); - - mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); - - /* - * TLSv1.2: - * hash = PRF( master, finished_label, - * Hash( handshake ) )[0.11] - */ - -#if !defined(MBEDTLS_SHA512_ALT) - MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha512 state", (unsigned char *) - sha512.state, sizeof( sha512.state ) ); -#endif - - sender = ( from == MBEDTLS_SSL_IS_CLIENT ) - ? "client finished" - : "server finished"; - - mbedtls_sha512_finish( &sha512, padbuf ); - - ssl->handshake->tls_prf( session->master, 48, sender, - padbuf, 48, buf, len ); - - MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); - - mbedtls_sha512_free( &sha512 ); - - mbedtls_zeroize( padbuf, sizeof( padbuf ) ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); -} -#endif /* MBEDTLS_SHA512_C */ -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ) -{ - MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup: final free" ) ); - - /* - * Free our handshake params - */ - mbedtls_ssl_handshake_free( ssl->handshake ); - mbedtls_free( ssl->handshake ); - ssl->handshake = NULL; - - /* - * Free the previous transform and swith in the current one - */ - if( ssl->transform ) - { - mbedtls_ssl_transform_free( ssl->transform ); - mbedtls_free( ssl->transform ); - } - ssl->transform = ssl->transform_negotiate; - ssl->transform_negotiate = NULL; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup: final free" ) ); -} - -void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ) -{ - int resume = ssl->handshake->resume; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - { - ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_DONE; - ssl->renego_records_seen = 0; - } -#endif - - /* - * Free the previous session and switch in the current one - */ - if( ssl->session ) - { -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - /* RFC 7366 3.1: keep the EtM state */ - ssl->session_negotiate->encrypt_then_mac = - ssl->session->encrypt_then_mac; -#endif - - mbedtls_ssl_session_free( ssl->session ); - mbedtls_free( ssl->session ); - } - ssl->session = ssl->session_negotiate; - ssl->session_negotiate = NULL; - - /* - * Add cache entry - */ - if( ssl->conf->f_set_cache != NULL && - ssl->session->id_len != 0 && - resume == 0 ) - { - if( ssl->conf->f_set_cache( ssl->conf->p_cache, ssl->session ) != 0 ) - MBEDTLS_SSL_DEBUG_MSG( 1, ( "cache did not store session" ) ); - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->handshake->flight != NULL ) - { - /* Cancel handshake timer */ - ssl_set_timer( ssl, 0 ); - - /* Keep last flight around in case we need to resend it: - * we need the handshake and transform structures for that */ - MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip freeing handshake and transform" ) ); - } - else -#endif - ssl_handshake_wrapup_free_hs_transform( ssl ); - - ssl->state++; - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) ); -} - -int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) -{ - int ret, hash_len; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); - - /* - * Set the out_msg pointer to the correct location based on IV length - */ - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) - { - ssl->out_msg = ssl->out_iv + ssl->transform_negotiate->ivlen - - ssl->transform_negotiate->fixed_ivlen; - } - else - ssl->out_msg = ssl->out_iv; - - ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint ); - - /* - * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites - * may define some other value. Currently (early 2016), no defined - * ciphersuite does this (and this is unlikely to change as activity has - * moved to TLS 1.3 now) so we can keep the hardcoded 12 here. - */ - hash_len = ( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) ? 36 : 12; - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->verify_data_len = hash_len; - memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len ); -#endif - - ssl->out_msglen = 4 + hash_len; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_FINISHED; - - /* - * In case of session resuming, invert the client and server - * ChangeCipherSpec messages order. - */ - if( ssl->handshake->resume != 0 ) - { -#if defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; -#endif -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; -#endif - } - else - ssl->state++; - - /* - * Switch to our negotiated transform and session parameters for outbound - * data. - */ - MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - unsigned char i; - - /* Remember current epoch settings for resending */ - ssl->handshake->alt_transform_out = ssl->transform_out; - memcpy( ssl->handshake->alt_out_ctr, ssl->out_ctr, 8 ); - - /* Set sequence_number to zero */ - memset( ssl->out_ctr + 2, 0, 6 ); - - /* Increment epoch */ - for( i = 2; i > 0; i-- ) - if( ++ssl->out_ctr[i - 1] != 0 ) - break; - - /* The loop goes to its end iff the counter is wrapping */ - if( i == 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); - return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); - } - } - else -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - memset( ssl->out_ctr, 0, 8 ); - - ssl->transform_out = ssl->transform_negotiate; - ssl->session_out = ssl->session_negotiate; - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_activate != NULL ) - { - if( ( ret = mbedtls_ssl_hw_record_activate( ssl, MBEDTLS_SSL_CHANNEL_OUTBOUND ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_activate", ret ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - } -#endif - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - mbedtls_ssl_send_flight_completed( ssl ); -#endif - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished" ) ); - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_PROTO_SSL3) -#define SSL_MAX_HASH_LEN 36 -#else -#define SSL_MAX_HASH_LEN 12 -#endif - -int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) -{ - int ret; - unsigned int hash_len; - unsigned char buf[SSL_MAX_HASH_LEN]; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse finished" ) ); - - ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 ); - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - /* There is currently no ciphersuite using another length with TLS 1.2 */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - hash_len = 36; - else -#endif - hash_len = 12; - - if( ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED || - ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + hash_len ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); - } - - if( mbedtls_ssl_safer_memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), - buf, hash_len ) != 0 ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); - return( MBEDTLS_ERR_SSL_BAD_HS_FINISHED ); - } - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->verify_data_len = hash_len; - memcpy( ssl->peer_verify_data, buf, hash_len ); -#endif - - if( ssl->handshake->resume != 0 ) - { -#if defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; -#endif -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; -#endif - } - else - ssl->state++; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - mbedtls_ssl_recv_flight_completed( ssl ); -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse finished" ) ); - - return( 0 ); -} - -static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) -{ - memset( handshake, 0, sizeof( mbedtls_ssl_handshake_params ) ); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_init( &handshake->fin_md5 ); - mbedtls_sha1_init( &handshake->fin_sha1 ); - mbedtls_md5_starts( &handshake->fin_md5 ); - mbedtls_sha1_starts( &handshake->fin_sha1 ); -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) - mbedtls_sha256_init( &handshake->fin_sha256 ); - mbedtls_sha256_starts( &handshake->fin_sha256, 0 ); -#endif -#if defined(MBEDTLS_SHA512_C) - mbedtls_sha512_init( &handshake->fin_sha512 ); - mbedtls_sha512_starts( &handshake->fin_sha512, 1 ); -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - - handshake->update_checksum = ssl_update_checksum_start; - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - mbedtls_ssl_sig_hash_set_init( &handshake->hash_algs ); -#endif - -#if defined(MBEDTLS_DHM_C) - mbedtls_dhm_init( &handshake->dhm_ctx ); -#endif -#if defined(MBEDTLS_ECDH_C) - mbedtls_ecdh_init( &handshake->ecdh_ctx ); -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - mbedtls_ecjpake_init( &handshake->ecjpake_ctx ); -#if defined(MBEDTLS_SSL_CLI_C) - handshake->ecjpake_cache = NULL; - handshake->ecjpake_cache_len = 0; -#endif -#endif - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; -#endif -} - -static void ssl_transform_init( mbedtls_ssl_transform *transform ) -{ - memset( transform, 0, sizeof(mbedtls_ssl_transform) ); - - mbedtls_cipher_init( &transform->cipher_ctx_enc ); - mbedtls_cipher_init( &transform->cipher_ctx_dec ); - - mbedtls_md_init( &transform->md_ctx_enc ); - mbedtls_md_init( &transform->md_ctx_dec ); -} - -void mbedtls_ssl_session_init( mbedtls_ssl_session *session ) -{ - memset( session, 0, sizeof(mbedtls_ssl_session) ); -} - -static int ssl_handshake_init( mbedtls_ssl_context *ssl ) -{ - /* Clear old handshake information if present */ - if( ssl->transform_negotiate ) - mbedtls_ssl_transform_free( ssl->transform_negotiate ); - if( ssl->session_negotiate ) - mbedtls_ssl_session_free( ssl->session_negotiate ); - if( ssl->handshake ) - mbedtls_ssl_handshake_free( ssl->handshake ); - - /* - * Either the pointers are now NULL or cleared properly and can be freed. - * Now allocate missing structures. - */ - if( ssl->transform_negotiate == NULL ) - { - ssl->transform_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_transform) ); - } - - if( ssl->session_negotiate == NULL ) - { - ssl->session_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_session) ); - } - - if( ssl->handshake == NULL ) - { - ssl->handshake = mbedtls_calloc( 1, sizeof(mbedtls_ssl_handshake_params) ); - } - - /* All pointers should exist and can be directly freed without issue */ - if( ssl->handshake == NULL || - ssl->transform_negotiate == NULL || - ssl->session_negotiate == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc() of ssl sub-contexts failed" ) ); - - mbedtls_free( ssl->handshake ); - mbedtls_free( ssl->transform_negotiate ); - mbedtls_free( ssl->session_negotiate ); - - ssl->handshake = NULL; - ssl->transform_negotiate = NULL; - ssl->session_negotiate = NULL; - - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - /* Initialize structures */ - mbedtls_ssl_session_init( ssl->session_negotiate ); - ssl_transform_init( ssl->transform_negotiate ); - ssl_handshake_params_init( ssl->handshake ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - ssl->handshake->alt_transform_out = ssl->transform_out; - - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; - else - ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; - - ssl_set_timer( ssl, 0 ); - } -#endif - - return( 0 ); -} - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) -/* Dummy cookie callbacks for defaults */ -static int ssl_cookie_write_dummy( void *ctx, - unsigned char **p, unsigned char *end, - const unsigned char *cli_id, size_t cli_id_len ) -{ - ((void) ctx); - ((void) p); - ((void) end); - ((void) cli_id); - ((void) cli_id_len); - - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); -} - -static int ssl_cookie_check_dummy( void *ctx, - const unsigned char *cookie, size_t cookie_len, - const unsigned char *cli_id, size_t cli_id_len ) -{ - ((void) ctx); - ((void) cookie); - ((void) cookie_len); - ((void) cli_id); - ((void) cli_id_len); - - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); -} -#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ - -/* - * Initialize an SSL context - */ -void mbedtls_ssl_init( mbedtls_ssl_context *ssl ) -{ - memset( ssl, 0, sizeof( mbedtls_ssl_context ) ); -} - -/* - * Setup an SSL context - */ -int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, - const mbedtls_ssl_config *conf ) -{ - int ret; - const size_t len = MBEDTLS_SSL_BUFFER_LEN; - - ssl->conf = conf; - - /* - * Prepare base structures - */ - if( ( ssl-> in_buf = mbedtls_calloc( 1, len ) ) == NULL || - ( ssl->out_buf = mbedtls_calloc( 1, len ) ) == NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", len ) ); - mbedtls_free( ssl->in_buf ); - ssl->in_buf = NULL; - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - ssl->out_hdr = ssl->out_buf; - ssl->out_ctr = ssl->out_buf + 3; - ssl->out_len = ssl->out_buf + 11; - ssl->out_iv = ssl->out_buf + 13; - ssl->out_msg = ssl->out_buf + 13; - - ssl->in_hdr = ssl->in_buf; - ssl->in_ctr = ssl->in_buf + 3; - ssl->in_len = ssl->in_buf + 11; - ssl->in_iv = ssl->in_buf + 13; - ssl->in_msg = ssl->in_buf + 13; - } - else -#endif - { - ssl->out_ctr = ssl->out_buf; - ssl->out_hdr = ssl->out_buf + 8; - ssl->out_len = ssl->out_buf + 11; - ssl->out_iv = ssl->out_buf + 13; - ssl->out_msg = ssl->out_buf + 13; - - ssl->in_ctr = ssl->in_buf; - ssl->in_hdr = ssl->in_buf + 8; - ssl->in_len = ssl->in_buf + 11; - ssl->in_iv = ssl->in_buf + 13; - ssl->in_msg = ssl->in_buf + 13; - } - - if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -/* - * Reset an initialized and used SSL context for re-use while retaining - * all application-set variables, function pointers and data. - * - * If partial is non-zero, keep data in the input buffer and client ID. - * (Use when a DTLS client reconnects from the same port.) - */ -static int ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) -{ - int ret; - - ssl->state = MBEDTLS_SSL_HELLO_REQUEST; - - /* Cancel any possibly running timer */ - ssl_set_timer( ssl, 0 ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE; - ssl->renego_records_seen = 0; - - ssl->verify_data_len = 0; - memset( ssl->own_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); - memset( ssl->peer_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); -#endif - ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; - - ssl->in_offt = NULL; - - ssl->in_msg = ssl->in_buf + 13; - ssl->in_msgtype = 0; - ssl->in_msglen = 0; - if( partial == 0 ) - ssl->in_left = 0; -#if defined(MBEDTLS_SSL_PROTO_DTLS) - ssl->next_record_offset = 0; - ssl->in_epoch = 0; -#endif -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - ssl_dtls_replay_reset( ssl ); -#endif - - ssl->in_hslen = 0; - ssl->nb_zero = 0; - - ssl->keep_current_message = 0; - - ssl->out_msg = ssl->out_buf + 13; - ssl->out_msgtype = 0; - ssl->out_msglen = 0; - ssl->out_left = 0; -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - if( ssl->split_done != MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ) - ssl->split_done = 0; -#endif - - ssl->transform_in = NULL; - ssl->transform_out = NULL; - - memset( ssl->out_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); - if( partial == 0 ) - memset( ssl->in_buf, 0, MBEDTLS_SSL_BUFFER_LEN ); - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_reset != NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_reset()" ) ); - if( ( ret = mbedtls_ssl_hw_record_reset( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_hw_record_reset", ret ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - } -#endif - - if( ssl->transform ) - { - mbedtls_ssl_transform_free( ssl->transform ); - mbedtls_free( ssl->transform ); - ssl->transform = NULL; - } - - if( ssl->session ) - { - mbedtls_ssl_session_free( ssl->session ); - mbedtls_free( ssl->session ); - ssl->session = NULL; - } - -#if defined(MBEDTLS_SSL_ALPN) - ssl->alpn_chosen = NULL; -#endif - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) - if( partial == 0 ) - { - mbedtls_free( ssl->cli_id ); - ssl->cli_id = NULL; - ssl->cli_id_len = 0; - } -#endif - - if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -/* - * Reset an initialized and used SSL context for re-use while retaining - * all application-set variables, function pointers and data. - */ -int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) -{ - return( ssl_session_reset_int( ssl, 0 ) ); -} - -/* - * SSL set accessors - */ -void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ) -{ - conf->endpoint = endpoint; -} - -void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ) -{ - conf->transport = transport; -} - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) -void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ) -{ - conf->anti_replay = mode; -} -#endif - -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) -void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ) -{ - conf->badmac_limit = limit; -} -#endif - -#if defined(MBEDTLS_SSL_PROTO_DTLS) -void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ) -{ - conf->hs_timeout_min = min; - conf->hs_timeout_max = max; -} -#endif - -void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ) -{ - conf->authmode = authmode; -} - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ) -{ - conf->f_vrfy = f_vrfy; - conf->p_vrfy = p_vrfy; -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - conf->f_rng = f_rng; - conf->p_rng = p_rng; -} - -void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, - void (*f_dbg)(void *, int, const char *, int, const char *), - void *p_dbg ) -{ - conf->f_dbg = f_dbg; - conf->p_dbg = p_dbg; -} - -void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, - void *p_bio, - mbedtls_ssl_send_t *f_send, - mbedtls_ssl_recv_t *f_recv, - mbedtls_ssl_recv_timeout_t *f_recv_timeout ) -{ - ssl->p_bio = p_bio; - ssl->f_send = f_send; - ssl->f_recv = f_recv; - ssl->f_recv_timeout = f_recv_timeout; -} - -void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ) -{ - conf->read_timeout = timeout; -} - -void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, - void *p_timer, - mbedtls_ssl_set_timer_t *f_set_timer, - mbedtls_ssl_get_timer_t *f_get_timer ) -{ - ssl->p_timer = p_timer; - ssl->f_set_timer = f_set_timer; - ssl->f_get_timer = f_get_timer; - - /* Make sure we start with no timer running */ - ssl_set_timer( ssl, 0 ); -} - -#if defined(MBEDTLS_SSL_SRV_C) -void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, - void *p_cache, - int (*f_get_cache)(void *, mbedtls_ssl_session *), - int (*f_set_cache)(void *, const mbedtls_ssl_session *) ) -{ - conf->p_cache = p_cache; - conf->f_get_cache = f_get_cache; - conf->f_set_cache = f_set_cache; -} -#endif /* MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_SSL_CLI_C) -int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ) -{ - int ret; - - if( ssl == NULL || - session == NULL || - ssl->session_negotiate == NULL || - ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) - { - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - if( ( ret = ssl_session_copy( ssl->session_negotiate, session ) ) != 0 ) - return( ret ); - - ssl->handshake->resume = 1; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_CLI_C */ - -void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, - const int *ciphersuites ) -{ - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = ciphersuites; - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = ciphersuites; - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = ciphersuites; - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = ciphersuites; -} - -void mbedtls_ssl_conf_ciphersuites_for_version( mbedtls_ssl_config *conf, - const int *ciphersuites, - int major, int minor ) -{ - if( major != MBEDTLS_SSL_MAJOR_VERSION_3 ) - return; - - if( minor < MBEDTLS_SSL_MINOR_VERSION_0 || minor > MBEDTLS_SSL_MINOR_VERSION_3 ) - return; - - conf->ciphersuite_list[minor] = ciphersuites; -} - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, - const mbedtls_x509_crt_profile *profile ) -{ - conf->cert_profile = profile; -} - -/* Append a new keycert entry to a (possibly empty) list */ -static int ssl_append_key_cert( mbedtls_ssl_key_cert **head, - mbedtls_x509_crt *cert, - mbedtls_pk_context *key ) -{ - mbedtls_ssl_key_cert *new; - - new = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); - if( new == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - new->cert = cert; - new->key = key; - new->next = NULL; - - /* Update head is the list was null, else add to the end */ - if( *head == NULL ) - { - *head = new; - } - else - { - mbedtls_ssl_key_cert *cur = *head; - while( cur->next != NULL ) - cur = cur->next; - cur->next = new; - } - - return( 0 ); -} - -int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, - mbedtls_x509_crt *own_cert, - mbedtls_pk_context *pk_key ) -{ - return( ssl_append_key_cert( &conf->key_cert, own_cert, pk_key ) ); -} - -void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, - mbedtls_x509_crt *ca_chain, - mbedtls_x509_crl *ca_crl ) -{ - conf->ca_chain = ca_chain; - conf->ca_crl = ca_crl; -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) -int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, - mbedtls_x509_crt *own_cert, - mbedtls_pk_context *pk_key ) -{ - return( ssl_append_key_cert( &ssl->handshake->sni_key_cert, - own_cert, pk_key ) ); -} - -void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, - mbedtls_x509_crt *ca_chain, - mbedtls_x509_crl *ca_crl ) -{ - ssl->handshake->sni_ca_chain = ca_chain; - ssl->handshake->sni_ca_crl = ca_crl; -} - -void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, - int authmode ) -{ - ssl->handshake->sni_authmode = authmode; -} -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -/* - * Set EC J-PAKE password for current handshake - */ -int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, - const unsigned char *pw, - size_t pw_len ) -{ - mbedtls_ecjpake_role role; - - if( ssl->handshake == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - role = MBEDTLS_ECJPAKE_SERVER; - else - role = MBEDTLS_ECJPAKE_CLIENT; - - return( mbedtls_ecjpake_setup( &ssl->handshake->ecjpake_ctx, - role, - MBEDTLS_MD_SHA256, - MBEDTLS_ECP_DP_SECP256R1, - pw, pw_len ) ); -} -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, - const unsigned char *psk, size_t psk_len, - const unsigned char *psk_identity, size_t psk_identity_len ) -{ - if( psk == NULL || psk_identity == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( psk_len > MBEDTLS_PSK_MAX_LEN ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - /* Identity len will be encoded on two bytes */ - if( ( psk_identity_len >> 16 ) != 0 || - psk_identity_len > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - if( conf->psk != NULL || conf->psk_identity != NULL ) - { - mbedtls_free( conf->psk ); - mbedtls_free( conf->psk_identity ); - conf->psk = NULL; - conf->psk_identity = NULL; - } - - if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL || - ( conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ) ) == NULL ) - { - mbedtls_free( conf->psk ); - mbedtls_free( conf->psk_identity ); - conf->psk = NULL; - conf->psk_identity = NULL; - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - conf->psk_len = psk_len; - conf->psk_identity_len = psk_identity_len; - - memcpy( conf->psk, psk, conf->psk_len ); - memcpy( conf->psk_identity, psk_identity, conf->psk_identity_len ); - - return( 0 ); -} - -int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, - const unsigned char *psk, size_t psk_len ) -{ - if( psk == NULL || ssl->handshake == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( psk_len > MBEDTLS_PSK_MAX_LEN ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( ssl->handshake->psk != NULL ) - mbedtls_free( ssl->handshake->psk ); - - if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - ssl->handshake->psk_len = psk_len; - memcpy( ssl->handshake->psk, psk, ssl->handshake->psk_len ); - - return( 0 ); -} - -void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, - int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, - size_t), - void *p_psk ) -{ - conf->f_psk = f_psk; - conf->p_psk = p_psk; -} -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ - -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) -int mbedtls_ssl_conf_dh_param( mbedtls_ssl_config *conf, const char *dhm_P, const char *dhm_G ) -{ - int ret; - - if( ( ret = mbedtls_mpi_read_string( &conf->dhm_P, 16, dhm_P ) ) != 0 || - ( ret = mbedtls_mpi_read_string( &conf->dhm_G, 16, dhm_G ) ) != 0 ) - { - mbedtls_mpi_free( &conf->dhm_P ); - mbedtls_mpi_free( &conf->dhm_G ); - return( ret ); - } - - return( 0 ); -} - -int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ) -{ - int ret; - - if( ( ret = mbedtls_mpi_copy( &conf->dhm_P, &dhm_ctx->P ) ) != 0 || - ( ret = mbedtls_mpi_copy( &conf->dhm_G, &dhm_ctx->G ) ) != 0 ) - { - mbedtls_mpi_free( &conf->dhm_P ); - mbedtls_mpi_free( &conf->dhm_G ); - return( ret ); - } - - return( 0 ); -} -#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) -/* - * Set the minimum length for Diffie-Hellman parameters - */ -void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, - unsigned int bitlen ) -{ - conf->dhm_min_bitlen = bitlen; -} -#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -/* - * Set allowed/preferred hashes for handshake signatures - */ -void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, - const int *hashes ) -{ - conf->sig_hashes = hashes; -} -#endif - -#if defined(MBEDTLS_ECP_C) -/* - * Set the allowed elliptic curves - */ -void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, - const mbedtls_ecp_group_id *curve_list ) -{ - conf->curve_list = curve_list; -} -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ) -{ - size_t hostname_len; - - if( hostname == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - hostname_len = strlen( hostname ); - - if( hostname_len + 1 == 0 ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - ssl->hostname = mbedtls_calloc( 1, hostname_len + 1 ); - - if( ssl->hostname == NULL ) - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - - memcpy( ssl->hostname, hostname, hostname_len ); - - ssl->hostname[hostname_len] = '\0'; - - return( 0 ); -} -#endif - -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) -void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, - int (*f_sni)(void *, mbedtls_ssl_context *, - const unsigned char *, size_t), - void *p_sni ) -{ - conf->f_sni = f_sni; - conf->p_sni = p_sni; -} -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ - -#if defined(MBEDTLS_SSL_ALPN) -int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ) -{ - size_t cur_len, tot_len; - const char **p; - - /* - * RFC 7301 3.1: "Empty strings MUST NOT be included and byte strings - * MUST NOT be truncated." - * We check lengths now rather than later. - */ - tot_len = 0; - for( p = protos; *p != NULL; p++ ) - { - cur_len = strlen( *p ); - tot_len += cur_len; - - if( cur_len == 0 || cur_len > 255 || tot_len > 65535 ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - conf->alpn_list = protos; - - return( 0 ); -} - -const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ) -{ - return( ssl->alpn_chosen ); -} -#endif /* MBEDTLS_SSL_ALPN */ - -void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ) -{ - conf->max_major_ver = major; - conf->max_minor_ver = minor; -} - -void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ) -{ - conf->min_major_ver = major; - conf->min_minor_ver = minor; -} - -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) && defined(MBEDTLS_SSL_CLI_C) -void mbedtls_ssl_conf_fallback( mbedtls_ssl_config *conf, char fallback ) -{ - conf->fallback = fallback; -} -#endif - -#if defined(MBEDTLS_SSL_SRV_C) -void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, - char cert_req_ca_list ) -{ - conf->cert_req_ca_list = cert_req_ca_list; -} -#endif - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) -void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ) -{ - conf->encrypt_then_mac = etm; -} -#endif - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) -void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ) -{ - conf->extended_ms = ems; -} -#endif - -#if defined(MBEDTLS_ARC4_C) -void mbedtls_ssl_conf_arc4_support( mbedtls_ssl_config *conf, char arc4 ) -{ - conf->arc4_disabled = arc4; -} -#endif - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ) -{ - if( mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID || - mfl_code_to_length[mfl_code] > MBEDTLS_SSL_MAX_CONTENT_LEN ) - { - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - conf->mfl_code = mfl_code; - - return( 0 ); -} -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) -void mbedtls_ssl_conf_truncated_hmac( mbedtls_ssl_config *conf, int truncate ) -{ - conf->trunc_hmac = truncate; -} -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ - -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) -void mbedtls_ssl_conf_cbc_record_splitting( mbedtls_ssl_config *conf, char split ) -{ - conf->cbc_record_splitting = split; -} -#endif - -void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ) -{ - conf->allow_legacy_renegotiation = allow_legacy; -} - -#if defined(MBEDTLS_SSL_RENEGOTIATION) -void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ) -{ - conf->disable_renegotiation = renegotiation; -} - -void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ) -{ - conf->renego_max_records = max_records; -} - -void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, - const unsigned char period[8] ) -{ - memcpy( conf->renego_period, period, 8 ); -} -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) -#if defined(MBEDTLS_SSL_CLI_C) -void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ) -{ - conf->session_tickets = use_tickets; -} -#endif - -#if defined(MBEDTLS_SSL_SRV_C) -void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, - mbedtls_ssl_ticket_write_t *f_ticket_write, - mbedtls_ssl_ticket_parse_t *f_ticket_parse, - void *p_ticket ) -{ - conf->f_ticket_write = f_ticket_write; - conf->f_ticket_parse = f_ticket_parse; - conf->p_ticket = p_ticket; -} -#endif -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ - -#if defined(MBEDTLS_SSL_EXPORT_KEYS) -void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf, - mbedtls_ssl_export_keys_t *f_export_keys, - void *p_export_keys ) -{ - conf->f_export_keys = f_export_keys; - conf->p_export_keys = p_export_keys; -} -#endif - -/* - * SSL get accessors - */ -size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ) -{ - return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); -} - -uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ) -{ - if( ssl->session != NULL ) - return( ssl->session->verify_result ); - - if( ssl->session_negotiate != NULL ) - return( ssl->session_negotiate->verify_result ); - - return( 0xFFFFFFFF ); -} - -const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ) -{ - if( ssl == NULL || ssl->session == NULL ) - return( NULL ); - - return mbedtls_ssl_get_ciphersuite_name( ssl->session->ciphersuite ); -} - -const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - switch( ssl->minor_ver ) - { - case MBEDTLS_SSL_MINOR_VERSION_2: - return( "DTLSv1.0" ); - - case MBEDTLS_SSL_MINOR_VERSION_3: - return( "DTLSv1.2" ); - - default: - return( "unknown (DTLS)" ); - } - } -#endif - - switch( ssl->minor_ver ) - { - case MBEDTLS_SSL_MINOR_VERSION_0: - return( "SSLv3.0" ); - - case MBEDTLS_SSL_MINOR_VERSION_1: - return( "TLSv1.0" ); - - case MBEDTLS_SSL_MINOR_VERSION_2: - return( "TLSv1.1" ); - - case MBEDTLS_SSL_MINOR_VERSION_3: - return( "TLSv1.2" ); - - default: - return( "unknown" ); - } -} - -int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ) -{ - size_t transform_expansion; - const mbedtls_ssl_transform *transform = ssl->transform_out; - -#if defined(MBEDTLS_ZLIB_SUPPORT) - if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL ) - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); -#endif - - if( transform == NULL ) - return( (int) mbedtls_ssl_hdr_len( ssl ) ); - - switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) ) - { - case MBEDTLS_MODE_GCM: - case MBEDTLS_MODE_CCM: - case MBEDTLS_MODE_STREAM: - transform_expansion = transform->minlen; - break; - - case MBEDTLS_MODE_CBC: - transform_expansion = transform->maclen - + mbedtls_cipher_get_block_size( &transform->cipher_ctx_enc ); - break; - - default: - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - - return( (int)( mbedtls_ssl_hdr_len( ssl ) + transform_expansion ) ); -} - -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) -size_t mbedtls_ssl_get_max_frag_len( const mbedtls_ssl_context *ssl ) -{ - size_t max_len; - - /* - * Assume mfl_code is correct since it was checked when set - */ - max_len = mfl_code_to_length[ssl->conf->mfl_code]; - - /* - * Check if a smaller max length was negotiated - */ - if( ssl->session_out != NULL && - mfl_code_to_length[ssl->session_out->mfl_code] < max_len ) - { - max_len = mfl_code_to_length[ssl->session_out->mfl_code]; - } - - return max_len; -} -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ) -{ - if( ssl == NULL || ssl->session == NULL ) - return( NULL ); - - return( ssl->session->peer_cert ); -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -#if defined(MBEDTLS_SSL_CLI_C) -int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *dst ) -{ - if( ssl == NULL || - dst == NULL || - ssl->session == NULL || - ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) - { - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - - return( ssl_session_copy( dst, ssl->session ) ); -} -#endif /* MBEDTLS_SSL_CLI_C */ - -/* - * Perform a single step of the SSL handshake - */ -int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - -#if defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - ret = mbedtls_ssl_handshake_client_step( ssl ); -#endif -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - ret = mbedtls_ssl_handshake_server_step( ssl ); -#endif - - return( ret ); -} - -/* - * Perform the SSL handshake - */ -int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ) -{ - int ret = 0; - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> handshake" ) ); - - while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - { - ret = mbedtls_ssl_handshake_step( ssl ); - - if( ret != 0 ) - break; - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= handshake" ) ); - - return( ret ); -} - -#if defined(MBEDTLS_SSL_RENEGOTIATION) -#if defined(MBEDTLS_SSL_SRV_C) -/* - * Write HelloRequest to request renegotiation on server - */ -static int ssl_write_hello_request( mbedtls_ssl_context *ssl ) -{ - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello request" ) ); - - ssl->out_msglen = 4; - ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; - ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello request" ) ); - - return( 0 ); -} -#endif /* MBEDTLS_SSL_SRV_C */ - -/* - * Actually renegotiate current connection, triggered by either: - * - any side: calling mbedtls_ssl_renegotiate(), - * - client: receiving a HelloRequest during mbedtls_ssl_read(), - * - server: receiving any handshake message on server during mbedtls_ssl_read() after - * the initial handshake is completed. - * If the handshake doesn't complete due to waiting for I/O, it will continue - * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively. - */ -static int ssl_start_renegotiation( mbedtls_ssl_context *ssl ) -{ - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) ); - - if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) - return( ret ); - - /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and - * the ServerHello will have message_seq = 1" */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) - { - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - ssl->handshake->out_msg_seq = 1; - else - ssl->handshake->in_msg_seq = 1; - } -#endif - - ssl->state = MBEDTLS_SSL_HELLO_REQUEST; - ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS; - - if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); - return( ret ); - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) ); - - return( 0 ); -} - -/* - * Renegotiate current connection on client, - * or request renegotiation on server - */ -int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ) -{ - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - -#if defined(MBEDTLS_SSL_SRV_C) - /* On server, just send the request */ - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) - { - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; - - /* Did we already try/start sending HelloRequest? */ - if( ssl->out_left != 0 ) - return( mbedtls_ssl_flush_output( ssl ) ); - - return( ssl_write_hello_request( ssl ) ); - } -#endif /* MBEDTLS_SSL_SRV_C */ - -#if defined(MBEDTLS_SSL_CLI_C) - /* - * On client, either start the renegotiation process or, - * if already in progress, continue the handshake - */ - if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) - { - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( ( ret = ssl_start_renegotiation( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); - return( ret ); - } - } - else - { - if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); - return( ret ); - } - } -#endif /* MBEDTLS_SSL_CLI_C */ - - return( ret ); -} - -/* - * Check record counters and renegotiate if they're above the limit. - */ -static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) -{ - size_t ep_len = ssl_ep_len( ssl ); - int in_ctr_cmp; - int out_ctr_cmp; - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || - ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || - ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ) - { - return( 0 ); - } - - in_ctr_cmp = memcmp( ssl->in_ctr + ep_len, - ssl->conf->renego_period + ep_len, 8 - ep_len ); - out_ctr_cmp = memcmp( ssl->out_ctr + ep_len, - ssl->conf->renego_period + ep_len, 8 - ep_len ); - - if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 ) - { - return( 0 ); - } - - MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) ); - return( mbedtls_ssl_renegotiate( ssl ) ); -} -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - -/* - * Receive application data decrypted from the SSL layer - */ -int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) -{ - int ret; - size_t n; - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) - return( ret ); - - if( ssl->handshake != NULL && - ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) - { - if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) - return( ret ); - } - } -#endif - - /* - * Check if renegotiation is necessary and/or handshake is - * in process. If yes, perform/continue, and fall through - * if an unexpected packet is received while the client - * is waiting for the ServerHello. - * - * (There is no equivalent to the last condition on - * the server-side as it is not treated as within - * a handshake while waiting for the ClientHello - * after a renegotiation request.) - */ - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - ret = ssl_check_ctr_renegotiate( ssl ); - if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && - ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); - return( ret ); - } -#endif - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - { - ret = mbedtls_ssl_handshake( ssl ); - if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && - ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); - return( ret ); - } - } - - /* - * TODO - * - * The logic should be streamlined here: - * - * Instead of - * - * - Manually checking whether ssl->in_offt is NULL - * - Fetching a new record if yes - * - Setting ssl->in_offt if one finds an application record - * - Resetting keep_current_message after handling the application data - * - * one should - * - * - Adapt read_record to set ssl->in_offt automatically - * when a new application data record is processed. - * - Always call mbedtls_ssl_read_record here. - * - * This way, the logic of ssl_read would be much clearer: - * - * (1) Always call record layer and see what kind of record is on - * and have it ready for consumption (in particular, in_offt - * properly set for application data records). - * (2) If it's application data (either freshly fetched - * or something already being partially processed), - * serve the read request from it. - * (3) If it's something different from application data, - * handle it accordingly, e.g. potentially start a - * renegotiation. - * - * This will also remove the need to manually reset - * ssl->keep_current_message = 0 below. - * - */ - - if( ssl->in_offt == NULL ) - { - /* Start timer if not already running */ - if( ssl->f_get_timer != NULL && - ssl->f_get_timer( ssl->p_timer ) == -1 ) - { - ssl_set_timer( ssl, ssl->conf->read_timeout ); - } - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) - return( 0 ); - - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - if( ssl->in_msglen == 0 && - ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA ) - { - /* - * OpenSSL sends empty messages to randomize the IV - */ - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) - return( 0 ); - - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - } - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "received handshake message" ) ); - - /* - * - For client-side, expect SERVER_HELLO_REQUEST. - * - For server-side, expect CLIENT_HELLO. - * - Fail (TLS) or silently drop record (DTLS) in other cases. - */ - -#if defined(MBEDTLS_SSL_CLI_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && - ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || - ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) ); - - /* With DTLS, drop the packet (probably from last handshake) */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( MBEDTLS_ERR_SSL_WANT_READ ); -#endif - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } -#endif /* MBEDTLS_SSL_CLI_C */ - -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) ); - - /* With DTLS, drop the packet (probably from last handshake) */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - return( MBEDTLS_ERR_SSL_WANT_READ ); -#endif - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } -#endif /* MBEDTLS_SSL_SRV_C */ - - /* Determine whether renegotiation attempt should be accepted */ - - if( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || - ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && - ssl->conf->allow_legacy_renegotiation == - MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) - { - /* - * Refuse renegotiation - */ - - MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) ); - -#if defined(MBEDTLS_SSL_PROTO_SSL3) - if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) - { - /* SSLv3 does not have a "no_renegotiation" warning, so - we send a fatal alert and abort the connection. */ - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - else -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 ) - { - if( ( ret = mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_WARNING, - MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 ) - { - return( ret ); - } - } - else -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || - MBEDTLS_SSL_PROTO_TLS1_2 */ - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - } - } - else - { - /* - * Accept renegotiation request - */ - - /* DTLS clients need to know renego is server-initiated */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) - { - ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; - } -#endif - ret = ssl_start_renegotiation( ssl ); - if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && - ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret ); - return( ret ); - } - } - - return( MBEDTLS_ERR_SSL_WANT_READ ); - } - else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) - { - if( ssl->conf->renego_max_records >= 0 ) - { - if( ++ssl->renego_records_seen > ssl->conf->renego_max_records ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " - "but not honored by client" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - } - } -#endif /* MBEDTLS_SSL_RENEGOTIATION */ - - /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */ - if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) ); - return( MBEDTLS_ERR_SSL_WANT_READ ); - } - - if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) ); - return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); - } - - ssl->in_offt = ssl->in_msg; - - /* We're going to return something now, cancel timer, - * except if handshake (renegotiation) is in progress */ - if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) - ssl_set_timer( ssl, 0 ); - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - /* If we requested renego but received AppData, resend HelloRequest. - * Do it now, after setting in_offt, to avoid taking this branch - * again if ssl_write_hello_request() returns WANT_WRITE */ -#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) - { - if( ( ret = ssl_resend_hello_request( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_resend_hello_request", ret ); - return( ret ); - } - } -#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ -#endif /* MBEDTLS_SSL_PROTO_DTLS */ - } - - n = ( len < ssl->in_msglen ) - ? len : ssl->in_msglen; - - memcpy( buf, ssl->in_offt, n ); - ssl->in_msglen -= n; - - if( ssl->in_msglen == 0 ) - { - /* all bytes consumed */ - ssl->in_offt = NULL; - ssl->keep_current_message = 0; - } - else - { - /* more data available */ - ssl->in_offt += n; - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) ); - - return( (int) n ); -} - -/* - * Send application data to be encrypted by the SSL layer, - * taking care of max fragment length and buffer size - */ -static int ssl_write_real( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ - int ret; -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - size_t max_len = mbedtls_ssl_get_max_frag_len( ssl ); - - if( len > max_len ) - { -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) " - "maximum fragment length: %d > %d", - len, max_len ) ); - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - else -#endif - len = max_len; - } -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ - - if( ssl->out_left != 0 ) - { - if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); - return( ret ); - } - } - else - { - ssl->out_msglen = len; - ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; - memcpy( ssl->out_msg, buf, len ); - - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); - return( ret ); - } - } - - return( (int) len ); -} - -/* - * Write application data, doing 1/n-1 splitting if necessary. - * - * With non-blocking I/O, ssl_write_real() may return WANT_WRITE, - * then the caller will call us again with the same arguments, so - * remember wether we already did the split or not. - */ -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) -static int ssl_write_split( mbedtls_ssl_context *ssl, - const unsigned char *buf, size_t len ) -{ - int ret; - - if( ssl->conf->cbc_record_splitting == - MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED || - len <= 1 || - ssl->minor_ver > MBEDTLS_SSL_MINOR_VERSION_1 || - mbedtls_cipher_get_cipher_mode( &ssl->transform_out->cipher_ctx_enc ) - != MBEDTLS_MODE_CBC ) - { - return( ssl_write_real( ssl, buf, len ) ); - } - - if( ssl->split_done == 0 ) - { - if( ( ret = ssl_write_real( ssl, buf, 1 ) ) <= 0 ) - return( ret ); - ssl->split_done = 1; - } - - if( ( ret = ssl_write_real( ssl, buf + 1, len - 1 ) ) <= 0 ) - return( ret ); - ssl->split_done = 0; - - return( ret + 1 ); -} -#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ - -/* - * Write application data (public-facing wrapper) - */ -int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) -{ - int ret; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) ); - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); - return( ret ); - } -#endif - - if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) - { - if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); - return( ret ); - } - } - -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - ret = ssl_write_split( ssl, buf, len ); -#else - ret = ssl_write_real( ssl, buf, len ); -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) ); - - return( ret ); -} - -/* - * Notify the peer that the connection is being closed - */ -int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ) -{ - int ret; - - if( ssl == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) ); - - if( ssl->out_left != 0 ) - return( mbedtls_ssl_flush_output( ssl ) ); - - if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) - { - if( ( ret = mbedtls_ssl_send_alert_message( ssl, - MBEDTLS_SSL_ALERT_LEVEL_WARNING, - MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret ); - return( ret ); - } - } - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write close notify" ) ); - - return( 0 ); -} - -void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ) -{ - if( transform == NULL ) - return; - -#if defined(MBEDTLS_ZLIB_SUPPORT) - deflateEnd( &transform->ctx_deflate ); - inflateEnd( &transform->ctx_inflate ); -#endif - - mbedtls_cipher_free( &transform->cipher_ctx_enc ); - mbedtls_cipher_free( &transform->cipher_ctx_dec ); - - mbedtls_md_free( &transform->md_ctx_enc ); - mbedtls_md_free( &transform->md_ctx_dec ); - - mbedtls_zeroize( transform, sizeof( mbedtls_ssl_transform ) ); -} - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert ) -{ - mbedtls_ssl_key_cert *cur = key_cert, *next; - - while( cur != NULL ) - { - next = cur->next; - mbedtls_free( cur ); - cur = next; - } -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) -{ - if( handshake == NULL ) - return; - -#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ - defined(MBEDTLS_SSL_PROTO_TLS1_1) - mbedtls_md5_free( &handshake->fin_md5 ); - mbedtls_sha1_free( &handshake->fin_sha1 ); -#endif -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) -#if defined(MBEDTLS_SHA256_C) - mbedtls_sha256_free( &handshake->fin_sha256 ); -#endif -#if defined(MBEDTLS_SHA512_C) - mbedtls_sha512_free( &handshake->fin_sha512 ); -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - -#if defined(MBEDTLS_DHM_C) - mbedtls_dhm_free( &handshake->dhm_ctx ); -#endif -#if defined(MBEDTLS_ECDH_C) - mbedtls_ecdh_free( &handshake->ecdh_ctx ); -#endif -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - mbedtls_ecjpake_free( &handshake->ecjpake_ctx ); -#if defined(MBEDTLS_SSL_CLI_C) - mbedtls_free( handshake->ecjpake_cache ); - handshake->ecjpake_cache = NULL; - handshake->ecjpake_cache_len = 0; -#endif -#endif - -#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - /* explicit void pointer cast for buggy MS compiler */ - mbedtls_free( (void *) handshake->curves ); -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - if( handshake->psk != NULL ) - { - mbedtls_zeroize( handshake->psk, handshake->psk_len ); - mbedtls_free( handshake->psk ); - } -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ - defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - /* - * Free only the linked list wrapper, not the keys themselves - * since the belong to the SNI callback - */ - if( handshake->sni_key_cert != NULL ) - { - mbedtls_ssl_key_cert *cur = handshake->sni_key_cert, *next; - - while( cur != NULL ) - { - next = cur->next; - mbedtls_free( cur ); - cur = next; - } - } -#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - mbedtls_free( handshake->verify_cookie ); - mbedtls_free( handshake->hs_msg ); - ssl_flight_free( handshake->flight ); -#endif - - mbedtls_zeroize( handshake, sizeof( mbedtls_ssl_handshake_params ) ); -} - -void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) -{ - if( session == NULL ) - return; - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - if( session->peer_cert != NULL ) - { - mbedtls_x509_crt_free( session->peer_cert ); - mbedtls_free( session->peer_cert ); - } -#endif - -#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) - mbedtls_free( session->ticket ); -#endif - - mbedtls_zeroize( session, sizeof( mbedtls_ssl_session ) ); -} - -/* - * Free an SSL context - */ -void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) -{ - if( ssl == NULL ) - return; - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> free" ) ); - - if( ssl->out_buf != NULL ) - { - mbedtls_zeroize( ssl->out_buf, MBEDTLS_SSL_BUFFER_LEN ); - mbedtls_free( ssl->out_buf ); - } - - if( ssl->in_buf != NULL ) - { - mbedtls_zeroize( ssl->in_buf, MBEDTLS_SSL_BUFFER_LEN ); - mbedtls_free( ssl->in_buf ); - } - -#if defined(MBEDTLS_ZLIB_SUPPORT) - if( ssl->compress_buf != NULL ) - { - mbedtls_zeroize( ssl->compress_buf, MBEDTLS_SSL_BUFFER_LEN ); - mbedtls_free( ssl->compress_buf ); - } -#endif - - if( ssl->transform ) - { - mbedtls_ssl_transform_free( ssl->transform ); - mbedtls_free( ssl->transform ); - } - - if( ssl->handshake ) - { - mbedtls_ssl_handshake_free( ssl->handshake ); - mbedtls_ssl_transform_free( ssl->transform_negotiate ); - mbedtls_ssl_session_free( ssl->session_negotiate ); - - mbedtls_free( ssl->handshake ); - mbedtls_free( ssl->transform_negotiate ); - mbedtls_free( ssl->session_negotiate ); - } - - if( ssl->session ) - { - mbedtls_ssl_session_free( ssl->session ); - mbedtls_free( ssl->session ); - } - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - if( ssl->hostname != NULL ) - { - mbedtls_zeroize( ssl->hostname, strlen( ssl->hostname ) ); - mbedtls_free( ssl->hostname ); - } -#endif - -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - if( mbedtls_ssl_hw_record_finish != NULL ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "going for mbedtls_ssl_hw_record_finish()" ) ); - mbedtls_ssl_hw_record_finish( ssl ); - } -#endif - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) - mbedtls_free( ssl->cli_id ); -#endif - - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= free" ) ); - - /* Actually clear after last debug message */ - mbedtls_zeroize( ssl, sizeof( mbedtls_ssl_context ) ); -} - -/* - * Initialze mbedtls_ssl_config - */ -void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ) -{ - memset( conf, 0, sizeof( mbedtls_ssl_config ) ); -} - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -static int ssl_preset_default_hashes[] = { -#if defined(MBEDTLS_SHA512_C) - MBEDTLS_MD_SHA512, - MBEDTLS_MD_SHA384, -#endif -#if defined(MBEDTLS_SHA256_C) - MBEDTLS_MD_SHA256, - MBEDTLS_MD_SHA224, -#endif -#if defined(MBEDTLS_SHA1_C) && defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE) - MBEDTLS_MD_SHA1, -#endif - MBEDTLS_MD_NONE -}; -#endif - -static int ssl_preset_suiteb_ciphersuites[] = { - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, - MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, - 0 -}; - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -static int ssl_preset_suiteb_hashes[] = { - MBEDTLS_MD_SHA256, - MBEDTLS_MD_SHA384, - MBEDTLS_MD_NONE -}; -#endif - -#if defined(MBEDTLS_ECP_C) -static mbedtls_ecp_group_id ssl_preset_suiteb_curves[] = { - MBEDTLS_ECP_DP_SECP256R1, - MBEDTLS_ECP_DP_SECP384R1, - MBEDTLS_ECP_DP_NONE -}; -#endif - -/* - * Load default in mbedtls_ssl_config - */ -int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, - int endpoint, int transport, int preset ) -{ -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) - int ret; -#endif - - /* Use the functions here so that they are covered in tests, - * but otherwise access member directly for efficiency */ - mbedtls_ssl_conf_endpoint( conf, endpoint ); - mbedtls_ssl_conf_transport( conf, transport ); - - /* - * Things that are common to all presets - */ -#if defined(MBEDTLS_SSL_CLI_C) - if( endpoint == MBEDTLS_SSL_IS_CLIENT ) - { - conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED; -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - conf->session_tickets = MBEDTLS_SSL_SESSION_TICKETS_ENABLED; -#endif - } -#endif - -#if defined(MBEDTLS_ARC4_C) - conf->arc4_disabled = MBEDTLS_SSL_ARC4_DISABLED; -#endif - -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; -#endif - -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; -#endif - -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - conf->cbc_record_splitting = MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED; -#endif - -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) - conf->f_cookie_write = ssl_cookie_write_dummy; - conf->f_cookie_check = ssl_cookie_check_dummy; -#endif - -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED; -#endif - -#if defined(MBEDTLS_SSL_SRV_C) - conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED; -#endif - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN; - conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX; -#endif - -#if defined(MBEDTLS_SSL_RENEGOTIATION) - conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT; - memset( conf->renego_period, 0x00, 2 ); - memset( conf->renego_period + 2, 0xFF, 6 ); -#endif - -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) - if( endpoint == MBEDTLS_SSL_IS_SERVER ) - { - if( ( ret = mbedtls_ssl_conf_dh_param( conf, - MBEDTLS_DHM_RFC5114_MODP_2048_P, - MBEDTLS_DHM_RFC5114_MODP_2048_G ) ) != 0 ) - { - return( ret ); - } - } -#endif - - /* - * Preset-specific defaults - */ - switch( preset ) - { - /* - * NSA Suite B - */ - case MBEDTLS_SSL_PRESET_SUITEB: - conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; - conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */ - conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; - conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; - - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = - ssl_preset_suiteb_ciphersuites; - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - conf->cert_profile = &mbedtls_x509_crt_profile_suiteb; -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - conf->sig_hashes = ssl_preset_suiteb_hashes; -#endif - -#if defined(MBEDTLS_ECP_C) - conf->curve_list = ssl_preset_suiteb_curves; -#endif - break; - - /* - * Default - */ - default: - conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; - conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_1; /* TLS 1.0 */ - conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; - conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; - -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_2; -#endif - - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_0] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_1] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_2] = - conf->ciphersuite_list[MBEDTLS_SSL_MINOR_VERSION_3] = - mbedtls_ssl_list_ciphersuites(); - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - conf->cert_profile = &mbedtls_x509_crt_profile_default; -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - conf->sig_hashes = ssl_preset_default_hashes; -#endif - -#if defined(MBEDTLS_ECP_C) - conf->curve_list = mbedtls_ecp_grp_id_list(); -#endif - -#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) - conf->dhm_min_bitlen = 1024; -#endif - } - - return( 0 ); -} - -/* - * Free mbedtls_ssl_config - */ -void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ) -{ -#if defined(MBEDTLS_DHM_C) - mbedtls_mpi_free( &conf->dhm_P ); - mbedtls_mpi_free( &conf->dhm_G ); -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - if( conf->psk != NULL ) - { - mbedtls_zeroize( conf->psk, conf->psk_len ); - mbedtls_zeroize( conf->psk_identity, conf->psk_identity_len ); - mbedtls_free( conf->psk ); - mbedtls_free( conf->psk_identity ); - conf->psk_len = 0; - conf->psk_identity_len = 0; - } -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - ssl_key_cert_free( conf->key_cert ); -#endif - - mbedtls_zeroize( conf, sizeof( mbedtls_ssl_config ) ); -} - -#if defined(MBEDTLS_PK_C) && \ - ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) ) -/* - * Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX - */ -unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ) -{ -#if defined(MBEDTLS_RSA_C) - if( mbedtls_pk_can_do( pk, MBEDTLS_PK_RSA ) ) - return( MBEDTLS_SSL_SIG_RSA ); -#endif -#if defined(MBEDTLS_ECDSA_C) - if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECDSA ) ) - return( MBEDTLS_SSL_SIG_ECDSA ); -#endif - return( MBEDTLS_SSL_SIG_ANON ); -} - -unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ) -{ - switch( type ) { - case MBEDTLS_PK_RSA: - return( MBEDTLS_SSL_SIG_RSA ); - case MBEDTLS_PK_ECDSA: - case MBEDTLS_PK_ECKEY: - return( MBEDTLS_SSL_SIG_ECDSA ); - default: - return( MBEDTLS_SSL_SIG_ANON ); - } -} - -mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ) -{ - switch( sig ) - { -#if defined(MBEDTLS_RSA_C) - case MBEDTLS_SSL_SIG_RSA: - return( MBEDTLS_PK_RSA ); -#endif -#if defined(MBEDTLS_ECDSA_C) - case MBEDTLS_SSL_SIG_ECDSA: - return( MBEDTLS_PK_ECDSA ); -#endif - default: - return( MBEDTLS_PK_NONE ); - } -} -#endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_ECDSA_C ) */ - -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ - defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) - -/* Find an entry in a signature-hash set matching a given hash algorithm. */ -mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, - mbedtls_pk_type_t sig_alg ) -{ - switch( sig_alg ) - { - case MBEDTLS_PK_RSA: - return( set->rsa ); - case MBEDTLS_PK_ECDSA: - return( set->ecdsa ); - default: - return( MBEDTLS_MD_NONE ); - } -} - -/* Add a signature-hash-pair to a signature-hash set */ -void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, - mbedtls_pk_type_t sig_alg, - mbedtls_md_type_t md_alg ) -{ - switch( sig_alg ) - { - case MBEDTLS_PK_RSA: - if( set->rsa == MBEDTLS_MD_NONE ) - set->rsa = md_alg; - break; - - case MBEDTLS_PK_ECDSA: - if( set->ecdsa == MBEDTLS_MD_NONE ) - set->ecdsa = md_alg; - break; - - default: - break; - } -} - -/* Allow exactly one hash algorithm for each signature. */ -void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, - mbedtls_md_type_t md_alg ) -{ - set->rsa = md_alg; - set->ecdsa = md_alg; -} - -#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && - MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ - -/* - * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX - */ -mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ) -{ - switch( hash ) - { -#if defined(MBEDTLS_MD5_C) - case MBEDTLS_SSL_HASH_MD5: - return( MBEDTLS_MD_MD5 ); -#endif -#if defined(MBEDTLS_SHA1_C) - case MBEDTLS_SSL_HASH_SHA1: - return( MBEDTLS_MD_SHA1 ); -#endif -#if defined(MBEDTLS_SHA256_C) - case MBEDTLS_SSL_HASH_SHA224: - return( MBEDTLS_MD_SHA224 ); - case MBEDTLS_SSL_HASH_SHA256: - return( MBEDTLS_MD_SHA256 ); -#endif -#if defined(MBEDTLS_SHA512_C) - case MBEDTLS_SSL_HASH_SHA384: - return( MBEDTLS_MD_SHA384 ); - case MBEDTLS_SSL_HASH_SHA512: - return( MBEDTLS_MD_SHA512 ); -#endif - default: - return( MBEDTLS_MD_NONE ); - } -} - -/* - * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX - */ -unsigned char mbedtls_ssl_hash_from_md_alg( int md ) -{ - switch( md ) - { -#if defined(MBEDTLS_MD5_C) - case MBEDTLS_MD_MD5: - return( MBEDTLS_SSL_HASH_MD5 ); -#endif -#if defined(MBEDTLS_SHA1_C) - case MBEDTLS_MD_SHA1: - return( MBEDTLS_SSL_HASH_SHA1 ); -#endif -#if defined(MBEDTLS_SHA256_C) - case MBEDTLS_MD_SHA224: - return( MBEDTLS_SSL_HASH_SHA224 ); - case MBEDTLS_MD_SHA256: - return( MBEDTLS_SSL_HASH_SHA256 ); -#endif -#if defined(MBEDTLS_SHA512_C) - case MBEDTLS_MD_SHA384: - return( MBEDTLS_SSL_HASH_SHA384 ); - case MBEDTLS_MD_SHA512: - return( MBEDTLS_SSL_HASH_SHA512 ); -#endif - default: - return( MBEDTLS_SSL_HASH_NONE ); - } -} - -#if defined(MBEDTLS_ECP_C) -/* - * Check if a curve proposed by the peer is in our list. - * Return 0 if we're willing to use it, -1 otherwise. - */ -int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ) -{ - const mbedtls_ecp_group_id *gid; - - if( ssl->conf->curve_list == NULL ) - return( -1 ); - - for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ ) - if( *gid == grp_id ) - return( 0 ); - - return( -1 ); -} -#endif /* MBEDTLS_ECP_C */ - -#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) -/* - * Check if a hash proposed by the peer is in our list. - * Return 0 if we're willing to use it, -1 otherwise. - */ -int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, - mbedtls_md_type_t md ) -{ - const int *cur; - - if( ssl->conf->sig_hashes == NULL ) - return( -1 ); - - for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) - if( *cur == (int) md ) - return( 0 ); - - return( -1 ); -} -#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */ - -#if defined(MBEDTLS_X509_CRT_PARSE_C) -int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, - const mbedtls_ssl_ciphersuite_t *ciphersuite, - int cert_endpoint, - uint32_t *flags ) -{ - int ret = 0; -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) - int usage = 0; -#endif -#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) - const char *ext_oid; - size_t ext_len; -#endif - -#if !defined(MBEDTLS_X509_CHECK_KEY_USAGE) && \ - !defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) - ((void) cert); - ((void) cert_endpoint); - ((void) flags); -#endif - -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) - if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) - { - /* Server part of the key exchange */ - switch( ciphersuite->key_exchange ) - { - case MBEDTLS_KEY_EXCHANGE_RSA: - case MBEDTLS_KEY_EXCHANGE_RSA_PSK: - usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT; - break; - - case MBEDTLS_KEY_EXCHANGE_DHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: - usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; - break; - - case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: - case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: - usage = MBEDTLS_X509_KU_KEY_AGREEMENT; - break; - - /* Don't use default: we want warnings when adding new values */ - case MBEDTLS_KEY_EXCHANGE_NONE: - case MBEDTLS_KEY_EXCHANGE_PSK: - case MBEDTLS_KEY_EXCHANGE_DHE_PSK: - case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: - case MBEDTLS_KEY_EXCHANGE_ECJPAKE: - usage = 0; - } - } - else - { - /* Client auth: we only implement rsa_sign and mbedtls_ecdsa_sign for now */ - usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; - } - - if( mbedtls_x509_crt_check_key_usage( cert, usage ) != 0 ) - { - *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE; - ret = -1; - } -#else - ((void) ciphersuite); -#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ - -#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) - if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) - { - ext_oid = MBEDTLS_OID_SERVER_AUTH; - ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_SERVER_AUTH ); - } - else - { - ext_oid = MBEDTLS_OID_CLIENT_AUTH; - ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_CLIENT_AUTH ); - } - - if( mbedtls_x509_crt_check_extended_key_usage( cert, ext_oid, ext_len ) != 0 ) - { - *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE; - ret = -1; - } -#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ - - return( ret ); -} -#endif /* MBEDTLS_X509_CRT_PARSE_C */ - -/* - * Convert version numbers to/from wire format - * and, for DTLS, to/from TLS equivalent. - * - * For TLS this is the identity. - * For DTLS, use 1's complement (v -> 255 - v, and then map as follows: - * 1.0 <-> 3.2 (DTLS 1.0 is based on TLS 1.1) - * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) - */ -void mbedtls_ssl_write_version( int major, int minor, int transport, - unsigned char ver[2] ) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - if( minor == MBEDTLS_SSL_MINOR_VERSION_2 ) - --minor; /* DTLS 1.0 stored as TLS 1.1 internally */ - - ver[0] = (unsigned char)( 255 - ( major - 2 ) ); - ver[1] = (unsigned char)( 255 - ( minor - 1 ) ); - } - else -#else - ((void) transport); -#endif - { - ver[0] = (unsigned char) major; - ver[1] = (unsigned char) minor; - } -} - -void mbedtls_ssl_read_version( int *major, int *minor, int transport, - const unsigned char ver[2] ) -{ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) - { - *major = 255 - ver[0] + 2; - *minor = 255 - ver[1] + 1; - - if( *minor == MBEDTLS_SSL_MINOR_VERSION_1 ) - ++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */ - } - else -#else - ((void) transport); -#endif - { - *major = ver[0]; - *minor = ver[1]; - } -} - -int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ) -{ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) - return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; - - switch( md ) - { -#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) -#if defined(MBEDTLS_MD5_C) - case MBEDTLS_SSL_HASH_MD5: - return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; -#endif -#if defined(MBEDTLS_SHA1_C) - case MBEDTLS_SSL_HASH_SHA1: - ssl->handshake->calc_verify = ssl_calc_verify_tls; - break; -#endif -#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SHA512_C) - case MBEDTLS_SSL_HASH_SHA384: - ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384; - break; -#endif -#if defined(MBEDTLS_SHA256_C) - case MBEDTLS_SSL_HASH_SHA256: - ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256; - break; -#endif - default: - return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; - } - - return 0; -#else /* !MBEDTLS_SSL_PROTO_TLS1_2 */ - (void) ssl; - (void) md; - - return MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH; -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -} - -#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/components/mbedtls/library/threading.c b/components/mbedtls/library/threading.c deleted file mode 100644 index 07586756f2..0000000000 --- a/components/mbedtls/library/threading.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Threading abstraction layer - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_THREADING_C) - -#include "mbedtls/threading.h" - -#if defined(MBEDTLS_THREADING_PTHREAD) -static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) -{ - if( mutex == NULL ) - return; - - mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0; -} - -static void threading_mutex_free_pthread( mbedtls_threading_mutex_t *mutex ) -{ - if( mutex == NULL || !mutex->is_valid ) - return; - - (void) pthread_mutex_destroy( &mutex->mutex ); - mutex->is_valid = 0; -} - -static int threading_mutex_lock_pthread( mbedtls_threading_mutex_t *mutex ) -{ - if( mutex == NULL || ! mutex->is_valid ) - return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); - - if( pthread_mutex_lock( &mutex->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); - - return( 0 ); -} - -static int threading_mutex_unlock_pthread( mbedtls_threading_mutex_t *mutex ) -{ - if( mutex == NULL || ! mutex->is_valid ) - return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); - - if( pthread_mutex_unlock( &mutex->mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); - - return( 0 ); -} - -void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_init_pthread; -void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_free_pthread; -int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_lock_pthread; -int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_unlock_pthread; - -/* - * With phtreads we can statically initialize mutexes - */ -#define MUTEX_INIT = { PTHREAD_MUTEX_INITIALIZER, 1 } - -#endif /* MBEDTLS_THREADING_PTHREAD */ - -#if defined(MBEDTLS_THREADING_ALT) -static int threading_mutex_fail( mbedtls_threading_mutex_t *mutex ) -{ - ((void) mutex ); - return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); -} -static void threading_mutex_dummy( mbedtls_threading_mutex_t *mutex ) -{ - ((void) mutex ); - return; -} - -void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; -void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; -int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; -int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; - -/* - * Set functions pointers and initialize global mutexes - */ -void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), - void (*mutex_free)( mbedtls_threading_mutex_t * ), - int (*mutex_lock)( mbedtls_threading_mutex_t * ), - int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ) -{ - mbedtls_mutex_init = mutex_init; - mbedtls_mutex_free = mutex_free; - mbedtls_mutex_lock = mutex_lock; - mbedtls_mutex_unlock = mutex_unlock; - - mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); - mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); -} - -/* - * Free global mutexes - */ -void mbedtls_threading_free_alt( void ) -{ - mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); - mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); -} -#endif /* MBEDTLS_THREADING_ALT */ - -/* - * Define global mutexes - */ -#ifndef MUTEX_INIT -#define MUTEX_INIT -#endif -mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; -mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; - -#endif /* MBEDTLS_THREADING_C */ diff --git a/components/mbedtls/library/timing.c b/components/mbedtls/library/timing.c deleted file mode 100644 index a7c7ff0279..0000000000 --- a/components/mbedtls/library/timing.c +++ /dev/null @@ -1,525 +0,0 @@ -/* - * Portable interface to the CPU cycle counter - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif - -#if defined(MBEDTLS_TIMING_C) - -#include "mbedtls/timing.h" - -#if !defined(MBEDTLS_TIMING_ALT) - -#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ - !defined(__APPLE__) && !defined(_WIN32) -#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h" -#endif - -#ifndef asm -#define asm __asm -#endif - -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) - -#include -#include - -struct _hr_time -{ - LARGE_INTEGER start; -}; - -#else - -#include -#include -#include -#include -#include - -struct _hr_time -{ - struct timeval start; -}; - -#endif /* _WIN32 && !EFIX64 && !EFI32 */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - ( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - unsigned long tsc; - __asm rdtsc - __asm mov [tsc], eax - return( tsc ); -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */ - -/* some versions of mingw-64 have 32-bit longs even on x84_64 */ -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && ( defined(__i386__) || ( \ - ( defined(__amd64__) || defined( __x86_64__) ) && __SIZEOF_LONG__ == 4 ) ) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - unsigned long lo, hi; - asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); - return( lo ); -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && __i386__ */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && ( defined(__amd64__) || defined(__x86_64__) ) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - unsigned long lo, hi; - asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); - return( lo | ( hi << 32 ) ); -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && ( __amd64__ || __x86_64__ ) */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && ( defined(__powerpc__) || defined(__ppc__) ) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - unsigned long tbl, tbu0, tbu1; - - do - { - asm volatile( "mftbu %0" : "=r" (tbu0) ); - asm volatile( "mftb %0" : "=r" (tbl ) ); - asm volatile( "mftbu %0" : "=r" (tbu1) ); - } - while( tbu0 != tbu1 ); - - return( tbl ); -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && ( __powerpc__ || __ppc__ ) */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && defined(__sparc64__) - -#if defined(__OpenBSD__) -#warning OpenBSD does not allow access to tick register using software version instead -#else -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - unsigned long tick; - asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) ); - return( tick ); -} -#endif /* __OpenBSD__ */ -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && __sparc64__ */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - unsigned long tick; - asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" ); - asm volatile( "mov %%g1, %0" : "=r" (tick) ); - return( tick ); -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && __sparc__ && !__sparc64__ */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && defined(__alpha__) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - unsigned long cc; - asm volatile( "rpcc %0" : "=r" (cc) ); - return( cc & 0xFFFFFFFF ); -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && __alpha__ */ - -#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ - defined(__GNUC__) && defined(__ia64__) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - unsigned long itc; - asm volatile( "mov %0 = ar.itc" : "=r" (itc) ); - return( itc ); -} -#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && - __GNUC__ && __ia64__ */ - -#if !defined(HAVE_HARDCLOCK) && defined(_MSC_VER) && \ - !defined(EFIX64) && !defined(EFI32) - -#define HAVE_HARDCLOCK - -unsigned long mbedtls_timing_hardclock( void ) -{ - LARGE_INTEGER offset; - - QueryPerformanceCounter( &offset ); - - return( (unsigned long)( offset.QuadPart ) ); -} -#endif /* !HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */ - -#if !defined(HAVE_HARDCLOCK) - -#define HAVE_HARDCLOCK - -static int hardclock_init = 0; -static struct timeval tv_init; - -unsigned long mbedtls_timing_hardclock( void ) -{ - struct timeval tv_cur; - - if( hardclock_init == 0 ) - { - gettimeofday( &tv_init, NULL ); - hardclock_init = 1; - } - - gettimeofday( &tv_cur, NULL ); - return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000 - + ( tv_cur.tv_usec - tv_init.tv_usec ) ); -} -#endif /* !HAVE_HARDCLOCK */ - -volatile int mbedtls_timing_alarmed = 0; - -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) - -unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) -{ - unsigned long delta; - LARGE_INTEGER offset, hfreq; - struct _hr_time *t = (struct _hr_time *) val; - - QueryPerformanceCounter( &offset ); - QueryPerformanceFrequency( &hfreq ); - - delta = (unsigned long)( ( 1000 * - ( offset.QuadPart - t->start.QuadPart ) ) / - hfreq.QuadPart ); - - if( reset ) - QueryPerformanceCounter( &t->start ); - - return( delta ); -} - -/* It's OK to use a global because alarm() is supposed to be global anyway */ -static DWORD alarmMs; - -static DWORD WINAPI TimerProc( LPVOID TimerContext ) -{ - ((void) TimerContext); - Sleep( alarmMs ); - mbedtls_timing_alarmed = 1; - return( TRUE ); -} - -void mbedtls_set_alarm( int seconds ) -{ - DWORD ThreadId; - - mbedtls_timing_alarmed = 0; - alarmMs = seconds * 1000; - CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) ); -} - -#else /* _WIN32 && !EFIX64 && !EFI32 */ - -unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) -{ - unsigned long delta; - struct timeval offset; - struct _hr_time *t = (struct _hr_time *) val; - - gettimeofday( &offset, NULL ); - - if( reset ) - { - t->start.tv_sec = offset.tv_sec; - t->start.tv_usec = offset.tv_usec; - return( 0 ); - } - - delta = ( offset.tv_sec - t->start.tv_sec ) * 1000 - + ( offset.tv_usec - t->start.tv_usec ) / 1000; - - return( delta ); -} - -static void sighandler( int signum ) -{ - mbedtls_timing_alarmed = 1; - signal( signum, sighandler ); -} - -void mbedtls_set_alarm( int seconds ) -{ - mbedtls_timing_alarmed = 0; - signal( SIGALRM, sighandler ); - alarm( seconds ); -} - -#endif /* _WIN32 && !EFIX64 && !EFI32 */ - -/* - * Set delays to watch - */ -void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ) -{ - mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; - - ctx->int_ms = int_ms; - ctx->fin_ms = fin_ms; - - if( fin_ms != 0 ) - (void) mbedtls_timing_get_timer( &ctx->timer, 1 ); -} - -/* - * Get number of delays expired - */ -int mbedtls_timing_get_delay( void *data ) -{ - mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; - unsigned long elapsed_ms; - - if( ctx->fin_ms == 0 ) - return( -1 ); - - elapsed_ms = mbedtls_timing_get_timer( &ctx->timer, 0 ); - - if( elapsed_ms >= ctx->fin_ms ) - return( 2 ); - - if( elapsed_ms >= ctx->int_ms ) - return( 1 ); - - return( 0 ); -} - -#endif /* !MBEDTLS_TIMING_ALT */ - -#if defined(MBEDTLS_SELF_TEST) - -/* - * Busy-waits for the given number of milliseconds. - * Used for testing mbedtls_timing_hardclock. - */ -static void busy_msleep( unsigned long msec ) -{ - struct mbedtls_timing_hr_time hires; - unsigned long i = 0; /* for busy-waiting */ - volatile unsigned long j; /* to prevent optimisation */ - - (void) mbedtls_timing_get_timer( &hires, 1 ); - - while( mbedtls_timing_get_timer( &hires, 0 ) < msec ) - i++; - - j = i; - (void) j; -} - -#define FAIL do \ -{ \ - if( verbose != 0 ) \ - mbedtls_printf( "failed\n" ); \ - \ - return( 1 ); \ -} while( 0 ) - -/* - * Checkup routine - * - * Warning: this is work in progress, some tests may not be reliable enough - * yet! False positives may happen. - */ -int mbedtls_timing_self_test( int verbose ) -{ - unsigned long cycles, ratio; - unsigned long millisecs, secs; - int hardfail; - struct mbedtls_timing_hr_time hires; - uint32_t a, b; - mbedtls_timing_delay_context ctx; - - if( verbose != 0 ) - mbedtls_printf( " TIMING tests note: will take some time!\n" ); - - - if( verbose != 0 ) - mbedtls_printf( " TIMING test #1 (set_alarm / get_timer): " ); - - for( secs = 1; secs <= 3; secs++ ) - { - (void) mbedtls_timing_get_timer( &hires, 1 ); - - mbedtls_set_alarm( (int) secs ); - while( !mbedtls_timing_alarmed ) - ; - - millisecs = mbedtls_timing_get_timer( &hires, 0 ); - - /* For some reason on Windows it looks like alarm has an extra delay - * (maybe related to creating a new thread). Allow some room here. */ - if( millisecs < 800 * secs || millisecs > 1200 * secs + 300 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( 1 ); - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " TIMING test #2 (set/get_delay ): " ); - - for( a = 200; a <= 400; a += 200 ) - { - for( b = 200; b <= 400; b += 200 ) - { - mbedtls_timing_set_delay( &ctx, a, a + b ); - - busy_msleep( a - a / 8 ); - if( mbedtls_timing_get_delay( &ctx ) != 0 ) - FAIL; - - busy_msleep( a / 4 ); - if( mbedtls_timing_get_delay( &ctx ) != 1 ) - FAIL; - - busy_msleep( b - a / 8 - b / 8 ); - if( mbedtls_timing_get_delay( &ctx ) != 1 ) - FAIL; - - busy_msleep( b / 4 ); - if( mbedtls_timing_get_delay( &ctx ) != 2 ) - FAIL; - } - } - - mbedtls_timing_set_delay( &ctx, 0, 0 ); - busy_msleep( 200 ); - if( mbedtls_timing_get_delay( &ctx ) != -1 ) - FAIL; - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - - if( verbose != 0 ) - mbedtls_printf( " TIMING test #3 (hardclock / get_timer): " ); - - /* - * Allow one failure for possible counter wrapping. - * On a 4Ghz 32-bit machine the cycle counter wraps about once per second; - * since the whole test is about 10ms, it shouldn't happen twice in a row. - */ - hardfail = 0; - -hard_test: - if( hardfail > 1 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed (ignored)\n" ); - - goto hard_test_done; - } - - /* Get a reference ratio cycles/ms */ - millisecs = 1; - cycles = mbedtls_timing_hardclock(); - busy_msleep( millisecs ); - cycles = mbedtls_timing_hardclock() - cycles; - ratio = cycles / millisecs; - - /* Check that the ratio is mostly constant */ - for( millisecs = 2; millisecs <= 4; millisecs++ ) - { - cycles = mbedtls_timing_hardclock(); - busy_msleep( millisecs ); - cycles = mbedtls_timing_hardclock() - cycles; - - /* Allow variation up to 20% */ - if( cycles / millisecs < ratio - ratio / 5 || - cycles / millisecs > ratio + ratio / 5 ) - { - hardfail++; - goto hard_test; - } - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - -hard_test_done: - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - - return( 0 ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_TIMING_C */ diff --git a/components/mbedtls/library/version.c b/components/mbedtls/library/version.c deleted file mode 100644 index 6ca80d4695..0000000000 --- a/components/mbedtls/library/version.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Version information - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_VERSION_C) - -#include "mbedtls/version.h" -#include - -unsigned int mbedtls_version_get_number() -{ - return( MBEDTLS_VERSION_NUMBER ); -} - -void mbedtls_version_get_string( char *string ) -{ - memcpy( string, MBEDTLS_VERSION_STRING, - sizeof( MBEDTLS_VERSION_STRING ) ); -} - -void mbedtls_version_get_string_full( char *string ) -{ - memcpy( string, MBEDTLS_VERSION_STRING_FULL, - sizeof( MBEDTLS_VERSION_STRING_FULL ) ); -} - -#endif /* MBEDTLS_VERSION_C */ diff --git a/components/mbedtls/library/version_features.c b/components/mbedtls/library/version_features.c deleted file mode 100644 index 5cbe8aca37..0000000000 --- a/components/mbedtls/library/version_features.c +++ /dev/null @@ -1,683 +0,0 @@ -/* - * Version feature information - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_VERSION_C) - -#include "mbedtls/version.h" - -#include - -static const char *features[] = { -#if defined(MBEDTLS_VERSION_FEATURES) -#if defined(MBEDTLS_HAVE_ASM) - "MBEDTLS_HAVE_ASM", -#endif /* MBEDTLS_HAVE_ASM */ -#if defined(MBEDTLS_NO_UDBL_DIVISION) - "MBEDTLS_NO_UDBL_DIVISION", -#endif /* MBEDTLS_NO_UDBL_DIVISION */ -#if defined(MBEDTLS_HAVE_SSE2) - "MBEDTLS_HAVE_SSE2", -#endif /* MBEDTLS_HAVE_SSE2 */ -#if defined(MBEDTLS_HAVE_TIME) - "MBEDTLS_HAVE_TIME", -#endif /* MBEDTLS_HAVE_TIME */ -#if defined(MBEDTLS_HAVE_TIME_DATE) - "MBEDTLS_HAVE_TIME_DATE", -#endif /* MBEDTLS_HAVE_TIME_DATE */ -#if defined(MBEDTLS_PLATFORM_MEMORY) - "MBEDTLS_PLATFORM_MEMORY", -#endif /* MBEDTLS_PLATFORM_MEMORY */ -#if defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) - "MBEDTLS_PLATFORM_NO_STD_FUNCTIONS", -#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ -#if defined(MBEDTLS_PLATFORM_EXIT_ALT) - "MBEDTLS_PLATFORM_EXIT_ALT", -#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ -#if defined(MBEDTLS_PLATFORM_TIME_ALT) - "MBEDTLS_PLATFORM_TIME_ALT", -#endif /* MBEDTLS_PLATFORM_TIME_ALT */ -#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) - "MBEDTLS_PLATFORM_FPRINTF_ALT", -#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ -#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) - "MBEDTLS_PLATFORM_PRINTF_ALT", -#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ -#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) - "MBEDTLS_PLATFORM_SNPRINTF_ALT", -#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ -#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) - "MBEDTLS_PLATFORM_NV_SEED_ALT", -#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ -#if defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) - "MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT", -#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ -#if defined(MBEDTLS_DEPRECATED_WARNING) - "MBEDTLS_DEPRECATED_WARNING", -#endif /* MBEDTLS_DEPRECATED_WARNING */ -#if defined(MBEDTLS_DEPRECATED_REMOVED) - "MBEDTLS_DEPRECATED_REMOVED", -#endif /* MBEDTLS_DEPRECATED_REMOVED */ -#if defined(MBEDTLS_TIMING_ALT) - "MBEDTLS_TIMING_ALT", -#endif /* MBEDTLS_TIMING_ALT */ -#if defined(MBEDTLS_AES_ALT) - "MBEDTLS_AES_ALT", -#endif /* MBEDTLS_AES_ALT */ -#if defined(MBEDTLS_ARC4_ALT) - "MBEDTLS_ARC4_ALT", -#endif /* MBEDTLS_ARC4_ALT */ -#if defined(MBEDTLS_BLOWFISH_ALT) - "MBEDTLS_BLOWFISH_ALT", -#endif /* MBEDTLS_BLOWFISH_ALT */ -#if defined(MBEDTLS_CAMELLIA_ALT) - "MBEDTLS_CAMELLIA_ALT", -#endif /* MBEDTLS_CAMELLIA_ALT */ -#if defined(MBEDTLS_DES_ALT) - "MBEDTLS_DES_ALT", -#endif /* MBEDTLS_DES_ALT */ -#if defined(MBEDTLS_XTEA_ALT) - "MBEDTLS_XTEA_ALT", -#endif /* MBEDTLS_XTEA_ALT */ -#if defined(MBEDTLS_MD2_ALT) - "MBEDTLS_MD2_ALT", -#endif /* MBEDTLS_MD2_ALT */ -#if defined(MBEDTLS_MD4_ALT) - "MBEDTLS_MD4_ALT", -#endif /* MBEDTLS_MD4_ALT */ -#if defined(MBEDTLS_MD5_ALT) - "MBEDTLS_MD5_ALT", -#endif /* MBEDTLS_MD5_ALT */ -#if defined(MBEDTLS_RIPEMD160_ALT) - "MBEDTLS_RIPEMD160_ALT", -#endif /* MBEDTLS_RIPEMD160_ALT */ -#if defined(MBEDTLS_SHA1_ALT) - "MBEDTLS_SHA1_ALT", -#endif /* MBEDTLS_SHA1_ALT */ -#if defined(MBEDTLS_SHA256_ALT) - "MBEDTLS_SHA256_ALT", -#endif /* MBEDTLS_SHA256_ALT */ -#if defined(MBEDTLS_SHA512_ALT) - "MBEDTLS_SHA512_ALT", -#endif /* MBEDTLS_SHA512_ALT */ -#if defined(MBEDTLS_ECP_ALT) - "MBEDTLS_ECP_ALT", -#endif /* MBEDTLS_ECP_ALT */ -#if defined(MBEDTLS_MD2_PROCESS_ALT) - "MBEDTLS_MD2_PROCESS_ALT", -#endif /* MBEDTLS_MD2_PROCESS_ALT */ -#if defined(MBEDTLS_MD4_PROCESS_ALT) - "MBEDTLS_MD4_PROCESS_ALT", -#endif /* MBEDTLS_MD4_PROCESS_ALT */ -#if defined(MBEDTLS_MD5_PROCESS_ALT) - "MBEDTLS_MD5_PROCESS_ALT", -#endif /* MBEDTLS_MD5_PROCESS_ALT */ -#if defined(MBEDTLS_RIPEMD160_PROCESS_ALT) - "MBEDTLS_RIPEMD160_PROCESS_ALT", -#endif /* MBEDTLS_RIPEMD160_PROCESS_ALT */ -#if defined(MBEDTLS_SHA1_PROCESS_ALT) - "MBEDTLS_SHA1_PROCESS_ALT", -#endif /* MBEDTLS_SHA1_PROCESS_ALT */ -#if defined(MBEDTLS_SHA256_PROCESS_ALT) - "MBEDTLS_SHA256_PROCESS_ALT", -#endif /* MBEDTLS_SHA256_PROCESS_ALT */ -#if defined(MBEDTLS_SHA512_PROCESS_ALT) - "MBEDTLS_SHA512_PROCESS_ALT", -#endif /* MBEDTLS_SHA512_PROCESS_ALT */ -#if defined(MBEDTLS_DES_SETKEY_ALT) - "MBEDTLS_DES_SETKEY_ALT", -#endif /* MBEDTLS_DES_SETKEY_ALT */ -#if defined(MBEDTLS_DES_CRYPT_ECB_ALT) - "MBEDTLS_DES_CRYPT_ECB_ALT", -#endif /* MBEDTLS_DES_CRYPT_ECB_ALT */ -#if defined(MBEDTLS_DES3_CRYPT_ECB_ALT) - "MBEDTLS_DES3_CRYPT_ECB_ALT", -#endif /* MBEDTLS_DES3_CRYPT_ECB_ALT */ -#if defined(MBEDTLS_AES_SETKEY_ENC_ALT) - "MBEDTLS_AES_SETKEY_ENC_ALT", -#endif /* MBEDTLS_AES_SETKEY_ENC_ALT */ -#if defined(MBEDTLS_AES_SETKEY_DEC_ALT) - "MBEDTLS_AES_SETKEY_DEC_ALT", -#endif /* MBEDTLS_AES_SETKEY_DEC_ALT */ -#if defined(MBEDTLS_AES_ENCRYPT_ALT) - "MBEDTLS_AES_ENCRYPT_ALT", -#endif /* MBEDTLS_AES_ENCRYPT_ALT */ -#if defined(MBEDTLS_AES_DECRYPT_ALT) - "MBEDTLS_AES_DECRYPT_ALT", -#endif /* MBEDTLS_AES_DECRYPT_ALT */ -#if defined(MBEDTLS_ECP_INTERNAL_ALT) - "MBEDTLS_ECP_INTERNAL_ALT", -#endif /* MBEDTLS_ECP_INTERNAL_ALT */ -#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) - "MBEDTLS_ECP_RANDOMIZE_JAC_ALT", -#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ -#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) - "MBEDTLS_ECP_ADD_MIXED_ALT", -#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ -#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) - "MBEDTLS_ECP_DOUBLE_JAC_ALT", -#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) - "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT", -#endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT */ -#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) - "MBEDTLS_ECP_NORMALIZE_JAC_ALT", -#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ -#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) - "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT", -#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ -#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) - "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT", -#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ -#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) - "MBEDTLS_ECP_NORMALIZE_MXZ_ALT", -#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ -#if defined(MBEDTLS_TEST_NULL_ENTROPY) - "MBEDTLS_TEST_NULL_ENTROPY", -#endif /* MBEDTLS_TEST_NULL_ENTROPY */ -#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) - "MBEDTLS_ENTROPY_HARDWARE_ALT", -#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ -#if defined(MBEDTLS_AES_ROM_TABLES) - "MBEDTLS_AES_ROM_TABLES", -#endif /* MBEDTLS_AES_ROM_TABLES */ -#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) - "MBEDTLS_CAMELLIA_SMALL_MEMORY", -#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ -#if defined(MBEDTLS_CIPHER_MODE_CBC) - "MBEDTLS_CIPHER_MODE_CBC", -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#if defined(MBEDTLS_CIPHER_MODE_CFB) - "MBEDTLS_CIPHER_MODE_CFB", -#endif /* MBEDTLS_CIPHER_MODE_CFB */ -#if defined(MBEDTLS_CIPHER_MODE_CTR) - "MBEDTLS_CIPHER_MODE_CTR", -#endif /* MBEDTLS_CIPHER_MODE_CTR */ -#if defined(MBEDTLS_CIPHER_NULL_CIPHER) - "MBEDTLS_CIPHER_NULL_CIPHER", -#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ -#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) - "MBEDTLS_CIPHER_PADDING_PKCS7", -#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ -#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) - "MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS", -#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ -#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) - "MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN", -#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ -#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) - "MBEDTLS_CIPHER_PADDING_ZEROS", -#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ -#if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) - "MBEDTLS_ENABLE_WEAK_CIPHERSUITES", -#endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ -#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) - "MBEDTLS_REMOVE_ARC4_CIPHERSUITES", -#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ -#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) - "MBEDTLS_ECP_DP_SECP192R1_ENABLED", -#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) - "MBEDTLS_ECP_DP_SECP224R1_ENABLED", -#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) - "MBEDTLS_ECP_DP_SECP256R1_ENABLED", -#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) - "MBEDTLS_ECP_DP_SECP384R1_ENABLED", -#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) - "MBEDTLS_ECP_DP_SECP521R1_ENABLED", -#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) - "MBEDTLS_ECP_DP_SECP192K1_ENABLED", -#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) - "MBEDTLS_ECP_DP_SECP224K1_ENABLED", -#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) - "MBEDTLS_ECP_DP_SECP256K1_ENABLED", -#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) - "MBEDTLS_ECP_DP_BP256R1_ENABLED", -#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) - "MBEDTLS_ECP_DP_BP384R1_ENABLED", -#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) - "MBEDTLS_ECP_DP_BP512R1_ENABLED", -#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ -#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) - "MBEDTLS_ECP_DP_CURVE25519_ENABLED", -#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ -#if defined(MBEDTLS_ECP_NIST_OPTIM) - "MBEDTLS_ECP_NIST_OPTIM", -#endif /* MBEDTLS_ECP_NIST_OPTIM */ -#if defined(MBEDTLS_ECDSA_DETERMINISTIC) - "MBEDTLS_ECDSA_DETERMINISTIC", -#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ -#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - "MBEDTLS_KEY_EXCHANGE_PSK_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) - "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) - "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ -#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) - "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED", -#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ -#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) - "MBEDTLS_PK_PARSE_EC_EXTENDED", -#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ -#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) - "MBEDTLS_ERROR_STRERROR_DUMMY", -#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ -#if defined(MBEDTLS_GENPRIME) - "MBEDTLS_GENPRIME", -#endif /* MBEDTLS_GENPRIME */ -#if defined(MBEDTLS_FS_IO) - "MBEDTLS_FS_IO", -#endif /* MBEDTLS_FS_IO */ -#if defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) - "MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES", -#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ -#if defined(MBEDTLS_NO_PLATFORM_ENTROPY) - "MBEDTLS_NO_PLATFORM_ENTROPY", -#endif /* MBEDTLS_NO_PLATFORM_ENTROPY */ -#if defined(MBEDTLS_ENTROPY_FORCE_SHA256) - "MBEDTLS_ENTROPY_FORCE_SHA256", -#endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */ -#if defined(MBEDTLS_ENTROPY_NV_SEED) - "MBEDTLS_ENTROPY_NV_SEED", -#endif /* MBEDTLS_ENTROPY_NV_SEED */ -#if defined(MBEDTLS_MEMORY_DEBUG) - "MBEDTLS_MEMORY_DEBUG", -#endif /* MBEDTLS_MEMORY_DEBUG */ -#if defined(MBEDTLS_MEMORY_BACKTRACE) - "MBEDTLS_MEMORY_BACKTRACE", -#endif /* MBEDTLS_MEMORY_BACKTRACE */ -#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) - "MBEDTLS_PK_RSA_ALT_SUPPORT", -#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ -#if defined(MBEDTLS_PKCS1_V15) - "MBEDTLS_PKCS1_V15", -#endif /* MBEDTLS_PKCS1_V15 */ -#if defined(MBEDTLS_PKCS1_V21) - "MBEDTLS_PKCS1_V21", -#endif /* MBEDTLS_PKCS1_V21 */ -#if defined(MBEDTLS_RSA_NO_CRT) - "MBEDTLS_RSA_NO_CRT", -#endif /* MBEDTLS_RSA_NO_CRT */ -#if defined(MBEDTLS_SELF_TEST) - "MBEDTLS_SELF_TEST", -#endif /* MBEDTLS_SELF_TEST */ -#if defined(MBEDTLS_SHA256_SMALLER) - "MBEDTLS_SHA256_SMALLER", -#endif /* MBEDTLS_SHA256_SMALLER */ -#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) - "MBEDTLS_SSL_ALL_ALERT_MESSAGES", -#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */ -#if defined(MBEDTLS_SSL_DEBUG_ALL) - "MBEDTLS_SSL_DEBUG_ALL", -#endif /* MBEDTLS_SSL_DEBUG_ALL */ -#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) - "MBEDTLS_SSL_ENCRYPT_THEN_MAC", -#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ -#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) - "MBEDTLS_SSL_EXTENDED_MASTER_SECRET", -#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ -#if defined(MBEDTLS_SSL_FALLBACK_SCSV) - "MBEDTLS_SSL_FALLBACK_SCSV", -#endif /* MBEDTLS_SSL_FALLBACK_SCSV */ -#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) - "MBEDTLS_SSL_HW_RECORD_ACCEL", -#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ -#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) - "MBEDTLS_SSL_CBC_RECORD_SPLITTING", -#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */ -#if defined(MBEDTLS_SSL_RENEGOTIATION) - "MBEDTLS_SSL_RENEGOTIATION", -#endif /* MBEDTLS_SSL_RENEGOTIATION */ -#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) - "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO", -#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */ -#if defined(MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE) - "MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE", -#endif /* MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE */ -#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) - "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH", -#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ -#if defined(MBEDTLS_SSL_PROTO_SSL3) - "MBEDTLS_SSL_PROTO_SSL3", -#endif /* MBEDTLS_SSL_PROTO_SSL3 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1) - "MBEDTLS_SSL_PROTO_TLS1", -#endif /* MBEDTLS_SSL_PROTO_TLS1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_1) - "MBEDTLS_SSL_PROTO_TLS1_1", -#endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ -#if defined(MBEDTLS_SSL_PROTO_TLS1_2) - "MBEDTLS_SSL_PROTO_TLS1_2", -#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -#if defined(MBEDTLS_SSL_PROTO_DTLS) - "MBEDTLS_SSL_PROTO_DTLS", -#endif /* MBEDTLS_SSL_PROTO_DTLS */ -#if defined(MBEDTLS_SSL_ALPN) - "MBEDTLS_SSL_ALPN", -#endif /* MBEDTLS_SSL_ALPN */ -#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) - "MBEDTLS_SSL_DTLS_ANTI_REPLAY", -#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ -#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) - "MBEDTLS_SSL_DTLS_HELLO_VERIFY", -#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ -#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) - "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE", -#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */ -#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) - "MBEDTLS_SSL_DTLS_BADMAC_LIMIT", -#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ -#if defined(MBEDTLS_SSL_SESSION_TICKETS) - "MBEDTLS_SSL_SESSION_TICKETS", -#endif /* MBEDTLS_SSL_SESSION_TICKETS */ -#if defined(MBEDTLS_SSL_EXPORT_KEYS) - "MBEDTLS_SSL_EXPORT_KEYS", -#endif /* MBEDTLS_SSL_EXPORT_KEYS */ -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - "MBEDTLS_SSL_SERVER_NAME_INDICATION", -#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ -#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) - "MBEDTLS_SSL_TRUNCATED_HMAC", -#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ -#if defined(MBEDTLS_THREADING_ALT) - "MBEDTLS_THREADING_ALT", -#endif /* MBEDTLS_THREADING_ALT */ -#if defined(MBEDTLS_THREADING_PTHREAD) - "MBEDTLS_THREADING_PTHREAD", -#endif /* MBEDTLS_THREADING_PTHREAD */ -#if defined(MBEDTLS_VERSION_FEATURES) - "MBEDTLS_VERSION_FEATURES", -#endif /* MBEDTLS_VERSION_FEATURES */ -#if defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) - "MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3", -#endif /* MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 */ -#if defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) - "MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION", -#endif /* MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */ -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) - "MBEDTLS_X509_CHECK_KEY_USAGE", -#endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ -#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) - "MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE", -#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) - "MBEDTLS_X509_RSASSA_PSS_SUPPORT", -#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ -#if defined(MBEDTLS_ZLIB_SUPPORT) - "MBEDTLS_ZLIB_SUPPORT", -#endif /* MBEDTLS_ZLIB_SUPPORT */ -#if defined(MBEDTLS_AESNI_C) - "MBEDTLS_AESNI_C", -#endif /* MBEDTLS_AESNI_C */ -#if defined(MBEDTLS_AES_C) - "MBEDTLS_AES_C", -#endif /* MBEDTLS_AES_C */ -#if defined(MBEDTLS_ARC4_C) - "MBEDTLS_ARC4_C", -#endif /* MBEDTLS_ARC4_C */ -#if defined(MBEDTLS_ASN1_PARSE_C) - "MBEDTLS_ASN1_PARSE_C", -#endif /* MBEDTLS_ASN1_PARSE_C */ -#if defined(MBEDTLS_ASN1_WRITE_C) - "MBEDTLS_ASN1_WRITE_C", -#endif /* MBEDTLS_ASN1_WRITE_C */ -#if defined(MBEDTLS_BASE64_C) - "MBEDTLS_BASE64_C", -#endif /* MBEDTLS_BASE64_C */ -#if defined(MBEDTLS_BIGNUM_C) - "MBEDTLS_BIGNUM_C", -#endif /* MBEDTLS_BIGNUM_C */ -#if defined(MBEDTLS_BLOWFISH_C) - "MBEDTLS_BLOWFISH_C", -#endif /* MBEDTLS_BLOWFISH_C */ -#if defined(MBEDTLS_CAMELLIA_C) - "MBEDTLS_CAMELLIA_C", -#endif /* MBEDTLS_CAMELLIA_C */ -#if defined(MBEDTLS_CCM_C) - "MBEDTLS_CCM_C", -#endif /* MBEDTLS_CCM_C */ -#if defined(MBEDTLS_CERTS_C) - "MBEDTLS_CERTS_C", -#endif /* MBEDTLS_CERTS_C */ -#if defined(MBEDTLS_CIPHER_C) - "MBEDTLS_CIPHER_C", -#endif /* MBEDTLS_CIPHER_C */ -#if defined(MBEDTLS_CMAC_C) - "MBEDTLS_CMAC_C", -#endif /* MBEDTLS_CMAC_C */ -#if defined(MBEDTLS_CTR_DRBG_C) - "MBEDTLS_CTR_DRBG_C", -#endif /* MBEDTLS_CTR_DRBG_C */ -#if defined(MBEDTLS_DEBUG_C) - "MBEDTLS_DEBUG_C", -#endif /* MBEDTLS_DEBUG_C */ -#if defined(MBEDTLS_DES_C) - "MBEDTLS_DES_C", -#endif /* MBEDTLS_DES_C */ -#if defined(MBEDTLS_DHM_C) - "MBEDTLS_DHM_C", -#endif /* MBEDTLS_DHM_C */ -#if defined(MBEDTLS_ECDH_C) - "MBEDTLS_ECDH_C", -#endif /* MBEDTLS_ECDH_C */ -#if defined(MBEDTLS_ECDSA_C) - "MBEDTLS_ECDSA_C", -#endif /* MBEDTLS_ECDSA_C */ -#if defined(MBEDTLS_ECJPAKE_C) - "MBEDTLS_ECJPAKE_C", -#endif /* MBEDTLS_ECJPAKE_C */ -#if defined(MBEDTLS_ECP_C) - "MBEDTLS_ECP_C", -#endif /* MBEDTLS_ECP_C */ -#if defined(MBEDTLS_ENTROPY_C) - "MBEDTLS_ENTROPY_C", -#endif /* MBEDTLS_ENTROPY_C */ -#if defined(MBEDTLS_ERROR_C) - "MBEDTLS_ERROR_C", -#endif /* MBEDTLS_ERROR_C */ -#if defined(MBEDTLS_GCM_C) - "MBEDTLS_GCM_C", -#endif /* MBEDTLS_GCM_C */ -#if defined(MBEDTLS_HAVEGE_C) - "MBEDTLS_HAVEGE_C", -#endif /* MBEDTLS_HAVEGE_C */ -#if defined(MBEDTLS_HMAC_DRBG_C) - "MBEDTLS_HMAC_DRBG_C", -#endif /* MBEDTLS_HMAC_DRBG_C */ -#if defined(MBEDTLS_MD_C) - "MBEDTLS_MD_C", -#endif /* MBEDTLS_MD_C */ -#if defined(MBEDTLS_MD2_C) - "MBEDTLS_MD2_C", -#endif /* MBEDTLS_MD2_C */ -#if defined(MBEDTLS_MD4_C) - "MBEDTLS_MD4_C", -#endif /* MBEDTLS_MD4_C */ -#if defined(MBEDTLS_MD5_C) - "MBEDTLS_MD5_C", -#endif /* MBEDTLS_MD5_C */ -#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) - "MBEDTLS_MEMORY_BUFFER_ALLOC_C", -#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ -#if defined(MBEDTLS_NET_C) - "MBEDTLS_NET_C", -#endif /* MBEDTLS_NET_C */ -#if defined(MBEDTLS_OID_C) - "MBEDTLS_OID_C", -#endif /* MBEDTLS_OID_C */ -#if defined(MBEDTLS_PADLOCK_C) - "MBEDTLS_PADLOCK_C", -#endif /* MBEDTLS_PADLOCK_C */ -#if defined(MBEDTLS_PEM_PARSE_C) - "MBEDTLS_PEM_PARSE_C", -#endif /* MBEDTLS_PEM_PARSE_C */ -#if defined(MBEDTLS_PEM_WRITE_C) - "MBEDTLS_PEM_WRITE_C", -#endif /* MBEDTLS_PEM_WRITE_C */ -#if defined(MBEDTLS_PK_C) - "MBEDTLS_PK_C", -#endif /* MBEDTLS_PK_C */ -#if defined(MBEDTLS_PK_PARSE_C) - "MBEDTLS_PK_PARSE_C", -#endif /* MBEDTLS_PK_PARSE_C */ -#if defined(MBEDTLS_PK_WRITE_C) - "MBEDTLS_PK_WRITE_C", -#endif /* MBEDTLS_PK_WRITE_C */ -#if defined(MBEDTLS_PKCS5_C) - "MBEDTLS_PKCS5_C", -#endif /* MBEDTLS_PKCS5_C */ -#if defined(MBEDTLS_PKCS11_C) - "MBEDTLS_PKCS11_C", -#endif /* MBEDTLS_PKCS11_C */ -#if defined(MBEDTLS_PKCS12_C) - "MBEDTLS_PKCS12_C", -#endif /* MBEDTLS_PKCS12_C */ -#if defined(MBEDTLS_PLATFORM_C) - "MBEDTLS_PLATFORM_C", -#endif /* MBEDTLS_PLATFORM_C */ -#if defined(MBEDTLS_RIPEMD160_C) - "MBEDTLS_RIPEMD160_C", -#endif /* MBEDTLS_RIPEMD160_C */ -#if defined(MBEDTLS_RSA_C) - "MBEDTLS_RSA_C", -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_SHA1_C) - "MBEDTLS_SHA1_C", -#endif /* MBEDTLS_SHA1_C */ -#if defined(MBEDTLS_SHA256_C) - "MBEDTLS_SHA256_C", -#endif /* MBEDTLS_SHA256_C */ -#if defined(MBEDTLS_SHA512_C) - "MBEDTLS_SHA512_C", -#endif /* MBEDTLS_SHA512_C */ -#if defined(MBEDTLS_SSL_CACHE_C) - "MBEDTLS_SSL_CACHE_C", -#endif /* MBEDTLS_SSL_CACHE_C */ -#if defined(MBEDTLS_SSL_COOKIE_C) - "MBEDTLS_SSL_COOKIE_C", -#endif /* MBEDTLS_SSL_COOKIE_C */ -#if defined(MBEDTLS_SSL_TICKET_C) - "MBEDTLS_SSL_TICKET_C", -#endif /* MBEDTLS_SSL_TICKET_C */ -#if defined(MBEDTLS_SSL_CLI_C) - "MBEDTLS_SSL_CLI_C", -#endif /* MBEDTLS_SSL_CLI_C */ -#if defined(MBEDTLS_SSL_SRV_C) - "MBEDTLS_SSL_SRV_C", -#endif /* MBEDTLS_SSL_SRV_C */ -#if defined(MBEDTLS_SSL_TLS_C) - "MBEDTLS_SSL_TLS_C", -#endif /* MBEDTLS_SSL_TLS_C */ -#if defined(MBEDTLS_THREADING_C) - "MBEDTLS_THREADING_C", -#endif /* MBEDTLS_THREADING_C */ -#if defined(MBEDTLS_TIMING_C) - "MBEDTLS_TIMING_C", -#endif /* MBEDTLS_TIMING_C */ -#if defined(MBEDTLS_VERSION_C) - "MBEDTLS_VERSION_C", -#endif /* MBEDTLS_VERSION_C */ -#if defined(MBEDTLS_X509_USE_C) - "MBEDTLS_X509_USE_C", -#endif /* MBEDTLS_X509_USE_C */ -#if defined(MBEDTLS_X509_CRT_PARSE_C) - "MBEDTLS_X509_CRT_PARSE_C", -#endif /* MBEDTLS_X509_CRT_PARSE_C */ -#if defined(MBEDTLS_X509_CRL_PARSE_C) - "MBEDTLS_X509_CRL_PARSE_C", -#endif /* MBEDTLS_X509_CRL_PARSE_C */ -#if defined(MBEDTLS_X509_CSR_PARSE_C) - "MBEDTLS_X509_CSR_PARSE_C", -#endif /* MBEDTLS_X509_CSR_PARSE_C */ -#if defined(MBEDTLS_X509_CREATE_C) - "MBEDTLS_X509_CREATE_C", -#endif /* MBEDTLS_X509_CREATE_C */ -#if defined(MBEDTLS_X509_CRT_WRITE_C) - "MBEDTLS_X509_CRT_WRITE_C", -#endif /* MBEDTLS_X509_CRT_WRITE_C */ -#if defined(MBEDTLS_X509_CSR_WRITE_C) - "MBEDTLS_X509_CSR_WRITE_C", -#endif /* MBEDTLS_X509_CSR_WRITE_C */ -#if defined(MBEDTLS_XTEA_C) - "MBEDTLS_XTEA_C", -#endif /* MBEDTLS_XTEA_C */ -#endif /* MBEDTLS_VERSION_FEATURES */ - NULL -}; - -int mbedtls_version_check_feature( const char *feature ) -{ - const char **idx = features; - - if( *idx == NULL ) - return( -2 ); - - if( feature == NULL ) - return( -1 ); - - while( *idx != NULL ) - { - if( !strcmp( *idx, feature ) ) - return( 0 ); - idx++; - } - return( -1 ); -} - -#endif /* MBEDTLS_VERSION_C */ diff --git a/components/mbedtls/library/x509.c b/components/mbedtls/library/x509.c deleted file mode 100644 index e94a8a329f..0000000000 --- a/components/mbedtls/library/x509.c +++ /dev/null @@ -1,1098 +0,0 @@ -/* - * X.509 common functions for parsing and verification - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The ITU-T X.509 standard defines a certificate format for PKI. - * - * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) - * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) - * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) - * - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_X509_USE_C) - -#include "mbedtls/x509.h" -#include "mbedtls/asn1.h" -#include "mbedtls/oid.h" - -#include -#include - -#if defined(MBEDTLS_PEM_PARSE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_free free -#define mbedtls_calloc calloc -#define mbedtls_printf printf -#define mbedtls_snprintf snprintf -#endif - - -#if defined(MBEDTLS_HAVE_TIME) -#include "mbedtls/platform_time.h" -#endif - -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) -#include -#else -#include -#endif - -#if defined(MBEDTLS_FS_IO) -#include -#if !defined(_WIN32) -#include -#include -#include -#endif -#endif - -#define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); } -#define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); } - -/* - * CertificateSerialNumber ::= INTEGER - */ -int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *serial ) -{ - int ret; - - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_X509_INVALID_SERIAL + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) && - **p != MBEDTLS_ASN1_INTEGER ) - return( MBEDTLS_ERR_X509_INVALID_SERIAL + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - serial->tag = *(*p)++; - - if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret ); - - serial->p = *p; - *p += serial->len; - - return( 0 ); -} - -/* Get an algorithm identifier without parameters (eg for signatures) - * - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL } - */ -int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *alg ) -{ - int ret; - - if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - return( 0 ); -} - -/* - * Parse an algorithm identifier with (optional) paramaters - */ -int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *alg, mbedtls_x509_buf *params ) -{ - int ret; - - if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - return( 0 ); -} - -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) -/* - * HashAlgorithm ::= AlgorithmIdentifier - * - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL } - * - * For HashAlgorithm, parameters MUST be NULL or absent. - */ -static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg ) -{ - int ret; - unsigned char *p; - const unsigned char *end; - mbedtls_x509_buf md_oid; - size_t len; - - /* Make sure we got a SEQUENCE and setup bounds */ - if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - p = (unsigned char *) alg->p; - end = p + alg->len; - - if( p >= end ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - /* Parse md_oid */ - md_oid.tag = *p; - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - md_oid.p = p; - p += md_oid.len; - - /* Get md_alg from md_oid */ - if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - /* Make sure params is absent of NULL */ - if( p == end ) - return( 0 ); - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - if( p != end ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * RSASSA-PSS-params ::= SEQUENCE { - * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, - * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, - * saltLength [2] INTEGER DEFAULT 20, - * trailerField [3] INTEGER DEFAULT 1 } - * -- Note that the tags in this Sequence are explicit. - * - * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value - * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other - * option. Enfore this at parsing time. - */ -int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, - mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, - int *salt_len ) -{ - int ret; - unsigned char *p; - const unsigned char *end, *end2; - size_t len; - mbedtls_x509_buf alg_id, alg_params; - - /* First set everything to defaults */ - *md_alg = MBEDTLS_MD_SHA1; - *mgf_md = MBEDTLS_MD_SHA1; - *salt_len = 20; - - /* Make sure params is a SEQUENCE and setup bounds */ - if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - p = (unsigned char *) params->p; - end = p + params->len; - - if( p == end ) - return( 0 ); - - /* - * HashAlgorithm - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) - { - end2 = p + len; - - /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ - if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - if( p != end2 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - if( p == end ) - return( 0 ); - - /* - * MaskGenAlgorithm - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) - { - end2 = p + len; - - /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ - if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 ) - return( ret ); - - /* Only MFG1 is recognised for now */ - if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 ) - return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE + - MBEDTLS_ERR_OID_NOT_FOUND ); - - /* Parse HashAlgorithm */ - if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 ) - return( ret ); - - if( p != end2 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - if( p == end ) - return( 0 ); - - /* - * salt_len - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 ) - { - end2 = p + len; - - if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - if( p != end2 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - if( p == end ) - return( 0 ); - - /* - * trailer_field (if present, must be 1) - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 ) - { - int trailer_field; - - end2 = p + len; - - if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - if( p != end2 ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - if( trailer_field != 1 ) - return( MBEDTLS_ERR_X509_INVALID_ALG ); - } - else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); - - if( p != end ) - return( MBEDTLS_ERR_X509_INVALID_ALG + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} -#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ - -/* - * AttributeTypeAndValue ::= SEQUENCE { - * type AttributeType, - * value AttributeValue } - * - * AttributeType ::= OBJECT IDENTIFIER - * - * AttributeValue ::= ANY DEFINED BY AttributeType - */ -static int x509_get_attr_type_value( unsigned char **p, - const unsigned char *end, - mbedtls_x509_name *cur ) -{ - int ret; - size_t len; - mbedtls_x509_buf *oid; - mbedtls_x509_buf *val; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); - - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_X509_INVALID_NAME + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - oid = &cur->oid; - oid->tag = **p; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); - - oid->p = *p; - *p += oid->len; - - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_X509_INVALID_NAME + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && - **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && - **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && - **p != MBEDTLS_ASN1_BIT_STRING ) - return( MBEDTLS_ERR_X509_INVALID_NAME + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - val = &cur->val; - val->tag = *(*p)++; - - if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); - - val->p = *p; - *p += val->len; - - cur->next = NULL; - - return( 0 ); -} - -/* - * Name ::= CHOICE { -- only one possibility for now -- - * rdnSequence RDNSequence } - * - * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName - * - * RelativeDistinguishedName ::= - * SET OF AttributeTypeAndValue - * - * AttributeTypeAndValue ::= SEQUENCE { - * type AttributeType, - * value AttributeValue } - * - * AttributeType ::= OBJECT IDENTIFIER - * - * AttributeValue ::= ANY DEFINED BY AttributeType - * - * The data structure is optimized for the common case where each RDN has only - * one element, which is represented as a list of AttributeTypeAndValue. - * For the general case we still use a flat list, but we mark elements of the - * same set so that they are "merged" together in the functions that consume - * this list, eg mbedtls_x509_dn_gets(). - */ -int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, - mbedtls_x509_name *cur ) -{ - int ret; - size_t set_len; - const unsigned char *end_set; - - /* don't use recursion, we'd risk stack overflow if not optimized */ - while( 1 ) - { - /* - * parse SET - */ - if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); - - end_set = *p + set_len; - - while( 1 ) - { - if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) - return( ret ); - - if( *p == end_set ) - break; - - /* Mark this item as being no the only one in a set */ - cur->next_merged = 1; - - cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); - - if( cur->next == NULL ) - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - - cur = cur->next; - } - - /* - * continue until end of SEQUENCE is reached - */ - if( *p == end ) - return( 0 ); - - cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); - - if( cur->next == NULL ) - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - - cur = cur->next; - } -} - -static int x509_parse_int( unsigned char **p, size_t n, int *res ) -{ - *res = 0; - - for( ; n > 0; --n ) - { - if( ( **p < '0') || ( **p > '9' ) ) - return ( MBEDTLS_ERR_X509_INVALID_DATE ); - - *res *= 10; - *res += ( *(*p)++ - '0' ); - } - - return( 0 ); -} - -static int x509_date_is_valid(const mbedtls_x509_time *t) -{ - int ret = MBEDTLS_ERR_X509_INVALID_DATE; - - CHECK_RANGE( 0, 9999, t->year ); - CHECK_RANGE( 0, 23, t->hour ); - CHECK_RANGE( 0, 59, t->min ); - CHECK_RANGE( 0, 59, t->sec ); - - switch( t->mon ) - { - case 1: case 3: case 5: case 7: case 8: case 10: case 12: - CHECK_RANGE( 1, 31, t->day ); - break; - case 4: case 6: case 9: case 11: - CHECK_RANGE( 1, 30, t->day ); - break; - case 2: - CHECK_RANGE( 1, 28 + (t->year % 4 == 0), t->day ); - break; - default: - return( ret ); - } - - return( 0 ); -} - -/* - * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) - * field. - */ -static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, - mbedtls_x509_time *tm ) -{ - int ret; - - /* - * Minimum length is 10 or 12 depending on yearlen - */ - if ( len < yearlen + 8 ) - return ( MBEDTLS_ERR_X509_INVALID_DATE ); - len -= yearlen + 8; - - /* - * Parse year, month, day, hour, minute - */ - CHECK( x509_parse_int( p, yearlen, &tm->year ) ); - if ( 2 == yearlen ) - { - if ( tm->year < 50 ) - tm->year += 100; - - tm->year += 1900; - } - - CHECK( x509_parse_int( p, 2, &tm->mon ) ); - CHECK( x509_parse_int( p, 2, &tm->day ) ); - CHECK( x509_parse_int( p, 2, &tm->hour ) ); - CHECK( x509_parse_int( p, 2, &tm->min ) ); - - /* - * Parse seconds if present - */ - if ( len >= 2 ) - { - CHECK( x509_parse_int( p, 2, &tm->sec ) ); - len -= 2; - } - else - return ( MBEDTLS_ERR_X509_INVALID_DATE ); - - /* - * Parse trailing 'Z' if present - */ - if ( 1 == len && 'Z' == **p ) - { - (*p)++; - len--; - } - - /* - * We should have parsed all characters at this point - */ - if ( 0 != len ) - return ( MBEDTLS_ERR_X509_INVALID_DATE ); - - CHECK( x509_date_is_valid( tm ) ); - - return ( 0 ); -} - -/* - * Time ::= CHOICE { - * utcTime UTCTime, - * generalTime GeneralizedTime } - */ -int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, - mbedtls_x509_time *tm ) -{ - int ret; - size_t len, year_len; - unsigned char tag; - - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_X509_INVALID_DATE + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - tag = **p; - - if( tag == MBEDTLS_ASN1_UTC_TIME ) - year_len = 2; - else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME ) - year_len = 4; - else - return( MBEDTLS_ERR_X509_INVALID_DATE + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - (*p)++; - ret = mbedtls_asn1_get_len( p, end, &len ); - - if( ret != 0 ) - return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); - - return x509_parse_time( p, len, year_len, tm ); -} - -int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ) -{ - int ret; - size_t len; - int tag_type; - - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - tag_type = **p; - - if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret ); - - sig->tag = tag_type; - sig->len = len; - sig->p = *p; - - *p += len; - - return( 0 ); -} - -/* - * Get signature algorithm from alg OID and optional parameters - */ -int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, - mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, - void **sig_opts ) -{ - int ret; - - if( *sig_opts != NULL ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 ) - return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret ); - -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) - if( *pk_alg == MBEDTLS_PK_RSASSA_PSS ) - { - mbedtls_pk_rsassa_pss_options *pss_opts; - - pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) ); - if( pss_opts == NULL ) - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - - ret = mbedtls_x509_get_rsassa_pss_params( sig_params, - md_alg, - &pss_opts->mgf1_hash_id, - &pss_opts->expected_salt_len ); - if( ret != 0 ) - { - mbedtls_free( pss_opts ); - return( ret ); - } - - *sig_opts = (void *) pss_opts; - } - else -#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ - { - /* Make sure parameters are absent or NULL */ - if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) || - sig_params->len != 0 ) - return( MBEDTLS_ERR_X509_INVALID_ALG ); - } - - return( 0 ); -} - -/* - * X.509 Extensions (No parsing of extensions, pointer should - * be either manually updated or extensions should be parsed!) - */ -int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, - mbedtls_x509_buf *ext, int tag ) -{ - int ret; - size_t len; - - if( *p == end ) - return( 0 ); - - ext->tag = **p; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ) ) != 0 ) - return( ret ); - - ext->p = *p; - end = *p + ext->len; - - /* - * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension - * - * Extension ::= SEQUENCE { - * extnID OBJECT IDENTIFIER, - * critical BOOLEAN DEFAULT FALSE, - * extnValue OCTET STRING } - */ - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - if( end != *p + len ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * Store the name in printable form into buf; no more - * than size characters will be written - */ -int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ) -{ - int ret; - size_t i, n; - unsigned char c, merge = 0; - const mbedtls_x509_name *name; - const char *short_name = NULL; - char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; - - memset( s, 0, sizeof( s ) ); - - name = dn; - p = buf; - n = size; - - while( name != NULL ) - { - if( !name->oid.p ) - { - name = name->next; - continue; - } - - if( name != dn ) - { - ret = mbedtls_snprintf( p, n, merge ? " + " : ", " ); - MBEDTLS_X509_SAFE_SNPRINTF; - } - - ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name ); - - if( ret == 0 ) - ret = mbedtls_snprintf( p, n, "%s=", short_name ); - else - ret = mbedtls_snprintf( p, n, "\?\?=" ); - MBEDTLS_X509_SAFE_SNPRINTF; - - for( i = 0; i < name->val.len; i++ ) - { - if( i >= sizeof( s ) - 1 ) - break; - - c = name->val.p[i]; - if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) - s[i] = '?'; - else s[i] = c; - } - s[i] = '\0'; - ret = mbedtls_snprintf( p, n, "%s", s ); - MBEDTLS_X509_SAFE_SNPRINTF; - - merge = name->next_merged; - name = name->next; - } - - return( (int) ( size - n ) ); -} - -/* - * Store the serial in printable form into buf; no more - * than size characters will be written - */ -int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ) -{ - int ret; - size_t i, n, nr; - char *p; - - p = buf; - n = size; - - nr = ( serial->len <= 32 ) - ? serial->len : 28; - - for( i = 0; i < nr; i++ ) - { - if( i == 0 && nr > 1 && serial->p[i] == 0x0 ) - continue; - - ret = mbedtls_snprintf( p, n, "%02X%s", - serial->p[i], ( i < nr - 1 ) ? ":" : "" ); - MBEDTLS_X509_SAFE_SNPRINTF; - } - - if( nr != serial->len ) - { - ret = mbedtls_snprintf( p, n, "...." ); - MBEDTLS_X509_SAFE_SNPRINTF; - } - - return( (int) ( size - n ) ); -} - -/* - * Helper for writing signature algorithms - */ -int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, - mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, - const void *sig_opts ) -{ - int ret; - char *p = buf; - size_t n = size; - const char *desc = NULL; - - ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc ); - if( ret != 0 ) - ret = mbedtls_snprintf( p, n, "???" ); - else - ret = mbedtls_snprintf( p, n, "%s", desc ); - MBEDTLS_X509_SAFE_SNPRINTF; - -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) - if( pk_alg == MBEDTLS_PK_RSASSA_PSS ) - { - const mbedtls_pk_rsassa_pss_options *pss_opts; - const mbedtls_md_info_t *md_info, *mgf_md_info; - - pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; - - md_info = mbedtls_md_info_from_type( md_alg ); - mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id ); - - ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)", - md_info ? mbedtls_md_get_name( md_info ) : "???", - mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???", - pss_opts->expected_salt_len ); - MBEDTLS_X509_SAFE_SNPRINTF; - } -#else - ((void) pk_alg); - ((void) md_alg); - ((void) sig_opts); -#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ - - return( (int)( size - n ) ); -} - -/* - * Helper for writing "RSA key size", "EC key size", etc - */ -int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ) -{ - char *p = buf; - size_t n = buf_size; - int ret; - - ret = mbedtls_snprintf( p, n, "%s key size", name ); - MBEDTLS_X509_SAFE_SNPRINTF; - - return( 0 ); -} - -#if defined(MBEDTLS_HAVE_TIME_DATE) -/* - * Set the time structure to the current time. - * Return 0 on success, non-zero on failure. - */ -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) -static int x509_get_current_time( mbedtls_x509_time *now ) -{ - SYSTEMTIME st; - - GetSystemTime( &st ); - - now->year = st.wYear; - now->mon = st.wMonth; - now->day = st.wDay; - now->hour = st.wHour; - now->min = st.wMinute; - now->sec = st.wSecond; - - return( 0 ); -} -#else -static int x509_get_current_time( mbedtls_x509_time *now ) -{ - struct tm *lt; - mbedtls_time_t tt; - int ret = 0; - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - tt = mbedtls_time( NULL ); - lt = gmtime( &tt ); - - if( lt == NULL ) - ret = -1; - else - { - now->year = lt->tm_year + 1900; - now->mon = lt->tm_mon + 1; - now->day = lt->tm_mday; - now->hour = lt->tm_hour; - now->min = lt->tm_min; - now->sec = lt->tm_sec; - } - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) - return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); -#endif - - return( ret ); -} -#endif /* _WIN32 && !EFIX64 && !EFI32 */ - -/* - * Return 0 if before <= after, 1 otherwise - */ -static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after ) -{ - if( before->year > after->year ) - return( 1 ); - - if( before->year == after->year && - before->mon > after->mon ) - return( 1 ); - - if( before->year == after->year && - before->mon == after->mon && - before->day > after->day ) - return( 1 ); - - if( before->year == after->year && - before->mon == after->mon && - before->day == after->day && - before->hour > after->hour ) - return( 1 ); - - if( before->year == after->year && - before->mon == after->mon && - before->day == after->day && - before->hour == after->hour && - before->min > after->min ) - return( 1 ); - - if( before->year == after->year && - before->mon == after->mon && - before->day == after->day && - before->hour == after->hour && - before->min == after->min && - before->sec > after->sec ) - return( 1 ); - - return( 0 ); -} - -int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) -{ - mbedtls_x509_time now; - - if( x509_get_current_time( &now ) != 0 ) - return( 1 ); - - return( x509_check_time( &now, to ) ); -} - -int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) -{ - mbedtls_x509_time now; - - if( x509_get_current_time( &now ) != 0 ) - return( 1 ); - - return( x509_check_time( from, &now ) ); -} - -#else /* MBEDTLS_HAVE_TIME_DATE */ - -int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) -{ - ((void) to); - return( 0 ); -} - -int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) -{ - ((void) from); - return( 0 ); -} -#endif /* MBEDTLS_HAVE_TIME_DATE */ - -#if defined(MBEDTLS_SELF_TEST) - -#include "mbedtls/x509_crt.h" -#include "mbedtls/certs.h" - -/* - * Checkup routine - */ -int mbedtls_x509_self_test( int verbose ) -{ -#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C) - int ret; - uint32_t flags; - mbedtls_x509_crt cacert; - mbedtls_x509_crt clicert; - - if( verbose != 0 ) - mbedtls_printf( " X.509 certificate load: " ); - - mbedtls_x509_crt_init( &clicert ); - - ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt, - mbedtls_test_cli_crt_len ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( ret ); - } - - mbedtls_x509_crt_init( &cacert ); - - ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt, - mbedtls_test_ca_crt_len ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( ret ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n X.509 signature verify: "); - - ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL ); - if( ret != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - return( ret ); - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n\n"); - - mbedtls_x509_crt_free( &cacert ); - mbedtls_x509_crt_free( &clicert ); - - return( 0 ); -#else - ((void) verbose); - return( 0 ); -#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */ -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_X509_USE_C */ diff --git a/components/mbedtls/library/x509_create.c b/components/mbedtls/library/x509_create.c deleted file mode 100644 index df20ec8ebd..0000000000 --- a/components/mbedtls/library/x509_create.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * X.509 base functions for creating certificates / CSRs - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_X509_CREATE_C) - -#include "mbedtls/x509.h" -#include "mbedtls/asn1write.h" -#include "mbedtls/oid.h" - -#include - -typedef struct { - const char *name; - size_t name_len; - const char*oid; -} x509_attr_descriptor_t; - -#define ADD_STRLEN( s ) s, sizeof( s ) - 1 - -static const x509_attr_descriptor_t x509_attrs[] = -{ - { ADD_STRLEN( "CN" ), MBEDTLS_OID_AT_CN }, - { ADD_STRLEN( "commonName" ), MBEDTLS_OID_AT_CN }, - { ADD_STRLEN( "C" ), MBEDTLS_OID_AT_COUNTRY }, - { ADD_STRLEN( "countryName" ), MBEDTLS_OID_AT_COUNTRY }, - { ADD_STRLEN( "O" ), MBEDTLS_OID_AT_ORGANIZATION }, - { ADD_STRLEN( "organizationName" ), MBEDTLS_OID_AT_ORGANIZATION }, - { ADD_STRLEN( "L" ), MBEDTLS_OID_AT_LOCALITY }, - { ADD_STRLEN( "locality" ), MBEDTLS_OID_AT_LOCALITY }, - { ADD_STRLEN( "R" ), MBEDTLS_OID_PKCS9_EMAIL }, - { ADD_STRLEN( "OU" ), MBEDTLS_OID_AT_ORG_UNIT }, - { ADD_STRLEN( "organizationalUnitName" ), MBEDTLS_OID_AT_ORG_UNIT }, - { ADD_STRLEN( "ST" ), MBEDTLS_OID_AT_STATE }, - { ADD_STRLEN( "stateOrProvinceName" ), MBEDTLS_OID_AT_STATE }, - { ADD_STRLEN( "emailAddress" ), MBEDTLS_OID_PKCS9_EMAIL }, - { ADD_STRLEN( "serialNumber" ), MBEDTLS_OID_AT_SERIAL_NUMBER }, - { ADD_STRLEN( "postalAddress" ), MBEDTLS_OID_AT_POSTAL_ADDRESS }, - { ADD_STRLEN( "postalCode" ), MBEDTLS_OID_AT_POSTAL_CODE }, - { ADD_STRLEN( "dnQualifier" ), MBEDTLS_OID_AT_DN_QUALIFIER }, - { ADD_STRLEN( "title" ), MBEDTLS_OID_AT_TITLE }, - { ADD_STRLEN( "surName" ), MBEDTLS_OID_AT_SUR_NAME }, - { ADD_STRLEN( "SN" ), MBEDTLS_OID_AT_SUR_NAME }, - { ADD_STRLEN( "givenName" ), MBEDTLS_OID_AT_GIVEN_NAME }, - { ADD_STRLEN( "GN" ), MBEDTLS_OID_AT_GIVEN_NAME }, - { ADD_STRLEN( "initials" ), MBEDTLS_OID_AT_INITIALS }, - { ADD_STRLEN( "pseudonym" ), MBEDTLS_OID_AT_PSEUDONYM }, - { ADD_STRLEN( "generationQualifier" ), MBEDTLS_OID_AT_GENERATION_QUALIFIER }, - { ADD_STRLEN( "domainComponent" ), MBEDTLS_OID_DOMAIN_COMPONENT }, - { ADD_STRLEN( "DC" ), MBEDTLS_OID_DOMAIN_COMPONENT }, - { NULL, 0, NULL } -}; - -static const char *x509_at_oid_from_name( const char *name, size_t name_len ) -{ - const x509_attr_descriptor_t *cur; - - for( cur = x509_attrs; cur->name != NULL; cur++ ) - if( cur->name_len == name_len && - strncmp( cur->name, name, name_len ) == 0 ) - break; - - return( cur->oid ); -} - -int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ) -{ - int ret = 0; - const char *s = name, *c = s; - const char *end = s + strlen( s ); - const char *oid = NULL; - int in_tag = 1; - char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; - char *d = data; - - /* Clear existing chain if present */ - mbedtls_asn1_free_named_data_list( head ); - - while( c <= end ) - { - if( in_tag && *c == '=' ) - { - if( ( oid = x509_at_oid_from_name( s, c - s ) ) == NULL ) - { - ret = MBEDTLS_ERR_X509_UNKNOWN_OID; - goto exit; - } - - s = c + 1; - in_tag = 0; - d = data; - } - - if( !in_tag && *c == '\\' && c != end ) - { - c++; - - /* Check for valid escaped characters */ - if( c == end || *c != ',' ) - { - ret = MBEDTLS_ERR_X509_INVALID_NAME; - goto exit; - } - } - else if( !in_tag && ( *c == ',' || c == end ) ) - { - if( mbedtls_asn1_store_named_data( head, oid, strlen( oid ), - (unsigned char *) data, - d - data ) == NULL ) - { - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - } - - while( c < end && *(c + 1) == ' ' ) - c++; - - s = c + 1; - in_tag = 1; - } - - if( !in_tag && s != c + 1 ) - { - *(d++) = *c; - - if( d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE ) - { - ret = MBEDTLS_ERR_X509_INVALID_NAME; - goto exit; - } - } - - c++; - } - -exit: - - return( ret ); -} - -/* The first byte of the value in the mbedtls_asn1_named_data structure is reserved - * to store the critical boolean for us - */ -int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, - int critical, const unsigned char *val, size_t val_len ) -{ - mbedtls_asn1_named_data *cur; - - if( ( cur = mbedtls_asn1_store_named_data( head, oid, oid_len, - NULL, val_len + 1 ) ) == NULL ) - { - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - } - - cur->val.p[0] = critical; - memcpy( cur->val.p + 1, val, val_len ); - - return( 0 ); -} - -/* - * RelativeDistinguishedName ::= - * SET OF AttributeTypeAndValue - * - * AttributeTypeAndValue ::= SEQUENCE { - * type AttributeType, - * value AttributeValue } - * - * AttributeType ::= OBJECT IDENTIFIER - * - * AttributeValue ::= ANY DEFINED BY AttributeType - */ -static int x509_write_name( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len, - const unsigned char *name, size_t name_len ) -{ - int ret; - size_t len = 0; - - // Write PrintableString for all except MBEDTLS_OID_PKCS9_EMAIL - // - if( MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_EMAIL ) == oid_len && - memcmp( oid, MBEDTLS_OID_PKCS9_EMAIL, oid_len ) == 0 ) - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_ia5_string( p, start, - (const char *) name, - name_len ) ); - } - else - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_printable_string( p, start, - (const char *) name, - name_len ) ); - } - - // Write OID - // - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SET ) ); - - return( (int) len ); -} - -int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, - mbedtls_asn1_named_data *first ) -{ - int ret; - size_t len = 0; - mbedtls_asn1_named_data *cur = first; - - while( cur != NULL ) - { - MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, (char *) cur->oid.p, - cur->oid.len, - cur->val.p, cur->val.len ) ); - cur = cur->next; - } - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - return( (int) len ); -} - -int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, - const char *oid, size_t oid_len, - unsigned char *sig, size_t size ) -{ - int ret; - size_t len = 0; - - if( *p < start || (size_t)( *p - start ) < size ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - len = size; - (*p) -= len; - memcpy( *p, sig, len ); - - if( *p - start < 1 ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - *--(*p) = 0; - len += 1; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); - - // Write OID - // - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( p, start, oid, - oid_len, 0 ) ); - - return( (int) len ); -} - -static int x509_write_extension( unsigned char **p, unsigned char *start, - mbedtls_asn1_named_data *ext ) -{ - int ret; - size_t len = 0; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1, - ext->val.len - 1 ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->val.len - 1 ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); - - if( ext->val.p[0] != 0 ) - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( p, start, 1 ) ); - } - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->oid.p, - ext->oid.len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->oid.len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - return( (int) len ); -} - -/* - * Extension ::= SEQUENCE { - * extnID OBJECT IDENTIFIER, - * critical BOOLEAN DEFAULT FALSE, - * extnValue OCTET STRING - * -- contains the DER encoding of an ASN.1 value - * -- corresponding to the extension type identified - * -- by extnID - * } - */ -int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, - mbedtls_asn1_named_data *first ) -{ - int ret; - size_t len = 0; - mbedtls_asn1_named_data *cur_ext = first; - - while( cur_ext != NULL ) - { - MBEDTLS_ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) ); - cur_ext = cur_ext->next; - } - - return( (int) len ); -} - -#endif /* MBEDTLS_X509_CREATE_C */ diff --git a/components/mbedtls/library/x509_crl.c b/components/mbedtls/library/x509_crl.c deleted file mode 100644 index 55d12acd03..0000000000 --- a/components/mbedtls/library/x509_crl.c +++ /dev/null @@ -1,723 +0,0 @@ -/* - * X.509 Certidicate Revocation List (CRL) parsing - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The ITU-T X.509 standard defines a certificate format for PKI. - * - * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) - * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) - * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) - * - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_X509_CRL_PARSE_C) - -#include "mbedtls/x509_crl.h" -#include "mbedtls/oid.h" - -#include - -#if defined(MBEDTLS_PEM_PARSE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_free free -#define mbedtls_calloc calloc -#define mbedtls_snprintf snprintf -#endif - -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) -#include -#else -#include -#endif - -#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) -#include -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * Version ::= INTEGER { v1(0), v2(1) } - */ -static int x509_crl_get_version( unsigned char **p, - const unsigned char *end, - int *ver ) -{ - int ret; - - if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - { - *ver = 0; - return( 0 ); - } - - return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); - } - - return( 0 ); -} - -/* - * X.509 CRL v2 extensions (no extensions parsed yet.) - */ -static int x509_get_crl_ext( unsigned char **p, - const unsigned char *end, - mbedtls_x509_buf *ext ) -{ - int ret; - size_t len = 0; - - /* Get explicit tag */ - if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( 0 ); - - return( ret ); - } - - while( *p < end ) - { - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - *p += len; - } - - if( *p != end ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * X.509 CRL v2 entry extensions (no extensions parsed yet.) - */ -static int x509_get_crl_entry_ext( unsigned char **p, - const unsigned char *end, - mbedtls_x509_buf *ext ) -{ - int ret; - size_t len = 0; - - /* OPTIONAL */ - if( end <= *p ) - return( 0 ); - - ext->tag = **p; - ext->p = *p; - - /* - * Get CRL-entry extension sequence header - * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2 - */ - if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - { - ext->p = NULL; - return( 0 ); - } - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - } - - end = *p + ext->len; - - if( end != *p + ext->len ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - while( *p < end ) - { - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - *p += len; - } - - if( *p != end ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * X.509 CRL Entries - */ -static int x509_get_entries( unsigned char **p, - const unsigned char *end, - mbedtls_x509_crl_entry *entry ) -{ - int ret; - size_t entry_len; - mbedtls_x509_crl_entry *cur_entry = entry; - - if( *p == end ) - return( 0 ); - - if( ( ret = mbedtls_asn1_get_tag( p, end, &entry_len, - MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( 0 ); - - return( ret ); - } - - end = *p + entry_len; - - while( *p < end ) - { - size_t len2; - const unsigned char *end2; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len2, - MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) - { - return( ret ); - } - - cur_entry->raw.tag = **p; - cur_entry->raw.p = *p; - cur_entry->raw.len = len2; - end2 = *p + len2; - - if( ( ret = mbedtls_x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_x509_get_time( p, end2, - &cur_entry->revocation_date ) ) != 0 ) - return( ret ); - - if( ( ret = x509_get_crl_entry_ext( p, end2, - &cur_entry->entry_ext ) ) != 0 ) - return( ret ); - - if( *p < end ) - { - cur_entry->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl_entry ) ); - - if( cur_entry->next == NULL ) - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - - cur_entry = cur_entry->next; - } - } - - return( 0 ); -} - -/* - * Parse one CRLs in DER format and append it to the chained list - */ -int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, - const unsigned char *buf, size_t buflen ) -{ - int ret; - size_t len; - unsigned char *p, *end; - mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; - mbedtls_x509_crl *crl = chain; - - /* - * Check for valid input - */ - if( crl == NULL || buf == NULL ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); - memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); - memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); - - /* - * Add new CRL on the end of the chain if needed. - */ - while( crl->version != 0 && crl->next != NULL ) - crl = crl->next; - - if( crl->version != 0 && crl->next == NULL ) - { - crl->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl ) ); - - if( crl->next == NULL ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - } - - mbedtls_x509_crl_init( crl->next ); - crl = crl->next; - } - - /* - * Copy raw DER-encoded CRL - */ - if( ( p = mbedtls_calloc( 1, buflen ) ) == NULL ) - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - - memcpy( p, buf, buflen ); - - crl->raw.p = p; - crl->raw.len = buflen; - - end = p + buflen; - - /* - * CertificateList ::= SEQUENCE { - * tbsCertList TBSCertList, - * signatureAlgorithm AlgorithmIdentifier, - * signatureValue BIT STRING } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT ); - } - - if( len != (size_t) ( end - p ) ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - - /* - * TBSCertList ::= SEQUENCE { - */ - crl->tbs.p = p; - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); - } - - end = p + len; - crl->tbs.len = end - crl->tbs.p; - - /* - * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } - * -- if present, MUST be v2 - * - * signature AlgorithmIdentifier - */ - if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 || - ( ret = mbedtls_x509_get_alg( &p, end, &crl->sig_oid, &sig_params1 ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( ret ); - } - - if( crl->version < 0 || crl->version > 1 ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); - } - - crl->version++; - - if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1, - &crl->sig_md, &crl->sig_pk, - &crl->sig_opts ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); - } - - /* - * issuer Name - */ - crl->issuer_raw.p = p; - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); - } - - if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( ret ); - } - - crl->issuer_raw.len = p - crl->issuer_raw.p; - - /* - * thisUpdate Time - * nextUpdate Time OPTIONAL - */ - if( ( ret = mbedtls_x509_get_time( &p, end, &crl->this_update ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( ret ); - } - - if( ( ret = mbedtls_x509_get_time( &p, end, &crl->next_update ) ) != 0 ) - { - if( ret != ( MBEDTLS_ERR_X509_INVALID_DATE + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) && - ret != ( MBEDTLS_ERR_X509_INVALID_DATE + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ) - { - mbedtls_x509_crl_free( crl ); - return( ret ); - } - } - - /* - * revokedCertificates SEQUENCE OF SEQUENCE { - * userCertificate CertificateSerialNumber, - * revocationDate Time, - * crlEntryExtensions Extensions OPTIONAL - * -- if present, MUST be v2 - * } OPTIONAL - */ - if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( ret ); - } - - /* - * crlExtensions EXPLICIT Extensions OPTIONAL - * -- if present, MUST be v2 - */ - if( crl->version == 2 ) - { - ret = x509_get_crl_ext( &p, end, &crl->crl_ext ); - - if( ret != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( ret ); - } - } - - if( p != end ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - - end = crl->raw.p + crl->raw.len; - - /* - * signatureAlgorithm AlgorithmIdentifier, - * signatureValue BIT STRING - */ - if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( ret ); - } - - if( crl->sig_oid.len != sig_oid2.len || - memcmp( crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len ) != 0 || - sig_params1.len != sig_params2.len || - ( sig_params1.len != 0 && - memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_SIG_MISMATCH ); - } - - if( ( ret = mbedtls_x509_get_sig( &p, end, &crl->sig ) ) != 0 ) - { - mbedtls_x509_crl_free( crl ); - return( ret ); - } - - if( p != end ) - { - mbedtls_x509_crl_free( crl ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - - return( 0 ); -} - -/* - * Parse one or more CRLs and add them to the chained list - */ -int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ) -{ -#if defined(MBEDTLS_PEM_PARSE_C) - int ret; - size_t use_len; - mbedtls_pem_context pem; - int is_pem = 0; - - if( chain == NULL || buf == NULL ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - do - { - mbedtls_pem_init( &pem ); - - // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated - // string - if( buflen == 0 || buf[buflen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN X509 CRL-----", - "-----END X509 CRL-----", - buf, NULL, 0, &use_len ); - - if( ret == 0 ) - { - /* - * Was PEM encoded - */ - is_pem = 1; - - buflen -= use_len; - buf += use_len; - - if( ( ret = mbedtls_x509_crl_parse_der( chain, - pem.buf, pem.buflen ) ) != 0 ) - { - mbedtls_pem_free( &pem ); - return( ret ); - } - } - else if( is_pem ) - { - mbedtls_pem_free( &pem ); - return( ret ); - } - - mbedtls_pem_free( &pem ); - } - /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte. - * And a valid CRL cannot be less than 1 byte anyway. */ - while( is_pem && buflen > 1 ); - - if( is_pem ) - return( 0 ); - else -#endif /* MBEDTLS_PEM_PARSE_C */ - return( mbedtls_x509_crl_parse_der( chain, buf, buflen ) ); -} - -#if defined(MBEDTLS_FS_IO) -/* - * Load one or more CRLs and add them to the chained list - */ -int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ) -{ - int ret; - size_t n; - unsigned char *buf; - - if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) - return( ret ); - - ret = mbedtls_x509_crl_parse( chain, buf, n ); - - mbedtls_zeroize( buf, n ); - mbedtls_free( buf ); - - return( ret ); -} -#endif /* MBEDTLS_FS_IO */ - -/* - * Return an informational string about the certificate. - */ -#define BEFORE_COLON 14 -#define BC "14" -/* - * Return an informational string about the CRL. - */ -int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, - const mbedtls_x509_crl *crl ) -{ - int ret; - size_t n; - char *p; - const mbedtls_x509_crl_entry *entry; - - p = buf; - n = size; - - ret = mbedtls_snprintf( p, n, "%sCRL version : %d", - prefix, crl->version ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = mbedtls_x509_dn_gets( p, n, &crl->issuer ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\n%sthis update : " \ - "%04d-%02d-%02d %02d:%02d:%02d", prefix, - crl->this_update.year, crl->this_update.mon, - crl->this_update.day, crl->this_update.hour, - crl->this_update.min, crl->this_update.sec ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\n%snext update : " \ - "%04d-%02d-%02d %02d:%02d:%02d", prefix, - crl->next_update.year, crl->next_update.mon, - crl->next_update.day, crl->next_update.hour, - crl->next_update.min, crl->next_update.sec ); - MBEDTLS_X509_SAFE_SNPRINTF; - - entry = &crl->entry; - - ret = mbedtls_snprintf( p, n, "\n%sRevoked certificates:", - prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - while( entry != NULL && entry->raw.len != 0 ) - { - ret = mbedtls_snprintf( p, n, "\n%sserial number: ", - prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_x509_serial_gets( p, n, &entry->serial ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, " revocation date: " \ - "%04d-%02d-%02d %02d:%02d:%02d", - entry->revocation_date.year, entry->revocation_date.mon, - entry->revocation_date.day, entry->revocation_date.hour, - entry->revocation_date.min, entry->revocation_date.sec ); - MBEDTLS_X509_SAFE_SNPRINTF; - - entry = entry->next; - } - - ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_x509_sig_alg_gets( p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md, - crl->sig_opts ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\n" ); - MBEDTLS_X509_SAFE_SNPRINTF; - - return( (int) ( size - n ) ); -} - -/* - * Initialize a CRL chain - */ -void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ) -{ - memset( crl, 0, sizeof(mbedtls_x509_crl) ); -} - -/* - * Unallocate all CRL data - */ -void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) -{ - mbedtls_x509_crl *crl_cur = crl; - mbedtls_x509_crl *crl_prv; - mbedtls_x509_name *name_cur; - mbedtls_x509_name *name_prv; - mbedtls_x509_crl_entry *entry_cur; - mbedtls_x509_crl_entry *entry_prv; - - if( crl == NULL ) - return; - - do - { -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) - mbedtls_free( crl_cur->sig_opts ); -#endif - - name_cur = crl_cur->issuer.next; - while( name_cur != NULL ) - { - name_prv = name_cur; - name_cur = name_cur->next; - mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); - mbedtls_free( name_prv ); - } - - entry_cur = crl_cur->entry.next; - while( entry_cur != NULL ) - { - entry_prv = entry_cur; - entry_cur = entry_cur->next; - mbedtls_zeroize( entry_prv, sizeof( mbedtls_x509_crl_entry ) ); - mbedtls_free( entry_prv ); - } - - if( crl_cur->raw.p != NULL ) - { - mbedtls_zeroize( crl_cur->raw.p, crl_cur->raw.len ); - mbedtls_free( crl_cur->raw.p ); - } - - crl_cur = crl_cur->next; - } - while( crl_cur != NULL ); - - crl_cur = crl; - do - { - crl_prv = crl_cur; - crl_cur = crl_cur->next; - - mbedtls_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) ); - if( crl_prv != crl ) - mbedtls_free( crl_prv ); - } - while( crl_cur != NULL ); -} - -#endif /* MBEDTLS_X509_CRL_PARSE_C */ diff --git a/components/mbedtls/library/x509_crt.c b/components/mbedtls/library/x509_crt.c deleted file mode 100644 index c6209fb40d..0000000000 --- a/components/mbedtls/library/x509_crt.c +++ /dev/null @@ -1,2425 +0,0 @@ -/* - * X.509 certificate parsing and verification - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The ITU-T X.509 standard defines a certificate format for PKI. - * - * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) - * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) - * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) - * - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_X509_CRT_PARSE_C) - -#include "mbedtls/x509_crt.h" -#include "mbedtls/oid.h" - -#include -#include - -#if defined(MBEDTLS_PEM_PARSE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_free free -#define mbedtls_calloc calloc -#define mbedtls_snprintf snprintf -#endif - -#if defined(MBEDTLS_THREADING_C) -#include "mbedtls/threading.h" -#endif - -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) -#include -#else -#include -#endif - -#if defined(MBEDTLS_FS_IO) -#include -#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) -#include -#include -#include -#endif /* !_WIN32 || EFIX64 || EFI32 */ -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * Default profile - */ -const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = -{ -#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES) - /* Allow SHA-1 (weak, but still safe in controlled environments) */ - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) | -#endif - /* Only SHA-2 hashes */ - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), - 0xFFFFFFF, /* Any PK alg */ - 0xFFFFFFF, /* Any curve */ - 2048, -}; - -/* - * Next-default profile - */ -const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next = -{ - /* Hashes from SHA-256 and above */ - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), - 0xFFFFFFF, /* Any PK alg */ -#if defined(MBEDTLS_ECP_C) - /* Curves at or above 128-bit security level */ - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ), -#else - 0, -#endif - 2048, -}; - -/* - * NSA Suite B Profile - */ -const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = -{ - /* Only SHA-256 and 384 */ - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), - /* Only ECDSA */ - MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ), -#if defined(MBEDTLS_ECP_C) - /* Only NIST P-256 and P-384 */ - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | - MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ), -#else - 0, -#endif - 0, -}; - -/* - * Check md_alg against profile - * Return 0 if md_alg acceptable for this profile, -1 otherwise - */ -static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile, - mbedtls_md_type_t md_alg ) -{ - if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 ) - return( 0 ); - - return( -1 ); -} - -/* - * Check pk_alg against profile - * Return 0 if pk_alg acceptable for this profile, -1 otherwise - */ -static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile, - mbedtls_pk_type_t pk_alg ) -{ - if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 ) - return( 0 ); - - return( -1 ); -} - -/* - * Check key against profile - * Return 0 if pk_alg acceptable for this profile, -1 otherwise - */ -static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, - mbedtls_pk_type_t pk_alg, - const mbedtls_pk_context *pk ) -{ -#if defined(MBEDTLS_RSA_C) - if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS ) - { - if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen ) - return( 0 ); - - return( -1 ); - } -#endif - -#if defined(MBEDTLS_ECP_C) - if( pk_alg == MBEDTLS_PK_ECDSA || - pk_alg == MBEDTLS_PK_ECKEY || - pk_alg == MBEDTLS_PK_ECKEY_DH ) - { - mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id; - - if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 ) - return( 0 ); - - return( -1 ); - } -#endif - - return( -1 ); -} - -/* - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - */ -static int x509_get_version( unsigned char **p, - const unsigned char *end, - int *ver ) -{ - int ret; - size_t len; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - { - *ver = 0; - return( 0 ); - } - - return( ret ); - } - - end = *p + len; - - if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); - - if( *p != end ) - return( MBEDTLS_ERR_X509_INVALID_VERSION + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * Validity ::= SEQUENCE { - * notBefore Time, - * notAfter Time } - */ -static int x509_get_dates( unsigned char **p, - const unsigned char *end, - mbedtls_x509_time *from, - mbedtls_x509_time *to ) -{ - int ret; - size_t len; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); - - end = *p + len; - - if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 ) - return( ret ); - - if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 ) - return( ret ); - - if( *p != end ) - return( MBEDTLS_ERR_X509_INVALID_DATE + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * X.509 v2/v3 unique identifier (not parsed) - */ -static int x509_get_uid( unsigned char **p, - const unsigned char *end, - mbedtls_x509_buf *uid, int n ) -{ - int ret; - - if( *p == end ) - return( 0 ); - - uid->tag = **p; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len, - MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( 0 ); - - return( ret ); - } - - uid->p = *p; - *p += uid->len; - - return( 0 ); -} - -static int x509_get_basic_constraints( unsigned char **p, - const unsigned char *end, - int *ca_istrue, - int *max_pathlen ) -{ - int ret; - size_t len; - - /* - * BasicConstraints ::= SEQUENCE { - * cA BOOLEAN DEFAULT FALSE, - * pathLenConstraint INTEGER (0..MAX) OPTIONAL } - */ - *ca_istrue = 0; /* DEFAULT FALSE */ - *max_pathlen = 0; /* endless */ - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - if( *p == end ) - return( 0 ); - - if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - ret = mbedtls_asn1_get_int( p, end, ca_istrue ); - - if( ret != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - if( *ca_istrue != 0 ) - *ca_istrue = 1; - } - - if( *p == end ) - return( 0 ); - - if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - if( *p != end ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - (*max_pathlen)++; - - return( 0 ); -} - -static int x509_get_ns_cert_type( unsigned char **p, - const unsigned char *end, - unsigned char *ns_cert_type) -{ - int ret; - mbedtls_x509_bitstring bs = { 0, 0, NULL }; - - if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - if( bs.len != 1 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_INVALID_LENGTH ); - - /* Get actual bitstring */ - *ns_cert_type = *bs.p; - return( 0 ); -} - -static int x509_get_key_usage( unsigned char **p, - const unsigned char *end, - unsigned int *key_usage) -{ - int ret; - size_t i; - mbedtls_x509_bitstring bs = { 0, 0, NULL }; - - if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - if( bs.len < 1 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_INVALID_LENGTH ); - - /* Get actual bitstring */ - *key_usage = 0; - for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ ) - { - *key_usage |= (unsigned int) bs.p[i] << (8*i); - } - - return( 0 ); -} - -/* - * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId - * - * KeyPurposeId ::= OBJECT IDENTIFIER - */ -static int x509_get_ext_key_usage( unsigned char **p, - const unsigned char *end, - mbedtls_x509_sequence *ext_key_usage) -{ - int ret; - - if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - /* Sequence length must be >= 1 */ - if( ext_key_usage->buf.p == NULL ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_INVALID_LENGTH ); - - return( 0 ); -} - -/* - * SubjectAltName ::= GeneralNames - * - * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName - * - * GeneralName ::= CHOICE { - * otherName [0] OtherName, - * rfc822Name [1] IA5String, - * dNSName [2] IA5String, - * x400Address [3] ORAddress, - * directoryName [4] Name, - * ediPartyName [5] EDIPartyName, - * uniformResourceIdentifier [6] IA5String, - * iPAddress [7] OCTET STRING, - * registeredID [8] OBJECT IDENTIFIER } - * - * OtherName ::= SEQUENCE { - * type-id OBJECT IDENTIFIER, - * value [0] EXPLICIT ANY DEFINED BY type-id } - * - * EDIPartyName ::= SEQUENCE { - * nameAssigner [0] DirectoryString OPTIONAL, - * partyName [1] DirectoryString } - * - * NOTE: we only parse and use dNSName at this point. - */ -static int x509_get_subject_alt_name( unsigned char **p, - const unsigned char *end, - mbedtls_x509_sequence *subject_alt_name ) -{ - int ret; - size_t len, tag_len; - mbedtls_asn1_buf *buf; - unsigned char tag; - mbedtls_asn1_sequence *cur = subject_alt_name; - - /* Get main sequence tag */ - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - if( *p + len != end ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - while( *p < end ) - { - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - tag = **p; - (*p)++; - if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - if( ( tag & MBEDTLS_ASN1_CONTEXT_SPECIFIC ) != MBEDTLS_ASN1_CONTEXT_SPECIFIC ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - - /* Skip everything but DNS name */ - if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) ) - { - *p += tag_len; - continue; - } - - /* Allocate and assign next pointer */ - if( cur->buf.p != NULL ) - { - if( cur->next != NULL ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); - - cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); - - if( cur->next == NULL ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_ALLOC_FAILED ); - - cur = cur->next; - } - - buf = &(cur->buf); - buf->tag = tag; - buf->p = *p; - buf->len = tag_len; - *p += buf->len; - } - - /* Set final sequence entry's next pointer to NULL */ - cur->next = NULL; - - if( *p != end ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * X.509 v3 extensions - * - */ -static int x509_get_crt_ext( unsigned char **p, - const unsigned char *end, - mbedtls_x509_crt *crt ) -{ - int ret; - size_t len; - unsigned char *end_ext_data, *end_ext_octet; - - if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - return( 0 ); - - return( ret ); - } - - while( *p < end ) - { - /* - * Extension ::= SEQUENCE { - * extnID OBJECT IDENTIFIER, - * critical BOOLEAN DEFAULT FALSE, - * extnValue OCTET STRING } - */ - mbedtls_x509_buf extn_oid = {0, 0, NULL}; - int is_critical = 0; /* DEFAULT FALSE */ - int ext_type = 0; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - end_ext_data = *p + len; - - /* Get extension ID */ - extn_oid.tag = **p; - - if( ( ret = mbedtls_asn1_get_tag( p, end, &extn_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - extn_oid.p = *p; - *p += extn_oid.len; - - if( ( end - *p ) < 1 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_OUT_OF_DATA ); - - /* Get optional critical */ - if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 && - ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - /* Data should be octet string type */ - if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, - MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); - - end_ext_octet = *p + len; - - if( end_ext_octet != end_ext_data ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - /* - * Detect supported extensions - */ - ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type ); - - if( ret != 0 ) - { - /* No parser found, skip extension */ - *p = end_ext_octet; - -#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) - if( is_critical ) - { - /* Data is marked as critical: fail */ - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); - } -#endif - continue; - } - - /* Forbid repeated extensions */ - if( ( crt->ext_types & ext_type ) != 0 ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); - - crt->ext_types |= ext_type; - - switch( ext_type ) - { - case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS: - /* Parse basic constraints */ - if( ( ret = x509_get_basic_constraints( p, end_ext_octet, - &crt->ca_istrue, &crt->max_pathlen ) ) != 0 ) - return( ret ); - break; - - case MBEDTLS_X509_EXT_KEY_USAGE: - /* Parse key usage */ - if( ( ret = x509_get_key_usage( p, end_ext_octet, - &crt->key_usage ) ) != 0 ) - return( ret ); - break; - - case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE: - /* Parse extended key usage */ - if( ( ret = x509_get_ext_key_usage( p, end_ext_octet, - &crt->ext_key_usage ) ) != 0 ) - return( ret ); - break; - - case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: - /* Parse subject alt name */ - if( ( ret = x509_get_subject_alt_name( p, end_ext_octet, - &crt->subject_alt_names ) ) != 0 ) - return( ret ); - break; - - case MBEDTLS_X509_EXT_NS_CERT_TYPE: - /* Parse netscape certificate type */ - if( ( ret = x509_get_ns_cert_type( p, end_ext_octet, - &crt->ns_cert_type ) ) != 0 ) - return( ret ); - break; - - default: - return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); - } - } - - if( *p != end ) - return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - - return( 0 ); -} - -/* - * Parse and fill a single X.509 certificate in DER format - */ -static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char *buf, - size_t buflen ) -{ - int ret; - size_t len; - unsigned char *p, *end, *crt_end; - mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; - - memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); - memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); - memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); - - /* - * Check for valid input - */ - if( crt == NULL || buf == NULL ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - // Use the original buffer until we figure out actual length - p = (unsigned char*) buf; - len = buflen; - end = p + len; - - /* - * Certificate ::= SEQUENCE { - * tbsCertificate TBSCertificate, - * signatureAlgorithm AlgorithmIdentifier, - * signatureValue BIT STRING } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT ); - } - - if( len > (size_t) ( end - p ) ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - crt_end = p + len; - - // Create and populate a new buffer for the raw field - crt->raw.len = crt_end - buf; - crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len ); - if( p == NULL ) - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - - memcpy( p, buf, crt->raw.len ); - - // Direct pointers to the new buffer - p += crt->raw.len - len; - end = crt_end = p + len; - - /* - * TBSCertificate ::= SEQUENCE { - */ - crt->tbs.p = p; - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); - } - - end = p + len; - crt->tbs.len = end - crt->tbs.p; - - /* - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - * - * CertificateSerialNumber ::= INTEGER - * - * signature AlgorithmIdentifier - */ - if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 || - ( ret = mbedtls_x509_get_serial( &p, end, &crt->serial ) ) != 0 || - ( ret = mbedtls_x509_get_alg( &p, end, &crt->sig_oid, - &sig_params1 ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - - if( crt->version < 0 || crt->version > 2 ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); - } - - crt->version++; - - if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1, - &crt->sig_md, &crt->sig_pk, - &crt->sig_opts ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - - /* - * issuer Name - */ - crt->issuer_raw.p = p; - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); - } - - if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - - crt->issuer_raw.len = p - crt->issuer_raw.p; - - /* - * Validity ::= SEQUENCE { - * notBefore Time, - * notAfter Time } - * - */ - if( ( ret = x509_get_dates( &p, end, &crt->valid_from, - &crt->valid_to ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - - /* - * subject Name - */ - crt->subject_raw.p = p; - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); - } - - if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - - crt->subject_raw.len = p - crt->subject_raw.p; - - /* - * SubjectPublicKeyInfo - */ - if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - - /* - * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, - * -- If present, version shall be v2 or v3 - * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, - * -- If present, version shall be v2 or v3 - * extensions [3] EXPLICIT Extensions OPTIONAL - * -- If present, version shall be v3 - */ - if( crt->version == 2 || crt->version == 3 ) - { - ret = x509_get_uid( &p, end, &crt->issuer_id, 1 ); - if( ret != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - } - - if( crt->version == 2 || crt->version == 3 ) - { - ret = x509_get_uid( &p, end, &crt->subject_id, 2 ); - if( ret != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - } - -#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) - if( crt->version == 3 ) -#endif - { - ret = x509_get_crt_ext( &p, end, crt ); - if( ret != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - } - - if( p != end ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - - end = crt_end; - - /* - * } - * -- end of TBSCertificate - * - * signatureAlgorithm AlgorithmIdentifier, - * signatureValue BIT STRING - */ - if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - - if( crt->sig_oid.len != sig_oid2.len || - memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 || - sig_params1.len != sig_params2.len || - ( sig_params1.len != 0 && - memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_SIG_MISMATCH ); - } - - if( ( ret = mbedtls_x509_get_sig( &p, end, &crt->sig ) ) != 0 ) - { - mbedtls_x509_crt_free( crt ); - return( ret ); - } - - if( p != end ) - { - mbedtls_x509_crt_free( crt ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - - return( 0 ); -} - -/* - * Parse one X.509 certificate in DER format from a buffer and add them to a - * chained list - */ -int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf, - size_t buflen ) -{ - int ret; - mbedtls_x509_crt *crt = chain, *prev = NULL; - - /* - * Check for valid input - */ - if( crt == NULL || buf == NULL ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - while( crt->version != 0 && crt->next != NULL ) - { - prev = crt; - crt = crt->next; - } - - /* - * Add new certificate on the end of the chain if needed. - */ - if( crt->version != 0 && crt->next == NULL ) - { - crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); - - if( crt->next == NULL ) - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - - prev = crt; - mbedtls_x509_crt_init( crt->next ); - crt = crt->next; - } - - if( ( ret = x509_crt_parse_der_core( crt, buf, buflen ) ) != 0 ) - { - if( prev ) - prev->next = NULL; - - if( crt != chain ) - mbedtls_free( crt ); - - return( ret ); - } - - return( 0 ); -} - -/* - * Parse one or more PEM certificates from a buffer and add them to the chained - * list - */ -int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ) -{ -#if defined(MBEDTLS_PEM_PARSE_C) - int success = 0, first_error = 0, total_failed = 0; - int buf_format = MBEDTLS_X509_FORMAT_DER; -#endif - - /* - * Check for valid input - */ - if( chain == NULL || buf == NULL ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - /* - * Determine buffer content. Buffer contains either one DER certificate or - * one or more PEM certificates. - */ -#if defined(MBEDTLS_PEM_PARSE_C) - if( buflen != 0 && buf[buflen - 1] == '\0' && - strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL ) - { - buf_format = MBEDTLS_X509_FORMAT_PEM; - } - - if( buf_format == MBEDTLS_X509_FORMAT_DER ) - return mbedtls_x509_crt_parse_der( chain, buf, buflen ); -#else - return mbedtls_x509_crt_parse_der( chain, buf, buflen ); -#endif - -#if defined(MBEDTLS_PEM_PARSE_C) - if( buf_format == MBEDTLS_X509_FORMAT_PEM ) - { - int ret; - mbedtls_pem_context pem; - - /* 1 rather than 0 since the terminating NULL byte is counted in */ - while( buflen > 1 ) - { - size_t use_len; - mbedtls_pem_init( &pem ); - - /* If we get there, we know the string is null-terminated */ - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN CERTIFICATE-----", - "-----END CERTIFICATE-----", - buf, NULL, 0, &use_len ); - - if( ret == 0 ) - { - /* - * Was PEM encoded - */ - buflen -= use_len; - buf += use_len; - } - else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA ) - { - return( ret ); - } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - { - mbedtls_pem_free( &pem ); - - /* - * PEM header and footer were found - */ - buflen -= use_len; - buf += use_len; - - if( first_error == 0 ) - first_error = ret; - - total_failed++; - continue; - } - else - break; - - ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen ); - - mbedtls_pem_free( &pem ); - - if( ret != 0 ) - { - /* - * Quit parsing on a memory error - */ - if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED ) - return( ret ); - - if( first_error == 0 ) - first_error = ret; - - total_failed++; - continue; - } - - success = 1; - } - } - - if( success ) - return( total_failed ); - else if( first_error ) - return( first_error ); - else - return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT ); -#endif /* MBEDTLS_PEM_PARSE_C */ -} - -#if defined(MBEDTLS_FS_IO) -/* - * Load one or more certificates and add them to the chained list - */ -int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ) -{ - int ret; - size_t n; - unsigned char *buf; - - if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) - return( ret ); - - ret = mbedtls_x509_crt_parse( chain, buf, n ); - - mbedtls_zeroize( buf, n ); - mbedtls_free( buf ); - - return( ret ); -} - -int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) -{ - int ret = 0; -#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) - int w_ret; - WCHAR szDir[MAX_PATH]; - char filename[MAX_PATH]; - char *p; - size_t len = strlen( path ); - - WIN32_FIND_DATAW file_data; - HANDLE hFind; - - if( len > MAX_PATH - 3 ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - memset( szDir, 0, sizeof(szDir) ); - memset( filename, 0, MAX_PATH ); - memcpy( filename, path, len ); - filename[len++] = '\\'; - p = filename + len; - filename[len++] = '*'; - - w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir, - MAX_PATH - 3 ); - if( w_ret == 0 ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - hFind = FindFirstFileW( szDir, &file_data ); - if( hFind == INVALID_HANDLE_VALUE ) - return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); - - len = MAX_PATH - len; - do - { - memset( p, 0, len ); - - if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) - continue; - - w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, - lstrlenW( file_data.cFileName ), - p, (int) len - 1, - NULL, NULL ); - if( w_ret == 0 ) - { - ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; - goto cleanup; - } - - w_ret = mbedtls_x509_crt_parse_file( chain, filename ); - if( w_ret < 0 ) - ret++; - else - ret += w_ret; - } - while( FindNextFileW( hFind, &file_data ) != 0 ); - - if( GetLastError() != ERROR_NO_MORE_FILES ) - ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; - -cleanup: - FindClose( hFind ); -#else /* _WIN32 */ - int t_ret; - int snp_ret; - struct stat sb; - struct dirent *entry; - char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN]; - DIR *dir = opendir( path ); - - if( dir == NULL ) - return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); - -#if defined(MBEDTLS_THREADING_C) - if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 ) - { - closedir( dir ); - return( ret ); - } -#endif /* MBEDTLS_THREADING_C */ - - while( ( entry = readdir( dir ) ) != NULL ) - { - snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name, - "%s/%s", path, entry->d_name ); - - if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name ) - { - ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; - goto cleanup; - } - else if( stat( entry_name, &sb ) == -1 ) - { - ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; - goto cleanup; - } - - if( !S_ISREG( sb.st_mode ) ) - continue; - - // Ignore parse errors - // - t_ret = mbedtls_x509_crt_parse_file( chain, entry_name ); - if( t_ret < 0 ) - ret++; - else - ret += t_ret; - } - -cleanup: - closedir( dir ); - -#if defined(MBEDTLS_THREADING_C) - if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 ) - ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; -#endif /* MBEDTLS_THREADING_C */ - -#endif /* _WIN32 */ - - return( ret ); -} -#endif /* MBEDTLS_FS_IO */ - -static int x509_info_subject_alt_name( char **buf, size_t *size, - const mbedtls_x509_sequence *subject_alt_name ) -{ - size_t i; - size_t n = *size; - char *p = *buf; - const mbedtls_x509_sequence *cur = subject_alt_name; - const char *sep = ""; - size_t sep_len = 0; - - while( cur != NULL ) - { - if( cur->buf.len + sep_len >= n ) - { - *p = '\0'; - return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); - } - - n -= cur->buf.len + sep_len; - for( i = 0; i < sep_len; i++ ) - *p++ = sep[i]; - for( i = 0; i < cur->buf.len; i++ ) - *p++ = cur->buf.p[i]; - - sep = ", "; - sep_len = 2; - - cur = cur->next; - } - - *p = '\0'; - - *size = n; - *buf = p; - - return( 0 ); -} - -#define PRINT_ITEM(i) \ - { \ - ret = mbedtls_snprintf( p, n, "%s" i, sep ); \ - MBEDTLS_X509_SAFE_SNPRINTF; \ - sep = ", "; \ - } - -#define CERT_TYPE(type,name) \ - if( ns_cert_type & type ) \ - PRINT_ITEM( name ); - -static int x509_info_cert_type( char **buf, size_t *size, - unsigned char ns_cert_type ) -{ - int ret; - size_t n = *size; - char *p = *buf; - const char *sep = ""; - - CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" ); - CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" ); - CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" ); - CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" ); - CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" ); - CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" ); - CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" ); - CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" ); - - *size = n; - *buf = p; - - return( 0 ); -} - -#define KEY_USAGE(code,name) \ - if( key_usage & code ) \ - PRINT_ITEM( name ); - -static int x509_info_key_usage( char **buf, size_t *size, - unsigned int key_usage ) -{ - int ret; - size_t n = *size; - char *p = *buf; - const char *sep = ""; - - KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" ); - KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" ); - KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" ); - KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" ); - KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" ); - KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" ); - KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" ); - KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" ); - KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" ); - - *size = n; - *buf = p; - - return( 0 ); -} - -static int x509_info_ext_key_usage( char **buf, size_t *size, - const mbedtls_x509_sequence *extended_key_usage ) -{ - int ret; - const char *desc; - size_t n = *size; - char *p = *buf; - const mbedtls_x509_sequence *cur = extended_key_usage; - const char *sep = ""; - - while( cur != NULL ) - { - if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 ) - desc = "???"; - - ret = mbedtls_snprintf( p, n, "%s%s", sep, desc ); - MBEDTLS_X509_SAFE_SNPRINTF; - - sep = ", "; - - cur = cur->next; - } - - *size = n; - *buf = p; - - return( 0 ); -} - -/* - * Return an informational string about the certificate. - */ -#define BEFORE_COLON 18 -#define BC "18" -int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, - const mbedtls_x509_crt *crt ) -{ - int ret; - size_t n; - char *p; - char key_size_str[BEFORE_COLON]; - - p = buf; - n = size; - - if( NULL == crt ) - { - ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" ); - MBEDTLS_X509_SAFE_SNPRINTF; - - return( (int) ( size - n ) ); - } - - ret = mbedtls_snprintf( p, n, "%scert. version : %d\n", - prefix, crt->version ); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = mbedtls_snprintf( p, n, "%sserial number : ", - prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_x509_serial_gets( p, n, &crt->serial ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = mbedtls_x509_dn_gets( p, n, &crt->issuer ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = mbedtls_x509_dn_gets( p, n, &crt->subject ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\n%sissued on : " \ - "%04d-%02d-%02d %02d:%02d:%02d", prefix, - crt->valid_from.year, crt->valid_from.mon, - crt->valid_from.day, crt->valid_from.hour, - crt->valid_from.min, crt->valid_from.sec ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\n%sexpires on : " \ - "%04d-%02d-%02d %02d:%02d:%02d", prefix, - crt->valid_to.year, crt->valid_to.mon, - crt->valid_to.day, crt->valid_to.hour, - crt->valid_to.min, crt->valid_to.sec ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_x509_sig_alg_gets( p, n, &crt->sig_oid, crt->sig_pk, - crt->sig_md, crt->sig_opts ); - MBEDTLS_X509_SAFE_SNPRINTF; - - /* Key size */ - if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, - mbedtls_pk_get_name( &crt->pk ) ) ) != 0 ) - { - return( ret ); - } - - ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str, - (int) mbedtls_pk_get_bitlen( &crt->pk ) ); - MBEDTLS_X509_SAFE_SNPRINTF; - - /* - * Optional extensions - */ - - if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS ) - { - ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix, - crt->ca_istrue ? "true" : "false" ); - MBEDTLS_X509_SAFE_SNPRINTF; - - if( crt->max_pathlen > 0 ) - { - ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 ); - MBEDTLS_X509_SAFE_SNPRINTF; - } - } - - if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) - { - ret = mbedtls_snprintf( p, n, "\n%ssubject alt name : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - if( ( ret = x509_info_subject_alt_name( &p, &n, - &crt->subject_alt_names ) ) != 0 ) - return( ret ); - } - - if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE ) - { - ret = mbedtls_snprintf( p, n, "\n%scert. type : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 ) - return( ret ); - } - - if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) - { - ret = mbedtls_snprintf( p, n, "\n%skey usage : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 ) - return( ret ); - } - - if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) - { - ret = mbedtls_snprintf( p, n, "\n%sext key usage : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - if( ( ret = x509_info_ext_key_usage( &p, &n, - &crt->ext_key_usage ) ) != 0 ) - return( ret ); - } - - ret = mbedtls_snprintf( p, n, "\n" ); - MBEDTLS_X509_SAFE_SNPRINTF; - - return( (int) ( size - n ) ); -} - -struct x509_crt_verify_string { - int code; - const char *string; -}; - -static const struct x509_crt_verify_string x509_crt_verify_strings[] = { - { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" }, - { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" }, - { MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" }, - { MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" }, - { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" }, - { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" }, - { MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" }, - { MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" }, - { MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" }, - { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" }, - { MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" }, - { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" }, - { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" }, - { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" }, - { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." }, - { MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, - { MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." }, - { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." }, - { MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, - { MBEDTLS_X509_BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." }, - { 0, NULL } -}; - -int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, - uint32_t flags ) -{ - int ret; - const struct x509_crt_verify_string *cur; - char *p = buf; - size_t n = size; - - for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ ) - { - if( ( flags & cur->code ) == 0 ) - continue; - - ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string ); - MBEDTLS_X509_SAFE_SNPRINTF; - flags ^= cur->code; - } - - if( flags != 0 ) - { - ret = mbedtls_snprintf( p, n, "%sUnknown reason " - "(this should not happen)\n", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - } - - return( (int) ( size - n ) ); -} - -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) -int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, - unsigned int usage ) -{ - unsigned int usage_must, usage_may; - unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY - | MBEDTLS_X509_KU_DECIPHER_ONLY; - - if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 ) - return( 0 ); - - usage_must = usage & ~may_mask; - - if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - usage_may = usage & may_mask; - - if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - return( 0 ); -} -#endif - -#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) -int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, - const char *usage_oid, - size_t usage_len ) -{ - const mbedtls_x509_sequence *cur; - - /* Extension is not mandatory, absent means no restriction */ - if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 ) - return( 0 ); - - /* - * Look for the requested usage (or wildcard ANY) in our list - */ - for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next ) - { - const mbedtls_x509_buf *cur_oid = &cur->buf; - - if( cur_oid->len == usage_len && - memcmp( cur_oid->p, usage_oid, usage_len ) == 0 ) - { - return( 0 ); - } - - if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 ) - return( 0 ); - } - - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); -} -#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ - -#if defined(MBEDTLS_X509_CRL_PARSE_C) -/* - * Return 1 if the certificate is revoked, or 0 otherwise. - */ -int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ) -{ - const mbedtls_x509_crl_entry *cur = &crl->entry; - - while( cur != NULL && cur->serial.len != 0 ) - { - if( crt->serial.len == cur->serial.len && - memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 ) - { - if( mbedtls_x509_time_is_past( &cur->revocation_date ) ) - return( 1 ); - } - - cur = cur->next; - } - - return( 0 ); -} - -/* - * Check that the given certificate is not revoked according to the CRL. - * Skip validation is no CRL for the given CA is present. - */ -static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, - mbedtls_x509_crl *crl_list, - const mbedtls_x509_crt_profile *profile ) -{ - int flags = 0; - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; - const mbedtls_md_info_t *md_info; - - if( ca == NULL ) - return( flags ); - - while( crl_list != NULL ) - { - if( crl_list->version == 0 || - crl_list->issuer_raw.len != ca->subject_raw.len || - memcmp( crl_list->issuer_raw.p, ca->subject_raw.p, - crl_list->issuer_raw.len ) != 0 ) - { - crl_list = crl_list->next; - continue; - } - - /* - * Check if the CA is configured to sign CRLs - */ -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) - if( mbedtls_x509_crt_check_key_usage( ca, MBEDTLS_X509_KU_CRL_SIGN ) != 0 ) - { - flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; - break; - } -#endif - - /* - * Check if CRL is correctly signed by the trusted CA - */ - if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 ) - flags |= MBEDTLS_X509_BADCRL_BAD_MD; - - if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 ) - flags |= MBEDTLS_X509_BADCRL_BAD_PK; - - md_info = mbedtls_md_info_from_type( crl_list->sig_md ); - if( md_info == NULL ) - { - /* - * Cannot check 'unknown' hash - */ - flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; - break; - } - - mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ); - - if( x509_profile_check_key( profile, crl_list->sig_pk, &ca->pk ) != 0 ) - flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - - if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk, - crl_list->sig_md, hash, mbedtls_md_get_size( md_info ), - crl_list->sig.p, crl_list->sig.len ) != 0 ) - { - flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; - break; - } - - /* - * Check for validity of CRL (Do not drop out) - */ - if( mbedtls_x509_time_is_past( &crl_list->next_update ) ) - flags |= MBEDTLS_X509_BADCRL_EXPIRED; - - if( mbedtls_x509_time_is_future( &crl_list->this_update ) ) - flags |= MBEDTLS_X509_BADCRL_FUTURE; - - /* - * Check if certificate is revoked - */ - if( mbedtls_x509_crt_is_revoked( crt, crl_list ) ) - { - flags |= MBEDTLS_X509_BADCERT_REVOKED; - break; - } - - crl_list = crl_list->next; - } - - return( flags ); -} -#endif /* MBEDTLS_X509_CRL_PARSE_C */ - -/* - * Like memcmp, but case-insensitive and always returns -1 if different - */ -static int x509_memcasecmp( const void *s1, const void *s2, size_t len ) -{ - size_t i; - unsigned char diff; - const unsigned char *n1 = s1, *n2 = s2; - - for( i = 0; i < len; i++ ) - { - diff = n1[i] ^ n2[i]; - - if( diff == 0 ) - continue; - - if( diff == 32 && - ( ( n1[i] >= 'a' && n1[i] <= 'z' ) || - ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) - { - continue; - } - - return( -1 ); - } - - return( 0 ); -} - -/* - * Return 0 if name matches wildcard, -1 otherwise - */ -static int x509_check_wildcard( const char *cn, mbedtls_x509_buf *name ) -{ - size_t i; - size_t cn_idx = 0, cn_len = strlen( cn ); - - if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) - return( 0 ); - - for( i = 0; i < cn_len; ++i ) - { - if( cn[i] == '.' ) - { - cn_idx = i; - break; - } - } - - if( cn_idx == 0 ) - return( -1 ); - - if( cn_len - cn_idx == name->len - 1 && - x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) - { - return( 0 ); - } - - return( -1 ); -} - -/* - * Compare two X.509 strings, case-insensitive, and allowing for some encoding - * variations (but not all). - * - * Return 0 if equal, -1 otherwise. - */ -static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b ) -{ - if( a->tag == b->tag && - a->len == b->len && - memcmp( a->p, b->p, b->len ) == 0 ) - { - return( 0 ); - } - - if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && - ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && - a->len == b->len && - x509_memcasecmp( a->p, b->p, b->len ) == 0 ) - { - return( 0 ); - } - - return( -1 ); -} - -/* - * Compare two X.509 Names (aka rdnSequence). - * - * See RFC 5280 section 7.1, though we don't implement the whole algorithm: - * we sometimes return unequal when the full algorithm would return equal, - * but never the other way. (In particular, we don't do Unicode normalisation - * or space folding.) - * - * Return 0 if equal, -1 otherwise. - */ -static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b ) -{ - /* Avoid recursion, it might not be optimised by the compiler */ - while( a != NULL || b != NULL ) - { - if( a == NULL || b == NULL ) - return( -1 ); - - /* type */ - if( a->oid.tag != b->oid.tag || - a->oid.len != b->oid.len || - memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 ) - { - return( -1 ); - } - - /* value */ - if( x509_string_cmp( &a->val, &b->val ) != 0 ) - return( -1 ); - - /* structure of the list of sets */ - if( a->next_merged != b->next_merged ) - return( -1 ); - - a = a->next; - b = b->next; - } - - /* a == NULL == b */ - return( 0 ); -} - -/* - * Check if 'parent' is a suitable parent (signing CA) for 'child'. - * Return 0 if yes, -1 if not. - * - * top means parent is a locally-trusted certificate - * bottom means child is the end entity cert - */ -static int x509_crt_check_parent( const mbedtls_x509_crt *child, - const mbedtls_x509_crt *parent, - int top, int bottom ) -{ - int need_ca_bit; - - /* Parent must be the issuer */ - if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 ) - return( -1 ); - - /* Parent must have the basicConstraints CA bit set as a general rule */ - need_ca_bit = 1; - - /* Exception: v1/v2 certificates that are locally trusted. */ - if( top && parent->version < 3 ) - need_ca_bit = 0; - - /* Exception: self-signed end-entity certs that are locally trusted. */ - if( top && bottom && - child->raw.len == parent->raw.len && - memcmp( child->raw.p, parent->raw.p, child->raw.len ) == 0 ) - { - need_ca_bit = 0; - } - - if( need_ca_bit && ! parent->ca_istrue ) - return( -1 ); - -#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) - if( need_ca_bit && - mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 ) - { - return( -1 ); - } -#endif - - return( 0 ); -} - -static int x509_crt_verify_top( - mbedtls_x509_crt *child, mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const mbedtls_x509_crt_profile *profile, - int path_cnt, int self_cnt, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ) -{ - int ret; - uint32_t ca_flags = 0; - int check_path_cnt; - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; - const mbedtls_md_info_t *md_info; - mbedtls_x509_crt *future_past_ca = NULL; - - if( mbedtls_x509_time_is_past( &child->valid_to ) ) - *flags |= MBEDTLS_X509_BADCERT_EXPIRED; - - if( mbedtls_x509_time_is_future( &child->valid_from ) ) - *flags |= MBEDTLS_X509_BADCERT_FUTURE; - - if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_MD; - - if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_PK; - - /* - * Child is the top of the chain. Check against the trust_ca list. - */ - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; - - md_info = mbedtls_md_info_from_type( child->sig_md ); - if( md_info == NULL ) - { - /* - * Cannot check 'unknown', no need to try any CA - */ - trust_ca = NULL; - } - else - mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); - - for( /* trust_ca */ ; trust_ca != NULL; trust_ca = trust_ca->next ) - { - if( x509_crt_check_parent( child, trust_ca, 1, path_cnt == 0 ) != 0 ) - continue; - - check_path_cnt = path_cnt + 1; - - /* - * Reduce check_path_cnt to check against if top of the chain is - * the same as the trusted CA - */ - if( child->subject_raw.len == trust_ca->subject_raw.len && - memcmp( child->subject_raw.p, trust_ca->subject_raw.p, - child->issuer_raw.len ) == 0 ) - { - check_path_cnt--; - } - - /* Self signed certificates do not count towards the limit */ - if( trust_ca->max_pathlen > 0 && - trust_ca->max_pathlen < check_path_cnt - self_cnt ) - { - continue; - } - - if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &trust_ca->pk, - child->sig_md, hash, mbedtls_md_get_size( md_info ), - child->sig.p, child->sig.len ) != 0 ) - { - continue; - } - - if( mbedtls_x509_time_is_past( &trust_ca->valid_to ) || - mbedtls_x509_time_is_future( &trust_ca->valid_from ) ) - { - if ( future_past_ca == NULL ) - future_past_ca = trust_ca; - - continue; - } - - break; - } - - if( trust_ca != NULL || ( trust_ca = future_past_ca ) != NULL ) - { - /* - * Top of chain is signed by a trusted CA - */ - *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED; - - if( x509_profile_check_key( profile, child->sig_pk, &trust_ca->pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - } - - /* - * If top of chain is not the same as the trusted CA send a verify request - * to the callback for any issues with validity and CRL presence for the - * trusted CA certificate. - */ - if( trust_ca != NULL && - ( child->subject_raw.len != trust_ca->subject_raw.len || - memcmp( child->subject_raw.p, trust_ca->subject_raw.p, - child->issuer_raw.len ) != 0 ) ) - { -#if defined(MBEDTLS_X509_CRL_PARSE_C) - /* Check trusted CA's CRL for the chain's top crt */ - *flags |= x509_crt_verifycrl( child, trust_ca, ca_crl, profile ); -#else - ((void) ca_crl); -#endif - - if( mbedtls_x509_time_is_past( &trust_ca->valid_to ) ) - ca_flags |= MBEDTLS_X509_BADCERT_EXPIRED; - - if( mbedtls_x509_time_is_future( &trust_ca->valid_from ) ) - ca_flags |= MBEDTLS_X509_BADCERT_FUTURE; - - if( NULL != f_vrfy ) - { - if( ( ret = f_vrfy( p_vrfy, trust_ca, path_cnt + 1, - &ca_flags ) ) != 0 ) - { - return( ret ); - } - } - } - - /* Call callback on top cert */ - if( NULL != f_vrfy ) - { - if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) - return( ret ); - } - - *flags |= ca_flags; - - return( 0 ); -} - -static int x509_crt_verify_child( - mbedtls_x509_crt *child, mbedtls_x509_crt *parent, - mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, - const mbedtls_x509_crt_profile *profile, - int path_cnt, int self_cnt, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ) -{ - int ret; - uint32_t parent_flags = 0; - unsigned char hash[MBEDTLS_MD_MAX_SIZE]; - mbedtls_x509_crt *grandparent; - const mbedtls_md_info_t *md_info; - - /* Counting intermediate self signed certificates */ - if( ( path_cnt != 0 ) && x509_name_cmp( &child->issuer, &child->subject ) == 0 ) - self_cnt++; - - /* path_cnt is 0 for the first intermediate CA */ - if( 1 + path_cnt > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) - { - /* return immediately as the goal is to avoid unbounded recursion */ - return( MBEDTLS_ERR_X509_FATAL_ERROR ); - } - - if( mbedtls_x509_time_is_past( &child->valid_to ) ) - *flags |= MBEDTLS_X509_BADCERT_EXPIRED; - - if( mbedtls_x509_time_is_future( &child->valid_from ) ) - *flags |= MBEDTLS_X509_BADCERT_FUTURE; - - if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_MD; - - if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_PK; - - md_info = mbedtls_md_info_from_type( child->sig_md ); - if( md_info == NULL ) - { - /* - * Cannot check 'unknown' hash - */ - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; - } - else - { - mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ); - - if( x509_profile_check_key( profile, child->sig_pk, &parent->pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - - if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, - child->sig_md, hash, mbedtls_md_get_size( md_info ), - child->sig.p, child->sig.len ) != 0 ) - { - *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; - } - } - -#if defined(MBEDTLS_X509_CRL_PARSE_C) - /* Check trusted CA's CRL for the given crt */ - *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile ); -#endif - - /* Look for a grandparent in trusted CAs */ - for( grandparent = trust_ca; - grandparent != NULL; - grandparent = grandparent->next ) - { - if( x509_crt_check_parent( parent, grandparent, - 0, path_cnt == 0 ) == 0 ) - break; - } - - if( grandparent != NULL ) - { - ret = x509_crt_verify_top( parent, grandparent, ca_crl, profile, - path_cnt + 1, self_cnt, &parent_flags, f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); - } - else - { - /* Look for a grandparent upwards the chain */ - for( grandparent = parent->next; - grandparent != NULL; - grandparent = grandparent->next ) - { - /* +2 because the current step is not yet accounted for - * and because max_pathlen is one higher than it should be. - * Also self signed certificates do not count to the limit. */ - if( grandparent->max_pathlen > 0 && - grandparent->max_pathlen < 2 + path_cnt - self_cnt ) - { - continue; - } - - if( x509_crt_check_parent( parent, grandparent, - 0, path_cnt == 0 ) == 0 ) - break; - } - - /* Is our parent part of the chain or at the top? */ - if( grandparent != NULL ) - { - ret = x509_crt_verify_child( parent, grandparent, trust_ca, ca_crl, - profile, path_cnt + 1, self_cnt, &parent_flags, - f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); - } - else - { - ret = x509_crt_verify_top( parent, trust_ca, ca_crl, profile, - path_cnt + 1, self_cnt, &parent_flags, - f_vrfy, p_vrfy ); - if( ret != 0 ) - return( ret ); - } - } - - /* child is verified to be a child of the parent, call verify callback */ - if( NULL != f_vrfy ) - if( ( ret = f_vrfy( p_vrfy, child, path_cnt, flags ) ) != 0 ) - return( ret ); - - *flags |= parent_flags; - - return( 0 ); -} - -/* - * Verify the certificate validity - */ -int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ) -{ - return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl, - &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) ); -} - - -/* - * Verify the certificate validity, with profile - */ -int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const mbedtls_x509_crt_profile *profile, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ) -{ - size_t cn_len; - int ret; - int pathlen = 0, selfsigned = 0; - mbedtls_x509_crt *parent; - mbedtls_x509_name *name; - mbedtls_x509_sequence *cur = NULL; - mbedtls_pk_type_t pk_type; - - *flags = 0; - - if( profile == NULL ) - { - ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; - goto exit; - } - - if( cn != NULL ) - { - name = &crt->subject; - cn_len = strlen( cn ); - - if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) - { - cur = &crt->subject_alt_names; - - while( cur != NULL ) - { - if( cur->buf.len == cn_len && - x509_memcasecmp( cn, cur->buf.p, cn_len ) == 0 ) - break; - - if( cur->buf.len > 2 && - memcmp( cur->buf.p, "*.", 2 ) == 0 && - x509_check_wildcard( cn, &cur->buf ) == 0 ) - { - break; - } - - cur = cur->next; - } - - if( cur == NULL ) - *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; - } - else - { - while( name != NULL ) - { - if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 ) - { - if( name->val.len == cn_len && - x509_memcasecmp( name->val.p, cn, cn_len ) == 0 ) - break; - - if( name->val.len > 2 && - memcmp( name->val.p, "*.", 2 ) == 0 && - x509_check_wildcard( cn, &name->val ) == 0 ) - break; - } - - name = name->next; - } - - if( name == NULL ) - *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; - } - } - - /* Check the type and size of the key */ - pk_type = mbedtls_pk_get_type( &crt->pk ); - - if( x509_profile_check_pk_alg( profile, pk_type ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_PK; - - if( x509_profile_check_key( profile, pk_type, &crt->pk ) != 0 ) - *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; - - /* Look for a parent in trusted CAs */ - for( parent = trust_ca; parent != NULL; parent = parent->next ) - { - if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 ) - break; - } - - if( parent != NULL ) - { - ret = x509_crt_verify_top( crt, parent, ca_crl, profile, - pathlen, selfsigned, flags, f_vrfy, p_vrfy ); - if( ret != 0 ) - goto exit; - } - else - { - /* Look for a parent upwards the chain */ - for( parent = crt->next; parent != NULL; parent = parent->next ) - if( x509_crt_check_parent( crt, parent, 0, pathlen == 0 ) == 0 ) - break; - - /* Are we part of the chain or at the top? */ - if( parent != NULL ) - { - ret = x509_crt_verify_child( crt, parent, trust_ca, ca_crl, profile, - pathlen, selfsigned, flags, f_vrfy, p_vrfy ); - if( ret != 0 ) - goto exit; - } - else - { - ret = x509_crt_verify_top( crt, trust_ca, ca_crl, profile, - pathlen, selfsigned, flags, f_vrfy, p_vrfy ); - if( ret != 0 ) - goto exit; - } - } - -exit: - /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by - * the SSL module for authmode optional, but non-zero return from the - * callback means a fatal error so it shouldn't be ignored */ - if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ) - ret = MBEDTLS_ERR_X509_FATAL_ERROR; - - if( ret != 0 ) - { - *flags = (uint32_t) -1; - return( ret ); - } - - if( *flags != 0 ) - return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ); - - return( 0 ); -} - -/* - * Initialize a certificate chain - */ -void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ) -{ - memset( crt, 0, sizeof(mbedtls_x509_crt) ); -} - -/* - * Unallocate all certificate data - */ -void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) -{ - mbedtls_x509_crt *cert_cur = crt; - mbedtls_x509_crt *cert_prv; - mbedtls_x509_name *name_cur; - mbedtls_x509_name *name_prv; - mbedtls_x509_sequence *seq_cur; - mbedtls_x509_sequence *seq_prv; - - if( crt == NULL ) - return; - - do - { - mbedtls_pk_free( &cert_cur->pk ); - -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) - mbedtls_free( cert_cur->sig_opts ); -#endif - - name_cur = cert_cur->issuer.next; - while( name_cur != NULL ) - { - name_prv = name_cur; - name_cur = name_cur->next; - mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); - mbedtls_free( name_prv ); - } - - name_cur = cert_cur->subject.next; - while( name_cur != NULL ) - { - name_prv = name_cur; - name_cur = name_cur->next; - mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); - mbedtls_free( name_prv ); - } - - seq_cur = cert_cur->ext_key_usage.next; - while( seq_cur != NULL ) - { - seq_prv = seq_cur; - seq_cur = seq_cur->next; - mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) ); - mbedtls_free( seq_prv ); - } - - seq_cur = cert_cur->subject_alt_names.next; - while( seq_cur != NULL ) - { - seq_prv = seq_cur; - seq_cur = seq_cur->next; - mbedtls_zeroize( seq_prv, sizeof( mbedtls_x509_sequence ) ); - mbedtls_free( seq_prv ); - } - - if( cert_cur->raw.p != NULL ) - { - mbedtls_zeroize( cert_cur->raw.p, cert_cur->raw.len ); - mbedtls_free( cert_cur->raw.p ); - } - - cert_cur = cert_cur->next; - } - while( cert_cur != NULL ); - - cert_cur = crt; - do - { - cert_prv = cert_cur; - cert_cur = cert_cur->next; - - mbedtls_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) ); - if( cert_prv != crt ) - mbedtls_free( cert_prv ); - } - while( cert_cur != NULL ); -} - -#endif /* MBEDTLS_X509_CRT_PARSE_C */ diff --git a/components/mbedtls/library/x509_csr.c b/components/mbedtls/library/x509_csr.c deleted file mode 100644 index 26a06db4f6..0000000000 --- a/components/mbedtls/library/x509_csr.c +++ /dev/null @@ -1,423 +0,0 @@ -/* - * X.509 Certificate Signing Request (CSR) parsing - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * The ITU-T X.509 standard defines a certificate format for PKI. - * - * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) - * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) - * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) - * - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf - * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_X509_CSR_PARSE_C) - -#include "mbedtls/x509_csr.h" -#include "mbedtls/oid.h" - -#include - -#if defined(MBEDTLS_PEM_PARSE_C) -#include "mbedtls/pem.h" -#endif - -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#include -#define mbedtls_free free -#define mbedtls_calloc calloc -#define mbedtls_snprintf snprintf -#endif - -#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) -#include -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * Version ::= INTEGER { v1(0) } - */ -static int x509_csr_get_version( unsigned char **p, - const unsigned char *end, - int *ver ) -{ - int ret; - - if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) - { - if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) - { - *ver = 0; - return( 0 ); - } - - return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); - } - - return( 0 ); -} - -/* - * Parse a CSR in DER format - */ -int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, - const unsigned char *buf, size_t buflen ) -{ - int ret; - size_t len; - unsigned char *p, *end; - mbedtls_x509_buf sig_params; - - memset( &sig_params, 0, sizeof( mbedtls_x509_buf ) ); - - /* - * Check for valid input - */ - if( csr == NULL || buf == NULL || buflen == 0 ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - mbedtls_x509_csr_init( csr ); - - /* - * first copy the raw DER data - */ - p = mbedtls_calloc( 1, len = buflen ); - - if( p == NULL ) - return( MBEDTLS_ERR_X509_ALLOC_FAILED ); - - memcpy( p, buf, buflen ); - - csr->raw.p = p; - csr->raw.len = len; - end = p + len; - - /* - * CertificationRequest ::= SEQUENCE { - * certificationRequestInfo CertificationRequestInfo, - * signatureAlgorithm AlgorithmIdentifier, - * signature BIT STRING - * } - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT ); - } - - if( len != (size_t) ( end - p ) ) - { - mbedtls_x509_csr_free( csr ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - - /* - * CertificationRequestInfo ::= SEQUENCE { - */ - csr->cri.p = p; - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); - } - - end = p + len; - csr->cri.len = end - csr->cri.p; - - /* - * Version ::= INTEGER { v1(0) } - */ - if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( ret ); - } - - if( csr->version != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); - } - - csr->version++; - - /* - * subject Name - */ - csr->subject_raw.p = p; - - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); - } - - if( ( ret = mbedtls_x509_get_name( &p, p + len, &csr->subject ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( ret ); - } - - csr->subject_raw.len = p - csr->subject_raw.p; - - /* - * subjectPKInfo SubjectPublicKeyInfo - */ - if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( ret ); - } - - /* - * attributes [0] Attributes - * - * The list of possible attributes is open-ended, though RFC 2985 - * (PKCS#9) defines a few in section 5.4. We currently don't support any, - * so we just ignore them. This is a safe thing to do as the worst thing - * that could happen is that we issue a certificate that does not match - * the requester's expectations - this cannot cause a violation of our - * signature policies. - */ - if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, - MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); - } - - p += len; - - end = csr->raw.p + csr->raw.len; - - /* - * signatureAlgorithm AlgorithmIdentifier, - * signature BIT STRING - */ - if( ( ret = mbedtls_x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( ret ); - } - - if( ( ret = mbedtls_x509_get_sig_alg( &csr->sig_oid, &sig_params, - &csr->sig_md, &csr->sig_pk, - &csr->sig_opts ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); - } - - if( ( ret = mbedtls_x509_get_sig( &p, end, &csr->sig ) ) != 0 ) - { - mbedtls_x509_csr_free( csr ); - return( ret ); - } - - if( p != end ) - { - mbedtls_x509_csr_free( csr ); - return( MBEDTLS_ERR_X509_INVALID_FORMAT + - MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); - } - - return( 0 ); -} - -/* - * Parse a CSR, allowing for PEM or raw DER encoding - */ -int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ) -{ -#if defined(MBEDTLS_PEM_PARSE_C) - int ret; - size_t use_len; - mbedtls_pem_context pem; -#endif - - /* - * Check for valid input - */ - if( csr == NULL || buf == NULL || buflen == 0 ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - -#if defined(MBEDTLS_PEM_PARSE_C) - mbedtls_pem_init( &pem ); - - /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ - if( buf[buflen - 1] != '\0' ) - ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; - else - ret = mbedtls_pem_read_buffer( &pem, - "-----BEGIN CERTIFICATE REQUEST-----", - "-----END CERTIFICATE REQUEST-----", - buf, NULL, 0, &use_len ); - - if( ret == 0 ) - { - /* - * Was PEM encoded, parse the result - */ - if( ( ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ) ) != 0 ) - return( ret ); - - mbedtls_pem_free( &pem ); - return( 0 ); - } - else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) - { - mbedtls_pem_free( &pem ); - return( ret ); - } - else -#endif /* MBEDTLS_PEM_PARSE_C */ - return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) ); -} - -#if defined(MBEDTLS_FS_IO) -/* - * Load a CSR into the structure - */ -int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ) -{ - int ret; - size_t n; - unsigned char *buf; - - if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) - return( ret ); - - ret = mbedtls_x509_csr_parse( csr, buf, n ); - - mbedtls_zeroize( buf, n ); - mbedtls_free( buf ); - - return( ret ); -} -#endif /* MBEDTLS_FS_IO */ - -#define BEFORE_COLON 14 -#define BC "14" -/* - * Return an informational string about the CSR. - */ -int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, - const mbedtls_x509_csr *csr ) -{ - int ret; - size_t n; - char *p; - char key_size_str[BEFORE_COLON]; - - p = buf; - n = size; - - ret = mbedtls_snprintf( p, n, "%sCSR version : %d", - prefix, csr->version ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - ret = mbedtls_x509_dn_gets( p, n, &csr->subject ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); - MBEDTLS_X509_SAFE_SNPRINTF; - - ret = mbedtls_x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md, - csr->sig_opts ); - MBEDTLS_X509_SAFE_SNPRINTF; - - if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, - mbedtls_pk_get_name( &csr->pk ) ) ) != 0 ) - { - return( ret ); - } - - ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str, - (int) mbedtls_pk_get_bitlen( &csr->pk ) ); - MBEDTLS_X509_SAFE_SNPRINTF; - - return( (int) ( size - n ) ); -} - -/* - * Initialize a CSR - */ -void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ) -{ - memset( csr, 0, sizeof(mbedtls_x509_csr) ); -} - -/* - * Unallocate all CSR data - */ -void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ) -{ - mbedtls_x509_name *name_cur; - mbedtls_x509_name *name_prv; - - if( csr == NULL ) - return; - - mbedtls_pk_free( &csr->pk ); - -#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) - mbedtls_free( csr->sig_opts ); -#endif - - name_cur = csr->subject.next; - while( name_cur != NULL ) - { - name_prv = name_cur; - name_cur = name_cur->next; - mbedtls_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); - mbedtls_free( name_prv ); - } - - if( csr->raw.p != NULL ) - { - mbedtls_zeroize( csr->raw.p, csr->raw.len ); - mbedtls_free( csr->raw.p ); - } - - mbedtls_zeroize( csr, sizeof( mbedtls_x509_csr ) ); -} - -#endif /* MBEDTLS_X509_CSR_PARSE_C */ diff --git a/components/mbedtls/library/x509write_crt.c b/components/mbedtls/library/x509write_crt.c deleted file mode 100644 index 4d674abcf8..0000000000 --- a/components/mbedtls/library/x509write_crt.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * X.509 certificate writing - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * References: - * - certificates: RFC 5280, updated by RFC 6818 - * - CSRs: PKCS#10 v1.7 aka RFC 2986 - * - attributes: PKCS#9 v2.0 aka RFC 2985 - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_X509_CRT_WRITE_C) - -#include "mbedtls/x509_crt.h" -#include "mbedtls/oid.h" -#include "mbedtls/asn1write.h" -#include "mbedtls/sha1.h" - -#include - -#if defined(MBEDTLS_PEM_WRITE_C) -#include "mbedtls/pem.h" -#endif /* MBEDTLS_PEM_WRITE_C */ - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ) -{ - memset( ctx, 0, sizeof(mbedtls_x509write_cert) ); - - mbedtls_mpi_init( &ctx->serial ); - ctx->version = MBEDTLS_X509_CRT_VERSION_3; -} - -void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ) -{ - mbedtls_mpi_free( &ctx->serial ); - - mbedtls_asn1_free_named_data_list( &ctx->subject ); - mbedtls_asn1_free_named_data_list( &ctx->issuer ); - mbedtls_asn1_free_named_data_list( &ctx->extensions ); - - mbedtls_zeroize( ctx, sizeof(mbedtls_x509write_cert) ); -} - -void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ) -{ - ctx->version = version; -} - -void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ) -{ - ctx->md_alg = md_alg; -} - -void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ) -{ - ctx->subject_key = key; -} - -void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ) -{ - ctx->issuer_key = key; -} - -int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, - const char *subject_name ) -{ - return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); -} - -int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, - const char *issuer_name ) -{ - return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name ); -} - -int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ) -{ - int ret; - - if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 ) - return( ret ); - - return( 0 ); -} - -int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, - const char *not_after ) -{ - if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 || - strlen( not_after ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ) - { - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - } - strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); - strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); - ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; - ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; - - return( 0 ); -} - -int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, - const char *oid, size_t oid_len, - int critical, - const unsigned char *val, size_t val_len ) -{ - return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, - critical, val, val_len ); -} - -int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, - int is_ca, int max_pathlen ) -{ - int ret; - unsigned char buf[9]; - unsigned char *c = buf + sizeof(buf); - size_t len = 0; - - memset( buf, 0, sizeof(buf) ); - - if( is_ca && max_pathlen > 127 ) - return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); - - if( is_ca ) - { - if( max_pathlen >= 0 ) - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, max_pathlen ) ); - } - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) ); - } - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS, - MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ), - 0, buf + sizeof(buf) - len, len ); -} - -#if defined(MBEDTLS_SHA1_C) -int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ) -{ - int ret; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ - unsigned char *c = buf + sizeof(buf); - size_t len = 0; - - memset( buf, 0, sizeof(buf) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) ); - - mbedtls_sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); - c = buf + sizeof(buf) - 20; - len = 20; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) ); - - return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, - MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), - 0, buf + sizeof(buf) - len, len ); -} - -int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ) -{ - int ret; - unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ - unsigned char *c = buf + sizeof(buf); - size_t len = 0; - - memset( buf, 0, sizeof(buf) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) ); - - mbedtls_sha1( buf + sizeof(buf) - len, len, buf + sizeof(buf) - 20 ); - c = buf + sizeof(buf) - 20; - len = 20; - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - return mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, - MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), - 0, buf + sizeof(buf) - len, len ); -} -#endif /* MBEDTLS_SHA1_C */ - -int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, - unsigned int key_usage ) -{ - unsigned char buf[4], ku; - unsigned char *c; - int ret; - - /* We currently only support 7 bits, from 0x80 to 0x02 */ - if( ( key_usage & ~0xfe ) != 0 ) - return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); - - c = buf + 4; - ku = (unsigned char) key_usage; - - if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 7 ) ) != 4 ) - return( ret ); - - ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, - MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), - 1, buf, 4 ); - if( ret != 0 ) - return( ret ); - - return( 0 ); -} - -int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, - unsigned char ns_cert_type ) -{ - unsigned char buf[4]; - unsigned char *c; - int ret; - - c = buf + 4; - - if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) - return( ret ); - - ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, - MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), - 0, buf, 4 ); - if( ret != 0 ) - return( ret ); - - return( 0 ); -} - -static int x509_write_time( unsigned char **p, unsigned char *start, - const char *t, size_t size ) -{ - int ret; - size_t len = 0; - - /* - * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) - */ - if( t[0] == '2' && t[1] == '0' && t[2] < '5' ) - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, - (const unsigned char *) t + 2, - size - 2 ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_UTC_TIME ) ); - } - else - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, - (const unsigned char *) t, - size ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_GENERALIZED_TIME ) ); - } - - return( (int) len ); -} - -int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - const char *sig_oid; - size_t sig_oid_len = 0; - unsigned char *c, *c2; - unsigned char hash[64]; - unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; - unsigned char tmp_buf[2048]; - size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; - size_t len = 0; - mbedtls_pk_type_t pk_alg; - - /* - * Prepare data to be signed in tmp_buf - */ - c = tmp_buf + sizeof( tmp_buf ); - - /* Signature algorithm needed in TBS, and later for actual signature */ - pk_alg = mbedtls_pk_get_type( ctx->issuer_key ); - if( pk_alg == MBEDTLS_PK_ECKEY ) - pk_alg = MBEDTLS_PK_ECDSA; - - if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, - &sig_oid, &sig_oid_len ) ) != 0 ) - { - return( ret ); - } - - /* - * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension - */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 3 ) ); - - /* - * SubjectPublicKeyInfo - */ - MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->subject_key, - tmp_buf, c - tmp_buf ) ); - c -= pub_len; - len += pub_len; - - /* - * Subject ::= Name - */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); - - /* - * Validity ::= SEQUENCE { - * notBefore Time, - * notAfter Time } - */ - sub_len = 0; - - MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after, - MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); - - MBEDTLS_ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before, - MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); - - len += sub_len; - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - /* - * Issuer ::= Name - */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->issuer ) ); - - /* - * Signature ::= AlgorithmIdentifier - */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, tmp_buf, - sig_oid, strlen( sig_oid ), 0 ) ); - - /* - * Serial ::= INTEGER - */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, tmp_buf, &ctx->serial ) ); - - /* - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - */ - sub_len = 0; - MBEDTLS_ASN1_CHK_ADD( sub_len, mbedtls_asn1_write_int( &c, tmp_buf, ctx->version ) ); - len += sub_len; - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, sub_len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | - MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - /* - * Make signature - */ - mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); - - if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len, - f_rng, p_rng ) ) != 0 ) - { - return( ret ); - } - - /* - * Write data to output buffer - */ - c2 = buf + size; - MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, - sig_oid, sig_oid_len, sig, sig_len ) ); - - if( len > (size_t)( c2 - buf ) ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - c2 -= len; - memcpy( c2, c, len ); - - len += sig_and_oid_len; - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - return( (int) len ); -} - -#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" -#define PEM_END_CRT "-----END CERTIFICATE-----\n" - -#if defined(MBEDTLS_PEM_WRITE_C) -int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - unsigned char output_buf[4096]; - size_t olen = 0; - - if( ( ret = mbedtls_x509write_crt_der( crt, output_buf, sizeof(output_buf), - f_rng, p_rng ) ) < 0 ) - { - return( ret ); - } - - if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT, - output_buf + sizeof(output_buf) - ret, - ret, buf, size, &olen ) ) != 0 ) - { - return( ret ); - } - - return( 0 ); -} -#endif /* MBEDTLS_PEM_WRITE_C */ - -#endif /* MBEDTLS_X509_CRT_WRITE_C */ diff --git a/components/mbedtls/library/x509write_csr.c b/components/mbedtls/library/x509write_csr.c deleted file mode 100644 index 8fd856b2a2..0000000000 --- a/components/mbedtls/library/x509write_csr.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * X.509 Certificate Signing Request writing - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ -/* - * References: - * - CSRs: PKCS#10 v1.7 aka RFC 2986 - * - attributes: PKCS#9 v2.0 aka RFC 2985 - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_X509_CSR_WRITE_C) - -#include "mbedtls/x509_csr.h" -#include "mbedtls/oid.h" -#include "mbedtls/asn1write.h" - -#include -#include - -#if defined(MBEDTLS_PEM_WRITE_C) -#include "mbedtls/pem.h" -#endif - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ) -{ - memset( ctx, 0, sizeof(mbedtls_x509write_csr) ); -} - -void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ) -{ - mbedtls_asn1_free_named_data_list( &ctx->subject ); - mbedtls_asn1_free_named_data_list( &ctx->extensions ); - - mbedtls_zeroize( ctx, sizeof(mbedtls_x509write_csr) ); -} - -void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ) -{ - ctx->md_alg = md_alg; -} - -void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ) -{ - ctx->key = key; -} - -int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, - const char *subject_name ) -{ - return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); -} - -int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, - const char *oid, size_t oid_len, - const unsigned char *val, size_t val_len ) -{ - return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, - 0, val, val_len ); -} - -int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ) -{ - unsigned char buf[4]; - unsigned char *c; - int ret; - - c = buf + 4; - - if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 7 ) ) != 4 ) - return( ret ); - - ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, - MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), - buf, 4 ); - if( ret != 0 ) - return( ret ); - - return( 0 ); -} - -int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, - unsigned char ns_cert_type ) -{ - unsigned char buf[4]; - unsigned char *c; - int ret; - - c = buf + 4; - - if( ( ret = mbedtls_asn1_write_bitstring( &c, buf, &ns_cert_type, 8 ) ) != 4 ) - return( ret ); - - ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, - MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), - buf, 4 ); - if( ret != 0 ) - return( ret ); - - return( 0 ); -} - -int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - const char *sig_oid; - size_t sig_oid_len = 0; - unsigned char *c, *c2; - unsigned char hash[64]; - unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; - unsigned char tmp_buf[2048]; - size_t pub_len = 0, sig_and_oid_len = 0, sig_len; - size_t len = 0; - mbedtls_pk_type_t pk_alg; - - /* - * Prepare data to be signed in tmp_buf - */ - c = tmp_buf + sizeof( tmp_buf ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); - - if( len ) - { - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SET ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( &c, tmp_buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, - MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - } - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ); - - MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key, - tmp_buf, c - tmp_buf ) ); - c -= pub_len; - len += pub_len; - - /* - * Subject ::= Name - */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) ); - - /* - * Version ::= INTEGER { v1(0), v2(1), v3(2) } - */ - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, tmp_buf, 0 ) ); - - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - /* - * Prepare signature - */ - mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); - - pk_alg = mbedtls_pk_get_type( ctx->key ); - if( pk_alg == MBEDTLS_PK_ECKEY ) - pk_alg = MBEDTLS_PK_ECDSA; - - if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, - f_rng, p_rng ) ) != 0 || - ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, - &sig_oid, &sig_oid_len ) ) != 0 ) - { - return( ret ); - } - - /* - * Write data to output buffer - */ - c2 = buf + size; - MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf, - sig_oid, sig_oid_len, sig, sig_len ) ); - - if( len > (size_t)( c2 - buf ) ) - return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); - - c2 -= len; - memcpy( c2, c, len ); - - len += sig_and_oid_len; - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); - MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED | - MBEDTLS_ASN1_SEQUENCE ) ); - - return( (int) len ); -} - -#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" -#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" - -#if defined(MBEDTLS_PEM_WRITE_C) -int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - unsigned char output_buf[4096]; - size_t olen = 0; - - if( ( ret = mbedtls_x509write_csr_der( ctx, output_buf, sizeof(output_buf), - f_rng, p_rng ) ) < 0 ) - { - return( ret ); - } - - if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR, - output_buf + sizeof(output_buf) - ret, - ret, buf, size, &olen ) ) != 0 ) - { - return( ret ); - } - - return( 0 ); -} -#endif /* MBEDTLS_PEM_WRITE_C */ - -#endif /* MBEDTLS_X509_CSR_WRITE_C */ diff --git a/components/mbedtls/library/xtea.c b/components/mbedtls/library/xtea.c deleted file mode 100644 index fe0a3509f6..0000000000 --- a/components/mbedtls/library/xtea.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * An 32-bit implementation of the XTEA algorithm - * - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * This file is part of mbed TLS (https://tls.mbed.org) - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_XTEA_C) - -#include "mbedtls/xtea.h" - -#include - -#if defined(MBEDTLS_SELF_TEST) -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_printf printf -#endif /* MBEDTLS_PLATFORM_C */ -#endif /* MBEDTLS_SELF_TEST */ - -#if !defined(MBEDTLS_XTEA_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT32_BE -#define GET_UINT32_BE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ - | ( (uint32_t) (b)[(i) + 1] << 16 ) \ - | ( (uint32_t) (b)[(i) + 2] << 8 ) \ - | ( (uint32_t) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_UINT32_BE -#define PUT_UINT32_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -void mbedtls_xtea_init( mbedtls_xtea_context *ctx ) -{ - memset( ctx, 0, sizeof( mbedtls_xtea_context ) ); -} - -void mbedtls_xtea_free( mbedtls_xtea_context *ctx ) -{ - if( ctx == NULL ) - return; - - mbedtls_zeroize( ctx, sizeof( mbedtls_xtea_context ) ); -} - -/* - * XTEA key schedule - */ -void mbedtls_xtea_setup( mbedtls_xtea_context *ctx, const unsigned char key[16] ) -{ - int i; - - memset( ctx, 0, sizeof(mbedtls_xtea_context) ); - - for( i = 0; i < 4; i++ ) - { - GET_UINT32_BE( ctx->k[i], key, i << 2 ); - } -} - -/* - * XTEA encrypt function - */ -int mbedtls_xtea_crypt_ecb( mbedtls_xtea_context *ctx, int mode, - const unsigned char input[8], unsigned char output[8]) -{ - uint32_t *k, v0, v1, i; - - k = ctx->k; - - GET_UINT32_BE( v0, input, 0 ); - GET_UINT32_BE( v1, input, 4 ); - - if( mode == MBEDTLS_XTEA_ENCRYPT ) - { - uint32_t sum = 0, delta = 0x9E3779B9; - - for( i = 0; i < 32; i++ ) - { - v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); - sum += delta; - v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); - } - } - else /* MBEDTLS_XTEA_DECRYPT */ - { - uint32_t delta = 0x9E3779B9, sum = delta * 32; - - for( i = 0; i < 32; i++ ) - { - v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum>>11) & 3]); - sum -= delta; - v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); - } - } - - PUT_UINT32_BE( v0, output, 0 ); - PUT_UINT32_BE( v1, output, 4 ); - - return( 0 ); -} - -#if defined(MBEDTLS_CIPHER_MODE_CBC) -/* - * XTEA-CBC buffer encryption/decryption - */ -int mbedtls_xtea_crypt_cbc( mbedtls_xtea_context *ctx, int mode, size_t length, - unsigned char iv[8], const unsigned char *input, - unsigned char *output) -{ - int i; - unsigned char temp[8]; - - if( length % 8 ) - return( MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH ); - - if( mode == MBEDTLS_XTEA_DECRYPT ) - { - while( length > 0 ) - { - memcpy( temp, input, 8 ); - mbedtls_xtea_crypt_ecb( ctx, mode, input, output ); - - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - else - { - while( length > 0 ) - { - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - mbedtls_xtea_crypt_ecb( ctx, mode, output, output ); - memcpy( iv, output, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - - return( 0 ); -} -#endif /* MBEDTLS_CIPHER_MODE_CBC */ -#endif /* !MBEDTLS_XTEA_ALT */ - -#if defined(MBEDTLS_SELF_TEST) - -/* - * XTEA tests vectors (non-official) - */ - -static const unsigned char xtea_test_key[6][16] = -{ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 } -}; - -static const unsigned char xtea_test_pt[6][8] = -{ - { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, - { 0x5a, 0x5b, 0x6e, 0x27, 0x89, 0x48, 0xd7, 0x7f }, - { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, - { 0x70, 0xe1, 0x22, 0x5d, 0x6e, 0x4e, 0x76, 0x55 } -}; - -static const unsigned char xtea_test_ct[6][8] = -{ - { 0x49, 0x7d, 0xf3, 0xd0, 0x72, 0x61, 0x2c, 0xb5 }, - { 0xe7, 0x8f, 0x2d, 0x13, 0x74, 0x43, 0x41, 0xd8 }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }, - { 0xa0, 0x39, 0x05, 0x89, 0xf8, 0xb8, 0xef, 0xa5 }, - { 0xed, 0x23, 0x37, 0x5a, 0x82, 0x1a, 0x8c, 0x2d }, - { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 } -}; - -/* - * Checkup routine - */ -int mbedtls_xtea_self_test( int verbose ) -{ - int i, ret = 0; - unsigned char buf[8]; - mbedtls_xtea_context ctx; - - mbedtls_xtea_init( &ctx ); - for( i = 0; i < 6; i++ ) - { - if( verbose != 0 ) - mbedtls_printf( " XTEA test #%d: ", i + 1 ); - - memcpy( buf, xtea_test_pt[i], 8 ); - - mbedtls_xtea_setup( &ctx, xtea_test_key[i] ); - mbedtls_xtea_crypt_ecb( &ctx, MBEDTLS_XTEA_ENCRYPT, buf, buf ); - - if( memcmp( buf, xtea_test_ct[i], 8 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - mbedtls_printf( "passed\n" ); - } - - if( verbose != 0 ) - mbedtls_printf( "\n" ); - -exit: - mbedtls_xtea_free( &ctx ); - - return( ret ); -} - -#endif /* MBEDTLS_SELF_TEST */ - -#endif /* MBEDTLS_XTEA_C */ diff --git a/components/mbedtls/mbedtls b/components/mbedtls/mbedtls new file mode 160000 index 0000000000..b3a48ac894 --- /dev/null +++ b/components/mbedtls/mbedtls @@ -0,0 +1 @@ +Subproject commit b3a48ac894b660f6b99dd10f01818fb6fc389b42 diff --git a/tools/ci/mirror-list.txt b/tools/ci/mirror-list.txt index 789d4e844f..5ff4fb74a3 100644 --- a/tools/ci/mirror-list.txt +++ b/tools/ci/mirror-list.txt @@ -5,6 +5,7 @@ components/coap/libcoap @GENERAL_MIRROR_SERVER@/idf/ components/esptool_py/esptool @GENERAL_MIRROR_SERVER@/idf/esptool.git ALLOW_TO_SYNC_FROM_PUBLIC components/json/cJSON @GENERAL_MIRROR_SERVER@/idf/cJSON.git ALLOW_TO_SYNC_FROM_PUBLIC components/libsodium/libsodium @GENERAL_MIRROR_SERVER@/idf/libsodium.git ALLOW_TO_SYNC_FROM_PUBLIC +components/mbedtls/mbedtls @GENERAL_MIRROR_SERVER@/idf/mbedtls.git ALLOW_TO_SYNC_FROM_PUBLIC components/micro-ecc/micro-ecc @GENERAL_MIRROR_SERVER@/idf/micro-ecc.git ALLOW_TO_SYNC_FROM_PUBLIC components/nghttp/nghttp2 @GENERAL_MIRROR_SERVER@/idf/nghttp2.git ALLOW_TO_SYNC_FROM_PUBLIC components/spiffs/spiffs @GENERAL_MIRROR_SERVER@/idf/spiffs.git ALLOW_TO_SYNC_FROM_PUBLIC From 254e29aca494d6e8b54cba44562c5fe6709da7a2 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 8 May 2018 23:21:01 +0800 Subject: [PATCH 058/187] mbedtls: update usage of deprecated mbedtls_shaX APIs The following mbedTLS APIs have been deprecated and replaced with the new ones which return error codes: mbedtls_shaX_starts -> mbedtls_shaX_starts_ret mbedtls_shaX_update -> mbedtls_shaX_update_ret mbedtls_shaX_finish -> mbedtls_shaX_finish_ret mbedtls_shaX_process -> mbedtls_shaX_internal_process Update hardware implementations of SHA functions, and other IDF components which used above functions, to use new versions. --- .../bootloader_support/src/bootloader_sha.c | 6 +- .../crypto_hash_sha256_mbedtls.c | 17 ++-- .../crypto_hash_sha512_mbedtls.c | 16 ++-- components/mbedtls/port/esp_sha1.c | 78 +++++++++++++++--- components/mbedtls/port/esp_sha256.c | 81 ++++++++++++++++--- components/mbedtls/port/esp_sha512.c | 79 +++++++++++++++--- components/mbedtls/test/test_mbedtls_sha.c | 66 +++++++-------- .../src/fast_crypto/fast_sha256-internal.c | 24 ++++-- 8 files changed, 276 insertions(+), 91 deletions(-) diff --git a/components/bootloader_support/src/bootloader_sha.c b/components/bootloader_support/src/bootloader_sha.c index 079093ef8a..be23f7f26a 100644 --- a/components/bootloader_support/src/bootloader_sha.c +++ b/components/bootloader_support/src/bootloader_sha.c @@ -28,7 +28,7 @@ bootloader_sha256_handle_t bootloader_sha256_start() return NULL; } mbedtls_sha256_init(ctx); - mbedtls_sha256_starts(ctx, false); + assert(mbedtls_sha256_starts_ret(ctx, false) == 0); return ctx; } @@ -36,7 +36,7 @@ void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, { assert(handle != NULL); mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle; - mbedtls_sha256_update(ctx, data, data_len); + assert(mbedtls_sha256_update_ret(ctx, data, data_len) == 0); } void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest) @@ -44,7 +44,7 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest assert(handle != NULL); mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle; if (digest != NULL) { - mbedtls_sha256_finish(ctx, digest); + assert(mbedtls_sha256_finish_ret(ctx, digest) == 0); } mbedtls_sha256_free(ctx); free(handle); diff --git a/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha256_mbedtls.c b/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha256_mbedtls.c index b4fb442699..39c36c70a0 100644 --- a/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha256_mbedtls.c +++ b/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha256_mbedtls.c @@ -63,7 +63,10 @@ crypto_hash_sha256_init(crypto_hash_sha256_state *state) { mbedtls_sha256_context ctx; mbedtls_sha256_init(&ctx); - mbedtls_sha256_starts(&ctx, 0); + int ret = mbedtls_sha256_starts_ret(&ctx, 0); + if (ret != 0) { + return ret; + } sha256_mbedtls_to_libsodium(state, &ctx); return 0; } @@ -74,7 +77,10 @@ crypto_hash_sha256_update(crypto_hash_sha256_state *state, { mbedtls_sha256_context ctx; sha256_libsodium_to_mbedtls(&ctx, state); - mbedtls_sha256_update(&ctx, in, inlen); + int ret = mbedtls_sha256_update_ret(&ctx, in, inlen); + if (ret != 0) { + return ret; + } sha256_mbedtls_to_libsodium(state, &ctx); return 0; } @@ -84,15 +90,12 @@ crypto_hash_sha256_final(crypto_hash_sha256_state *state, unsigned char *out) { mbedtls_sha256_context ctx; sha256_libsodium_to_mbedtls(&ctx, state); - mbedtls_sha256_finish(&ctx, out); - sha256_mbedtls_to_libsodium(state, &ctx); - return 0; + return mbedtls_sha256_finish_ret(&ctx, out); } int crypto_hash_sha256(unsigned char *out, const unsigned char *in, unsigned long long inlen) { - mbedtls_sha256(in, inlen, out, 0); - return 0; + return mbedtls_sha256_ret(in, inlen, out, 0); } diff --git a/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha512_mbedtls.c b/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha512_mbedtls.c index 49fee0ca69..48d31a61e4 100644 --- a/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha512_mbedtls.c +++ b/components/libsodium/port/crypto_hash_mbedtls/crypto_hash_sha512_mbedtls.c @@ -67,7 +67,10 @@ crypto_hash_sha512_init(crypto_hash_sha512_state *state) { mbedtls_sha512_context ctx; mbedtls_sha512_init(&ctx); - mbedtls_sha512_starts(&ctx, 0); + int ret = mbedtls_sha512_starts_ret(&ctx, 0); + if (ret != 0) { + return ret; + } sha512_mbedtls_to_libsodium(state, &ctx); return 0; } @@ -78,7 +81,10 @@ crypto_hash_sha512_update(crypto_hash_sha512_state *state, { mbedtls_sha512_context ctx; sha512_libsodium_to_mbedtls(&ctx, state); - mbedtls_sha512_update(&ctx, in, inlen); + int ret = mbedtls_sha512_update_ret(&ctx, in, inlen); + if (ret != 0) { + return ret; + } sha512_mbedtls_to_libsodium(state, &ctx); return 0; } @@ -88,14 +94,12 @@ crypto_hash_sha512_final(crypto_hash_sha512_state *state, unsigned char *out) { mbedtls_sha512_context ctx; sha512_libsodium_to_mbedtls(&ctx, state); - mbedtls_sha512_finish(&ctx, out); - return 0; + return mbedtls_sha512_finish_ret(&ctx, out); } int crypto_hash_sha512(unsigned char *out, const unsigned char *in, unsigned long long inlen) { - mbedtls_sha512(in, inlen, out, 0); - return 0; + return mbedtls_sha512_ret(in, inlen, out, 0); } diff --git a/components/mbedtls/port/esp_sha1.c b/components/mbedtls/port/esp_sha1.c index 6751596933..fddc32dd5d 100644 --- a/components/mbedtls/port/esp_sha1.c +++ b/components/mbedtls/port/esp_sha1.c @@ -111,7 +111,7 @@ void mbedtls_sha1_clone( mbedtls_sha1_context *dst, /* * SHA-1 context setup */ -void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) +int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ) { ctx->total[0] = 0; ctx->total[1] = 0; @@ -126,11 +126,20 @@ void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) esp_sha_unlock_engine(SHA1); } ctx->mode = ESP_MBEDTLS_SHA1_UNUSED; + + return 0; } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) +{ + mbedtls_sha1_starts_ret( ctx ); +} +#endif + static void mbedtls_sha1_software_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ); -void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) { bool first_block = false; if (ctx->mode == ESP_MBEDTLS_SHA1_UNUSED) { @@ -148,8 +157,18 @@ void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[6 } else { mbedtls_sha1_software_process(ctx, data); } + + return 0; } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha1_process( ctx, data ); +} +#endif + static void mbedtls_sha1_software_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) { @@ -310,13 +329,14 @@ static void mbedtls_sha1_software_process( mbedtls_sha1_context *ctx, const unsi /* * SHA-1 process buffer */ -void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ) +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ) { + int ret; size_t fill; uint32_t left; if( ilen == 0 ) - return; + return 0; left = ctx->total[0] & 0x3F; fill = 64 - left; @@ -330,7 +350,11 @@ void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, if( left && ilen >= fill ) { memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_sha1_process( ctx, ctx->buffer ); + + if ( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) { + return ret; + } + input += fill; ilen -= fill; left = 0; @@ -338,15 +362,29 @@ void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, while( ilen >= 64 ) { - mbedtls_sha1_process( ctx, input ); + if ( ( ret = mbedtls_internal_sha1_process( ctx, input ) ) != 0 ) { + return ret; + } + input += 64; ilen -= 64; } if( ilen > 0 ) memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return 0; } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha1_update_ret( ctx, input, ilen ); +} +#endif + static const unsigned char sha1_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -358,8 +396,9 @@ static const unsigned char sha1_padding[64] = /* * SHA-1 final digest */ -void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ) +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, unsigned char output[20] ) { + int ret; uint32_t last, padn; uint32_t high, low; unsigned char msglen[8]; @@ -374,14 +413,16 @@ void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ) last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - mbedtls_sha1_update( ctx, sha1_padding, padn ); - mbedtls_sha1_update( ctx, msglen, 8 ); + if ( ( ret = mbedtls_sha1_update_ret( ctx, sha1_padding, padn ) ) != 0 ) { + goto out; + } + if ( ( ret = mbedtls_sha1_update_ret( ctx, msglen, 8 ) ) != 0 ) { + goto out; + } /* if state is in hardware, read it out */ if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) { esp_sha_read_digest_state(SHA1, ctx->state); - esp_sha_unlock_engine(SHA1); - ctx->mode = ESP_MBEDTLS_SHA1_SOFTWARE; } PUT_UINT32_BE( ctx->state[0], output, 0 ); @@ -390,6 +431,21 @@ void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ) PUT_UINT32_BE( ctx->state[3], output, 12 ); PUT_UINT32_BE( ctx->state[4], output, 16 ); +out: + if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) { + esp_sha_unlock_engine(SHA1); + ctx->mode = ESP_MBEDTLS_SHA1_SOFTWARE; + } + + return ret; } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ) +{ + mbedtls_sha1_finish_ret( ctx, output ); +} +#endif + #endif /* MBEDTLS_SHA1_C && MBEDTLS_SHA1_ALT */ diff --git a/components/mbedtls/port/esp_sha256.c b/components/mbedtls/port/esp_sha256.c index fd136062a4..4eb37c077d 100644 --- a/components/mbedtls/port/esp_sha256.c +++ b/components/mbedtls/port/esp_sha256.c @@ -111,7 +111,7 @@ void mbedtls_sha256_clone( mbedtls_sha256_context *dst, /* * SHA-256 context setup */ -void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) +int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ) { ctx->total[0] = 0; ctx->total[1] = 0; @@ -146,9 +146,17 @@ void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) esp_sha_unlock_engine(SHA2_256); } ctx->mode = ESP_MBEDTLS_SHA256_UNUSED; + return 0; } -#if !defined(MBEDTLS_SHA256_PROCESS_ALT) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ) +{ + mbedtls_sha256_starts_ret( ctx, is224 ); +} +#endif + static const uint32_t K[] = { 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, @@ -196,7 +204,7 @@ static const uint32_t K[] = static void mbedtls_sha256_software_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ); -void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) { bool first_block = false; @@ -215,8 +223,17 @@ void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char da } else { mbedtls_sha256_software_process(ctx, data); } + + return 0; } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha256_process( ctx, data ); +} +#endif static void mbedtls_sha256_software_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) { @@ -272,19 +289,19 @@ static void mbedtls_sha256_software_process( mbedtls_sha256_context *ctx, const for( i = 0; i < 8; i++ ) ctx->state[i] += A[i]; } -#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ /* * SHA-256 process buffer */ -void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen ) { + int ret; size_t fill; uint32_t left; if( ilen == 0 ) - return; + return 0; left = ctx->total[0] & 0x3F; fill = 64 - left; @@ -298,7 +315,11 @@ void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *in if( left && ilen >= fill ) { memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_sha256_process( ctx, ctx->buffer ); + + if ( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) { + return ret; + } + input += fill; ilen -= fill; left = 0; @@ -306,15 +327,29 @@ void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *in while( ilen >= 64 ) { - mbedtls_sha256_process( ctx, input ); + if ( ( ret = mbedtls_internal_sha256_process( ctx, input ) ) != 0 ) { + return ret; + } + input += 64; ilen -= 64; } if( ilen > 0 ) memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return 0; } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha256_update_ret( ctx, input, ilen ); +} +#endif + static const unsigned char sha256_padding[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -326,8 +361,9 @@ static const unsigned char sha256_padding[64] = /* * SHA-256 final digest */ -void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ) +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, unsigned char output[32] ) { + int ret; uint32_t last, padn; uint32_t high, low; unsigned char msglen[8]; @@ -342,14 +378,17 @@ void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32 last = ctx->total[0] & 0x3F; padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - mbedtls_sha256_update( ctx, sha256_padding, padn ); - mbedtls_sha256_update( ctx, msglen, 8 ); + if ( ( ret = mbedtls_sha256_update_ret( ctx, sha256_padding, padn ) ) != 0 ) { + goto out; + } + + if ( ( ret = mbedtls_sha256_update_ret( ctx, msglen, 8 ) ) != 0 ) { + goto out; + } /* if state is in hardware, read it out */ if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) { esp_sha_read_digest_state(SHA2_256, ctx->state); - esp_sha_unlock_engine(SHA2_256); - ctx->mode = ESP_MBEDTLS_SHA256_SOFTWARE; } PUT_UINT32_BE( ctx->state[0], output, 0 ); @@ -362,6 +401,22 @@ void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32 if( ctx->is224 == 0 ) PUT_UINT32_BE( ctx->state[7], output, 28 ); + +out: + if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) { + esp_sha_unlock_engine(SHA2_256); + ctx->mode = ESP_MBEDTLS_SHA256_SOFTWARE; + } + + return ret; } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ) +{ + mbedtls_sha256_finish_ret( ctx, output ); +} +#endif + #endif /* MBEDTLS_SHA256_C && MBEDTLS_SHA256_ALT */ diff --git a/components/mbedtls/port/esp_sha512.c b/components/mbedtls/port/esp_sha512.c index 7a2bb15cb7..a61f5f5c2e 100644 --- a/components/mbedtls/port/esp_sha512.c +++ b/components/mbedtls/port/esp_sha512.c @@ -135,7 +135,7 @@ void mbedtls_sha512_clone( mbedtls_sha512_context *dst, /* * SHA-512 context setup */ -void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ) +int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ) { ctx->total[0] = 0; ctx->total[1] = 0; @@ -170,8 +170,17 @@ void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ) esp_sha_unlock_engine(sha_type(ctx)); } ctx->mode = ESP_MBEDTLS_SHA512_UNUSED; + + return 0; } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ) +{ + mbedtls_sha512_starts_ret( ctx, is384 ); +} +#endif /* * Round constants @@ -222,7 +231,7 @@ static const uint64_t K[80] = static void mbedtls_sha512_software_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ); -void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ) +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ) { bool first_block = false; @@ -241,8 +250,17 @@ void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char da } else { mbedtls_sha512_software_process(ctx, data); } + + return 0; } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) +{ + mbedtls_internal_sha512_process( ctx, data ); +} +#endif static void mbedtls_sha512_software_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ) @@ -317,14 +335,15 @@ static void mbedtls_sha512_software_process( mbedtls_sha512_context *ctx, const /* * SHA-512 process buffer */ -void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input, +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, const unsigned char *input, size_t ilen ) { + int ret; size_t fill; unsigned int left; if( ilen == 0 ) - return; + return 0; left = (unsigned int) (ctx->total[0] & 0x7F); fill = 128 - left; @@ -337,7 +356,10 @@ void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *in if( left && ilen >= fill ) { memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_sha512_process( ctx, ctx->buffer ); + if ( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) { + return ret; + } + input += fill; ilen -= fill; left = 0; @@ -345,15 +367,30 @@ void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *in while( ilen >= 128 ) { - mbedtls_sha512_process( ctx, input ); + if ( ( ret = mbedtls_internal_sha512_process( ctx, input ) ) != 0 ) { + return ret; + } + input += 128; ilen -= 128; } if( ilen > 0 ) memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return 0; } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha512_update_ret( ctx, input, ilen ); +} +#endif + + static const unsigned char sha512_padding[128] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -369,8 +406,9 @@ static const unsigned char sha512_padding[128] = /* * SHA-512 final digest */ -void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] ) +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, unsigned char output[64] ) { + int ret; size_t last, padn; uint64_t high, low; unsigned char msglen[16]; @@ -385,14 +423,17 @@ void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64 last = (size_t)( ctx->total[0] & 0x7F ); padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last ); - mbedtls_sha512_update( ctx, sha512_padding, padn ); - mbedtls_sha512_update( ctx, msglen, 16 ); + if ( ( ret = mbedtls_sha512_update_ret( ctx, sha512_padding, padn ) ) != 0 ) { + goto out; + } + + if ( ( ret = mbedtls_sha512_update_ret( ctx, msglen, 16 ) ) != 0 ) { + goto out; + } /* if state is in hardware, read it out */ if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) { esp_sha_read_digest_state(sha_type(ctx), ctx->state); - esp_sha_unlock_engine(sha_type(ctx)); - ctx->mode = ESP_MBEDTLS_SHA512_SOFTWARE; } PUT_UINT64_BE( ctx->state[0], output, 0 ); @@ -407,6 +448,22 @@ void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64 PUT_UINT64_BE( ctx->state[6], output, 48 ); PUT_UINT64_BE( ctx->state[7], output, 56 ); } + +out: + if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) { + esp_sha_unlock_engine(sha_type(ctx)); + ctx->mode = ESP_MBEDTLS_SHA512_SOFTWARE; + } + + return ret; } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ) +{ + mbedtls_sha512_finish_ret( ctx, output ); +} +#endif + #endif /* MBEDTLS_SHA512_C && MBEDTLS_SHA512_ALT */ diff --git a/components/mbedtls/test/test_mbedtls_sha.c b/components/mbedtls/test/test_mbedtls_sha.c index fba16ef0b5..aa81d63032 100644 --- a/components/mbedtls/test/test_mbedtls_sha.c +++ b/components/mbedtls/test/test_mbedtls_sha.c @@ -62,19 +62,19 @@ TEST_CASE("mbedtls SHA interleaving", "[mbedtls]") mbedtls_sha256_init(&sha256_ctx); mbedtls_sha512_init(&sha512_ctx); - mbedtls_sha1_starts(&sha1_ctx); - mbedtls_sha256_starts(&sha256_ctx, false); - mbedtls_sha512_starts(&sha512_ctx, false); + TEST_ASSERT_EQUAL(0, mbedtls_sha1_starts_ret(&sha1_ctx)); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts_ret(&sha256_ctx, false)); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_starts_ret(&sha512_ctx, false)); for (int i = 0; i < 10; i++) { - mbedtls_sha1_update(&sha1_ctx, one_hundred_as, 100); - mbedtls_sha256_update(&sha256_ctx, one_hundred_as, 100); - mbedtls_sha512_update(&sha512_ctx, one_hundred_bs, 100); + TEST_ASSERT_EQUAL(0, mbedtls_sha1_update_ret(&sha1_ctx, one_hundred_as, 100)); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_update_ret(&sha256_ctx, one_hundred_as, 100)); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&sha512_ctx, one_hundred_bs, 100)); } - mbedtls_sha1_finish(&sha1_ctx, sha1); - mbedtls_sha256_finish(&sha256_ctx, sha256); - mbedtls_sha512_finish(&sha512_ctx, sha512); + TEST_ASSERT_EQUAL(0, mbedtls_sha1_finish_ret(&sha1_ctx, sha1)); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish_ret(&sha256_ctx, sha256)); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish_ret(&sha512_ctx, sha512)); TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 calculation"); TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, sha256, 32, "SHA256 calculation"); @@ -89,11 +89,11 @@ static void tskRunSHA1Test(void *pvParameters) for (int i = 0; i < 1000; i++) { mbedtls_sha1_init(&sha1_ctx); - mbedtls_sha1_starts(&sha1_ctx); + TEST_ASSERT_EQUAL(0, mbedtls_sha1_starts_ret(&sha1_ctx)); for (int j = 0; j < 10; j++) { - mbedtls_sha1_update(&sha1_ctx, (unsigned char *)one_hundred_as, 100); + TEST_ASSERT_EQUAL(0, mbedtls_sha1_update_ret(&sha1_ctx, (unsigned char *)one_hundred_as, 100)); } - mbedtls_sha1_finish(&sha1_ctx, sha1); + TEST_ASSERT_EQUAL(0, mbedtls_sha1_finish_ret(&sha1_ctx, sha1)); TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha1_thousand_as, sha1, 20, "SHA1 calculation"); } xSemaphoreGive(done_sem); @@ -107,11 +107,11 @@ static void tskRunSHA256Test(void *pvParameters) for (int i = 0; i < 1000; i++) { mbedtls_sha256_init(&sha256_ctx); - mbedtls_sha256_starts(&sha256_ctx, false); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts_ret(&sha256_ctx, false)); for (int j = 0; j < 10; j++) { - mbedtls_sha256_update(&sha256_ctx, (unsigned char *)one_hundred_bs, 100); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_update_ret(&sha256_ctx, (unsigned char *)one_hundred_bs, 100)); } - mbedtls_sha256_finish(&sha256_ctx, sha256); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish_ret(&sha256_ctx, sha256)); TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_bs, sha256, 32, "SHA256 calculation"); } @@ -187,21 +187,21 @@ TEST_CASE("mbedtls SHA512 clone", "[mbedtls]") unsigned char sha512[64]; mbedtls_sha512_init(&ctx); - mbedtls_sha512_starts(&ctx, false); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_starts_ret(&ctx, false)); for (int i = 0; i < 5; i++) { - mbedtls_sha512_update(&ctx, one_hundred_bs, 100); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&ctx, one_hundred_bs, 100)); } mbedtls_sha512_clone(&clone, &ctx); for (int i = 0; i < 5; i++) { - mbedtls_sha512_update(&ctx, one_hundred_bs, 100); - mbedtls_sha512_update(&clone, one_hundred_bs, 100); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&ctx, one_hundred_bs, 100)); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&clone, one_hundred_bs, 100)); } - mbedtls_sha512_finish(&ctx, sha512); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish_ret(&ctx, sha512)); TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 original calculation"); - mbedtls_sha512_finish(&clone, sha512); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish_ret(&clone, sha512)); TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 cloned calculation"); } @@ -212,21 +212,21 @@ TEST_CASE("mbedtls SHA384 clone", "[mbedtls]") unsigned char sha384[48]; mbedtls_sha512_init(&ctx); - mbedtls_sha512_starts(&ctx, true); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_starts_ret(&ctx, true)); for (int i = 0; i < 5; i++) { - mbedtls_sha512_update(&ctx, one_hundred_bs, 100); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&ctx, one_hundred_bs, 100)); } mbedtls_sha512_clone(&clone, &ctx); for (int i = 0; i < 5; i++) { - mbedtls_sha512_update(&ctx, one_hundred_bs, 100); - mbedtls_sha512_update(&clone, one_hundred_bs, 100); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&ctx, one_hundred_bs, 100)); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&clone, one_hundred_bs, 100)); } - mbedtls_sha512_finish(&ctx, sha384); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish_ret(&ctx, sha384)); TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha384_thousand_bs, sha384, 48, "SHA512 original calculation"); - mbedtls_sha512_finish(&clone, sha384); + TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish_ret(&clone, sha384)); TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha384_thousand_bs, sha384, 48, "SHA512 cloned calculation"); } @@ -238,20 +238,20 @@ TEST_CASE("mbedtls SHA256 clone", "[mbedtls]") unsigned char sha256[64]; mbedtls_sha256_init(&ctx); - mbedtls_sha256_starts(&ctx, false); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts_ret(&ctx, false)); for (int i = 0; i < 5; i++) { - mbedtls_sha256_update(&ctx, one_hundred_as, 100); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_update_ret(&ctx, one_hundred_as, 100)); } mbedtls_sha256_clone(&clone, &ctx); for (int i = 0; i < 5; i++) { - mbedtls_sha256_update(&ctx, one_hundred_as, 100); - mbedtls_sha256_update(&clone, one_hundred_as, 100); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_update_ret(&ctx, one_hundred_as, 100)); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_update_ret(&clone, one_hundred_as, 100)); } - mbedtls_sha256_finish(&ctx, sha256); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish_ret(&ctx, sha256)); TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, sha256, 32, "SHA256 original calculation"); - mbedtls_sha256_finish(&clone, sha256); + TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish_ret(&clone, sha256)); TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, sha256, 32, "SHA256 cloned calculation"); } diff --git a/components/wpa_supplicant/src/fast_crypto/fast_sha256-internal.c b/components/wpa_supplicant/src/fast_crypto/fast_sha256-internal.c index 587b9096fc..7650cb87ed 100644 --- a/components/wpa_supplicant/src/fast_crypto/fast_sha256-internal.c +++ b/components/wpa_supplicant/src/fast_crypto/fast_sha256-internal.c @@ -28,21 +28,31 @@ int fast_sha256_vector(size_t num_elem, const uint8_t *addr[], const size_t *len, uint8_t *mac) { + int ret = 0; 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]); + if (mbedtls_sha256_starts_ret(&ctx, 0) != 0) { + ret = -1; + goto out; } - mbedtls_sha256_finish(&ctx, mac); + for(size_t index = 0; index < num_elem; index++) { + if (mbedtls_sha256_update_ret(&ctx, addr[index], len[index]) != 0) { + ret = -1; + goto out; + } + } + if (mbedtls_sha256_finish_ret(&ctx, mac) != 0) { + ret = -1; + goto out; + } + +out: mbedtls_sha256_free(&ctx); - return 0; + return ret; } - From aad51ea8a0e337eb30e70767488a01c3c46fa9d7 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 8 May 2018 23:22:57 +0800 Subject: [PATCH 059/187] =?UTF-8?q?mbedtls/port:=20don=E2=80=99t=20re-decl?= =?UTF-8?q?are=20mbedtls=5FshaX=20functions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ALT header files for sha1, sha256, sha512 are only supposed to declare mbedtls_sha1_context data structure. Function prototypes should come from original header files. --- components/mbedtls/port/include/sha1_alt.h | 50 ------------------- components/mbedtls/port/include/sha256_alt.h | 52 -------------------- components/mbedtls/port/include/sha512_alt.h | 52 -------------------- 3 files changed, 154 deletions(-) diff --git a/components/mbedtls/port/include/sha1_alt.h b/components/mbedtls/port/include/sha1_alt.h index fbe740c7e0..54b7740878 100644 --- a/components/mbedtls/port/include/sha1_alt.h +++ b/components/mbedtls/port/include/sha1_alt.h @@ -47,56 +47,6 @@ typedef struct } mbedtls_sha1_context; -/** - * \brief Initialize SHA-1 context - * - * \param ctx SHA-1 context to be initialized - */ -void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); - -/** - * \brief Clear SHA-1 context - * - * \param ctx SHA-1 context to be cleared - */ -void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); - -/** - * \brief Clone (the state of) a SHA-1 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_sha1_clone( mbedtls_sha1_context *dst, - const mbedtls_sha1_context *src ); - -/** - * \brief SHA-1 context setup - * - * \param ctx context to be initialized - */ -void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); - -/** - * \brief SHA-1 process buffer - * - * \param ctx SHA-1 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief SHA-1 final digest - * - * \param ctx SHA-1 context - * \param output SHA-1 checksum result - */ -void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ); - -/* Internal use */ -void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ); - #endif #ifdef __cplusplus diff --git a/components/mbedtls/port/include/sha256_alt.h b/components/mbedtls/port/include/sha256_alt.h index cc87333aaa..436f5324c8 100644 --- a/components/mbedtls/port/include/sha256_alt.h +++ b/components/mbedtls/port/include/sha256_alt.h @@ -48,58 +48,6 @@ typedef struct } mbedtls_sha256_context; -/** - * \brief Initialize SHA-256 context - * - * \param ctx SHA-256 context to be initialized - */ -void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); - -/** - * \brief Clear SHA-256 context - * - * \param ctx SHA-256 context to be cleared - */ -void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); - -/** - * \brief Clone (the state of) a SHA-256 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_sha256_clone( mbedtls_sha256_context *dst, - const mbedtls_sha256_context *src ); - -/** - * \brief SHA-256 context setup - * - * \param ctx context to be initialized - * \param is224 0 = use SHA256, 1 = use SHA224 - */ -void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ); - -/** - * \brief SHA-256 process buffer - * - * \param ctx SHA-256 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, - size_t ilen ); - -/** - * \brief SHA-256 final digest - * - * \param ctx SHA-256 context - * \param output SHA-224/256 checksum result - */ -void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ); - -/* Internal use */ -void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ); - #endif #ifdef __cplusplus diff --git a/components/mbedtls/port/include/sha512_alt.h b/components/mbedtls/port/include/sha512_alt.h index 70ae24e166..36b8fc9d24 100644 --- a/components/mbedtls/port/include/sha512_alt.h +++ b/components/mbedtls/port/include/sha512_alt.h @@ -48,58 +48,6 @@ typedef struct } mbedtls_sha512_context; -/** - * \brief Initialize SHA-512 context - * - * \param ctx SHA-512 context to be initialized - */ -void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); - -/** - * \brief Clear SHA-512 context - * - * \param ctx SHA-512 context to be cleared - */ -void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); - -/** - * \brief Clone (the state of) a SHA-512 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_sha512_clone( mbedtls_sha512_context *dst, - const mbedtls_sha512_context *src ); - -/** - * \brief SHA-512 context setup - * - * \param ctx context to be initialized - * \param is384 0 = use SHA512, 1 = use SHA384 - */ -void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ); - -/** - * \brief SHA-512 process buffer - * - * \param ctx SHA-512 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input, - size_t ilen ); - -/** - * \brief SHA-512 final digest - * - * \param ctx SHA-512 context - * \param output SHA-384/512 checksum result - */ -void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] ); - -/* Internal use */ -void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ); - #endif #ifdef __cplusplus From dbc919eff565c47c4e4990fb18e58e78a7111ec4 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 8 May 2018 23:50:22 +0800 Subject: [PATCH 060/187] mbedtls: update usage of mbedtls_aes_encrypt/decrypt --- components/esp32/hwcrypto/aes.c | 20 +++++++++++++++++-- components/esp32/include/hwcrypto/aes.h | 10 ++++++++-- components/mbedtls/port/include/aes_alt.h | 4 ++-- .../src/fast_crypto/fast_aes-unwrap.c | 7 +++++-- .../src/fast_crypto/fast_aes-wrap.c | 7 +++++-- .../fast_crypto/fast_crypto_internal-cipher.c | 8 ++++++-- 6 files changed, 44 insertions(+), 12 deletions(-) diff --git a/components/esp32/hwcrypto/aes.c b/components/esp32/hwcrypto/aes.c index 716bc636fe..1e9bdc8523 100644 --- a/components/esp32/hwcrypto/aes.c +++ b/components/esp32/hwcrypto/aes.c @@ -155,7 +155,7 @@ static inline void esp_aes_block(const void *input, void *output) /* * AES-ECB block encryption */ -void esp_aes_encrypt( esp_aes_context *ctx, +int esp_internal_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) { @@ -163,13 +163,21 @@ void esp_aes_encrypt( esp_aes_context *ctx, esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT); esp_aes_block(input, output); esp_aes_release_hardware(); + return 0; +} + +void esp_aes_encrypt( esp_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + esp_internal_aes_encrypt(ctx, input, output); } /* * AES-ECB block decryption */ -void esp_aes_decrypt( esp_aes_context *ctx, +int esp_internal_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) { @@ -177,6 +185,14 @@ void esp_aes_decrypt( esp_aes_context *ctx, esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT); esp_aes_block(input, output); esp_aes_release_hardware(); + return 0; +} + +void esp_aes_decrypt( esp_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + esp_internal_aes_decrypt(ctx, input, output); } diff --git a/components/esp32/include/hwcrypto/aes.h b/components/esp32/include/hwcrypto/aes.h index 0bcd1f490c..cc0f560861 100644 --- a/components/esp32/include/hwcrypto/aes.h +++ b/components/esp32/include/hwcrypto/aes.h @@ -243,7 +243,10 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx, * \param input Plaintext block * \param output Output (ciphertext) block */ -void esp_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ); +int esp_internal_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ); + +/** Deprecated, see esp_aes_internal_encrypt */ +void esp_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated)); /** * \brief Internal AES block decryption function @@ -254,7 +257,10 @@ void esp_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsig * \param input Ciphertext block * \param output Output (plaintext) block */ -void esp_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ); +int esp_internal_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ); + +/** Deprecated, see esp_aes_internal_decrypt */ +void esp_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated)); #ifdef __cplusplus } diff --git a/components/mbedtls/port/include/aes_alt.h b/components/mbedtls/port/include/aes_alt.h index a4d0b70c3a..5c143f2c5a 100644 --- a/components/mbedtls/port/include/aes_alt.h +++ b/components/mbedtls/port/include/aes_alt.h @@ -47,8 +47,8 @@ typedef esp_aes_context mbedtls_aes_context; #if defined(MBEDTLS_CIPHER_MODE_CTR) #define mbedtls_aes_crypt_ctr esp_aes_crypt_ctr #endif -#define mbedtls_aes_encrypt esp_aes_encrypt -#define mbedtls_aes_decrypt esp_aes_decrypt +#define mbedtls_internal_aes_encrypt esp_internal_aes_encrypt +#define mbedtls_internal_aes_decrypt esp_internal_aes_decrypt #endif /* MBEDTLS_AES_ALT */ #ifdef __cplusplus diff --git a/components/wpa_supplicant/src/fast_crypto/fast_aes-unwrap.c b/components/wpa_supplicant/src/fast_crypto/fast_aes-unwrap.c index d6bfdfab15..fd4a49ff43 100644 --- a/components/wpa_supplicant/src/fast_crypto/fast_aes-unwrap.c +++ b/components/wpa_supplicant/src/fast_crypto/fast_aes-unwrap.c @@ -58,7 +58,10 @@ fast_aes_unwrap(const uint8_t *kek, int n, const uint8_t *cipher, uint8_t *plain os_memcpy(b, a, 8); b[7] ^= n * j + i; os_memcpy(b + 8, r, 8); - mbedtls_aes_decrypt(&ctx, b, b); + ret = mbedtls_internal_aes_decrypt(&ctx, b, b); + if (ret != 0) { + break; + } os_memcpy(a, b, 8); os_memcpy(r, b + 8, 8); r -= 8; @@ -77,5 +80,5 @@ fast_aes_unwrap(const uint8_t *kek, int n, const uint8_t *cipher, uint8_t *plain } } - return 0; + return ret; } diff --git a/components/wpa_supplicant/src/fast_crypto/fast_aes-wrap.c b/components/wpa_supplicant/src/fast_crypto/fast_aes-wrap.c index 01a98a3add..3b9eec1c16 100644 --- a/components/wpa_supplicant/src/fast_crypto/fast_aes-wrap.c +++ b/components/wpa_supplicant/src/fast_crypto/fast_aes-wrap.c @@ -61,7 +61,10 @@ int fast_aes_wrap(const uint8_t *kek, int n, const uint8_t *plain, uint8_t *ciph for (i = 1; i <= n; i++) { os_memcpy(b, a, 8); os_memcpy(b + 8, r, 8); - mbedtls_aes_encrypt(&ctx, b, b); + ret = mbedtls_internal_aes_encrypt(&ctx, b, b); + if (ret != 0) { + break; + } os_memcpy(a, b, 8); a[7] ^= n * j + i; os_memcpy(r, b + 8, 8); @@ -76,5 +79,5 @@ int fast_aes_wrap(const uint8_t *kek, int n, const uint8_t *plain, uint8_t *ciph * variables. */ - return 0; + return ret; } 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 index fb00760bdf..472e173262 100644 --- a/components/wpa_supplicant/src/fast_crypto/fast_crypto_internal-cipher.c +++ b/components/wpa_supplicant/src/fast_crypto/fast_crypto_internal-cipher.c @@ -136,7 +136,9 @@ int fast_crypto_cipher_encrypt(struct crypto_cipher *ctx, const uint8_t *plain, 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); + if (mbedtls_internal_aes_encrypt(&(fast_ctx->u.aes.ctx_enc), fast_ctx->u.aes.cbc, fast_ctx->u.aes.cbc) != 0) { + return -1; + } os_memcpy(crypt, fast_ctx->u.aes.cbc, AES_BLOCK_SIZE); plain += AES_BLOCK_SIZE; crypt += AES_BLOCK_SIZE; @@ -209,7 +211,9 @@ int fast_crypto_cipher_decrypt(struct crypto_cipher *ctx, const uint8_t *crypt, 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); + if (mbedtls_internal_aes_decrypt(&(fast_ctx->u.aes.ctx_dec), crypt, plain) != 0) { + return -1; + } 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); From 7dada45d60f31a8d29b3c6357f931366f987667a Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 8 May 2018 23:51:23 +0800 Subject: [PATCH 061/187] mbedtls: enable deprecation warnings when building unit tests --- components/mbedtls/Makefile.projbuild | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/mbedtls/Makefile.projbuild b/components/mbedtls/Makefile.projbuild index ec9d6f2ce7..cf49f9a1d5 100644 --- a/components/mbedtls/Makefile.projbuild +++ b/components/mbedtls/Makefile.projbuild @@ -2,3 +2,7 @@ # alternative config file CPPFLAGS += -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' +# Catch usage of deprecated mbedTLS functions when building tests +ifneq ("$(TEST_COMPONENTS_LIST)","") +CPPFLAGS += -DMBEDTLS_DEPRECATED_WARNING +endif From 800d9f00a8d8e926e5f51014acb7e18745daf082 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 4 May 2018 15:53:59 +0800 Subject: [PATCH 062/187] ci: add extra UT test job --- .gitlab-ci.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a0e579ea1a..b013c847d4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -890,6 +890,13 @@ UT_004_09: - UT_T1_1 - UT_psram +UT_004_10: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + - UT_psram + IT_001_01: <<: *test_template tags: From b7a5fef87149c55f861d7fd08edebd8d0c900bee Mon Sep 17 00:00:00 2001 From: zhiweijian Date: Thu, 10 May 2018 11:39:34 +0800 Subject: [PATCH 063/187] Component/bt: fix crash without SMP when deinit bluedroid - fix crash without SMP when bluedroid deinit - modify default menuconfig in blufi demo --- components/bt/bluedroid/btc/core/btc_main.c | 2 ++ examples/bluetooth/blufi/sdkconfig.defaults | 22 +++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/components/bt/bluedroid/btc/core/btc_main.c b/components/bt/bluedroid/btc/core/btc_main.c index b6c9606be6..df3bfc4001 100644 --- a/components/bt/bluedroid/btc/core/btc_main.c +++ b/components/bt/bluedroid/btc/core/btc_main.c @@ -44,7 +44,9 @@ static void btc_enable_bluetooth(void) static void btc_disable_bluetooth(void) { +#if (SMP_INCLUDED) btc_config_shut_down(); +#endif if (BTA_DisableBluetooth() != BTA_SUCCESS) { future_ready(*btc_main_get_future_p(BTC_MAIN_DISABLE_FUTURE), FUTURE_FAIL); } diff --git a/examples/bluetooth/blufi/sdkconfig.defaults b/examples/bluetooth/blufi/sdkconfig.defaults index dcf4ad2c2d..a0d1d3652f 100644 --- a/examples/bluetooth/blufi/sdkconfig.defaults +++ b/examples/bluetooth/blufi/sdkconfig.defaults @@ -5,3 +5,25 @@ # BT config # CONFIG_BT_ENABLED=y +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_0=y +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_1= +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 +CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI=y +CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4= +CONFIG_BLUEDROID_ENABLED=y +CONFIG_BLUEDROID_PINNED_TO_CORE_0=y +CONFIG_BLUEDROID_PINNED_TO_CORE_1= +CONFIG_BLUEDROID_PINNED_TO_CORE=0 +CONFIG_BTC_TASK_STACK_SIZE=3072 +CONFIG_BLUEDROID_MEM_DEBUG= +CONFIG_CLASSIC_BT_ENABLED= +CONFIG_GATTS_ENABLE=y +CONFIG_GATTC_ENABLE= +CONFIG_BLE_SMP_ENABLE= +CONFIG_BLE_ENABLE_SRVCHG_REG=y +CONFIG_BT_STACK_NO_LOG= +CONFIG_BT_ACL_CONNECTIONS=4 +CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST= +CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY= +CONFIG_SMP_ENABLE= +CONFIG_BT_RESERVE_DRAM=0x10000 From dfbc59f1c2047d6b16c7545f1bbfdd81559af4c6 Mon Sep 17 00:00:00 2001 From: baohongde Date: Thu, 10 May 2018 16:16:25 +0800 Subject: [PATCH 064/187] component/bt: Fix can't be connected if init SPP again after SPP deinit --- components/bt/bluedroid/btc/profile/std/spp/btc_spp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c b/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c index dcab978657..c8b58d4d4b 100644 --- a/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c +++ b/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c @@ -353,6 +353,7 @@ static void btc_spp_uninit(void) } for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) { if (spp_local_param.spp_slots[i] != NULL && !(spp_local_param.spp_slots[i]->connected)) { + BTA_JvRfcommStopServer(spp_local_param.spp_slots[i]->sdp_handle, (void *)spp_local_param.spp_slots[i]->id); BTA_JvDeleteRecord(spp_local_param.spp_slots[i]->sdp_handle); BTA_JvFreeChannel(spp_local_param.spp_slots[i]->scn, BTA_JV_CONN_TYPE_RFCOMM); free_spp_slot(spp_local_param.spp_slots[i]); From be76260d812293d2402bbd8ffd439ce5f0b7ffa0 Mon Sep 17 00:00:00 2001 From: zhangyanjiao Date: Thu, 10 May 2018 16:22:43 +0800 Subject: [PATCH 065/187] wifi: fix some potential thread safe issue change some API function to throw event: esp_wifi_deauth_sta esp_wifi_get_country esp_wifi_ap_get_sta_list esp_wifi_sta_get_ap_info esp_wifi_stop esp_wifi_get_channel esp_wifi_get_protocol esp_wifi_get_bandwidth --- components/esp32/lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp32/lib b/components/esp32/lib index 92a091649f..ab80b0b980 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 92a091649f7c8476580177e2a769b15d9c4c191f +Subproject commit ab80b0b980997af5c224f2316a33486fe4af7258 From feb64c3be657a4e04aae6061a0c87bf03f6ea31a Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 10 May 2018 17:18:17 +0800 Subject: [PATCH 066/187] ledc driver: Clarify logging of function argument errors Some parameter errors did not specify which parameter was invalid. Adds a new macro to name the invalid param. --- components/driver/ledc.c | 110 ++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 59 deletions(-) diff --git a/components/driver/ledc.c b/components/driver/ledc.c index 0365deb2ea..05ab95499d 100644 --- a/components/driver/ledc.c +++ b/components/driver/ledc.c @@ -28,10 +28,12 @@ static const char* LEDC_TAG = "ledc"; static portMUX_TYPE ledc_spinlock = portMUX_INITIALIZER_UNLOCKED; #define LEDC_CHECK(a, str, ret_val) \ if (!(a)) { \ - ESP_LOGE(LEDC_TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \ + ESP_LOGE(LEDC_TAG, "%s(%d): %s", __FUNCTION__, __LINE__, str); \ return (ret_val); \ } +#define LEDC_ARG_CHECK(a, param) LEDC_CHECK(a, param " argument is invalid", ESP_ERR_INVALID_ARG) + typedef struct { uint16_t speed_mode; uint16_t direction; @@ -53,18 +55,8 @@ static ledc_isr_handle_t s_ledc_fade_isr_handle = NULL; #define LEDC_STEP_NUM_MAX (1023) #define LEDC_DUTY_DECIMAL_BIT_NUM (4) -#define LEDC_MODE_ERR_STR "LEDC mode error" -#define LEDC_TIMER_ERR_STR "LEDC timer error" -#define LEDC_CHANNEL_ERR_STR "LEDC channel error" -#define LEDC_SCALE_ERR_STR "LEDC scale error" -#define LEDC_CYCLE_ERR_STR "LEDC cycle num error" -#define LEDC_GPIO_OUT_ERR_STR "LEDC GPIO output number error" -#define LEDC_FADE_DIR_ERR_STR "LEDC fade direction error" -#define LEDC_FADE_SERVICE_ERR_STR "LEDC fade service not installed" -#define LEDC_FADE_TARGET_ERR_STR "LEDC fade target duty error" -#define LEDC_FADE_INSTALLED_ERR_STR "LEDC fade service already installed" -#define LEDC_FADE_MODE_ERR_STR "LEDC fade mode error" -#define LEDC_FADE_INIT_ERROR_STR "LEDC fade channel init error" +static const char *LEDC_FADE_SERVICE_ERR_STR = "LEDC fade service not installed"; +static const char *LEDC_FADE_INIT_ERROR_STR = "LEDC fade channel init error"; static void ledc_ls_timer_update(ledc_mode_t speed_mode, ledc_timer_t timer_sel) { @@ -83,8 +75,8 @@ static IRAM_ATTR void ledc_ls_channel_update(ledc_mode_t speed_mode, ledc_channe esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t clock_divider, uint32_t duty_resolution, ledc_clk_src_t clk_src) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(timer_sel <= LEDC_TIMER_3, LEDC_TIMER_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(timer_sel <= LEDC_TIMER_3, "timer_sel") portENTER_CRITICAL(&ledc_spinlock); LEDC.timer_group[speed_mode].timer[timer_sel].conf.clock_divider = clock_divider; LEDC.timer_group[speed_mode].timer[timer_sel].conf.tick_sel = clk_src; @@ -113,8 +105,8 @@ static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t timer_idx) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(timer_idx <= LEDC_TIMER_3, LEDC_TIMER_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(timer_idx <= LEDC_TIMER_3, "timer_idx"); portENTER_CRITICAL(&ledc_spinlock); LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel = timer_idx; ledc_ls_channel_update(speed_mode, channel); @@ -124,8 +116,8 @@ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, uint32_t timer_sel) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(timer_sel <= LEDC_TIMER_3, LEDC_TIMER_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(timer_sel <= LEDC_TIMER_3, "timer_sel"); portENTER_CRITICAL(&ledc_spinlock); LEDC.timer_group[speed_mode].timer[timer_sel].conf.rst = 1; LEDC.timer_group[speed_mode].timer[timer_sel].conf.rst = 0; @@ -136,8 +128,8 @@ esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, uint32_t timer_sel) esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, uint32_t timer_sel) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(timer_sel <= LEDC_TIMER_3, LEDC_TIMER_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(timer_sel <= LEDC_TIMER_3, "timer_sel"); portENTER_CRITICAL(&ledc_spinlock); LEDC.timer_group[speed_mode].timer[timer_sel].conf.pause = 1; ledc_ls_timer_update(speed_mode, timer_sel); @@ -147,8 +139,8 @@ esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, uint32_t timer_sel) esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(timer_sel <= LEDC_TIMER_3, LEDC_TIMER_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(timer_sel <= LEDC_TIMER_3, "timer_sel"); portENTER_CRITICAL(&ledc_spinlock); LEDC.timer_group[speed_mode].timer[timer_sel].conf.pause = 0; ledc_ls_timer_update(speed_mode, timer_sel); @@ -158,7 +150,7 @@ esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel) static esp_err_t ledc_enable_intr_type(ledc_mode_t speed_mode, uint32_t channel, ledc_intr_type_t type) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); uint32_t value; uint32_t intr_type = type; portENTER_CRITICAL(&ledc_spinlock); @@ -179,7 +171,7 @@ static esp_err_t ledc_enable_intr_type(ledc_mode_t speed_mode, uint32_t channel, esp_err_t ledc_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, ledc_isr_handle_t *handle) { esp_err_t ret; - LEDC_CHECK(fn, "ledc isr null", ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(fn, "fn"); portENTER_CRITICAL(&ledc_spinlock); ret = esp_intr_alloc(ETS_LEDC_INTR_SOURCE, intr_alloc_flags, fn, arg, handle); portEXIT_CRITICAL(&ledc_spinlock); @@ -192,7 +184,7 @@ esp_err_t ledc_timer_config(const ledc_timer_config_t* timer_conf) int duty_resolution = timer_conf->duty_resolution; int timer_num = timer_conf->timer_num; int speed_mode = timer_conf->speed_mode; - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); periph_module_enable(PERIPH_LEDC_MODULE); if (freq_hz == 0 || duty_resolution == 0 || duty_resolution > LEDC_TIMER_15_BIT) { ESP_LOGE(LEDC_TAG, "freq_hz=%u duty_resolution=%u", freq_hz, duty_resolution); @@ -238,9 +230,9 @@ esp_err_t ledc_timer_config(const ledc_timer_config_t* timer_conf) esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc_channel) { - LEDC_CHECK(ledc_channel <= LEDC_CHANNEL_7, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), LEDC_GPIO_OUT_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(ledc_channel <= LEDC_CHANNEL_7, "ledc_channel"); + LEDC_ARG_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "gpio_num"); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO); gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT); if (speed_mode == LEDC_HIGH_SPEED_MODE) { @@ -259,10 +251,10 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t* ledc_conf) uint32_t timer_select = ledc_conf->timer_sel; uint32_t intr_type = ledc_conf->intr_type; uint32_t duty = ledc_conf->duty; - LEDC_CHECK(ledc_channel <= LEDC_CHANNEL_7, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), LEDC_GPIO_OUT_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(timer_select <= LEDC_TIMER_3, LEDC_TIMER_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(ledc_channel <= LEDC_CHANNEL_7, "ledc_channel"); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "gpio_num"); + LEDC_ARG_CHECK(timer_select <= LEDC_TIMER_3, "timer_select"); periph_module_enable(PERIPH_LEDC_MODULE); esp_err_t ret = ESP_OK; /*set channel parameters*/ @@ -291,8 +283,8 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t* ledc_conf) esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(channel <= LEDC_CHANNEL_7, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(channel <= LEDC_CHANNEL_7, "channel"); portENTER_CRITICAL(&ledc_spinlock); LEDC.channel_group[speed_mode].channel[channel].conf0.sig_out_en = 1; LEDC.channel_group[speed_mode].channel[channel].conf1.duty_start = 1; @@ -303,8 +295,8 @@ esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel) esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idle_level) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(channel <= LEDC_CHANNEL_7, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(channel <= LEDC_CHANNEL_7, "channel"); portENTER_CRITICAL(&ledc_spinlock); LEDC.channel_group[speed_mode].channel[channel].conf0.idle_lv = idle_level & 0x1; LEDC.channel_group[speed_mode].channel[channel].conf0.sig_out_en = 0; @@ -317,13 +309,12 @@ esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idl esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, ledc_duty_direction_t fade_direction, uint32_t step_num, uint32_t duty_cyle_num, uint32_t duty_scale) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(channel <= LEDC_CHANNEL_7, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(fade_direction <= LEDC_DUTY_DIR_INCREASE, LEDC_FADE_DIR_ERR_STR, ESP_ERR_INVALID_ARG); - if (step_num > LEDC_DUTY_NUM_HSCH0_V || duty_cyle_num > LEDC_DUTY_CYCLE_HSCH0_V || duty_scale > LEDC_DUTY_SCALE_HSCH0_V) { - ESP_LOGE(LEDC_TAG, "step_num=%u duty_cyle_num=%u duty_scale=%u", step_num, duty_cyle_num, duty_scale); - return ESP_ERR_INVALID_ARG; - } + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(channel <= LEDC_CHANNEL_7, "channel"); + LEDC_ARG_CHECK(fade_direction <= LEDC_DUTY_DIR_INCREASE, "fade_direction"); + LEDC_ARG_CHECK(step_num <= LEDC_DUTY_NUM_HSCH0_V, "step_num"); + LEDC_ARG_CHECK(duty_cyle_num <= LEDC_DUTY_CYCLE_HSCH0_V, "duty_cycle_num"); + LEDC_ARG_CHECK(duty_scale <= LEDC_DUTY_SCALE_HSCH0_V, "duty_scale"); if (s_ledc_fade_rec[speed_mode][channel]) { ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_DISABLE); } @@ -341,8 +332,8 @@ esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(channel <= LEDC_CHANNEL_7, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(channel <= LEDC_CHANNEL_7, "channel"); if (s_ledc_fade_rec[speed_mode][channel]) { ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_DISABLE); } @@ -360,14 +351,14 @@ esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t uint32_t ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, (LEDC_ERR_DUTY)); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); uint32_t duty = (LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> 4); return duty; } esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t freq_hz) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); portENTER_CRITICAL(&ledc_spinlock); esp_err_t ret = ESP_OK; uint32_t clock_divider = 0; @@ -390,7 +381,7 @@ esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, (0)); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); portENTER_CRITICAL(&ledc_spinlock); uint32_t freq = 0; uint32_t timer_source_clk = LEDC.timer_group[speed_mode].timer[timer_num].conf.tick_sel; @@ -516,13 +507,14 @@ static esp_err_t ledc_fade_channel_init_check(ledc_mode_t speed_mode, ledc_chann esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int max_fade_time_ms) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(channel < LEDC_CHANNEL_MAX, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel"); + LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK, LEDC_FADE_INIT_ERROR_STR, ESP_FAIL); int timer_sel = LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel; uint32_t max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_resolution)) - 1; - LEDC_CHECK(target_duty <= max_duty, LEDC_FADE_TARGET_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(target_duty <= max_duty, "target_duty"); + uint32_t freq = ledc_get_freq(speed_mode, timer_sel); uint32_t duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM; uint32_t duty_delta = target_duty > duty_cur ? target_duty - duty_cur : duty_cur - target_duty; @@ -547,15 +539,15 @@ esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int scale, int cycle_num) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, LEDC_MODE_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(channel < LEDC_CHANNEL_MAX, LEDC_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel"); LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL); - LEDC_CHECK(scale > 0, LEDC_SCALE_ERR_STR, ESP_ERR_INVALID_ARG); - LEDC_CHECK(cycle_num > 0, LEDC_CYCLE_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(scale > 0, "scale"); + LEDC_ARG_CHECK(cycle_num > 0, "cycle_num"); int timer_sel = LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel; uint32_t max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_resolution)) - 1; - LEDC_CHECK(target_duty <= max_duty, LEDC_FADE_TARGET_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(target_duty <= max_duty, "target_duty"); //disable the interrupt, so the operation will not mess up ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_DISABLE); @@ -631,7 +623,7 @@ void ledc_fade_func_uninstall() esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t wait_done) { LEDC_CHECK(s_ledc_fade_rec != NULL, LEDC_FADE_SERVICE_ERR_STR, ESP_ERR_INVALID_STATE); - LEDC_CHECK(wait_done < LEDC_FADE_MAX, LEDC_FADE_MODE_ERR_STR, ESP_ERR_INVALID_ARG); + LEDC_ARG_CHECK(wait_done < LEDC_FADE_MAX, "wait_done"); xSemaphoreTake(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux, portMAX_DELAY); if (wait_done == LEDC_FADE_WAIT_DONE) { s_ledc_fade_rec[speed_mode][channel]->mode = LEDC_FADE_WAIT_DONE; From b2a1a79eb42b6dd0668a7171d130da4bfba82799 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Thu, 10 May 2018 18:00:11 +0530 Subject: [PATCH 067/187] i2s: fix issue in dma descriptor allocation if SPIRAM is enabled It has been observed that, if external SPIRAM is enabled, then under certain scenarios (e.g. internal memory being too much fragmented), I2S tx/rx descriptors can land in external SPIRAM and hence resulting in failure in DMA. Adding explicit capability to allocate in only DMA capable memory. Signed-off-by: Mahavir Jain --- components/driver/i2s.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/driver/i2s.c b/components/driver/i2s.c index 6257f46368..b3d296af8e 100755 --- a/components/driver/i2s.c +++ b/components/driver/i2s.c @@ -487,6 +487,7 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) lldesc_t *finish_desc; if (i2s_reg->int_st.out_dscr_err || i2s_reg->int_st.in_dscr_err) { + ESP_EARLY_LOGE(I2S_TAG, "dma error, interrupt status: 0x%08x", i2s_reg->int_st.val); if (p_i2s->i2s_queue) { i2s_event.type = I2S_EVENT_DMA_ERROR; if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) { @@ -581,14 +582,13 @@ static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, in memset(dma->buf, 0, sizeof(char*) * dma_buf_count); for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) { - dma->buf[bux_idx] = (char*) malloc(dma_buf_len * sample_size); + dma->buf[bux_idx] = (char*) heap_caps_calloc(1, dma_buf_len * sample_size, MALLOC_CAP_DMA); if (dma->buf[bux_idx] == NULL) { ESP_LOGE(I2S_TAG, "Error malloc dma buffer"); i2s_destroy_dma_queue(i2s_num, dma); return NULL; } ESP_LOGD(I2S_TAG, "Addr[%d] = %d", bux_idx, (int)dma->buf[bux_idx]); - memset(dma->buf[bux_idx], 0, dma_buf_len * sample_size); } dma->desc = (lldesc_t**) malloc(sizeof(lldesc_t*) * dma_buf_count); @@ -598,7 +598,7 @@ static i2s_dma_t *i2s_create_dma_queue(i2s_port_t i2s_num, int dma_buf_count, in return NULL; } for (bux_idx = 0; bux_idx < dma_buf_count; bux_idx++) { - dma->desc[bux_idx] = (lldesc_t*) malloc(sizeof(lldesc_t)); + dma->desc[bux_idx] = (lldesc_t*) heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_DMA); if (dma->desc[bux_idx] == NULL) { ESP_LOGE(I2S_TAG, "Error malloc dma description entry"); i2s_destroy_dma_queue(i2s_num, dma); From 12f707932f359daf16eb1ccd3d2ef111159ed877 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Sat, 17 Mar 2018 12:26:08 +0800 Subject: [PATCH 068/187] log: clean up docs, clarify esp_log_level_set usage Closes https://github.com/espressif/esp-idf/issues/1713 --- components/log/README.rst | 22 ++++++++++--------- components/log/include/esp_log.h | 37 ++++++++++++++++---------------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/components/log/README.rst b/components/log/README.rst index 0a9d876f46..034c32d792 100644 --- a/components/log/README.rst +++ b/components/log/README.rst @@ -4,11 +4,15 @@ Logging library Overview -------- -Log library has two ways of managing log verbosity: compile time, set via menuconfig; and runtime, using ``esp_log_level_set`` function. +Log library has two ways of managing log verbosity: compile time, set via menuconfig; and runtime, using :cpp:func:`esp_log_level_set` function. -At compile time, filtering is done using ``CONFIG_LOG_DEFAULT_LEVEL`` macro, set via menuconfig. All logging statements for levels higher than ``CONFIG_LOG_DEFAULT_LEVEL`` will be removed by the preprocessor. +The log levels are Error, Warning, Info, Debug, and Verbose (from lowest to highest level of verbosity). -At run time, all logs below ``CONFIG_LOG_DEFAULT_LEVEL`` are enabled by default. ``esp_log_level_set`` function may be used to set logging level per module. Modules are identified by their tags, which are human-readable ASCII zero-terminated strings. +At compile time, filtering is done using :ref:`CONFIG_LOG_DEFAULT_LEVEL` option, set via menuconfig. All logging statements for levels higher than :ref:`CONFIG_LOG_DEFAULT_LEVEL` will be removed by the preprocessor. + +At run time, all logs below :ref:`CONFIG_LOG_DEFAULT_LEVEL` are enabled by default. :cpp:func:`esp_log_level_set` function may be used to reduce logging level per module. Modules are identified by their tags, which are human-readable ASCII zero-terminated strings. + +Note that :cpp:func:`esp_log_level_set` can not increase logging level beyound that set by :ref:`CONFIG_LOG_DEFAULT_LEVEL`. To increase log level for a specific file at compile time, `LOG_LOCAL_LEVEL` macro can be used (see below for details). How to use this library ----------------------- @@ -27,15 +31,13 @@ then use one of logging macros to produce output, e.g: Several macros are available for different verbosity levels: -* ``ESP_LOGE`` - error +* ``ESP_LOGE`` - error (lowest) * ``ESP_LOGW`` - warning * ``ESP_LOGI`` - info * ``ESP_LOGD`` - debug -* ``ESP_LOGV`` - verbose +* ``ESP_LOGV`` - verbose (highest) -Additionally there is an _EARLY_ variant for each of these macros (e.g. ``ESP_EARLY_LOGE``). These variants can run in startup code, before heap allocator and syscalls have been initialized. When compiling bootloader, normal ``ESP_LOGx`` macros fall back to the same implementation as ``ESP_EARLY_LOGx`` macros. So the only place where ``ESP_EARLY_LOGx`` have to be used explicitly is the early startup code, such as heap allocator initialization code. - -(Note that such distinction would not have been necessary if we would have an ``ets_vprintf`` function in the ROM. Then it would be possible to switch implementation from _EARLY_ version to normal version on the fly. Unfortunately, ``ets_vprintf`` in ROM has been inlined by the compiler into ``ets_printf``, so it is not accessible outside.) +Additionally there is an ``_EARLY`` variant for each of these macros (e.g. :c:macro:`ESP_EARLY_LOGE`). These variants can run in startup code, before heap allocator and syscalls have been initialized. When compiling bootloader, normal ``ESP_LOGx`` macros fall back to the same implementation as ``ESP_EARLY_LOGx`` macros. So the only place where ``ESP_EARLY_LOGx`` have to be used explicitly is the early startup code, such as heap allocator initialization code. To override default verbosity level at file or component scope, define ``LOG_LOCAL_LEVEL`` macro. At file scope, define it before including ``esp_log.h``, e.g.: @@ -51,7 +53,7 @@ At component scope, define it in component makefile: CFLAGS += -D LOG_LOCAL_LEVEL=ESP_LOG_DEBUG -To configure logging output per module at runtime, add calls to ``esp_log_level_set`` function: +To configure logging output per module at runtime, add calls to :cpp:func:`esp_log_level_set` function: .. code-block:: c @@ -62,5 +64,5 @@ To configure logging output per module at runtime, add calls to ``esp_log_level_ Logging to Host via JTAG ^^^^^^^^^^^^^^^^^^^^^^^^ -By default logging library uses vprintf-like function to write formatted output to dedicated UART. With calling a simple API, all log output my be routed to JTAG instead, and make the logging several times faster. For details please refer to section :ref:`app_trace-logging-to-host`. +By default logging library uses vprintf-like function to write formatted output to dedicated UART. By calling a simple API, all log output may be routed to JTAG instead, making logging several times faster. For details please refer to section :ref:`app_trace-logging-to-host`. diff --git a/components/log/include/esp_log.h b/components/log/include/esp_log.h index 1c796cfff6..e57aabbdd5 100644 --- a/components/log/include/esp_log.h +++ b/components/log/include/esp_log.h @@ -44,10 +44,18 @@ typedef int (*vprintf_like_t)(const char *, va_list); * * If logging for given component has already been enabled, changes previous setting. * + * Note that this function can not raise log level above the level set using + * CONFIG_LOG_DEFAULT_LEVEL setting in menuconfig. + * + * To raise log level above the default one for a given file, define + * LOG_LOCAL_LEVEL to one of the ESP_LOG_* values, before including + * esp_log.h in this file. + * * @param tag Tag of the log entries to enable. Must be a non-NULL zero terminated string. * Value "*" resets log level for all tags to the given value. * - * @param level Selects log level to enable. Only logs at this and lower levels will be shown. + * @param level Selects log level to enable. Only logs at this and lower verbosity + * levels will be shown. */ void esp_log_level_set(const char* tag, esp_log_level_t level); @@ -98,6 +106,8 @@ uint32_t esp_log_early_timestamp(void); */ void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__ ((format (printf, 3, 4))); +/** @cond */ + #include "esp_log_internal.h" #ifndef LOG_LOCAL_LEVEL @@ -108,16 +118,15 @@ void esp_log_write(esp_log_level_t level, const char* tag, const char* format, . #endif #endif +/** @endcond */ + /** * @brief Log a buffer of hex bytes at specified level, separated into 16 bytes each line. * * @param tag description tag - * * @param buffer Pointer to the buffer array - * * @param buff_len length of buffer in bytes - * - * @param level level of the log + * @param level level of the log * */ #define ESP_LOG_BUFFER_HEX_LEVEL( tag, buffer, buff_len, level ) \ @@ -131,12 +140,9 @@ void esp_log_write(esp_log_level_t level, const char* tag, const char* format, . * @brief Log a buffer of characters at specified level, separated into 16 bytes each line. Buffer should contain only printable characters. * * @param tag description tag - * * @param buffer Pointer to the buffer array - * * @param buff_len length of buffer in bytes - * - * @param level level of the log + * @param level level of the log * */ #define ESP_LOG_BUFFER_CHAR_LEVEL( tag, buffer, buff_len, level ) \ @@ -158,11 +164,8 @@ void esp_log_write(esp_log_level_t level, const char* tag, const char* format, . * It is highly recommend to use terminals with over 102 text width. * * @param tag description tag - * * @param buffer Pointer to the buffer array - * * @param buff_len length of buffer in bytes - * * @param level level of the log */ #define ESP_LOG_BUFFER_HEXDUMP( tag, buffer, buff_len, level ) \ @@ -176,9 +179,7 @@ void esp_log_write(esp_log_level_t level, const char* tag, const char* format, . * @brief Log a buffer of hex bytes at Info level * * @param tag description tag - * * @param buffer Pointer to the buffer array - * * @param buff_len length of buffer in bytes * * @see ``esp_log_buffer_hex_level`` @@ -195,9 +196,7 @@ void esp_log_write(esp_log_level_t level, const char* tag, const char* format, . * @brief Log a buffer of characters at Info level. Buffer should contain only printable characters. * * @param tag description tag - * * @param buffer Pointer to the buffer array - * * @param buff_len length of buffer in bytes * * @see ``esp_log_buffer_char_level`` @@ -210,6 +209,7 @@ void esp_log_write(esp_log_level_t level, const char* tag, const char* format, . }\ } while(0) +/** @cond */ //to be back compatible #define esp_log_buffer_hex ESP_LOG_BUFFER_HEX @@ -243,6 +243,8 @@ void esp_log_write(esp_log_level_t level, const char* tag, const char* format, . #define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%d) %s: " format LOG_RESET_COLOR "\n" +/** @endcond */ + /// macro to output logs in startup code, before heap allocator and syscalls have been initialized. log at ``ESP_LOG_ERROR`` level. @see ``printf``,``ESP_LOGE`` #define ESP_EARLY_LOGE( tag, format, ... ) ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_ERROR, E, ##__VA_ARGS__) /// macro to output logs in startup code at ``ESP_LOG_WARN`` level. @see ``ESP_EARLY_LOGE``,``ESP_LOGE``, ``printf`` @@ -287,11 +289,8 @@ void esp_log_write(esp_log_level_t level, const char* tag, const char* format, . /** runtime macro to output logs at a specified level. * * @param tag tag of the log, which can be used to change the log level by ``esp_log_level_set`` at runtime. - * * @param level level of the output log. - * * @param format format of the output log. see ``printf`` - * * @param ... variables to be replaced into the log. see ``printf`` * * @see ``printf`` From 733ff15719ec30e3fbb76aa5475ccfa2acc208af Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Thu, 10 May 2018 14:26:47 +0200 Subject: [PATCH 069/187] VFS: use O_APPEND flag of open() correctly Closes https://github.com/espressif/esp-idf/pull/1455 --- components/fatfs/src/vfs_fat.c | 25 +++++- components/spiffs/esp_spiffs.c | 3 +- components/vfs/test/test_vfs_append.c | 116 ++++++++++++++++++++++++++ 3 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 components/vfs/test/test_vfs_append.c diff --git a/components/fatfs/src/vfs_fat.c b/components/fatfs/src/vfs_fat.c index 556492e3ed..1e059e134e 100644 --- a/components/fatfs/src/vfs_fat.c +++ b/components/fatfs/src/vfs_fat.c @@ -32,6 +32,7 @@ typedef struct { FATFS fs; /* fatfs library FS structure */ char tmp_path_buf[FILENAME_MAX+3]; /* temporary buffer used to prepend drive name to the path */ char tmp_path_buf2[FILENAME_MAX+3]; /* as above; used in functions which take two path arguments */ + bool *o_append; /* O_APPEND is stored here for each max_files entries (because O_APPEND is not compatible with FA_OPEN_APPEND) */ FIL files[0]; /* array with max_files entries; must be the final member of the structure */ } vfs_fat_ctx_t; @@ -147,12 +148,18 @@ esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, siz if (fat_ctx == NULL) { return ESP_ERR_NO_MEM; } + fat_ctx->o_append = malloc(max_files * sizeof(bool)); + if (fat_ctx->o_append == NULL) { + free(fat_ctx); + return ESP_ERR_NO_MEM; + } fat_ctx->max_files = max_files; strlcpy(fat_ctx->fat_drive, fat_drive, sizeof(fat_ctx->fat_drive) - 1); strlcpy(fat_ctx->base_path, base_path, sizeof(fat_ctx->base_path) - 1); esp_err_t err = esp_vfs_register(base_path, &vfs, fat_ctx); if (err != ESP_OK) { + free(fat_ctx->o_append); free(fat_ctx); return err; } @@ -180,6 +187,7 @@ esp_err_t esp_vfs_fat_unregister_path(const char* base_path) return err; } _lock_close(&fat_ctx->lock); + free(fat_ctx->o_append); free(fat_ctx); s_fat_ctxs[ctx] = NULL; return ESP_OK; @@ -306,6 +314,13 @@ static int vfs_fat_open(void* ctx, const char * path, int flags, int mode) fd = -1; goto out; } + // O_APPEND need to be stored because it is not compatible with FA_OPEN_APPEND: + // - FA_OPEN_APPEND means to jump to the end of file only after open() + // - O_APPEND means to jump to the end only before each write() + // Other VFS drivers handles O_APPEND well (to the best of my knowledge), + // therefore this flag is stored here (at this VFS level) in order to save + // memory. + fat_ctx->o_append[fd] = (flags & O_APPEND) == O_APPEND; out: _lock_release(&fat_ctx->lock); return fd; @@ -315,8 +330,16 @@ static ssize_t vfs_fat_write(void* ctx, int fd, const void * data, size_t size) { vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; FIL* file = &fat_ctx->files[fd]; + FRESULT res; + if (fat_ctx->o_append[fd]) { + if ((res = f_lseek(file, f_size(file))) != FR_OK) { + ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); + errno = fresult_to_errno(res); + return -1; + } + } unsigned written = 0; - FRESULT res = f_write(file, data, size, &written); + res = f_write(file, data, size, &written); if (res != FR_OK) { ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); errno = fresult_to_errno(res); diff --git a/components/spiffs/esp_spiffs.c b/components/spiffs/esp_spiffs.c index c344e57764..d5fb180038 100644 --- a/components/spiffs/esp_spiffs.c +++ b/components/spiffs/esp_spiffs.c @@ -522,7 +522,8 @@ static int spiffs_mode_conv(int m) res |= SPIFFS_O_CREAT | SPIFFS_O_EXCL; } else if ((m & O_CREAT) && (m & O_TRUNC)) { res |= SPIFFS_O_CREAT | SPIFFS_O_TRUNC; - } else if (m & O_APPEND) { + } + if (m & O_APPEND) { res |= SPIFFS_O_CREAT | SPIFFS_O_APPEND; } return res; diff --git a/components/vfs/test/test_vfs_append.c b/components/vfs/test/test_vfs_append.c new file mode 100644 index 0000000000..d12d334e02 --- /dev/null +++ b/components/vfs/test/test_vfs_append.c @@ -0,0 +1,116 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include "unity.h" +#include "esp_vfs.h" +#include "esp_vfs_fat.h" +#include "esp_spiffs.h" +#include "wear_levelling.h" + +#define TEST_PARTITION_LABEL "flash_test" + +#define OPEN_MODE 0 +#define MSG1 "Hello" +#define MSG2 " " +#define MSG3 "world!" + +static inline void test_write(int fd, const char *str, const char *msg) +{ + TEST_ASSERT_EQUAL_MESSAGE(strlen(str), write(fd, str, strlen(str)), msg); +} + +static inline void test_read(int fd, const char *str, const char *msg) +{ + char buf[strlen(str)]; + TEST_ASSERT_EQUAL_MESSAGE(strlen(str), read(fd, buf, strlen(str)), msg); + TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(str, buf, strlen(str), msg); +} + +static inline void test_read_fails(int fd, const char *msg) +{ + char buf; + TEST_ASSERT_EQUAL_MESSAGE(0, read(fd, &buf, 1), msg); +} + +static void test_append(const char *path) +{ + int fd = open(path, O_RDWR | O_APPEND | O_CREAT | O_TRUNC, OPEN_MODE); + TEST_ASSERT_NOT_EQUAL(-1, fd); + + test_write(fd, MSG1, "write MSG1"); + test_read_fails(fd, "read fails MSG1"); + lseek(fd, 0, SEEK_SET); + test_read(fd, MSG1, "read MSG1"); + + lseek(fd, 0, SEEK_SET); + test_write(fd, MSG2, "write MSG2"); + test_read_fails(fd, "read fails MSG2"); //because write moved the pointer + lseek(fd, 0, SEEK_SET); + test_read(fd, MSG1 MSG2, "read MSG1 + MSG2"); + + TEST_ASSERT_NOT_EQUAL(-1, close(fd)); + fd = open(path, O_RDWR | O_APPEND, OPEN_MODE); + TEST_ASSERT_NOT_EQUAL(-1, fd); + + //after reopening the pointer should be at the beginning + test_read(fd, MSG1 MSG2, "read reopening"); + + lseek(fd, strlen(MSG1), SEEK_SET); + test_read(fd, MSG2, "read MSG2"); + lseek(fd, strlen(MSG1), SEEK_SET); + test_write(fd, MSG3, "write MSG3"); + test_read_fails(fd, "read fails MSG3"); //because write moved the pointer + lseek(fd, strlen(MSG1), SEEK_SET); + test_read(fd, MSG2 MSG3, "read MSG2 + MSG3"); + + lseek(fd, 0, SEEK_SET); + test_read(fd, MSG1 MSG2 MSG3, "read MSG1 + MSG2 + MSG3"); + + TEST_ASSERT_NOT_EQUAL(-1, close(fd)); + TEST_ASSERT_NOT_EQUAL(-1, unlink(path)); +} + +TEST_CASE("open() with O_APPEND on FATFS works well", "[vfs][FATFS]") +{ + wl_handle_t test_wl_handle; + + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = true, + .max_files = 2 + }; + TEST_ESP_OK(esp_vfs_fat_spiflash_mount("/spiflash", NULL, &mount_config, &test_wl_handle)); + + test_append("/spiflash/file.txt"); + + TEST_ESP_OK(esp_vfs_fat_spiflash_unmount("/spiflash", test_wl_handle)); +} + +TEST_CASE("open() with O_APPEND on SPIFFS works well", "[vfs][spiffs]") +{ + esp_vfs_spiffs_conf_t conf = { + .base_path = "/spiffs", + .partition_label = TEST_PARTITION_LABEL, + .max_files = 2, + .format_if_mount_failed = true + }; + TEST_ESP_OK(esp_vfs_spiffs_register(&conf)); + + test_append("/spiffs/file.txt"); + + TEST_ESP_OK(esp_vfs_spiffs_unregister(TEST_PARTITION_LABEL)); +} From 0033c3ef3a0a326340a9640de69c29312f037391 Mon Sep 17 00:00:00 2001 From: XiaXiaotian Date: Mon, 9 Apr 2018 14:29:53 +0800 Subject: [PATCH 070/187] refactor smartconfig move wifi part to wifi lib and lwip part to idf --- components/esp32/lib | 2 +- .../component.mk | 0 .../include/smartconfig_ack.h} | 4 +-- .../smartconfig_ack.c} | 26 ++++++++++--------- 4 files changed, 17 insertions(+), 15 deletions(-) rename components/{smartconfig => smartconfig_ack}/component.mk (100%) rename components/{smartconfig/include/smartconfig.h => smartconfig_ack/include/smartconfig_ack.h} (97%) rename components/{smartconfig/smartconfig.c => smartconfig_ack/smartconfig_ack.c} (88%) mode change 100644 => 100755 diff --git a/components/esp32/lib b/components/esp32/lib index ab80b0b980..efae38d4d6 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit ab80b0b980997af5c224f2316a33486fe4af7258 +Subproject commit efae38d4d6f43c59e1570fe6dd0f483b26cbd7e7 diff --git a/components/smartconfig/component.mk b/components/smartconfig_ack/component.mk similarity index 100% rename from components/smartconfig/component.mk rename to components/smartconfig_ack/component.mk diff --git a/components/smartconfig/include/smartconfig.h b/components/smartconfig_ack/include/smartconfig_ack.h similarity index 97% rename from components/smartconfig/include/smartconfig.h rename to components/smartconfig_ack/include/smartconfig_ack.h index 1723a775b8..be49fd3bd1 100644 --- a/components/smartconfig/include/smartconfig.h +++ b/components/smartconfig_ack/include/smartconfig_ack.h @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef SMARTCONFIG_H -#define SMARTCONFIG_H +#ifndef SMARTCONFIG_ACK_H +#define SMARTCONFIG_ACK_H #ifdef __cplusplus extern "C" { diff --git a/components/smartconfig/smartconfig.c b/components/smartconfig_ack/smartconfig_ack.c old mode 100644 new mode 100755 similarity index 88% rename from components/smartconfig/smartconfig.c rename to components/smartconfig_ack/smartconfig_ack.c index a0636d0789..be5c4a676d --- a/components/smartconfig/smartconfig.c +++ b/components/smartconfig_ack/smartconfig_ack.c @@ -25,7 +25,7 @@ #include "esp_log.h" #include "esp_wifi.h" #include "esp_smartconfig.h" -#include "smartconfig.h" +#include "smartconfig_ack.h" static const char *TAG = "smartconfig"; @@ -50,7 +50,7 @@ static void sc_ack_send_task(void *pvParameters) int remote_port = (ack->type == SC_ACK_TYPE_ESPTOUCH) ? SC_ACK_TOUCH_SERVER_PORT : SC_ACK_AIRKISS_SERVER_PORT; struct sockaddr_in server_addr; socklen_t sin_size = sizeof(server_addr); - int send_sock = 0; + int send_sock = -1; int optval = 1; int sendlen; int ack_len = (ack->type == SC_ACK_TYPE_ESPTOUCH) ? SC_ACK_TOUCH_LEN : SC_ACK_AIRKISS_LEN; @@ -78,10 +78,9 @@ static void sc_ack_send_task(void *pvParameters) /* Create UDP socket. */ send_sock = socket(AF_INET, SOCK_DGRAM, 0); - if (send_sock < 0) { + if ((send_sock < LWIP_SOCKET_OFFSET) || (send_sock > (FD_SETSIZE - 1))) { ESP_LOGE(TAG, "Creat udp socket failed"); - free(ack); - vTaskDelete(NULL); + goto _end; } setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, &optval, sizeof(int)); @@ -100,9 +99,7 @@ static void sc_ack_send_task(void *pvParameters) if (ack->cb) { ack->cb(SC_STATUS_LINK_OVER, remote_ip); } - close(send_sock); - free(ack); - vTaskDelete(NULL); + goto _end; } } else { @@ -112,9 +109,7 @@ static void sc_ack_send_task(void *pvParameters) continue; } ESP_LOGE(TAG, "send failed, errno %d", err); - close(send_sock); - free(ack); - vTaskDelete(NULL); + goto _end; } } } @@ -123,6 +118,10 @@ static void sc_ack_send_task(void *pvParameters) } } +_end: + if ((send_sock >= LWIP_SOCKET_OFFSET) && (send_sock <= (FD_SETSIZE - 1))) { + close(send_sock); + } free(ack); vTaskDelete(NULL); } @@ -145,7 +144,10 @@ void sc_ack_send(sc_ack_t *param) s_sc_ack_send = true; - xTaskCreate(sc_ack_send_task, "sc_ack_send_task", SC_ACK_TASK_STACK_SIZE, ack, SC_ACK_TASK_PRIORITY, NULL); + if (xTaskCreate(sc_ack_send_task, "sc_ack_send_task", SC_ACK_TASK_STACK_SIZE, ack, SC_ACK_TASK_PRIORITY, NULL) != pdPASS) { + ESP_LOGE(TAG, "Create sending smartconfig ACK task fail"); + free(ack); + } } void sc_ack_send_stop(void) From b840a09900abd08d23512669a52e45311323860d Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 11 May 2018 16:42:52 +0800 Subject: [PATCH 071/187] ci: increase number of unit test jobs --- .gitlab-ci.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b013c847d4..d5491a64d3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -701,6 +701,13 @@ UT_001_09: - UT_T1_1 - UT_default +UT_001_10: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + - UT_default + UT_002_01: <<: *unit_test_template tags: @@ -764,6 +771,13 @@ UT_002_09: - UT_T1_1 - UT_release +UT_002_10: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + - UT_release + UT_003_01: <<: *unit_test_template tags: @@ -827,6 +841,13 @@ UT_003_09: - UT_T1_1 - UT_single_core +UT_003_10: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + - UT_single_core + UT_004_01: <<: *unit_test_template tags: @@ -897,6 +918,13 @@ UT_004_10: - UT_T1_1 - UT_psram +UT_004_11: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + - UT_psram + IT_001_01: <<: *test_template tags: From d53661a6634f65814c018bedfbe38f18a9297d22 Mon Sep 17 00:00:00 2001 From: kooho <2229179028@qq.com> Date: Mon, 5 Feb 2018 21:51:32 +0800 Subject: [PATCH 072/187] driver(adc): add descriptions for the issue that starting ADC can trigger interrupt of GPIO36 and GPIO39. --- components/driver/include/driver/adc.h | 19 +++++++++++++++++++ components/driver/include/driver/gpio.h | 4 ++++ 2 files changed, 23 insertions(+) diff --git a/components/driver/include/driver/adc.h b/components/driver/include/driver/adc.h index e6c6df1a40..b5a9a9848e 100644 --- a/components/driver/include/driver/adc.h +++ b/components/driver/include/driver/adc.h @@ -192,6 +192,10 @@ esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten); /** * @brief Take an ADC1 reading from a single channel. + * @note When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on, + * the input of GPIO36 and GPIO39 will be pulled down for about 80ns. + * When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39. + * Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue. * * @note Call adc1_config_width() before the first time this * function is called. @@ -210,6 +214,11 @@ int adc1_get_raw(adc1_channel_t channel); /** @cond */ //Doxygen command to hide deprecated function from API Reference /* + * @note When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on, + * the input of GPIO36 and GPIO39 will be pulled down for about 80ns. + * When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39. + * Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue. + * * @deprecated This function returns an ADC1 reading but is deprecated due to * a misleading name and has been changed to directly call the new function. * Use the new function adc1_get_raw() instead @@ -288,6 +297,11 @@ void adc1_ulp_enable(); /** * @brief Read Hall Sensor * + * @note When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on, + * the input of GPIO36 and GPIO39 will be pulled down for about 80ns. + * When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39. + * Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue. + * * @note The Hall Sensor uses channels 0 and 3 of ADC1. Do not configure * these channels for use as ADC channels. * @@ -349,6 +363,11 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten); /** * @brief Take an ADC2 reading on a single channel * + * @note When the power switch of SARADC1, SARADC2, HALL sensor and AMP sensor is turned on, + * the input of GPIO36 and GPIO39 will be pulled down for about 80ns. + * When enabling power for any of these peripherals, ignore input from GPIO36 and GPIO39. + * Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue. + * * @note For a given channel, ``adc2_config_channel_atten()`` * must be called before the first time this function is called. If Wi-Fi is started via ``esp_wifi_start()``, this * function will always fail with ``ESP_ERR_TIMEOUT``. diff --git a/components/driver/include/driver/gpio.h b/components/driver/include/driver/gpio.h index 2f272ef5e7..aed6427bf8 100644 --- a/components/driver/include/driver/gpio.h +++ b/components/driver/include/driver/gpio.h @@ -265,6 +265,10 @@ esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type); /** * @brief Enable GPIO module interrupt signal * + * @note Please do not use the interrupt of GPIO36 and GPIO39 when using ADC. + * Please refer to the comments of `adc1_get_raw`. + * Please refer to section 3.11 of 'ECO_and_Workarounds_for_Bugs_in_ESP32' for the description of this issue. + * * @param gpio_num GPIO number. If you want to enable an interrupt on e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16); * * @return From 2041c08681043c6d6136aaaf702d385f0a867c14 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Fri, 11 May 2018 11:08:58 +0200 Subject: [PATCH 073/187] Bluedroid: remove warnings about discarding "const" for "const char*" --- components/bt/bluedroid/bta/dm/bta_dm_api.c | 2 +- components/bt/bluedroid/bta/include/bta/bta_api.h | 2 +- components/bt/bluedroid/bta/jv/bta_jv_act.c | 6 +++--- components/bt/bluedroid/btc/core/btc_dm.c | 2 +- components/bt/bluedroid/stack/gap/gap_conn.c | 2 +- components/bt/bluedroid/stack/include/stack/gap_api.h | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/components/bt/bluedroid/bta/dm/bta_dm_api.c b/components/bt/bluedroid/bta/dm/bta_dm_api.c index fdd5f97a93..6564adc824 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_api.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_api.c @@ -166,7 +166,7 @@ void BTA_DisableTestMode(void) ** Returns void ** *******************************************************************************/ -void BTA_DmSetDeviceName(char *p_name) +void BTA_DmSetDeviceName(const char *p_name) { tBTA_DM_API_SET_NAME *p_msg; diff --git a/components/bt/bluedroid/bta/include/bta/bta_api.h b/components/bt/bluedroid/bta/include/bta/bta_api.h index b2ef0ecd3a..ae645f5753 100644 --- a/components/bt/bluedroid/bta/include/bta/bta_api.h +++ b/components/bt/bluedroid/bta/include/bta/bta_api.h @@ -1416,7 +1416,7 @@ extern void BTA_DisableTestMode(void); ** Returns void ** *******************************************************************************/ -extern void BTA_DmSetDeviceName(char *p_name); +extern void BTA_DmSetDeviceName(const char *p_name); extern void BTA_DmUpdateWhiteList(BOOLEAN add_remove, BD_ADDR remote_addr, tBTA_ADD_WHITELIST_CBACK *add_wl_cb); diff --git a/components/bt/bluedroid/bta/jv/bta_jv_act.c b/components/bt/bluedroid/bta/jv/bta_jv_act.c index 9ce6677456..12dfd13b25 100644 --- a/components/bt/bluedroid/bta/jv/bta_jv_act.c +++ b/components/bt/bluedroid/bta/jv/bta_jv_act.c @@ -951,7 +951,7 @@ static bool create_base_record(const uint32_t sdp_handle, const char *name, cons proto_list[2].num_params = 0; } - char *stage = "protocol_list"; + const char *stage = "protocol_list"; if (!SDP_AddProtocolList(sdp_handle, num_proto_elements, proto_list)){ APPL_TRACE_ERROR("create_base_record: failed to create base service " "record, stage: %s, scn: %d, name: %s, with_obex: %d", @@ -1000,7 +1000,7 @@ static int add_spp_sdp(const char *name, const int channel) { } // Create the base SDP record. - char *stage = "create_base_record"; + const char *stage = "create_base_record"; if (!create_base_record(handle, name, channel, FALSE /* with_obex */)){ SDP_DeleteRecord(handle); APPL_TRACE_ERROR("add_spp_sdp: failed to register SPP service, " @@ -2769,4 +2769,4 @@ extern void bta_jv_l2cap_close_fixed (tBTA_JV_MSG *p_data) } -#endif ///defined BTA_JV_INCLUDED && BTA_JV_INCLUDED == TRUE \ No newline at end of file +#endif ///defined BTA_JV_INCLUDED && BTA_JV_INCLUDED == TRUE diff --git a/components/bt/bluedroid/btc/core/btc_dm.c b/components/bt/bluedroid/btc/core/btc_dm.c index d6d41e2346..8bc2370ad4 100644 --- a/components/bt/bluedroid/btc/core/btc_dm.c +++ b/components/bt/bluedroid/btc/core/btc_dm.c @@ -454,7 +454,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) /* Set initial device name, it can be overwritten later */ if (p_data->enable.status == BTA_SUCCESS) { - char *initial_device_name = "ESP32"; + const char *initial_device_name = "ESP32"; BTA_DmSetDeviceName(initial_device_name); } btc_enable_bluetooth_evt(p_data->enable.status); diff --git a/components/bt/bluedroid/stack/gap/gap_conn.c b/components/bt/bluedroid/stack/gap/gap_conn.c index 3ca81d082c..ecb7b726f5 100644 --- a/components/bt/bluedroid/stack/gap/gap_conn.c +++ b/components/bt/bluedroid/stack/gap/gap_conn.c @@ -123,7 +123,7 @@ void gap_conn_init (void) ** Returns handle of the connection if successful, else GAP_INVALID_HANDLE ** *******************************************************************************/ -UINT16 GAP_ConnOpen (char *p_serv_name, UINT8 service_id, BOOLEAN is_server, +UINT16 GAP_ConnOpen (const char *p_serv_name, UINT8 service_id, BOOLEAN is_server, BD_ADDR p_rem_bda, UINT16 psm, tL2CAP_CFG_INFO *p_cfg, tL2CAP_ERTM_INFO *ertm_info, UINT16 security, UINT8 chan_mode_mask, tGAP_CONN_CALLBACK *p_cb) diff --git a/components/bt/bluedroid/stack/include/stack/gap_api.h b/components/bt/bluedroid/stack/include/stack/gap_api.h index 031247f7c0..5d8d87645d 100644 --- a/components/bt/bluedroid/stack/include/stack/gap_api.h +++ b/components/bt/bluedroid/stack/include/stack/gap_api.h @@ -140,7 +140,7 @@ typedef void (tGAP_BLE_CMPL_CBACK)(BOOLEAN status, BD_ADDR addr, UINT16 length, ** Returns handle of the connection if successful, else GAP_INVALID_HANDLE ** *******************************************************************************/ -extern UINT16 GAP_ConnOpen (char *p_serv_name, UINT8 service_id, BOOLEAN is_server, +extern UINT16 GAP_ConnOpen (const char *p_serv_name, UINT8 service_id, BOOLEAN is_server, BD_ADDR p_rem_bda, UINT16 psm, tL2CAP_CFG_INFO *p_cfg, tL2CAP_ERTM_INFO *ertm_info, UINT16 security, UINT8 chan_mode_mask, tGAP_CONN_CALLBACK *p_cb); From 1b7ed6455b6af8521da9c744b4cee54a0a9e95d6 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 11 May 2018 18:14:13 +0800 Subject: [PATCH 074/187] esp32/test: temporarily disable test for light sleep duration Until the issue in CI is debugged --- components/esp32/test/test_sleep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp32/test/test_sleep.c b/components/esp32/test/test_sleep.c index c298d3220b..201c2312e3 100644 --- a/components/esp32/test/test_sleep.c +++ b/components/esp32/test/test_sleep.c @@ -127,7 +127,7 @@ TEST_CASE("light sleep stress test with periodic esp_timer", "[deepsleep]") #endif -TEST_CASE("light sleep duration is correct", "[deepsleep]") +TEST_CASE("light sleep duration is correct", "[deepsleep][ignore]") { // don't power down XTAL — powering it up takes different time on // different boards From 1bebec05c68ae2c1771c41510df2ce43a31c30ac Mon Sep 17 00:00:00 2001 From: kooho <2229179028@qq.com> Date: Thu, 12 Apr 2018 15:38:39 +0800 Subject: [PATCH 075/187] driver(ledc): fix duty and fade issues and add thread-safe version APIs. 1. Fix the duty fade check issue reported from https://github.com/espressif/esp-idf/issues/1914 2. Fix the duty overflow issue when duty_scale is set to 1. 3. Fix the duty fade error when a fade operation is under way. We must configure a new duty setting after the previous fade operation has finished due to hardware limit. 4. Add thread-safe version APIs to set duty and fade. 5. Correct the duty range in driver. --- components/driver/include/driver/ledc.h | 182 ++++++-- components/driver/ledc.c | 548 +++++++++++++++--------- 2 files changed, 501 insertions(+), 229 deletions(-) diff --git a/components/driver/include/driver/ledc.h b/components/driver/include/driver/ledc.h index c5250213d6..8f70b1c003 100644 --- a/components/driver/include/driver/ledc.h +++ b/components/driver/include/driver/ledc.h @@ -27,6 +27,7 @@ extern "C" { #define LEDC_APB_CLK_HZ (APB_CLK_FREQ) #define LEDC_REF_CLK_HZ (1*1000000) #define LEDC_ERR_DUTY (0xFFFFFFFF) +#define LEDC_ERR_VAL (-1) typedef enum { LEDC_HIGH_SPEED_MODE = 0, /*!< LEDC high speed speed_mode */ @@ -42,6 +43,7 @@ typedef enum { typedef enum { LEDC_DUTY_DIR_DECREASE = 0, /*!< LEDC duty decrease direction */ LEDC_DUTY_DIR_INCREASE = 1, /*!< LEDC duty increase direction */ + LEDC_DUTY_DIR_MAX, } ledc_duty_direction_t; typedef enum { @@ -54,6 +56,7 @@ typedef enum { LEDC_TIMER_1, /*!< LEDC timer 1 */ LEDC_TIMER_2, /*!< LEDC timer 2 */ LEDC_TIMER_3, /*!< LEDC timer 3 */ + LEDC_TIMER_MAX, } ledc_timer_t; typedef enum { @@ -69,12 +72,27 @@ typedef enum { } ledc_channel_t; typedef enum { - LEDC_TIMER_10_BIT = 10, /*!< LEDC PWM duty resolution of 10 bits */ - LEDC_TIMER_11_BIT = 11, /*!< LEDC PWM duty resolution of 11 bits */ - LEDC_TIMER_12_BIT = 12, /*!< LEDC PWM duty resolution of 12 bits */ - LEDC_TIMER_13_BIT = 13, /*!< LEDC PWM duty resolution of 13 bits */ - LEDC_TIMER_14_BIT = 14, /*!< LEDC PWM duty resolution of 14 bits */ - LEDC_TIMER_15_BIT = 15, /*!< LEDC PWM duty resolution of 15 bits */ + LEDC_TIMER_1_BIT = 1, /*!< LEDC PWM duty resolution of 1 bits */ + LEDC_TIMER_2_BIT, /*!< LEDC PWM duty resolution of 2 bits */ + LEDC_TIMER_3_BIT, /*!< LEDC PWM duty resolution of 3 bits */ + LEDC_TIMER_4_BIT, /*!< LEDC PWM duty resolution of 4 bits */ + LEDC_TIMER_5_BIT, /*!< LEDC PWM duty resolution of 5 bits */ + LEDC_TIMER_6_BIT, /*!< LEDC PWM duty resolution of 6 bits */ + LEDC_TIMER_7_BIT, /*!< LEDC PWM duty resolution of 7 bits */ + LEDC_TIMER_8_BIT, /*!< LEDC PWM duty resolution of 8 bits */ + LEDC_TIMER_9_BIT, /*!< LEDC PWM duty resolution of 9 bits */ + LEDC_TIMER_10_BIT, /*!< LEDC PWM duty resolution of 10 bits */ + LEDC_TIMER_11_BIT, /*!< LEDC PWM duty resolution of 11 bits */ + LEDC_TIMER_12_BIT, /*!< LEDC PWM duty resolution of 12 bits */ + LEDC_TIMER_13_BIT, /*!< LEDC PWM duty resolution of 13 bits */ + LEDC_TIMER_14_BIT, /*!< LEDC PWM duty resolution of 14 bits */ + LEDC_TIMER_15_BIT, /*!< LEDC PWM duty resolution of 15 bits */ + LEDC_TIMER_16_BIT, /*!< LEDC PWM duty resolution of 16 bits */ + LEDC_TIMER_17_BIT, /*!< LEDC PWM duty resolution of 17 bits */ + LEDC_TIMER_18_BIT, /*!< LEDC PWM duty resolution of 18 bits */ + LEDC_TIMER_19_BIT, /*!< LEDC PWM duty resolution of 19 bits */ + LEDC_TIMER_20_BIT, /*!< LEDC PWM duty resolution of 20 bits */ + LEDC_TIMER_BIT_MAX, } ledc_timer_bit_t; typedef enum { @@ -92,7 +110,8 @@ typedef struct { ledc_channel_t channel; /*!< LEDC channel (0 - 7) */ ledc_intr_type_t intr_type; /*!< configure interrupt, Fade interrupt enable or Fade interrupt disable */ ledc_timer_t timer_sel; /*!< Select the timer source of channel (0 - 3) */ - uint32_t duty; /*!< LEDC channel duty, the range of duty setting is [0, (2**duty_resolution) - 1] */ + uint32_t duty; /*!< LEDC channel duty, the range of duty setting is [0, (2**duty_resolution)] */ + int hpoint; /*!< LEDC channel hpoint value, the max value is 0xfffff */ } ledc_channel_config_t; /** @@ -137,9 +156,11 @@ esp_err_t ledc_timer_config(const ledc_timer_config_t* timer_conf); /** * @brief LEDC update channel parameters - * Call this function to activate the LEDC updated parameters. - * After ledc_set_duty, ledc_set_fade, we need to call this function to update the settings. - * + * @note Call this function to activate the LEDC updated parameters. + * After ledc_set_duty, we need to call this function to update the settings. + * @note ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to + * control one LEDC channel in different tasks at the same time. + * A thread-safe version of API is ledc_set_duty_and_update * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, * @param channel LEDC channel (0-7), select from ledc_channel_t * @@ -191,12 +212,47 @@ esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num); /** - * @brief LEDC set duty + * @brief LEDC set duty and hpoint value * Only after calling ledc_update_duty will the duty update. + * @note ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to + * control one LEDC channel in different tasks at the same time. + * A thread-safe version of API is ledc_set_duty_and_update + * @note If a fade operation is running in progress on that channel, the driver would not allow it to be stopped. + * Other duty operations will have to wait until the fade operation has finished. + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode + * @param channel LEDC channel (0-7), select from ledc_channel_t + * @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution)] + * @param hpoint Set the LEDC hpoint value(max: 0xfffff) + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t ledc_set_duty_with_hpoint(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, uint32_t hpoint); + +/** + * @brief LEDC get hpoint value, the counter value when the output is set high level. * * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode * @param channel LEDC channel (0-7), select from ledc_channel_t - * @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution) - 1] + * @return + * - LEDC_ERR_VAL if parameter error + * - Others Current hpoint value of LEDC channel + */ +int ledc_get_hpoint(ledc_mode_t speed_mode, ledc_channel_t channel); + +/** + * @brief LEDC set duty + * This function do not change the hpoint value of this channel. if needed, please call ledc_set_duty_with_hpoint. + * only after calling ledc_update_duty will the duty update. + * @note ledc_set_duty, ledc_set_duty_with_hpoint and ledc_update_duty are not thread-safe, do not call these functions to + * control one LEDC channel in different tasks at the same time. + * A thread-safe version of API is ledc_set_duty_and_update. + * @note If a fade operation is running in progress on that channel, the driver would not allow it to be stopped. + * Other duty operations will have to wait until the fade operation has finished. + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode + * @param channel LEDC channel (0-7), select from ledc_channel_t + * @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution)] * * @return * - ESP_OK Success @@ -219,20 +275,21 @@ uint32_t ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel); /** * @brief LEDC set gradient * Set LEDC gradient, After the function calls the ledc_update_duty function, the function can take effect. - * - * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode - * @param channel LEDC channel (0-7), select from ledc_channel_t - * @param duty Set the start of the gradient duty, the range of duty setting is [0, (2**duty_resolution) - 1] - * @param gradule_direction Set the direction of the gradient - * @param step_num Set the number of the gradient - * @param duty_cyle_num Set how many LEDC tick each time the gradient lasts - * @param duty_scale Set gradient change amplitude + * @note If a fade operation is running in progress on that channel, the driver would not allow it to be stopped. + * Other duty operations will have to wait until the fade operation has finished. + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode + * @param channel LEDC channel (0-7), select from ledc_channel_t + * @param duty Set the start of the gradient duty, the range of duty setting is [0, (2**duty_resolution)] + * @param fade_direction Set the direction of the gradient + * @param step_num Set the number of the gradient + * @param duty_cyle_num Set how many LEDC tick each time the gradient lasts + * @param duty_scale Set gradient change amplitude * * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error */ -esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, ledc_duty_direction_t gradule_direction, +esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, ledc_duty_direction_t fade_direction, uint32_t step_num, uint32_t duty_cyle_num, uint32_t duty_scale); /** @@ -259,7 +316,7 @@ esp_err_t ledc_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode * @param timer_sel Timer index (0-3), there are 4 timers in LEDC module * @param clock_divider Timer clock divide value, the timer clock is divided from the selected clock source - * @param duty_resolution Resolution of duty setting in number of bits. The range of duty values is [0, (2**duty_resolution) - 1] + * @param duty_resolution Resolution of duty setting in number of bits. The range of duty values is [0, (2**duty_resolution)] * @param clk_src Select LEDC source clock. * * @return @@ -319,9 +376,14 @@ esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel); esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, uint32_t channel, uint32_t timer_idx); /** - * @brief Set LEDC fade function. Should call ledc_fade_func_install() before calling this function. + * @brief Set LEDC fade function. + * @note Call ledc_fade_func_install() once before calling this function. * Call ledc_fade_start() after this to start fading. - * + * @note ledc_set_fade_with_step, ledc_set_fade_with_time and ledc_fade_start are not thread-safe, do not call these functions to + * control one LEDC channel in different tasks at the same time. + * A thread-safe version of API is ledc_set_fade_step_and_start + * @note If a fade operation is running in progress on that channel, the driver would not allow it to be stopped. + * Other duty operations will have to wait until the fade operation has finished. * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, * @param channel LEDC channel index (0-7), select from ledc_channel_t * @param target_duty Target duty of fading [0, (2**duty_resolution) - 1] @@ -334,12 +396,17 @@ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, uint32_t channel, uint * - ESP_ERR_INVALID_STATE Fade function not installed. * - ESP_FAIL Fade function init error */ -esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int scale, int cycle_num); +esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num); /** - * @brief Set LEDC fade function, with a limited time. Should call ledc_fade_func_install() before calling this function. + * @brief Set LEDC fade function, with a limited time. + * @note Call ledc_fade_func_install() once before calling this function. * Call ledc_fade_start() after this to start fading. - * + * @note ledc_set_fade_with_step, ledc_set_fade_with_time and ledc_fade_start are not thread-safe, do not call these functions to + * control one LEDC channel in different tasks at the same time. + * A thread-safe version of API is ledc_set_fade_step_and_start + * @note If a fade operation is running in progress on that channel, the driver would not allow it to be stopped. + * Other duty operations will have to wait until the fade operation has finished. * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, * @param channel LEDC channel index (0-7), select from ledc_channel_t * @param target_duty Target duty of fading.( 0 - (2 ** duty_resolution - 1))) @@ -354,8 +421,7 @@ esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int max_fade_time_ms); /** - * @brief Install ledc fade function. This function will occupy interrupt of LEDC module. - * + * @brief Install LEDC fade function. This function will occupy interrupt of LEDC module. * @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred) * ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. * @@ -373,18 +439,70 @@ void ledc_fade_func_uninstall(); /** * @brief Start LEDC fading. - * + * @note Call ledc_fade_func_install() once before calling this function. + * Call this API right after ledc_set_fade_with_time or ledc_set_fade_with_step before to start fading. + * @note If a fade operation is running in progress on that channel, the driver would not allow it to be stopped. + * Other duty operations will have to wait until the fade operation has finished. * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode * @param channel LEDC channel number - * @param wait_done Whether to block until fading done. + * @param fade_mode Whether to block until fading done. * * @return * - ESP_OK Success * - ESP_ERR_INVALID_STATE Fade function not installed. * - ESP_ERR_INVALID_ARG Parameter error. */ -esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t wait_done); +esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t fade_mode); +/** + * @brief A thread-safe API to set duty for LEDC channel and update the settings immediately + * @note If a fade operation is running in progress on that channel, the driver would not allow it to be stopped. + * Other duty operations will have to wait until the fade operation has finished. + * + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode + * @param channel LEDC channel (0-7), select from ledc_channel_t + * @param duty Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution)] + * @param hpoint Set the LEDC hpoint value(max: 0xfffff) + * + */ +esp_err_t ledc_set_duty_and_update(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, uint32_t hpoint); + +/** + * @brief A thread-safe API to set and start LEDC fade function, with a limited time. + * @note Call ledc_fade_func_install() once, before calling this function. + * @note If a fade operation is running in progress on that channel, the driver would not allow it to be stopped. + * Other duty operations will have to wait until the fade operation has finished. + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, + * @param channel LEDC channel index (0-7), select from ledc_channel_t + * @param target_duty Target duty of fading.( 0 - (2 ** duty_resolution - 1))) + * @param max_fade_time_ms The maximum time of the fading ( ms ). + * @param fade_mode choose blocking or non-blocking mode + * @return + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_OK Success + * - ESP_ERR_INVALID_STATE Fade function not installed. + * - ESP_FAIL Fade function init error + */ +esp_err_t ledc_set_fade_time_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t max_fade_time_ms, ledc_fade_mode_t fade_mode); + +/** + * @brief A thread-safe API to set and start LEDC fade function. + * @note Call ledc_fade_func_install() once before calling this function. + * @note If a fade operation is running in progress on that channel, the driver would not allow it to be stopped. + * Other duty operations will have to wait until the fade operation has finished. + * @param speed_mode Select the LEDC speed_mode, high-speed mode and low-speed mode, + * @param channel LEDC channel index (0-7), select from ledc_channel_t + * @param target_duty Target duty of fading [0, (2**duty_resolution) - 1] + * @param scale Controls the increase or decrease step scale. + * @param cycle_num increase or decrease the duty every cycle_num cycles + * @param fade_mode choose blocking or non-blocking mode + * @return + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_OK Success + * - ESP_ERR_INVALID_STATE Fade function not installed. + * - ESP_FAIL Fade function init error + */ +esp_err_t ledc_set_fade_step_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num, ledc_fade_mode_t fade_mode); #ifdef __cplusplus } #endif diff --git a/components/driver/ledc.c b/components/driver/ledc.c index 05ab95499d..6891877c86 100644 --- a/components/driver/ledc.c +++ b/components/driver/ledc.c @@ -51,12 +51,14 @@ typedef struct { static ledc_fade_t *s_ledc_fade_rec[LEDC_SPEED_MODE_MAX][LEDC_CHANNEL_MAX]; static ledc_isr_handle_t s_ledc_fade_isr_handle = NULL; -#define LEDC_VAL_NO_CHANGE (-1) -#define LEDC_STEP_NUM_MAX (1023) -#define LEDC_DUTY_DECIMAL_BIT_NUM (4) - +#define LEDC_VAL_NO_CHANGE (-1) +#define LEDC_STEP_NUM_MAX (1023) +#define LEDC_DUTY_DECIMAL_BIT_NUM (4) +#define LEDC_HPOINT_VAL_MAX (LEDC_HPOINT_HSCH1_V) +#define LEDC_FADE_TOO_SLOW_STR "LEDC FADE TOO SLOW" +#define LEDC_FADE_TOO_FAST_STR "LEDC FADE TOO FAST" static const char *LEDC_FADE_SERVICE_ERR_STR = "LEDC fade service not installed"; -static const char *LEDC_FADE_INIT_ERROR_STR = "LEDC fade channel init error"; +static const char *LEDC_FADE_INIT_ERROR_STR = "LEDC fade channel init error, not enough memory or service not installed"; static void ledc_ls_timer_update(ledc_mode_t speed_mode, ledc_timer_t timer_sel) { @@ -72,82 +74,6 @@ static IRAM_ATTR void ledc_ls_channel_update(ledc_mode_t speed_mode, ledc_channe } } -esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t clock_divider, uint32_t duty_resolution, - ledc_clk_src_t clk_src) -{ - LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); - LEDC_ARG_CHECK(timer_sel <= LEDC_TIMER_3, "timer_sel") - portENTER_CRITICAL(&ledc_spinlock); - LEDC.timer_group[speed_mode].timer[timer_sel].conf.clock_divider = clock_divider; - LEDC.timer_group[speed_mode].timer[timer_sel].conf.tick_sel = clk_src; - LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_resolution = duty_resolution; - ledc_ls_timer_update(speed_mode, timer_sel); - portEXIT_CRITICAL(&ledc_spinlock); - return ESP_OK; -} - -static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel_t channel_num, int hpoint_val, uint32_t duty_val, - uint32_t duty_direction, uint32_t duty_num, uint32_t duty_cycle, uint32_t duty_scale) -{ - portENTER_CRITICAL(&ledc_spinlock); - if (hpoint_val >= 0) { - LEDC.channel_group[speed_mode].channel[channel_num].hpoint.hpoint = hpoint_val; - } - LEDC.channel_group[speed_mode].channel[channel_num].duty.duty = duty_val; - LEDC.channel_group[speed_mode].channel[channel_num].conf1.val = ((duty_direction & LEDC_DUTY_INC_HSCH0_V) << LEDC_DUTY_INC_HSCH0_S) | - ((duty_num & LEDC_DUTY_NUM_HSCH0_V) << LEDC_DUTY_NUM_HSCH0_S) | - ((duty_cycle & LEDC_DUTY_CYCLE_HSCH0_V) << LEDC_DUTY_CYCLE_HSCH0_S) | - ((duty_scale & LEDC_DUTY_SCALE_HSCH0_V) << LEDC_DUTY_SCALE_HSCH0_S); - ledc_ls_channel_update(speed_mode, channel_num); - portEXIT_CRITICAL(&ledc_spinlock); - return ESP_OK; -} - -esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t timer_idx) -{ - LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); - LEDC_ARG_CHECK(timer_idx <= LEDC_TIMER_3, "timer_idx"); - portENTER_CRITICAL(&ledc_spinlock); - LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel = timer_idx; - ledc_ls_channel_update(speed_mode, channel); - portEXIT_CRITICAL(&ledc_spinlock); - return ESP_OK; -} - -esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, uint32_t timer_sel) -{ - LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); - LEDC_ARG_CHECK(timer_sel <= LEDC_TIMER_3, "timer_sel"); - portENTER_CRITICAL(&ledc_spinlock); - LEDC.timer_group[speed_mode].timer[timer_sel].conf.rst = 1; - LEDC.timer_group[speed_mode].timer[timer_sel].conf.rst = 0; - ledc_ls_timer_update(speed_mode, timer_sel); - portEXIT_CRITICAL(&ledc_spinlock); - return ESP_OK; -} - -esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, uint32_t timer_sel) -{ - LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); - LEDC_ARG_CHECK(timer_sel <= LEDC_TIMER_3, "timer_sel"); - portENTER_CRITICAL(&ledc_spinlock); - LEDC.timer_group[speed_mode].timer[timer_sel].conf.pause = 1; - ledc_ls_timer_update(speed_mode, timer_sel); - portEXIT_CRITICAL(&ledc_spinlock); - return ESP_OK; -} - -esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel) -{ - LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); - LEDC_ARG_CHECK(timer_sel <= LEDC_TIMER_3, "timer_sel"); - portENTER_CRITICAL(&ledc_spinlock); - LEDC.timer_group[speed_mode].timer[timer_sel].conf.pause = 0; - ledc_ls_timer_update(speed_mode, timer_sel); - portEXIT_CRITICAL(&ledc_spinlock); - return ESP_OK; -} - static esp_err_t ledc_enable_intr_type(ledc_mode_t speed_mode, uint32_t channel, ledc_intr_type_t type) { LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); @@ -168,6 +94,124 @@ static esp_err_t ledc_enable_intr_type(ledc_mode_t speed_mode, uint32_t channel, return ESP_OK; } +static void _ledc_fade_hw_acquire(ledc_mode_t mode, ledc_channel_t channel) +{ + ledc_fade_t* fade = s_ledc_fade_rec[mode][channel]; + if (fade) { + xSemaphoreTake(fade->ledc_fade_sem, portMAX_DELAY); + ledc_enable_intr_type(mode, channel, LEDC_INTR_DISABLE); + } +} + +static void _ledc_fade_hw_release(ledc_mode_t mode, ledc_channel_t channel) +{ + ledc_fade_t* fade = s_ledc_fade_rec[mode][channel]; + if (fade) { + xSemaphoreGive(fade->ledc_fade_sem); + } +} + +static void _ledc_op_lock_acquire(ledc_mode_t mode, ledc_channel_t channel) +{ + ledc_fade_t* fade = s_ledc_fade_rec[mode][channel]; + if (fade) { + xSemaphoreTake(fade->ledc_fade_mux, portMAX_DELAY); + } +} + +static void _ledc_op_lock_release(ledc_mode_t mode, ledc_channel_t channel) +{ + ledc_fade_t* fade = s_ledc_fade_rec[mode][channel]; + if (fade) { + xSemaphoreGive(fade->ledc_fade_mux); + } +} + +static int ledc_get_max_duty(ledc_mode_t speed_mode, ledc_channel_t channel) +{ + // The arguments are checked before internally calling this function. + int timer_sel = LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel; + int max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_resolution)); + return max_duty; +} + +esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t clock_divider, uint32_t duty_resolution, + ledc_clk_src_t clk_src) +{ + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(timer_sel < LEDC_TIMER_MAX, "timer_select"); + portENTER_CRITICAL(&ledc_spinlock); + LEDC.timer_group[speed_mode].timer[timer_sel].conf.clock_divider = clock_divider; + LEDC.timer_group[speed_mode].timer[timer_sel].conf.tick_sel = clk_src; + LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_resolution = duty_resolution; + ledc_ls_timer_update(speed_mode, timer_sel); + portEXIT_CRITICAL(&ledc_spinlock); + return ESP_OK; +} + +static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel_t channel_num, int hpoint_val, int duty_val, + uint32_t duty_direction, uint32_t duty_num, uint32_t duty_cycle, uint32_t duty_scale) +{ + portENTER_CRITICAL(&ledc_spinlock); + if (hpoint_val >= 0) { + LEDC.channel_group[speed_mode].channel[channel_num].hpoint.hpoint = hpoint_val & LEDC_HPOINT_HSCH1_V; + } + if (duty_val >= 0) { + LEDC.channel_group[speed_mode].channel[channel_num].duty.duty = duty_val; + } + LEDC.channel_group[speed_mode].channel[channel_num].conf1.val = ((duty_direction & LEDC_DUTY_INC_HSCH0_V) << LEDC_DUTY_INC_HSCH0_S) | + ((duty_num & LEDC_DUTY_NUM_HSCH0_V) << LEDC_DUTY_NUM_HSCH0_S) | + ((duty_cycle & LEDC_DUTY_CYCLE_HSCH0_V) << LEDC_DUTY_CYCLE_HSCH0_S) | + ((duty_scale & LEDC_DUTY_SCALE_HSCH0_V) << LEDC_DUTY_SCALE_HSCH0_S); + ledc_ls_channel_update(speed_mode, channel_num); + portEXIT_CRITICAL(&ledc_spinlock); + return ESP_OK; +} + +esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t timer_idx) +{ + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(timer_idx < LEDC_TIMER_MAX, "timer_select"); portENTER_CRITICAL(&ledc_spinlock); + LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel = timer_idx; + ledc_ls_channel_update(speed_mode, channel); + portEXIT_CRITICAL(&ledc_spinlock); + return ESP_OK; +} + +esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, uint32_t timer_sel) +{ + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(timer_sel < LEDC_TIMER_MAX, "timer_select"); + portENTER_CRITICAL(&ledc_spinlock); + LEDC.timer_group[speed_mode].timer[timer_sel].conf.rst = 1; + LEDC.timer_group[speed_mode].timer[timer_sel].conf.rst = 0; + ledc_ls_timer_update(speed_mode, timer_sel); + portEXIT_CRITICAL(&ledc_spinlock); + return ESP_OK; +} + +esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, uint32_t timer_sel) +{ + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(timer_sel < LEDC_TIMER_MAX, "timer_select"); + portENTER_CRITICAL(&ledc_spinlock); + LEDC.timer_group[speed_mode].timer[timer_sel].conf.pause = 1; + ledc_ls_timer_update(speed_mode, timer_sel); + portEXIT_CRITICAL(&ledc_spinlock); + return ESP_OK; +} + +esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel) +{ + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(timer_sel < LEDC_TIMER_MAX, "timer_select"); + portENTER_CRITICAL(&ledc_spinlock); + LEDC.timer_group[speed_mode].timer[timer_sel].conf.pause = 0; + ledc_ls_timer_update(speed_mode, timer_sel); + portEXIT_CRITICAL(&ledc_spinlock); + return ESP_OK; +} + esp_err_t ledc_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, ledc_isr_handle_t *handle) { esp_err_t ret; @@ -180,13 +224,14 @@ esp_err_t ledc_isr_register(void (*fn)(void*), void * arg, int intr_alloc_flags, esp_err_t ledc_timer_config(const ledc_timer_config_t* timer_conf) { - int freq_hz = timer_conf->freq_hz; - int duty_resolution = timer_conf->duty_resolution; - int timer_num = timer_conf->timer_num; - int speed_mode = timer_conf->speed_mode; + LEDC_ARG_CHECK(timer_conf != NULL, "timer_conf"); + uint32_t freq_hz = timer_conf->freq_hz; + uint32_t duty_resolution = timer_conf->duty_resolution; + uint32_t timer_num = timer_conf->timer_num; + uint32_t speed_mode = timer_conf->speed_mode; LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); periph_module_enable(PERIPH_LEDC_MODULE); - if (freq_hz == 0 || duty_resolution == 0 || duty_resolution > LEDC_TIMER_15_BIT) { + if (freq_hz == 0 || duty_resolution == 0 || duty_resolution >= LEDC_TIMER_BIT_MAX) { ESP_LOGE(LEDC_TAG, "freq_hz=%u duty_resolution=%u", freq_hz, duty_resolution); return ESP_ERR_INVALID_ARG; } @@ -230,7 +275,7 @@ esp_err_t ledc_timer_config(const ledc_timer_config_t* timer_conf) esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc_channel) { - LEDC_ARG_CHECK(ledc_channel <= LEDC_CHANNEL_7, "ledc_channel"); + LEDC_ARG_CHECK(ledc_channel < LEDC_CHANNEL_MAX, "ledc_channel"); LEDC_ARG_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "gpio_num"); LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO); @@ -245,22 +290,24 @@ esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc esp_err_t ledc_channel_config(const ledc_channel_config_t* ledc_conf) { + LEDC_ARG_CHECK(ledc_conf, "ledc_conf"); uint32_t speed_mode = ledc_conf->speed_mode; uint32_t gpio_num = ledc_conf->gpio_num; uint32_t ledc_channel = ledc_conf->channel; uint32_t timer_select = ledc_conf->timer_sel; uint32_t intr_type = ledc_conf->intr_type; uint32_t duty = ledc_conf->duty; - LEDC_ARG_CHECK(ledc_channel <= LEDC_CHANNEL_7, "ledc_channel"); + uint32_t hpoint = ledc_conf->hpoint; + LEDC_ARG_CHECK(ledc_channel < LEDC_CHANNEL_MAX, "ledc_channel"); LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); LEDC_ARG_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "gpio_num"); - LEDC_ARG_CHECK(timer_select <= LEDC_TIMER_3, "timer_select"); + LEDC_ARG_CHECK(timer_select < LEDC_TIMER_MAX, "timer_select"); periph_module_enable(PERIPH_LEDC_MODULE); esp_err_t ret = ESP_OK; /*set channel parameters*/ /* channel parameters decide how the waveform looks like in one period*/ - /* set channel duty, duty range is (0 ~ ((2 ** duty_resolution) - 1))*/ - ledc_set_duty(speed_mode, ledc_channel, duty); + /* set channel duty and hpoint value, duty range is (0 ~ ((2 ** duty_resolution) - 1)), max hpoint value is 0xfffff*/ + ledc_set_duty_with_hpoint(speed_mode, ledc_channel, duty, hpoint); /*update duty settings*/ ledc_update_duty(speed_mode, ledc_channel); /*bind the channel with the timer*/ @@ -284,7 +331,7 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t* ledc_conf) esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel) { LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); - LEDC_ARG_CHECK(channel <= LEDC_CHANNEL_7, "channel"); + LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel"); portENTER_CRITICAL(&ledc_spinlock); LEDC.channel_group[speed_mode].channel[channel].conf0.sig_out_en = 1; LEDC.channel_group[speed_mode].channel[channel].conf1.duty_start = 1; @@ -296,7 +343,7 @@ esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel) esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idle_level) { LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); - LEDC_ARG_CHECK(channel <= LEDC_CHANNEL_7, "channel"); + LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel"); portENTER_CRITICAL(&ledc_spinlock); LEDC.channel_group[speed_mode].channel[channel].conf0.idle_lv = idle_level & 0x1; LEDC.channel_group[speed_mode].channel[channel].conf0.sig_out_en = 0; @@ -310,42 +357,61 @@ esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t uint32_t step_num, uint32_t duty_cyle_num, uint32_t duty_scale) { LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); - LEDC_ARG_CHECK(channel <= LEDC_CHANNEL_7, "channel"); - LEDC_ARG_CHECK(fade_direction <= LEDC_DUTY_DIR_INCREASE, "fade_direction"); + LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel"); + LEDC_ARG_CHECK(fade_direction < LEDC_DUTY_DIR_MAX, "fade_direction"); LEDC_ARG_CHECK(step_num <= LEDC_DUTY_NUM_HSCH0_V, "step_num"); LEDC_ARG_CHECK(duty_cyle_num <= LEDC_DUTY_CYCLE_HSCH0_V, "duty_cycle_num"); LEDC_ARG_CHECK(duty_scale <= LEDC_DUTY_SCALE_HSCH0_V, "duty_scale"); - if (s_ledc_fade_rec[speed_mode][channel]) { - ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_DISABLE); - } + _ledc_fade_hw_acquire(speed_mode, channel); ledc_duty_config(speed_mode, channel, //uint32_t chan_num, - 0, //uint32_t hpoint_val, + LEDC_VAL_NO_CHANGE, duty << 4, //uint32_t duty_val,the least 4 bits are decimal part fade_direction, //uint32_t increase, step_num, //uint32_t duty_num, duty_cyle_num, //uint32_t duty_cycle, duty_scale //uint32_t duty_scale ); + _ledc_fade_hw_release(speed_mode, channel); return ESP_OK; } -esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty) +esp_err_t ledc_set_duty_with_hpoint(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, uint32_t hpoint) { LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); - LEDC_ARG_CHECK(channel <= LEDC_CHANNEL_7, "channel"); - if (s_ledc_fade_rec[speed_mode][channel]) { - ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_DISABLE); - } + LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel"); + LEDC_ARG_CHECK(hpoint <= LEDC_HPOINT_VAL_MAX, "hpoint"); + /* The channel configuration should not be changed before the fade operation is done. */ + _ledc_fade_hw_acquire(speed_mode, channel); ledc_duty_config(speed_mode, channel, //uint32_t chan_num, - 0, //uint32_t hpoint_val, + hpoint, //uint32_t hpoint_val, duty << 4, //uint32_t duty_val,the least 4 bits are decimal part 1, //uint32_t increase, 1, //uint32_t duty_num, 1, //uint32_t duty_cycle, 0 //uint32_t duty_scale ); + _ledc_fade_hw_release(speed_mode, channel); + return ESP_OK; +} + +esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty) +{ + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel"); + /* The channel configuration should not be changed before the fade operation is done. */ + _ledc_fade_hw_acquire(speed_mode, channel); + ledc_duty_config(speed_mode, + channel, //uint32_t chan_num, + LEDC_VAL_NO_CHANGE, + duty << 4, //uint32_t duty_val,the least 4 bits are decimal part + 1, //uint32_t increase, + 1, //uint32_t duty_num, + 1, //uint32_t duty_cycle, + 0 //uint32_t duty_scale + ); + _ledc_fade_hw_release(speed_mode, channel); return ESP_OK; } @@ -356,6 +422,14 @@ uint32_t ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel) return duty; } +int ledc_get_hpoint(ledc_mode_t speed_mode, ledc_channel_t channel) +{ + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode argument is invalid", LEDC_ERR_VAL); + LEDC_CHECK(channel < LEDC_CHANNEL_MAX, "channel argument is invalid", LEDC_ERR_VAL); + uint32_t hpoint = LEDC.channel_group[speed_mode].channel[channel].hpoint.hpoint; + return hpoint; +} + esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t freq_hz) { LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); @@ -417,17 +491,16 @@ void IRAM_ATTR ledc_fade_isr(void* arg) } uint32_t duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM; if (duty_cur == s_ledc_fade_rec[speed_mode][channel]->target_duty) { - if (s_ledc_fade_rec[speed_mode][channel]->mode == LEDC_FADE_WAIT_DONE) { - xSemaphoreGiveFromISR(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem, &HPTaskAwoken); - if (HPTaskAwoken == pdTRUE) { - portYIELD_FROM_ISR(); - } + xSemaphoreGiveFromISR(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem, &HPTaskAwoken); + if (HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR(); } continue; } uint32_t duty_tar = s_ledc_fade_rec[speed_mode][channel]->target_duty; int scale = s_ledc_fade_rec[speed_mode][channel]->scale; if (scale == 0) { + xSemaphoreGiveFromISR(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem, &HPTaskAwoken); continue; } int cycle = s_ledc_fade_rec[speed_mode][channel]->cycle_num; @@ -479,6 +552,10 @@ static esp_err_t ledc_fade_channel_deinit(ledc_mode_t speed_mode, ledc_channel_t static esp_err_t ledc_fade_channel_init_check(ledc_mode_t speed_mode, ledc_channel_t channel) { + if (s_ledc_fade_isr_handle == NULL) { + ESP_LOGE(LEDC_TAG, "Fade service not installed, call ledc_fade_func_install"); + return ESP_FAIL; + } if (s_ledc_fade_rec[speed_mode][channel] == NULL) { #if CONFIG_SPIRAM_USE_MALLOC s_ledc_fade_rec[speed_mode][channel] = (ledc_fade_t *) heap_caps_calloc(1, sizeof(ledc_fade_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); @@ -494,6 +571,7 @@ static esp_err_t ledc_fade_channel_init_check(ledc_mode_t speed_mode, ledc_chann s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem = xSemaphoreCreateBinary(); #endif s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux = xSemaphoreCreateMutex(); + xSemaphoreGive(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem); } if (s_ledc_fade_rec[speed_mode][channel] && s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux @@ -505,94 +583,123 @@ static esp_err_t ledc_fade_channel_init_check(ledc_mode_t speed_mode, ledc_chann } } -esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int max_fade_time_ms) +static esp_err_t _ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int scale, int cycle_num) { - LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); - LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel"); - LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK, LEDC_FADE_INIT_ERROR_STR, ESP_FAIL); - - int timer_sel = LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel; - uint32_t max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_resolution)) - 1; - LEDC_ARG_CHECK(target_duty <= max_duty, "target_duty"); - - uint32_t freq = ledc_get_freq(speed_mode, timer_sel); - uint32_t duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM; - uint32_t duty_delta = target_duty > duty_cur ? target_duty - duty_cur : duty_cur - target_duty; - - if (duty_delta == 0) { - return ESP_OK; - } - int total_cycles = max_fade_time_ms * freq / 1000; - if (total_cycles == 0) { - return ledc_set_duty(speed_mode, channel, target_duty); - } - int scale, cycle_num; - if (total_cycles > duty_delta) { - scale = 1; - cycle_num = total_cycles / duty_delta; - } else { - cycle_num = 1; - scale = (duty_delta + total_cycles - 1) / total_cycles; - } - return ledc_set_fade_with_step(speed_mode, channel, target_duty, scale, cycle_num); -} - -esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int scale, int cycle_num) -{ - LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); - LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel"); - LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL); - LEDC_ARG_CHECK(scale > 0, "scale"); - LEDC_ARG_CHECK(cycle_num > 0, "cycle_num"); - - int timer_sel = LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel; - uint32_t max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_resolution)) - 1; - LEDC_ARG_CHECK(target_duty <= max_duty, "target_duty"); - //disable the interrupt, so the operation will not mess up - ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_DISABLE); - portENTER_CRITICAL(&ledc_spinlock); uint32_t duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM; - uint32_t duty_delta = target_duty > duty_cur ? target_duty - duty_cur : duty_cur - target_duty; - if (duty_delta == 0) { - portEXIT_CRITICAL(&ledc_spinlock); - return ESP_OK; + // if duty == max_duty and scale and fade_down == 1, counter would overflow. + if (duty_cur == ledc_get_max_duty(speed_mode, channel)) { + duty_cur -= 1; } s_ledc_fade_rec[speed_mode][channel]->speed_mode = speed_mode; s_ledc_fade_rec[speed_mode][channel]->target_duty = target_duty; s_ledc_fade_rec[speed_mode][channel]->cycle_num = cycle_num; s_ledc_fade_rec[speed_mode][channel]->scale = scale; - int step_num; - if (duty_cur > target_duty) { - s_ledc_fade_rec[speed_mode][channel]->direction = LEDC_DUTY_DIR_DECREASE; - step_num = (duty_cur - target_duty) / scale; - step_num = step_num > LEDC_STEP_NUM_MAX ? LEDC_STEP_NUM_MAX : step_num; - } else { - s_ledc_fade_rec[speed_mode][channel]->direction = LEDC_DUTY_DIR_INCREASE; - step_num = (target_duty - duty_cur) / scale; - step_num = step_num > LEDC_STEP_NUM_MAX ? LEDC_STEP_NUM_MAX : step_num; + int step_num = 0; + int dir = LEDC_DUTY_DIR_DECREASE; + if (scale > 0) { + if (duty_cur > target_duty) { + s_ledc_fade_rec[speed_mode][channel]->direction = LEDC_DUTY_DIR_DECREASE; + step_num = (duty_cur - target_duty) / scale; + step_num = step_num > LEDC_STEP_NUM_MAX ? LEDC_STEP_NUM_MAX : step_num; + } else { + s_ledc_fade_rec[speed_mode][channel]->direction = LEDC_DUTY_DIR_INCREASE; + dir = LEDC_DUTY_DIR_INCREASE; + step_num = (target_duty - duty_cur) / scale; + step_num = step_num > LEDC_STEP_NUM_MAX ? LEDC_STEP_NUM_MAX : step_num; + } } portEXIT_CRITICAL(&ledc_spinlock); + if (scale > 0 && step_num > 0) { + ledc_duty_config(speed_mode, channel, LEDC_VAL_NO_CHANGE, duty_cur << 4, dir, step_num, cycle_num, scale); + ESP_LOGD(LEDC_TAG, "cur duty: %d; target: %d, step: %d, cycle: %d; scale: %d; dir: %d\n", + duty_cur, target_duty, step_num, cycle_num, scale, dir); + } else { + ledc_duty_config(speed_mode, channel, LEDC_VAL_NO_CHANGE, target_duty << 4, dir, 0, 1, 0); + ESP_LOGD(LEDC_TAG, "Set to target duty: %d", target_duty); + } + return ESP_OK; +} - ledc_set_fade( - speed_mode, - channel, - duty_cur, - s_ledc_fade_rec[speed_mode][channel]->direction, - step_num, - s_ledc_fade_rec[speed_mode][channel]->cycle_num, - s_ledc_fade_rec[speed_mode][channel]->scale - ); - ESP_LOGD(LEDC_TAG, "cur duty: %d; target: %d, step: %d, cycle: %d; scale: %d\n", - LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM, - target_duty, - step_num, - s_ledc_fade_rec[speed_mode][channel]->cycle_num, - s_ledc_fade_rec[speed_mode][channel]->scale - ); +static esp_err_t _ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int max_fade_time_ms) +{ + int timer_sel = LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel; + uint32_t freq = ledc_get_freq(speed_mode, timer_sel); + uint32_t duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM; + uint32_t duty_delta = target_duty > duty_cur ? target_duty - duty_cur : duty_cur - target_duty; + + if (duty_delta == 0) { + return _ledc_set_fade_with_step(speed_mode, channel, target_duty, 0, 0); + } + int total_cycles = max_fade_time_ms * freq / 1000; + if (total_cycles == 0) { + ESP_LOGW(LEDC_TAG, LEDC_FADE_TOO_FAST_STR); + return _ledc_set_fade_with_step(speed_mode, channel, target_duty, 0, 0); + } + int scale, cycle_num; + if (total_cycles > duty_delta) { + scale = 1; + cycle_num = total_cycles / duty_delta; + if (cycle_num > LEDC_DUTY_NUM_HSCH0_V) { + ESP_LOGW(LEDC_TAG, LEDC_FADE_TOO_SLOW_STR); + cycle_num = LEDC_DUTY_NUM_HSCH0_V; + } + } else { + cycle_num = 1; + scale = duty_delta / total_cycles; + } + return _ledc_set_fade_with_step(speed_mode, channel, target_duty, scale, cycle_num); +} + +static void _ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t fade_mode) +{ + s_ledc_fade_rec[speed_mode][channel]->mode = fade_mode; + // Clear interrupt status of channel int duty_resolution_ch0 = (speed_mode == LEDC_HIGH_SPEED_MODE) ? LEDC_DUTY_CHNG_END_HSCH0_INT_ENA_S : LEDC_DUTY_CHNG_END_LSCH0_INT_ENA_S; LEDC.int_clr.val |= BIT(duty_resolution_ch0 + channel); + // Enable interrupt for channel ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_FADE_END); + ledc_update_duty(speed_mode, channel); + if (fade_mode == LEDC_FADE_WAIT_DONE) { + xSemaphoreTake(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem, portMAX_DELAY); + } +} + +esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int max_fade_time_ms) +{ + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel"); + LEDC_ARG_CHECK(target_duty <= ledc_get_max_duty(speed_mode, channel), "target_duty"); + LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL); + + _ledc_fade_hw_acquire(speed_mode, channel); + _ledc_set_fade_with_time(speed_mode, channel, target_duty, max_fade_time_ms); + _ledc_fade_hw_release(speed_mode, channel); + return ESP_OK; +} + +esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num) +{ + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel"); + LEDC_ARG_CHECK((scale > 0) && (scale <= LEDC_DUTY_SCALE_HSCH0_V), "fade scale"); + LEDC_ARG_CHECK((cycle_num > 0) && (cycle_num <= LEDC_DUTY_CYCLE_HSCH0_V), "cycle_num"); + LEDC_ARG_CHECK(target_duty <= ledc_get_max_duty(speed_mode, channel), "target_duty"); + LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL); + + _ledc_fade_hw_acquire(speed_mode, channel); + _ledc_set_fade_with_step(speed_mode, channel, target_duty, scale, cycle_num); + _ledc_fade_hw_release(speed_mode, channel); + return ESP_OK; +} + +esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t fade_mode) +{ + LEDC_CHECK(s_ledc_fade_rec != NULL, LEDC_FADE_SERVICE_ERR_STR, ESP_ERR_INVALID_STATE); + LEDC_ARG_CHECK(fade_mode < LEDC_FADE_MAX, "fade_mode"); + _ledc_fade_hw_acquire(speed_mode, channel); + _ledc_fade_start(speed_mode, channel, fade_mode); + _ledc_fade_hw_release(speed_mode, channel); return ESP_OK; } @@ -620,19 +727,66 @@ void ledc_fade_func_uninstall() return; } -esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t wait_done) +/* + * The functions below are thread-safe version of APIs for duty and fade control. + * These APIs can be called from different tasks. + */ +esp_err_t ledc_set_duty_and_update(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, uint32_t hpoint) { - LEDC_CHECK(s_ledc_fade_rec != NULL, LEDC_FADE_SERVICE_ERR_STR, ESP_ERR_INVALID_STATE); - LEDC_ARG_CHECK(wait_done < LEDC_FADE_MAX, "wait_done"); - xSemaphoreTake(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux, portMAX_DELAY); - if (wait_done == LEDC_FADE_WAIT_DONE) { - s_ledc_fade_rec[speed_mode][channel]->mode = LEDC_FADE_WAIT_DONE; - ledc_update_duty(speed_mode, channel); - xSemaphoreTake(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem, portMAX_DELAY); - } else { - s_ledc_fade_rec[speed_mode][channel]->mode = LEDC_FADE_NO_WAIT; - ledc_update_duty(speed_mode, channel); - } - xSemaphoreGive(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux); + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel"); + LEDC_ARG_CHECK(duty <= ledc_get_max_duty(speed_mode, channel), "target_duty"); + _ledc_op_lock_acquire(speed_mode, channel); + _ledc_fade_hw_acquire(speed_mode, channel); + ledc_duty_config(speed_mode, + channel, //uint32_t chan_num, + hpoint, //uint32_t hpoint_val, + duty << 4, //uint32_t duty_val,the least 4 bits are decimal part + 1, //uint32_t increase, + 1, //uint32_t duty_num, + 1, //uint32_t duty_cycle, + 0 //uint32_t duty_scale + ); + ledc_update_duty(speed_mode, channel); + _ledc_fade_hw_release(speed_mode, channel); + _ledc_op_lock_release(speed_mode, channel); + return ESP_OK; +} + +esp_err_t ledc_set_fade_time_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t max_fade_time_ms, ledc_fade_mode_t fade_mode) +{ + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel"); + LEDC_ARG_CHECK(fade_mode < LEDC_FADE_MAX, "fade_mode"); + LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL); + LEDC_ARG_CHECK(target_duty <= ledc_get_max_duty(speed_mode, channel), "target_duty"); + _ledc_op_lock_acquire(speed_mode, channel); + _ledc_fade_hw_acquire(speed_mode, channel); + _ledc_set_fade_with_time(speed_mode, channel, target_duty, max_fade_time_ms); + _ledc_fade_start(speed_mode, channel, fade_mode); + if (fade_mode == LEDC_FADE_WAIT_DONE) { + _ledc_fade_hw_release(speed_mode, channel); + } + _ledc_op_lock_release(speed_mode, channel); + return ESP_OK; +} + +esp_err_t ledc_set_fade_step_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num, ledc_fade_mode_t fade_mode) +{ + LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode"); + LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel"); + LEDC_ARG_CHECK(fade_mode < LEDC_FADE_MAX, "fade_mode"); + LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL); + LEDC_ARG_CHECK((scale > 0) && (scale <= LEDC_DUTY_SCALE_HSCH0_V), "fade scale"); + LEDC_ARG_CHECK((cycle_num > 0) && (cycle_num <= LEDC_DUTY_CYCLE_HSCH0_V), "cycle_num"); + LEDC_ARG_CHECK(target_duty <= ledc_get_max_duty(speed_mode, channel), "target_duty"); + _ledc_op_lock_acquire(speed_mode, channel); + _ledc_fade_hw_acquire(speed_mode, channel); + _ledc_set_fade_with_step(speed_mode, channel, target_duty, scale, cycle_num); + _ledc_fade_start(speed_mode, channel, fade_mode); + if (fade_mode == LEDC_FADE_WAIT_DONE) { + _ledc_fade_hw_release(speed_mode, channel); + } + _ledc_op_lock_release(speed_mode, channel); return ESP_OK; } From 1c81e4be600b9ca8abe1af3beba93c15f561960a Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Sun, 13 May 2018 11:46:09 +0800 Subject: [PATCH 076/187] esp32: fix interrupt list insert issue If the allocated interrupt list is not empty and the new item will be inserted as the header of the list, insert_vector_desc() causes crash because pre is null. This commit fix this issue. --- components/esp32/intr_alloc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/esp32/intr_alloc.c b/components/esp32/intr_alloc.c index ab0c3126fa..22d97ccc88 100644 --- a/components/esp32/intr_alloc.c +++ b/components/esp32/intr_alloc.c @@ -194,10 +194,10 @@ static void insert_vector_desc(vector_desc_t *to_insert) prev=vd; vd=vd->next; } - if (vd==NULL && prev==NULL) { + if ((vector_desc_head==NULL) || (prev==NULL)) { //First item + to_insert->next = vd; vector_desc_head=to_insert; - vector_desc_head->next=NULL; } else { prev->next=to_insert; to_insert->next=vd; From 57297cf7b7512c877b564a81ea5a3b2d33081bcb Mon Sep 17 00:00:00 2001 From: XiaXiaotian Date: Mon, 5 Feb 2018 11:52:56 +0800 Subject: [PATCH 077/187] add sniffer control packet support --- components/esp32/include/esp_wifi.h | 25 +++++++++++++++++++++++ components/esp32/include/esp_wifi_types.h | 21 +++++++++++++++---- components/esp32/lib | 2 +- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h index 0b24b71cb2..79d6bd4b50 100755 --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -674,6 +674,31 @@ esp_err_t esp_wifi_set_promiscuous_filter(const wifi_promiscuous_filter_t *filte */ esp_err_t esp_wifi_get_promiscuous_filter(wifi_promiscuous_filter_t *filter); +/** + * @brief Enable subtype filter of the control packet in promiscuous mode. + * + * @note The default filter is to filter none control packet. + * + * @param filter the subtype of the control packet filtered in promiscuous mode. + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + */ +esp_err_t esp_wifi_set_promiscuous_ctrl_filter(const wifi_promiscuous_filter_t *filter); + +/** + * @brief Get the subtype filter of the control packet in promiscuous mode. + * + * @param[out] filter store the current status of subtype filter of the control packet in promiscuous mode + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument + */ +esp_err_t esp_wifi_get_promiscuous_ctrl_filter(wifi_promiscuous_filter_t *filter); + /** * @brief Set the configuration of the ESP32 STA or AP * diff --git a/components/esp32/include/esp_wifi_types.h b/components/esp32/include/esp_wifi_types.h index 0adba4c239..4f1c4cd71e 100755 --- a/components/esp32/include/esp_wifi_types.h +++ b/components/esp32/include/esp_wifi_types.h @@ -332,6 +332,7 @@ typedef struct { */ typedef enum { WIFI_PKT_MGMT, /**< Management frame, indicates 'buf' argument is wifi_promiscuous_pkt_t */ + WIFI_PKT_CTRL, /**< Control frame, indicates 'buf' argument is wifi_promiscuous_pkt_t */ WIFI_PKT_DATA, /**< Data frame, indiciates 'buf' argument is wifi_promiscuous_pkt_t */ WIFI_PKT_MISC, /**< Other type, such as MIMO etc. 'buf' argument is wifi_promiscuous_pkt_t but the payload is zero length. */ } wifi_promiscuous_pkt_type_t; @@ -339,10 +340,22 @@ typedef enum { #define WIFI_PROMIS_FILTER_MASK_ALL (0xFFFFFFFF) /**< filter all packets */ #define WIFI_PROMIS_FILTER_MASK_MGMT (1) /**< filter the packets with type of WIFI_PKT_MGMT */ -#define WIFI_PROMIS_FILTER_MASK_DATA (1<<1) /**< filter the packets with type of WIFI_PKT_DATA */ -#define WIFI_PROMIS_FILTER_MASK_MISC (1<<2) /**< filter the packets with type of WIFI_PKT_MISC */ -#define WIFI_PROMIS_FILTER_MASK_DATA_MPDU (1<<3) /**< filter the MPDU which is a kind of WIFI_PKT_DATA */ -#define WIFI_PROMIS_FILTER_MASK_DATA_AMPDU (1<<4) /**< filter the AMPDU which is a kind of WIFI_PKT_DATA */ +#define WIFI_PROMIS_FILTER_MASK_CTRL (1<<1) /**< filter the packets with type of WIFI_PKT_CTRL */ +#define WIFI_PROMIS_FILTER_MASK_DATA (1<<2) /**< filter the packets with type of WIFI_PKT_DATA */ +#define WIFI_PROMIS_FILTER_MASK_MISC (1<<3) /**< filter the packets with type of WIFI_PKT_MISC */ +#define WIFI_PROMIS_FILTER_MASK_DATA_MPDU (1<<4) /**< filter the MPDU which is a kind of WIFI_PKT_DATA */ +#define WIFI_PROMIS_FILTER_MASK_DATA_AMPDU (1<<5) /**< filter the AMPDU which is a kind of WIFI_PKT_DATA */ + +#define WIFI_PROMIS_CTRL_FILTER_MASK_ALL (0xFF800000) /**< filter all control packets */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_WRAPPER (1<<23) /**< filter the control packets with subtype of Control Wrapper */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_BAR (1<<24) /**< filter the control packets with subtype of Block Ack Request */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_BA (1<<25) /**< filter the control packets with subtype of Block Ack */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_PSPOLL (1<<26) /**< filter the control packets with subtype of PS-Poll */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_RTS (1<<27) /**< filter the control packets with subtype of RTS */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_CTS (1<<28) /**< filter the control packets with subtype of CTS */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_ACK (1<<29) /**< filter the control packets with subtype of ACK */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_CFEND (1<<30) /**< filter the control packets with subtype of CF-END */ +#define WIFI_PROMIS_CTRL_FILTER_MASK_CFENDACK (1<<31) /**< filter the control packets with subtype of CF-END+CF-ACK */ /** @brief Mask for filtering different packet types in promiscuous mode. */ typedef struct { diff --git a/components/esp32/lib b/components/esp32/lib index efae38d4d6..a93e18a06e 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit efae38d4d6f43c59e1570fe6dd0f483b26cbd7e7 +Subproject commit a93e18a06ef30002a92522054d7cd13206e30d4d From 4345e198cefcab08d6b086eeaab8569ea642f7fe Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Fri, 4 May 2018 11:44:38 +0200 Subject: [PATCH 078/187] Implement VFS support for access() Closes https://github.com/espressif/esp-idf/issues/1085 --- components/fatfs/src/vfs_fat.c | 32 ++++++- components/vfs/include/esp_vfs.h | 7 ++ components/vfs/test/test_vfs_access.c | 127 ++++++++++++++++++++++++++ components/vfs/vfs.c | 14 +++ components/vfs/vfs_uart.c | 24 ++++- 5 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 components/vfs/test/test_vfs_access.c diff --git a/components/fatfs/src/vfs_fat.c b/components/fatfs/src/vfs_fat.c index 1e059e134e..70b780d527 100644 --- a/components/fatfs/src/vfs_fat.c +++ b/components/fatfs/src/vfs_fat.c @@ -84,6 +84,7 @@ static void vfs_fat_seekdir(void* ctx, DIR* pdir, long offset); static int vfs_fat_closedir(void* ctx, DIR* pdir); static int vfs_fat_mkdir(void* ctx, const char* name, mode_t mode); static int vfs_fat_rmdir(void* ctx, const char* name); +static int vfs_fat_access(void* ctx, const char *path, int amode); static vfs_fat_ctx_t* s_fat_ctxs[FF_VOLUMES] = { NULL, NULL }; //backwards-compatibility with esp_vfs_fat_unregister() @@ -141,7 +142,8 @@ esp_err_t esp_vfs_fat_register(const char* base_path, const char* fat_drive, siz .seekdir_p = &vfs_fat_seekdir, .telldir_p = &vfs_fat_telldir, .mkdir_p = &vfs_fat_mkdir, - .rmdir_p = &vfs_fat_rmdir + .rmdir_p = &vfs_fat_rmdir, + .access_p = &vfs_fat_access, }; size_t ctx_size = sizeof(vfs_fat_ctx_t) + max_files * sizeof(FIL); vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) calloc(1, ctx_size); @@ -720,3 +722,31 @@ static int vfs_fat_rmdir(void* ctx, const char* name) } return 0; } + +static int vfs_fat_access(void* ctx, const char *path, int amode) +{ + FILINFO info; + int ret = 0; + FRESULT res; + + vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx; + + _lock_acquire(&fat_ctx->lock); + prepend_drive_to_path(fat_ctx, &path, NULL); + res = f_stat(path, &info); + _lock_release(&fat_ctx->lock); + + if (res == FR_OK) { + if (((amode & W_OK) == W_OK) && ((info.fattrib & AM_RDO) == AM_RDO)) { + ret = -1; + errno = EACCES; + } + // There is no flag to test readable or executable: we assume that if + // it exists then it is readable and executable + } else { + ret = -1; + errno = ENOENT; + } + + return ret; +} diff --git a/components/vfs/include/esp_vfs.h b/components/vfs/include/esp_vfs.h index 54aaaba26d..202be24859 100644 --- a/components/vfs/include/esp_vfs.h +++ b/components/vfs/include/esp_vfs.h @@ -18,6 +18,9 @@ #include #include #include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" #include "esp_err.h" #include #include @@ -160,6 +163,10 @@ typedef struct int (*fsync_p)(void* ctx, int fd); int (*fsync)(int fd); }; + union { + int (*access_p)(void* ctx, const char *path, int amode); + int (*access)(const char *path, int amode); + }; } esp_vfs_t; diff --git a/components/vfs/test/test_vfs_access.c b/components/vfs/test/test_vfs_access.c new file mode 100644 index 0000000000..02e7d56f82 --- /dev/null +++ b/components/vfs/test/test_vfs_access.c @@ -0,0 +1,127 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include "unity.h" +#include "driver/uart.h" +#include "esp_vfs.h" +#include "esp_vfs_dev.h" +#include "esp_vfs_fat.h" +#include "wear_levelling.h" + +static wl_handle_t test_wl_handle; + +TEST_CASE("Can use access() for UART", "[vfs]") +{ + const char *uarts[] = {"/dev/uart/0", "/dev/uart/1", "/dev/uart/2"}; + + uart_driver_install(UART_NUM_0, 256, 0, 0, NULL, 0); + uart_driver_install(UART_NUM_1, 256, 0, 0, NULL, 0); + uart_driver_install(UART_NUM_2, 256, 0, 0, NULL, 0); + + for (int i = 0; i < sizeof(uarts)/sizeof(uarts[0]); ++i) { + TEST_ASSERT_EQUAL_MESSAGE(access(uarts[i], F_OK), 0, uarts[i]); + + TEST_ASSERT_EQUAL_MESSAGE(access(uarts[i], R_OK), 0, uarts[i]); + TEST_ASSERT_EQUAL_MESSAGE(access(uarts[i], W_OK), 0, uarts[i]); + TEST_ASSERT_EQUAL_MESSAGE(access(uarts[i], X_OK), -1, uarts[i]); + TEST_ASSERT_EQUAL_MESSAGE(errno, EACCES, uarts[i]); + + TEST_ASSERT_EQUAL_MESSAGE(access(uarts[i], R_OK | W_OK), 0, uarts[i]); + TEST_ASSERT_EQUAL_MESSAGE(access(uarts[i], R_OK | X_OK), -1, uarts[i]); + TEST_ASSERT_EQUAL_MESSAGE(errno, EACCES, uarts[i]); + TEST_ASSERT_EQUAL_MESSAGE(access(uarts[i], W_OK | X_OK), -1, uarts[i]); + TEST_ASSERT_EQUAL_MESSAGE(errno, EACCES, uarts[i]); + TEST_ASSERT_EQUAL_MESSAGE(access(uarts[i], R_OK | W_OK | X_OK), -1, uarts[i]); + TEST_ASSERT_EQUAL_MESSAGE(errno, EACCES, uarts[i]); + } + + TEST_ASSERT_EQUAL(access("/dev/uart/3", F_OK), -1); + TEST_ASSERT_EQUAL(errno, ENOENT); + + uart_driver_delete(UART_NUM_0); + uart_driver_delete(UART_NUM_1); + uart_driver_delete(UART_NUM_2); +} + +static inline void test_spi_flash_setup() +{ + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = true, + .max_files = 5 + }; + + TEST_ESP_OK(esp_vfs_fat_spiflash_mount("/spiflash", NULL, &mount_config, &test_wl_handle)); +} + +static inline void test_spi_flash_teardown() +{ + TEST_ESP_OK(esp_vfs_fat_spiflash_unmount("/spiflash", test_wl_handle)); +} + +static inline void test_fatfs_create_file(const char *name) +{ + int fd = open(name, O_WRONLY | O_CREAT | O_TRUNC); + TEST_ASSERT_NOT_EQUAL(fd, -1); + TEST_ASSERT_EQUAL(0, close(fd)); +} + +static inline void test_fatfs_delete_file(const char *name) +{ + int ret = unlink(name); + TEST_ASSERT_EQUAL(ret, 0); +} + +TEST_CASE("Can use access() for FATFS", "[vfs][fatfs][wear_levelling]") +{ + const char *path = "/spiflash/access.txt"; + + test_spi_flash_setup(); + + { + int ret = access(path, F_OK); + + if (ret != -1) { + // it wasn't deleted before so we delete it now to pass the test + // case the next time + test_fatfs_delete_file(path); + } + + TEST_ASSERT_EQUAL(ret, -1); + TEST_ASSERT_EQUAL(errno, ENOENT); + } + + test_fatfs_create_file(path); + TEST_ASSERT_EQUAL(access(path, F_OK), 0); + + TEST_ASSERT_EQUAL(access(path, R_OK), 0); + TEST_ASSERT_EQUAL(access(path, W_OK), 0); + TEST_ASSERT_EQUAL(access(path, X_OK), 0); + TEST_ASSERT_EQUAL(access(path, R_OK | W_OK), 0); + TEST_ASSERT_EQUAL(access(path, R_OK | X_OK), 0); + TEST_ASSERT_EQUAL(access(path, W_OK | X_OK), 0); + TEST_ASSERT_EQUAL(access(path, R_OK | W_OK | X_OK), 0); + + //TODO f_chmod the file and re-test the access rights (this requires + // f_chmod support to be implemented in VFS) + + test_fatfs_delete_file(path); + TEST_ASSERT_EQUAL(access(path, F_OK), -1); + TEST_ASSERT_EQUAL(errno, ENOENT); + + test_spi_flash_teardown(); +} diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index 2e84571b3e..d7ca283ec3 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -623,3 +623,17 @@ int fsync(int fd) CHECK_AND_CALL(ret, r, vfs, fsync, local_fd); return ret; } + +int access(const char *path, int amode) +{ + int ret; + const vfs_entry_t* vfs = get_vfs_for_path(path); + struct _reent* r = __getreent(); + if (vfs == NULL) { + __errno_r(r) = ENOENT; + return -1; + } + const char* path_within_vfs = translate_path(vfs, path); + CHECK_AND_CALL(ret, r, vfs, access, path_within_vfs, amode); + return ret; +} diff --git a/components/vfs/vfs_uart.c b/components/vfs/vfs_uart.c index 13b227aad5..83e89acc34 100644 --- a/components/vfs/vfs_uart.c +++ b/components/vfs/vfs_uart.c @@ -267,6 +267,27 @@ static int uart_fcntl(int fd, int cmd, va_list args) return result; } +static int uart_access(const char *path, int amode) +{ + int ret = -1; + + if (strcmp(path, "/0") == 0 || strcmp(path, "/1") == 0 || strcmp(path, "/2") == 0) { + if (F_OK == amode) { + ret = 0; //path exists + } else { + if ((((amode & R_OK) == R_OK) || ((amode & W_OK) == W_OK)) && ((amode & X_OK) != X_OK)) { + ret = 0; //path is readable and/or writable but not executable + } else { + errno = EACCES; + } + } + } else { + errno = ENOENT; + } + + return ret; +} + void esp_vfs_dev_uart_register() { esp_vfs_t vfs = { @@ -276,7 +297,8 @@ void esp_vfs_dev_uart_register() .fstat = &uart_fstat, .close = &uart_close, .read = &uart_read, - .fcntl = &uart_fcntl + .fcntl = &uart_fcntl, + .access = &uart_access, }; ESP_ERROR_CHECK(esp_vfs_register("/dev/uart", &vfs, NULL)); } From c94a5ecfdd4f90a9f2be760545d671a80ad85c6d Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 14 May 2018 16:07:18 +0800 Subject: [PATCH 079/187] mbedtls: Add mbedtls submodule check to build system --- components/mbedtls/component.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/mbedtls/component.mk b/components/mbedtls/component.mk index af0b8b6ea7..9db378c1be 100644 --- a/components/mbedtls/component.mk +++ b/components/mbedtls/component.mk @@ -7,3 +7,6 @@ COMPONENT_ADD_INCLUDEDIRS := port/include mbedtls/include COMPONENT_SRCDIRS := mbedtls/library port COMPONENT_OBJEXCLUDE := mbedtls/library/net_sockets.o + +COMPONENT_SUBMODULES += mbedtls + From 036dbce3d0d1af49713d45af9fbbed1ac8f772c6 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 14 May 2018 16:07:27 +0800 Subject: [PATCH 080/187] Fix "undefined variable which git" warning when submodules not initialized --- make/project.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/project.mk b/make/project.mk index a2f26e8f11..01b29bcb38 100644 --- a/make/project.mk +++ b/make/project.mk @@ -511,7 +511,7 @@ check-submodules: $(IDF_PATH)/$(1)/.git $(IDF_PATH)/$(1)/.git: @echo "WARNING: Missing submodule $(1)..." [ -e ${IDF_PATH}/.git ] || ( echo "ERROR: esp-idf must be cloned from git to work."; exit 1) - [ -x $$(which git) ] || ( echo "ERROR: Need to run 'git submodule init $(1)' in esp-idf root directory."; exit 1) + [ -x "$(shell which git)" ] || ( echo "ERROR: Need to run 'git submodule init $(1)' in esp-idf root directory."; exit 1) @echo "Attempting 'git submodule update --init $(1)' in esp-idf root directory..." cd ${IDF_PATH} && git submodule update --init $(1) From c384fa24924914d27f8b31ac23e35d6350b752be Mon Sep 17 00:00:00 2001 From: jack Date: Tue, 24 Apr 2018 16:38:46 +0800 Subject: [PATCH 081/187] rename clock enable and reset bits for SPI modules 1.The names of clock enable and reset bits do not match with TRM, just rename them. --- components/driver/periph_ctrl.c | 12 ++++++------ components/esp32/clk.c | 8 ++++---- components/esp32/spiram_psram.c | 2 +- components/esp32/system_api.c | 2 +- components/esp32/test/test_intr_alloc.c | 6 +++--- components/soc/esp32/include/soc/dport_reg.h | 18 ++++++++++++------ 6 files changed, 27 insertions(+), 21 deletions(-) diff --git a/components/driver/periph_ctrl.c b/components/driver/periph_ctrl.c index 67431a4276..59baf48311 100644 --- a/components/driver/periph_ctrl.c +++ b/components/driver/periph_ctrl.c @@ -91,11 +91,11 @@ static uint32_t get_clk_en_mask(periph_module_t periph) case PERIPH_PCNT_MODULE: return DPORT_PCNT_CLK_EN; case PERIPH_SPI_MODULE: - return DPORT_SPI_CLK_EN_1; + return DPORT_SPI01_CLK_EN; case PERIPH_HSPI_MODULE: - return DPORT_SPI_CLK_EN; + return DPORT_SPI2_CLK_EN; case PERIPH_VSPI_MODULE: - return DPORT_SPI_CLK_EN_2; + return DPORT_SPI3_CLK_EN; case PERIPH_SPI_DMA_MODULE: return DPORT_SPI_DMA_CLK_EN; case PERIPH_SDMMC_MODULE: @@ -159,11 +159,11 @@ static uint32_t get_rst_en_mask(periph_module_t periph) case PERIPH_PCNT_MODULE: return DPORT_PCNT_RST; case PERIPH_SPI_MODULE: - return DPORT_SPI_RST_1; + return DPORT_SPI01_RST; case PERIPH_HSPI_MODULE: - return DPORT_SPI_RST; + return DPORT_SPI2_RST; case PERIPH_VSPI_MODULE: - return DPORT_SPI_RST_2; + return DPORT_SPI3_RST; case PERIPH_SPI_DMA_MODULE: return DPORT_SPI_DMA_RST; case PERIPH_SDMMC_MODULE: diff --git a/components/esp32/clk.c b/components/esp32/clk.c index ec8d73c9bb..64fe3af4a1 100644 --- a/components/esp32/clk.c +++ b/components/esp32/clk.c @@ -221,7 +221,7 @@ void esp_perip_clk_init(void) #if CONFIG_CONSOLE_UART_NUM != 2 DPORT_UART2_CLK_EN | #endif - DPORT_SPI_CLK_EN | + DPORT_SPI2_CLK_EN | DPORT_I2C_EXT0_CLK_EN | DPORT_UHCI0_CLK_EN | DPORT_RMT_CLK_EN | @@ -229,7 +229,7 @@ void esp_perip_clk_init(void) DPORT_LEDC_CLK_EN | DPORT_UHCI1_CLK_EN | DPORT_TIMERGROUP1_CLK_EN | - DPORT_SPI_CLK_EN_2 | + DPORT_SPI3_CLK_EN | DPORT_PWM0_CLK_EN | DPORT_I2C_EXT1_CLK_EN | DPORT_CAN_CLK_EN | @@ -253,11 +253,11 @@ void esp_perip_clk_init(void) #if CONFIG_SPIRAM_SPEED_80M -//80MHz SPIRAM uses SPI2 as well; it's initialized before this is called. Because it is used in +//80MHz SPIRAM uses SPI3 as well; it's initialized before this is called. Because it is used in //a weird mode where clock to the peripheral is disabled but reset is also disabled, it 'hangs' //in a state where it outputs a continuous 80MHz signal. Mask its bit here because we should //not modify that state, regardless of what we calculated earlier. - common_perip_clk &= ~DPORT_SPI_CLK_EN_2; + common_perip_clk &= ~DPORT_SPI3_CLK_EN; #endif /* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock, diff --git a/components/esp32/spiram_psram.c b/components/esp32/spiram_psram.c index 279de8d2f7..50a8571d84 100644 --- a/components/esp32/spiram_psram.c +++ b/components/esp32/spiram_psram.c @@ -543,7 +543,7 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad while (1) { spi_status = READ_PERI_REG(SPI_EXT2_REG(PSRAM_SPI_3)); if (spi_status != 0 && spi_status != 1) { - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN); break; } } diff --git a/components/esp32/system_api.c b/components/esp32/system_api.c index 9b242c789f..8068f3bc4f 100644 --- a/components/esp32/system_api.c +++ b/components/esp32/system_api.c @@ -327,7 +327,7 @@ void IRAM_ATTR esp_restart_noos() // Reset timer/spi/uart DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, - DPORT_TIMERS_RST | DPORT_SPI_RST_1 | DPORT_UART_RST); + DPORT_TIMERS_RST | DPORT_SPI01_RST | DPORT_UART_RST); DPORT_REG_WRITE(DPORT_PERIP_RST_EN_REG, 0); // Set CPU back to XTAL source, no PLL, same as hard reset diff --git a/components/esp32/test/test_intr_alloc.c b/components/esp32/test/test_intr_alloc.c index 2eef456a56..00a325b1ea 100644 --- a/components/esp32/test/test_intr_alloc.c +++ b/components/esp32/test/test_intr_alloc.c @@ -16,6 +16,7 @@ #include "soc/dport_reg.h" #include "soc/io_mux_reg.h" #include "esp_intr_alloc.h" +#include "driver/periph_ctrl.h" #include "driver/timer.h" @@ -266,9 +267,8 @@ TEST_CASE("allocate 2 handlers for a same source and remove the later one","[esp intr_alloc_test_ctx_t ctx = {false, false, false, false }; intr_handle_t handle1, handle2; - //enable spi - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN ); - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST); + //enable HSPI(spi2) + periph_module_enable(PERIPH_HSPI_MODULE); esp_err_t r; r=esp_intr_alloc(ETS_SPI2_INTR_SOURCE, ESP_INTR_FLAG_SHARED, int_handler1, &ctx, &handle1); diff --git a/components/soc/esp32/include/soc/dport_reg.h b/components/soc/esp32/include/soc/dport_reg.h index b7c9bdb905..ecb1cf3a29 100644 --- a/components/soc/esp32/include/soc/dport_reg.h +++ b/components/soc/esp32/include/soc/dport_reg.h @@ -958,7 +958,8 @@ #define DPORT_CAN_CLK_EN (BIT(19)) #define DPORT_I2C_EXT1_CLK_EN (BIT(18)) #define DPORT_PWM0_CLK_EN (BIT(17)) -#define DPORT_SPI_CLK_EN_2 (BIT(16)) +#define DPORT_SPI_CLK_EN_2 (BIT(16)) /** Deprecated, please use DPORT_SPI3_CLK_EN **/ +#define DPORT_SPI3_CLK_EN (BIT(16)) #define DPORT_TIMERGROUP1_CLK_EN (BIT(15)) #define DPORT_EFUSE_CLK_EN (BIT(14)) #define DPORT_TIMERGROUP_CLK_EN (BIT(13)) @@ -968,12 +969,14 @@ #define DPORT_RMT_CLK_EN (BIT(9)) #define DPORT_UHCI0_CLK_EN (BIT(8)) #define DPORT_I2C_EXT0_CLK_EN (BIT(7)) -#define DPORT_SPI_CLK_EN (BIT(6)) +#define DPORT_SPI_CLK_EN (BIT(6)) /** Deprecated, please use DPORT_SPI2_CLK_EN **/ +#define DPORT_SPI2_CLK_EN (BIT(6)) #define DPORT_UART1_CLK_EN (BIT(5)) #define DPORT_I2S0_CLK_EN (BIT(4)) #define DPORT_WDG_CLK_EN (BIT(3)) #define DPORT_UART_CLK_EN (BIT(2)) -#define DPORT_SPI_CLK_EN_1 (BIT(1)) +#define DPORT_SPI_CLK_EN_1 (BIT(1)) /** Deprecated, please use DPORT_SPI01_CLK_EN **/ +#define DPORT_SPI01_CLK_EN (BIT(1)) #define DPORT_TIMERS_CLK_EN (BIT(0)) #define DPORT_PERIP_RST_EN_REG (DR_REG_DPORT_BASE + 0x0C4) /* DPORT_PERIP_RST : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ @@ -992,7 +995,8 @@ #define DPORT_CAN_RST (BIT(19)) #define DPORT_I2C_EXT1_RST (BIT(18)) #define DPORT_PWM0_RST (BIT(17)) -#define DPORT_SPI_RST_2 (BIT(16)) +#define DPORT_SPI_RST_2 (BIT(16)) /** Deprecated, please use DPORT_SPI3_RST **/ +#define DPORT_SPI3_RST (BIT(16)) #define DPORT_TIMERGROUP1_RST (BIT(15)) #define DPORT_EFUSE_RST (BIT(14)) #define DPORT_TIMERGROUP_RST (BIT(13)) @@ -1002,12 +1006,14 @@ #define DPORT_RMT_RST (BIT(9)) #define DPORT_UHCI0_RST (BIT(8)) #define DPORT_I2C_EXT0_RST (BIT(7)) -#define DPORT_SPI_RST (BIT(6)) +#define DPORT_SPI_RST (BIT(6)) /** Deprecated, please use DPORT_SPI2_RST **/ +#define DPORT_SPI2_RST (BIT(6)) #define DPORT_UART1_RST (BIT(5)) #define DPORT_I2S0_RST (BIT(4)) #define DPORT_WDG_RST (BIT(3)) #define DPORT_UART_RST (BIT(2)) -#define DPORT_SPI_RST_1 (BIT(1)) +#define DPORT_SPI_RST_1 (BIT(1)) /** Deprecated, please use DPORT_SPI01_RST **/ +#define DPORT_SPI01_RST (BIT(1)) #define DPORT_TIMERS_RST (BIT(0)) #define DPORT_SLAVE_SPI_CONFIG_REG (DR_REG_DPORT_BASE + 0x0C8) /* DPORT_SPI_DECRYPT_ENABLE : R/W ;bitpos:[12] ;default: 1'b0 ; */ From ca08397b6bf64dd384dd9f40588a7f0b59447764 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Mon, 14 May 2018 11:54:27 +0200 Subject: [PATCH 082/187] Fix compilation errors when -O3 is used Closes https://github.com/espressif/esp-idf/issues/718 --- components/bt/bluedroid/stack/btm/btm_ble.c | 2 +- components/driver/rtc_module.c | 5 +++-- components/fatfs/src/vfs_fat.c | 1 + components/sdmmc/sdmmc_cmd.c | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/components/bt/bluedroid/stack/btm/btm_ble.c b/components/bt/bluedroid/stack/btm/btm_ble.c index 872a24e6fa..2d3c751724 100644 --- a/components/bt/bluedroid/stack/btm/btm_ble.c +++ b/components/bt/bluedroid/stack/btm/btm_ble.c @@ -880,7 +880,7 @@ tBTM_SEC_ACTION btm_ble_determine_security_act(BOOLEAN is_originator, BD_ADDR bd auth_req |= BTM_LE_AUTH_REQ_MITM; } - tBTM_BLE_SEC_REQ_ACT ble_sec_act; + tBTM_BLE_SEC_REQ_ACT ble_sec_act = BTM_BLE_SEC_REQ_ACT_NONE; btm_ble_link_sec_check(bdaddr, auth_req, &ble_sec_act); BTM_TRACE_DEBUG ("%s ble_sec_act %d", __func__ , ble_sec_act); diff --git a/components/driver/rtc_module.c b/components/driver/rtc_module.c index c2bff692b4..bdcc43c1d6 100644 --- a/components/driver/rtc_module.c +++ b/components/driver/rtc_module.c @@ -508,9 +508,10 @@ static void touch_pad_filter_cb(void *arg) if (s_touch_pad_filter == NULL) { return; } - uint16_t val; + uint16_t val = 0; for (int i = 0; i < TOUCH_PAD_MAX; i++) { - touch_pad_read(i, &val); + (void) touch_pad_read(i, &val); + // if touch_pad_read fails then the previous value of val is used s_touch_pad_filter->filtered_val[i] = s_touch_pad_filter->filtered_val[i] == 0 ? (val << TOUCH_PAD_SHIFT_DEFAULT) : s_touch_pad_filter->filtered_val[i]; s_touch_pad_filter->filtered_val[i] = _touch_filter_iir((val << TOUCH_PAD_SHIFT_DEFAULT), s_touch_pad_filter->filtered_val[i], TOUCH_PAD_FILTER_FACTOR_DEFAULT); diff --git a/components/fatfs/src/vfs_fat.c b/components/fatfs/src/vfs_fat.c index 1e059e134e..439cc875f7 100644 --- a/components/fatfs/src/vfs_fat.c +++ b/components/fatfs/src/vfs_fat.c @@ -637,6 +637,7 @@ static int vfs_fat_readdir_r(void* ctx, DIR* pdir, vfs_fat_dir_t* fat_dir = (vfs_fat_dir_t*) pdir; FRESULT res = f_readdir(&fat_dir->ffdir, &fat_dir->filinfo); if (res != FR_OK) { + *out_dirent = NULL; ESP_LOGD(TAG, "%s: fresult=%d", __func__, res); return fresult_to_errno(res); } diff --git a/components/sdmmc/sdmmc_cmd.c b/components/sdmmc/sdmmc_cmd.c index 7279dec44c..f46dbf324b 100644 --- a/components/sdmmc/sdmmc_cmd.c +++ b/components/sdmmc/sdmmc_cmd.c @@ -321,7 +321,7 @@ esp_err_t sdmmc_card_init(const sdmmc_host_t* config, sdmmc_card_t* card) } else { /* IO card */ if (config->flags & SDMMC_HOST_FLAG_4BIT) { - uint8_t card_cap; + uint8_t card_cap = 0; err = sdmmc_io_rw_direct(card, 0, SD_IO_CCCR_CARD_CAP, SD_ARG_CMD52_READ, &card_cap); if (err != ESP_OK) { From a8d26d7e4d8652b5ec39b28085217c11de009659 Mon Sep 17 00:00:00 2001 From: kooho <2229179028@qq.com> Date: Sat, 24 Feb 2018 16:36:21 +0800 Subject: [PATCH 083/187] driver(rmt):Fix rmt_tx_stop bug. --- components/driver/rmt.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/components/driver/rmt.c b/components/driver/rmt.c index 046b634ca9..84d7a81db1 100644 --- a/components/driver/rmt.c +++ b/components/driver/rmt.c @@ -66,6 +66,7 @@ typedef struct { int tx_offset; int tx_len_rem; int tx_sub_len; + bool wait_done; //Mark whether wait tx done. rmt_channel_t channel; const rmt_item32_t* tx_data; xSemaphoreHandle tx_sem; @@ -181,7 +182,10 @@ esp_err_t rmt_tx_stop(rmt_channel_t channel) { RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&rmt_spinlock); + RMTMEM.chan[channel].data32[0].val = 0; RMT.conf_ch[channel].conf1.tx_start = 0; + RMT.conf_ch[channel].conf1.mem_rd_rst = 1; + RMT.conf_ch[channel].conf1.mem_rd_rst = 0; portEXIT_CRITICAL(&rmt_spinlock); return ESP_OK; } @@ -548,6 +552,8 @@ static void IRAM_ATTR rmt_driver_isr_default(void* arg) //TX END case 0: xSemaphoreGiveFromISR(p_rmt->tx_sem, &HPTaskAwoken); + RMT.conf_ch[channel].conf1.mem_rd_rst = 1; + RMT.conf_ch[channel].conf1.mem_rd_rst = 0; if(HPTaskAwoken == pdTRUE) { portYIELD_FROM_ISR(); } @@ -635,8 +641,10 @@ esp_err_t rmt_driver_uninstall(rmt_channel_t channel) if(p_rmt_obj[channel] == NULL) { return ESP_OK; } - xSemaphoreTake(p_rmt_obj[channel]->tx_sem, portMAX_DELAY); - + //Avoid blocking here(when the interrupt is disabled and do not wait tx done). + if(p_rmt_obj[channel]->wait_done) { + xSemaphoreTake(p_rmt_obj[channel]->tx_sem, portMAX_DELAY); + } rmt_set_rx_intr_en(channel, 0); rmt_set_err_intr_en(channel, 0); rmt_set_tx_intr_en(channel, 0); @@ -695,6 +703,7 @@ esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int intr p_rmt_obj[channel]->channel = channel; p_rmt_obj[channel]->tx_offset = 0; p_rmt_obj[channel]->tx_sub_len = 0; + p_rmt_obj[channel]->wait_done = false; if(p_rmt_obj[channel]->tx_sem == NULL) { p_rmt_obj[channel]->tx_sem = xSemaphoreCreateBinary(); @@ -748,9 +757,10 @@ esp_err_t rmt_write_items(rmt_channel_t channel, const rmt_item32_t* rmt_item, i } else { rmt_fill_memory(channel, rmt_item, len_rem, 0); RMTMEM.chan[channel].data32[len_rem].val = 0; - len_rem = 0; + p_rmt->tx_len_rem = 0; } rmt_tx_start(channel, true); + p_rmt->wait_done = wait_tx_done; if(wait_tx_done) { xSemaphoreTake(p_rmt->tx_sem, portMAX_DELAY); xSemaphoreGive(p_rmt->tx_sem); @@ -763,6 +773,7 @@ esp_err_t rmt_wait_tx_done(rmt_channel_t channel, TickType_t wait_time) RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); RMT_CHECK(p_rmt_obj[channel] != NULL, RMT_DRIVER_ERROR_STR, ESP_FAIL); if(xSemaphoreTake(p_rmt_obj[channel]->tx_sem, wait_time) == pdTRUE) { + p_rmt_obj[channel]->wait_done = false; xSemaphoreGive(p_rmt_obj[channel]->tx_sem); return ESP_OK; } From b5de860bcbb5665176f47cec4a0ad3df842d1495 Mon Sep 17 00:00:00 2001 From: chenjianqiang Date: Mon, 14 May 2018 19:47:16 +0800 Subject: [PATCH 084/187] revise the explain of a parameter(brk_len) in uart driver file --- components/driver/include/driver/uart.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/driver/include/driver/uart.h b/components/driver/include/driver/uart.h index f6419c0e87..08c398f61f 100644 --- a/components/driver/include/driver/uart.h +++ b/components/driver/include/driver/uart.h @@ -594,8 +594,7 @@ int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size); * @param uart_num UART_NUM_0, UART_NUM_1 or UART_NUM_2 * @param src data buffer address * @param size data length to send - * @param brk_len break signal length (unit: the time it takes to send a complete byte - including start, stop and parity bits at current_baudrate) + * @param brk_len break signal duration(unit: the time it takes to send one bit at current baudrate) * * @return * - (-1) Parameter error From da6cb6c741ba4297b3112b2d3b871e8c7f0c2e11 Mon Sep 17 00:00:00 2001 From: Hrishikesh Dhayagude Date: Wed, 25 Apr 2018 07:41:06 +0530 Subject: [PATCH 085/187] components/bt: Improve the Bluetooth debug messaging scheme As of now, when Bluetooth debugs are enabled, all the messages are mapped to BT_PRINTF which is mapped to ESP_LOGE. Hence, make monitor shows all logs in red color which might lead to missing the actual errors This patch maps the Bluetooth messages to appropriate ESP_LOG* messages and improves readability. Also, make the BT trace level be configurable in menuconfig, so that each layer of bt trace can be enabled/disabled. Finally, add debug log control for BTC, OSI, BLUFI and clear up Bluetooth debug logs. So, with this the method of enabling Bluetooth logs is as follows: 1. make menuconfig -> Component config -> Bluetooth -> Bluedroid Enable -> BT DEBUG LOG LEVEL -> set trace level for every layer of BT Signed-off-by: Hrishikesh Dhayagude --- components/bt/Kconfig | 743 +++++++++++++++++- components/bt/bluedroid/bta/dm/bta_dm_act.c | 2 +- components/bt/bluedroid/bta/dm/bta_dm_pm.c | 2 +- .../bt/bluedroid/bta/gatt/bta_gattc_act.c | 2 +- .../bt/bluedroid/bta/gatt/bta_gattc_cache.c | 5 +- .../bt/bluedroid/bta/gatt/bta_gattc_utils.c | 3 +- components/bt/bluedroid/bta/hh/bta_hh_api.c | 3 +- components/bt/bluedroid/bta/hh/bta_hh_le.c | 4 +- .../bt/bluedroid/bta/sys/bta_sys_main.c | 10 +- components/bt/bluedroid/btc/core/btc_alarm.c | 2 +- .../bt/bluedroid/btc/core/btc_ble_storage.c | 10 +- components/bt/bluedroid/btc/core/btc_config.c | 6 +- components/bt/bluedroid/btc/core/btc_dev.c | 2 +- components/bt/bluedroid/btc/core/btc_dm.c | 66 +- components/bt/bluedroid/btc/core/btc_main.c | 4 +- .../bt/bluedroid/btc/core/btc_profile_queue.c | 2 +- components/bt/bluedroid/btc/core/btc_sm.c | 10 +- .../bt/bluedroid/btc/core/btc_storage.c | 14 +- components/bt/bluedroid/btc/core/btc_task.c | 6 +- .../btc/profile/esp/ble_button/button_pro.c | 32 +- .../btc/profile/esp/blufi/blufi_prf.c | 90 +-- .../btc/profile/esp/blufi/blufi_protocol.c | 4 +- .../esp/wechat_AirSync/wx_airsync_prf.c | 8 +- .../btc/profile/std/a2dp/btc_a2dp_source.c | 6 +- .../bluedroid/btc/profile/std/a2dp/btc_av.c | 82 +- .../bluedroid/btc/profile/std/avrc/btc_avrc.c | 62 +- .../btc/profile/std/battery/battery_prf.c | 40 +- .../btc/profile/std/gap/btc_gap_ble.c | 90 +-- .../btc/profile/std/gap/btc_gap_bt.c | 10 +- .../btc/profile/std/gatt/btc_gatt_common.c | 4 +- .../btc/profile/std/gatt/btc_gatt_util.c | 8 +- .../btc/profile/std/gatt/btc_gattc.c | 24 +- .../btc/profile/std/gatt/btc_gatts.c | 50 +- .../btc/profile/std/hid_le/hid_le_prf.c | 40 +- .../bluedroid/btc/profile/std/spp/btc_spp.c | 62 +- .../common/include/common/bt_trace.h | 405 ++++++---- components/bt/bluedroid/hci/hci_hal_h4.c | 16 +- components/bt/bluedroid/hci/hci_layer.c | 28 +- .../bt/bluedroid/hci/hci_packet_parser.c | 2 +- .../bt/bluedroid/hci/packet_fragmenter.c | 10 +- components/bt/bluedroid/main/bte_main.c | 6 +- components/bt/bluedroid/osi/alarm.c | 38 +- components/bt/bluedroid/osi/allocator.c | 12 +- components/bt/bluedroid/osi/buffer.c | 4 +- components/bt/bluedroid/osi/config.c | 42 +- components/bt/bluedroid/osi/future.c | 6 +- .../bt/bluedroid/stack/btm/btm_ble_gap.c | 12 +- components/bt/bluedroid/stack/btm/btm_pm.c | 4 +- components/bt/bluedroid/stack/btm/btm_sec.c | 8 +- components/bt/bluedroid/stack/btu/btu_hcif.c | 2 +- components/bt/bluedroid/stack/btu/btu_task.c | 20 +- components/bt/bluedroid/stack/gatt/gatt_sr.c | 6 +- .../bt/bluedroid/stack/hcic/hciblecmds.c | 2 +- components/bt/bluedroid/stack/l2cap/l2c_api.c | 4 +- .../bt/bluedroid/stack/l2cap/l2c_main.c | 2 +- .../bt/bluedroid/stack/l2cap/l2cap_client.c | 36 +- .../bt/bluedroid/stack/rfcomm/port_api.c | 2 +- components/bt/bluedroid/stack/sdp/sdp_api.c | 2 +- 58 files changed, 1519 insertions(+), 658 deletions(-) diff --git a/components/bt/Kconfig b/components/bt/Kconfig index b46f872317..37d660cf98 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -169,12 +169,753 @@ config BLE_SMP_ENABLE This option can be close when the app not used the ble security connect. config BT_STACK_NO_LOG - bool "Close the bluedroid bt stack log print" + bool "Disable BT debug logs (minimize bin size)" depends on BLUEDROID_ENABLED default n help This select can save the rodata code size +menu "BT DEBUG LOG LEVEL" + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + +choice HCI_INITIAL_TRACE_LEVEL + prompt "HCI layer" + default HCI_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for HCI layer + +config HCI_TRACE_LEVEL_NONE + bool "NONE" +config HCI_TRACE_LEVEL_ERROR + bool "ERROR" +config HCI_TRACE_LEVEL_WARNING + bool "WARNING" +config HCI_TRACE_LEVEL_API + bool "API" +config HCI_TRACE_LEVEL_EVENT + bool "EVENT" +config HCI_TRACE_LEVEL_DEBUG + bool "DEBUG" +config HCI_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config HCI_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if HCI_TRACE_LEVEL_NONE + default 1 if HCI_TRACE_LEVEL_ERROR + default 2 if HCI_TRACE_LEVEL_WARNING + default 3 if HCI_TRACE_LEVEL_API + default 4 if HCI_TRACE_LEVEL_EVENT + default 5 if HCI_TRACE_LEVEL_DEBUG + default 6 if HCI_TRACE_LEVEL_VERBOSE + default 2 + +choice BTM_INITIAL_TRACE_LEVEL + prompt "BTM layer" + default BTM_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for BTM layer + +config BTM_TRACE_LEVEL_NONE + bool "NONE" +config BTM_TRACE_LEVEL_ERROR + bool "ERROR" +config BTM_TRACE_LEVEL_WARNING + bool "WARNING" +config BTM_TRACE_LEVEL_API + bool "API" +config BTM_TRACE_LEVEL_EVENT + bool "EVENT" +config BTM_TRACE_LEVEL_DEBUG + bool "DEBUG" +config BTM_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config BTM_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if BTM_TRACE_LEVEL_NONE + default 1 if BTM_TRACE_LEVEL_ERROR + default 2 if BTM_TRACE_LEVEL_WARNING + default 3 if BTM_TRACE_LEVEL_API + default 4 if BTM_TRACE_LEVEL_EVENT + default 5 if BTM_TRACE_LEVEL_DEBUG + default 6 if BTM_TRACE_LEVEL_VERBOSE + default 2 + +choice L2CAP_INITIAL_TRACE_LEVEL + prompt "L2CAP layer" + default L2CAP_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for L2CAP layer + +config L2CAP_TRACE_LEVEL_NONE + bool "NONE" +config L2CAP_TRACE_LEVEL_ERROR + bool "ERROR" +config L2CAP_TRACE_LEVEL_WARNING + bool "WARNING" +config L2CAP_TRACE_LEVEL_API + bool "API" +config L2CAP_TRACE_LEVEL_EVENT + bool "EVENT" +config L2CAP_TRACE_LEVEL_DEBUG + bool "DEBUG" +config L2CAP_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config L2CAP_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if L2CAP_TRACE_LEVEL_NONE + default 1 if L2CAP_TRACE_LEVEL_ERROR + default 2 if L2CAP_TRACE_LEVEL_WARNING + default 3 if L2CAP_TRACE_LEVEL_API + default 4 if L2CAP_TRACE_LEVEL_EVENT + default 5 if L2CAP_TRACE_LEVEL_DEBUG + default 6 if L2CAP_TRACE_LEVEL_VERBOSE + default 2 + +choice RFCOMM_INITIAL_TRACE_LEVEL + prompt "RFCOMM layer" + default RFCOMM_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for RFCOMM layer + +config RFCOMM_TRACE_LEVEL_NONE + bool "NONE" +config RFCOMM_TRACE_LEVEL_ERROR + bool "ERROR" +config RFCOMM_TRACE_LEVEL_WARNING + bool "WARNING" +config RFCOMM_TRACE_LEVEL_API + bool "API" +config RFCOMM_TRACE_LEVEL_EVENT + bool "EVENT" +config RFCOMM_TRACE_LEVEL_DEBUG + bool "DEBUG" +config RFCOMM_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config RFCOMM_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if RFCOMM_TRACE_LEVEL_NONE + default 1 if RFCOMM_TRACE_LEVEL_ERROR + default 2 if RFCOMM_TRACE_LEVEL_WARNING + default 3 if RFCOMM_TRACE_LEVEL_API + default 4 if RFCOMM_TRACE_LEVEL_EVENT + default 5 if RFCOMM_TRACE_LEVEL_DEBUG + default 6 if RFCOMM_TRACE_LEVEL_VERBOSE + default 2 + +choice SDP_INITIAL_TRACE_LEVEL + prompt "SDP layer" + default SDP_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for SDP layer + +config SDP_TRACE_LEVEL_NONE + bool "NONE" +config SDP_TRACE_LEVEL_ERROR + bool "ERROR" +config SDP_TRACE_LEVEL_WARNING + bool "WARNING" +config SDP_TRACE_LEVEL_API + bool "API" +config SDP_TRACE_LEVEL_EVENT + bool "EVENT" +config SDP_TRACE_LEVEL_DEBUG + bool "DEBUG" +config SDP_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config SDP_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if SDP_TRACE_LEVEL_NONE + default 1 if SDP_TRACE_LEVEL_ERROR + default 2 if SDP_TRACE_LEVEL_WARNING + default 3 if SDP_TRACE_LEVEL_API + default 4 if SDP_TRACE_LEVEL_EVENT + default 5 if SDP_TRACE_LEVEL_DEBUG + default 6 if SDP_TRACE_LEVEL_VERBOSE + default 2 + +choice GAP_INITIAL_TRACE_LEVEL + prompt "GAP layer" + default GAP_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for GAP layer + +config GAP_TRACE_LEVEL_NONE + bool "NONE" +config GAP_TRACE_LEVEL_ERROR + bool "ERROR" +config GAP_TRACE_LEVEL_WARNING + bool "WARNING" +config GAP_TRACE_LEVEL_API + bool "API" +config GAP_TRACE_LEVEL_EVENT + bool "EVENT" +config GAP_TRACE_LEVEL_DEBUG + bool "DEBUG" +config GAP_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config GAP_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if GAP_TRACE_LEVEL_NONE + default 1 if GAP_TRACE_LEVEL_ERROR + default 2 if GAP_TRACE_LEVEL_WARNING + default 3 if GAP_TRACE_LEVEL_API + default 4 if GAP_TRACE_LEVEL_EVENT + default 5 if GAP_TRACE_LEVEL_DEBUG + default 6 if GAP_TRACE_LEVEL_VERBOSE + default 2 + +choice BNEP_INITIAL_TRACE_LEVEL + prompt "BNEP layer" + default BNEP_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for BNEP layer + +config BNEP_TRACE_LEVEL_NONE + bool "NONE" +config BNEP_TRACE_LEVEL_ERROR + bool "ERROR" +config BNEP_TRACE_LEVEL_WARNING + bool "WARNING" +config BNEP_TRACE_LEVEL_API + bool "API" +config BNEP_TRACE_LEVEL_EVENT + bool "EVENT" +config BNEP_TRACE_LEVEL_DEBUG + bool "DEBUG" +config BNEP_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config BNEP_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if BNEP_TRACE_LEVEL_NONE + default 1 if BNEP_TRACE_LEVEL_ERROR + default 2 if BNEP_TRACE_LEVEL_WARNING + default 3 if BNEP_TRACE_LEVEL_API + default 4 if BNEP_TRACE_LEVEL_EVENT + default 5 if BNEP_TRACE_LEVEL_DEBUG + default 6 if BNEP_TRACE_LEVEL_VERBOSE + default 2 + +choice PAN_INITIAL_TRACE_LEVEL + prompt "PAN layer" + default PAN_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for PAN layer + +config PAN_TRACE_LEVEL_NONE + bool "NONE" +config PAN_TRACE_LEVEL_ERROR + bool "ERROR" +config PAN_TRACE_LEVEL_WARNING + bool "WARNING" +config PAN_TRACE_LEVEL_API + bool "API" +config PAN_TRACE_LEVEL_EVENT + bool "EVENT" +config PAN_TRACE_LEVEL_DEBUG + bool "DEBUG" +config PAN_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config PAN_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if PAN_TRACE_LEVEL_NONE + default 1 if PAN_TRACE_LEVEL_ERROR + default 2 if PAN_TRACE_LEVEL_WARNING + default 3 if PAN_TRACE_LEVEL_API + default 4 if PAN_TRACE_LEVEL_EVENT + default 5 if PAN_TRACE_LEVEL_DEBUG + default 6 if PAN_TRACE_LEVEL_VERBOSE + default 2 + +choice A2D_INITIAL_TRACE_LEVEL + prompt "A2D layer" + default A2D_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for A2D layer + +config A2D_TRACE_LEVEL_NONE + bool "NONE" +config A2D_TRACE_LEVEL_ERROR + bool "ERROR" +config A2D_TRACE_LEVEL_WARNING + bool "WARNING" +config A2D_TRACE_LEVEL_API + bool "API" +config A2D_TRACE_LEVEL_EVENT + bool "EVENT" +config A2D_TRACE_LEVEL_DEBUG + bool "DEBUG" +config A2D_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config A2D_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if A2D_TRACE_LEVEL_NONE + default 1 if A2D_TRACE_LEVEL_ERROR + default 2 if A2D_TRACE_LEVEL_WARNING + default 3 if A2D_TRACE_LEVEL_API + default 4 if A2D_TRACE_LEVEL_EVENT + default 5 if A2D_TRACE_LEVEL_DEBUG + default 6 if A2D_TRACE_LEVEL_VERBOSE + default 2 + +choice AVDT_INITIAL_TRACE_LEVEL + prompt "AVDT layer" + default AVDT_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for AVDT layer + +config AVDT_TRACE_LEVEL_NONE + bool "NONE" +config AVDT_TRACE_LEVEL_ERROR + bool "ERROR" +config AVDT_TRACE_LEVEL_WARNING + bool "WARNING" +config AVDT_TRACE_LEVEL_API + bool "API" +config AVDT_TRACE_LEVEL_EVENT + bool "EVENT" +config AVDT_TRACE_LEVEL_DEBUG + bool "DEBUG" +config AVDT_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config AVDT_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if AVDT_TRACE_LEVEL_NONE + default 1 if AVDT_TRACE_LEVEL_ERROR + default 2 if AVDT_TRACE_LEVEL_WARNING + default 3 if AVDT_TRACE_LEVEL_API + default 4 if AVDT_TRACE_LEVEL_EVENT + default 5 if AVDT_TRACE_LEVEL_DEBUG + default 6 if AVDT_TRACE_LEVEL_VERBOSE + default 2 + +choice AVCT_INITIAL_TRACE_LEVEL + prompt "AVCT layer" + default AVCT_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for AVCT layer + +config AVCT_TRACE_LEVEL_NONE + bool "NONE" +config AVCT_TRACE_LEVEL_ERROR + bool "ERROR" +config AVCT_TRACE_LEVEL_WARNING + bool "WARNING" +config AVCT_TRACE_LEVEL_API + bool "API" +config AVCT_TRACE_LEVEL_EVENT + bool "EVENT" +config AVCT_TRACE_LEVEL_DEBUG + bool "DEBUG" +config AVCT_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config AVCT_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if AVCT_TRACE_LEVEL_NONE + default 1 if AVCT_TRACE_LEVEL_ERROR + default 2 if AVCT_TRACE_LEVEL_WARNING + default 3 if AVCT_TRACE_LEVEL_API + default 4 if AVCT_TRACE_LEVEL_EVENT + default 5 if AVCT_TRACE_LEVEL_DEBUG + default 6 if AVCT_TRACE_LEVEL_VERBOSE + default 2 + +choice AVRC_INITIAL_TRACE_LEVEL + prompt "AVRC layer" + default AVRC_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for AVRC layer + +config AVRC_TRACE_LEVEL_NONE + bool "NONE" +config AVRC_TRACE_LEVEL_ERROR + bool "ERROR" +config AVRC_TRACE_LEVEL_WARNING + bool "WARNING" +config AVRC_TRACE_LEVEL_API + bool "API" +config AVRC_TRACE_LEVEL_EVENT + bool "EVENT" +config AVRC_TRACE_LEVEL_DEBUG + bool "DEBUG" +config AVRC_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config AVRC_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if AVRC_TRACE_LEVEL_NONE + default 1 if AVRC_TRACE_LEVEL_ERROR + default 2 if AVRC_TRACE_LEVEL_WARNING + default 3 if AVRC_TRACE_LEVEL_API + default 4 if AVRC_TRACE_LEVEL_EVENT + default 5 if AVRC_TRACE_LEVEL_DEBUG + default 6 if AVRC_TRACE_LEVEL_VERBOSE + default 2 + +choice MCA_INITIAL_TRACE_LEVEL + prompt "MCA layer" + default MCA_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for MCA layer + +config MCA_TRACE_LEVEL_NONE + bool "NONE" +config MCA_TRACE_LEVEL_ERROR + bool "ERROR" +config MCA_TRACE_LEVEL_WARNING + bool "WARNING" +config MCA_TRACE_LEVEL_API + bool "API" +config MCA_TRACE_LEVEL_EVENT + bool "EVENT" +config MCA_TRACE_LEVEL_DEBUG + bool "DEBUG" +config MCA_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config MCA_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if MCA_TRACE_LEVEL_NONE + default 1 if MCA_TRACE_LEVEL_ERROR + default 2 if MCA_TRACE_LEVEL_WARNING + default 3 if MCA_TRACE_LEVEL_API + default 4 if MCA_TRACE_LEVEL_EVENT + default 5 if MCA_TRACE_LEVEL_DEBUG + default 6 if MCA_TRACE_LEVEL_VERBOSE + default 2 + +choice HID_INITIAL_TRACE_LEVEL + prompt "HID layer" + default HID_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for HID layer + +config HID_TRACE_LEVEL_NONE + bool "NONE" +config HID_TRACE_LEVEL_ERROR + bool "ERROR" +config HID_TRACE_LEVEL_WARNING + bool "WARNING" +config HID_TRACE_LEVEL_API + bool "API" +config HID_TRACE_LEVEL_EVENT + bool "EVENT" +config HID_TRACE_LEVEL_DEBUG + bool "DEBUG" +config HID_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config HID_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if HID_TRACE_LEVEL_NONE + default 1 if HID_TRACE_LEVEL_ERROR + default 2 if HID_TRACE_LEVEL_WARNING + default 3 if HID_TRACE_LEVEL_API + default 4 if HID_TRACE_LEVEL_EVENT + default 5 if HID_TRACE_LEVEL_DEBUG + default 6 if HID_TRACE_LEVEL_VERBOSE + default 2 + +choice APPL_INITIAL_TRACE_LEVEL + prompt "APPL layer" + default APPL_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for APPL layer + +config APPL_TRACE_LEVEL_NONE + bool "NONE" +config APPL_TRACE_LEVEL_ERROR + bool "ERROR" +config APPL_TRACE_LEVEL_WARNING + bool "WARNING" +config APPL_TRACE_LEVEL_API + bool "API" +config APPL_TRACE_LEVEL_EVENT + bool "EVENT" +config APPL_TRACE_LEVEL_DEBUG + bool "DEBUG" +config APPL_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config APPL_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if APPL_TRACE_LEVEL_NONE + default 1 if APPL_TRACE_LEVEL_ERROR + default 2 if APPL_TRACE_LEVEL_WARNING + default 3 if APPL_TRACE_LEVEL_API + default 4 if APPL_TRACE_LEVEL_EVENT + default 5 if APPL_TRACE_LEVEL_DEBUG + default 6 if APPL_TRACE_LEVEL_VERBOSE + default 2 + +choice GATT_INITIAL_TRACE_LEVEL + prompt "GATT layer" + default GATT_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for GATT layer + +config GATT_TRACE_LEVEL_NONE + bool "NONE" +config GATT_TRACE_LEVEL_ERROR + bool "ERROR" +config GATT_TRACE_LEVEL_WARNING + bool "WARNING" +config GATT_TRACE_LEVEL_API + bool "API" +config GATT_TRACE_LEVEL_EVENT + bool "EVENT" +config GATT_TRACE_LEVEL_DEBUG + bool "DEBUG" +config GATT_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config GATT_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if GATT_TRACE_LEVEL_NONE + default 1 if GATT_TRACE_LEVEL_ERROR + default 2 if GATT_TRACE_LEVEL_WARNING + default 3 if GATT_TRACE_LEVEL_API + default 4 if GATT_TRACE_LEVEL_EVENT + default 5 if GATT_TRACE_LEVEL_DEBUG + default 6 if GATT_TRACE_LEVEL_VERBOSE + default 2 + +choice SMP_INITIAL_TRACE_LEVEL + prompt "SMP layer" + default SMP_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for SMP layer + +config SMP_TRACE_LEVEL_NONE + bool "NONE" +config SMP_TRACE_LEVEL_ERROR + bool "ERROR" +config SMP_TRACE_LEVEL_WARNING + bool "WARNING" +config SMP_TRACE_LEVEL_API + bool "API" +config SMP_TRACE_LEVEL_EVENT + bool "EVENT" +config SMP_TRACE_LEVEL_DEBUG + bool "DEBUG" +config SMP_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config SMP_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if SMP_TRACE_LEVEL_NONE + default 1 if SMP_TRACE_LEVEL_ERROR + default 2 if SMP_TRACE_LEVEL_WARNING + default 3 if SMP_TRACE_LEVEL_API + default 4 if SMP_TRACE_LEVEL_EVENT + default 5 if SMP_TRACE_LEVEL_DEBUG + default 6 if SMP_TRACE_LEVEL_VERBOSE + default 2 + +choice BTIF_INITIAL_TRACE_LEVEL + prompt "BTIF layer" + default BTIF_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for BTIF layer + +config BTIF_TRACE_LEVEL_NONE + bool "NONE" +config BTIF_TRACE_LEVEL_ERROR + bool "ERROR" +config BTIF_TRACE_LEVEL_WARNING + bool "WARNING" +config BTIF_TRACE_LEVEL_API + bool "API" +config BTIF_TRACE_LEVEL_EVENT + bool "EVENT" +config BTIF_TRACE_LEVEL_DEBUG + bool "DEBUG" +config BTIF_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config BTIF_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if BTIF_TRACE_LEVEL_NONE + default 1 if BTIF_TRACE_LEVEL_ERROR + default 2 if BTIF_TRACE_LEVEL_WARNING + default 3 if BTIF_TRACE_LEVEL_API + default 4 if BTIF_TRACE_LEVEL_EVENT + default 5 if BTIF_TRACE_LEVEL_DEBUG + default 6 if BTIF_TRACE_LEVEL_VERBOSE + default 2 + +choice BTC_INITIAL_TRACE_LEVEL + prompt "BTC layer" + default BTC_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for BTC layer + +config BTC_TRACE_LEVEL_NONE + bool "NONE" +config BTC_TRACE_LEVEL_ERROR + bool "ERROR" +config BTC_TRACE_LEVEL_WARNING + bool "WARNING" +config BTC_TRACE_LEVEL_API + bool "API" +config BTC_TRACE_LEVEL_EVENT + bool "EVENT" +config BTC_TRACE_LEVEL_DEBUG + bool "DEBUG" +config BTC_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config BTC_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if BTC_TRACE_LEVEL_NONE + default 1 if BTC_TRACE_LEVEL_ERROR + default 2 if BTC_TRACE_LEVEL_WARNING + default 3 if BTC_TRACE_LEVEL_API + default 4 if BTC_TRACE_LEVEL_EVENT + default 5 if BTC_TRACE_LEVEL_DEBUG + default 6 if BTC_TRACE_LEVEL_VERBOSE + default 2 + +choice OSI_INITIAL_TRACE_LEVEL + prompt "OSI layer" + default OSI_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for OSI layer + +config OSI_TRACE_LEVEL_NONE + bool "NONE" +config OSI_TRACE_LEVEL_ERROR + bool "ERROR" +config OSI_TRACE_LEVEL_WARNING + bool "WARNING" +config OSI_TRACE_LEVEL_API + bool "API" +config OSI_TRACE_LEVEL_EVENT + bool "EVENT" +config OSI_TRACE_LEVEL_DEBUG + bool "DEBUG" +config OSI_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config OSI_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if OSI_TRACE_LEVEL_NONE + default 1 if OSI_TRACE_LEVEL_ERROR + default 2 if OSI_TRACE_LEVEL_WARNING + default 3 if OSI_TRACE_LEVEL_API + default 4 if OSI_TRACE_LEVEL_EVENT + default 5 if OSI_TRACE_LEVEL_DEBUG + default 6 if OSI_TRACE_LEVEL_VERBOSE + default 2 + +choice BLUFI_INITIAL_TRACE_LEVEL + prompt "BLUFI layer" + default BLUFI_TRACE_LEVEL_WARNING + depends on BLUEDROID_ENABLED && !BT_STACK_NO_LOG + help + Define BT trace level for BLUFI layer + +config BLUFI_TRACE_LEVEL_NONE + bool "NONE" +config BLUFI_TRACE_LEVEL_ERROR + bool "ERROR" +config BLUFI_TRACE_LEVEL_WARNING + bool "WARNING" +config BLUFI_TRACE_LEVEL_API + bool "API" +config BLUFI_TRACE_LEVEL_EVENT + bool "EVENT" +config BLUFI_TRACE_LEVEL_DEBUG + bool "DEBUG" +config BLUFI_TRACE_LEVEL_VERBOSE + bool "VERBOSE" +endchoice + +config BLUFI_INITIAL_TRACE_LEVEL + int + depends on BLUEDROID_ENABLED + default 0 if BLUFI_TRACE_LEVEL_NONE + default 1 if BLUFI_TRACE_LEVEL_ERROR + default 2 if BLUFI_TRACE_LEVEL_WARNING + default 3 if BLUFI_TRACE_LEVEL_API + default 4 if BLUFI_TRACE_LEVEL_EVENT + default 5 if BLUFI_TRACE_LEVEL_DEBUG + default 6 if BLUFI_TRACE_LEVEL_VERBOSE + default 2 + +endmenu #BT DEBUG LOG LEVEL + + config BT_ACL_CONNECTIONS int "BT/BLE MAX ACL CONNECTIONS(1~7)" depends on BLUEDROID_ENABLED diff --git a/components/bt/bluedroid/bta/dm/bta_dm_act.c b/components/bt/bluedroid/bta/dm/bta_dm_act.c index 3bf5487731..3985dc839d 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_act.c @@ -5529,7 +5529,7 @@ static void bta_dm_gatt_disc_result(tBTA_GATT_ID service_id) APPL_TRACE_ERROR("%s out of room to accomodate more service ids ble_raw_size = %d ble_raw_used = %d", __FUNCTION__, bta_dm_search_cb.ble_raw_size, bta_dm_search_cb.ble_raw_used ); } - LOG_INFO("%s service_id_uuid_len=%d ", __func__, service_id.uuid.len); + APPL_TRACE_API("%s service_id_uuid_len=%d ", __func__, service_id.uuid.len); if ( bta_dm_search_cb.state != BTA_DM_SEARCH_IDLE) { /* send result back to app now, one by one */ diff --git a/components/bt/bluedroid/bta/dm/bta_dm_pm.c b/components/bt/bluedroid/bta/dm/bta_dm_pm.c index 3354a33b2a..a876ec36a9 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_pm.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_pm.c @@ -595,7 +595,7 @@ static void bta_dm_pm_set_mode(BD_ADDR peer_addr, tBTA_DM_PM_ACTION pm_request, if ((timer_idx = bta_pm_action_to_timer_idx(pm_action)) != BTA_DM_PM_MODE_TIMER_MAX) { remaining_ticks = bta_dm_pm_get_remaining_ticks(&bta_dm_cb.pm_timer[i].timer[timer_idx]); if (remaining_ticks < timeout) { - LOG_DEBUG("%s remain 0\n", __func__); + APPL_TRACE_DEBUG("%s remain 0\n", __func__); /* Cancel and restart the timer */ /* * TODO: The value of pm_action[timer_idx] is diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c index 8eace1a0a1..e836003dd4 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_act.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_act.c @@ -2198,7 +2198,7 @@ void bta_gattc_listen(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg) } /* if listen to all */ else { - LOG_DEBUG("Listen For All now"); + APPL_TRACE_DEBUG("Listen For All now"); /* go through all connected device and send callback for all connected slave connection */ bta_gattc_process_listen_all(p_msg->api_listen.client_if); diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c b/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c index b17dc9ec0e..8a5625356c 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_cache.c @@ -40,7 +40,6 @@ #include "btm_int.h" #include "errno.h" -#define LOG_TAG "bt_bta_gattc" // #include "osi/include/log.h" static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb); @@ -106,7 +105,7 @@ bool display_cache_attribute(void *data, void *context) bool display_cache_service(void *data, void *context) { tBTA_GATTC_SERVICE *p_cur_srvc = data; - LOG_INFO("Service: handle[%d ~ %d] %s[0x%04x] inst[%d]", + APPL_TRACE_API("Service: handle[%d ~ %d] %s[0x%04x] inst[%d]", p_cur_srvc->s_handle, p_cur_srvc->e_handle, ((p_cur_srvc->uuid.len == 2) ? "uuid16" : "uuid128"), p_cur_srvc->uuid.uu.uuid16, @@ -611,7 +610,7 @@ static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) p_srvc_cb->update_sec_sev = false; } /* no service found at all, the end of server discovery*/ - LOG_DEBUG("%s no more services found", __func__); + APPL_TRACE_DEBUG("%s no more services found", __func__); #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache); diff --git a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c index 9b3e5c0308..774134478b 100644 --- a/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c +++ b/components/bt/bluedroid/bta/gatt/bta_gattc_utils.c @@ -36,7 +36,6 @@ #include "stack/l2c_api.h" #include "osi/allocator.h" -#define LOG_TAG "bt_bta_gattc" /***************************************************************************** ** Constants *****************************************************************************/ @@ -963,7 +962,7 @@ void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src) break; default: - LOG_ERROR("%s: Unknown UUID length %d!", __FUNCTION__, p_src->len); + APPL_TRACE_ERROR("%s: Unknown UUID length %d!", __FUNCTION__, p_src->len); break; } } diff --git a/components/bt/bluedroid/bta/hh/bta_hh_api.c b/components/bt/bluedroid/bta/hh/bta_hh_api.c index ed96d8ee72..43f7542872 100644 --- a/components/bt/bluedroid/bta/hh/bta_hh_api.c +++ b/components/bt/bluedroid/bta/hh/bta_hh_api.c @@ -35,7 +35,6 @@ #include "stack/l2c_api.h" #include "bta/utl.h" -#define LOG_TAG "bt_bta_hh" #include "osi/include/log.h" /***************************************************************************** @@ -67,7 +66,7 @@ void BTA_HhEnable(tBTA_SEC sec_mask, tBTA_HH_CBACK *p_cback) /* register with BTA system manager */ bta_sys_register(BTA_ID_HH, &bta_hh_reg); - LOG_INFO("%s sec_mask:0x%x p_cback:%p", __func__, sec_mask, p_cback); + APPL_TRACE_API("%s sec_mask:0x%x p_cback:%p", __func__, sec_mask, p_cback); p_buf = (tBTA_HH_API_ENABLE *)osi_malloc((UINT16)sizeof(tBTA_HH_API_ENABLE)); if (p_buf != NULL) { diff --git a/components/bt/bluedroid/bta/hh/bta_hh_le.c b/components/bt/bluedroid/bta/hh/bta_hh_le.c index 78eca9c2b8..9f61be4158 100644 --- a/components/bt/bluedroid/bta/hh/bta_hh_le.c +++ b/components/bt/bluedroid/bta/hh/bta_hh_le.c @@ -613,7 +613,7 @@ tBTA_HH_STATUS bta_hh_le_read_char_dscrpt(tBTA_HH_DEV_CB *p_cb, UINT16 srvc_uuid status = BTA_HH_OK; } else { #if BTA_HH_DEBUG == TRUE - LOG_WARN("%s No descriptor exists: %s(0x%04x)", __func__, + APPL_TRACE_WARNING("%s No descriptor exists: %s(0x%04x)", __func__, bta_hh_uuid_to_str(char_descp_uuid), char_descp_uuid); #endif } @@ -1092,7 +1092,7 @@ void bta_hh_le_expl_rpt(tBTA_HH_DEV_CB *p_dev_cb, p_char_id = &char_result; } while (1); - LOG_INFO("%s all BLE reports searched", __func__); + APPL_TRACE_API("%s all BLE reports searched", __func__); bta_hh_le_read_rpt_ref_descr(p_dev_cb, &p_dev_cb->hid_srvc[p_dev_cb->cur_srvc_index].report[0]); diff --git a/components/bt/bluedroid/bta/sys/bta_sys_main.c b/components/bt/bluedroid/bta/sys/bta_sys_main.c index 3efd2a39d8..e3b8c77fa9 100644 --- a/components/bt/bluedroid/bta/sys/bta_sys_main.c +++ b/components/bt/bluedroid/bta/sys/bta_sys_main.c @@ -59,8 +59,8 @@ static osi_mutex_t bta_alarm_lock; /* trace level */ /* TODO Bluedroid - Hard-coded trace levels - Needs to be configurable */ -UINT8 appl_trace_level = BT_TRACE_LEVEL_WARNING; //APPL_INITIAL_TRACE_LEVEL; -UINT8 btif_trace_level = BT_TRACE_LEVEL_WARNING; +UINT8 appl_trace_level = APPL_INITIAL_TRACE_LEVEL; +UINT8 btif_trace_level = BTIF_INITIAL_TRACE_LEVEL; void btu_bta_alarm_ready(fixed_queue_t *queue); @@ -607,7 +607,7 @@ void bta_sys_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout_ms) osi_alarm_t *alarm = hash_map_get(bta_alarm_hash_map, p_tle); if (alarm == NULL) { - LOG_ERROR("%s unable to create alarm.", __func__); + APPL_TRACE_ERROR("%s unable to create alarm.", __func__); return; } @@ -651,7 +651,7 @@ void bta_sys_stop_timer(TIMER_LIST_ENT *p_tle) osi_alarm_t *alarm = hash_map_get(bta_alarm_hash_map, p_tle); if (alarm == NULL) { - LOG_DEBUG("%s expected alarm was not in bta alarm hash map.", __func__); + APPL_TRACE_DEBUG("%s expected alarm was not in bta alarm hash map.", __func__); return; } osi_alarm_cancel(alarm); @@ -672,7 +672,7 @@ void bta_sys_free_timer(TIMER_LIST_ENT *p_tle) osi_alarm_t *alarm = hash_map_get(bta_alarm_hash_map, p_tle); if (alarm == NULL) { - LOG_DEBUG("%s expected alarm was not in bta alarm hash map.", __func__); + APPL_TRACE_DEBUG("%s expected alarm was not in bta alarm hash map.", __func__); return; } osi_alarm_cancel(alarm); diff --git a/components/bt/bluedroid/btc/core/btc_alarm.c b/components/bt/bluedroid/btc/core/btc_alarm.c index 9d8d52bcac..ade9f093ac 100644 --- a/components/bt/bluedroid/btc/core/btc_alarm.c +++ b/components/bt/bluedroid/btc/core/btc_alarm.c @@ -19,7 +19,7 @@ void btc_alarm_handler(btc_msg_t *msg) { btc_alarm_args_t *arg = (btc_alarm_args_t *)msg->arg; - LOG_DEBUG("%s act %d\n", __FUNCTION__, msg->act); + BTC_TRACE_DEBUG("%s act %d\n", __FUNCTION__, msg->act); if (arg->cb) { arg->cb(arg->cb_data); diff --git a/components/bt/bluedroid/btc/core/btc_ble_storage.c b/components/bt/bluedroid/btc/core/btc_ble_storage.c index b0dbf2f9e5..bb42810fc4 100644 --- a/components/bt/bluedroid/btc/core/btc_ble_storage.c +++ b/components/bt/bluedroid/btc/core/btc_ble_storage.c @@ -645,7 +645,7 @@ static void _btc_read_le_key(const uint8_t key_type, const size_t key_len, bt_bd } char bd_str[20] = {0}; - LOG_DEBUG("%s() Adding key type %d for %s", __func__, + BTC_TRACE_DEBUG("%s() Adding key type %d for %s", __func__, key_type, bdaddr_to_string(&bd_addr, bd_str, sizeof(bd_str))); BTA_DmAddBleKey(bta_bd_addr, (tBTA_LE_KEY_VALUE *)buffer, key_type); } @@ -663,7 +663,7 @@ static bt_status_t _btc_storage_in_fetch_bonded_ble_device(const char *remote_bd bool key_found = false; if (!btc_config_get_int(remote_bd_addr, BTC_BLE_STORAGE_DEV_TYPE_STR, (int *)&device_type)) { - LOG_ERROR("%s, device_type = %x", __func__, device_type); + BTC_TRACE_ERROR("%s, device_type = %x", __func__, device_type); return BT_STATUS_FAIL; } @@ -715,9 +715,9 @@ static bt_status_t btc_storage_in_fetch_bonded_ble_devices(int add) ((device_type & BT_DEVICE_TYPE_BLE) != BT_DEVICE_TYPE_BLE)) { continue; } - LOG_DEBUG("%s, name = %s", __func__, name); + BTC_TRACE_DEBUG("%s, name = %s", __func__, name); if (_btc_storage_in_fetch_bonded_ble_device(name, add) != BT_STATUS_SUCCESS) { - LOG_DEBUG("Remote device:%s, no link key or ble key found", name); + BTC_TRACE_DEBUG("Remote device:%s, no link key or ble key found", name); } else { status = BT_STATUS_SUCCESS; } @@ -743,7 +743,7 @@ bt_status_t btc_storage_load_bonded_ble_devices(void) { bt_status_t status; status = btc_storage_in_fetch_bonded_ble_devices(1); - LOG_DEBUG("Storage load rslt %d\n", status); + BTC_TRACE_DEBUG("Storage load rslt %d\n", status); return status; } diff --git a/components/bt/bluedroid/btc/core/btc_config.c b/components/bt/bluedroid/btc/core/btc_config.c index 4a859340b2..b987a32e0c 100644 --- a/components/bt/bluedroid/btc/core/btc_config.c +++ b/components/bt/bluedroid/btc/core/btc_config.c @@ -73,10 +73,10 @@ bool btc_config_init(void) osi_mutex_new(&lock); config = config_new(CONFIG_FILE_PATH); if (!config) { - LOG_WARN("%s unable to load config file; starting unconfigured.\n", __func__); + BTC_TRACE_WARNING("%s unable to load config file; starting unconfigured.\n", __func__); config = config_new_empty(); if (!config) { - LOG_ERROR("%s unable to allocate a config object.\n", __func__); + BTC_TRACE_ERROR("%s unable to allocate a config object.\n", __func__); goto error; } } @@ -90,7 +90,7 @@ error:; config_free(config); osi_mutex_free(&lock); config = NULL; - LOG_ERROR("%s failed\n", __func__); + BTC_TRACE_ERROR("%s failed\n", __func__); return false; } diff --git a/components/bt/bluedroid/btc/core/btc_dev.c b/components/bt/bluedroid/btc/core/btc_dev.c index 976e5a16c6..b5c85b9651 100644 --- a/components/bt/bluedroid/btc/core/btc_dev.c +++ b/components/bt/bluedroid/btc/core/btc_dev.c @@ -22,7 +22,7 @@ void btc_dev_call_handler(btc_msg_t *msg) { btc_dev_args_t *arg = (btc_dev_args_t *)msg->arg; - LOG_DEBUG("%s act %d\n", __FUNCTION__, msg->act); + BTC_TRACE_DEBUG("%s act %d\n", __FUNCTION__, msg->act); switch (msg->act) { case BTC_DEV_ACT_SET_DEVICE_NAME: diff --git a/components/bt/bluedroid/btc/core/btc_dm.c b/components/bt/bluedroid/btc/core/btc_dm.c index 8bc2370ad4..89ca9e0be0 100644 --- a/components/bt/bluedroid/btc/core/btc_dm.c +++ b/components/bt/bluedroid/btc/core/btc_dm.c @@ -128,7 +128,7 @@ static void btc_enable_bluetooth_evt(tBTA_STATUS status) static void btc_disable_bluetooth_evt(void) { - LOG_DEBUG("%s", __FUNCTION__); + BTC_TRACE_DEBUG("%s", __FUNCTION__); future_ready(*btc_main_get_future_p(BTC_MAIN_DISABLE_FUTURE), FUTURE_SUCCESS); } @@ -141,7 +141,7 @@ void btc_dm_load_ble_local_keys(void) if (btc_storage_get_ble_local_key(BTC_LE_LOCAL_KEY_ER,(char*)&ble_local_key_cb.er[0], BT_OCTET16_LEN)== BT_STATUS_SUCCESS) { ble_local_key_cb.is_er_rcvd = TRUE; - LOG_DEBUG("%s BLE ER key loaded",__func__ ); + BTC_TRACE_DEBUG("%s BLE ER key loaded",__func__ ); } if ((btc_storage_get_ble_local_key(BTC_LE_LOCAL_KEY_IR,(char*)&ble_local_key_cb.id_keys.ir[0], @@ -151,7 +151,7 @@ void btc_dm_load_ble_local_keys(void) (btc_storage_get_ble_local_key(BTC_LE_LOCAL_KEY_DHK,(char*)&ble_local_key_cb.id_keys.dhk[0], BT_OCTET16_LEN)== BT_STATUS_SUCCESS)) { ble_local_key_cb.is_id_keys_rcvd = TRUE; - LOG_DEBUG("%s BLE ID keys loaded", __func__); + BTC_TRACE_DEBUG("%s BLE ID keys loaded", __func__); } } @@ -169,14 +169,14 @@ void btc_dm_get_ble_local_keys(tBTA_DM_BLE_LOCAL_KEY_MASK *p_key_mask, BT_OCTET1 memcpy(&p_id_keys->dhk[0], &ble_local_key_cb.id_keys.dhk[0], sizeof(BT_OCTET16)); *p_key_mask |= BTA_BLE_LOCAL_KEY_TYPE_ID; } - LOG_DEBUG("%s *p_key_mask=0x%02x",__func__, *p_key_mask); + BTC_TRACE_DEBUG("%s *p_key_mask=0x%02x",__func__, *p_key_mask); } static void btc_dm_remove_ble_bonding_keys(void) { bt_bdaddr_t bd_addr; - LOG_DEBUG("%s\n",__func__); + BTC_TRACE_DEBUG("%s\n",__func__); bdcpy(bd_addr.address, pairing_cb.bd_addr); @@ -192,7 +192,7 @@ static void btc_dm_save_ble_bonding_keys(void) bdcpy(bd_addr.address, pairing_cb.bd_addr); btc_storage_set_ble_dev_type(&bd_addr, false); - LOG_DEBUG("%s, penc = %d, pid = %d", __func__, pairing_cb.ble.is_penc_key_rcvd, pairing_cb.ble.is_pid_key_rcvd); + BTC_TRACE_DEBUG("%s, penc = %d, pid = %d", __func__, pairing_cb.ble.is_penc_key_rcvd, pairing_cb.ble.is_pid_key_rcvd); if (pairing_cb.ble.is_penc_key_rcvd) { btc_storage_add_ble_bonding_key(&bd_addr, (char *) &pairing_cb.ble.penc_key, @@ -241,7 +241,7 @@ static void btc_dm_save_ble_bonding_keys(void) static void btc_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) { /* Save link key, if not temporary */ - LOG_DEBUG("%s, status = %d", __func__, p_auth_cmpl->success); + BTC_TRACE_DEBUG("%s, status = %d", __func__, p_auth_cmpl->success); bt_status_t status = BT_STATUS_FAIL; int addr_type; bt_bdaddr_t bdaddr; @@ -250,10 +250,10 @@ static void btc_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) if (p_auth_cmpl->success) { status = BT_STATUS_SUCCESS; - LOG_DEBUG ("%s, - p_auth_cmpl->bd_addr: %08x%04x", __func__, + BTC_TRACE_DEBUG ("%s, - p_auth_cmpl->bd_addr: %08x%04x", __func__, (p_auth_cmpl->bd_addr[0] << 24) + (p_auth_cmpl->bd_addr[1] << 16) + (p_auth_cmpl->bd_addr[2] << 8) + p_auth_cmpl->bd_addr[3], (p_auth_cmpl->bd_addr[4] << 8) + p_auth_cmpl->bd_addr[5]); - LOG_DEBUG ("%s, - pairing_cb.bd_addr: %08x%04x", __func__, + BTC_TRACE_DEBUG ("%s, - pairing_cb.bd_addr: %08x%04x", __func__, (pairing_cb.bd_addr[0] << 24) + (pairing_cb.bd_addr[1] << 16) + (pairing_cb.bd_addr[2] << 8) + pairing_cb.bd_addr[3], (pairing_cb.bd_addr[4] << 8) + pairing_cb.bd_addr[5]); if (btc_storage_get_remote_addr_type(&bdaddr, &addr_type) != BT_STATUS_SUCCESS) { @@ -279,7 +279,7 @@ static void btc_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) } - LOG_DEBUG("%s, authentication status = %x", __func__, status); + BTC_TRACE_DEBUG("%s, authentication status = %x", __func__, status); return; } @@ -290,7 +290,7 @@ static void btc_dm_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) /* Save link key, if not temporary */ bt_bdaddr_t bd_addr; bt_status_t status; - LOG_DEBUG("%s: bond state success %d, present %d, type%d\n", __func__, p_auth_cmpl->success, + BTC_TRACE_DEBUG("%s: bond state success %d, present %d, type%d\n", __func__, p_auth_cmpl->success, p_auth_cmpl->key_present, p_auth_cmpl->key_type); bdcpy(bd_addr.address, p_auth_cmpl->bd_addr); @@ -304,14 +304,14 @@ static void btc_dm_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) #endif if (1) { bt_status_t ret; - LOG_DEBUG("%s: Storing link key. key_type=0x%x", + BTC_TRACE_DEBUG("%s: Storing link key. key_type=0x%x", __FUNCTION__, p_auth_cmpl->key_type); ret = btc_storage_add_bonded_device(&bd_addr, p_auth_cmpl->key, p_auth_cmpl->key_type, 16); BTC_ASSERTC(ret == BT_STATUS_SUCCESS, "storing link key failed", ret); } else { - LOG_DEBUG("%s: Temporary key. Not storing. key_type=0x%x", + BTC_TRACE_DEBUG("%s: Temporary key. Not storing. key_type=0x%x", __FUNCTION__, p_auth_cmpl->key_type); } } @@ -323,7 +323,7 @@ static void btc_dm_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) // Map the HCI fail reason to bt status switch (p_auth_cmpl->fail_reason) { case HCI_ERR_PAGE_TIMEOUT: - LOG_WARN("%s() - Pairing timeout; retrying () ...", __FUNCTION__); + BTC_TRACE_WARNING("%s() - Pairing timeout; retrying () ...", __FUNCTION__); return; /* Fall-through */ case HCI_ERR_CONNECTION_TOUT: @@ -349,7 +349,7 @@ static void btc_dm_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) case HCI_ERR_INSUFFCIENT_SECURITY: case HCI_ERR_PEER_USER: case HCI_ERR_UNSPECIFIED: - LOG_DEBUG(" %s() Authentication fail reason %d", + BTC_TRACE_DEBUG(" %s() Authentication fail reason %d", __FUNCTION__, p_auth_cmpl->fail_reason); /* if autopair attempts are more than 1, or not attempted */ status = BT_STATUS_AUTH_FAILURE; @@ -381,7 +381,7 @@ void btc_clear_services_mask(void) static bt_status_t btc_in_execute_service_request(tBTA_SERVICE_ID service_id, BOOLEAN b_enable) { - LOG_DEBUG("%s service_id: %d\n", __FUNCTION__, service_id); + BTC_TRACE_DEBUG("%s service_id: %d\n", __FUNCTION__, service_id); /* Check the service_ID and invoke the profile's BT state changed API */ switch (service_id) { #if BTC_AV_INCLUDED @@ -393,7 +393,7 @@ static bt_status_t btc_in_execute_service_request(tBTA_SERVICE_ID service_id, break; #endif default: - LOG_ERROR("%s: Unknown service being enabled\n", __FUNCTION__); + BTC_TRACE_ERROR("%s: Unknown service being enabled\n", __FUNCTION__); return BT_STATUS_FAIL; } return BT_STATUS_SUCCESS; @@ -410,7 +410,7 @@ bt_status_t btc_dm_enable_service(tBTA_SERVICE_ID service_id) btc_enabled_services |= (1 << service_id); - LOG_DEBUG("%s: current services:0x%x", __FUNCTION__, btc_enabled_services); + BTC_TRACE_DEBUG("%s: current services:0x%x", __FUNCTION__, btc_enabled_services); btc_dm_execute_service_request(TRUE, (char *)p_id); @@ -423,7 +423,7 @@ bt_status_t btc_dm_disable_service(tBTA_SERVICE_ID service_id) btc_enabled_services &= (tBTA_SERVICE_MASK)(~(1 << service_id)); - LOG_DEBUG("%s: Current Services:0x%x", __FUNCTION__, btc_enabled_services); + BTC_TRACE_DEBUG("%s: Current Services:0x%x", __FUNCTION__, btc_enabled_services); btc_dm_execute_service_request(FALSE, (char *)p_id); @@ -441,7 +441,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) ble_msg.sig = BTC_SIG_API_CB; ble_msg.pid = BTC_PID_GAP_BLE; // tBTA_SERVICE_MASK service_mask; - LOG_DEBUG("btc_dm_upstreams_cback ev: %d\n", msg->act); + BTC_TRACE_DEBUG("btc_dm_upstreams_cback ev: %d\n", msg->act); switch (msg->act) { case BTA_DM_ENABLE_EVT: { @@ -484,7 +484,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) #if (SMP_INCLUDED == TRUE) bt_bdaddr_t bd_addr; rsp_app = true; - LOG_DEBUG("BTA_DM_DEV_UNPAIRED_EVT"); + BTC_TRACE_DEBUG("BTA_DM_DEV_UNPAIRED_EVT"); memcpy(bd_addr.address, p_data->link_down.bd_addr, sizeof(BD_ADDR)); btm_set_bond_type_dev(p_data->link_down.bd_addr, BOND_TYPE_UNKNOWN); param.remove_bond_dev_cmpl.status = ESP_BT_STATUS_FAIL; @@ -512,7 +512,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) case BTA_DM_LINK_UP_EVT: case BTA_DM_LINK_DOWN_EVT: case BTA_DM_HW_ERROR_EVT: - LOG_DEBUG( "btc_dm_sec_cback : unhandled event (%d)\n", msg->act ); + BTC_TRACE_DEBUG( "btc_dm_sec_cback : unhandled event (%d)\n", msg->act ); break; #if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE) && (SMP_INCLUDED == TRUE)) case BTA_DM_BLE_AUTH_CMPL_EVT: { @@ -536,7 +536,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) memcpy(param.ble_security.ble_key.bd_addr, p_data->ble_key.bd_addr, BD_ADDR_LEN); switch (p_data->ble_key.key_type) { case BTM_LE_KEY_PENC: { - LOG_DEBUG("Rcv BTA_LE_KEY_PENC"); + BTC_TRACE_DEBUG("Rcv BTA_LE_KEY_PENC"); pairing_cb.ble.is_penc_key_rcvd = TRUE; pairing_cb.ble.penc_key = p_data->ble_key.p_key_value->penc_key; memcpy(&pairing_cb.ble.penc_key, &p_data->ble_key.p_key_value->penc_key, @@ -546,7 +546,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) break; } case BTM_LE_KEY_PID: { - LOG_DEBUG("Rcv BTA_LE_KEY_PID"); + BTC_TRACE_DEBUG("Rcv BTA_LE_KEY_PID"); pairing_cb.ble.is_pid_key_rcvd = TRUE; memcpy(&pairing_cb.ble.pid_key, &p_data->ble_key.p_key_value->pid_key, sizeof(tBTM_LE_PID_KEYS)); @@ -555,7 +555,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) break; } case BTM_LE_KEY_PCSRK: { - LOG_DEBUG("Rcv BTA_LE_KEY_PCSRK"); + BTC_TRACE_DEBUG("Rcv BTA_LE_KEY_PCSRK"); pairing_cb.ble.is_pcsrk_key_rcvd = TRUE; memcpy(&pairing_cb.ble.pcsrk_key, &p_data->ble_key.p_key_value->pcsrk_key, sizeof(tBTM_LE_PCSRK_KEYS)); @@ -564,7 +564,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) break; } case BTM_LE_KEY_LENC: { - LOG_DEBUG("Rcv BTA_LE_KEY_LENC"); + BTC_TRACE_DEBUG("Rcv BTA_LE_KEY_LENC"); pairing_cb.ble.is_lenc_key_rcvd = TRUE; memcpy(&pairing_cb.ble.lenc_key, &p_data->ble_key.p_key_value->lenc_key, sizeof(tBTM_LE_LENC_KEYS)); @@ -573,7 +573,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) break; } case BTM_LE_KEY_LCSRK: { - LOG_DEBUG("Rcv BTA_LE_KEY_LCSRK"); + BTC_TRACE_DEBUG("Rcv BTA_LE_KEY_LCSRK"); pairing_cb.ble.is_lcsrk_key_rcvd = TRUE; memcpy(&pairing_cb.ble.lcsrk_key, &p_data->ble_key.p_key_value->lcsrk_key, sizeof(tBTM_LE_LCSRK_KEYS)); @@ -582,7 +582,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) break; } case BTM_LE_KEY_LID: { - LOG_DEBUG("Rcv BTA_LE_KEY_LID"); + BTC_TRACE_DEBUG("Rcv BTA_LE_KEY_LID"); pairing_cb.ble.is_lidk_key_rcvd = TRUE; break; } @@ -621,7 +621,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) rsp_app = true; ble_msg.act = ESP_GAP_BLE_LOCAL_IR_EVT; memcpy(¶m.ble_security.ble_id_keys, &p_data->ble_id_keys, sizeof(tBTA_BLE_LOCAL_ID_KEYS)); - LOG_DEBUG("BTA_DM_BLE_LOCAL_IR_EVT. "); + BTC_TRACE_DEBUG("BTA_DM_BLE_LOCAL_IR_EVT. "); ble_local_key_cb.is_id_keys_rcvd = TRUE; memcpy(&ble_local_key_cb.id_keys.irk[0], &p_data->ble_id_keys.irk[0], sizeof(BT_OCTET16)); @@ -644,7 +644,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) rsp_app = true; ble_msg.act = ESP_GAP_BLE_LOCAL_ER_EVT; memcpy(¶m.ble_security.ble_id_keys, &p_data->ble_id_keys, sizeof(tBTA_BLE_LOCAL_ID_KEYS)); - LOG_DEBUG("BTA_DM_BLE_LOCAL_ER_EVT. "); + BTC_TRACE_DEBUG("BTA_DM_BLE_LOCAL_ER_EVT. "); ble_local_key_cb.is_er_rcvd = TRUE; memcpy(&ble_local_key_cb.er[0], &p_data->ble_er[0], sizeof(BT_OCTET16)); btc_storage_add_ble_local_key( (char *)&ble_local_key_cb.er[0], @@ -666,10 +666,10 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) case BTA_DM_SP_RMT_OOB_EVT: case BTA_DM_SP_KEYPRESS_EVT: case BTA_DM_ROLE_CHG_EVT: - LOG_DEBUG( "btc_dm_sec_cback : unhandled event (%d)\n", msg->act ); + BTC_TRACE_DEBUG( "btc_dm_sec_cback : unhandled event (%d)\n", msg->act ); break; default: - LOG_DEBUG( "btc_dm_sec_cback : unhandled event (%d)\n", msg->act ); + BTC_TRACE_DEBUG( "btc_dm_sec_cback : unhandled event (%d)\n", msg->act ); break; } @@ -678,7 +678,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) sizeof(esp_ble_gap_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } btc_dm_sec_arg_deep_free(msg); diff --git a/components/bt/bluedroid/btc/core/btc_main.c b/components/bt/bluedroid/btc/core/btc_main.c index b6c9606be6..fb90abb997 100644 --- a/components/bt/bluedroid/btc/core/btc_main.c +++ b/components/bt/bluedroid/btc/core/btc_main.c @@ -89,7 +89,7 @@ static void btc_deinit_bluetooth(void) void btc_main_call_handler(btc_msg_t *msg) { - LOG_DEBUG("%s act %d\n", __func__, msg->act); + BTC_TRACE_DEBUG("%s act %d\n", __func__, msg->act); switch (msg->act) { case BTC_MAIN_ACT_INIT: @@ -105,7 +105,7 @@ void btc_main_call_handler(btc_msg_t *msg) btc_disable_bluetooth(); break; default: - LOG_ERROR("%s UNKNOWN ACT %d\n", __func__, msg->act); + BTC_TRACE_ERROR("%s UNKNOWN ACT %d\n", __func__, msg->act); break; } } diff --git a/components/bt/bluedroid/btc/core/btc_profile_queue.c b/components/bt/bluedroid/btc/core/btc_profile_queue.c index cd495f0e5f..6d01b0d19f 100644 --- a/components/bt/bluedroid/btc/core/btc_profile_queue.c +++ b/components/bt/bluedroid/btc/core/btc_profile_queue.c @@ -49,7 +49,7 @@ static void queue_int_add(connect_node_t *p_param) for (const list_node_t *node = list_begin(connect_queue); node != list_end(connect_queue); node = list_next(node)) { if (((connect_node_t *)list_node(node))->uuid == p_param->uuid) { - LOG_DEBUG("%s dropping duplicate connect request for uuid: %04x", __func__, p_param->uuid); + BTC_TRACE_DEBUG("%s dropping duplicate connect request for uuid: %04x", __func__, p_param->uuid); return; } } diff --git a/components/bt/bluedroid/btc/core/btc_sm.c b/components/bt/bluedroid/btc/core/btc_sm.c index cdf75548f7..6e96ae5940 100644 --- a/components/bt/bluedroid/btc/core/btc_sm.c +++ b/components/bt/bluedroid/btc/core/btc_sm.c @@ -72,7 +72,7 @@ btc_sm_handle_t btc_sm_init(const btc_sm_handler_t *p_handlers, btc_sm_state_t i btc_sm_cb_t *p_cb; if (p_handlers == NULL) { - LOG_ERROR("%s : p_handlers is NULL", __FUNCTION__); + BTC_TRACE_ERROR("%s : p_handlers is NULL", __FUNCTION__); return NULL; } @@ -100,7 +100,7 @@ void btc_sm_shutdown(btc_sm_handle_t handle) btc_sm_cb_t *p_cb = (btc_sm_cb_t *)handle; if (p_cb == NULL) { - LOG_ERROR("%s : Invalid handle", __FUNCTION__); + BTC_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); return; } osi_free(p_cb); @@ -120,7 +120,7 @@ btc_sm_state_t btc_sm_get_state(btc_sm_handle_t handle) btc_sm_cb_t *p_cb = (btc_sm_cb_t *)handle; if (p_cb == NULL) { - LOG_ERROR("%s : Invalid handle", __FUNCTION__); + BTC_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); return 0; } @@ -146,7 +146,7 @@ bt_status_t btc_sm_dispatch(btc_sm_handle_t handle, btc_sm_event_t event, btc_sm_cb_t *p_cb = (btc_sm_cb_t *)handle; if (p_cb == NULL) { - LOG_ERROR("%s : Invalid handle", __FUNCTION__); + BTC_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); return BT_STATUS_FAIL; } @@ -176,7 +176,7 @@ bt_status_t btc_sm_change_state(btc_sm_handle_t handle, btc_sm_state_t state) btc_sm_cb_t *p_cb = (btc_sm_cb_t *)handle; if (p_cb == NULL) { - LOG_ERROR("%s : Invalid handle", __FUNCTION__); + BTC_TRACE_ERROR("%s : Invalid handle", __FUNCTION__); return BT_STATUS_FAIL; } diff --git a/components/bt/bluedroid/btc/core/btc_storage.c b/components/bt/bluedroid/btc/core/btc_storage.c index 5114a6befd..654a1bf288 100644 --- a/components/bt/bluedroid/btc/core/btc_storage.c +++ b/components/bt/bluedroid/btc/core/btc_storage.c @@ -42,7 +42,7 @@ bt_status_t btc_storage_add_bonded_device(bt_bdaddr_t *remote_bd_addr, bdstr_t bdstr; bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr)); - LOG_DEBUG("add to storage: Remote device:%s\n", bdstr); + BTC_TRACE_DEBUG("add to storage: Remote device:%s\n", bdstr); btc_config_lock(); int ret = btc_config_set_int(bdstr, BTC_STORAGE_LINK_KEY_TYPE_STR, (int)key_type); @@ -52,7 +52,7 @@ bt_status_t btc_storage_add_bonded_device(bt_bdaddr_t *remote_bd_addr, btc_config_flush(); btc_config_unlock(); - LOG_DEBUG("Storage add rslt %d\n", ret); + BTC_TRACE_DEBUG("Storage add rslt %d\n", ret); return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL; } @@ -77,7 +77,7 @@ static bt_status_t btc_in_fetch_bonded_devices(int add) continue; } - LOG_DEBUG("Remote device:%s\n", name); + BTC_TRACE_DEBUG("Remote device:%s\n", name); LINK_KEY link_key; size_t size = sizeof(link_key); if (btc_config_get_bin(name, BTC_STORAGE_LINK_KEY_STR, link_key, &size)) { @@ -100,11 +100,11 @@ static bt_status_t btc_in_fetch_bonded_devices(int add) } bt_linkkey_file_found = TRUE; } else { - LOG_ERROR("bounded device:%s, LinkKeyType or PinLength is invalid\n", name); + BTC_TRACE_ERROR("bounded device:%s, LinkKeyType or PinLength is invalid\n", name); } } if (!bt_linkkey_file_found) { - LOG_DEBUG("Remote device:%s, no link key\n", name); + BTC_TRACE_DEBUG("Remote device:%s, no link key\n", name); } } btc_config_unlock(); @@ -129,7 +129,7 @@ bt_status_t btc_storage_load_bonded_devices(void) { bt_status_t status; status = btc_in_fetch_bonded_devices(1); - LOG_DEBUG("Storage load rslt %d\n", status); + BTC_TRACE_DEBUG("Storage load rslt %d\n", status); return status; } @@ -148,7 +148,7 @@ bt_status_t btc_storage_remove_bonded_device(bt_bdaddr_t *remote_bd_addr) bdstr_t bdstr; bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr)); int ret = 1; - LOG_DEBUG("Add to storage: Remote device:%s\n", bdstr); + BTC_TRACE_DEBUG("Add to storage: Remote device:%s\n", bdstr); btc_config_lock(); if (btc_config_exist(bdstr, BTC_STORAGE_LINK_KEY_TYPE_STR)) { diff --git a/components/bt/bluedroid/btc/core/btc_task.c b/components/bt/bluedroid/btc/core/btc_task.c index d98e6b4c33..1d14d7ecf0 100644 --- a/components/bt/bluedroid/btc/core/btc_task.c +++ b/components/bt/bluedroid/btc/core/btc_task.c @@ -95,7 +95,7 @@ static void btc_task(void *arg) for (;;) { if (pdTRUE == xQueueReceive(xBtcQueue, &msg, (portTickType)portMAX_DELAY)) { - LOG_DEBUG("%s msg %u %u %u %p\n", __func__, msg.sig, msg.pid, msg.act, msg.arg); + BTC_TRACE_DEBUG("%s msg %u %u %u %p\n", __func__, msg.sig, msg.pid, msg.act, msg.arg); switch (msg.sig) { case BTC_SIG_API_CALL: profile_tab[msg.pid].btc_call(&msg); @@ -120,7 +120,7 @@ static bt_status_t btc_task_post(btc_msg_t *msg, task_post_t timeout) } if (xQueueSend(xBtcQueue, msg, timeout) != pdTRUE) { - LOG_ERROR("Btc Post failed\n"); + BTC_TRACE_ERROR("Btc Post failed\n"); return BT_STATUS_BUSY; } @@ -135,7 +135,7 @@ bt_status_t btc_transfer_context(btc_msg_t *msg, void *arg, int arg_len, btc_arg return BT_STATUS_PARM_INVALID; } - LOG_DEBUG("%s msg %u %u %u %p\n", __func__, msg->sig, msg->pid, msg->act, arg); + BTC_TRACE_DEBUG("%s msg %u %u %u %p\n", __func__, msg->sig, msg->pid, msg->act, arg); memcpy(&lmsg, msg, sizeof(btc_msg_t)); if (arg) { diff --git a/components/bt/bluedroid/btc/profile/esp/ble_button/button_pro.c b/components/bt/bluedroid/btc/profile/esp/ble_button/button_pro.c index 506356b33c..d7233ae564 100644 --- a/components/bt/bluedroid/btc/profile/esp/ble_button/button_pro.c +++ b/components/bt/bluedroid/btc/profile/esp/ble_button/button_pro.c @@ -63,19 +63,19 @@ static void button_profile_cb(esp_gatts_evt_t event, esp_gatts_t *p_data) uint8_t net_event = 0xff; uint8_t len = 0; uint8_t *p_rec_data = NULL; - //LOG_ERROR("p_data->status = %x\n",p_data->status); + //BTC_TRACE_ERROR("p_data->status = %x\n",p_data->status); //if(p_data->status != BTA_GATT_OK){ - // LOG_ERROR("button profile register failed\n"); + // BTC_TRACE_ERROR("button profile register failed\n"); // return; //} - LOG_ERROR("button profile cb event = %x\n", event); + BTC_TRACE_ERROR("button profile cb event = %x\n", event); switch (event) { case ESP_GATTS_REG_EVT: - LOG_ERROR("p_data->reg_oper.status = %x\n", p_data->reg_oper.status); - LOG_ERROR("(p_data->reg_oper.uuid.uu.uuid16=%x\n", p_data->reg_oper.uuid.uu.uuid16); + BTC_TRACE_ERROR("p_data->reg_oper.status = %x\n", p_data->reg_oper.status); + BTC_TRACE_ERROR("(p_data->reg_oper.uuid.uu.uuid16=%x\n", p_data->reg_oper.uuid.uu.uuid16); if (p_data->reg_oper.status != BTA_GATT_OK) { - LOG_ERROR("button profile register failed\n"); + BTC_TRACE_ERROR("button profile register failed\n"); } button_cb_env.gatt_if = p_data->reg_oper.server_if; button_cb_env.enabled = true; @@ -96,11 +96,11 @@ static void button_profile_cb(esp_gatts_evt_t event, esp_gatts_t *p_data) case ESP_GATTS_WRITE_EVT: esp_ble_gatts_send_rsp(p_data->req_data.conn_id, p_data->req_data.trans_id, p_data->req_data.status, NULL); - LOG_ERROR("Received button data:"); + BTC_TRACE_ERROR("Received button data:"); for (int i = 0; i < p_data->req_data.p_data->write_req.len; i++) { - LOG_ERROR("%x", p_data->req_data.p_data->write_req.value[i]); + BTC_TRACE_ERROR("%x", p_data->req_data.p_data->write_req.value[i]); } - LOG_ERROR("\n"); + BTC_TRACE_ERROR("\n"); if (p_data->req_data.p_data->write_req.handle == button_cb_env.button_inst.but_wirt_hdl) { p_rec_data = &p_data->req_data.p_data->write_req.value[0]; @@ -154,12 +154,12 @@ static void button_profile_cb(esp_gatts_evt_t event, esp_gatts_t *p_data) button_cb_env.button_inst.but_cfg_hdl = p_data->add_result.attr_id; } ///Start advertising - LOG_ERROR("\n*******Start sent the ADV.*************\n"); + BTC_TRACE_ERROR("\n*******Start sent the ADV.*************\n"); //esp_ble_start_advertising (&adv_params); //BTA_GATTS_Listen(button_cb_env.gatt_if, true, NULL); break; case ESP_GATTS_CONNECT_EVT: - LOG_ERROR("############BUTTON CONNCET EVT################\n"); + BTC_TRACE_ERROR("############BUTTON CONNCET EVT################\n"); //esp_ble_stop_advertising(); //set the connection flag to true button_env_clcb_alloc(p_data->conn.conn_id, p_data->conn.remote_bda); @@ -205,7 +205,7 @@ void Button_CreateService(void) button_cb_env.inst_id = inst; //if(!button_cb_env.enabled) //{ - // LOG_ERROR("button service added error."); + // BTC_TRACE_ERROR("button service added error."); //} esp_ble_gatts_create_srvc(server_if, &uuid, inst, num_handle, true); @@ -228,7 +228,7 @@ but_clcb_t *button_env_clcb_alloc (uint16_t conn_id, BD_ADDR remote_bda) if (!p_clcb->in_use) { p_clcb->in_use = TRUE; p_clcb->conn_id = conn_id; - LOG_ERROR("p_clcb->conn_id = %x\n", conn_id); + BTC_TRACE_ERROR("p_clcb->conn_id = %x\n", conn_id); p_clcb->connected = TRUE; memcpy(p_clcb->remote_bda, remote_bda, BD_ADDR_LEN); } @@ -295,9 +295,9 @@ esp_gatt_status_t button_init (but_prf_cb_t call_back) { tBT_UUID app_uuid = {LEN_UUID_16, {ATT_SVC_BUTTON}}; - LOG_ERROR("\n=============================button_init==============================================\n"); + BTC_TRACE_ERROR("\n=============================button_init==============================================\n"); if (button_cb_env.enabled) { - LOG_ERROR("button svc already initaliezd\n"); + BTC_TRACE_ERROR("button svc already initaliezd\n"); return ESP_GATT_ERROR; } else { memset(&button_cb_env, 0, sizeof(button_env_cb_t)); @@ -331,7 +331,7 @@ void button_msg_notify(uint16_t len, uint8_t *button_msg) //notify rsp==false; indicate rsp==true. BOOLEAN rsp = false; if (!conn_status && button_cb_env.clcb.congest) { - LOG_ERROR("the conneciton for button profile has been loss\n"); + BTC_TRACE_ERROR("the conneciton for button profile has been loss\n"); return; } diff --git a/components/bt/bluedroid/btc/profile/esp/blufi/blufi_prf.c b/components/bt/bluedroid/btc/profile/esp/blufi/blufi_prf.c index de58b0201e..3bfa6afbc8 100644 --- a/components/bt/bluedroid/btc/profile/esp/blufi/blufi_prf.c +++ b/components/bt/bluedroid/btc/profile/esp/blufi/blufi_prf.c @@ -79,7 +79,7 @@ static inline void btc_blufi_cb_to_app(esp_blufi_cb_event_t event, esp_blufi_cb_ static void blufi_create_service(void) { if (!blufi_env.enabled) { - LOG_ERROR("blufi service added error."); + BTC_TRACE_ERROR("blufi service added error."); return; } @@ -91,14 +91,14 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) { tBTA_GATTS_RSP rsp; - LOG_DEBUG("blufi profile cb event = %x\n", event); + BLUFI_TRACE_DEBUG("blufi profile cb event = %x\n", event); switch (event) { case BTA_GATTS_REG_EVT: - LOG_DEBUG("REG: status %d, app_uuid %04x, gatt_if %d\n", p_data->reg_oper.status, p_data->reg_oper.uuid.uu.uuid16, p_data->reg_oper.server_if); + BLUFI_TRACE_DEBUG("REG: status %d, app_uuid %04x, gatt_if %d\n", p_data->reg_oper.status, p_data->reg_oper.uuid.uu.uuid16, p_data->reg_oper.server_if); if (p_data->reg_oper.status != BTA_GATT_OK) { - LOG_ERROR("BLUFI profile register failed\n"); + BLUFI_TRACE_ERROR("BLUFI profile register failed\n"); return; } @@ -107,7 +107,7 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) //create the blufi service to the service data base. if (p_data->reg_oper.uuid.uu.uuid16 == BLUFI_APP_UUID) { - LOG_DEBUG("%s %d\n", __func__, __LINE__); + BLUFI_TRACE_DEBUG("%s %d\n", __func__, __LINE__); blufi_create_service(); } break; @@ -115,10 +115,10 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) esp_blufi_cb_param_t param; btc_msg_t msg; - LOG_DEBUG("DEREG: status %d, gatt_if %d\n", p_data->reg_oper.status, p_data->reg_oper.server_if); + BLUFI_TRACE_DEBUG("DEREG: status %d, gatt_if %d\n", p_data->reg_oper.status, p_data->reg_oper.server_if); if (p_data->reg_oper.status != BTA_GATT_OK) { - LOG_ERROR("BLUFI profile unregister failed\n"); + BLUFI_TRACE_ERROR("BLUFI profile unregister failed\n"); return; } @@ -148,7 +148,7 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) if (blufi_env.prepare_buf == NULL) { blufi_env.prepare_buf = osi_malloc(BLUFI_PREPAIR_BUF_MAX_SIZE); if (blufi_env.prepare_buf == NULL) { - LOG_ERROR("Blufi prep no mem\n"); + BLUFI_TRACE_ERROR("Blufi prep no mem\n"); status = GATT_NO_RESOURCES; } } else { @@ -165,7 +165,7 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) rsp.attr_value.offset = p_data->req_data.p_data->write_req.offset; memcpy(rsp.attr_value.value, p_data->req_data.p_data->write_req.value, p_data->req_data.p_data->write_req.len); - LOG_DEBUG("prep write, len=%d, offset=%d\n", p_data->req_data.p_data->write_req.len, p_data->req_data.p_data->write_req.offset); + BLUFI_TRACE_DEBUG("prep write, len=%d, offset=%d\n", p_data->req_data.p_data->write_req.len, p_data->req_data.p_data->write_req.offset); BTA_GATTS_SendRsp(p_data->req_data.conn_id, p_data->req_data.trans_id, status, &rsp); @@ -177,7 +177,7 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) return; } else { - LOG_DEBUG("norm write, len=%d, offset=%d\n", p_data->req_data.p_data->write_req.len, p_data->req_data.p_data->write_req.offset); + BLUFI_TRACE_DEBUG("norm write, len=%d, offset=%d\n", p_data->req_data.p_data->write_req.len, p_data->req_data.p_data->write_req.offset); BTA_GATTS_SendRsp(p_data->req_data.conn_id, p_data->req_data.trans_id, p_data->req_data.status, NULL); } @@ -189,7 +189,7 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) break; } case BTA_GATTS_EXEC_WRITE_EVT: - LOG_DEBUG("exec write exec %d\n", p_data->req_data.p_data->exec_write); + BLUFI_TRACE_DEBUG("exec write exec %d\n", p_data->req_data.p_data->exec_write); BTA_GATTS_SendRsp(p_data->req_data.conn_id, p_data->req_data.trans_id, GATT_SUCCESS, NULL); @@ -205,11 +205,11 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) break; case BTA_GATTS_MTU_EVT: - LOG_DEBUG("MTU size %d\n", p_data->req_data.p_data->mtu); + BLUFI_TRACE_DEBUG("MTU size %d\n", p_data->req_data.p_data->mtu); blufi_env.frag_size = p_data->req_data.p_data->mtu - BLUFI_MTU_RESERVED_SIZE; break; case BTA_GATTS_CONF_EVT: - LOG_DEBUG("CONIRM EVT\n"); + BLUFI_TRACE_DEBUG("CONIRM EVT\n"); if (p_data && p_data->req_data.value){ osi_free(p_data->req_data.value); } @@ -268,7 +268,7 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) esp_blufi_cb_param_t param; //set the connection flag to true - LOG_INFO("\ndevice is connected "BT_BD_ADDR_STR", server_if=%d,reason=0x%x,connect_id=%d\n", + BLUFI_TRACE_API("\ndevice is connected "BT_BD_ADDR_STR", server_if=%d,reason=0x%x,connect_id=%d\n", BT_BD_ADDR_HEX(p_data->conn.remote_bda), p_data->conn.server_if, p_data->conn.reason, p_data->conn.conn_id); @@ -291,7 +291,7 @@ static void blufi_profile_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) blufi_env.is_connected = false; //set the connection flag to true - LOG_INFO("\ndevice is disconnected "BT_BD_ADDR_STR", server_if=%d,reason=0x%x,connect_id=%d\n", + BLUFI_TRACE_API("\ndevice is disconnected "BT_BD_ADDR_STR", server_if=%d,reason=0x%x,connect_id=%d\n", BT_BD_ADDR_HEX(p_data->conn.remote_bda), p_data->conn.server_if, p_data->conn.reason, p_data->conn.conn_id); @@ -324,7 +324,7 @@ static tGATT_STATUS btc_blufi_profile_init(void) esp_blufi_callbacks_t *store_p = blufi_env.cbs; if (blufi_env.enabled) { - LOG_ERROR("BLUFI already initialized"); + BLUFI_TRACE_ERROR("BLUFI already initialized"); return GATT_ERROR; } @@ -341,7 +341,7 @@ static tGATT_STATUS btc_blufi_profile_init(void) static tGATT_STATUS btc_blufi_profile_deinit(void) { if (!blufi_env.enabled) { - LOG_ERROR("BLUFI already de-initialized"); + BTC_TRACE_ERROR("BLUFI already de-initialized"); return GATT_ERROR; } @@ -381,7 +381,7 @@ static void btc_blufi_recv_handler(uint8_t *data, int len) int ret; if (hdr->seq != blufi_env.recv_seq) { - LOG_ERROR("%s seq %d is not expect %d\n", __func__, hdr->seq, blufi_env.recv_seq + 1); + BTC_TRACE_ERROR("%s seq %d is not expect %d\n", __func__, hdr->seq, blufi_env.recv_seq + 1); btc_blufi_report_error(ESP_BLUFI_SEQUENCE_ERROR); return; } @@ -393,7 +393,7 @@ static void btc_blufi_recv_handler(uint8_t *data, int len) && (blufi_env.cbs && blufi_env.cbs->decrypt_func)) { ret = blufi_env.cbs->decrypt_func(hdr->seq, hdr->data, hdr->data_len); if (ret != hdr->data_len) { /* enc must be success and enc len must equal to plain len */ - LOG_ERROR("%s decrypt error %d\n", __func__, ret); + BTC_TRACE_ERROR("%s decrypt error %d\n", __func__, ret); btc_blufi_report_error(ESP_BLUFI_DECRYPT_ERROR); return; } @@ -405,7 +405,7 @@ static void btc_blufi_recv_handler(uint8_t *data, int len) checksum = blufi_env.cbs->checksum_func(hdr->seq, &hdr->seq, hdr->data_len + 2); checksum_pkt = hdr->data[hdr->data_len] | (((uint16_t) hdr->data[hdr->data_len + 1]) << 8); if (checksum != checksum_pkt) { - LOG_ERROR("%s checksum error %04x, pkt %04x\n", __func__, checksum, checksum_pkt); + BTC_TRACE_ERROR("%s checksum error %04x, pkt %04x\n", __func__, checksum, checksum_pkt); btc_blufi_report_error(ESP_BLUFI_CHECKSUM_ERROR); return; } @@ -420,7 +420,7 @@ static void btc_blufi_recv_handler(uint8_t *data, int len) blufi_env.total_len = hdr->data[0] | (((uint16_t) hdr->data[1]) << 8); blufi_env.aggr_buf = osi_malloc(blufi_env.total_len); if (blufi_env.aggr_buf == NULL) { - LOG_ERROR("%s no mem, len %d\n", __func__, blufi_env.total_len); + BTC_TRACE_ERROR("%s no mem, len %d\n", __func__, blufi_env.total_len); return; } } @@ -451,7 +451,7 @@ void btc_blufi_send_encap(uint8_t type, uint8_t *data, int total_data_len) if (remain_len > blufi_env.frag_size) { hdr = osi_malloc(sizeof(struct blufi_hdr) + 2 + blufi_env.frag_size + 2); if (hdr == NULL) { - LOG_ERROR("%s no mem\n", __func__); + BTC_TRACE_ERROR("%s no mem\n", __func__); return; } hdr->fc = 0x0; @@ -463,7 +463,7 @@ void btc_blufi_send_encap(uint8_t type, uint8_t *data, int total_data_len) } else { hdr = osi_malloc(sizeof(struct blufi_hdr) + remain_len + 2); if (hdr == NULL) { - LOG_ERROR("%s no mem\n", __func__); + BTC_TRACE_ERROR("%s no mem\n", __func__); return; } hdr->fc = 0x0; @@ -496,7 +496,7 @@ void btc_blufi_send_encap(uint8_t type, uint8_t *data, int total_data_len) if (ret == hdr->data_len) { /* enc must be success and enc len must equal to plain len */ hdr->fc |= BLUFI_FC_ENC; } else { - LOG_ERROR("%s encrypt error %d\n", __func__, ret); + BTC_TRACE_ERROR("%s encrypt error %d\n", __func__, ret); btc_blufi_report_error(ESP_BLUFI_ENCRYPT_ERROR); osi_free(hdr); return; @@ -586,7 +586,7 @@ static void btc_blufi_wifi_conn_report(uint8_t opmode, uint8_t sta_conn_state, u } } if (p - data > data_len) { - LOG_ERROR("%s len error %d %d\n", __func__, (int)(p - data), data_len); + BTC_TRACE_ERROR("%s len error %d %d\n", __func__, (int)(p - data), data_len); } btc_blufi_send_encap(type, data, data_len); @@ -603,7 +603,7 @@ void btc_blufi_send_wifi_list(uint16_t apCount, esp_blufi_ap_record_t *list) uint malloc_size = (1 + 1 + sizeof(list->ssid)) * apCount; p = data = osi_malloc(malloc_size); if (data == NULL) { - LOG_ERROR("malloc error\n"); + BTC_TRACE_ERROR("malloc error\n"); return; } type = BLUFI_BUILD_TYPE(BLUFI_TYPE_DATA, BLUFI_TYPE_DATA_SUBTYPE_WIFI_LIST); @@ -613,7 +613,7 @@ void btc_blufi_send_wifi_list(uint16_t apCount, esp_blufi_ap_record_t *list) data_len = (p - data); //current_len + ssid + rssi + total_len_value if((data_len + len + 1 + 1) > malloc_size) { - LOG_ERROR("%s len error", __func__); + BTC_TRACE_ERROR("%s len error", __func__); osi_free(data); return; } @@ -653,7 +653,7 @@ static void btc_blufi_send_error_info(uint8_t state) type = BLUFI_BUILD_TYPE(BLUFI_TYPE_DATA, BLUFI_TYPE_DATA_SUBTYPE_ERROR_INFO); *p++ = state; if (p - data > data_len) { - LOG_ERROR("%s len error %d %d\n", __func__, (int)(p - data), data_len); + BTC_TRACE_ERROR("%s len error %d %d\n", __func__, (int)(p - data), data_len); } btc_blufi_send_encap(type, data, data_len); @@ -663,12 +663,12 @@ static void btc_blufi_send_error_info(uint8_t state) static void btc_blufi_send_custom_data(uint8_t *value, uint32_t value_len) { if(value == NULL || value_len == 0) { - LOG_ERROR("%s value or value len error", __func__); + BTC_TRACE_ERROR("%s value or value len error", __func__); return; } uint8_t *data = osi_malloc(value_len); if (data == NULL) { - LOG_ERROR("%s mem malloc error", __func__); + BTC_TRACE_ERROR("%s mem malloc error", __func__); return; } uint8_t type = BLUFI_BUILD_TYPE(BLUFI_TYPE_DATA, BLUFI_TYPE_DATA_SUBTYPE_CUSTOM_DATA); @@ -686,77 +686,77 @@ void btc_blufi_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) case ESP_BLUFI_EVENT_RECV_STA_SSID: dst->sta_ssid.ssid = osi_malloc(src->sta_ssid.ssid_len); if (dst->sta_ssid.ssid == NULL) { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } memcpy(dst->sta_ssid.ssid, src->sta_ssid.ssid, src->sta_ssid.ssid_len); break; case ESP_BLUFI_EVENT_RECV_STA_PASSWD: dst->sta_passwd.passwd = osi_malloc(src->sta_passwd.passwd_len); if (dst->sta_passwd.passwd == NULL) { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } memcpy(dst->sta_passwd.passwd, src->sta_passwd.passwd, src->sta_passwd.passwd_len); break; case ESP_BLUFI_EVENT_RECV_SOFTAP_SSID: dst->softap_ssid.ssid = osi_malloc(src->softap_ssid.ssid_len); if (dst->softap_ssid.ssid == NULL) { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } memcpy(dst->softap_ssid.ssid, src->softap_ssid.ssid, src->softap_ssid.ssid_len); break; case ESP_BLUFI_EVENT_RECV_SOFTAP_PASSWD: dst->softap_passwd.passwd = osi_malloc(src->softap_passwd.passwd_len); if (dst->softap_passwd.passwd == NULL) { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } memcpy(dst->softap_passwd.passwd, src->softap_passwd.passwd, src->softap_passwd.passwd_len); break; case ESP_BLUFI_EVENT_RECV_USERNAME: dst->username.name = osi_malloc(src->username.name_len); if (dst->username.name == NULL) { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } memcpy(dst->username.name, src->username.name, src->username.name_len); break; case ESP_BLUFI_EVENT_RECV_CA_CERT: dst->ca.cert = osi_malloc(src->ca.cert_len); if (dst->ca.cert == NULL) { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } memcpy(dst->ca.cert, src->ca.cert, src->ca.cert_len); break; case ESP_BLUFI_EVENT_RECV_CLIENT_CERT: dst->client_cert.cert = osi_malloc(src->client_cert.cert_len); if (dst->client_cert.cert == NULL) { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } memcpy(dst->client_cert.cert, src->client_cert.cert, src->client_cert.cert_len); break; case ESP_BLUFI_EVENT_RECV_SERVER_CERT: dst->server_cert.cert = osi_malloc(src->server_cert.cert_len); if (dst->server_cert.cert == NULL) { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } memcpy(dst->server_cert.cert, src->server_cert.cert, src->server_cert.cert_len); break; case ESP_BLUFI_EVENT_RECV_CLIENT_PRIV_KEY: dst->client_pkey.pkey = osi_malloc(src->client_pkey.pkey_len); if (dst->client_pkey.pkey == NULL) { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } memcpy(dst->client_pkey.pkey, src->client_pkey.pkey, src->client_pkey.pkey_len); break; case ESP_BLUFI_EVENT_RECV_SERVER_PRIV_KEY: dst->server_pkey.pkey = osi_malloc(src->server_pkey.pkey_len); if (dst->server_pkey.pkey == NULL) { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } memcpy(dst->server_pkey.pkey, src->server_pkey.pkey, src->server_pkey.pkey_len); break; case ESP_BLUFI_EVENT_RECV_CUSTOM_DATA: dst->custom_data.data = osi_malloc(src->custom_data.data_len); if (dst->custom_data.data == NULL) { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); break; } memcpy(dst->custom_data.data, src->custom_data.data, src->custom_data.data_len); @@ -898,7 +898,7 @@ void btc_blufi_cb_handler(btc_msg_t *msg) btc_blufi_cb_to_app(ESP_BLUFI_EVENT_RECV_CUSTOM_DATA, param); break; default: - LOG_ERROR("%s UNKNOWN %d\n", __func__, msg->act); + BTC_TRACE_ERROR("%s UNKNOWN %d\n", __func__, msg->act); break; } @@ -995,12 +995,12 @@ void btc_blufi_call_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) case BTC_BLUFI_ACT_SEND_CUSTOM_DATA:{ uint8_t *data = src->custom_data.data; if(data == NULL) { - LOG_ERROR("custom data is NULL\n"); + BTC_TRACE_ERROR("custom data is NULL\n"); break; } dst->custom_data.data = osi_malloc(src->custom_data.data_len); if(dst->custom_data.data == NULL) { - LOG_ERROR("custom data malloc error\n"); + BTC_TRACE_ERROR("custom data malloc error\n"); break; } memcpy(dst->custom_data.data, src->custom_data.data, src->custom_data.data_len); @@ -1085,7 +1085,7 @@ void btc_blufi_call_handler(btc_msg_t *msg) btc_blufi_send_custom_data(arg->custom_data.data, arg->custom_data.data_len); break; default: - LOG_ERROR("%s UNKNOWN %d\n", __func__, msg->act); + BTC_TRACE_ERROR("%s UNKNOWN %d\n", __func__, msg->act); break; } btc_blufi_call_deep_free(msg); diff --git a/components/bt/bluedroid/btc/profile/esp/blufi/blufi_protocol.c b/components/bt/bluedroid/btc/profile/esp/blufi/blufi_protocol.c index 19ab994ba6..b962d10051 100644 --- a/components/bt/bluedroid/btc/profile/esp/blufi/blufi_protocol.c +++ b/components/bt/bluedroid/btc/profile/esp/blufi/blufi_protocol.c @@ -113,7 +113,7 @@ void btc_blufi_protocol_handler(uint8_t type, uint8_t *data, int len) btc_transfer_context(&msg, NULL, 0, NULL); break; default: - LOG_ERROR("%s Unkown Ctrl pkt %02x\n", __func__, type); + BTC_TRACE_ERROR("%s Unkown Ctrl pkt %02x\n", __func__, type); break; } break; @@ -260,7 +260,7 @@ void btc_blufi_protocol_handler(uint8_t type, uint8_t *data, int len) btc_transfer_context(&msg, ¶m, sizeof(esp_blufi_cb_param_t), btc_blufi_cb_deep_copy); break; default: - LOG_ERROR("%s Unkown Ctrl pkt %02x\n", __func__, type); + BTC_TRACE_ERROR("%s Unkown Ctrl pkt %02x\n", __func__, type); break; } break; diff --git a/components/bt/bluedroid/btc/profile/esp/wechat_AirSync/wx_airsync_prf.c b/components/bt/bluedroid/btc/profile/esp/wechat_AirSync/wx_airsync_prf.c index 2620b60d82..b4b349ead3 100644 --- a/components/bt/bluedroid/btc/profile/esp/wechat_AirSync/wx_airsync_prf.c +++ b/components/bt/bluedroid/btc/profile/esp/wechat_AirSync/wx_airsync_prf.c @@ -57,12 +57,12 @@ static void airsync_profile_cb(esp_gatts_evt_t event, esp_gatts_t *p_data) tAirSync_INST *p_inst = &airsync_cb_env.airsync_inst; - LOG_ERROR("airsync profile cb event = %x\n", event); + BTC_TRACE_ERROR("airsync profile cb event = %x\n", event); switch (event) { case ESP_GATTS_REG_EVT: if (p_data->reg_oper.status != BTA_GATT_OK) { - LOG_ERROR("button profile register failed\n"); + BTC_TRACE_ERROR("button profile register failed\n"); } airsync_cb_env.gatt_if = p_data->reg_oper.server_if; airsync_cb_env.enabled = true; @@ -203,7 +203,7 @@ tAirSync_CLCB *airsync_env_clcb_alloc (UINT16 conn_id, BD_ADDR remote_bda) if (!p_clcb->in_use) { p_clcb->in_use = TRUE; p_clcb->conn_id = conn_id; - LOG_ERROR("p_clcb->conn_id = %x\n", conn_id); + BTC_TRACE_ERROR("p_clcb->conn_id = %x\n", conn_id); p_clcb->connected = TRUE; memcpy(p_clcb->remote_bda, remote_bda, BD_ADDR_LEN); } @@ -248,7 +248,7 @@ tGATT_STATUS AirSync_Init(tAIRSYNC_CBACK *call_back) if (airsync_cb_env.enabled) { - LOG_ERROR("airsync svc already initaliezd\n"); + BTC_TRACE_ERROR("airsync svc already initaliezd\n"); return ESP_GATT_ERROR; } else { memset(&airsync_cb_env, 0, sizeof(tAIRSYNC_CB_ENV)); diff --git a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c index 827542dc18..da5ff32b96 100644 --- a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c +++ b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c @@ -1136,7 +1136,7 @@ static UINT8 btc_get_num_aa_frame(void) } btc_aa_src_cb.media_feeding_state.pcm.counter -= result * pcm_bytes_per_frame; - LOG_VERBOSE("WRITE %d FRAMES", result); + BTC_TRACE_VERBOSE("WRITE %d FRAMES", result); } break; @@ -1461,7 +1461,7 @@ static void btc_a2dp_source_send_aa_frame(void) } /* send it */ - LOG_VERBOSE("%s: send %d frames", __FUNCTION__, nb_frame_2_send); + BTC_TRACE_VERBOSE("%s: send %d frames", __FUNCTION__, nb_frame_2_send); bta_av_ci_src_data_ready(BTA_AV_CHNL_AUDIO); } @@ -1540,7 +1540,7 @@ static void btc_a2dp_source_aa_start_tx(void) btc_aa_src_cb.media_alarm = osi_alarm_new("aaTx", btc_a2dp_source_alarm_cb, NULL, BTC_MEDIA_TIME_TICK_MS); if (!btc_aa_src_cb.media_alarm) { - LOG_ERROR("%s unable to allocate media alarm.", __func__); + BTC_TRACE_ERROR("%s unable to allocate media alarm.", __func__); return; } diff --git a/components/bt/bluedroid/btc/profile/std/a2dp/btc_av.c b/components/bt/bluedroid/btc/profile/std/a2dp/btc_av.c index 3256293755..0541111886 100644 --- a/components/bt/bluedroid/btc/profile/std/a2dp/btc_av.c +++ b/components/bt/bluedroid/btc/profile/std/a2dp/btc_av.c @@ -227,13 +227,13 @@ static void btc_initiate_av_open_tmr_hdlr(void *arg) btc_av_connect_req_t connect_req; /* is there at least one RC connection - There should be */ if (btc_rc_get_connected_peer(peer_addr)) { - LOG_DEBUG("%s Issuing connect to the remote RC peer", __FUNCTION__); + BTC_TRACE_DEBUG("%s Issuing connect to the remote RC peer", __FUNCTION__); /* In case of AVRCP connection request, we will initiate SRC connection */ memcpy(connect_req.target_bda.address, peer_addr, sizeof(bt_bdaddr_t)); connect_req.uuid = UUID_SERVCLASS_AUDIO_SOURCE; btc_dispatch_sm_event(BTC_AV_CONNECT_REQ_EVT, &connect_req, sizeof(btc_av_connect_req_t)); } else { - LOG_ERROR("%s No connected RC peers", __FUNCTION__); + BTC_TRACE_ERROR("%s No connected RC peers", __FUNCTION__); } } #endif /* BTC_AV_SRC_INCLUDED */ @@ -283,7 +283,7 @@ static void btc_report_audio_state(esp_a2d_audio_state_t state, bt_bdaddr_t *bd_ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data) { - LOG_DEBUG("%s event:%s flags %x\n", __FUNCTION__, + BTC_TRACE_DEBUG("%s event:%s flags %x\n", __FUNCTION__, dump_av_sm_event_name(event), btc_av_cb.flags); switch (event) { @@ -332,7 +332,7 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data) */ #if BTC_AV_SRC_INCLUDED - LOG_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV"); + BTC_TRACE_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV"); tle_av_open_on_rc = osi_alarm_new("AVconn", btc_initiate_av_open_tmr_hdlr, NULL, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000); osi_alarm_set(tle_av_open_on_rc, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000); #endif /* BTC_AV_SRC_INCLUDED */ @@ -358,7 +358,7 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data) break; default: - LOG_WARN("%s : unhandled event:%s\n", __FUNCTION__, + BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, dump_av_sm_event_name(event)); return FALSE; @@ -379,7 +379,7 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data) static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data) { - LOG_DEBUG("%s event:%s flags %x\n", __FUNCTION__, + BTC_TRACE_DEBUG("%s event:%s flags %x\n", __FUNCTION__, dump_av_sm_event_name(event), btc_av_cb.flags); switch (event) { @@ -392,7 +392,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data) break; case BTA_AV_REJECT_EVT: - LOG_DEBUG(" Received BTA_AV_REJECT_EVT \n"); + BTC_TRACE_DEBUG(" Received BTA_AV_REJECT_EVT \n"); btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, &(btc_av_cb.peer_bda), 0); btc_sm_change_state(btc_av_cb.sm_handle, BTC_AV_STATE_IDLE); break; @@ -401,7 +401,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data) tBTA_AV *p_bta_data = (tBTA_AV *)p_data; esp_a2d_connection_state_t state; btc_sm_state_t av_state; - LOG_DEBUG("status:%d, edr 0x%x\n", p_bta_data->open.status, + BTC_TRACE_DEBUG("status:%d, edr 0x%x\n", p_bta_data->open.status, p_bta_data->open.edr); if (p_bta_data->open.status == BTA_AV_SUCCESS) { @@ -411,7 +411,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data) btc_av_cb.peer_sep = p_bta_data->open.sep; } else { - LOG_WARN("BTA_AV_OPEN_EVT::FAILED status: %d\n", + BTC_TRACE_WARNING("BTA_AV_OPEN_EVT::FAILED status: %d\n", p_bta_data->open.status ); state = ESP_A2D_CONNECTION_STATE_DISCONNECTED; av_state = BTC_AV_STATE_IDLE; @@ -447,11 +447,11 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data) // Check for device, if same device which moved to opening then ignore callback if (memcmp ((bt_bdaddr_t *)p_data, &(btc_av_cb.peer_bda), sizeof(btc_av_cb.peer_bda)) == 0) { - LOG_DEBUG("%s: Same device moved to Opening state,ignore Connect Req\n", __func__); + BTC_TRACE_DEBUG("%s: Same device moved to Opening state,ignore Connect Req\n", __func__); btc_queue_advance(); break; } else { - LOG_DEBUG("%s: Moved from idle by Incoming Connection request\n", __func__); + BTC_TRACE_DEBUG("%s: Moved from idle by Incoming Connection request\n", __func__); btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, (bt_bdaddr_t *)p_data, 0); btc_queue_advance(); break; @@ -461,10 +461,10 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data) // Check for device, if same device which moved to opening then ignore callback if (memcmp (((tBTA_AV *)p_data)->pend.bd_addr, &(btc_av_cb.peer_bda), sizeof(btc_av_cb.peer_bda)) == 0) { - LOG_DEBUG("%s: Same device moved to Opening state,ignore Pending Req\n", __func__); + BTC_TRACE_DEBUG("%s: Same device moved to Opening state,ignore Pending Req\n", __func__); break; } else { - LOG_DEBUG("%s: Moved from idle by outgoing Connection request\n", __func__); + BTC_TRACE_DEBUG("%s: Moved from idle by outgoing Connection request\n", __func__); BTA_AvDisconnect(((tBTA_AV *)p_data)->pend.bd_addr); break; } @@ -472,7 +472,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data) CHECK_RC_EVENT(event, p_data); default: - LOG_WARN("%s : unhandled event:%s\n", __FUNCTION__, + BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, dump_av_sm_event_name(event)); return FALSE; @@ -494,7 +494,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data) static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data) { - LOG_DEBUG("%s event:%s flags %x\n", __FUNCTION__, + BTC_TRACE_DEBUG("%s event:%s flags %x\n", __FUNCTION__, dump_av_sm_event_name(event), btc_av_cb.flags); switch (event) { @@ -548,7 +548,7 @@ static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data) break; default: - LOG_WARN("%s : unhandled event:%s\n", __FUNCTION__, + BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, dump_av_sm_event_name(event)); return FALSE; } @@ -570,12 +570,12 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data) { tBTA_AV *p_av = (tBTA_AV *)p_data; - LOG_DEBUG("%s event:%s flags %x\n", __FUNCTION__, + BTC_TRACE_DEBUG("%s event:%s flags %x\n", __FUNCTION__, dump_av_sm_event_name(event), btc_av_cb.flags); if ( (event == BTA_AV_REMOTE_CMD_EVT) && (btc_av_cb.flags & BTC_AV_FLAG_REMOTE_SUSPEND) && (p_av->remote_cmd.rc_id == BTA_AV_RC_PLAY) ) { - LOG_INFO("%s: Resetting remote suspend flag on RC PLAY\n", __FUNCTION__); + BTC_TRACE_DEBUG("%s: Resetting remote suspend flag on RC PLAY\n", __FUNCTION__); btc_av_cb.flags &= ~BTC_AV_FLAG_REMOTE_SUSPEND; } @@ -600,7 +600,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data) break; case BTA_AV_START_EVT: { - LOG_INFO("BTA_AV_START_EVT status %d, suspending %d, init %d\n", + BTC_TRACE_DEBUG("BTA_AV_START_EVT status %d, suspending %d, init %d\n", p_av->start.status, p_av->start.suspending, p_av->start.initiator); if ((p_av->start.status == BTA_SUCCESS) && (p_av->start.suspending == TRUE)) { @@ -613,7 +613,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data) */ if (!(btc_av_cb.flags & BTC_AV_FLAG_PENDING_START)) { if (btc_av_cb.peer_sep == AVDT_TSEP_SNK) { - LOG_INFO("%s: trigger suspend as remote initiated!!", __FUNCTION__); + BTC_TRACE_DEBUG("%s: trigger suspend as remote initiated!!", __FUNCTION__); btc_dispatch_sm_event(BTC_AV_SUSPEND_STREAM_REQ_EVT, NULL, 0); } } @@ -679,7 +679,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data) case BTA_AV_RECONFIG_EVT: if ((btc_av_cb.flags & BTC_AV_FLAG_PENDING_START) && (p_av->reconfig.status == BTA_AV_SUCCESS)) { - LOG_WARN("reconfig done BTA_AVstart()\n"); + BTC_TRACE_WARNING("reconfig done BTA_AVstart()\n"); BTA_AvStart(); } else if (btc_av_cb.flags & BTC_AV_FLAG_PENDING_START) { btc_av_cb.flags &= ~BTC_AV_FLAG_PENDING_START; @@ -690,9 +690,9 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data) case BTC_AV_CONNECT_REQ_EVT: if (memcmp (&((btc_av_connect_req_t *)p_data)->target_bda, &(btc_av_cb.peer_bda), sizeof(btc_av_cb.peer_bda)) == 0) { - LOG_DEBUG("%s: Ignore BTC_AVCONNECT_REQ_EVT for same device\n", __func__); + BTC_TRACE_DEBUG("%s: Ignore BTC_AVCONNECT_REQ_EVT for same device\n", __func__); } else { - LOG_DEBUG("%s: Moved to opened by Other Incoming Conn req\n", __func__); + BTC_TRACE_DEBUG("%s: Moved to opened by Other Incoming Conn req\n", __func__); btc_report_connection_state(ESP_A2D_CONNECTION_STATE_DISCONNECTED, (bt_bdaddr_t *)p_data, ESP_A2D_DISC_RSN_NORMAL); } @@ -702,7 +702,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data) CHECK_RC_EVENT(event, p_data); default: - LOG_WARN("%s : unhandled event:%s\n", __FUNCTION__, + BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, dump_av_sm_event_name(event)); return FALSE; @@ -724,7 +724,7 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data) { tBTA_AV *p_av = (tBTA_AV *)p_data; - LOG_DEBUG("%s event:%s flags %x\n", __FUNCTION__, + BTC_TRACE_DEBUG("%s event:%s flags %x\n", __FUNCTION__, dump_av_sm_event_name(event), btc_av_cb.flags); switch (event) { @@ -799,7 +799,7 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data) case BTA_AV_SUSPEND_EVT: - LOG_INFO("BTA_AV_SUSPEND_EVT status %d, init %d\n", + BTC_TRACE_DEBUG("BTA_AV_SUSPEND_EVT status %d, init %d\n", p_av->suspend.status, p_av->suspend.initiator); /* a2dp suspended, stop media task until resumed */ @@ -871,7 +871,7 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data) CHECK_RC_EVENT(event, p_data); default: - LOG_WARN("%s : unhandled event:%s\n", __FUNCTION__, + BTC_TRACE_WARNING("%s : unhandled event:%s\n", __FUNCTION__, dump_av_sm_event_name(event)); return FALSE; @@ -1005,7 +1005,7 @@ static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid) btc_av_connect_req_t connect_req; memcpy(&connect_req.target_bda, bd_addr, sizeof(bt_bdaddr_t)); connect_req.uuid = uuid; - LOG_DEBUG("%s\n", __FUNCTION__); + BTC_TRACE_DEBUG("%s\n", __FUNCTION__); btc_sm_dispatch(btc_av_cb.sm_handle, BTC_AV_CONNECT_REQ_EVT, (char *)&connect_req); @@ -1023,7 +1023,7 @@ static bt_status_t connect_int(bt_bdaddr_t *bd_addr, uint16_t uuid) *******************************************************************************/ static void clean_up(int service_id) { - LOG_DEBUG("%s\n", __FUNCTION__); + BTC_TRACE_DEBUG("%s\n", __FUNCTION__); if (service_id == BTA_A2DP_SOURCE_SERVICE_ID) { #if BTC_AV_SRC_INCLUDED @@ -1081,7 +1081,7 @@ BOOLEAN btc_av_stream_ready(void) { btc_sm_state_t state = btc_sm_get_state(btc_av_cb.sm_handle); - LOG_DEBUG("btc_av_stream_ready : sm hdl %d, state %d, flags %x\n", + BTC_TRACE_DEBUG("btc_av_stream_ready : sm hdl %d, state %d, flags %x\n", (int)btc_av_cb.sm_handle, state, btc_av_cb.flags); /* check if we are remotely suspended or stop is pending */ @@ -1106,7 +1106,7 @@ BOOLEAN btc_av_stream_started_ready(void) { btc_sm_state_t state = btc_sm_get_state(btc_av_cb.sm_handle); - LOG_DEBUG("btc_av_stream_started : sm hdl %d, state %d, flags %x\n", + BTC_TRACE_DEBUG("btc_av_stream_started : sm hdl %d, state %d, flags %x\n", (int)btc_av_cb.sm_handle, state, btc_av_cb.flags); /* disallow media task to start if we have pending actions */ @@ -1149,7 +1149,7 @@ static void bte_av_callback(tBTA_AV_EVT event, tBTA_AV *p_data) stat = btc_transfer_context(&msg, p_data, sizeof(tBTA_AV), btc_av_event_deep_copy); if (stat) { - LOG_ERROR("%s transfer failed\n", __func__); + BTC_TRACE_ERROR("%s transfer failed\n", __func__); } } @@ -1166,7 +1166,7 @@ static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data) if ( (state == BTC_AV_STATE_STARTED) || /* send SBC packets only in Started State */ (state == BTC_AV_STATE_OPENED) ) { que_len = btc_a2dp_sink_enque_buf((BT_HDR *)p_data); - LOG_DEBUG(" Packets in Que %d\n", que_len); + BTC_TRACE_DEBUG(" Packets in Que %d\n", que_len); } else { return; } @@ -1191,14 +1191,14 @@ static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data) memcpy(arg.mcc.cie.sbc, (uint8_t *)p_data + 3, ESP_A2D_CIE_LEN_SBC); btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL); } else { - LOG_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d\n", a2d_status); + BTC_TRACE_ERROR("ERROR dump_codec_info A2D_ParsSbcInfo fail:%d\n", a2d_status); } } } #else static void bte_av_media_callback(tBTA_AV_EVT event, tBTA_AV_MEDIA *p_data) { - LOG_WARN("%s : event %u\n", __func__, event); + BTC_TRACE_WARNING("%s : event %u\n", __func__, event); } #endif @@ -1313,7 +1313,7 @@ BOOLEAN btc_av_is_peer_edr(void) ******************************************************************************/ void btc_av_clear_remote_suspend_flag(void) { - LOG_DEBUG("%s: flag :%x\n", __func__, btc_av_cb.flags); + BTC_TRACE_DEBUG("%s: flag :%x\n", __func__, btc_av_cb.flags); btc_av_cb.flags &= ~BTC_AV_FLAG_REMOTE_SUSPEND; } @@ -1393,7 +1393,7 @@ void btc_a2dp_call_handler(btc_msg_t *msg) break; } default: - LOG_WARN("%s : unhandled event: %d\n", __FUNCTION__, msg->act); + BTC_TRACE_WARNING("%s : unhandled event: %d\n", __FUNCTION__, msg->act); } } @@ -1416,14 +1416,14 @@ void btc_a2dp_cb_handler(btc_msg_t *msg) *******************************************************************************/ static bt_status_t btc_a2d_sink_init(void) { - LOG_DEBUG("%s()\n", __func__); + BTC_TRACE_DEBUG("%s()\n", __func__); return btc_av_init(BTA_A2DP_SINK_SERVICE_ID); } static bt_status_t btc_a2d_sink_connect(bt_bdaddr_t *remote_bda) { - LOG_DEBUG("%s\n", __FUNCTION__); + BTC_TRACE_DEBUG("%s\n", __FUNCTION__); CHECK_BTAV_INIT(); return btc_queue_connect(UUID_SERVCLASS_AUDIO_SINK, remote_bda, connect_int); @@ -1449,7 +1449,7 @@ static void btc_a2d_sink_deinit(void) *******************************************************************************/ static bt_status_t btc_a2d_src_init(void) { - LOG_DEBUG("%s()\n", __func__); + BTC_TRACE_DEBUG("%s()\n", __func__); return btc_av_init(BTA_A2DP_SOURCE_SERVICE_ID); } @@ -1461,7 +1461,7 @@ static void btc_a2d_src_deinit(void) static bt_status_t btc_a2d_src_connect(bt_bdaddr_t *remote_bda) { - LOG_DEBUG("%s\n", __FUNCTION__); + BTC_TRACE_DEBUG("%s\n", __FUNCTION__); CHECK_BTAV_INIT(); return btc_queue_connect(UUID_SERVCLASS_AUDIO_SOURCE, remote_bda, connect_int); diff --git a/components/bt/bluedroid/btc/profile/std/avrc/btc_avrc.c b/components/bt/bluedroid/btc/profile/std/avrc/btc_avrc.c index 4d061aed90..a2e21e163b 100644 --- a/components/bt/bluedroid/btc/profile/std/avrc/btc_avrc.c +++ b/components/bt/bluedroid/btc/profile/std/avrc/btc_avrc.c @@ -47,9 +47,9 @@ #define MAX_CMD_QUEUE_LEN 8 #define CHECK_ESP_RC_CONNECTED do { \ - LOG_DEBUG("## %s ##", __FUNCTION__); \ + BTC_TRACE_DEBUG("## %s ##", __FUNCTION__); \ if (btc_rc_vb.rc_connected == FALSE) { \ - LOG_WARN("Function %s() called when RC is not connected", __FUNCTION__); \ + BTC_TRACE_WARNING("Function %s() called when RC is not connected", __FUNCTION__); \ return ESP_ERR_INVALID_STATE; \ } \ } while (0) @@ -138,17 +138,17 @@ static void handle_rc_features(void) ***************************************************************************/ static void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open) { - LOG_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_open->rc_handle); + BTC_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_open->rc_handle); bt_bdaddr_t rc_addr; if (p_rc_open->status == BTA_AV_SUCCESS) { //check if already some RC is connected if (btc_rc_vb.rc_connected) { - LOG_ERROR("Got RC OPEN in connected state, Connected RC: %d \ + BTC_TRACE_ERROR("Got RC OPEN in connected state, Connected RC: %d \ and Current RC: %d", btc_rc_vb.rc_handle, p_rc_open->rc_handle ); if ((btc_rc_vb.rc_handle != p_rc_open->rc_handle) && (bdcmp(btc_rc_vb.rc_addr, p_rc_open->peer_addr))) { - LOG_DEBUG("Got RC connected for some other handle"); + BTC_TRACE_DEBUG("Got RC connected for some other handle"); BTA_AvCloseRc(p_rc_open->rc_handle); return; } @@ -174,7 +174,7 @@ static void handle_rc_connect (tBTA_AV_RC_OPEN *p_rc_open) handle_rc_features(); } } else { - LOG_ERROR("%s Connect failed with error code: %d", + BTC_TRACE_ERROR("%s Connect failed with error code: %d", __FUNCTION__, p_rc_open->status); btc_rc_vb.rc_connected = FALSE; } @@ -192,10 +192,10 @@ static void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close) { bt_bdaddr_t rc_addr; - LOG_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_close->rc_handle); + BTC_TRACE_DEBUG("%s: rc_handle: %d", __FUNCTION__, p_rc_close->rc_handle); if ((p_rc_close->rc_handle != btc_rc_vb.rc_handle) && (bdcmp(btc_rc_vb.rc_addr, p_rc_close->peer_addr))) { - LOG_ERROR("Got disconnect of unknown device"); + BTC_TRACE_ERROR("Got disconnect of unknown device"); return; } @@ -296,7 +296,7 @@ static void handle_rc_metadata_rsp ( tBTA_AV_META_MSG *p_remote_rsp) break; } #else - LOG_ERROR("%s AVRCP metadata is not enabled", __FUNCTION__); + BTC_TRACE_ERROR("%s AVRCP metadata is not enabled", __FUNCTION__); #endif } @@ -322,7 +322,7 @@ static void handle_rc_passthrough_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp) key_state = 0; } - LOG_DEBUG("%s: rc_id=%d status=%s", __FUNCTION__, p_remote_rsp->rc_id, status); + BTC_TRACE_DEBUG("%s: rc_id=%d status=%s", __FUNCTION__, p_remote_rsp->rc_id, status); do { esp_avrc_ct_cb_param_t param; @@ -333,10 +333,10 @@ static void handle_rc_passthrough_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp) btc_avrc_ct_cb_to_app(ESP_AVRC_CT_PASSTHROUGH_RSP_EVT, ¶m); } while (0); } else { - LOG_ERROR("%s DUT does not support AVRCP controller role", __FUNCTION__); + BTC_TRACE_ERROR("%s DUT does not support AVRCP controller role", __FUNCTION__); } #else - LOG_ERROR("%s AVRCP controller role is not enabled", __FUNCTION__); + BTC_TRACE_ERROR("%s AVRCP controller role is not enabled", __FUNCTION__); #endif } @@ -350,10 +350,10 @@ static void handle_rc_passthrough_rsp ( tBTA_AV_REMOTE_RSP *p_remote_rsp) ***************************************************************************/ void btc_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data) { - LOG_DEBUG ("%s event:%s", __FUNCTION__, dump_rc_event(event)); + BTC_TRACE_DEBUG ("%s event:%s", __FUNCTION__, dump_rc_event(event)); switch (event) { case BTA_AV_RC_OPEN_EVT: { - LOG_DEBUG("Peer_features:%x", p_data->rc_open.peer_features); + BTC_TRACE_DEBUG("Peer_features:%x", p_data->rc_open.peer_features); handle_rc_connect( &(p_data->rc_open) ); } break; @@ -363,14 +363,14 @@ void btc_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data) #if (AVRC_CTLR_INCLUDED == TRUE) case BTA_AV_REMOTE_RSP_EVT: { - LOG_DEBUG("RSP: rc_id:0x%x key_state:%d", p_data->remote_rsp.rc_id, + BTC_TRACE_DEBUG("RSP: rc_id:0x%x key_state:%d", p_data->remote_rsp.rc_id, p_data->remote_rsp.key_state); handle_rc_passthrough_rsp( (&p_data->remote_rsp) ); } break; #endif case BTA_AV_RC_FEAT_EVT: { - LOG_DEBUG("Peer_features:%x", p_data->rc_feat.peer_features); + BTC_TRACE_DEBUG("Peer_features:%x", p_data->rc_feat.peer_features); btc_rc_vb.rc_features = p_data->rc_feat.peer_features; handle_rc_features(); } @@ -384,7 +384,7 @@ void btc_rc_handler(tBTA_AV_EVT event, tBTA_AV *p_data) // below events are not handled for now case BTA_AV_REMOTE_CMD_EVT: default: - LOG_DEBUG("Unhandled RC event : 0x%x", event); + BTC_TRACE_DEBUG("Unhandled RC event : 0x%x", event); } } @@ -419,7 +419,7 @@ BOOLEAN btc_rc_get_connected_peer(BD_ADDR peer_addr) *******************************************************************************/ static void btc_avrc_ct_init(void) { - LOG_DEBUG("## %s ##", __FUNCTION__); + BTC_TRACE_DEBUG("## %s ##", __FUNCTION__); memset (&btc_rc_vb, 0, sizeof(btc_rc_vb)); btc_rc_vb.rc_vol_label = MAX_LABEL; @@ -438,10 +438,10 @@ static void btc_avrc_ct_init(void) ***************************************************************************/ static void btc_avrc_ct_deinit(void) { - LOG_INFO("## %s ##", __FUNCTION__); + BTC_TRACE_API("## %s ##", __FUNCTION__); memset(&btc_rc_vb, 0, sizeof(btc_rc_cb_t)); - LOG_INFO("## %s ## completed", __FUNCTION__); + BTC_TRACE_API("## %s ## completed", __FUNCTION__); } static bt_status_t btc_avrc_ct_send_set_player_value_cmd(uint8_t tl, uint8_t attr_id, uint8_t value_id) @@ -471,12 +471,12 @@ static bt_status_t btc_avrc_ct_send_set_player_value_cmd(uint8_t tl, uint8_t att status = BT_STATUS_SUCCESS; } else { status = BT_STATUS_FAIL; - LOG_DEBUG("%s: feature not supported", __FUNCTION__); + BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__); } } #else - LOG_DEBUG("%s: feature not enabled", __FUNCTION__); + BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__); #endif return status; @@ -505,12 +505,12 @@ static bt_status_t btc_avrc_ct_send_register_notification_cmd(uint8_t tl, uint8_ status = BT_STATUS_SUCCESS; } else { status = BT_STATUS_FAIL; - LOG_DEBUG("%s: feature not supported", __FUNCTION__); + BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__); } } #else - LOG_DEBUG("%s: feature not enabled", __FUNCTION__); + BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__); #endif return status; @@ -547,12 +547,12 @@ static bt_status_t btc_avrc_ct_send_metadata_cmd (uint8_t tl, uint8_t attr_mask) status = BT_STATUS_SUCCESS; } else { status = BT_STATUS_FAIL; - LOG_DEBUG("%s: feature not supported", __FUNCTION__); + BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__); } } #else - LOG_DEBUG("%s: feature not enabled", __FUNCTION__); + BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__); #endif return status; @@ -564,19 +564,19 @@ static bt_status_t btc_avrc_ct_send_passthrough_cmd(uint8_t tl, uint8_t key_code #if (AVRC_CTLR_INCLUDED == TRUE) CHECK_ESP_RC_CONNECTED; - LOG_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__, + BTC_TRACE_DEBUG("%s: key-code: %d, key-state: %d", __FUNCTION__, key_code, key_state); if (btc_rc_vb.rc_features & BTA_AV_FEAT_RCTG) { BTA_AvRemoteCmd(btc_rc_vb.rc_handle, tl, (tBTA_AV_RC)key_code, (tBTA_AV_STATE)key_state); status = BT_STATUS_SUCCESS; - LOG_INFO("%s: succesfully sent passthrough command to BTA", __FUNCTION__); + BTC_TRACE_API("%s: succesfully sent passthrough command to BTA", __FUNCTION__); } else { status = BT_STATUS_FAIL; - LOG_DEBUG("%s: feature not supported", __FUNCTION__); + BTC_TRACE_DEBUG("%s: feature not supported", __FUNCTION__); } #else - LOG_DEBUG("%s: feature not enabled", __FUNCTION__); + BTC_TRACE_DEBUG("%s: feature not enabled", __FUNCTION__); #endif return status; @@ -614,7 +614,7 @@ void btc_avrc_call_handler(btc_msg_t *msg) break; } default: - LOG_WARN("%s : unhandled event: %d\n", __FUNCTION__, msg->act); + BTC_TRACE_WARNING("%s : unhandled event: %d\n", __FUNCTION__, msg->act); } } diff --git a/components/bt/bluedroid/btc/profile/std/battery/battery_prf.c b/components/bt/bluedroid/btc/profile/std/battery/battery_prf.c index d11a09f1bb..5a03aab553 100644 --- a/components/bt/bluedroid/btc/profile/std/battery/battery_prf.c +++ b/components/bt/bluedroid/btc/profile/std/battery/battery_prf.c @@ -64,7 +64,7 @@ static void bas_gatts_callback(esp_gatts_evt_t event, tBTA_GATTS *p_data) case ESP_GATTS_REG_EVT: { esp_gatt_status_t status = p_data->reg_oper.status; server_if = p_data->reg_oper.server_if; - LOG_ERROR("BAS register completed: event=%d, status=%d, server_if=%d\n", + BTC_TRACE_ERROR("BAS register completed: event=%d, status=%d, server_if=%d\n", event, status, server_if); UINT8 app_id = 0xff; @@ -77,18 +77,18 @@ static void bas_gatts_callback(esp_gatts_evt_t event, tBTA_GATTS *p_data) /*connect callback*/ case ESP_GATTS_CONNECT_EVT: { - LOG_ERROR("\ndevice is connected "BT_BD_ADDR_STR", server_if=%d,reason=0x%x,connect_id=%d\n", + BTC_TRACE_ERROR("\ndevice is connected "BT_BD_ADDR_STR", server_if=%d,reason=0x%x,connect_id=%d\n", BT_BD_ADDR_HEX(p_data->conn.remote_bda), p_data->conn.server_if, p_data->conn.reason, p_data->conn.conn_id); /*return whether the remote device is currently connected*/ int is_connected = BTA_DmGetConnectionState(p_data->conn.remote_bda); - LOG_ERROR("is_connected=%d\n", is_connected); + BTC_TRACE_ERROR("is_connected=%d\n", is_connected); } break; /*create service callback*/ case ESP_GATTS_CREATE_EVT: { - LOG_ERROR("create service:server_if=%d,service_id=0x%x,service_uuid=0x%x\n", + BTC_TRACE_ERROR("create service:server_if=%d,service_id=0x%x,service_uuid=0x%x\n", p_data->create.server_if, p_data->create.service_id, p_data->create.uuid.uu.uuid16); UINT16 service_uuid = p_data->create.uuid.uu.uuid16; @@ -107,7 +107,7 @@ static void bas_gatts_callback(esp_gatts_evt_t event, tBTA_GATTS *p_data) break; case ESP_GATTS_ADD_CHAR_EVT: { - LOG_ERROR("create characteristic:server_if=%d,service_id=0x%x,char_uuid=0x%x\n", + BTC_TRACE_ERROR("create characteristic:server_if=%d,service_id=0x%x,char_uuid=0x%x\n", p_data->add_result.server_if, p_data->add_result.service_id, p_data->add_result.char_uuid.uu.uuid16); UINT16 char_uuid = p_data->add_result.char_uuid.uu.uuid16; @@ -144,7 +144,7 @@ static void bas_gatts_callback(esp_gatts_evt_t event, tBTA_GATTS *p_data) case ESP_GATTS_ADD_CHAR_DESCR_EVT: { - LOG_ERROR("create descriptor:server_if=%d,service_id=0x%x,attr_id=0x%x,char_uuid=0x%x\n", + BTC_TRACE_ERROR("create descriptor:server_if=%d,service_id=0x%x,attr_id=0x%x,char_uuid=0x%x\n", p_data->add_result.server_if, p_data->add_result.service_id, p_data->add_result.attr_id, p_data->add_result.char_uuid.uu.uuid16); bas_AddCharDescr(p_data->add_result.service_id, p_data->add_result.attr_id); @@ -152,7 +152,7 @@ static void bas_gatts_callback(esp_gatts_evt_t event, tBTA_GATTS *p_data) break; case ESP_GATTS_START_EVT: { - LOG_ERROR("start service:server_if=%d,service_id=0x%x\n", p_data->srvc_oper.server_if, + BTC_TRACE_ERROR("start service:server_if=%d,service_id=0x%x\n", p_data->srvc_oper.server_if, p_data->srvc_oper.service_id); bas_service_cmpl(p_data->srvc_oper.service_id, p_data->srvc_oper.status); @@ -168,7 +168,7 @@ static void bas_gatts_callback(esp_gatts_evt_t event, tBTA_GATTS *p_data) UINT16 conn_id = p_data->req_data.conn_id; UINT16 handle = p_data->req_data.p_data->read_req.handle; bool is_long = p_data->req_data.p_data->read_req.is_long; - LOG_ERROR("read request:event=0x%x,handle=0x%x,trans_id=0x%x,conn_id=0x%x\n", + BTC_TRACE_ERROR("read request:event=0x%x,handle=0x%x,trans_id=0x%x,conn_id=0x%x\n", event, handle, trans_id, conn_id); if (dis_valid_handle_range(handle)) { @@ -188,7 +188,7 @@ static void bas_gatts_callback(esp_gatts_evt_t event, tBTA_GATTS *p_data) UINT32 trans_id = p_data->req_data.trans_id; UINT16 conn_id = p_data->req_data.conn_id; UINT16 handle = p_data->req_data.p_data->write_req.handle; - LOG_ERROR("write request:event=0x%x,handle=0x%x,trans_id=0x%x,conn_id=0x%x\n", + BTC_TRACE_ERROR("write request:event=0x%x,handle=0x%x,trans_id=0x%x,conn_id=0x%x\n", event, handle, trans_id, conn_id); bas_s_write_attr_value(p_data->req_data.p_data, trans_id, conn_id, p_data->req_data.remote_bda); @@ -199,7 +199,7 @@ static void bas_gatts_callback(esp_gatts_evt_t event, tBTA_GATTS *p_data) UINT32 trans_id = p_data->req_data.trans_id; UINT16 conn_id = p_data->req_data.conn_id; UINT8 exec_write = p_data->req_data.p_data->exec_write; - LOG_ERROR("execute write request:event=0x%x,exce_write=0x%x,trans_id=0x%x,conn_id=0x%x\n", + BTC_TRACE_ERROR("execute write request:event=0x%x,exce_write=0x%x,trans_id=0x%x,conn_id=0x%x\n", event, exec_write, trans_id, conn_id); } break; @@ -208,7 +208,7 @@ static void bas_gatts_callback(esp_gatts_evt_t event, tBTA_GATTS *p_data) UINT32 trans_id = p_data->req_data.trans_id; UINT16 conn_id = p_data->req_data.conn_id; UINT16 mtu = p_data->req_data.p_data->mtu; - LOG_ERROR("exchange mtu request:event=0x%x,mtu=0x%x,trans_id=0x%x,conn_id=0x%x\n", + BTC_TRACE_ERROR("exchange mtu request:event=0x%x,mtu=0x%x,trans_id=0x%x,conn_id=0x%x\n", event, mtu, trans_id, conn_id); } break; @@ -217,13 +217,13 @@ static void bas_gatts_callback(esp_gatts_evt_t event, tBTA_GATTS *p_data) UINT32 trans_id = p_data->req_data.trans_id; UINT16 conn_id = p_data->req_data.conn_id; - LOG_ERROR("configue request:trans_id=0x%x,conn_id=0x%x\n", + BTC_TRACE_ERROR("configue request:trans_id=0x%x,conn_id=0x%x\n", trans_id, conn_id); } break; default: - LOG_ERROR("unsettled event: %d\n", event); + BTC_TRACE_ERROR("unsettled event: %d\n", event); break; } @@ -240,32 +240,32 @@ static void bas_callback(UINT32 trans_id, UINT16 conn_id, UINT8 app_id, tGATT_STATUS st = ESP_GATT_OK; switch (event) { case BA_READ_LEVEL_REQ : { - LOG_ERROR("read battery level\n"); + BTC_TRACE_ERROR("read battery level\n"); p_rsp.ba_level = 60; //battery level Battery_Rsp(trans_id, conn_id, app_id, st, event, &p_rsp); } break; case BA_READ_PRE_FMT_REQ : { - LOG_ERROR("read presentation format\n"); + BTC_TRACE_ERROR("read presentation format\n"); } break; case BA_READ_CLT_CFG_REQ : { - LOG_ERROR("read client characteristic configuration request\n"); + BTC_TRACE_ERROR("read client characteristic configuration request\n"); p_rsp.clt_cfg = 0x0001; //notification Battery_Rsp(trans_id, conn_id, app_id, st, event, &p_rsp); } break; case BA_READ_RPT_REF_REQ : { - LOG_ERROR("read report reference descriptor\n"); + BTC_TRACE_ERROR("read report reference descriptor\n"); } break; /*battery level notify*/ case BA_WRITE_CLT_CFG_REQ : { - LOG_ERROR("write client characteristic configuration request\n"); + BTC_TRACE_ERROR("write client characteristic configuration request\n"); Battery_Rsp(trans_id, conn_id, app_id, st, event, NULL); int battery_level = 50; @@ -398,8 +398,8 @@ void bas_init(tBTA_GATTS_IF gatt_if, UINT16 app_id) p_inst = &battery_cb.battery_inst[battery_cb.inst_id]; - LOG_ERROR("create battery service\n"); - LOG_ERROR("inst_id=%d\n", battery_cb.inst_id); + BTC_TRACE_ERROR("create battery service\n"); + BTC_TRACE_ERROR("inst_id=%d\n", battery_cb.inst_id); esp_ble_gatts_create_srvc (gatt_if, &bas_uuid, battery_cb.inst_id , BA_MAX_ATTR_NUM, ba_reg_info.is_pri); diff --git a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c index e0654e6f5e..fd88148155 100644 --- a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c +++ b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c @@ -211,7 +211,7 @@ static void btc_to_bta_adv_data(esp_ble_adv_data_t *p_adv_data, tBTA_BLE_ADV_DAT } if (NULL != bta_adv_data->p_services->p_uuid) { - LOG_DEBUG("%s - In 16-UUID_data", __FUNCTION__); + BTC_TRACE_DEBUG("%s - In 16-UUID_data", __FUNCTION__); mask |= BTM_BLE_AD_BIT_SERVICE; ++bta_adv_data->p_services->num_service; *p_uuid_out16++ = bt_uuid.uu.uuid16; @@ -231,7 +231,7 @@ static void btc_to_bta_adv_data(esp_ble_adv_data_t *p_adv_data, tBTA_BLE_ADV_DAT } if (NULL != bta_adv_data->p_service_32b->p_uuid) { - LOG_DEBUG("%s - In 32-UUID_data", __FUNCTION__); + BTC_TRACE_DEBUG("%s - In 32-UUID_data", __FUNCTION__); mask |= BTM_BLE_AD_BIT_SERVICE_32; ++bta_adv_data->p_service_32b->num_service; *p_uuid_out32++ = bt_uuid.uu.uuid32; @@ -245,11 +245,11 @@ static void btc_to_bta_adv_data(esp_ble_adv_data_t *p_adv_data, tBTA_BLE_ADV_DAT bta_adv_data->p_services_128b = osi_malloc(sizeof(tBTA_BLE_128SERVICE)); if (NULL != bta_adv_data->p_services_128b) { - LOG_DEBUG("%s - In 128-UUID_data", __FUNCTION__); + BTC_TRACE_DEBUG("%s - In 128-UUID_data", __FUNCTION__); mask |= BTM_BLE_AD_BIT_SERVICE_128; memcpy(bta_adv_data->p_services_128b->uuid128, bt_uuid.uu.uuid128, LEN_UUID_128); - LOG_DEBUG("%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x", bt_uuid.uu.uuid128[0], + BTC_TRACE_DEBUG("%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x", bt_uuid.uu.uuid128[0], bt_uuid.uu.uuid128[1], bt_uuid.uu.uuid128[2], bt_uuid.uu.uuid128[3], bt_uuid.uu.uuid128[4], bt_uuid.uu.uuid128[5], bt_uuid.uu.uuid128[6], bt_uuid.uu.uuid128[7], bt_uuid.uu.uuid128[8], bt_uuid.uu.uuid128[9], @@ -285,7 +285,7 @@ static void btc_adv_data_callback(tBTA_STATUS status) sizeof(esp_ble_gap_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } @@ -304,7 +304,7 @@ static void btc_scan_rsp_data_callback(tBTA_STATUS status) sizeof(esp_ble_gap_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } @@ -323,7 +323,7 @@ static void btc_adv_data_raw_callback(tBTA_STATUS status) sizeof(esp_ble_gap_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } @@ -342,7 +342,7 @@ static void btc_scan_rsp_data_raw_callback(tBTA_STATUS status) sizeof(esp_ble_gap_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } @@ -387,7 +387,7 @@ static void btc_start_adv_callback(uint8_t status) sizeof(esp_ble_gap_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } @@ -406,7 +406,7 @@ static void btc_stop_adv_callback(uint8_t status) sizeof(esp_ble_gap_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } @@ -417,24 +417,24 @@ static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params, tBT if (!BLE_ISVALID_PARAM(ble_adv_params->adv_int_min, BTM_BLE_ADV_INT_MIN, BTM_BLE_ADV_INT_MAX) || !BLE_ISVALID_PARAM(ble_adv_params->adv_int_max, BTM_BLE_ADV_INT_MIN, BTM_BLE_ADV_INT_MAX)) { status = ESP_BT_STATUS_PARM_INVALID; - LOG_ERROR("Invalid advertisting interval parameters.\n"); + BTC_TRACE_ERROR("Invalid advertisting interval parameters.\n"); } if ((ble_adv_params->adv_type < ADV_TYPE_IND) || (ble_adv_params->adv_type > ADV_TYPE_DIRECT_IND_LOW) ) { status = ESP_BT_STATUS_PARM_INVALID; - LOG_ERROR("Invalid advertisting type parameters.\n"); + BTC_TRACE_ERROR("Invalid advertisting type parameters.\n"); } if ((ble_adv_params->adv_filter_policy < ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY) || (ble_adv_params->adv_filter_policy > ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST) ) { status = ESP_BT_STATUS_PARM_INVALID; - LOG_ERROR("Invalid advertisting type parameters.\n"); + BTC_TRACE_ERROR("Invalid advertisting type parameters.\n"); } if((ble_adv_params->channel_map | ADV_CHNL_ALL) != ADV_CHNL_ALL || ble_adv_params->channel_map == 0) { status = ESP_BT_STATUS_PARM_INVALID; - LOG_ERROR("Invalid advertisting channel map parameters.\n"); + BTC_TRACE_ERROR("Invalid advertisting channel map parameters.\n"); } if(status != ESP_BT_STATUS_SUCCESS) { if(start_adv_cback) { @@ -443,7 +443,7 @@ static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params, tBT return; } - LOG_DEBUG("API_Ble_AppStartAdvertising\n"); + BTC_TRACE_DEBUG("API_Ble_AppStartAdvertising\n"); memcpy(peer_addr.bda, ble_adv_params->peer_addr, ESP_BD_ADDR_LEN); peer_addr.type = ble_adv_params->peer_addr_type; @@ -473,7 +473,7 @@ static void btc_scan_params_callback(tGATT_IF gatt_if, tBTM_STATUS status) sizeof(esp_ble_gap_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } @@ -522,26 +522,26 @@ static void btc_search_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data } case BTA_DM_INQ_CMPL_EVT: { param.scan_rst.num_resps = p_data->inq_cmpl.num_resps; - LOG_DEBUG("%s BLE observe complete. Num Resp %d\n", __FUNCTION__, p_data->inq_cmpl.num_resps); + BTC_TRACE_DEBUG("%s BLE observe complete. Num Resp %d\n", __FUNCTION__, p_data->inq_cmpl.num_resps); break; } case BTA_DM_DISC_RES_EVT: - LOG_DEBUG("BTA_DM_DISC_RES_EVT\n"); + BTC_TRACE_DEBUG("BTA_DM_DISC_RES_EVT\n"); break; case BTA_DM_DISC_BLE_RES_EVT: - LOG_DEBUG("BTA_DM_DISC_BLE_RES_EVT\n"); + BTC_TRACE_DEBUG("BTA_DM_DISC_BLE_RES_EVT\n"); break; case BTA_DM_DISC_CMPL_EVT: - LOG_DEBUG("BTA_DM_DISC_CMPL_EVT\n"); + BTC_TRACE_DEBUG("BTA_DM_DISC_CMPL_EVT\n"); break; case BTA_DM_DI_DISC_CMPL_EVT: - LOG_DEBUG("BTA_DM_DI_DISC_CMPL_EVT\n"); + BTC_TRACE_DEBUG("BTA_DM_DI_DISC_CMPL_EVT\n"); break; case BTA_DM_SEARCH_CANCEL_CMPL_EVT: - LOG_DEBUG("BTA_DM_SEARCH_CANCEL_CMPL_EVT\n"); + BTC_TRACE_DEBUG("BTA_DM_SEARCH_CANCEL_CMPL_EVT\n"); break; default: - LOG_ERROR("%s : Unknown event 0x%x\n", __FUNCTION__, event); + BTC_TRACE_ERROR("%s : Unknown event 0x%x\n", __FUNCTION__, event); return; } btc_transfer_context(&msg, ¶m, sizeof(esp_ble_gap_cb_param_t), NULL); @@ -562,7 +562,7 @@ static void btc_start_scan_callback(uint8_t status) sizeof(esp_ble_gap_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } @@ -581,7 +581,7 @@ static void btc_stop_scan_callback(tBTA_STATUS status) sizeof(esp_ble_gap_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } @@ -604,7 +604,7 @@ void btc_update_conn_param_callback (UINT8 status, BD_ADDR bd_addr, tBTM_LE_UPDA sizeof(esp_ble_gap_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } @@ -623,7 +623,7 @@ static void btc_set_pkt_length_callback(UINT8 status, tBTM_LE_SET_PKT_DATA_LENGT sizeof(esp_ble_gap_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } @@ -641,7 +641,7 @@ static void btc_add_whitelist_complete_callback(UINT8 status, tBTM_WL_OPERATION sizeof(esp_ble_gap_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } @@ -658,7 +658,7 @@ static void btc_set_rand_addr_callback(UINT8 status) sizeof(esp_ble_gap_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } @@ -676,7 +676,7 @@ static void btc_set_local_privacy_callback(UINT8 status) sizeof(esp_ble_gap_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } @@ -686,7 +686,7 @@ static void btc_set_encryption_callback(BD_ADDR bd_addr, tBTA_TRANSPORT transpor { UNUSED(bd_addr); UNUSED(transport); - LOG_DEBUG("enc_status = %x\n", enc_status); + BTC_TRACE_DEBUG("enc_status = %x\n", enc_status); return; } #endif ///SMP_INCLUDED == TRUE @@ -708,7 +708,7 @@ static void btc_read_ble_rssi_cmpl_callback(void *p_data) sizeof(esp_ble_gap_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } @@ -726,7 +726,7 @@ static void btc_ble_start_scanning(uint32_t duration, //Start scan the device BTA_DmBleScan(true, duration, results_cb, start_scan_cb); } else { - LOG_ERROR("The start_scan_cb or results_cb invalid\n"); + BTC_TRACE_ERROR("The start_scan_cb or results_cb invalid\n"); } } @@ -752,7 +752,7 @@ static void btc_ble_update_conn_params(BD_ADDR bd_addr, uint16_t min_int, } if (min_int < BTM_BLE_CONN_INT_MIN || max_int > BTM_BLE_CONN_INT_MAX) { - LOG_ERROR("Invalid interval value.\n"); + BTC_TRACE_ERROR("Invalid interval value.\n"); } BTA_DmBleUpdateConnectionParams(bd_addr, min_int, max_int, @@ -794,11 +794,11 @@ static void btc_ble_set_rand_addr (BD_ADDR rand_addr, tBTA_SET_RAND_ADDR_CBACK * BTA_DmSetRandAddress(rand_addr, btc_set_rand_addr_callback); } else { btc_set_rand_addr_callback(BTM_INVALID_STATIC_RAND_ADDR); - LOG_ERROR("Invalid random address, the high bit should be 0b11, all bits of the random part shall not be to 1 or 0"); + BTC_TRACE_ERROR("Invalid random address, the high bit should be 0b11, all bits of the random part shall not be to 1 or 0"); } } else { btc_set_rand_addr_callback(BTM_INVALID_STATIC_RAND_ADDR); - LOG_ERROR("Invalid random addressm, the address value is NULL"); + BTC_TRACE_ERROR("Invalid random addressm, the address value is NULL"); } } @@ -819,7 +819,7 @@ void btc_gap_ble_cb_handler(btc_msg_t *msg) if (msg->act < ESP_GAP_BLE_EVT_MAX) { btc_gap_ble_cb_to_app(msg->act, param); } else { - LOG_ERROR("%s, unknow msg->act = %d", __func__, msg->act); + BTC_TRACE_ERROR("%s, unknow msg->act = %d", __func__, msg->act); } btc_gap_ble_cb_deep_free(msg); @@ -884,13 +884,13 @@ void btc_gap_ble_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) if (dst->set_security_param.value != NULL) { memcpy(dst->set_security_param.value, src->set_security_param.value, length); } else { - LOG_ERROR("%s %d no mem\n",__func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act); } } break; } default: - LOG_ERROR("Unhandled deep copy %d\n", msg->act); + BTC_TRACE_ERROR("Unhandled deep copy %d\n", msg->act); break; } } @@ -899,14 +899,14 @@ void btc_gap_ble_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) { switch (msg->act) { default: - LOG_ERROR("%s, Unhandled deep copy %d\n", __func__, msg->act); + BTC_TRACE_ERROR("%s, Unhandled deep copy %d\n", __func__, msg->act); break; } } void btc_gap_ble_arg_deep_free(btc_msg_t *msg) { - LOG_DEBUG("%s \n", __func__); + BTC_TRACE_DEBUG("%s \n", __func__); switch (msg->act) { case BTC_GAP_BLE_ACT_CFG_ADV_DATA: { esp_ble_adv_data_t *adv = &((btc_ble_gap_args_t *)msg->arg)->cfg_adv_data.adv_data; @@ -938,17 +938,17 @@ void btc_gap_ble_arg_deep_free(btc_msg_t *msg) break; } default: - LOG_DEBUG("Unhandled deep free %d\n", msg->act); + BTC_TRACE_DEBUG("Unhandled deep free %d\n", msg->act); break; } } void btc_gap_ble_cb_deep_free(btc_msg_t *msg) { - LOG_DEBUG("%s", __func__); + BTC_TRACE_DEBUG("%s", __func__); switch (msg->act) { default: - LOG_DEBUG("Unhandled deep free %d", msg->act); + BTC_TRACE_DEBUG("Unhandled deep free %d", msg->act); break; } } @@ -957,7 +957,7 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) { btc_ble_gap_args_t *arg = (btc_ble_gap_args_t *)msg->arg; - LOG_DEBUG("%s act %d\n", __FUNCTION__, msg->act); + BTC_TRACE_DEBUG("%s act %d\n", __FUNCTION__, msg->act); switch (msg->act) { case BTC_GAP_BLE_ACT_CFG_ADV_DATA: { diff --git a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c index c612009c18..6c2a6d5f14 100644 --- a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c +++ b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c @@ -69,7 +69,7 @@ static void btc_bt_set_scan_mode(esp_bt_scan_mode_t mode) break; default: - LOG_WARN("invalid scan mode (0x%x)", mode); + BTC_TRACE_WARNING("invalid scan mode (0x%x)", mode); return; } @@ -318,7 +318,7 @@ static void btc_gap_bt_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEAR uint32_t cod = devclass2uint (p_data->inq_res.dev_class); if (cod == 0) { - LOG_DEBUG("%s cod is 0, set as unclassified", __func__); + BTC_TRACE_DEBUG("%s cod is 0, set as unclassified", __func__); cod = COD_UNCLASSIFIED; } @@ -577,7 +577,7 @@ static void btc_gap_bt_set_cod(btc_gap_bt_args_t *arg) p_cod.service = cod->service << 5; bool ret = utl_set_device_class(&p_cod, arg->set_cod.mode); if (!ret){ - LOG_ERROR("%s set class of device failed!",__func__); + BTC_TRACE_ERROR("%s set class of device failed!",__func__); } } @@ -586,7 +586,7 @@ esp_err_t btc_gap_bt_get_cod(esp_bt_cod_t *cod) tBTA_UTL_COD p_cod; bool ret = utl_get_device_class(&p_cod); if (!ret){ - LOG_ERROR("%s get class of device failed!",__func__); + BTC_TRACE_ERROR("%s get class of device failed!",__func__); return ESP_BT_STATUS_FAIL; } cod->minor = p_cod.minor >> 2; @@ -635,7 +635,7 @@ esp_err_t btc_gap_bt_remove_bond_device(btc_gap_bt_args_t *arg) void btc_gap_bt_call_handler(btc_msg_t *msg) { btc_gap_bt_args_t *arg = (btc_gap_bt_args_t *)msg->arg; - LOG_DEBUG("%s act %d\n", __func__, msg->act); + BTC_TRACE_DEBUG("%s act %d\n", __func__, msg->act); switch (msg->act) { case BTC_GAP_BT_ACT_SET_SCAN_MODE: { btc_bt_set_scan_mode(arg->set_scan_mode.mode); diff --git a/components/bt/bluedroid/btc/profile/std/gatt/btc_gatt_common.c b/components/bt/bluedroid/btc/profile/std/gatt/btc_gatt_common.c index c78ddedbf4..e688f77753 100644 --- a/components/bt/bluedroid/btc/profile/std/gatt/btc_gatt_common.c +++ b/components/bt/bluedroid/btc/profile/std/gatt/btc_gatt_common.c @@ -31,7 +31,7 @@ static void btc_set_local_mtu(uint16_t mtu) void btc_gatt_com_call_handler(btc_msg_t *msg) { - LOG_DEBUG("%s act %d\n", __func__, msg->act); + BTC_TRACE_DEBUG("%s act %d\n", __func__, msg->act); switch (msg->act) { case BTC_GATT_ACT_SET_LOCAL_MTU: { @@ -40,7 +40,7 @@ void btc_gatt_com_call_handler(btc_msg_t *msg) break; } default: - LOG_ERROR("%s UNKNOWN ACT %d\n", __func__, msg->act); + BTC_TRACE_ERROR("%s UNKNOWN ACT %d\n", __func__, msg->act); break; } } diff --git a/components/bt/bluedroid/btc/profile/std/gatt/btc_gatt_util.c b/components/bt/bluedroid/btc/profile/std/gatt/btc_gatt_util.c index 8cb0080ee1..8653f60561 100644 --- a/components/bt/bluedroid/btc/profile/std/gatt/btc_gatt_util.c +++ b/components/bt/bluedroid/btc/profile/std/gatt/btc_gatt_util.c @@ -82,7 +82,7 @@ void btc128_to_bta_uuid(tBT_UUID *p_dest, uint8_t *p_src) break; default: - LOG_ERROR("%s: Unknown UUID length %d!", __FUNCTION__, p_dest->len); + BTC_TRACE_ERROR("%s: Unknown UUID length %d!", __FUNCTION__, p_dest->len); break; } } @@ -103,7 +103,7 @@ void btc_to_bta_uuid(tBT_UUID *p_dest, esp_bt_uuid_t *p_src) } else if (p_src->len == 0) { /* do nothing for now, there's some scenario will input 0 */ } else { - LOG_ERROR("%s UUID len is invalid %d\n", __func__, p_src->len); + BTC_TRACE_ERROR("%s UUID len is invalid %d\n", __func__, p_src->len); } } @@ -136,7 +136,7 @@ void bta_to_btc_uuid(esp_bt_uuid_t *p_dest, tBT_UUID *p_src) /* do nothing for now, there's some scenario will input 0 such as, receive notify, the descriptor may be 0 */ } else { - LOG_ERROR("%s UUID len is invalid %d\n", __func__, p_src->len); + BTC_TRACE_ERROR("%s UUID len is invalid %d\n", __func__, p_src->len); } } @@ -187,7 +187,7 @@ uint16_t set_read_value(uint8_t *gattc_if, esp_ble_gattc_cb_param_t *p_dest, tBT if (( p_src->status == BTA_GATT_OK ) && (p_src->p_value != NULL)) { - LOG_DEBUG("%s len = %d ", __func__, p_src->p_value->len); + BTC_TRACE_DEBUG("%s len = %d ", __func__, p_src->p_value->len); p_dest->read.value_len = p_src->p_value->len; if ( p_src->p_value->len > 0 && p_src->p_value->p_value != NULL ) { p_dest->read.value = p_src->p_value->p_value; diff --git a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c index ea86459fc3..0694b990f0 100644 --- a/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c +++ b/components/bt/bluedroid/btc/profile/std/gatt/btc_gattc.c @@ -43,7 +43,7 @@ void btc_gattc_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) if (dst->write_char.value) { memcpy(dst->write_char.value, src->write_char.value, src->write_char.value_len); } else { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } break; } @@ -52,7 +52,7 @@ void btc_gattc_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) if (dst->write_descr.value) { memcpy(dst->write_descr.value, src->write_descr.value, src->write_descr.value_len); } else { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } break; } @@ -61,7 +61,7 @@ void btc_gattc_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) if (dst->prep_write.value) { memcpy(dst->prep_write.value, src->prep_write.value, src->prep_write.value_len); } else { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } break; } @@ -70,12 +70,12 @@ void btc_gattc_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) if (dst->prep_write_descr.value) { memcpy(dst->prep_write_descr.value, src->prep_write_descr.value, src->prep_write_descr.value_len); } else { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } break; } default: - LOG_DEBUG("%s Unhandled deep copy %d\n", __func__, msg->act); + BTC_TRACE_DEBUG("%s Unhandled deep copy %d\n", __func__, msg->act); break; } } @@ -110,7 +110,7 @@ void btc_gattc_arg_deep_free(btc_msg_t *msg) break; } default: - LOG_DEBUG("%s Unhandled deep free %d\n", __func__, msg->act); + BTC_TRACE_DEBUG("%s Unhandled deep free %d\n", __func__, msg->act); break; } @@ -137,7 +137,7 @@ static void btc_gattc_copy_req_data(btc_msg_t *msg, void *p_dest, void *p_src) p_dest_data->read.p_value->len = p_src_data->read.p_value->len; memcpy(p_dest_data->read.p_value->p_value, p_src_data->read.p_value->p_value, p_src_data->read.p_value->len); } else { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } } break; @@ -149,7 +149,7 @@ static void btc_gattc_copy_req_data(btc_msg_t *msg, void *p_dest, void *p_src) if (p_dest_data->get_addr_list.bda_list) { memcpy(p_dest_data->get_addr_list.bda_list, p_src_data->get_addr_list.bda_list, sizeof(BD_ADDR) * num_addr); } else { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } } break; @@ -194,7 +194,7 @@ static void btc_gattc_cback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data) ret = btc_transfer_context(&msg, p_data, sizeof(tBTA_GATTC), btc_gattc_copy_req_data); if (ret) { - LOG_ERROR("%s transfer failed\n", __func__); + BTC_TRACE_ERROR("%s transfer failed\n", __func__); } } @@ -292,7 +292,7 @@ static void btc_gattc_fill_gatt_db_conversion(uint16_t count, uint16_t num, esp_ break; } default: - LOG_WARN("%s(), Not support type(%d)", __func__, type); + BTC_TRACE_WARNING("%s(), Not support type(%d)", __func__, type); break; } } @@ -750,7 +750,7 @@ void btc_gattc_call_handler(btc_msg_t *msg) BTA_GATTC_CacheGetAddrList(arg->get_addr_list.gattc_if); break; default: - LOG_ERROR("%s: Unhandled event (%d)!\n", __FUNCTION__, msg->act); + BTC_TRACE_ERROR("%s: Unhandled event (%d)!\n", __FUNCTION__, msg->act); break; } @@ -972,7 +972,7 @@ void btc_gattc_cb_handler(btc_msg_t *msg) break; } default: - LOG_DEBUG("%s: Unhandled event (%d)!", __FUNCTION__, msg->act); + BTC_TRACE_DEBUG("%s: Unhandled event (%d)!", __FUNCTION__, msg->act); break; } diff --git a/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c b/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c index a265057d5b..74ae46a6ed 100644 --- a/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c +++ b/components/bt/bluedroid/btc/profile/std/gatt/btc_gatts.c @@ -68,7 +68,7 @@ static inline void btc_gatts_uuid_format_convert(esp_bt_uuid_t* dest_uuid, uint1 memcpy(dest_uuid->uuid.uuid128, src_uuid_p, src_uuid_len); } else{ - LOG_ERROR("%s wrong uuid length %d\n", __func__, src_uuid_len); + BTC_TRACE_ERROR("%s wrong uuid length %d\n", __func__, src_uuid_len); } } @@ -85,7 +85,7 @@ void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) if (dst->send_ind.value) { memcpy(dst->send_ind.value, src->send_ind.value, src->send_ind.value_len); } else { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } break; } @@ -95,7 +95,7 @@ void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) if (dst->send_rsp.rsp) { memcpy(dst->send_rsp.rsp, src->send_rsp.rsp, sizeof(esp_gatt_rsp_t)); } else { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } } break; @@ -108,7 +108,7 @@ void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) memcpy(dst->add_char.char_val.attr_value, src->add_char.char_val.attr_value, src->add_char.char_val.attr_len); }else{ - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } } break; @@ -120,7 +120,7 @@ void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) memcpy(dst->add_descr.descr_val.attr_value, src->add_descr.descr_val.attr_value, src->add_descr.descr_val.attr_len); }else{ - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } } break; @@ -133,7 +133,7 @@ void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) memcpy(dst->create_attr_tab.gatts_attr_db, src->create_attr_tab.gatts_attr_db, sizeof(esp_gatts_attr_db_t)*num_attr); }else{ - LOG_ERROR("%s %d no mem\n",__func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act); } } break; @@ -145,13 +145,13 @@ void btc_gatts_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) if(dst->set_attr_val.value != NULL){ memcpy(dst->set_attr_val.value, src->set_attr_val.value, len); }else{ - LOG_ERROR("%s %d no mem\n",__func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n",__func__, msg->act); } } break; } default: - LOG_DEBUG("%s Unhandled deep copy %d\n", __func__, msg->act); + BTC_TRACE_DEBUG("%s Unhandled deep copy %d\n", __func__, msg->act); break; } @@ -200,7 +200,7 @@ void btc_gatts_arg_deep_free(btc_msg_t *msg) break; default: - LOG_DEBUG("%s Unhandled deep free %d\n", __func__, msg->act); + BTC_TRACE_DEBUG("%s Unhandled deep free %d\n", __func__, msg->act); break; } @@ -244,7 +244,7 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db, } future_p = future_new(); if (future_p == NULL) { - LOG_ERROR("%s failed:no mem\n", __func__); + BTC_TRACE_ERROR("%s failed:no mem\n", __func__); return ; } btc_creat_tab_env.complete_future = future_p; @@ -265,7 +265,7 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db, srvc_inst_id, max_nb_attr, true); btc_creat_tab_env.is_use_svc = true; } else { - LOG_ERROR("Each service table can only created one primary service."); + BTC_TRACE_ERROR("Each service table can only created one primary service."); param.add_attr_tab.status = ESP_GATT_ERROR; btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, ¶m); //reset the env after sent the data to app @@ -274,7 +274,7 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db, } if (future_await(future_p) == FUTURE_FAIL) { - LOG_ERROR("%s failed\n", __func__); + BTC_TRACE_ERROR("%s failed\n", __func__); return; } break; @@ -292,7 +292,7 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db, srvc_inst_id, max_nb_attr, false); btc_creat_tab_env.is_use_svc = true; } else { - LOG_ERROR("Each service table can only created one secondary service."); + BTC_TRACE_ERROR("Each service table can only created one secondary service."); param.add_attr_tab.status = ESP_GATT_ERROR; btc_gatts_cb_to_app(ESP_GATTS_CREAT_ATTR_TAB_EVT, gatts_if, ¶m); //reset the env after sent the data to app @@ -300,7 +300,7 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db, return; } if (future_await(future_p) == FUTURE_FAIL) { - LOG_ERROR("%s failed\n", __func__); + BTC_TRACE_ERROR("%s failed\n", __func__); return; } break; @@ -314,7 +314,7 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db, incl_svc_desc->start_hdl); if (future_await(future_p) == FUTURE_FAIL) { - LOG_ERROR("%s failed\n", __func__); + BTC_TRACE_ERROR("%s failed\n", __func__); return; } } @@ -333,7 +333,7 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db, if(btc_creat_tab_env.svc_start_hdl != 0){ svc_hal = btc_creat_tab_env.svc_start_hdl; if((gatts_attr_db[i].att_desc.value) == NULL){ - LOG_ERROR("%s Characteristic declaration should not be NULL\n", __func__); + BTC_TRACE_ERROR("%s Characteristic declaration should not be NULL\n", __func__); } else{ char_property = (uint8_t)(*(uint8_t*)(gatts_attr_db[i].att_desc.value)); @@ -348,7 +348,7 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db, perm, char_property, &attr_val, &control); if (future_await(future_p) == FUTURE_FAIL) { - LOG_ERROR("%s failed\n", __func__); + BTC_TRACE_ERROR("%s failed\n", __func__); return; } } @@ -383,7 +383,7 @@ static void btc_gatts_act_create_attr_tab(esp_gatts_attr_db_t *gatts_attr_db, BTA_GATTS_AddCharDescriptor(svc_hal, perm, &bta_char_uuid, &attr_val, &control); if (future_await(future_p) == FUTURE_FAIL) { - LOG_ERROR("%s failed\n", __func__); + BTC_TRACE_ERROR("%s failed\n", __func__); return; } } @@ -424,18 +424,18 @@ static esp_gatt_status_t btc_gatts_check_valid_attr_tab(esp_gatts_attr_db_t *gat case ESP_GATT_UUID_PRI_SERVICE: case ESP_GATT_UUID_SEC_SERVICE: if (++svc_num > 1) { - LOG_ERROR("Each service table can only created one primary service or secondly service."); + BTC_TRACE_ERROR("Each service table can only created one primary service or secondly service."); return ESP_GATT_ERROR; } break; case ESP_GATT_UUID_INCLUDE_SERVICE: { esp_gatts_incl_svc_desc_t *svc_desc = (esp_gatts_incl_svc_desc_t *)gatts_attr_db[i].att_desc.value; if(svc_desc == NULL) { - LOG_ERROR("%s, The include service attribute should not be NULL.", __func__); + BTC_TRACE_ERROR("%s, The include service attribute should not be NULL.", __func__); return ESP_GATT_INVALID_PDU; } else if((svc_desc->start_hdl == 0) || (svc_desc->end_hdl == 0) || (svc_desc->start_hdl == svc_desc->end_hdl)) { - LOG_ERROR("%s, The include service attribute handle is invalid, start_hanlde = %d, end_handle = %d",\ + BTC_TRACE_ERROR("%s, The include service attribute handle is invalid, start_hanlde = %d, end_handle = %d",\ __func__, svc_desc->start_hdl, svc_desc->end_hdl); return ESP_GATT_INVALID_HANDLE; } @@ -443,14 +443,14 @@ static esp_gatt_status_t btc_gatts_check_valid_attr_tab(esp_gatts_attr_db_t *gat } case ESP_GATT_UUID_CHAR_DECLARE: if((gatts_attr_db[i].att_desc.value) == NULL) { - LOG_ERROR("%s, Characteristic declaration should not be NULL.", __func__); + BTC_TRACE_ERROR("%s, Characteristic declaration should not be NULL.", __func__); return ESP_GATT_INVALID_PDU; } if(gatts_attr_db[i+1].att_desc.uuid_length != ESP_UUID_LEN_16 && gatts_attr_db[i+1].att_desc.uuid_length != ESP_UUID_LEN_32 && gatts_attr_db[i+1].att_desc.uuid_length != ESP_UUID_LEN_128) { - LOG_ERROR("%s, The Charateristic uuid length = %d is invalid", __func__,\ + BTC_TRACE_ERROR("%s, The Charateristic uuid length = %d is invalid", __func__,\ gatts_attr_db[i+1].att_desc.uuid_length); return ESP_GATT_INVALID_ATTR_LEN; } @@ -462,7 +462,7 @@ static esp_gatt_status_t btc_gatts_check_valid_attr_tab(esp_gatts_attr_db_t *gat uuid == ESP_GATT_UUID_CHAR_SRVR_CONFIG || uuid == ESP_GATT_UUID_CHAR_PRESENT_FORMAT || uuid == ESP_GATT_UUID_CHAR_AGG_FORMAT || uuid == ESP_GATT_UUID_CHAR_VALID_RANGE || uuid == ESP_GATT_UUID_EXT_RPT_REF_DESCR || uuid == ESP_GATT_UUID_RPT_REF_DESCR) { - LOG_ERROR("%s, The charateristic value uuid = %d is invalid", __func__, uuid); + BTC_TRACE_ERROR("%s, The charateristic value uuid = %d is invalid", __func__, uuid); return ESP_GATT_INVALID_PDU; } } @@ -584,7 +584,7 @@ static void btc_gatts_inter_cb(tBTA_GATTS_EVT event, tBTA_GATTS *p_data) sizeof(tBTA_GATTS), btc_gatts_cb_param_copy_req); if (status != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } diff --git a/components/bt/bluedroid/btc/profile/std/hid_le/hid_le_prf.c b/components/bt/bluedroid/btc/profile/std/hid_le/hid_le_prf.c index 06a882a739..6f54bd4caf 100644 --- a/components/bt/bluedroid/btc/profile/std/hid_le/hid_le_prf.c +++ b/components/bt/bluedroid/btc/profile/std/hid_le/hid_le_prf.c @@ -265,12 +265,12 @@ static void hidd_add_characterisitc(const char_desc_t *char_desc) { uint16_t service_id; if (char_desc == NULL) { - LOG_ERROR("Invalid hid characteristic\n"); + BTC_TRACE_ERROR("Invalid hid characteristic\n"); return; } //check the hid device serivce has been register to the data base or not if (!hidd_le_env.enabled) { - LOG_ERROR("The hid device didn't register yet\n"); + BTC_TRACE_ERROR("The hid device didn't register yet\n"); return; } //get the service id from the env whitch has been register @@ -306,7 +306,7 @@ static void hidd_le_profile_cb(esp_gatts_evt_t event, esp_gatts_t *p_data) case ESP_GATTS_REG_EVT: //check the register of the hid device profile has been succeess or not if (p_data->reg_oper.status != ESP_GATT_OK) { - LOG_ERROR("hidd profile register failed\n"); + BTC_TRACE_ERROR("hidd profile register failed\n"); } hidd_le_env.hidd_inst.app_id = app_id; //save the gatt interface in the hid device ENV @@ -337,9 +337,9 @@ static void hidd_le_profile_cb(esp_gatts_evt_t event, esp_gatts_t *p_data) case ESP_GATTS_ADD_CHAR_EVT: //save the charateristic handle to the env hidd_le_env.hidd_inst.att_tbl[hid_char_idx - 1] = p_data->add_result.attr_id; - LOG_ERROR("hanlder = %x, p_data->add_result.char_uuid.uu.uuid16 = %x\n", p_data->add_result.attr_id, + BTC_TRACE_ERROR("hanlder = %x, p_data->add_result.char_uuid.uu.uuid16 = %x\n", p_data->add_result.attr_id, p_data->add_result.char_uuid.uu.uuid16); - LOG_ERROR("hid_char_idx=%x\n", hid_char_idx); + BTC_TRACE_ERROR("hid_char_idx=%x\n", hid_char_idx); if (hid_char_idx <= HIDD_LE_CHAR_MAX) { //added the characteristic until the index overflow if ((p_data->add_result.char_uuid.uu.uuid16 == CHAR_BOOT_KB_IN_REPORT_UUID) || @@ -347,7 +347,7 @@ static void hidd_le_profile_cb(esp_gatts_evt_t event, esp_gatts_t *p_data) // add the gattc config descriptor to the notify charateristic //tBTA_GATT_PERM perm = (GATT_PERM_WRITE|GATT_PERM_WRITE); uuid.uu.uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG; - LOG_ERROR("p_data->add_result.char_uuid.uu.uuid16 = %x\n", + BTC_TRACE_ERROR("p_data->add_result.char_uuid.uu.uuid16 = %x\n", p_data->add_result.char_uuid.uu.uuid16); esp_ble_gatts_add_char_descr (hidd_le_env.hidd_clcb.cur_srvc_id, GATT_PERM_WRITE, @@ -366,7 +366,7 @@ static void hidd_le_profile_cb(esp_gatts_evt_t event, esp_gatts_t *p_data) BTA_GATTS_AddCharDescriptor (hidd_le_env.hidd_clcb.cur_srvc_id, GATT_PERM_READ, &uuid); - LOG_ERROR("p_data->add_result.char_uuid.uu.uuid16 = %x\n", + BTC_TRACE_ERROR("p_data->add_result.char_uuid.uu.uuid16 = %x\n", p_data->add_result.char_uuid.uu.uuid16); } if (p_data->add_result.char_uuid.uu.uuid16 == GATT_UUID_RPT_REF_DESCR) { @@ -377,12 +377,12 @@ static void hidd_le_profile_cb(esp_gatts_evt_t event, esp_gatts_t *p_data) } break; case ESP_GATTS_READ_EVT: { - LOG_ERROR("Hidd profile BTA_GATTS_READ_EVT\n"); + BTC_TRACE_ERROR("Hidd profile BTA_GATTS_READ_EVT\n"); UINT32 trans_id = p_data->req_data.trans_id; UINT16 conn_id = p_data->req_data.conn_id; UINT16 handle = p_data->req_data.p_data->read_req.handle; bool is_long = p_data->req_data.p_data->read_req.is_long; - LOG_ERROR("read request:event=0x%x,handle=0x%x,trans_id=0x%x,conn_id=0x%x\n", + BTC_TRACE_ERROR("read request:event=0x%x,handle=0x%x,trans_id=0x%x,conn_id=0x%x\n", event, handle, trans_id, conn_id); hidd_read_attr_value(p_data->req_data.p_data, trans_id); @@ -398,7 +398,7 @@ static void hidd_le_profile_cb(esp_gatts_evt_t event, esp_gatts_t *p_data) if (!p_clcb->in_use) { p_clcb->in_use = TRUE; p_clcb->conn_id = p_data->conn.conn_id;; - LOG_ERROR("hidd->conn_id = %x\n", p_data->conn.conn_id); + BTC_TRACE_ERROR("hidd->conn_id = %x\n", p_data->conn.conn_id); p_clcb->connected = TRUE; memcpy(p_clcb->remote_bda, p_data->conn.remote_bda, BD_ADDR_LEN); } @@ -510,7 +510,7 @@ void hidd_rsp (uint32_t trans_id, uint16_t conn_id, uint8_t app_id, hidd_inst_t *p_inst = &hidd_le_env.hidd_inst; tGATTS_RSP rsp; uint8_t *pp; - LOG_ERROR("conn_id = %x, trans_id = %x, event = %x\n", + BTC_TRACE_ERROR("conn_id = %x, trans_id = %x, event = %x\n", conn_id, trans_id, event); if (p_inst->app_id == app_id) { @@ -522,7 +522,7 @@ void hidd_rsp (uint32_t trans_id, uint16_t conn_id, uint8_t app_id, if (p_inst->pending_evt == event) { switch (event) { case HIDD_LE_READ_INFO_EVT: - LOG_ERROR(" p_inst->att_tbl[HIDD_LE_INFO_CHAR] = %x\n", + BTC_TRACE_ERROR(" p_inst->att_tbl[HIDD_LE_INFO_CHAR] = %x\n", p_inst->att_tbl[HIDD_LE_INFO_CHAR]); rsp.attr_value.handle = p_inst->att_tbl[HIDD_LE_INFO_CHAR]; rsp.attr_value.len = HID_INFORMATION_LEN; @@ -533,7 +533,7 @@ void hidd_rsp (uint32_t trans_id, uint16_t conn_id, uint8_t app_id, break; case HIDD_LE_READ_CTNL_PT_EVT: - LOG_ERROR(" p_inst->att_tbl[HIDD_LE_CTNL_PT_CHAR] = %x\n", + BTC_TRACE_ERROR(" p_inst->att_tbl[HIDD_LE_CTNL_PT_CHAR] = %x\n", p_inst->att_tbl[HIDD_LE_CTNL_PT_CHAR]); rsp.attr_value.handle = p_inst->att_tbl[HIDD_LE_CTNL_PT_CHAR]; rsp.attr_value.len = 0; @@ -542,7 +542,7 @@ void hidd_rsp (uint32_t trans_id, uint16_t conn_id, uint8_t app_id, break; case HIDD_LE_READ_REPORT_MAP_EVT: - LOG_ERROR("p_inst->att_tbl[HIDD_LE_REPORT_MAP_CHAR] = %x\n", + BTC_TRACE_ERROR("p_inst->att_tbl[HIDD_LE_REPORT_MAP_CHAR] = %x\n", p_inst->att_tbl[HIDD_LE_REPORT_MAP_CHAR]); rsp.attr_value.handle = p_inst->att_tbl[HIDD_LE_REPORT_MAP_CHAR]; rsp.attr_value.len = hidReportMapLen; @@ -552,7 +552,7 @@ void hidd_rsp (uint32_t trans_id, uint16_t conn_id, uint8_t app_id, esp_ble_gatts_send_rsp(conn_id, trans_id, status, &rsp); break; case HIDD_LE_READ_REPORT_EVT: - LOG_ERROR("p_inst->att_tbl[HIDD_LE_BOOT_KB_IN_REPORT_CHAR] = %x\n", + BTC_TRACE_ERROR("p_inst->att_tbl[HIDD_LE_BOOT_KB_IN_REPORT_CHAR] = %x\n", p_inst->att_tbl[HIDD_LE_BOOT_KB_IN_REPORT_CHAR]); rsp.attr_value.handle = p_inst->att_tbl[HIDD_LE_BOOT_KB_IN_REPORT_CHAR]; rsp.attr_value.len = 0; @@ -560,7 +560,7 @@ void hidd_rsp (uint32_t trans_id, uint16_t conn_id, uint8_t app_id, esp_ble_gatts_send_rsp(conn_id, trans_id, status, &rsp); break; case HIDD_LE_READ_PROTO_MODE_EVT: - LOG_ERROR("p_inst->att_tbl[HIDD_LE_PROTO_MODE_CHAR] = %x\n", + BTC_TRACE_ERROR("p_inst->att_tbl[HIDD_LE_PROTO_MODE_CHAR] = %x\n", p_inst->att_tbl[HIDD_LE_PROTO_MODE_CHAR]); rsp.attr_value.handle = p_inst->att_tbl[HIDD_LE_PROTO_MODE_CHAR]; rsp.attr_value.len = 1; @@ -570,7 +570,7 @@ void hidd_rsp (uint32_t trans_id, uint16_t conn_id, uint8_t app_id, esp_ble_gatts_send_rsp(conn_id, trans_id, status, &rsp); break; case HIDD_LE_BOOT_KB_IN_REPORT_EVT: - LOG_ERROR("p_inst->att_tbl[HIDD_LE_BOOT_KB_IN_REPORT_CHAR] = %x\n", + BTC_TRACE_ERROR("p_inst->att_tbl[HIDD_LE_BOOT_KB_IN_REPORT_CHAR] = %x\n", p_inst->att_tbl[HIDD_LE_BOOT_KB_IN_REPORT_CHAR]); rsp.attr_value.handle = p_inst->att_tbl[HIDD_LE_BOOT_KB_IN_REPORT_CHAR]; rsp.attr_value.len = 0; @@ -578,7 +578,7 @@ void hidd_rsp (uint32_t trans_id, uint16_t conn_id, uint8_t app_id, esp_ble_gatts_send_rsp(conn_id, trans_id, status, &rsp); break; case HIDD_LE_BOOT_KB_OUT_REPORT_EVT: - LOG_ERROR("p_inst->att_tbl[HIDD_LE_BOOT_KB_IN_REPORT_CHAR] = %x\n", + BTC_TRACE_ERROR("p_inst->att_tbl[HIDD_LE_BOOT_KB_IN_REPORT_CHAR] = %x\n", p_inst->att_tbl[HIDD_LE_BOOT_KB_IN_REPORT_CHAR]); rsp.attr_value.handle = p_inst->att_tbl[HIDD_LE_BOOT_KB_IN_REPORT_CHAR]; rsp.attr_value.len = 0; @@ -586,7 +586,7 @@ void hidd_rsp (uint32_t trans_id, uint16_t conn_id, uint8_t app_id, esp_ble_gatts_send_rsp(conn_id, trans_id, status, &rsp); break; case HIDD_LE_BOOT_MOUSE_IN_REPORT_EVT: - LOG_ERROR("p_inst->att_tbl[HIDD_LE_BOOT_KB_IN_REPORT_CHAR] = %x\n", + BTC_TRACE_ERROR("p_inst->att_tbl[HIDD_LE_BOOT_KB_IN_REPORT_CHAR] = %x\n", p_inst->att_tbl[HIDD_LE_BOOT_KB_IN_REPORT_CHAR]); rsp.attr_value.handle = p_inst->att_tbl[HIDD_LE_BOOT_KB_IN_REPORT_CHAR]; rsp.attr_value.len = 0; @@ -616,7 +616,7 @@ esp_gatt_status_t hidd_le_init (void) tBT_UUID app_uuid = {LEN_UUID_16, {ATT_SVC_HID}}; if (hidd_le_env.enabled) { - LOG_ERROR("hid device svc already initaliezd\n"); + BTC_TRACE_ERROR("hid device svc already initaliezd\n"); return ESP_GATT_ERROR; } else { memset(&hidd_le_env, 0, sizeof(hidd_le_env_t)); diff --git a/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c b/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c index c8b58d4d4b..ef3287ce89 100644 --- a/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c +++ b/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c @@ -204,12 +204,12 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u case BTA_JV_RFCOMM_SRV_OPEN_EVT: slot = find_slot_by_id(id); if (!slot) { - LOG_ERROR("%s unable to find RFCOMM slot!", __func__); + BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); break; } slot_new = malloc_spp_slot(); if (!slot_new) { - LOG_ERROR("%s unable to malloc RFCOMM slot!", __func__); + BTC_TRACE_ERROR("%s unable to malloc RFCOMM slot!", __func__); break; } new_user_data = (void *)(uintptr_t)slot_new->id; @@ -230,7 +230,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u case BTA_JV_RFCOMM_OPEN_EVT: slot = find_slot_by_id(id); if (!slot) { - LOG_ERROR("%s unable to find RFCOMM slot!", __func__); + BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); break; } slot->connected = TRUE; @@ -240,7 +240,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u case BTA_JV_RFCOMM_CLOSE_EVT: slot = find_slot_by_id(id); if (!slot) { - LOG_ERROR("%s unable to find RFCOMM slot!", __func__); + BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); break; } if (slot->connected) { @@ -264,7 +264,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u sizeof(tBTA_JV), NULL); if (status != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed", __func__); } return new_user_data; } @@ -281,12 +281,12 @@ static void btc_spp_dm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); slot = find_slot_by_id(id); if (!slot) { - LOG_ERROR("%s unable to find RFCOMM slot!", __func__); + BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); break; } if (p_data->scn == 0) { - LOG_ERROR("%s unable to get scn, start server fail!", __func__); + BTC_TRACE_ERROR("%s unable to get scn, start server fail!", __func__); btc_create_server_fail_cb(); free_spp_slot(slot); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -301,7 +301,7 @@ static void btc_spp_dm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); slot = find_slot_by_id(id); if (!slot) { - LOG_ERROR("%s unable to find RFCOMM slot!", __func__); + BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); break; } @@ -310,7 +310,7 @@ static void btc_spp_dm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d BTA_JvRfcommStartServer(slot->security, slot->role, slot->scn, slot->max_session, (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, (void *)slot->id); } else { - LOG_ERROR("%s unable to create record, start server fail!", __func__); + BTC_TRACE_ERROR("%s unable to create record, start server fail!", __func__); btc_create_server_fail_cb(); BTA_JvFreeChannel(slot->scn, BTA_JV_CONN_TYPE_RFCOMM); free_spp_slot(slot); @@ -325,7 +325,7 @@ static void btc_spp_dm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d status = btc_transfer_context(&msg, p_data, sizeof(tBTA_JV), NULL); if (status != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } break; } @@ -334,7 +334,7 @@ static void btc_spp_dm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d static void btc_spp_init(btc_spp_args_t *arg) { if (osi_mutex_new(&spp_local_param.spp_slot_mutex) != 0) { - LOG_ERROR("%s osi_mutex_new failed\n", __func__); + BTC_TRACE_ERROR("%s osi_mutex_new failed\n", __func__); } spp_local_param.spp_mode = arg->init.mode; spp_local_param.spp_slot_id = 0; @@ -376,7 +376,7 @@ static void btc_spp_connect(btc_spp_args_t *arg) osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); spp_slot_t *slot = malloc_spp_slot(); if (!slot) { - LOG_ERROR("%s unable to malloc RFCOMM slot!", __func__); + BTC_TRACE_ERROR("%s unable to malloc RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); return; } @@ -394,7 +394,7 @@ static void btc_spp_disconnect(btc_spp_args_t *arg) osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); spp_slot_t *slot = find_slot_by_handle(arg->disconnect.handle); if (!slot) { - LOG_ERROR("%s unable to find RFCOMM slot! disconnect fail!", __func__); + BTC_TRACE_ERROR("%s unable to find RFCOMM slot! disconnect fail!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); return; } @@ -409,7 +409,7 @@ static void btc_spp_start_srv(btc_spp_args_t *arg) osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); spp_slot_t *slot = malloc_spp_slot(); if (!slot) { - LOG_ERROR("%s unable to malloc RFCOMM slot!", __func__); + BTC_TRACE_ERROR("%s unable to malloc RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); return; } @@ -428,7 +428,7 @@ static void btc_spp_write(btc_spp_args_t *arg) osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); spp_slot_t *slot = find_slot_by_handle(arg->write.handle); if (!slot) { - LOG_ERROR("%s unable to find RFCOMM slot!", __func__); + BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); return; } @@ -462,9 +462,9 @@ void btc_spp_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) if (dst->start_discovery.p_uuid_list) { memcpy(dst->start_discovery.p_uuid_list, src->start_discovery.p_uuid_list, src->start_discovery.num_uuid * sizeof(tSDP_UUID)); } else if (src->start_discovery.num_uuid == 0) { - LOG_ERROR("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d no mem\n", __func__, msg->act); } else { - LOG_ERROR("%s %d osi_malloc failed\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act); } break; case BTC_SPP_ACT_WRITE: @@ -472,9 +472,9 @@ void btc_spp_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) if (dst->write.p_data) { memcpy(dst->write.p_data, src->write.p_data, src->write.len); } else if (src->write.len == 0) { - LOG_DEBUG("%s %d no mem\n", __func__, msg->act); + BTC_TRACE_DEBUG("%s %d no mem\n", __func__, msg->act); } else { - LOG_ERROR("%s %d osi_malloc failed\n", __func__, msg->act); + BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act); } break; default: @@ -523,7 +523,7 @@ void btc_spp_call_handler(btc_msg_t *msg) btc_spp_write(arg); break; default: - LOG_ERROR("%s: Unhandled event (%d)!\n", __FUNCTION__, msg->act); + BTC_TRACE_ERROR("%s: Unhandled event (%d)!\n", __FUNCTION__, msg->act); break; } btc_spp_arg_deep_free(msg); @@ -557,7 +557,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); slot = find_slot_by_handle(p_data->rfc_open.handle); if (!slot) { - LOG_ERROR("%s unable to find RFCOMM slot!", __func__); + BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); break; } @@ -581,7 +581,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); slot = find_slot_by_handle(p_data->rfc_srv_open.handle); if (!slot) { - LOG_ERROR("%s unable to find RFCOMM slot!", __func__); + BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); break; } @@ -598,7 +598,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); slot = find_slot_by_handle(p_data->rfc_write.handle); if (!slot) { - LOG_ERROR("%s unable to find RFCOMM slot!", __func__); + BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); break; } @@ -650,7 +650,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); slot = find_slot_by_handle(p_data->rfc_cong.handle); if (!slot) { - LOG_ERROR("%s unable to find RFCOMM slot!", __func__); + BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); break; } @@ -684,7 +684,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) osi_free (p_data->data_ind.p_buf); break; default: - LOG_DEBUG("%s: Unhandled event (%d)!", __FUNCTION__, msg->act); + BTC_TRACE_DEBUG("%s: Unhandled event (%d)!", __FUNCTION__, msg->act); break; } @@ -707,7 +707,7 @@ static void spp_delay_append(list_t *list, BT_HDR *p_buf){ vTaskDelay(100 / portTICK_PERIOD_MS); } osi_free(p_buf); - LOG_WARN("%s There is too much data not accepted, discard it!", __func__); + BTC_TRACE_WARNING("%s There is too much data not accepted, discard it!", __func__); } int bta_co_rfc_data_incoming(void *user_data, BT_HDR *p_buf) @@ -723,7 +723,7 @@ int bta_co_rfc_data_incoming(void *user_data, BT_HDR *p_buf) osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); spp_slot_t *slot = find_slot_by_id(id); if (!slot) { - LOG_ERROR("%s unable to find RFCOMM slot!", __func__); + BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); return 0; } @@ -734,7 +734,7 @@ int bta_co_rfc_data_incoming(void *user_data, BT_HDR *p_buf) status = btc_transfer_context(&msg, &p_data, sizeof(tBTA_JV), NULL); if (status != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } else { if (list_is_empty(slot->incoming_list)) { @@ -769,7 +769,7 @@ static ssize_t spp_vfs_write(int fd, const void * data, size_t size) osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); spp_slot_t *slot = find_slot_by_fd(fd); if (!slot) { - LOG_ERROR("%s unable to find RFCOMM slot!", __func__); + BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); return -1; } @@ -788,7 +788,7 @@ static int spp_vfs_close(int fd) osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); spp_slot_t *slot = find_slot_by_fd(fd); if (!slot) { - LOG_ERROR("%s unable to find RFCOMM slot!", __func__); + BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); return -1; } @@ -816,7 +816,7 @@ static ssize_t spp_vfs_read(int fd, void * dst, size_t size) osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); spp_slot_t *slot = find_slot_by_fd(fd); if (!slot) { - LOG_ERROR("%s unable to find RFCOMM slot!", __func__); + BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); return -1; } diff --git a/components/bt/bluedroid/common/include/common/bt_trace.h b/components/bt/bluedroid/common/include/common/bt_trace.h index b95dd3a8b7..7583479b2b 100644 --- a/components/bt/bluedroid/common/include/common/bt_trace.h +++ b/components/bt/bluedroid/common/include/common/bt_trace.h @@ -18,19 +18,42 @@ #ifndef _BT_TRACE_H_ #define _BT_TRACE_H_ + #include "sdkconfig.h" #include #include "stack/bt_types.h" +#ifndef LOG_LOCAL_LEVEL +#ifndef BOOTLOADER_BUILD +#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL +#else +#define LOG_LOCAL_LEVEL CONFIG_LOG_BOOTLOADER_LEVEL +#endif +#endif + #include "esp_log.h" -#define TAG "BT" +// Mapping between ESP_LOG_LEVEL and BT_TRACE_LEVEL +#if (LOG_LOCAL_LEVEL >= 4) +#define LOG_LOCAL_LEVEL_MAPPING (LOG_LOCAL_LEVEL+1) +#else +#define LOG_LOCAL_LEVEL_MAPPING LOG_LOCAL_LEVEL +#endif -#define BT_PRINTF(fmt, ...) ESP_LOGE(TAG, fmt, ##__VA_ARGS__) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define BT_LOG_LEVEL_CHECK(LAYER, LEVEL) (MAX(LAYER##_INITIAL_TRACE_LEVEL, LOG_LOCAL_LEVEL_MAPPING) >= BT_TRACE_LEVEL_##LEVEL) + +//#define TAG "BT" + +#define BT_PRINT_E(tag, format, ...) {esp_log_write(ESP_LOG_ERROR, tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } +#define BT_PRINT_W(tag, format, ...) {esp_log_write(ESP_LOG_WARN, tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } +#define BT_PRINT_I(tag, format, ...) {esp_log_write(ESP_LOG_INFO, tag, LOG_FORMAT(I, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } +#define BT_PRINT_D(tag, format, ...) {esp_log_write(ESP_LOG_DEBUG, tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } +#define BT_PRINT_V(tag, format, ...) {esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } #ifndef assert -#define assert(x) do { if (!(x)) BT_PRINTF("bt host error %s %u\n", __FILE__, __LINE__); } while (0) +#define assert(x) do { if (!(x)) BT_PRINT_E("bt host error %s %u\n", __FILE__, __LINE__); } while (0) #endif inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t len) @@ -42,15 +65,15 @@ inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t len) } if (prefix) { - BT_PRINTF("%s: len %d\n", prefix, len); + printf("%s: len %d\r\n", prefix, len); } for (i = 0; i < len; i+=16) { - BT_PRINTF("%02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x\n", + printf("%02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x\r\n", *(data + i), *(data + i + 1), *(data + i + 2), *(data + i + 3), *(data + i + 4), *(data + i + 5), *(data + i + 6), *(data + i + 7), *(data + i + 8), *(data + i + 9), *(data + i + 10), *(data + i + 11), *(data + i + 12), *(data + i + 13), *(data + i + 14), *(data + i + 15)); } - BT_PRINTF("\n"); + printf("\r\n"); } #ifdef BTTRC_DUMP_BUFFER @@ -174,6 +197,10 @@ inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t len) #define BT_USE_TRACES FALSE #endif +#ifndef BT_TRACE_APPL +#define BT_TRACE_APPL BT_USE_TRACES +#endif + /****************************************************************************** ** ** Trace Levels @@ -189,238 +216,310 @@ inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t len) // btla-specific ++ /* Core Stack default trace levels */ -#ifndef HCI_INITIAL_TRACE_LEVEL +#ifdef CONFIG_HCI_INITIAL_TRACE_LEVEL +#define HCI_INITIAL_TRACE_LEVEL CONFIG_HCI_INITIAL_TRACE_LEVEL +#else #define HCI_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -#ifndef BTM_INITIAL_TRACE_LEVEL +#ifdef CONFIG_BTM_INITIAL_TRACE_LEVEL +#define BTM_INITIAL_TRACE_LEVEL CONFIG_BTM_INITIAL_TRACE_LEVEL +#else #define BTM_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -#ifndef L2CAP_INITIAL_TRACE_LEVEL +#ifdef CONFIG_L2CAP_INITIAL_TRACE_LEVEL +#define L2CAP_INITIAL_TRACE_LEVEL CONFIG_L2CAP_INITIAL_TRACE_LEVEL +#else #define L2CAP_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -#ifndef RFCOMM_INITIAL_TRACE_LEVEL +#ifdef CONFIG_RFCOMM_INITIAL_TRACE_LEVEL +#define RFCOMM_INITIAL_TRACE_LEVEL CONFIG_RFCOMM_INITIAL_TRACE_LEVEL +#else #define RFCOMM_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -#ifndef SDP_INITIAL_TRACE_LEVEL +#ifdef CONFIG_SDP_INITIAL_TRACE_LEVEL +#define SDP_INITIAL_TRACE_LEVEL CONFIG_SDP_INITIAL_TRACE_LEVEL +#else #define SDP_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -#ifndef GAP_INITIAL_TRACE_LEVEL +#ifdef CONFIG_GAP_INITIAL_TRACE_LEVEL +#define GAP_INITIAL_TRACE_LEVEL CONFIG_GAP_INITIAL_TRACE_LEVEL +#else #define GAP_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -#ifndef BNEP_INITIAL_TRACE_LEVEL +#ifdef CONFIG_BNEP_INITIAL_TRACE_LEVEL +#define BNEP_INITIAL_TRACE_LEVEL CONFIG_BNEP_INITIAL_TRACE_LEVEL +#else #define BNEP_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -#ifndef PAN_INITIAL_TRACE_LEVEL +#ifdef CONFIG_PAN_INITIAL_TRACE_LEVEL +#define PAN_INITIAL_TRACE_LEVEL CONFIG_PAN_INITIAL_TRACE_LEVEL +#else #define PAN_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -#ifndef A2D_INITIAL_TRACE_LEVEL +#ifdef CONFIG_A2D_INITIAL_TRACE_LEVEL +#define A2D_INITIAL_TRACE_LEVEL CONFIG_A2D_INITIAL_TRACE_LEVEL +#else #define A2D_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -#ifndef AVDT_INITIAL_TRACE_LEVEL +#ifdef CONFIG_AVDT_INITIAL_TRACE_LEVEL +#define AVDT_INITIAL_TRACE_LEVEL CONFIG_AVDT_INITIAL_TRACE_LEVEL +#else #define AVDT_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -#ifndef AVCT_INITIAL_TRACE_LEVEL +#ifdef CONFIG_AVCT_INITIAL_TRACE_LEVEL +#define AVCT_INITIAL_TRACE_LEVEL CONFIG_AVCT_INITIAL_TRACE_LEVEL +#else #define AVCT_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -#ifndef AVRC_INITIAL_TRACE_LEVEL +#ifdef CONFIG_AVRC_INITIAL_TRACE_LEVEL +#define AVRC_INITIAL_TRACE_LEVEL CONFIG_AVRC_INITIAL_TRACE_LEVEL +#else #define AVRC_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -#ifndef MCA_INITIAL_TRACE_LEVEL +#ifdef CONFIG_MCA_INITIAL_TRACE_LEVEL +#define MCA_INITIAL_TRACE_LEVEL CONFIG_MCA_INITIAL_TRACE_LEVEL +#else #define MCA_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -#ifndef HID_INITIAL_TRACE_LEVEL +#ifdef CONFIG_HID_INITIAL_TRACE_LEVEL +#define HID_INITIAL_TRACE_LEVEL CONFIG_HID_INITIAL_TRACE_LEVEL +#else #define HID_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -#ifndef APPL_INITIAL_TRACE_LEVEL +#ifdef CONFIG_APPL_INITIAL_TRACE_LEVEL +#define APPL_INITIAL_TRACE_LEVEL CONFIG_APPL_INITIAL_TRACE_LEVEL +#else #define APPL_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -#ifndef BT_TRACE_APPL -#define BT_TRACE_APPL BT_USE_TRACES +#ifdef CONFIG_GATT_INITIAL_TRACE_LEVEL +#define GATT_INITIAL_TRACE_LEVEL CONFIG_GATT_INITIAL_TRACE_LEVEL +#else +#define GATT_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -#ifndef GATT_INITIAL_TRACE_LEVEL -#define GATT_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING -#endif - -#ifndef SMP_INITIAL_TRACE_LEVEL +#ifdef CONFIG_SMP_INITIAL_TRACE_LEVEL +#define SMP_INITIAL_TRACE_LEVEL CONFIG_SMP_INITIAL_TRACE_LEVEL +#else #define SMP_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -// btla-specific -- -/* Define common tracing for all */ -#define LOG_LEVEL_ERROR 1 -#define LOG_LEVEL_WARN 2 -#define LOG_LEVEL_INFO 3 -#define LOG_LEVEL_DEBUG 4 -#define LOG_LEVEL_VERBOSE 5 -#ifndef LOG_LEVEL -#define LOG_LEVEL LOG_LEVEL_INFO +#ifdef CONFIG_BTIF_INITIAL_TRACE_LEVEL +#define BTIF_INITIAL_TRACE_LEVEL CONFIG_BTIF_INITIAL_TRACE_LEVEL +#else +#define BTIF_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING #endif -#if !CONFIG_BT_STACK_NO_LOG -#define LOG_ERROR(fmt, args...) do {if (LOG_LEVEL >= LOG_LEVEL_ERROR) BT_PRINTF(fmt,## args);} while(0) -#define LOG_WARN(fmt, args...) do {if (LOG_LEVEL >= LOG_LEVEL_WARN) BT_PRINTF(fmt,## args);} while(0) -#define LOG_INFO(fmt, args...) do {if (LOG_LEVEL >= LOG_LEVEL_INFO) BT_PRINTF(fmt,## args);} while(0) -#define LOG_DEBUG(fmt, args...) do {if (LOG_LEVEL >= LOG_LEVEL_DEBUG) BT_PRINTF(fmt,## args);} while(0) -#define LOG_VERBOSE(fmt, args...) do {if (LOG_LEVEL >= LOG_LEVEL_VERBOSE) BT_PRINTF(fmt,## args);} while(0) +#ifdef CONFIG_BTC_INITIAL_TRACE_LEVEL +#define BTC_INITIAL_TRACE_LEVEL CONFIG_BTC_INITIAL_TRACE_LEVEL +#else +#define BTC_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING +#endif -/* Define tracing for the HCI unit -*/ -#define HCI_TRACE_ERROR(fmt, args...) {if (btu_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt,## args);} -#define HCI_TRACE_WARNING(fmt, args...) {if (btu_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt,## args);} -#define HCI_TRACE_EVENT(fmt, args...) {if (btu_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt,## args);} -#define HCI_TRACE_DEBUG(fmt, args...) {if (btu_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_PRINTF(fmt,## args);} +#ifdef CONFIG_OSI_INITIAL_TRACE_LEVEL +#define OSI_INITIAL_TRACE_LEVEL CONFIG_OSI_INITIAL_TRACE_LEVEL +#else +#define OSI_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING +#endif + +#ifdef CONFIG_BLUFI_INITIAL_TRACE_LEVEL +#define BLUFI_INITIAL_TRACE_LEVEL CONFIG_BLUFI_INITIAL_TRACE_LEVEL +#else +#define BLUFI_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING +#endif + +// btla-specific -- + +#if !CONFIG_BT_STACK_NO_LOG +#define LOG_ERROR(format, ... ) {if (LOG_LOCAL_LEVEL >= ESP_LOG_ERROR) esp_log_write(ESP_LOG_ERROR, "BT_LOG", LOG_FORMAT(E, format), esp_log_timestamp(), "BT_LOG", ##__VA_ARGS__); } +#define LOG_WARN(format, ... ) {if (LOG_LOCAL_LEVEL >= ESP_LOG_WARN) esp_log_write(ESP_LOG_WARN, "BT_LOG", LOG_FORMAT(W, format), esp_log_timestamp(), "BT_LOG", ##__VA_ARGS__); } +#define LOG_INFO(format, ... ) {if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) esp_log_write(ESP_LOG_INFO, "BT_LOG", LOG_FORMAT(I, format), esp_log_timestamp(), "BT_LOG", ##__VA_ARGS__); } +#define LOG_DEBUG(format, ... ) {if (LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) esp_log_write(ESP_LOG_DEBUG, "BT_LOG", LOG_FORMAT(D, format), esp_log_timestamp(), "BT_LOG", ##__VA_ARGS__); } +#define LOG_VERBOSE(format, ... ) {if (LOG_LOCAL_LEVEL >= ESP_LOG_VERBOSE) esp_log_write(ESP_LOG_VERBOSE, "BT_LOG", LOG_FORMAT(V, format), esp_log_timestamp(), "BT_LOG", ##__VA_ARGS__); } /* Define tracing for BTM */ -#define BTM_TRACE_ERROR(fmt, args...) {if (btm_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt, ## args);} -#define BTM_TRACE_WARNING(fmt, args...) {if (btm_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt, ## args);} -#define BTM_TRACE_API(fmt, args...) {if (btm_cb.trace_level >= BT_TRACE_LEVEL_API) BT_PRINTF(fmt, ## args);} -#define BTM_TRACE_EVENT(fmt, args...) {if (btm_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt, ## args);} -#define BTM_TRACE_DEBUG(fmt, args...) {if (btm_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_PRINTF(fmt, ## args);} +#define BTM_TRACE_ERROR(fmt, args...) {if (btm_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(BTM, ERROR)) BT_PRINT_E("BT_BTM", fmt, ## args);} +#define BTM_TRACE_WARNING(fmt, args...) {if (btm_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(BTM, WARNING)) BT_PRINT_W("BT_BTM", fmt, ## args);} +#define BTM_TRACE_API(fmt, args...) {if (btm_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(BTM,API)) BT_PRINT_I("BT_BTM", fmt, ## args);} +#define BTM_TRACE_EVENT(fmt, args...) {if (btm_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(BTM,EVENT)) BT_PRINT_D("BT_BTM", fmt, ## args);} +#define BTM_TRACE_DEBUG(fmt, args...) {if (btm_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(BTM,DEBUG)) BT_PRINT_D("BT_BTM", fmt, ## args);} /* Define tracing for the L2CAP unit */ -#define L2CAP_TRACE_ERROR(fmt, args...) {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt, ## args);} -#define L2CAP_TRACE_WARNING(fmt, args...) {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt, ## args);} -#define L2CAP_TRACE_API(fmt, args...) {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_API) BT_PRINTF(fmt, ## args);} -#define L2CAP_TRACE_EVENT(fmt, args...) {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt, ## args);} -#define L2CAP_TRACE_DEBUG(fmt, args...) {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_DEBUG) BT_PRINTF(fmt, ## args);} +#define L2CAP_TRACE_ERROR(fmt, args...) {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(L2CAP, ERROR)) BT_PRINT_E("BT_L2CAP", fmt, ## args);} +#define L2CAP_TRACE_WARNING(fmt, args...) {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(L2CAP, WARNING)) BT_PRINT_W("BT_L2CAP", fmt, ## args);} +#define L2CAP_TRACE_API(fmt, args...) {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(L2CAP,API)) BT_PRINT_I("BT_L2CAP", fmt, ## args);} +#define L2CAP_TRACE_EVENT(fmt, args...) {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(L2CAP,EVENT)) BT_PRINT_D("BT_L2CAP", fmt, ## args);} +#define L2CAP_TRACE_DEBUG(fmt, args...) {if (l2cb.l2cap_trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(L2CAP,DEBUG)) BT_PRINT_D("BT_L2CAP", fmt, ## args);} /* Define tracing for the SDP unit */ -#define SDP_TRACE_ERROR(fmt, args...) {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt, ## args);} -#define SDP_TRACE_WARNING(fmt, args...) {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt, ## args);} -#define SDP_TRACE_API(fmt, args...) {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_API) BT_PRINTF(fmt, ## args);} -#define SDP_TRACE_EVENT(fmt, args...) {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt, ## args);} -#define SDP_TRACE_DEBUG(fmt, args...) {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_PRINTF(fmt, ## args);} +#define SDP_TRACE_ERROR(fmt, args...) {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(SDP, ERROR)) BT_PRINT_E("BT_SDP", fmt, ## args);} +#define SDP_TRACE_WARNING(fmt, args...) {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(SDP, WARNING)) BT_PRINT_W("BT_SDP", fmt, ## args);} +#define SDP_TRACE_API(fmt, args...) {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(SDP,API)) BT_PRINT_I("BT_SDP", fmt, ## args);} +#define SDP_TRACE_EVENT(fmt, args...) {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(SDP,EVENT)) BT_PRINT_D("BT_SDP", fmt, ## args);} +#define SDP_TRACE_DEBUG(fmt, args...) {if (sdp_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(SDP,DEBUG)) BT_PRINT_D("BT_SDP", fmt, ## args);} /* Define tracing for the RFCOMM unit */ -#define RFCOMM_TRACE_ERROR(fmt, args...) {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt, ## args);} -#define RFCOMM_TRACE_WARNING(fmt, args...) {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt, ## args);} -#define RFCOMM_TRACE_API(fmt, args...) {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_API) BT_PRINTF(fmt, ## args);} -#define RFCOMM_TRACE_EVENT(fmt, args...) {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt, ## args);} -#define RFCOMM_TRACE_DEBUG(fmt, args...) {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_PRINTF(fmt, ## args);} +#define RFCOMM_TRACE_ERROR(fmt, args...) {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(RFCOMM, ERROR)) BT_PRINT_E("BT_RFCOMM", fmt, ## args);} +#define RFCOMM_TRACE_WARNING(fmt, args...) {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(RFCOMM, WARNING)) BT_PRINT_W("BT_RFCOMM", fmt, ## args);} +#define RFCOMM_TRACE_API(fmt, args...) {if (rfc_cb.trace_level >=BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(RFCOMM,API)) BT_PRINT_I("BT_RFCOMM", fmt, ## args);} +#define RFCOMM_TRACE_EVENT(fmt, args...) {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(RFCOMM,EVENT)) BT_PRINT_D("BT_RFCOMM", fmt, ## args);} +#define RFCOMM_TRACE_DEBUG(fmt, args...) {if (rfc_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(RFCOMM,DEBUG)) BT_PRINT_D("BT_RFCOMM", fmt, ## args);} /* Generic Access Profile traces */ -#define GAP_TRACE_ERROR(fmt, args...) {if (gap_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt, ## args);} -#define GAP_TRACE_EVENT(fmt, args...) {if (gap_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt, ## args);} -#define GAP_TRACE_API(fmt, args...) {if (gap_cb.trace_level >= BT_TRACE_LEVEL_API) BT_PRINTF(fmt, ## args);} -#define GAP_TRACE_WARNING(fmt, args...) {if (gap_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt, ## args);} +#define GAP_TRACE_ERROR(fmt, args...) {if (gap_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(GAP, ERROR)) BT_PRINT_E("BT_GAP", fmt, ## args);} +#define GAP_TRACE_API(fmt, args...) {if (gap_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(GAP,API)) BT_PRINT_I("BT_GAP", fmt, ## args);} +#define GAP_TRACE_EVENT(fmt, args...) {if (gap_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(GAP,EVENT)) BT_PRINT_D("BT_GAP", fmt, ## args);} +#define GAP_TRACE_WARNING(fmt, args...) {if (gap_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(GAP, WARNING)) BT_PRINT_W("BT_GAP", fmt, ## args);} /* define traces for HID Host */ -#define HIDH_TRACE_ERROR(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt, ## args);} -#define HIDH_TRACE_WARNING(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt, ## args);} -#define HIDH_TRACE_API(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_API) BT_PRINTF(fmt, ## args);} -#define HIDH_TRACE_EVENT(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt, ## args);} -#define HIDH_TRACE_DEBUG(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_PRINTF(fmt, ## args);} +#define HIDH_TRACE_ERROR(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(HIDH, ERROR)) BT_PRINT_E("BT_HIDH", fmt, ## args);} +#define HIDH_TRACE_WARNING(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(HIDH, WARNING)) BT_PRINT_W("BT_HIDH", fmt, ## args);} +#define HIDH_TRACE_API(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(HIDH,API)) BT_PRINT_I("BT_HIDH", fmt, ## args);} +#define HIDH_TRACE_EVENT(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(HIDH,EVENT)) BT_PRINT_D("BT_HIDH", fmt, ## args);} +#define HIDH_TRACE_DEBUG(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(HIDH,DEBUG)) BT_PRINT_D("BT_HIDH", fmt, ## args);} /* define traces for BNEP */ -#define BNEP_TRACE_ERROR(fmt, args...) {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt, ## args);} -#define BNEP_TRACE_WARNING(fmt, args...) {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt, ## args);} -#define BNEP_TRACE_API(fmt, args...) {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_API) BT_PRINTF(fmt, ## args);} -#define BNEP_TRACE_EVENT(fmt, args...) {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt, ## args);} -#define BNEP_TRACE_DEBUG(fmt, args...) {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_PRINTF(fmt, ## args);} +#define BNEP_TRACE_ERROR(fmt, args...) {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(BNEP, ERROR)) BT_PRINT_E("BT_BNEP", fmt, ## args);} +#define BNEP_TRACE_WARNING(fmt, args...) {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(BNEP, WARNING)) BT_PRINT_W("BT_BNEP", fmt, ## args);} +#define BNEP_TRACE_API(fmt, args...) {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(BNEP,API)) BT_PRINT_I("BT_BNEP", fmt, ## args);} +#define BNEP_TRACE_EVENT(fmt, args...) {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(BNEP,EVENT)) BT_PRINT_D("BT_BNEP", fmt, ## args);} +#define BNEP_TRACE_DEBUG(fmt, args...) {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(BNEP,DEBUG)) BT_PRINT_D("BT_BNEP", fmt, ## args);} /* define traces for PAN */ -#define PAN_TRACE_ERROR(fmt, args...) {if (pan_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt, ## args);} -#define PAN_TRACE_WARNING(fmt, args...) {if (pan_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt, ## args);} -#define PAN_TRACE_API(fmt, args...) {if (pan_cb.trace_level >= BT_TRACE_LEVEL_API) BT_PRINTF(fmt, ## args);} -#define PAN_TRACE_EVENT(fmt, args...) {if (pan_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt, ## args);} -#define PAN_TRACE_DEBUG(fmt, args...) {if (pan_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_PRINTF(fmt, ## args);} +#define PAN_TRACE_ERROR(fmt, args...) {if (pan_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(PAN, ERROR)) BT_PRINT_E("BT_PAN", fmt, ## args);} +#define PAN_TRACE_WARNING(fmt, args...) {if (pan_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(PAN, WARNING)) BT_PRINT_W("BT_PAN", fmt, ## args);} +#define PAN_TRACE_API(fmt, args...) {if (pan_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(PAN,API)) BT_PRINT_I("BT_PAN", fmt, ## args);} +#define PAN_TRACE_EVENT(fmt, args...) {if (pan_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(PAN,EVENT)) BT_PRINT_D("BT_PAN", fmt, ## args);} +#define PAN_TRACE_DEBUG(fmt, args...) {if (pan_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(PAN,DEBUG)) BT_PRINT_D("BT_PAN", fmt, ## args);} /* Define tracing for the A2DP profile */ -#define A2D_TRACE_ERROR(fmt, args...) {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt, ## args);} -#define A2D_TRACE_WARNING(fmt, args...) {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt, ## args);} -#define A2D_TRACE_EVENT(fmt, args...) {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt, ## args);} -#define A2D_TRACE_DEBUG(fmt, args...) {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_PRINTF(fmt, ## args);} -#define A2D_TRACE_API(fmt, args...) {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_API) BT_PRINTF(fmt, ## args);} +#define A2D_TRACE_ERROR(fmt, args...) {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(A2D, ERROR)) BT_PRINT_E("BT_A2D", fmt, ## args);} +#define A2D_TRACE_WARNING(fmt, args...) {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(A2D, WARNING)) BT_PRINT_W("BT_A2D", fmt, ## args);} +#define A2D_TRACE_API(fmt, args...) {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(A2D,API)) BT_PRINT_I("BT_A2D", fmt, ## args);} +#define A2D_TRACE_EVENT(fmt, args...) {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(A2D,EVENT)) BT_PRINT_D("BT_A2D", fmt, ## args);} +#define A2D_TRACE_DEBUG(fmt, args...) {if (a2d_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(A2D,DEBUG)) BT_PRINT_D("BT_A2D", fmt, ## args);} /* AVDTP */ -#define AVDT_TRACE_ERROR(fmt, args...) {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt, ## args);} -#define AVDT_TRACE_WARNING(fmt, args...) {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt, ## args);} -#define AVDT_TRACE_EVENT(fmt, args...) {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt, ## args);} -#define AVDT_TRACE_DEBUG(fmt, args...) {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_PRINTF(fmt, ## args);} -#define AVDT_TRACE_API(fmt, args...) {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_API) BT_PRINTF(fmt, ## args);} +#define AVDT_TRACE_ERROR(fmt, args...) {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(AVDT, ERROR)) BT_PRINT_E("BT_AVDT", fmt, ## args);} +#define AVDT_TRACE_WARNING(fmt, args...) {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(AVDT, WARNING)) BT_PRINT_W("BT_AVDT", fmt, ## args);} +#define AVDT_TRACE_API(fmt, args...) {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(AVDT,API)) BT_PRINT_I("BT_AVDT", fmt, ## args);} +#define AVDT_TRACE_EVENT(fmt, args...) {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(AVDT,EVENT)) BT_PRINT_D("BT_AVDT", fmt, ## args);} +#define AVDT_TRACE_DEBUG(fmt, args...) {if (avdt_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(AVDT,DEBUG)) BT_PRINT_D("BT_AVDT", fmt, ## args);} /* Define tracing for the AVCTP protocol */ -#define AVCT_TRACE_ERROR(fmt, args...) {if (avct_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt, ## args);} -#define AVCT_TRACE_WARNING(fmt, args...) {if (avct_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt, ## args);} -#define AVCT_TRACE_EVENT(fmt, args...) {if (avct_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt, ## args);} -#define AVCT_TRACE_DEBUG(fmt, args...) {if (avct_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_PRINTF(fmt, ## args);} -#define AVCT_TRACE_API(fmt, args...) {if (avct_cb.trace_level >= BT_TRACE_LEVEL_API) BT_PRINTF(fmt, ## args);} +#define AVCT_TRACE_ERROR(fmt, args...) {if (avct_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(AVCT, ERROR)) BT_PRINT_E("BT_AVCT", fmt, ## args);} +#define AVCT_TRACE_WARNING(fmt, args...) {if (avct_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(AVCT, WARNING)) BT_PRINT_W("BT_AVCT", fmt, ## args);} +#define AVCT_TRACE_API(fmt, args...) {if (avct_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(AVCT,API)) BT_PRINT_I("BT_AVCT", fmt, ## args);} +#define AVCT_TRACE_EVENT(fmt, args...) {if (avct_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(AVCT,EVENT)) BT_PRINT_D("BT_AVCT", fmt, ## args);} +#define AVCT_TRACE_DEBUG(fmt, args...) {if (avct_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(AVCT,DEBUG)) BT_PRINT_D("BT_AVCT", fmt, ## args);} /* Define tracing for the AVRCP profile */ -#define AVRC_TRACE_ERROR(fmt, args...) {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt, ## args);} -#define AVRC_TRACE_WARNING(fmt, args...) {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt, ## args);} -#define AVRC_TRACE_EVENT(fmt, args...) {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt, ## args);} -#define AVRC_TRACE_DEBUG(fmt, args...) {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_PRINTF(fmt, ## args);} -#define AVRC_TRACE_API(fmt, args...) {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_API) BT_PRINTF(fmt, ## args);} +#define AVRC_TRACE_ERROR(fmt, args...) {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(AVRC, ERROR)) BT_PRINT_E("BT_AVRC", fmt, ## args);} +#define AVRC_TRACE_WARNING(fmt, args...) {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(AVRC, WARNING)) BT_PRINT_W("BT_AVRC", fmt, ## args);} +#define AVRC_TRACE_API(fmt, args...) {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(AVRC,API)) BT_PRINT_I("BT_AVRC", fmt, ## args);} +#define AVRC_TRACE_EVENT(fmt, args...) {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(AVRC,EVENT)) BT_PRINT_D("BT_AVRC", fmt, ## args);} +#define AVRC_TRACE_DEBUG(fmt, args...) {if (avrc_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(AVRC,DEBUG)) BT_PRINT_D("BT_AVRC", fmt, ## args);} /* MCAP */ -#define MCA_TRACE_ERROR(fmt, args...) {if (mca_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt, ## args);} -#define MCA_TRACE_WARNING(fmt, args...) {if (mca_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt, ## args);} -#define MCA_TRACE_EVENT(fmt, args...) {if (mca_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt, ## args);} -#define MCA_TRACE_DEBUG(fmt, args...) {if (mca_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_PRINTF(fmt, ## args);} -#define MCA_TRACE_API(fmt, args...) {if (mca_cb.trace_level >= BT_TRACE_LEVEL_API) BT_PRINTF(fmt, ## args);} +#define MCA_TRACE_ERROR(fmt, args...) {if (mca_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(MCA, ERROR)) BT_PRINT_E("BT_MCA", fmt, ## args);} +#define MCA_TRACE_WARNING(fmt, args...) {if (mca_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(MCA, WARNING)) BT_PRINT_W("BT_MCA", fmt, ## args);} +#define MCA_TRACE_API(fmt, args...) {if (mca_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(MCA,API)) BT_PRINT_I("BT_MCA", fmt, ## args);} +#define MCA_TRACE_EVENT(fmt, args...) {if (mca_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(MCA,EVENT)) BT_PRINT_D("BT_MCA", fmt, ## args);} +#define MCA_TRACE_DEBUG(fmt, args...) {if (mca_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(MCA,DEBUG)) BT_PRINT_D("BT_MCA", fmt, ## args);} /* Define tracing for the ATT/GATT unit */ -#define GATT_TRACE_ERROR(fmt, args...) {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt, ## args);} -#define GATT_TRACE_WARNING(fmt, args...) {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt, ## args);} -#define GATT_TRACE_API(fmt, args...) {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_API) BT_PRINTF(fmt, ## args);} -#define GATT_TRACE_EVENT(fmt, args...) {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt, ## args);} -#define GATT_TRACE_DEBUG(fmt, args...) {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_PRINTF(fmt, ## args);} +#define GATT_TRACE_ERROR(fmt, args...) {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(GATT, ERROR)) BT_PRINT_E("BT_GATT", fmt, ## args);} +#define GATT_TRACE_WARNING(fmt, args...) {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(GATT, WARNING)) BT_PRINT_W("BT_GATT", fmt, ## args);} +#define GATT_TRACE_API(fmt, args...) {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(GATT,API)) BT_PRINT_I("BT_GATT", fmt, ## args);} +#define GATT_TRACE_EVENT(fmt, args...) {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(GATT,EVENT)) BT_PRINT_D("BT_GATT", fmt, ## args);} +#define GATT_TRACE_DEBUG(fmt, args...) {if (gatt_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(GATT,DEBUG)) BT_PRINT_D("BT_GATT", fmt, ## args);} /* Define tracing for the SMP unit */ -#define SMP_TRACE_ERROR(fmt, args...) {if (smp_cb.trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt, ## args);} -#define SMP_TRACE_WARNING(fmt, args...) {if (smp_cb.trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt, ## args);} -#define SMP_TRACE_API(fmt, args...) {if (smp_cb.trace_level >= BT_TRACE_LEVEL_API) BT_PRINTF(fmt, ## args);} -#define SMP_TRACE_EVENT(fmt, args...) {if (smp_cb.trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt, ## args);} -#define SMP_TRACE_DEBUG(fmt, args...) {if (smp_cb.trace_level >= BT_TRACE_LEVEL_DEBUG) BT_PRINTF(fmt, ## args);} +#define SMP_TRACE_ERROR(fmt, args...) {if (smp_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(SMP, ERROR)) BT_PRINT_E("BT_SMP", fmt, ## args);} +#define SMP_TRACE_WARNING(fmt, args...) {if (smp_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(SMP, WARNING)) BT_PRINT_W("BT_SMP", fmt, ## args);} +#define SMP_TRACE_API(fmt, args...) {if (smp_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(SMP,API)) BT_PRINT_I("BT_SMP", fmt, ## args);} +#define SMP_TRACE_EVENT(fmt, args...) {if (smp_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(SMP,EVENT)) BT_PRINT_D("BT_SMP", fmt, ## args);} +#define SMP_TRACE_DEBUG(fmt, args...) {if (smp_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(SMP,DEBUG)) BT_PRINT_D("BT_SMP", fmt, ## args);} + extern UINT8 btif_trace_level; // define traces for application -#define BTIF_TRACE_ERROR(fmt, args...) {if (btif_trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt, ## args);} -#define BTIF_TRACE_WARNING(fmt, args...) {if (btif_trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt, ## args);} -#define BTIF_TRACE_API(fmt, args...) {if (btif_trace_level >= BT_TRACE_LEVEL_API) BT_PRINTF(fmt, ## args);} -#define BTIF_TRACE_EVENT(fmt, args...) {if (btif_trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt, ## args);} -#define BTIF_TRACE_DEBUG(fmt, args...) {if (btif_trace_level >= BT_TRACE_LEVEL_DEBUG) BT_PRINTF(fmt, ## args);} -#define BTIF_TRACE_VERBOSE(fmt, args...) {if (btif_trace_level >= BT_TRACE_LEVEL_VERBOSE)BT_PRINTF(fmt, ## args);} +#define BTIF_TRACE_ERROR(fmt, args...) {if (btif_trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(BTIF, ERROR)) BT_PRINT_E("BT_BTIF", fmt, ## args);} +#define BTIF_TRACE_WARNING(fmt, args...) {if (btif_trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(BTIF, WARNING)) BT_PRINT_W("BT_BTIF", fmt, ## args);} +#define BTIF_TRACE_API(fmt, args...) {if (btif_trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(BTIF,API)) BT_PRINT_I("BT_BTIF", fmt, ## args);} +#define BTIF_TRACE_EVENT(fmt, args...) {if (btif_trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(BTIF,EVENT)) BT_PRINT_D("BT_BTIF", fmt, ## args);} +#define BTIF_TRACE_DEBUG(fmt, args...) {if (btif_trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(BTIF,DEBUG)) BT_PRINT_D("BT_BTIF", fmt, ## args);} +#define BTIF_TRACE_VERBOSE(fmt, args...) {if (btif_trace_level >= BT_TRACE_LEVEL_VERBOSE && BT_LOG_LEVEL_CHECK(BTIF,VERBOSE)) BT_PRINT_V("BT_BTIF", fmt, ## args);} /* define traces for application */ -#define APPL_TRACE_ERROR(fmt, args...) {if (appl_trace_level >= BT_TRACE_LEVEL_ERROR) BT_PRINTF(fmt, ## args);} -#define APPL_TRACE_WARNING(fmt, args...) {if (appl_trace_level >= BT_TRACE_LEVEL_WARNING) BT_PRINTF(fmt, ## args);} -#define APPL_TRACE_API(fmt, args...) {if (appl_trace_level >= BT_TRACE_LEVEL_API) BT_PRINTF(fmt, ## args);} -#define APPL_TRACE_EVENT(fmt, args...) {if (appl_trace_level >= BT_TRACE_LEVEL_EVENT) BT_PRINTF(fmt, ## args);} -#define APPL_TRACE_DEBUG(fmt, args...) {if (appl_trace_level >= BT_TRACE_LEVEL_DEBUG) BT_PRINTF(fmt, ## args);} -#define APPL_TRACE_VERBOSE(fmt, args...) {if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE) BT_PRINTF(fmt, ## args);} +#define APPL_TRACE_ERROR(fmt, args...) {if (appl_trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(APPL, ERROR)) BT_PRINT_E("BT_APPL", fmt, ## args);} +#define APPL_TRACE_WARNING(fmt, args...) {if (appl_trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(APPL, WARNING)) BT_PRINT_W("BT_APPL", fmt, ## args);} +#define APPL_TRACE_API(fmt, args...) {if (appl_trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(APPL,API)) BT_PRINT_I("BT_APPL", fmt, ## args);} +#define APPL_TRACE_EVENT(fmt, args...) {if (appl_trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(APPL,EVENT)) BT_PRINT_D("BT_APPL", fmt, ## args);} +#define APPL_TRACE_DEBUG(fmt, args...) {if (appl_trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(APPL,DEBUG)) BT_PRINT_D("BT_APPL", fmt, ## args);} +#define APPL_TRACE_VERBOSE(fmt, args...) {if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE && BT_LOG_LEVEL_CHECK(APPL,VERBOSE)) BT_PRINT_V("BT_APPL", fmt, ## args);} + +/* Define tracing for the HCI unit + * Modified from `btu_cb.trace_level` to `HCI_INITIAL_TRACE_LEVEL`, + * to use HCI_TRACE_XXXX in hci_layer.c without including `btu.h` +*/ +#define HCI_TRACE_ERROR(fmt, args...) {if (HCI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(HCI, ERROR)) BT_PRINT_E("BT_HCI", fmt,## args);} +#define HCI_TRACE_WARNING(fmt, args...) {if (HCI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(HCI, WARNING)) BT_PRINT_W("BT_HCI", fmt,## args);} +#define HCI_TRACE_EVENT(fmt, args...) {if (HCI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(HCI,EVENT)) BT_PRINT_D("BT_HCI", fmt,## args);} +#define HCI_TRACE_DEBUG(fmt, args...) {if (HCI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(HCI,DEBUG)) BT_PRINT_D("BT_HCI", fmt,## args);} + +/* define traces for BTC */ +#define BTC_TRACE_ERROR(fmt, args...) {if (BTC_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(BTC, ERROR)) BT_PRINT_E("BT_BTC", fmt, ## args);} +#define BTC_TRACE_WARNING(fmt, args...) {if (BTC_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(BTC, WARNING)) BT_PRINT_W("BT_BTC", fmt, ## args);} +#define BTC_TRACE_API(fmt, args...) {if (BTC_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(BTC,API)) BT_PRINT_I("BT_BTC", fmt, ## args);} +#define BTC_TRACE_EVENT(fmt, args...) {if (BTC_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(BTC,EVENT)) BT_PRINT_D("BT_BTC", fmt, ## args);} +#define BTC_TRACE_DEBUG(fmt, args...) {if (BTC_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(BTC,DEBUG)) BT_PRINT_D("BT_BTC", fmt, ## args);} +#define BTC_TRACE_VERBOSE(fmt, args...) {if (BTC_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_VERBOSE && BT_LOG_LEVEL_CHECK(BTC,VERBOSE)) BT_PRINT_V("BT_BTC", fmt, ## args);} + +/* define traces for OSI */ +#define OSI_TRACE_ERROR(fmt, args...) {if (OSI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(OSI, ERROR)) BT_PRINT_E("BT_OSI", fmt, ## args);} +#define OSI_TRACE_WARNING(fmt, args...) {if (OSI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(OSI, WARNING)) BT_PRINT_W("BT_OSI", fmt, ## args);} +#define OSI_TRACE_API(fmt, args...) {if (OSI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(OSI,API)) BT_PRINT_I("BT_OSI", fmt, ## args);} +#define OSI_TRACE_EVENT(fmt, args...) {if (OSI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(OSI,EVENT)) BT_PRINT_D("BT_OSI", fmt, ## args);} +#define OSI_TRACE_DEBUG(fmt, args...) {if (OSI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(OSI,DEBUG)) BT_PRINT_D("BT_OSI", fmt, ## args);} +#define OSI_TRACE_VERBOSE(fmt, args...) {if (OSI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_VERBOSE && BT_LOG_LEVEL_CHECK(OSI,VERBOSE)) BT_PRINT_V("BT_OSI", fmt, ## args);} + +/* define traces for BLUFI */ +#define BLUFI_TRACE_ERROR(fmt, args...) {if (BLUFI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(BLUFI, ERROR)) BT_PRINT_E("BT_BLUFI", fmt, ## args);} +#define BLUFI_TRACE_WARNING(fmt, args...) {if (BLUFI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(BLUFI, WARNING)) BT_PRINT_W("BT_BLUFI", fmt, ## args);} +#define BLUFI_TRACE_API(fmt, args...) {if (BLUFI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(BLUFI,API)) BT_PRINT_I("BT_BLUFI", fmt, ## args);} +#define BLUFI_TRACE_EVENT(fmt, args...) {if (BLUFI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(BLUFI,EVENT)) BT_PRINT_D("BT_BLUFI", fmt, ## args);} +#define BLUFI_TRACE_DEBUG(fmt, args...) {if (BLUFI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(BLUFI,DEBUG)) BT_PRINT_D("BT_BLUFI", fmt, ## args);} +#define BLUFI_TRACE_VERBOSE(fmt, args...) {if (BLUFI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_VERBOSE && BT_LOG_LEVEL_CHECK(BLUFI,VERBOSE)) BT_PRINT_V("BT_BLUFI", fmt, ## args);} #else #define LOG_ERROR(fmt, args...) @@ -571,6 +670,30 @@ extern UINT8 btif_trace_level; #define APPL_TRACE_EVENT(fmt, args...) #define APPL_TRACE_DEBUG(fmt, args...) #define APPL_TRACE_VERBOSE(fmt, args...) + +/* define traces for BTC */ +#define BTC_TRACE_ERROR(fmt, args...) +#define BTC_TRACE_WARNING(fmt, args...) +#define BTC_TRACE_API(fmt, args...) +#define BTC_TRACE_EVENT(fmt, args...) +#define BTC_TRACE_DEBUG(fmt, args...) +#define BTC_TRACE_VERBOSE(fmt, args...) + +/* define traces for OSI */ +#define OSI_TRACE_ERROR(fmt, args...) +#define OSI_TRACE_WARNING(fmt, args...) +#define OSI_TRACE_API(fmt, args...) +#define OSI_TRACE_EVENT(fmt, args...) +#define OSI_TRACE_DEBUG(fmt, args...) +#define OSI_TRACE_VERBOSE(fmt, args...) + +/* define traces for BLUFI */ +#define BLUFI_TRACE_ERROR(fmt, args...) +#define BLUFI_TRACE_WARNING(fmt, args...) +#define BLUFI_TRACE_API(fmt, args...) +#define BLUFI_TRACE_EVENT(fmt, args...) +#define BLUFI_TRACE_DEBUG(fmt, args...) +#define BLUFI_TRACE_VERBOSE(fmt, args...) #endif ///CONFIG_BT_STACK_NO_LOG @@ -579,25 +702,25 @@ extern UINT8 btif_trace_level; #define bdld(fmt, args...) \ do{\ if((MY_LOG_LEVEL) >= BT_TRACE_LEVEL_DEBUG) \ - BT_PRINTF(fmt, ## args); \ + BT_PRINT_D(fmt, ## args); \ }while(0) #define bdlw(fmt, args...) \ do{\ - if((MY_LOG_LEVEL) >= BT_TRACE_LEVEL_DEBUG) \ - BT_PRINTF(fmt, ## args); \ + if((MY_LOG_LEVEL) >= BT_TRACE_LEVEL_WARNING) \ + BT_PRINT_W(fmt, ## args); \ }while(0) #define bdle(fmt, args...) \ do{\ - if((MY_LOG_LEVEL) >= BT_TRACE_LEVEL_DEBUG) \ - BT_PRINTF(fmt, ## args); \ + if((MY_LOG_LEVEL) >= BT_TRACE_LEVEL_ERROR) \ + BT_PRINT_E(fmt, ## args); \ }while(0) #define bdla(assert_if) \ do{\ if(((MY_LOG_LEVEL) >= BT_TRACE_LEVEL_ERROR) && !(assert_if)) \ - BT_PRINTF("%s: assert failed\n", #assert_if); \ + BT_PRINT_E("%s: assert failed\n", #assert_if); \ }while(0) typedef UINT8 tBTTRC_PARAM_TYPE; diff --git a/components/bt/bluedroid/hci/hci_hal_h4.c b/components/bt/bluedroid/hci/hci_hal_h4.c index ec700dd15d..8b87a6faa0 100644 --- a/components/bt/bluedroid/hci/hci_hal_h4.c +++ b/components/bt/bluedroid/hci/hci_hal_h4.c @@ -83,7 +83,7 @@ static void hci_hal_env_init( if (hci_hal_env.rx_q) { fixed_queue_register_dequeue(hci_hal_env.rx_q, event_uart_has_bytes); } else { - LOG_ERROR("%s unable to create rx queue.\n", __func__); + HCI_TRACE_ERROR("%s unable to create rx queue.\n", __func__); } return; @@ -135,7 +135,7 @@ static uint16_t transmit_data(serial_data_type_t type, assert(length > 0); if (type < DATA_TYPE_COMMAND || type > DATA_TYPE_SCO) { - LOG_ERROR("%s invalid data type: %d", __func__, type); + HCI_TRACE_ERROR("%s invalid data type: %d", __func__, type); return 0; } @@ -178,7 +178,7 @@ task_post_status_t hci_hal_h4_task_post(task_post_t timeout) evt.par = 0; if (xQueueSend(xHciH4Queue, &evt, timeout) != pdTRUE) { - LOG_ERROR("xHciH4Queue failed\n"); + HCI_TRACE_ERROR("xHciH4Queue failed\n"); return TASK_POST_SUCCESS; } @@ -200,13 +200,13 @@ static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet) if (type == HCI_BLE_EVENT) { uint8_t len = 0; STREAM_TO_UINT8(len, stream); - LOG_ERROR("Workround stream corrupted during LE SCAN: pkt_len=%d ble_event_len=%d\n", + HCI_TRACE_ERROR("Workround stream corrupted during LE SCAN: pkt_len=%d ble_event_len=%d\n", packet->len, len); hci_hal_env.allocator->free(packet); return; } if (type < DATA_TYPE_ACL || type > DATA_TYPE_EVENT) { - LOG_ERROR("%s Unknown HCI message type. Dropping this byte 0x%x," + HCI_TRACE_ERROR("%s Unknown HCI message type. Dropping this byte 0x%x," " min %x, max %x\n", __func__, type, DATA_TYPE_ACL, DATA_TYPE_EVENT); hci_hal_env.allocator->free(packet); @@ -214,7 +214,7 @@ static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet) } hdr_size = preamble_sizes[type - 1]; if (packet->len < hdr_size) { - LOG_ERROR("Wrong packet length type=%d pkt_len=%d hdr_len=%d", + HCI_TRACE_ERROR("Wrong packet length type=%d pkt_len=%d hdr_len=%d", type, packet->len, hdr_size); hci_hal_env.allocator->free(packet); return; @@ -228,7 +228,7 @@ static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet) } if ((length + hdr_size) != packet->len) { - LOG_ERROR("Wrong packet length type=%d hdr_len=%d pd_len=%d " + HCI_TRACE_ERROR("Wrong packet length type=%d hdr_len=%d pd_len=%d " "pkt_len=%d", type, hdr_size, length, packet->len); hci_hal_env.allocator->free(packet); return; @@ -263,7 +263,7 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len) pkt_size = BT_HDR_SIZE + len; pkt = (BT_HDR *)hci_hal_env.allocator->alloc(pkt_size); if (!pkt) { - LOG_ERROR("%s couldn't aquire memory for inbound data buffer.\n", __func__); + HCI_TRACE_ERROR("%s couldn't aquire memory for inbound data buffer.\n", __func__); return -1; } pkt->offset = 0; diff --git a/components/bt/bluedroid/hci/hci_layer.c b/components/bt/bluedroid/hci/hci_layer.c index eaeb59fea4..59b08c4810 100644 --- a/components/bt/bluedroid/hci/hci_layer.c +++ b/components/bt/bluedroid/hci/hci_layer.c @@ -143,7 +143,7 @@ task_post_status_t hci_host_task_post(task_post_t timeout) evt.par = 0; if (xQueueSend(xHciHostQueue, &evt, timeout) != pdTRUE) { - LOG_ERROR("xHciHostQueue failed\n"); + HCI_TRACE_ERROR("xHciHostQueue failed\n"); return TASK_POST_FAIL; } @@ -162,7 +162,7 @@ static int hci_layer_init_env(void) if (hci_host_env.command_queue) { fixed_queue_register_dequeue(hci_host_env.command_queue, event_command_ready); } else { - LOG_ERROR("%s unable to create pending command queue.", __func__); + HCI_TRACE_ERROR("%s unable to create pending command queue.", __func__); return -1; } @@ -170,7 +170,7 @@ static int hci_layer_init_env(void) if (hci_host_env.packet_queue) { fixed_queue_register_dequeue(hci_host_env.packet_queue, event_packet_ready); } else { - LOG_ERROR("%s unable to create pending packet queue.", __func__); + HCI_TRACE_ERROR("%s unable to create pending packet queue.", __func__); return -1; } @@ -179,13 +179,13 @@ static int hci_layer_init_env(void) cmd_wait_q->timer_is_set = false; cmd_wait_q->commands_pending_response = list_new(NULL); if (!cmd_wait_q->commands_pending_response) { - LOG_ERROR("%s unable to create list for commands pending response.", __func__); + HCI_TRACE_ERROR("%s unable to create list for commands pending response.", __func__); return -1; } osi_mutex_new(&cmd_wait_q->commands_pending_response_lock); cmd_wait_q->command_response_timer = osi_alarm_new("cmd_rsp_to", command_timed_out, cmd_wait_q, COMMAND_PENDING_TIMEOUT); if (!cmd_wait_q->command_response_timer) { - LOG_ERROR("%s unable to create command response timer.", __func__); + HCI_TRACE_ERROR("%s unable to create command response timer.", __func__); return -1; } @@ -255,7 +255,7 @@ static void transmit_command( uint8_t *stream; waiting_command_t *wait_entry = osi_calloc(sizeof(waiting_command_t)); if (!wait_entry) { - LOG_ERROR("%s couldn't allocate space for wait entry.", __func__); + HCI_TRACE_ERROR("%s couldn't allocate space for wait entry.", __func__); return; } @@ -269,7 +269,7 @@ static void transmit_command( // Store the command message type in the event field // in case the upper layer didn't already command->event = MSG_STACK_TO_HC_HCI_CMD; - LOG_DEBUG("HCI Enqueue Comamnd opcode=0x%x\n", wait_entry->opcode); + HCI_TRACE_DEBUG("HCI Enqueue Comamnd opcode=0x%x\n", wait_entry->opcode); BTTRC_DUMP_BUFFER(NULL, command->data + command->offset, command->len); fixed_queue_enqueue(hci_host_env.command_queue, wait_entry); @@ -301,7 +301,7 @@ static void transmit_downward(uint16_t type, void *data) { if (type == MSG_STACK_TO_HC_HCI_CMD) { transmit_command((BT_HDR *)data, NULL, NULL, NULL); - LOG_WARN("%s legacy transmit of command. Use transmit_command instead.\n", __func__); + HCI_TRACE_WARNING("%s legacy transmit of command. Use transmit_command instead.\n", __func__); } else { fixed_queue_enqueue(hci_host_env.packet_queue, data); } @@ -398,12 +398,12 @@ static void command_timed_out(void *context) osi_mutex_unlock(&cmd_wait_q->commands_pending_response_lock); if (wait_entry == NULL) { - LOG_ERROR("%s with no commands pending response", __func__); + HCI_TRACE_ERROR("%s with no commands pending response", __func__); } else // We shouldn't try to recover the stack from this command timeout. // If it's caused by a software bug, fix it. If it's a hardware bug, fix it. { - LOG_ERROR("%s hci layer timeout waiting for response to a command. opcode: 0x%x", __func__, wait_entry->opcode); + HCI_TRACE_ERROR("%s hci layer timeout waiting for response to a command. opcode: 0x%x", __func__, wait_entry->opcode); } } @@ -430,7 +430,7 @@ static bool filter_incoming_event(BT_HDR *packet) STREAM_TO_UINT8(event_code, stream); STREAM_SKIP_UINT8(stream); // Skip the parameter total length field - LOG_DEBUG("Receive packet event_code=0x%x\n", event_code); + HCI_TRACE_DEBUG("Receive packet event_code=0x%x\n", event_code); if (event_code == HCI_COMMAND_COMPLETE_EVT) { STREAM_TO_UINT8(hci_host_env.command_credits, stream); @@ -438,7 +438,7 @@ static bool filter_incoming_event(BT_HDR *packet) wait_entry = get_waiting_command(opcode); if (!wait_entry) { - LOG_WARN("%s command complete event with no matching command. opcode: 0x%x.", __func__, opcode); + HCI_TRACE_WARNING("%s command complete event with no matching command. opcode: 0x%x.", __func__, opcode); } else if (wait_entry->complete_callback) { wait_entry->complete_callback(packet, wait_entry->context); } else if (wait_entry->complete_future) { @@ -456,7 +456,7 @@ static bool filter_incoming_event(BT_HDR *packet) wait_entry = get_waiting_command(opcode); if (!wait_entry) { - LOG_WARN("%s command status event with no matching command. opcode: 0x%x", __func__, opcode); + HCI_TRACE_WARNING("%s command status event with no matching command. opcode: 0x%x", __func__, opcode); } else if (wait_entry->status_callback) { wait_entry->status_callback(status, wait_entry->command, wait_entry->context); } @@ -516,7 +516,7 @@ static serial_data_type_t event_to_data_type(uint16_t event) } else if (event == MSG_STACK_TO_HC_HCI_CMD) { return DATA_TYPE_COMMAND; } else { - LOG_ERROR("%s invalid event type, could not translate 0x%x\n", __func__, event); + HCI_TRACE_ERROR("%s invalid event type, could not translate 0x%x\n", __func__, event); } return 0; diff --git a/components/bt/bluedroid/hci/hci_packet_parser.c b/components/bt/bluedroid/hci/hci_packet_parser.c index 6866872425..627d1ccb82 100644 --- a/components/bt/bluedroid/hci/hci_packet_parser.c +++ b/components/bt/bluedroid/hci/hci_packet_parser.c @@ -112,7 +112,7 @@ static void parse_read_local_extended_features_response( assert(*page_number_ptr < feature_pages_count); STREAM_TO_ARRAY(feature_pages[*page_number_ptr].as_array, stream, (int)sizeof(bt_device_features_t)); } else { - LOG_ERROR("%s() - WARNING: READING EXTENDED FEATURES FAILED. " + HCI_TRACE_ERROR("%s() - WARNING: READING EXTENDED FEATURES FAILED. " "THIS MAY INDICATE A FIRMWARE/CONTROLLER ISSUE.", __func__); } diff --git a/components/bt/bluedroid/hci/packet_fragmenter.c b/components/bt/bluedroid/hci/packet_fragmenter.c index 8bc593dd20..13c4e48549 100644 --- a/components/bt/bluedroid/hci/packet_fragmenter.c +++ b/components/bt/bluedroid/hci/packet_fragmenter.c @@ -130,7 +130,7 @@ static void fragment_and_dispatch(BT_HDR *packet) static void reassemble_and_dispatch(BT_HDR *packet) { - LOG_DEBUG("reassemble_and_dispatch\n"); + HCI_TRACE_DEBUG("reassemble_and_dispatch\n"); if ((packet->event & MSG_EVT_MASK) == MSG_HC_TO_STACK_HCI_ACL) { uint8_t *stream = packet->data + packet->offset; @@ -151,7 +151,7 @@ static void reassemble_and_dispatch(BT_HDR *packet) if (boundary_flag == START_PACKET_BOUNDARY) { if (partial_packet) { - LOG_WARN("%s found unfinished packet for handle with start packet. Dropping old.\n", __func__); + HCI_TRACE_WARNING("%s found unfinished packet for handle with start packet. Dropping old.\n", __func__); hash_map_erase(partial_packets, (void *)(uintptr_t)handle); buffer_allocator->free(partial_packet); } @@ -159,7 +159,7 @@ static void reassemble_and_dispatch(BT_HDR *packet) uint16_t full_length = l2cap_length + L2CAP_HEADER_SIZE + HCI_ACL_PREAMBLE_SIZE; if (full_length <= packet->len) { if (full_length < packet->len) { - LOG_WARN("%s found l2cap full length %d less than the hci length %d.\n", __func__, l2cap_length, packet->len); + HCI_TRACE_WARNING("%s found l2cap full length %d less than the hci length %d.\n", __func__, l2cap_length, packet->len); } callbacks->reassembled(packet); @@ -183,7 +183,7 @@ static void reassemble_and_dispatch(BT_HDR *packet) buffer_allocator->free(packet); } else { if (!partial_packet) { - LOG_ERROR("%s got continuation for unknown packet. Dropping it.\n", __func__); + HCI_TRACE_ERROR("%s got continuation for unknown packet. Dropping it.\n", __func__); buffer_allocator->free(packet); return; } @@ -192,7 +192,7 @@ static void reassemble_and_dispatch(BT_HDR *packet) packet->len -= HCI_ACL_PREAMBLE_SIZE; uint16_t projected_offset = partial_packet->offset + packet->len; if (projected_offset > partial_packet->len) { // len stores the expected length - LOG_ERROR("%s got packet which would exceed expected length of %d. Truncating.\n", __func__, partial_packet->len); + HCI_TRACE_ERROR("%s got packet which would exceed expected length of %d. Truncating.\n", __func__, partial_packet->len); packet->len = partial_packet->len - partial_packet->offset; projected_offset = partial_packet->len; } diff --git a/components/bt/bluedroid/main/bte_main.c b/components/bt/bluedroid/main/bte_main.c index 2db4fa03da..61c30e2824 100644 --- a/components/bt/bluedroid/main/bte_main.c +++ b/components/bt/bluedroid/main/bte_main.c @@ -77,7 +77,7 @@ int bte_main_boot_entry(bluedroid_init_done_cb_t cb) { hci = hci_layer_get_interface(); if (!hci) { - LOG_ERROR("%s could not get hci layer interface.\n", __func__); + APPL_TRACE_ERROR("%s could not get hci layer interface.\n", __func__); return -2; } @@ -122,9 +122,9 @@ void bte_main_shutdown(void) ******************************************************************************/ static void bte_main_enable(void) { - LOG_DEBUG("Enable HCI\n"); + APPL_TRACE_DEBUG("Enable HCI\n"); if (hci_start_up()) { - LOG_ERROR("Start HCI Host Layer Failure\n"); + APPL_TRACE_ERROR("Start HCI Host Layer Failure\n"); return; } diff --git a/components/bt/bluedroid/osi/alarm.c b/components/bt/bluedroid/osi/alarm.c index f86332191e..5307010590 100644 --- a/components/bt/bluedroid/osi/alarm.c +++ b/components/bt/bluedroid/osi/alarm.c @@ -52,7 +52,7 @@ static osi_alarm_err_t alarm_set(osi_alarm_t *alarm, period_ms_t timeout, bool i int osi_alarm_create_mux(void) { if (alarm_state != ALARM_STATE_IDLE) { - LOG_WARN("%s, invalid state %d\n", __func__, alarm_state); + OSI_TRACE_WARNING("%s, invalid state %d\n", __func__, alarm_state); return -1; } osi_mutex_new(&alarm_mutex); @@ -62,7 +62,7 @@ int osi_alarm_create_mux(void) int osi_alarm_delete_mux(void) { if (alarm_state != ALARM_STATE_IDLE) { - LOG_WARN("%s, invalid state %d\n", __func__, alarm_state); + OSI_TRACE_WARNING("%s, invalid state %d\n", __func__, alarm_state); return -1; } osi_mutex_free(&alarm_mutex); @@ -75,7 +75,7 @@ void osi_alarm_init(void) osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT); if (alarm_state != ALARM_STATE_IDLE) { - LOG_WARN("%s, invalid state %d\n", __func__, alarm_state); + OSI_TRACE_WARNING("%s, invalid state %d\n", __func__, alarm_state); goto end; } memset(alarm_cbs, 0x00, sizeof(alarm_cbs)); @@ -91,7 +91,7 @@ void osi_alarm_deinit(void) osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT); if (alarm_state != ALARM_STATE_OPEN) { - LOG_WARN("%s, invalid state %d\n", __func__, alarm_state); + OSI_TRACE_WARNING("%s, invalid state %d\n", __func__, alarm_state); goto end; } @@ -112,7 +112,7 @@ static struct alarm_t *alarm_cbs_lookfor_available(void) for (i = 0; i < ALARM_CBS_NUM; i++) { if (alarm_cbs[i].alarm_hdl == NULL) { //available - LOG_DEBUG("%s %d %p\n", __func__, i, &alarm_cbs[i]); + OSI_TRACE_DEBUG("%s %d %p\n", __func__, i, &alarm_cbs[i]); return &alarm_cbs[i]; } } @@ -122,9 +122,9 @@ static struct alarm_t *alarm_cbs_lookfor_available(void) static void alarm_cb_handler(struct alarm_t *alarm) { - LOG_DEBUG("TimerID %p\n", alarm); + OSI_TRACE_DEBUG("TimerID %p\n", alarm); if (alarm_state != ALARM_STATE_OPEN) { - LOG_WARN("%s, invalid state %d\n", __func__, alarm_state); + OSI_TRACE_WARNING("%s, invalid state %d\n", __func__, alarm_state); return; } btc_msg_t msg; @@ -144,7 +144,7 @@ osi_alarm_t *osi_alarm_new(const char *alarm_name, osi_alarm_callback_t callback osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT); if (alarm_state != ALARM_STATE_OPEN) { - LOG_ERROR("%s, invalid state %d\n", __func__, alarm_state); + OSI_TRACE_ERROR("%s, invalid state %d\n", __func__, alarm_state); timer_id = NULL; goto end; } @@ -152,7 +152,7 @@ osi_alarm_t *osi_alarm_new(const char *alarm_name, osi_alarm_callback_t callback timer_id = alarm_cbs_lookfor_available(); if (!timer_id) { - LOG_ERROR("%s alarm_cbs exhausted\n", __func__); + OSI_TRACE_ERROR("%s alarm_cbs exhausted\n", __func__); timer_id = NULL; goto end; } @@ -169,7 +169,7 @@ osi_alarm_t *osi_alarm_new(const char *alarm_name, osi_alarm_callback_t callback esp_err_t stat = esp_timer_create(&tca, &timer_id->alarm_hdl); if (stat != ESP_OK) { - LOG_ERROR("%s failed to create timer, err 0x%x\n", __func__, stat); + OSI_TRACE_ERROR("%s failed to create timer, err 0x%x\n", __func__, stat); timer_id = NULL; goto end; } @@ -182,13 +182,13 @@ end: static osi_alarm_err_t alarm_free(osi_alarm_t *alarm) { if (!alarm || alarm->alarm_hdl == NULL) { - LOG_ERROR("%s null\n", __func__); + OSI_TRACE_ERROR("%s null\n", __func__); return OSI_ALARM_ERR_INVALID_ARG; } esp_timer_stop(alarm->alarm_hdl); esp_err_t stat = esp_timer_delete(alarm->alarm_hdl); if (stat != ESP_OK) { - LOG_ERROR("%s failed to delete timer, err 0x%x\n", __func__, stat); + OSI_TRACE_ERROR("%s failed to delete timer, err 0x%x\n", __func__, stat); return OSI_ALARM_ERR_FAIL; } @@ -202,7 +202,7 @@ void osi_alarm_free(osi_alarm_t *alarm) osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT); if (alarm_state != ALARM_STATE_OPEN) { - LOG_ERROR("%s, invalid state %d\n", __func__, alarm_state); + OSI_TRACE_ERROR("%s, invalid state %d\n", __func__, alarm_state); goto end; } alarm_free(alarm); @@ -219,13 +219,13 @@ static osi_alarm_err_t alarm_set(osi_alarm_t *alarm, period_ms_t timeout, bool i osi_alarm_err_t ret = OSI_ALARM_ERR_PASS; osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT); if (alarm_state != ALARM_STATE_OPEN) { - LOG_ERROR("%s, invalid state %d\n", __func__, alarm_state); + OSI_TRACE_ERROR("%s, invalid state %d\n", __func__, alarm_state); ret = OSI_ALARM_ERR_INVALID_STATE; goto end; } if (!alarm || alarm->alarm_hdl == NULL) { - LOG_ERROR("%s null\n", __func__); + OSI_TRACE_ERROR("%s null\n", __func__); ret = OSI_ALARM_ERR_INVALID_ARG; goto end; } @@ -238,7 +238,7 @@ static osi_alarm_err_t alarm_set(osi_alarm_t *alarm, period_ms_t timeout, bool i stat = esp_timer_start_once(alarm->alarm_hdl, (uint64_t)timeout_us); } if (stat != ESP_OK) { - LOG_ERROR("%s failed to start timer, err 0x%x\n", __func__, stat); + OSI_TRACE_ERROR("%s failed to start timer, err 0x%x\n", __func__, stat); ret = OSI_ALARM_ERR_FAIL; goto end; } @@ -264,20 +264,20 @@ osi_alarm_err_t osi_alarm_cancel(osi_alarm_t *alarm) int ret = OSI_ALARM_ERR_PASS; osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT); if (alarm_state != ALARM_STATE_OPEN) { - LOG_ERROR("%s, invalid state %d\n", __func__, alarm_state); + OSI_TRACE_ERROR("%s, invalid state %d\n", __func__, alarm_state); ret = OSI_ALARM_ERR_INVALID_STATE; goto end; } if (!alarm || alarm->alarm_hdl == NULL) { - LOG_ERROR("%s null\n", __func__); + OSI_TRACE_ERROR("%s null\n", __func__); ret = OSI_ALARM_ERR_INVALID_ARG; goto end; } esp_err_t stat = esp_timer_stop(alarm->alarm_hdl); if (stat != ESP_OK) { - LOG_DEBUG("%s failed to stop timer, err 0x%x\n", __func__, stat); + OSI_TRACE_DEBUG("%s failed to stop timer, err 0x%x\n", __func__, stat); ret = OSI_ALARM_ERR_FAIL; goto end; } diff --git a/components/bt/bluedroid/osi/allocator.c b/components/bt/bluedroid/osi/allocator.c index 113f32becd..2bac1118a1 100644 --- a/components/bt/bluedroid/osi/allocator.c +++ b/components/bt/bluedroid/osi/allocator.c @@ -57,7 +57,7 @@ void osi_mem_dbg_record(void *p, int size, const char *func, int line) int i; if (!p || size == 0) { - LOG_ERROR("%s invalid !!\n", __func__); + OSI_TRACE_ERROR("%s invalid !!\n", __func__); return; } @@ -73,7 +73,7 @@ void osi_mem_dbg_record(void *p, int size, const char *func, int line) } if (i >= OSI_MEM_DBG_INFO_MAX) { - LOG_ERROR("%s full %s %d !!\n", __func__, func, line); + OSI_TRACE_ERROR("%s full %s %d !!\n", __func__, func, line); } } @@ -82,7 +82,7 @@ void osi_mem_dbg_clean(void *p, const char *func, int line) int i; if (!p) { - LOG_ERROR("%s invalid\n", __func__); + OSI_TRACE_ERROR("%s invalid\n", __func__); return; } @@ -98,7 +98,7 @@ void osi_mem_dbg_clean(void *p, const char *func, int line) } if (i >= OSI_MEM_DBG_INFO_MAX) { - LOG_ERROR("%s full %s %d !!\n", __func__, func, line); + OSI_TRACE_ERROR("%s full %s %d !!\n", __func__, func, line); } } @@ -108,10 +108,10 @@ void osi_mem_dbg_show(void) for (i = 0; i < OSI_MEM_DBG_INFO_MAX; i++) { if (mem_dbg_info[i].p || mem_dbg_info[i].size != 0 ) { - LOG_ERROR("--> p %p, s %d, f %s, l %d\n", mem_dbg_info[i].p, mem_dbg_info[i].size, mem_dbg_info[i].func, mem_dbg_info[i].line); + OSI_TRACE_ERROR("--> p %p, s %d, f %s, l %d\n", mem_dbg_info[i].p, mem_dbg_info[i].size, mem_dbg_info[i].func, mem_dbg_info[i].line); } } - LOG_ERROR("--> count %d\n", mem_dbg_count); + OSI_TRACE_ERROR("--> count %d\n", mem_dbg_count); } #endif diff --git a/components/bt/bluedroid/osi/buffer.c b/components/bt/bluedroid/osi/buffer.c index 42732cf977..6b21ed8e28 100644 --- a/components/bt/bluedroid/osi/buffer.c +++ b/components/bt/bluedroid/osi/buffer.c @@ -35,7 +35,7 @@ buffer_t *buffer_new(size_t size) buffer_t *buffer = osi_malloc(sizeof(buffer_t) + size); if (!buffer) { - LOG_ERROR("%s unable to allocate buffer of %zu bytes.", __func__, size); + OSI_TRACE_ERROR("%s unable to allocate buffer of %zu bytes.", __func__, size); return NULL; } @@ -60,7 +60,7 @@ buffer_t *buffer_new_slice(const buffer_t *buf, size_t slice_size) buffer_t *ret = osi_calloc(sizeof(buffer_t)); if (!ret) { - LOG_ERROR("%s unable to allocate new buffer for slice of length %zu.", __func__, slice_size); + OSI_TRACE_ERROR("%s unable to allocate new buffer for slice of length %zu.", __func__, slice_size); return NULL; } diff --git a/components/bt/bluedroid/osi/config.c b/components/bt/bluedroid/osi/config.c index 07f47c6d9d..55e782ca6a 100644 --- a/components/bt/bluedroid/osi/config.c +++ b/components/bt/bluedroid/osi/config.c @@ -62,13 +62,13 @@ config_t *config_new_empty(void) { config_t *config = osi_calloc(sizeof(config_t)); if (!config) { - LOG_ERROR("%s unable to allocate memory for config_t.\n", __func__); + OSI_TRACE_ERROR("%s unable to allocate memory for config_t.\n", __func__); goto error; } config->sections = list_new(section_free); if (!config->sections) { - LOG_ERROR("%s unable to allocate list for sections.\n", __func__); + OSI_TRACE_ERROR("%s unable to allocate list for sections.\n", __func__); goto error; } @@ -93,10 +93,10 @@ config_t *config_new(const char *filename) err = nvs_open(filename, NVS_READWRITE, &fp); if (err != ESP_OK) { if (err == ESP_ERR_NVS_NOT_INITIALIZED) { - LOG_ERROR("%s: NVS not initialized. " + OSI_TRACE_ERROR("%s: NVS not initialized. " "Call nvs_flash_init before initializing bluetooth.", __func__); } else { - LOG_ERROR("%s unable to open NVS namespace '%s'\n", __func__, filename); + OSI_TRACE_ERROR("%s unable to open NVS namespace '%s'\n", __func__, filename); } config_free(config); return NULL; @@ -136,15 +136,15 @@ bool config_has_key(const config_t *config, const char *section, const char *key bool config_has_key_in_section(config_t *config, const char *key, char *key_value) { - LOG_DEBUG("key = %s, value = %s", key, key_value); + OSI_TRACE_DEBUG("key = %s, value = %s", key, key_value); for (const list_node_t *node = list_begin(config->sections); node != list_end(config->sections); node = list_next(node)) { const section_t *section = (const section_t *)list_node(node); for (const list_node_t *node = list_begin(section->entries); node != list_end(section->entries); node = list_next(node)) { entry_t *entry = list_node(node); - LOG_DEBUG("entry->key = %s, entry->value = %s", entry->key, entry->value); + OSI_TRACE_DEBUG("entry->key = %s, entry->value = %s", entry->key, entry->value); if (!strcmp(entry->key, key) && !strcmp(entry->value, key_value)) { - LOG_DEBUG("%s, the irk aready in the flash.", __func__); + OSI_TRACE_DEBUG("%s, the irk aready in the flash.", __func__); return true; } } @@ -338,7 +338,7 @@ static int get_config_size_from_flash(nvs_handle fp) esp_err_t err; char *keyname = osi_calloc(sizeof(CONFIG_KEY) + 1); if (!keyname){ - LOG_ERROR("%s, malloc error\n", __func__); + OSI_TRACE_ERROR("%s, malloc error\n", __func__); return 0; } size_t length = CONFIG_FILE_DEFAULE_LENGTH; @@ -351,7 +351,7 @@ static int get_config_size_from_flash(nvs_handle fp) return 0; } if (err != ESP_OK) { - LOG_ERROR("%s, error %d\n", __func__, err); + OSI_TRACE_ERROR("%s, error %d\n", __func__, err); osi_free(keyname); return 0; } @@ -365,7 +365,7 @@ static int get_config_size_from_flash(nvs_handle fp) break; } if (err != ESP_OK) { - LOG_ERROR("%s, error %d\n", __func__, err); + OSI_TRACE_ERROR("%s, error %d\n", __func__, err); osi_free(keyname); return 0; } @@ -396,7 +396,7 @@ bool config_save(const config_t *config, const char *filename) err = nvs_open(filename, NVS_READWRITE, &fp); if (err != ESP_OK) { if (err == ESP_ERR_NVS_NOT_INITIALIZED) { - LOG_ERROR("%s: NVS not initialized. " + OSI_TRACE_ERROR("%s: NVS not initialized. " "Call nvs_flash_init before initializing bluetooth.", __func__); } err_code |= 0x02; @@ -407,15 +407,15 @@ bool config_save(const config_t *config, const char *filename) for (const list_node_t *node = list_begin(config->sections); node != list_end(config->sections); node = list_next(node)) { const section_t *section = (const section_t *)list_node(node); w_cnt = snprintf(line, 1024, "[%s]\n", section->name); - LOG_DEBUG("section name: %s, w_cnt + w_cnt_total = %d\n", section->name, w_cnt + w_cnt_total); + OSI_TRACE_DEBUG("section name: %s, w_cnt + w_cnt_total = %d\n", section->name, w_cnt + w_cnt_total); memcpy(buf + w_cnt_total, line, w_cnt); w_cnt_total += w_cnt; for (const list_node_t *enode = list_begin(section->entries); enode != list_end(section->entries); enode = list_next(enode)) { const entry_t *entry = (const entry_t *)list_node(enode); - LOG_DEBUG("(key, val): (%s, %s)\n", entry->key, entry->value); + OSI_TRACE_DEBUG("(key, val): (%s, %s)\n", entry->key, entry->value); w_cnt = snprintf(line, 1024, "%s = %s\n", entry->key, entry->value); - LOG_DEBUG("%s, w_cnt + w_cnt_total = %d", __func__, w_cnt + w_cnt_total); + OSI_TRACE_DEBUG("%s, w_cnt + w_cnt_total = %d", __func__, w_cnt + w_cnt_total); memcpy(buf + w_cnt_total, line, w_cnt); w_cnt_total += w_cnt; } @@ -444,10 +444,10 @@ bool config_save(const config_t *config, const char *filename) snprintf(keyname, sizeof(CONFIG_KEY)+1, "%s%d", CONFIG_KEY, i); if (i == count) { err = nvs_set_blob(fp, keyname, buf + i*CONFIG_FILE_MAX_SIZE, w_cnt_total - i*CONFIG_FILE_MAX_SIZE); - LOG_DEBUG("save keyname = %s, i = %d, %d\n", keyname, i, w_cnt_total - i*CONFIG_FILE_MAX_SIZE); + OSI_TRACE_DEBUG("save keyname = %s, i = %d, %d\n", keyname, i, w_cnt_total - i*CONFIG_FILE_MAX_SIZE); }else { err = nvs_set_blob(fp, keyname, buf + i*CONFIG_FILE_MAX_SIZE, CONFIG_FILE_MAX_SIZE); - LOG_DEBUG("save keyname = %s, i = %d, %d\n", keyname, i, CONFIG_FILE_MAX_SIZE); + OSI_TRACE_DEBUG("save keyname = %s, i = %d, %d\n", keyname, i, CONFIG_FILE_MAX_SIZE); } if (err != ESP_OK) { nvs_close(fp); @@ -481,7 +481,7 @@ error: osi_free(keyname); } if (err_code) { - LOG_ERROR("%s, err_code: 0x%x\n", __func__, err_code); + OSI_TRACE_ERROR("%s, err_code: 0x%x\n", __func__, err_code); } return false; } @@ -558,7 +558,7 @@ static void config_parse(nvs_handle fp, config_t *config) // get one line int line_len = p_line_end - p_line_bgn; if (line_len > 1023) { - LOG_WARN("%s exceed max line length on line %d.\n", __func__, line_num); + OSI_TRACE_WARNING("%s exceed max line length on line %d.\n", __func__, line_num); break; } memcpy(line, p_line_bgn, line_len); @@ -575,7 +575,7 @@ static void config_parse(nvs_handle fp, config_t *config) if (*line_ptr == '[') { size_t len = strlen(line_ptr); if (line_ptr[len - 1] != ']') { - LOG_WARN("%s unterminated section name on line %d.\n", __func__, line_num); + OSI_TRACE_WARNING("%s unterminated section name on line %d.\n", __func__, line_num); continue; } strncpy(section, line_ptr + 1, len - 2); @@ -583,7 +583,7 @@ static void config_parse(nvs_handle fp, config_t *config) } else { char *split = strchr(line_ptr, '='); if (!split) { - LOG_DEBUG("%s no key/value separator found on line %d.\n", __func__, line_num); + OSI_TRACE_DEBUG("%s no key/value separator found on line %d.\n", __func__, line_num); continue; } *split = '\0'; @@ -605,7 +605,7 @@ error: osi_free(keyname); } if (err_code) { - LOG_ERROR("%s returned with err code: %d\n", __func__, err_code); + OSI_TRACE_ERROR("%s returned with err code: %d\n", __func__, err_code); } } diff --git a/components/bt/bluedroid/osi/future.c b/components/bt/bluedroid/osi/future.c index 835ccbcff1..25eb5605e6 100644 --- a/components/bt/bluedroid/osi/future.c +++ b/components/bt/bluedroid/osi/future.c @@ -28,12 +28,12 @@ future_t *future_new(void) { future_t *ret = osi_calloc(sizeof(future_t)); if (!ret) { - LOG_ERROR("%s unable to allocate memory for return value.", __func__); + OSI_TRACE_ERROR("%s unable to allocate memory for return value.", __func__); goto error; } if (osi_sem_new(&ret->semaphore, 1, 0) != 0) { - LOG_ERROR("%s unable to allocate memory for the semaphore.", __func__); + OSI_TRACE_ERROR("%s unable to allocate memory for the semaphore.", __func__); goto error; } @@ -48,7 +48,7 @@ future_t *future_new_immediate(void *value) { future_t *ret = osi_calloc(sizeof(future_t)); if (!ret) { - LOG_ERROR("%s unable to allocate memory for return value.", __func__); + OSI_TRACE_ERROR("%s unable to allocate memory for return value.", __func__); goto error; } diff --git a/components/bt/bluedroid/stack/btm/btm_ble_gap.c b/components/bt/bluedroid/stack/btm/btm_ble_gap.c index bb4ec9fd8d..35ae79dfc3 100644 --- a/components/bt/bluedroid/stack/btm/btm_ble_gap.c +++ b/components/bt/bluedroid/stack/btm/btm_ble_gap.c @@ -1812,14 +1812,14 @@ UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst, } else { cp_len = p_data->p_manu->len; } - LOG_DEBUG("cp_len = %d\n,p_data->p_manu->len=%d\n", cp_len, p_data->p_manu->len); + BTM_TRACE_DEBUG("cp_len = %d\n,p_data->p_manu->len=%d\n", cp_len, p_data->p_manu->len); for (int i = 0; i < p_data->p_manu->len; i++) { - LOG_DEBUG("p_data->p_manu->p_val[%d] = %x\n", i, p_data->p_manu->p_val[i]); + BTM_TRACE_DEBUG("p_data->p_manu->p_val[%d] = %x\n", i, p_data->p_manu->p_val[i]); } *p++ = cp_len + 1; *p++ = BTM_BLE_AD_TYPE_MANU; ARRAY_TO_STREAM(p, p_data->p_manu->p_val, cp_len); - LOG_DEBUG("p_addr = %p\n,p_data->p_manu->p_val = %p\n", p, p_data->p_manu->p_val); + BTM_TRACE_DEBUG("p_addr = %p\n,p_data->p_manu->p_val = %p\n", p, p_data->p_manu->p_val); len -= (cp_len + MIN_ADV_LENGTH); data_mask &= ~BTM_BLE_AD_BIT_MANU; } @@ -2085,7 +2085,7 @@ void btm_ble_set_adv_flag(UINT16 connect_mode, UINT16 disc_mode) btm_ble_update_dmt_flag_bits (&flag, connect_mode, disc_mode); - LOG_DEBUG("disc_mode %04x", disc_mode); + BTM_TRACE_DEBUG("disc_mode %04x", disc_mode); /* update discoverable flag */ if (disc_mode & BTM_BLE_LIMITED_DISCOVERABLE) { flag &= ~BTM_BLE_GEN_DISC_FLAG; @@ -2098,7 +2098,7 @@ void btm_ble_set_adv_flag(UINT16 connect_mode, UINT16 disc_mode) } if (flag != old_flag) { - LOG_ERROR("flag = 0x%x,old_flag = 0x%x", flag, old_flag); + BTM_TRACE_ERROR("flag = 0x%x,old_flag = 0x%x", flag, old_flag); btm_ble_update_adv_flag(flag); } } @@ -3164,7 +3164,7 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt } if ((result = btm_ble_is_discoverable(bda, evt_type, p)) == 0) { - LOG_WARN("%s device is no longer discoverable so discarding advertising packet pkt", + BTM_TRACE_WARNING("%s device is no longer discoverable so discarding advertising packet pkt", __func__); return; } diff --git a/components/bt/bluedroid/stack/btm/btm_pm.c b/components/bt/bluedroid/stack/btm/btm_pm.c index 758be72b8e..7c3629ca4b 100644 --- a/components/bt/bluedroid/stack/btm/btm_pm.c +++ b/components/bt/bluedroid/stack/btm/btm_pm.c @@ -606,7 +606,7 @@ static tBTM_STATUS btm_pm_snd_md_req(UINT8 pm_id, int link_ind, tBTM_PM_PWR_MD * BTM_TRACE_DEBUG("btm_pm_snd_md_req state:0x%x, link_ind: %d", p_cb->state, link_ind); #endif // BTM_PM_DEBUG - LOG_DEBUG("%s switching from %s to %s.", __func__, mode_to_string(p_cb->state), mode_to_string(md_res.mode)); + BTM_TRACE_DEBUG("%s switching from %s to %s.", __func__, mode_to_string(p_cb->state), mode_to_string(md_res.mode)); switch (md_res.mode) { case BTM_PM_MD_ACTIVE: switch (p_cb->state) { @@ -772,7 +772,7 @@ void btm_pm_proc_mode_change (UINT8 hci_status, UINT16 hci_handle, UINT8 mode, U p_cb->state = mode; p_cb->interval = interval; - LOG_DEBUG("%s switched from %s to %s.", __func__, mode_to_string(old_state), mode_to_string(p_cb->state)); + BTM_TRACE_DEBUG("%s switched from %s to %s.", __func__, mode_to_string(old_state), mode_to_string(p_cb->state)); if ((p_lcb = l2cu_find_lcb_by_bd_addr(p->remote_addr, BT_TRANSPORT_BR_EDR)) != NULL) { if ((p_cb->state == BTM_PM_ST_ACTIVE) || (p_cb->state == BTM_PM_ST_SNIFF)) { diff --git a/components/bt/bluedroid/stack/btm/btm_sec.c b/components/bt/bluedroid/stack/btm/btm_sec.c index 00923e9f80..0cfa5f70de 100644 --- a/components/bt/bluedroid/stack/btm/btm_sec.c +++ b/components/bt/bluedroid/stack/btm/btm_sec.c @@ -231,7 +231,7 @@ BOOLEAN BTM_SecRegister(tBTM_APPL_INFO *p_cb_info) BTM_TRACE_EVENT("%s application registered\n", __func__); #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE - LOG_DEBUG("%s p_cb_info->p_le_callback == 0x%p\n", __func__, p_cb_info->p_le_callback); + BTM_TRACE_DEBUG("%s p_cb_info->p_le_callback == 0x%p\n", __func__, p_cb_info->p_le_callback); if (p_cb_info->p_le_callback) { BTM_TRACE_EVENT("%s SMP_Register( btm_proc_smp_cback )\n", __func__); SMP_Register(btm_proc_smp_cback); @@ -240,13 +240,13 @@ BOOLEAN BTM_SecRegister(tBTM_APPL_INFO *p_cb_info) btm_ble_reset_id(); } } else { - LOG_WARN("%s p_cb_info->p_le_callback == NULL\n", __func__); + BTM_TRACE_WARNING("%s p_cb_info->p_le_callback == NULL\n", __func__); } #endif btm_cb.api = *p_cb_info; #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE - LOG_DEBUG("%s btm_cb.api.p_le_callback = 0x%p\n", __func__, btm_cb.api.p_le_callback); + BTM_TRACE_DEBUG("%s btm_cb.api.p_le_callback = 0x%p\n", __func__, btm_cb.api.p_le_callback); #endif BTM_TRACE_EVENT("%s application registered\n", __func__); return (TRUE); @@ -2325,7 +2325,7 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle 2046 may report HCI_Encryption_Change and L2C Connection Request out of sequence because of data path issues. Delay this disconnect a little bit */ - LOG_INFO("%s peer should have initiated security process by now (SM4 to SM4)\n", __func__); + BTM_TRACE_API("%s peer should have initiated security process by now (SM4 to SM4)\n", __func__); p_dev_rec->p_callback = p_callback; p_dev_rec->sec_state = BTM_SEC_STATE_DELAY_FOR_ENC; (*p_callback) (bd_addr, transport, p_ref_data, rc); diff --git a/components/bt/bluedroid/stack/btu/btu_hcif.c b/components/bt/bluedroid/stack/btu/btu_hcif.c index 788cd41336..f0d50ed42b 100644 --- a/components/bt/bluedroid/stack/btu/btu_hcif.c +++ b/components/bt/bluedroid/stack/btu/btu_hcif.c @@ -1000,7 +1000,7 @@ static void btu_hcif_command_complete_evt(BT_HDR *response, void *context) BT_HDR *event = osi_calloc(sizeof(BT_HDR) + sizeof(command_complete_hack_t)); command_complete_hack_t *hack = (command_complete_hack_t *)&event->data[0]; - LOG_DEBUG("btu_hcif_command_complete_evt\n"); + HCI_TRACE_DEBUG("btu_hcif_command_complete_evt\n"); hack->callback = btu_hcif_command_complete_evt_on_task; hack->response = response; diff --git a/components/bt/bluedroid/stack/btu/btu_task.c b/components/bt/bluedroid/stack/btu/btu_task.c index af121c7050..5d6b82a0f7 100644 --- a/components/bt/bluedroid/stack/btu/btu_task.c +++ b/components/bt/bluedroid/stack/btu/btu_task.c @@ -256,7 +256,7 @@ void btu_task_thread_handler(void *arg) } default: // FAIL - LOG_ERROR("Received unexpected oneshot timer event:0x%x\n", p_tle->event); + HCI_TRACE_ERROR("Received unexpected oneshot timer event:0x%x\n", p_tle->event); break; } break; @@ -280,7 +280,7 @@ task_post_status_t btu_task_post(uint32_t sig, void *param, task_post_t timeout) evt.par = param; if (xQueueSend(xBtuQueue, &evt, timeout) != pdTRUE) { - LOG_ERROR("xBtuQueue failed\n"); + HCI_TRACE_ERROR("xBtuQueue failed\n"); return TASK_POST_FAIL; } @@ -462,7 +462,7 @@ void btu_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_sec) alarm = hash_map_get(btu_general_alarm_hash_map, p_tle); if (alarm == NULL) { - LOG_ERROR("%s Unable to create alarm", __func__); + HCI_TRACE_ERROR("%s Unable to create alarm", __func__); return; } osi_alarm_cancel(alarm); @@ -496,7 +496,7 @@ void btu_stop_timer(TIMER_LIST_ENT *p_tle) // Get the alarm for the timer list entry. osi_alarm_t *alarm = hash_map_get(btu_general_alarm_hash_map, p_tle); if (alarm == NULL) { - LOG_WARN("%s Unable to find expected alarm in hashmap", __func__); + HCI_TRACE_WARNING("%s Unable to find expected alarm in hashmap", __func__); return; } osi_alarm_cancel(alarm); @@ -520,7 +520,7 @@ void btu_free_timer(TIMER_LIST_ENT *p_tle) // Get the alarm for the timer list entry. osi_alarm_t *alarm = hash_map_get(btu_general_alarm_hash_map, p_tle); if (alarm == NULL) { - LOG_DEBUG("%s Unable to find expected alarm in hashmap", __func__); + HCI_TRACE_DEBUG("%s Unable to find expected alarm in hashmap", __func__); return; } osi_alarm_cancel(alarm); @@ -576,7 +576,7 @@ void btu_start_quick_timer(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_ti alarm = hash_map_get(btu_l2cap_alarm_hash_map, p_tle); if (alarm == NULL) { - LOG_ERROR("%s Unable to create alarm", __func__); + HCI_TRACE_ERROR("%s Unable to create alarm", __func__); return; } osi_alarm_cancel(alarm); @@ -609,7 +609,7 @@ void btu_stop_quick_timer(TIMER_LIST_ENT *p_tle) // Get the alarm for the timer list entry. osi_alarm_t *alarm = hash_map_get(btu_l2cap_alarm_hash_map, p_tle); if (alarm == NULL) { - LOG_WARN("%s Unable to find expected alarm in hashmap", __func__); + HCI_TRACE_WARNING("%s Unable to find expected alarm in hashmap", __func__); return; } osi_alarm_cancel(alarm); @@ -624,7 +624,7 @@ void btu_free_quick_timer(TIMER_LIST_ENT *p_tle) // Get the alarm for the timer list entry. osi_alarm_t *alarm = hash_map_get(btu_l2cap_alarm_hash_map, p_tle); if (alarm == NULL) { - LOG_DEBUG("%s Unable to find expected alarm in hashmap", __func__); + HCI_TRACE_DEBUG("%s Unable to find expected alarm in hashmap", __func__); return; } osi_alarm_cancel(alarm); @@ -662,7 +662,7 @@ void btu_start_timer_oneshot(TIMER_LIST_ENT *p_tle, UINT16 type, UINT32 timeout_ alarm = hash_map_get(btu_oneshot_alarm_hash_map, p_tle); if (alarm == NULL) { - LOG_ERROR("%s Unable to create alarm", __func__); + HCI_TRACE_ERROR("%s Unable to create alarm", __func__); return; } osi_alarm_cancel(alarm); @@ -686,7 +686,7 @@ void btu_stop_timer_oneshot(TIMER_LIST_ENT *p_tle) // Get the alarm for the timer list entry. osi_alarm_t *alarm = hash_map_get(btu_oneshot_alarm_hash_map, p_tle); if (alarm == NULL) { - LOG_WARN("%s Unable to find expected alarm in hashmap", __func__); + HCI_TRACE_WARNING("%s Unable to find expected alarm in hashmap", __func__); return; } osi_alarm_cancel(alarm); diff --git a/components/bt/bluedroid/stack/gatt/gatt_sr.c b/components/bt/bluedroid/stack/gatt/gatt_sr.c index b0036320b5..697540d4c1 100644 --- a/components/bt/bluedroid/stack/gatt/gatt_sr.c +++ b/components/bt/bluedroid/stack/gatt/gatt_sr.c @@ -1260,7 +1260,7 @@ void gatt_attr_process_prepare_write (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 hand is_need_prepare_write_rsp = TRUE; is_need_queue_data = TRUE; } else if (p_attr->p_value == NULL) { - LOG_ERROR("Error in %s, attribute of handle 0x%x not allocate value buffer\n", + GATT_TRACE_ERROR("Error in %s, attribute of handle 0x%x not allocate value buffer\n", __func__, handle); status = GATT_UNKNOWN_ERROR; } else { @@ -1306,11 +1306,11 @@ void gatt_attr_process_prepare_write (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 hand gatt_dequeue_sr_cmd(p_tcb); if (rsp_send_status != GATT_SUCCESS){ - LOG_ERROR("Error in %s, line=%d, fail to send prepare_write_rsp, status=0x%x\n", + GATT_TRACE_ERROR("Error in %s, line=%d, fail to send prepare_write_rsp, status=0x%x\n", __func__, __LINE__, rsp_send_status); } } else{ - LOG_ERROR("Error in %s, line=%d, queue_data should not be NULL here, fail to send prepare_write_rsp\n", + GATT_TRACE_ERROR("Error in %s, line=%d, queue_data should not be NULL here, fail to send prepare_write_rsp\n", __func__, __LINE__); } } diff --git a/components/bt/bluedroid/stack/hcic/hciblecmds.c b/components/bt/bluedroid/stack/hcic/hciblecmds.c index 634cb04521..89d4fd94c8 100644 --- a/components/bt/bluedroid/stack/hcic/hciblecmds.c +++ b/components/bt/bluedroid/stack/hcic/hciblecmds.c @@ -140,7 +140,7 @@ BOOLEAN btsnd_hcic_ble_set_adv_data (UINT8 data_len, UINT8 *p_data) UINT8 *pp; for (int i = 0; i < data_len; i++) { - LOG_DEBUG("p_data[%d] = %x\n", i, p_data[i]); + HCI_TRACE_DEBUG("p_data[%d] = %x\n", i, p_data[i]); } if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA + 1)) == NULL) { diff --git a/components/bt/bluedroid/stack/l2cap/l2c_api.c b/components/bt/bluedroid/stack/l2cap/l2c_api.c index 3c7745af98..654a4df632 100644 --- a/components/bt/bluedroid/stack/l2cap/l2c_api.c +++ b/components/bt/bluedroid/stack/l2cap/l2c_api.c @@ -327,7 +327,7 @@ bool L2CA_SetConnectionCallbacks(uint16_t local_cid, const tL2CAP_APPL_INFO *cal tL2C_CCB *channel_control_block = l2cu_find_ccb_by_cid(NULL, local_cid); if (!channel_control_block) { - LOG_ERROR("%s no channel control block found for L2CAP LCID=0x%04x.", __func__, local_cid); + L2CAP_TRACE_ERROR("%s no channel control block found for L2CAP LCID=0x%04x.", __func__, local_cid); return false; } @@ -339,7 +339,7 @@ bool L2CA_SetConnectionCallbacks(uint16_t local_cid, const tL2CAP_APPL_INFO *cal if (!channel_control_block->should_free_rcb) { registration_control_block = (tL2C_RCB *)osi_calloc(sizeof(tL2C_RCB)); if (!registration_control_block) { - LOG_ERROR("%s unable to allocate registration control block.", __func__); + L2CAP_TRACE_ERROR("%s unable to allocate registration control block.", __func__); return false; } diff --git a/components/bt/bluedroid/stack/l2cap/l2c_main.c b/components/bt/bluedroid/stack/l2cap/l2c_main.c index 9990db077b..c9f4c4d3b2 100644 --- a/components/bt/bluedroid/stack/l2cap/l2c_main.c +++ b/components/bt/bluedroid/stack/l2cap/l2c_main.c @@ -870,7 +870,7 @@ void l2c_init (void) l2cb.rcv_pending_q = list_new(NULL); if (l2cb.rcv_pending_q == NULL) { - LOG_ERROR("%s unable to allocate memory for link layer control block", __func__); + L2CAP_TRACE_ERROR("%s unable to allocate memory for link layer control block", __func__); } } diff --git a/components/bt/bluedroid/stack/l2cap/l2cap_client.c b/components/bt/bluedroid/stack/l2cap/l2cap_client.c index 002ed6b809..c7314b62ff 100644 --- a/components/bt/bluedroid/stack/l2cap/l2cap_client.c +++ b/components/bt/bluedroid/stack/l2cap/l2cap_client.c @@ -91,14 +91,14 @@ l2cap_client_t *l2cap_client_new(const l2cap_client_callbacks_t *callbacks, void if (!l2cap_clients) { l2cap_clients = list_new(NULL); if (!l2cap_clients) { - LOG_ERROR("%s unable to allocate space for L2CAP client list.", __func__); + L2CAP_TRACE_ERROR("%s unable to allocate space for L2CAP client list.", __func__); return NULL; } } l2cap_client_t *ret = (l2cap_client_t *)osi_calloc(sizeof(l2cap_client_t)); if (!ret) { - LOG_ERROR("%s unable to allocate L2CAP client.", __func__); + L2CAP_TRACE_ERROR("%s unable to allocate L2CAP client.", __func__); goto error; } @@ -108,7 +108,7 @@ l2cap_client_t *l2cap_client_new(const l2cap_client_callbacks_t *callbacks, void ret->remote_mtu = L2CAP_MTU_DEFAULT; ret->outbound_fragments = list_new(NULL); if (!ret) { - LOG_ERROR("%s unable to allocate outbound L2CAP fragment list.", __func__); + L2CAP_TRACE_ERROR("%s unable to allocate outbound L2CAP fragment list.", __func__); goto error; } @@ -146,7 +146,7 @@ bool l2cap_client_connect(l2cap_client_t *client, const bt_bdaddr_t *remote_bdad client->local_channel_id = L2CA_ConnectReq(psm, (uint8_t *)remote_bdaddr); if (!client->local_channel_id) { - LOG_ERROR("%s unable to create L2CAP connection.", __func__); + L2CAP_TRACE_ERROR("%s unable to create L2CAP connection.", __func__); return false; } @@ -159,7 +159,7 @@ void l2cap_client_disconnect(l2cap_client_t *client) assert(client != NULL); if (client->local_channel_id && !L2CA_DisconnectReq(client->local_channel_id)) { - LOG_ERROR("%s unable to send disconnect message for LCID 0x%04x.", __func__, client->local_channel_id); + L2CAP_TRACE_ERROR("%s unable to send disconnect message for LCID 0x%04x.", __func__, client->local_channel_id); } client->local_channel_id = 0; @@ -203,12 +203,12 @@ static void connect_completed_cb(uint16_t local_channel_id, uint16_t error_code) l2cap_client_t *client = find(local_channel_id); if (!client) { - LOG_ERROR("%s unable to find L2CAP client for LCID 0x%04x.", __func__, local_channel_id); + L2CAP_TRACE_ERROR("%s unable to find L2CAP client for LCID 0x%04x.", __func__, local_channel_id); return; } if (error_code != L2CAP_CONN_OK) { - LOG_ERROR("%s error connecting L2CAP channel: %d.", __func__, error_code); + L2CAP_TRACE_ERROR("%s error connecting L2CAP channel: %d.", __func__, error_code); client->callbacks.disconnected(client, client->context); return; } @@ -216,7 +216,7 @@ static void connect_completed_cb(uint16_t local_channel_id, uint16_t error_code) // Use default L2CAP parameters. tL2CAP_CFG_INFO desired_parameters = { 0 }; if (!L2CA_ConfigReq(local_channel_id, &desired_parameters)) { - LOG_ERROR("%s error sending L2CAP config parameters.", __func__); + L2CAP_TRACE_ERROR("%s error sending L2CAP config parameters.", __func__); client->callbacks.disconnected(client, client->context); } } @@ -227,7 +227,7 @@ static void config_request_cb(uint16_t local_channel_id, tL2CAP_CFG_INFO *reques l2cap_client_t *client = find(local_channel_id); if (!client) { - LOG_ERROR("%s unable to find L2CAP client matching LCID 0x%04x.", __func__, local_channel_id); + L2CAP_TRACE_ERROR("%s unable to find L2CAP client matching LCID 0x%04x.", __func__, local_channel_id); return; } @@ -255,7 +255,7 @@ static void config_request_cb(uint16_t local_channel_id, tL2CAP_CFG_INFO *reques } if (!L2CA_ConfigRsp(local_channel_id, &response)) { - LOG_ERROR("%s unable to send config response for LCID 0x%04x.", __func__, local_channel_id); + L2CAP_TRACE_ERROR("%s unable to send config response for LCID 0x%04x.", __func__, local_channel_id); l2cap_client_disconnect(client); return; } @@ -272,7 +272,7 @@ static void config_completed_cb(uint16_t local_channel_id, tL2CAP_CFG_INFO *nego l2cap_client_t *client = find(local_channel_id); if (!client) { - LOG_ERROR("%s unable to find L2CAP client matching LCID 0x%04x.", __func__, local_channel_id); + L2CAP_TRACE_ERROR("%s unable to find L2CAP client matching LCID 0x%04x.", __func__, local_channel_id); return; } @@ -283,7 +283,7 @@ static void config_completed_cb(uint16_t local_channel_id, tL2CAP_CFG_INFO *nego case L2CAP_CFG_UNACCEPTABLE_PARAMS: // TODO: see if we can renegotiate parameters instead of dropping the connection. - LOG_WARN("%s dropping L2CAP connection due to unacceptable config parameters.\n", __func__); + L2CAP_TRACE_WARNING("%s dropping L2CAP connection due to unacceptable config parameters.\n", __func__); l2cap_client_disconnect(client); break; @@ -297,7 +297,7 @@ static void config_completed_cb(uint16_t local_channel_id, tL2CAP_CFG_INFO *nego // Failure, no further parameter negotiation possible. default: - LOG_WARN("%s L2CAP parameter negotiation failed with error code %d.\n", __func__, negotiated_parameters->result); + L2CAP_TRACE_WARNING("%s L2CAP parameter negotiation failed with error code %d.\n", __func__, negotiated_parameters->result); l2cap_client_disconnect(client); break; } @@ -307,7 +307,7 @@ static void disconnect_request_cb(uint16_t local_channel_id, bool ack_required) { l2cap_client_t *client = find(local_channel_id); if (!client) { - LOG_ERROR("%s unable to find L2CAP client with LCID 0x%04x.\n", __func__, local_channel_id); + L2CAP_TRACE_ERROR("%s unable to find L2CAP client with LCID 0x%04x.\n", __func__, local_channel_id); return; } @@ -328,7 +328,7 @@ static void disconnect_completed_cb(uint16_t local_channel_id, UNUSED_ATTR uint1 l2cap_client_t *client = find(local_channel_id); if (!client) { - LOG_ERROR("%s unable to find L2CAP client with LCID 0x%04x.\n", __func__, local_channel_id); + L2CAP_TRACE_ERROR("%s unable to find L2CAP client with LCID 0x%04x.\n", __func__, local_channel_id); return; } @@ -344,7 +344,7 @@ static void congestion_cb(uint16_t local_channel_id, bool is_congested) l2cap_client_t *client = find(local_channel_id); if (!client) { - LOG_ERROR("%s unable to find L2CAP client matching LCID 0x%04x.\n", __func__, local_channel_id); + L2CAP_TRACE_ERROR("%s unable to find L2CAP client matching LCID 0x%04x.\n", __func__, local_channel_id); return; } @@ -367,7 +367,7 @@ static void read_ready_cb(uint16_t local_channel_id, BT_HDR *packet) l2cap_client_t *client = find(local_channel_id); if (!client) { - LOG_ERROR("%s unable to find L2CAP client matching LCID 0x%04x.\n", __func__, local_channel_id); + L2CAP_TRACE_ERROR("%s unable to find L2CAP client matching LCID 0x%04x.\n", __func__, local_channel_id); return; } @@ -435,7 +435,7 @@ static void dispatch_fragments(l2cap_client_t *client) return; case L2CAP_DW_FAILED: - LOG_ERROR("%s error writing data to L2CAP connection LCID 0x%04x; disconnecting.", __func__, client->local_channel_id); + L2CAP_TRACE_ERROR("%s error writing data to L2CAP connection LCID 0x%04x; disconnecting.", __func__, client->local_channel_id); l2cap_client_disconnect(client); return; diff --git a/components/bt/bluedroid/stack/rfcomm/port_api.c b/components/bt/bluedroid/stack/rfcomm/port_api.c index ea3f7b6efc..b5e2c569fa 100644 --- a/components/bt/bluedroid/stack/rfcomm/port_api.c +++ b/components/bt/bluedroid/stack/rfcomm/port_api.c @@ -1785,4 +1785,4 @@ const char *PORT_GetResultString (const uint8_t result_code) return result_code_strings[result_code]; } -#endif ///(defined RFCOMM_INCLUDED && RFCOMM_INCLUDED == TRUE) \ No newline at end of file +#endif ///(defined RFCOMM_INCLUDED && RFCOMM_INCLUDED == TRUE) diff --git a/components/bt/bluedroid/stack/sdp/sdp_api.c b/components/bt/bluedroid/stack/sdp/sdp_api.c index 529359a4fe..4c2e229892 100644 --- a/components/bt/bluedroid/stack/sdp/sdp_api.c +++ b/components/bt/bluedroid/stack/sdp/sdp_api.c @@ -1240,4 +1240,4 @@ UINT8 SDP_SetTraceLevel (UINT8 new_level) return (sdp_cb.trace_level); } -#endif ///SDP_INCLUDED == TRUE \ No newline at end of file +#endif ///SDP_INCLUDED == TRUE From 8f80cc733db74b7aaa76a3880907d0bf732eb249 Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Thu, 22 Mar 2018 17:39:59 +0500 Subject: [PATCH 086/187] soc: Change DPORT access When two CPUs read the area of the DPORT and the area of the APB, the result is corrupted for the CPU that read the APB area. And another CPU has valid data. The method of eliminating this error. Before reading the registers of the DPORT, make a preliminary reading of the APB register. In this case, the joint access of the two CPUs to the registers of the APB and the DPORT is successful. --- components/esp32/dport_access.c | 19 ++ components/esp32/hwcrypto/aes.c | 45 +-- components/esp32/hwcrypto/sha.c | 66 ++--- components/esp32/include/esp_dport_access.h | 7 +- components/esp32/test/test_dport.c | 258 +++++++++++++++++- components/mbedtls/port/esp_bignum.c | 37 +-- .../soc/esp32/include/soc/dport_access.h | 143 ++++++++-- components/spi_flash/flash_mmap.c | 50 ++-- 8 files changed, 467 insertions(+), 158 deletions(-) diff --git a/components/esp32/dport_access.c b/components/esp32/dport_access.c index 2281eea343..4e5d5b1776 100644 --- a/components/esp32/dport_access.c +++ b/components/esp32/dport_access.c @@ -217,3 +217,22 @@ void IRAM_ATTR esp_dport_access_int_resume(void) #endif } +/** + * @brief Read a sequence of DPORT registers to the buffer, SMP-safe version. + * + * This implementation uses a method of the pre-reading of the APB register + * before reading the register of the DPORT, without stall other CPU. + * There is disable/enable interrupt. + * + * @param[out] buff_out Contains the read data. + * @param[in] address Initial address for reading registers. + * @param[in] num_words The number of words. + */ +void IRAM_ATTR esp_dport_access_read_buffer(uint32_t *buff_out, uint32_t address, uint32_t num_words) +{ + DPORT_INTERRUPT_DISABLE(); + for (uint32_t i = 0; i < num_words; ++i) { + buff_out[i] = DPORT_SEQUENCE_REG_READ(address + i * 4); + } + DPORT_INTERRUPT_RESTORE(); +} diff --git a/components/esp32/hwcrypto/aes.c b/components/esp32/hwcrypto/aes.c index 1e9bdc8523..bddaf1fcda 100644 --- a/components/esp32/hwcrypto/aes.c +++ b/components/esp32/hwcrypto/aes.c @@ -53,31 +53,23 @@ void esp_aes_acquire_hardware( void ) /* newlib locks lazy initialize on ESP-IDF */ portENTER_CRITICAL(&aes_spinlock); - DPORT_STALL_OTHER_CPU_START(); - { - /* Enable AES hardware */ - _DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES); - /* Clear reset on digital signature & secure boot units, - otherwise AES unit is held in reset also. */ - _DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, - DPORT_PERI_EN_AES - | DPORT_PERI_EN_DIGITAL_SIGNATURE - | DPORT_PERI_EN_SECUREBOOT); - } - DPORT_STALL_OTHER_CPU_END(); + /* Enable AES hardware */ + DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES); + /* Clear reset on digital signature & secure boot units, + otherwise AES unit is held in reset also. */ + DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, + DPORT_PERI_EN_AES + | DPORT_PERI_EN_DIGITAL_SIGNATURE + | DPORT_PERI_EN_SECUREBOOT); } void esp_aes_release_hardware( void ) { - DPORT_STALL_OTHER_CPU_START(); - { - /* Disable AES hardware */ - _DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_AES); - /* Don't return other units to reset, as this pulls - reset on RSA & SHA units, respectively. */ - _DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES); - } - DPORT_STALL_OTHER_CPU_END(); + /* Disable AES hardware */ + DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_AES); + /* Don't return other units to reset, as this pulls + reset on RSA & SHA units, respectively. */ + DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES); portEXIT_CRITICAL(&aes_spinlock); } @@ -141,15 +133,8 @@ static inline void esp_aes_block(const void *input, void *output) } DPORT_REG_WRITE(AES_START_REG, 1); - - DPORT_STALL_OTHER_CPU_START(); - { - while (_DPORT_REG_READ(AES_IDLE_REG) != 1) { } - for (int i = 0; i < 4; i++) { - output_words[i] = mem_block[i]; - } - } - DPORT_STALL_OTHER_CPU_END(); + while (DPORT_REG_READ(AES_IDLE_REG) != 1) { } + esp_dport_access_read_buffer(output_words, (uint32_t)&mem_block[0], 4); } /* diff --git a/components/esp32/hwcrypto/sha.c b/components/esp32/hwcrypto/sha.c index 305b476a80..df0086be5d 100644 --- a/components/esp32/hwcrypto/sha.c +++ b/components/esp32/hwcrypto/sha.c @@ -159,16 +159,14 @@ static void esp_sha_lock_engine_inner(sha_engine_state *engine) _lock_acquire(&state_change_lock); if (sha_engines_all_idle()) { + /* Enable SHA hardware */ + DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA); + /* also clear reset on secure boot, otherwise SHA is held in reset */ + DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, + DPORT_PERI_EN_SHA + | DPORT_PERI_EN_SECUREBOOT); DPORT_STALL_OTHER_CPU_START(); - { - /* Enable SHA hardware */ - _DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA); - /* also clear reset on secure boot, otherwise SHA is held in reset */ - _DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, - DPORT_PERI_EN_SHA - | DPORT_PERI_EN_SECUREBOOT); - ets_sha_enable(); - } + ets_sha_enable(); DPORT_STALL_OTHER_CPU_END(); } @@ -191,12 +189,8 @@ void esp_sha_unlock_engine(esp_sha_type sha_type) if (sha_engines_all_idle()) { /* Disable SHA hardware */ /* Don't assert reset on secure boot, otherwise AES is held in reset */ - DPORT_STALL_OTHER_CPU_START(); - { - _DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_SHA); - _DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA); - } - DPORT_STALL_OTHER_CPU_END(); + DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_SHA); + DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA); } _lock_release(&state_change_lock); @@ -206,16 +200,14 @@ void esp_sha_unlock_engine(esp_sha_type sha_type) void esp_sha_wait_idle(void) { - DPORT_STALL_OTHER_CPU_START(); while(1) { - if(_DPORT_REG_READ(SHA_1_BUSY_REG) == 0 - && _DPORT_REG_READ(SHA_256_BUSY_REG) == 0 - && _DPORT_REG_READ(SHA_384_BUSY_REG) == 0 - && _DPORT_REG_READ(SHA_512_BUSY_REG) == 0) { + if(DPORT_REG_READ(SHA_1_BUSY_REG) == 0 + && DPORT_REG_READ(SHA_256_BUSY_REG) == 0 + && DPORT_REG_READ(SHA_384_BUSY_REG) == 0 + && DPORT_REG_READ(SHA_512_BUSY_REG) == 0) { break; } } - DPORT_STALL_OTHER_CPU_END(); } void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state) @@ -225,27 +217,23 @@ void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state) esp_sha_lock_memory_block(); - DPORT_STALL_OTHER_CPU_START(); // This block reads from DPORT memory (reg_addr_buf) - { - esp_sha_wait_idle(); + esp_sha_wait_idle(); - _DPORT_REG_WRITE(SHA_LOAD_REG(sha_type), 1); - while(_DPORT_REG_READ(SHA_BUSY_REG(sha_type)) == 1) { } - - uint32_t *digest_state_words = (uint32_t *)digest_state; - uint32_t *reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE); - if(sha_type == SHA2_384 || sha_type == SHA2_512) { - /* for these ciphers using 64-bit states, swap each pair of words */ - for(int i = 0; i < sha_length(sha_type)/4; i += 2) { - digest_state_words[i+1] = reg_addr_buf[i]; - digest_state_words[i]= reg_addr_buf[i+1]; - } - } else { - memcpy(digest_state_words, reg_addr_buf, sha_length(sha_type)); + DPORT_REG_WRITE(SHA_LOAD_REG(sha_type), 1); + while(DPORT_REG_READ(SHA_BUSY_REG(sha_type)) == 1) { } + uint32_t *digest_state_words = (uint32_t *)digest_state; + uint32_t *reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE); + if(sha_type == SHA2_384 || sha_type == SHA2_512) { + /* for these ciphers using 64-bit states, swap each pair of words */ + DPORT_INTERRUPT_DISABLE(); // Disable interrupt only on current CPU. + for(int i = 0; i < sha_length(sha_type)/4; i += 2) { + digest_state_words[i+1] = DPORT_SEQUENCE_REG_READ((uint32_t)®_addr_buf[i]); + digest_state_words[i] = DPORT_SEQUENCE_REG_READ((uint32_t)®_addr_buf[i+1]); } + DPORT_INTERRUPT_RESTORE(); // restore the previous interrupt level + } else { + esp_dport_access_read_buffer(digest_state_words, (uint32_t)®_addr_buf[0], sha_length(sha_type)/4); } - DPORT_STALL_OTHER_CPU_END(); - esp_sha_unlock_memory_block(); } diff --git a/components/esp32/include/esp_dport_access.h b/components/esp32/include/esp_dport_access.h index 3acf806888..1a46fa00c9 100644 --- a/components/esp32/include/esp_dport_access.h +++ b/components/esp32/include/esp_dport_access.h @@ -26,7 +26,7 @@ void esp_dport_access_stall_other_cpu_end(void); void esp_dport_access_int_init(void); void esp_dport_access_int_pause(void); void esp_dport_access_int_resume(void); - +void esp_dport_access_read_buffer(uint32_t *buff_out, uint32_t address, uint32_t num_words); //This routine does not stop the dport routines in any way that is recoverable. Please //only call in case of panic(). void esp_dport_access_int_abort(void); @@ -34,9 +34,14 @@ void esp_dport_access_int_abort(void); #if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM) #define DPORT_STALL_OTHER_CPU_START() #define DPORT_STALL_OTHER_CPU_END() +#define DPORT_STALL_OTHER_CPU_START() +#define DPORT_INTERRUPT_DISABLE() +#define DPORT_INTERRUPT_RESTORE() #else #define DPORT_STALL_OTHER_CPU_START() esp_dport_access_stall_other_cpu_start() #define DPORT_STALL_OTHER_CPU_END() esp_dport_access_stall_other_cpu_end() +#define DPORT_INTERRUPT_DISABLE() unsigned int intLvl = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL) +#define DPORT_INTERRUPT_RESTORE() XTOS_RESTORE_JUST_INTLEVEL(intLvl) #endif #ifdef __cplusplus diff --git a/components/esp32/test/test_dport.c b/components/esp32/test/test_dport.c index 930d8cdceb..6b5960bf48 100644 --- a/components/esp32/test/test_dport.c +++ b/components/esp32/test/test_dport.c @@ -6,12 +6,13 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" - +#include "soc/cpu.h" #include "unity.h" - +#include "rom/uart.h" #include "soc/uart_reg.h" #include "soc/dport_reg.h" - +#include "soc/rtc.h" +#define MHZ (1000000) static volatile bool exit_flag; static bool dport_test_result; static bool apb_test_result; @@ -54,40 +55,267 @@ static void accessAPB(void *pvParameters) vTaskDelete(NULL); } -TEST_CASE("access DPORT and APB at same time", "[esp32]") +void run_tasks(const char *task1_description, void (* task1_func)(void *), const char *task2_description, void (* task2_func)(void *), uint32_t delay_ms) { int i; TaskHandle_t th[2]; xSemaphoreHandle exit_sema[2]; for (i=0; i<2; i++) { - exit_sema[i] = xSemaphoreCreateMutex(); - xSemaphoreTake(exit_sema[i], portMAX_DELAY); + if((task1_func != NULL && i == 0) || (task2_func != NULL && i == 1)){ + exit_sema[i] = xSemaphoreCreateMutex(); + xSemaphoreTake(exit_sema[i], portMAX_DELAY); + } } exit_flag = false; #ifndef CONFIG_FREERTOS_UNICORE printf("assign task accessing DPORT to core 0 and task accessing APB to core 1\n"); - xTaskCreatePinnedToCore(accessDPORT , "accessDPORT" , 2048, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, &th[0], 0); - xTaskCreatePinnedToCore(accessAPB , "accessAPB" , 2048, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, &th[1], 1); + if(task1_func != NULL) xTaskCreatePinnedToCore(task1_func, task1_description, 2048, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, &th[0], 0); + if(task2_func != NULL) xTaskCreatePinnedToCore(task2_func, task2_description, 2048, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, &th[1], 1); #else printf("assign task accessing DPORT and accessing APB\n"); - xTaskCreate(accessDPORT , "accessDPORT" , 2048, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, &th[0]); - xTaskCreate(accessAPB , "accessAPB" , 2048, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, &th[1]); + if(task1_func != NULL) xTaskCreate(task1_func, task1_description, 2048, &exit_sema[0], UNITY_FREERTOS_PRIORITY - 1, &th[0]); + if(task2_func != NULL) xTaskCreate(task2_func, task2_description, 2048, &exit_sema[1], UNITY_FREERTOS_PRIORITY - 1, &th[1]); #endif - printf("start wait for 10 seconds\n"); - vTaskDelay(10000 / portTICK_PERIOD_MS); + printf("start wait for %d seconds [Test %s and %s]\n", delay_ms/1000, task1_description, task2_description); + vTaskDelay(delay_ms / portTICK_PERIOD_MS); // set exit flag to let thread exit exit_flag = true; for (i=0; i<2; i++) { - xSemaphoreTake(exit_sema[i], portMAX_DELAY); - vSemaphoreDelete(exit_sema[i]); + if ((task1_func != NULL && i == 0) || (task2_func != NULL && i == 1)) { + xSemaphoreTake(exit_sema[i], portMAX_DELAY); + vSemaphoreDelete(exit_sema[i]); + } } - TEST_ASSERT(dport_test_result == true && apb_test_result == true); } +TEST_CASE("access DPORT and APB at same time", "[esp32]") +{ + dport_test_result = false; + apb_test_result = false; + printf("CPU_FREQ = %d MHz\n", rtc_clk_cpu_freq_value(rtc_clk_cpu_freq_get()) / MHZ); + run_tasks("accessDPORT", accessDPORT, "accessAPB", accessAPB, 10000); +} + +void run_tasks_with_change_freq_cpu (rtc_cpu_freq_t cpu_freq) +{ + dport_test_result = false; + apb_test_result = false; + rtc_cpu_freq_t cur_freq = rtc_clk_cpu_freq_get(); + uint32_t freq_before_changed = rtc_clk_cpu_freq_value(cur_freq) / MHZ; + uint32_t freq_changed = freq_before_changed; + printf("CPU_FREQ = %d MHz\n", freq_before_changed); + + if (cur_freq != cpu_freq) { + uart_tx_wait_idle(CONFIG_CONSOLE_UART_NUM); + + rtc_clk_cpu_freq_set(cpu_freq); + + const int uart_num = CONFIG_CONSOLE_UART_NUM; + const int uart_baud = CONFIG_CONSOLE_UART_BAUDRATE; + uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud); + + freq_changed = rtc_clk_cpu_freq_value(rtc_clk_cpu_freq_get()) / MHZ; + printf("CPU_FREQ switching to %d MHz\n", freq_changed); + } + run_tasks("accessDPORT", accessDPORT, "accessAPB", accessAPB, 10000 / ((freq_before_changed <= freq_changed) ? 1 : (freq_before_changed / freq_changed))); + + // return old freq. + uart_tx_wait_idle(CONFIG_CONSOLE_UART_NUM); + rtc_clk_cpu_freq_set(cur_freq); + const int uart_num = CONFIG_CONSOLE_UART_NUM; + const int uart_baud = CONFIG_CONSOLE_UART_BAUDRATE; + uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud); +} + +TEST_CASE("access DPORT and APB at same time (Freq CPU and APB = 80 MHz)", "[esp32] [ignore]") +{ + run_tasks_with_change_freq_cpu(RTC_CPU_FREQ_80M); +} + +TEST_CASE("access DPORT and APB at same time (Freq CPU and APB = 40 MHz (XTAL))", "[esp32]") +{ + run_tasks_with_change_freq_cpu(RTC_CPU_FREQ_XTAL); +} + +static uint32_t stall_other_cpu_counter; +static uint32_t pre_reading_apb_counter; +static uint32_t apb_counter; + +static void accessDPORT_stall_other_cpu(void *pvParameters) +{ + xSemaphoreHandle *sema = (xSemaphoreHandle *) pvParameters; + uint32_t dport_date = DPORT_REG_READ(DPORT_DATE_REG); + uint32_t dport_date_cur; + dport_test_result = true; + stall_other_cpu_counter = 0; + // although exit flag is set in another task, checking (exit_flag == false) is safe + while (exit_flag == false) { + ++stall_other_cpu_counter; + DPORT_STALL_OTHER_CPU_START(); + dport_date_cur = _DPORT_REG_READ(DPORT_DATE_REG); + DPORT_STALL_OTHER_CPU_END(); + if (dport_date != dport_date_cur) { + apb_test_result = false; + break; + } + } + + xSemaphoreGive(*sema); + vTaskDelete(NULL); +} + +static void accessAPB_measure_performance(void *pvParameters) +{ + xSemaphoreHandle *sema = (xSemaphoreHandle *) pvParameters; + uint32_t uart_date = REG_READ(UART_DATE_REG(0)); + + apb_test_result = true; + apb_counter = 0; + // although exit flag is set in another task, checking (exit_flag == false) is safe + while (exit_flag == false) { + ++apb_counter; + if (uart_date != REG_READ(UART_DATE_REG(0))) { + apb_test_result = false; + break; + } + } + + xSemaphoreGive(*sema); + vTaskDelete(NULL); +} + +static void accessDPORT_pre_reading_apb(void *pvParameters) +{ + xSemaphoreHandle *sema = (xSemaphoreHandle *) pvParameters; + uint32_t dport_date = DPORT_REG_READ(DPORT_DATE_REG); + uint32_t dport_date_cur; + dport_test_result = true; + pre_reading_apb_counter = 0; + // although exit flag is set in another task, checking (exit_flag == false) is safe + while (exit_flag == false) { + ++pre_reading_apb_counter; + dport_date_cur = DPORT_REG_READ(DPORT_DATE_REG); + if (dport_date != dport_date_cur) { + apb_test_result = false; + break; + } + } + + xSemaphoreGive(*sema); + vTaskDelete(NULL); +} + +TEST_CASE("test for DPORT access performance", "[esp32]") +{ + dport_test_result = true; + apb_test_result = true; + typedef struct { + uint32_t dport; + uint32_t apb; + uint32_t summ; + } test_performance_t; + test_performance_t t[5] = {0}; + uint32_t delay_ms = 5000; + + run_tasks("-", NULL, "accessAPB", accessAPB_measure_performance, delay_ms); + t[0].apb = apb_counter; + t[0].dport = 0; + t[0].summ = t[0].apb + t[0].dport; + + run_tasks("accessDPORT_stall_other_cpu", accessDPORT_stall_other_cpu, "-", NULL, delay_ms); + t[1].apb = 0; + t[1].dport = stall_other_cpu_counter; + t[1].summ = t[1].apb + t[1].dport; + + run_tasks("accessDPORT_pre_reading_apb", accessDPORT_pre_reading_apb, "-", NULL, delay_ms); + t[2].apb = 0; + t[2].dport = pre_reading_apb_counter; + t[2].summ = t[2].apb + t[2].dport; + + run_tasks("accessDPORT_stall_other_cpu", accessDPORT_stall_other_cpu, "accessAPB", accessAPB_measure_performance, delay_ms); + t[3].apb = apb_counter; + t[3].dport = stall_other_cpu_counter; + t[3].summ = t[3].apb + t[3].dport; + + run_tasks("accessDPORT_pre_reading_apb", accessDPORT_pre_reading_apb, "accessAPB", accessAPB_measure_performance, delay_ms); + t[4].apb = apb_counter; + t[4].dport = pre_reading_apb_counter; + t[4].summ = t[4].apb + t[4].dport; + + printf("\nPerformance table: \n" + "The number of simultaneous read operations of the APB and DPORT registers\n" + "by different methods for %d seconds.\n", delay_ms/1000); + printf("+-----------------------+----------+----------+----------+\n"); + printf("| Method read DPORT | DPORT | APB | SUMM |\n"); + printf("+-----------------------+----------+----------+----------+\n"); + printf("|1.Only accessAPB |%10d|%10d|%10d|\n", t[0].dport, t[0].apb, t[0].summ); + printf("|2.Only STALL_OTHER_CPU |%10d|%10d|%10d|\n", t[1].dport, t[1].apb, t[1].summ); + printf("|3.Only PRE_READ_APB_REG|%10d|%10d|%10d|\n", t[2].dport, t[2].apb, t[2].summ); + printf("+-----------------------+----------+----------+----------+\n"); + printf("|4.STALL_OTHER_CPU |%10d|%10d|%10d|\n", t[3].dport, t[3].apb, t[3].summ); + printf("|5.PRE_READ_APB_REG |%10d|%10d|%10d|\n", t[4].dport, t[4].apb, t[4].summ); + printf("+-----------------------+----------+----------+----------+\n"); + printf("| ratio=PRE_READ/STALL |%10f|%10f|%10f|\n", (float)t[4].dport/t[3].dport, (float)t[4].apb/t[3].apb, (float)t[4].summ/t[3].summ); + printf("+-----------------------+----------+----------+----------+\n"); +} + +#define REPEAT_OPS 10000 + +static uint32_t start, end; + +#define BENCHMARK_START() do { \ + RSR(CCOUNT, start); \ + } while(0) + +#define BENCHMARK_END(OPERATION) do { \ + RSR(CCOUNT, end); \ + printf("%s took %d cycles/op (%d cycles for %d ops)\n", \ + OPERATION, (end - start)/REPEAT_OPS, \ + (end - start), REPEAT_OPS); \ + } while(0) + +TEST_CASE("BENCHMARK for DPORT access performance", "[freertos]") +{ + BENCHMARK_START(); + for (int i = 0; i < REPEAT_OPS; i++) { + DPORT_STALL_OTHER_CPU_START(); + _DPORT_REG_READ(DPORT_DATE_REG); + DPORT_STALL_OTHER_CPU_END(); + } + BENCHMARK_END("[old]DPORT access STALL OTHER CPU"); + + + BENCHMARK_START(); + for (int i = 0; i < REPEAT_OPS; i++) { + DPORT_REG_READ(DPORT_DATE_REG); + } + BENCHMARK_END("[new]DPORT access PRE-READ APB REG"); + + + BENCHMARK_START(); + for (int i = 0; i < REPEAT_OPS; i++) { + DPORT_SEQUENCE_REG_READ(DPORT_DATE_REG); + } + BENCHMARK_END("[seq]DPORT access PRE-READ APB REG"); + + + BENCHMARK_START(); + for (int i = 0; i < REPEAT_OPS; i++) { + REG_READ(UART_DATE_REG(0)); + } + BENCHMARK_END("REG_READ"); + + + BENCHMARK_START(); + for (int i = 0; i < REPEAT_OPS; i++) { + _DPORT_REG_READ(DPORT_DATE_REG); + } + BENCHMARK_END("_DPORT_REG_READ"); +} diff --git a/components/mbedtls/port/esp_bignum.c b/components/mbedtls/port/esp_bignum.c index f18652c7bb..3bfcd6145b 100644 --- a/components/mbedtls/port/esp_bignum.c +++ b/components/mbedtls/port/esp_bignum.c @@ -76,17 +76,13 @@ void esp_mpi_acquire_hardware( void ) /* newlib locks lazy initialize on ESP-IDF */ _lock_acquire(&mpi_lock); - DPORT_STALL_OTHER_CPU_START(); - { - _DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA); - /* also clear reset on digital signature, otherwise RSA is held in reset */ - _DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, - DPORT_PERI_EN_RSA - | DPORT_PERI_EN_DIGITAL_SIGNATURE); + DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA); + /* also clear reset on digital signature, otherwise RSA is held in reset */ + DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, + DPORT_PERI_EN_RSA + | DPORT_PERI_EN_DIGITAL_SIGNATURE); - _DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); - } - DPORT_STALL_OTHER_CPU_END(); + DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); while(DPORT_REG_READ(RSA_CLEAN_REG) != 1); // Note: from enabling RSA clock to here takes about 1.3us @@ -98,15 +94,11 @@ void esp_mpi_acquire_hardware( void ) void esp_mpi_release_hardware( void ) { - DPORT_STALL_OTHER_CPU_START(); - { - _DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); + DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); - /* don't reset digital signature unit, as this resets AES also */ - _DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_RSA); - _DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA); - } - DPORT_STALL_OTHER_CPU_END(); + /* don't reset digital signature unit, as this resets AES also */ + DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_RSA); + DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA); _lock_release(&mpi_lock); } @@ -183,14 +175,7 @@ static inline int mem_block_to_mpi(mbedtls_mpi *x, uint32_t mem_base, int num_wo MBEDTLS_MPI_CHK( mbedtls_mpi_grow(x, num_words) ); /* Copy data from memory block registers */ - DPORT_STALL_OTHER_CPU_START(); - { - for (size_t i = 0; i < num_words; ++i) { - x->p[i] = _DPORT_REG_READ(mem_base + i * 4); - } - } - DPORT_STALL_OTHER_CPU_END(); - + esp_dport_access_read_buffer(x->p, mem_base, num_words); /* Zero any remaining limbs in the bignum, if the buffer is bigger than num_words */ for(size_t i = num_words; i < x->n; i++) { diff --git a/components/soc/esp32/include/soc/dport_access.h b/components/soc/esp32/include/soc/dport_access.h index 817ac98e7b..db39082413 100644 --- a/components/soc/esp32/include/soc/dport_access.h +++ b/components/soc/esp32/include/soc/dport_access.h @@ -18,6 +18,9 @@ #include #include "esp_attr.h" #include "esp_dport_access.h" +#include "soc.h" +#include "uart_reg.h" +#include "xtensa/xtruntime.h" #ifdef __cplusplus extern "C" { @@ -28,10 +31,29 @@ extern "C" { // The _DPORT_xxx register read macros access DPORT memory directly (as opposed to // DPORT_REG_READ which applies SMP-safe protections). // -// Use DPORT_REG_READ versions to be SMP-safe in IDF apps. If you want to -// make a sequence of DPORT reads, use DPORT_STALL_OTHER_CPU_START() macro -// explicitly and then use _DPORT_REG_READ macro while other CPU is stalled. -// +// There are several ways to read the DPORT registers: +// 1) Use DPORT_REG_READ versions to be SMP-safe in IDF apps. +// This method uses the pre-read APB implementation(*) without stall other CPU. +// This is beneficial for single readings. +// 2) If you want to make a sequence of DPORT reads to buffer, +// use dport_read_buffer(buff_out, address, num_words), +// it is the faster method and it doesn't stop other CPU. +// 3) If you want to make a sequence of DPORT reads, but you don't want to stop other CPU +// and you want to do it faster then you need use DPORT_SEQUENCE_REG_READ(). +// The difference from the first is that the user himself must disable interrupts while DPORT reading. +// Note that disable interrupt need only if the chip has two cores. +// 4) If you want to make a sequence of DPORT reads, +// use DPORT_STALL_OTHER_CPU_START() macro explicitly +// and then use _DPORT_REG_READ macro while other CPU is stalled. +// After completing read operations, use DPORT_STALL_OTHER_CPU_END(). +// This method uses stall other CPU while reading DPORT registers. +// Useful for compatibility, as well as for large consecutive readings. +// This method is slower, but must be used if ROM functions or +// other code is called which accesses DPORT without any other workaround. +// *) The pre-readable APB register before reading the DPORT register +// helps synchronize the operation of the two CPUs, +// so that reading on different CPUs no longer causes random errors APB register. + // _DPORT_REG_WRITE & DPORT_REG_WRITE are equivalent. #define _DPORT_REG_READ(_r) (*(volatile uint32_t *)(_r)) #define _DPORT_REG_WRITE(_r, _v) (*(volatile uint32_t *)(_r)) = (_v) @@ -39,16 +61,78 @@ extern "C" { // Write value to DPORT register (does not require protecting) #define DPORT_REG_WRITE(_r, _v) _DPORT_REG_WRITE((_r), (_v)) -// Read value from register, SMP-safe version. +/** + * @brief Read value from register, SMP-safe version. + * + * This method uses the pre-reading of the APB register before reading the register of the DPORT. + * This implementation is useful for reading DORT registers for single reading without stall other CPU. + * There is disable/enable interrupt. + * + * @param reg Register address + * @return Value + */ static inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg) { - uint32_t val; +#ifndef CONFIG_FREERTOS_UNICORE + uint32_t apb; + unsigned int intLvl; + __asm__ __volatile__ (\ + "movi %[APB], "XTSTR(0x3ff40078)"\n"\ + "rsil %[LVL], "XTSTR(3)"\n"\ + "l32i %[APB], %[APB], 0\n"\ + "l32i %[REG], %[REG], 0\n"\ + "wsr %[LVL], "XTSTR(PS)"\n"\ + "rsync\n"\ + : [APB]"=a"(apb), [REG]"+a"(reg), [LVL]"=a"(intLvl)\ + : \ + : "memory" \ + ); + return reg; +#else + return _DPORT_REG_READ(reg); +#endif +} - DPORT_STALL_OTHER_CPU_START(); - val = _DPORT_REG_READ(reg); - DPORT_STALL_OTHER_CPU_END(); - - return val; +/** + * @brief Read value from register, NOT SMP-safe version. + * + * This method uses the pre-reading of the APB register before reading the register of the DPORT. + * There is not disable/enable interrupt. + * The difference from DPORT_REG_READ() is that the user himself must disable interrupts while DPORT reading. + * This implementation is useful for reading DORT registers in loop without stall other CPU. Note the usage example. + * The recommended way to read registers sequentially without stall other CPU + * is to use the method esp_dport_read_buffer(buff_out, address, num_words). It allows you to read registers in the buffer. + * + * \code{c} + * // This example shows how to use it. + * { // Use curly brackets to limit the visibility of variables in macros DPORT_INTERRUPT_DISABLE/RESTORE. + * DPORT_INTERRUPT_DISABLE(); // Disable interrupt only on current CPU. + * for (i = 0; i < max; ++i) { + * array[i] = DPORT_SEQUENCE_REG_READ(Address + i * 4); // reading DPORT registers + * } + * DPORT_INTERRUPT_RESTORE(); // restore the previous interrupt level + * } + * \endcode + * + * @param reg Register address + * @return Value + */ +static inline uint32_t IRAM_ATTR DPORT_SEQUENCE_REG_READ(uint32_t reg) +{ +#ifndef CONFIG_FREERTOS_UNICORE + uint32_t apb; + __asm__ __volatile__ (\ + "movi %[APB], "XTSTR(0x3ff40078)"\n"\ + "l32i %[APB], %[APB], 0\n"\ + "l32i %[REG], %[REG], 0\n"\ + : [APB]"=a"(apb), [REG]"+a"(reg)\ + : \ + : "memory" \ + ); + return reg; +#else + return _DPORT_REG_READ(reg); +#endif } //get bit or get bits from register @@ -93,16 +177,35 @@ static inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg) #define _DPORT_REG_SET_BIT(_r, _b) _DPORT_REG_WRITE((_r), (_DPORT_REG_READ(_r)|(_b))) #define _DPORT_REG_CLR_BIT(_r, _b) _DPORT_REG_WRITE((_r), (_DPORT_REG_READ(_r) & (~(_b)))) -//read value from register -static inline uint32_t IRAM_ATTR DPORT_READ_PERI_REG(uint32_t addr) +/** + * @brief Read value from register, SMP-safe version. + * + * This method uses the pre-reading of the APB register before reading the register of the DPORT. + * This implementation is useful for reading DORT registers for single reading without stall other CPU. + * + * @param reg Register address + * @return Value + */ +static inline uint32_t IRAM_ATTR DPORT_READ_PERI_REG(uint32_t reg) { - uint32_t val; - - DPORT_STALL_OTHER_CPU_START(); - val = _DPORT_READ_PERI_REG(addr); - DPORT_STALL_OTHER_CPU_END(); - - return val; +#ifndef CONFIG_FREERTOS_UNICORE + uint32_t apb; + unsigned int intLvl; + __asm__ __volatile__ (\ + "movi %[APB], "XTSTR(0x3ff40078)"\n"\ + "rsil %[LVL], "XTSTR(3)"\n"\ + "l32i %[APB], %[APB], 0\n"\ + "l32i %[REG], %[REG], 0\n"\ + "wsr %[LVL], "XTSTR(PS)"\n"\ + "rsync\n"\ + : [APB]"=a"(apb), [REG]"+a"(reg), [LVL]"=a"(intLvl)\ + : \ + : "memory" \ + ); + return reg; +#else + return _DPORT_READ_PERI_REG(reg); +#endif } //write value to register diff --git a/components/spi_flash/flash_mmap.c b/components/spi_flash/flash_mmap.c index 91e213d4d8..43fdf6ccd4 100644 --- a/components/spi_flash/flash_mmap.c +++ b/components/spi_flash/flash_mmap.c @@ -79,11 +79,10 @@ static void IRAM_ATTR spi_flash_mmap_init() if (s_mmap_page_refcnt[0] != 0) { return; /* mmap data already initialised */ } - - DPORT_STALL_OTHER_CPU_START(); + DPORT_INTERRUPT_DISABLE(); for (int i = 0; i < REGIONS_COUNT * PAGES_PER_REGION; ++i) { - uint32_t entry_pro = DPORT_PRO_FLASH_MMU_TABLE[i]; - uint32_t entry_app = DPORT_APP_FLASH_MMU_TABLE[i]; + uint32_t entry_pro = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]); + uint32_t entry_app = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_APP_FLASH_MMU_TABLE[i]); if (entry_pro != entry_app) { // clean up entries used by boot loader @@ -97,7 +96,7 @@ static void IRAM_ATTR spi_flash_mmap_init() DPORT_APP_FLASH_MMU_TABLE[i] = DPORT_FLASH_MMU_TABLE_INVALID_VAL; } } - DPORT_STALL_OTHER_CPU_END(); + DPORT_INTERRUPT_RESTORE(); } static void IRAM_ATTR get_mmu_region(spi_flash_mmap_memory_t memory, int* out_begin, int* out_size,uint32_t* region_addr) @@ -186,15 +185,15 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(int *pages, size_t page_count, spi_flas for (start = region_begin; start < end; ++start) { int pageno = 0; int pos; - DPORT_STALL_OTHER_CPU_START(); + DPORT_INTERRUPT_DISABLE(); for (pos = start; pos < start + page_count; ++pos, ++pageno) { - int table_val = (int) DPORT_PRO_FLASH_MMU_TABLE[pos]; + int table_val = (int) DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[pos]); uint8_t refcnt = s_mmap_page_refcnt[pos]; if (refcnt != 0 && table_val != pages[pageno]) { break; } } - DPORT_STALL_OTHER_CPU_END(); + DPORT_INTERRUPT_RESTORE(); // whole mapping range matched, bail out if (pos - start == page_count) { break; @@ -208,14 +207,16 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(int *pages, size_t page_count, spi_flas } else { // set up mapping using pages uint32_t pageno = 0; - DPORT_STALL_OTHER_CPU_START(); + DPORT_INTERRUPT_DISABLE(); for (int i = start; i != start + page_count; ++i, ++pageno) { // sanity check: we won't reconfigure entries with non-zero reference count + uint32_t entry_pro = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]); + uint32_t entry_app = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_APP_FLASH_MMU_TABLE[i]); assert(s_mmap_page_refcnt[i] == 0 || - (DPORT_PRO_FLASH_MMU_TABLE[i] == pages[pageno] && - DPORT_APP_FLASH_MMU_TABLE[i] == pages[pageno])); + (entry_pro == pages[pageno] && + entry_app == pages[pageno])); if (s_mmap_page_refcnt[i] == 0) { - if (DPORT_PRO_FLASH_MMU_TABLE[i] != pages[pageno] || DPORT_APP_FLASH_MMU_TABLE[i] != pages[pageno]) { + if (entry_pro != pages[pageno] || entry_app != pages[pageno]) { DPORT_PRO_FLASH_MMU_TABLE[i] = pages[pageno]; DPORT_APP_FLASH_MMU_TABLE[i] = pages[pageno]; need_flush = true; @@ -223,7 +224,7 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(int *pages, size_t page_count, spi_flas } ++s_mmap_page_refcnt[i]; } - DPORT_STALL_OTHER_CPU_END(); + DPORT_INTERRUPT_RESTORE(); LIST_INSERT_HEAD(&s_mmap_entries_head, new_entry, entries); new_entry->page = start; new_entry->count = page_count; @@ -264,7 +265,6 @@ void IRAM_ATTR spi_flash_munmap(spi_flash_mmap_handle_t handle) // for each page, decrement reference counter // if reference count is zero, disable MMU table entry to // facilitate debugging of use-after-free conditions - DPORT_STALL_OTHER_CPU_START(); for (int i = it->page; i < it->page + it->count; ++i) { assert(s_mmap_page_refcnt[i] > 0); if (--s_mmap_page_refcnt[i] == 0) { @@ -272,7 +272,6 @@ void IRAM_ATTR spi_flash_munmap(spi_flash_mmap_handle_t handle) DPORT_APP_FLASH_MMU_TABLE[i] = INVALID_ENTRY_VAL; } } - DPORT_STALL_OTHER_CPU_END(); LIST_REMOVE(it, entries); break; } @@ -294,7 +293,7 @@ void spi_flash_mmap_dump() for (int i = 0; i < REGIONS_COUNT * PAGES_PER_REGION; ++i) { if (s_mmap_page_refcnt[i] != 0) { printf("page %d: refcnt=%d paddr=%d\n", - i, (int) s_mmap_page_refcnt[i], DPORT_PRO_FLASH_MMU_TABLE[i]); + i, (int) s_mmap_page_refcnt[i], DPORT_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i])); } } } @@ -307,13 +306,13 @@ uint32_t spi_flash_mmap_get_free_pages(spi_flash_mmap_memory_t memory) int region_size; // number of pages to check uint32_t region_addr; // base address of memory region get_mmu_region(memory,®ion_begin,®ion_size,®ion_addr); - DPORT_STALL_OTHER_CPU_START(); + DPORT_INTERRUPT_DISABLE(); for (int i = region_begin; i < region_begin + region_size; ++i) { - if (s_mmap_page_refcnt[i] == 0 && DPORT_PRO_FLASH_MMU_TABLE[i] == INVALID_ENTRY_VAL) { + if (s_mmap_page_refcnt[i] == 0 && DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]) == INVALID_ENTRY_VAL) { count++; } } - DPORT_STALL_OTHER_CPU_END(); + DPORT_INTERRUPT_RESTORE(); return count; } @@ -403,9 +402,7 @@ uint32_t spi_flash_cache2phys(const void *cached) /* cached address was not in IROM or DROM */ return SPI_FLASH_CACHE2PHYS_FAIL; } - DPORT_STALL_OTHER_CPU_START(); - uint32_t phys_page = DPORT_PRO_FLASH_MMU_TABLE[cache_page]; - DPORT_STALL_OTHER_CPU_END(); + uint32_t phys_page = DPORT_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[cache_page]); if (phys_page == INVALID_ENTRY_VAL) { /* page is not mapped */ return SPI_FLASH_CACHE2PHYS_FAIL; @@ -432,16 +429,15 @@ const void *spi_flash_phys2cache(uint32_t phys_offs, spi_flash_mmap_memory_t mem base = VADDR1_START_ADDR; page_delta = 64; } - - DPORT_STALL_OTHER_CPU_START(); + DPORT_INTERRUPT_DISABLE(); for (int i = start; i < end; i++) { - if (DPORT_PRO_FLASH_MMU_TABLE[i] == phys_page) { + if (DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]) == phys_page) { i -= page_delta; intptr_t cache_page = base + (SPI_FLASH_MMU_PAGE_SIZE * i); - DPORT_STALL_OTHER_CPU_END(); + DPORT_INTERRUPT_RESTORE(); return (const void *) (cache_page | (phys_offs & (SPI_FLASH_MMU_PAGE_SIZE-1))); } } - DPORT_STALL_OTHER_CPU_END(); + DPORT_INTERRUPT_RESTORE(); return NULL; } From 3a6d256d3e81d7057ec6c9bd86f14d007df9e8eb Mon Sep 17 00:00:00 2001 From: David Cermak Date: Mon, 14 May 2018 15:03:37 +0200 Subject: [PATCH 087/187] DhcpFuzzer: Added AFL test for dhcpserver with sample packets --- components/lwip/test_afl_host/Makefile | 36 +++++++++ components/lwip/test_afl_host/dhcpserver_di.h | 21 +++++ components/lwip/test_afl_host/in/data0.bin | Bin 0 -> 300 bytes components/lwip/test_afl_host/in/data1.bin | Bin 0 -> 300 bytes components/lwip/test_afl_host/in/data2.bin | Bin 0 -> 300 bytes components/lwip/test_afl_host/in/data3.bin | Bin 0 -> 305 bytes components/lwip/test_afl_host/in/data4.bin | Bin 0 -> 300 bytes components/lwip/test_afl_host/in/data5.bin | Bin 0 -> 311 bytes components/lwip/test_afl_host/in/data6.bin | Bin 0 -> 316 bytes components/lwip/test_afl_host/network_mock.c | 74 ++++++++++++++++++ components/lwip/test_afl_host/test.c | 53 +++++++++++++ 11 files changed, 184 insertions(+) create mode 100644 components/lwip/test_afl_host/Makefile create mode 100644 components/lwip/test_afl_host/dhcpserver_di.h create mode 100644 components/lwip/test_afl_host/in/data0.bin create mode 100644 components/lwip/test_afl_host/in/data1.bin create mode 100644 components/lwip/test_afl_host/in/data2.bin create mode 100644 components/lwip/test_afl_host/in/data3.bin create mode 100644 components/lwip/test_afl_host/in/data4.bin create mode 100644 components/lwip/test_afl_host/in/data5.bin create mode 100644 components/lwip/test_afl_host/in/data6.bin create mode 100644 components/lwip/test_afl_host/network_mock.c create mode 100644 components/lwip/test_afl_host/test.c diff --git a/components/lwip/test_afl_host/Makefile b/components/lwip/test_afl_host/Makefile new file mode 100644 index 0000000000..1762fc6faf --- /dev/null +++ b/components/lwip/test_afl_host/Makefile @@ -0,0 +1,36 @@ +COMPONENTS_DIR=../.. +CFLAGS=-std=gnu99 -Og -ggdb -ffunction-sections -fdata-sections -nostdlib -Wall -Werror=all -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wextra -Wno-unused-parameter -Wno-sign-compare -Wno-address -Wno-unused-variable -DESP_PLATFORM -D IDF_VER=\"v3.1-dev-961-ga2556229-dirty\" -MMD -MP -DWITH_POSIX \ +-DIRAM_ATTR='' -D__ESP_ATTR_H__ +INC_DIRS=-I . -I $(COMPONENTS_DIR)/lwip/include/lwip -I $(COMPONENTS_DIR)/lwip/include/lwip/port -I $(COMPONENTS_DIR)/lwip/include/lwip/posix -I $(COMPONENTS_DIR)/lwip/apps/ping -I $(COMPONENTS_DIR)/app_trace/include -I $(COMPONENTS_DIR)/app_update/include -I $(COMPONENTS_DIR)/bootloader_support/include -I $(COMPONENTS_DIR)/bt/include -I $(COMPONENTS_DIR)/coap/port/include -I $(COMPONENTS_DIR)/coap/port/include/coap -I $(COMPONENTS_DIR)/coap/libcoap/include -I \ $(COMPONENTS_DIR)/coap/libcoap/include/coap -I $(COMPONENTS_DIR)/console -I $(COMPONENTS_DIR)/cxx/include -I $(COMPONENTS_DIR)/driver/include -I $(COMPONENTS_DIR)/esp-tls -I $(COMPONENTS_DIR)/esp32/include -I $(COMPONENTS_DIR)/esp_adc_cal/include -I $(COMPONENTS_DIR)/ethernet/include -I $(COMPONENTS_DIR)/expat/port/include -I $(COMPONENTS_DIR)/expat/include/expat -I $(COMPONENTS_DIR)/fatfs/src -I $(COMPONENTS_DIR)/freertos/include -I $(COMPONENTS_DIR)/heap/include -I \ $(COMPONENTS_DIR)/idf_test/include -I $(COMPONENTS_DIR)/jsmn/include -I $(COMPONENTS_DIR)/json/cJSON -I $(COMPONENTS_DIR)/libsodium/libsodium/src/libsodium/include -I $(COMPONENTS_DIR)/libsodium/port_include -I $(COMPONENTS_DIR)/log/include -I /home/david/esp/esp-idf/examples/wifi/simple_wifi/main/include -I $(COMPONENTS_DIR)/mbedtls/port/include -I $(COMPONENTS_DIR)/mbedtls/include -I $(COMPONENTS_DIR)/mdns/include -I $(COMPONENTS_DIR)/micro-ecc/micro-ecc -I \ $(COMPONENTS_DIR)/newlib/platform_include -I $(COMPONENTS_DIR)/newlib/include -I $(COMPONENTS_DIR)/nghttp/port/include -I $(COMPONENTS_DIR)/nghttp/nghttp2/lib/includes -I $(COMPONENTS_DIR)/nvs_flash/include -I $(COMPONENTS_DIR)/openssl/include -I $(COMPONENTS_DIR)/pthread/include -I $(COMPONENTS_DIR)/sdmmc/include -I $(COMPONENTS_DIR)/smartconfig/include -I $(COMPONENTS_DIR)/soc/esp32/include -I $(COMPONENTS_DIR)/soc/include -I $(COMPONENTS_DIR)/spi_flash/include -I \ $(COMPONENTS_DIR)/spiffs/include -I $(COMPONENTS_DIR)/tcpip_adapter/include -I $(COMPONENTS_DIR)/ulp/include -I $(COMPONENTS_DIR)/vfs/include -I $(COMPONENTS_DIR)/wear_levelling/include -I $(COMPONENTS_DIR)/wpa_supplicant/include -I $(COMPONENTS_DIR)/wpa_supplicant/port/include -I $(COMPONENTS_DIR)/esp32/include -I $(COMPONENTS_DIR)/xtensa-debug-module/include +TEST_NAME=test +FUZZ=afl-fuzz +LD=$(CC) +DHCPSERVER_C_DEPENDENCY_INJECTION=-include dhcpserver_di.h + +ifeq ($(MODE),sim) + CC=gcc + CFLAGS+=-DSIM + TEST_NAME=test_sim +else + CC=afl-clang-fast +endif + +CFLAGS+=$(INC_DIRS) +OBJECTS=dhcpserver.o test.o network_mock.o + +all: $(TEST_NAME) + +dhcpserver.o: ../apps/dhcpserver.c + @echo "[CC] $<" + $(CC) $(CFLAGS) $(DHCPSERVER_C_DEPENDENCY_INJECTION) -c $< -o $@ + +%.o: %.c + @echo "[CC] $<" + @$(CC) $(CFLAGS) -c $< -o $@ + +$(TEST_NAME): $(OBJECTS) + @echo "[LD] $@" + @$(LD) $(OBJECTS) -o $@ $(LDLIBS) + +fuzz: $(TEST_NAME) + @$(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME) diff --git a/components/lwip/test_afl_host/dhcpserver_di.h b/components/lwip/test_afl_host/dhcpserver_di.h new file mode 100644 index 0000000000..4e5224eea4 --- /dev/null +++ b/components/lwip/test_afl_host/dhcpserver_di.h @@ -0,0 +1,21 @@ +/* + * dhcpserver dependecy injection -- preincluded to inject interface test functions into static variables + * + */ +#include "lwip/pbuf.h" +#include "lwip/udp.h" +#include "tcpip_adapter.h" + +static void handle_dhcp(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); + +void (*dhcp_test_static_handle_hdcp)(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) = NULL; + +void dhcp_test_init_di() +{ + dhcp_test_static_handle_hdcp = handle_dhcp; +} + +void dhcp_test_handle_dhcp(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + dhcp_test_static_handle_hdcp(arg, pcb, p, addr, port); +} diff --git a/components/lwip/test_afl_host/in/data0.bin b/components/lwip/test_afl_host/in/data0.bin new file mode 100644 index 0000000000000000000000000000000000000000..2875ab855fc74a11fa5aa714f774dee80f6f2e52 GIT binary patch literal 300 zcmZQ%WMi=AxmLvh1P4~IFo9?o=(zrksdE{OH}vV`rr=~#Ms_n6php>bI8qYJGE;N| Joc|N+GXSYq4ekH{ literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/in/data1.bin b/components/lwip/test_afl_host/in/data1.bin new file mode 100644 index 0000000000000000000000000000000000000000..17c8877f8f27245440561427a5eabe62cdae5446 GIT binary patch literal 300 zcmZQ%WMlBHo$khf1$12h#?-kCi^LEWN^S~HHf3ZqVmYvag^7nFC9y0sMK{3NoR?9C TiJ70RoJU7rs#5DePTv6lQ)mvI literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/in/data2.bin b/components/lwip/test_afl_host/in/data2.bin new file mode 100644 index 0000000000000000000000000000000000000000..b1c32b9bdeb8cbaf3963cc1fc17a299eb10e15ad GIT binary patch literal 300 zcmZQ%WMlBHo$khf1$12h#?-kCi^LEWN^S~HHf3ZsV>z&bh0zE^GVySvB$j2S=mt2O W^D@dXG4r#P^XTYHRcigm;zt00{18R} literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/in/data3.bin b/components/lwip/test_afl_host/in/data3.bin new file mode 100644 index 0000000000000000000000000000000000000000..6c6a7ae2d9da5e536fd24677cdde1f4e7e519596 GIT binary patch literal 305 zcmZQ%WMgPra_$ZT7Lan=*+n!Oi^LEWN^S~HHf3ZsVmYvaF~yRJ^^OfsN=9-)a*D30 uo~fQ0k3?c#N>P4hif)>@g<-0NMQU=QvAMa0X|g#dqargKzl^b!^?v|hwHLhr literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/in/data4.bin b/components/lwip/test_afl_host/in/data4.bin new file mode 100644 index 0000000000000000000000000000000000000000..6d10ed9bd7996be4928f575f7592e9d96d662dc7 GIT binary patch literal 300 zcmZQ%WMg>g%qhu$1*F_|b`g!nA~8gTlAD5)O&J+2nON`G@T6oU7bK_Xn(CSAnej*@ p=A{(nXQt?;nOhj9T3DneCmNfZTbL%Bb22J2v+>IqTUq~S000{)6gB_= literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/in/data5.bin b/components/lwip/test_afl_host/in/data5.bin new file mode 100644 index 0000000000000000000000000000000000000000..51f77595fb40ec25a156cdd01cf30cfe40cea8cc GIT binary patch literal 311 zcmZQ%WMg>g%qhu$1*F_|b`g!nA~8gTlAD5)O&OVuSPraUVKxJijFwEScWii4GLj3D yQ*=%BO!droBogydit;m4bkoc&3{x#EQj-&n&CM-Llg&996`9%iWsI$?{{sLQ8W)5B literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/in/data6.bin b/components/lwip/test_afl_host/in/data6.bin new file mode 100644 index 0000000000000000000000000000000000000000..636fb4101427df688b1167edff5a87906262ad0b GIT binary patch literal 316 zcmZQ%WMj}gUB!S6yb-9@TKyZF%+M4|ZVFB|Wn{KxXN367h~>Zv78WxQ$!N*MddEf} yF)yVkKQl!)B_p{&*IdtlhtEARC$XYZ*U?zl$iUFtoQsi}jbBQ}*veY_KLY?XKpMON literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/network_mock.c b/components/lwip/test_afl_host/network_mock.c new file mode 100644 index 0000000000..be624cee14 --- /dev/null +++ b/components/lwip/test_afl_host/network_mock.c @@ -0,0 +1,74 @@ +#include +#include "lwip/opt.h" +#include "lwip/def.h" +#include "lwip/pbuf.h" +#include "lwip/udp.h" +#include "tcpip_adapter.h" +#include + +u16_t lwip_htons(u16_t n) +{ + return 0; +} + +u32_t lwip_htonl(u32_t n) +{ + return 0; +} + +esp_err_t tcpip_adapter_get_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info) +{ + return ESP_OK; +} + +struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) +{ + struct pbuf * p; + p = (struct pbuf *)malloc(MEMP_PBUF_POOL); + p->tot_len = length; + p->next = NULL; + p->type = PBUF_POOL; + p->len = length; + p->payload = malloc(length); + return p; +} + +u8_t pbuf_free(struct pbuf *p) +{ + if (p) { + if (p->payload) { + free(p->payload); + p->payload = NULL; + } + free (p); + p = NULL; + } + return 1; +} + +err_t udp_sendto(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u16_t dst_port) +{ + return ESP_OK; +} + +void udp_remove(struct udp_pcb *pcb) +{ +} + +struct udp_pcb *udp_new(void) +{ + return NULL; +} + +err_t udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) +{ + return ESP_OK; +} + +void udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg) +{ +} + +void udp_disconnect(struct udp_pcb *pcb) +{ +} diff --git a/components/lwip/test_afl_host/test.c b/components/lwip/test_afl_host/test.c new file mode 100644 index 0000000000..821e56f57f --- /dev/null +++ b/components/lwip/test_afl_host/test.c @@ -0,0 +1,53 @@ +#include +#include "lwip/pbuf.h" +#include "lwip/udp.h" +#include "tcpip_adapter.h" +#include + +const ip_addr_t ip_addr_any; +ip4_addr_t server_ip; +struct netif mynetif; + +// Dependency injected static function to pass the packet into parser +void dhcp_test_handle_dhcp(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); +void dhcp_test_init_di(); + +// Starting the test +int main() +{ + uint8_t *buf; + struct pbuf *p; + FILE *file; + size_t len = 1460; + + dhcp_test_init_di(); + + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + buf = p->payload; + + IP4_ADDR(&server_ip, 192,168,4,1); + dhcps_start(&mynetif, server_ip); + +#ifdef SIM + memset(buf, 0, 1460); + + file = fopen("in/data1.bin", "r"); + if (file) { + len = fread(buf, 1, 1460, file); + } + fclose(file); + int i; + for (i=0; i<1; i++) { +#else + while (__AFL_LOOP(1000)) { + memset(buf, 0, 1460); + size_t len = read(0, buf, 1460); +#endif + p->len = len; + p->tot_len = len; + p->next = NULL; + + dhcp_test_handle_dhcp(NULL, NULL, p, &ip_addr_any, 0); + } + return 0; +} From 684d211af33a1c35fa1ee3058865e178118311c4 Mon Sep 17 00:00:00 2001 From: krzychb Date: Wed, 9 May 2018 07:45:54 +0200 Subject: [PATCH 088/187] Corrected link rendering and additional translations --- docs/en/index.rst | 4 ++-- docs/zh_CN/index.rst | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/en/index.rst b/docs/en/index.rst index f3445d8dce..681d526d46 100644 --- a/docs/en/index.rst +++ b/docs/en/index.rst @@ -23,8 +23,8 @@ This is the documentation for Espressif IoT Development Framework (`esp-idf `_)的文档. ESP-IDF 是`ESP32 `_ 芯片的官方开发框架. +这是乐鑫 IoT 开发开发框架 (`esp-idf `_) 的文档. ESP-IDF 是 `ESP32 `_ 芯片的官方开发框架. ================== ================== ================== |快速入门|_ |API 参考|_ |H/W 参考|_ @@ -23,7 +23,7 @@ ESP-IDF 编程指南 .. |H/W 参考| image:: ../_static/hw-reference.gif .. _H/W 参考: hw-reference/index.html -.. |Api 指南| image:: ../_static/api-guides.gif +.. |API 指南| image:: ../_static/api-guides.gif .. _API 指南: api-guides/index.html .. |贡献代码| image:: ../_static/contribute.gif @@ -42,7 +42,7 @@ ESP-IDF 编程指南 API 指南 贡献代码 相关资源 - Copyrights - About + 版权 + 关于 * :ref:`genindex` From cf81db40a2a5afa8df4e2b14a47f25a01f14621c Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 20 Apr 2018 17:42:13 +0800 Subject: [PATCH 089/187] sdio: allow reads/writes with lengths not divisible by 4 CMD53 in byte mode supports transfers of any number of bytes between 1 and 512. This change removes limitation that the number of bytes must be divisible by 4. Host quirk, that such transfers must be split into two commands (one for the aligned part and the other one for unaligned) is taken into account. --- components/driver/sdmmc_transaction.c | 10 +++--- components/sdmmc/sdmmc_cmd.c | 50 +++++++++++++++++++++++---- components/sdmmc/test/test_sdio.c | 35 +++++++++++-------- 3 files changed, 70 insertions(+), 25 deletions(-) diff --git a/components/driver/sdmmc_transaction.c b/components/driver/sdmmc_transaction.c index 52dec2991c..c53b4b11c4 100644 --- a/components/driver/sdmmc_transaction.c +++ b/components/driver/sdmmc_transaction.c @@ -122,9 +122,10 @@ esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo) // convert cmdinfo to hardware register value sdmmc_hw_cmd_t hw_cmd = make_hw_cmd(cmdinfo); if (cmdinfo->data) { - if (cmdinfo->datalen < 4 || cmdinfo->blklen % 4 != 0) { - ESP_LOGD(TAG, "%s: invalid size: total=%d block=%d", - __func__, cmdinfo->datalen, cmdinfo->blklen); + // Length should be either <4 or >=4 and =0 (mod 4). + if (cmdinfo->datalen >= 4 && cmdinfo->datalen % 4 != 0) { + ESP_LOGD(TAG, "%s: invalid size: total=%d", + __func__, cmdinfo->datalen); ret = ESP_ERR_INVALID_SIZE; goto out; } @@ -212,7 +213,8 @@ static void fill_dma_descriptors(size_t num_desc) desc->owned_by_idmac = 1; desc->buffer1_ptr = s_cur_transfer.ptr; desc->next_desc_ptr = (last) ? NULL : &s_dma_desc[(next + 1) % SDMMC_DMA_DESC_CNT]; - desc->buffer1_size = size_to_fill; + assert(size_to_fill < 4 || size_to_fill % 4 == 0); + desc->buffer1_size = (size_to_fill + 3) & (~3); s_cur_transfer.size_remaining -= size_to_fill; s_cur_transfer.ptr += size_to_fill; diff --git a/components/sdmmc/sdmmc_cmd.c b/components/sdmmc/sdmmc_cmd.c index 7279dec44c..ab88b7780f 100644 --- a/components/sdmmc/sdmmc_cmd.c +++ b/components/sdmmc/sdmmc_cmd.c @@ -1269,22 +1269,57 @@ static esp_err_t sdmmc_io_rw_extended(sdmmc_card_t* card, int func, esp_err_t sdmmc_io_read_bytes(sdmmc_card_t* card, uint32_t function, uint32_t addr, void* dst, size_t size) { - return sdmmc_io_rw_extended(card, function, addr, - SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT, - dst, size); + /* host quirk: SDIO transfer with length not divisible by 4 bytes + * has to be split into two transfers: one with aligned length, + * the other one for the remaining 1-3 bytes. + */ + uint8_t *pc_dst = dst; + while (size > 0) { + size_t size_aligned = size & (~3); + size_t will_transfer = size_aligned > 0 ? size_aligned : size; + + esp_err_t err = sdmmc_io_rw_extended(card, function, addr, + SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT, + pc_dst, will_transfer); + if (err != ESP_OK) { + return err; + } + pc_dst += will_transfer; + size -= will_transfer; + addr += will_transfer; + } + return ESP_OK; } esp_err_t sdmmc_io_write_bytes(sdmmc_card_t* card, uint32_t function, uint32_t addr, const void* src, size_t size) { - return sdmmc_io_rw_extended(card, function, addr, - SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT, - (void*) src, size); + /* same host quirk as in sdmmc_io_read_bytes */ + const uint8_t *pc_src = (const uint8_t*) src; + + while (size > 0) { + size_t size_aligned = size & (~3); + size_t will_transfer = size_aligned > 0 ? size_aligned : size; + + esp_err_t err = sdmmc_io_rw_extended(card, function, addr, + SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT, + (void*) pc_src, will_transfer); + if (err != ESP_OK) { + return err; + } + pc_src += will_transfer; + size -= will_transfer; + addr += will_transfer; + } + return ESP_OK; } esp_err_t sdmmc_io_read_blocks(sdmmc_card_t* card, uint32_t function, uint32_t addr, void* dst, size_t size) { + if (size % 4 != 0) { + return ESP_ERR_INVALID_SIZE; + } return sdmmc_io_rw_extended(card, function, addr, SD_ARG_CMD53_READ | SD_ARG_CMD53_INCREMENT | SD_ARG_CMD53_BLOCK_MODE, dst, size); @@ -1293,6 +1328,9 @@ esp_err_t sdmmc_io_read_blocks(sdmmc_card_t* card, uint32_t function, esp_err_t sdmmc_io_write_blocks(sdmmc_card_t* card, uint32_t function, uint32_t addr, const void* src, size_t size) { + if (size % 4 != 0) { + return ESP_ERR_INVALID_SIZE; + } return sdmmc_io_rw_extended(card, function, addr, SD_ARG_CMD53_WRITE | SD_ARG_CMD53_INCREMENT | SD_ARG_CMD53_BLOCK_MODE, (void*) src, size); diff --git a/components/sdmmc/test/test_sdio.c b/components/sdmmc/test/test_sdio.c index 8b885baf55..f4eae05980 100644 --- a/components/sdmmc/test/test_sdio.c +++ b/components/sdmmc/test/test_sdio.c @@ -309,35 +309,33 @@ static void test_cmd52_read_write_single_byte(sdmmc_card_t* card) TEST_ASSERT_EQUAL_UINT8(test_byte_2, val); } -static void test_cmd53_read_write_multiple_bytes(sdmmc_card_t* card) +static void test_cmd53_read_write_multiple_bytes(sdmmc_card_t* card, size_t n_bytes) { printf("Write multiple bytes using CMD53\n"); const size_t scratch_area_reg = SLCHOST_CONF_W0 - DR_REG_SLCHOST_BASE; uint8_t* src = heap_caps_malloc(512, MALLOC_CAP_DMA); uint32_t* src_32 = (uint32_t*) src; - const size_t n_words = 6; - srand(0); - for (size_t i = 0; i < n_words; ++i) { + + for (size_t i = 0; i < (n_bytes + 3) / 4; ++i) { src_32[i] = rand(); } - size_t len = n_words * sizeof(uint32_t); - TEST_ESP_OK(sdmmc_io_write_bytes(card, 1, scratch_area_reg, src, len)); - ESP_LOG_BUFFER_HEX(TAG, src, len); + TEST_ESP_OK(sdmmc_io_write_bytes(card, 1, scratch_area_reg, src, n_bytes)); + ESP_LOG_BUFFER_HEX(TAG, src, n_bytes); printf("Read back using CMD52\n"); uint8_t* dst = heap_caps_malloc(512, MALLOC_CAP_DMA); - for (size_t i = 0; i < len; ++i) { + for (size_t i = 0; i < n_bytes; ++i) { TEST_ESP_OK(sdmmc_io_read_byte(card, 1, scratch_area_reg + i, &dst[i])); } - ESP_LOG_BUFFER_HEX(TAG, dst, len); - TEST_ASSERT_EQUAL_UINT8_ARRAY(src, dst, len); + ESP_LOG_BUFFER_HEX(TAG, dst, n_bytes); + TEST_ASSERT_EQUAL_UINT8_ARRAY(src, dst, n_bytes); printf("Read back using CMD53\n"); - TEST_ESP_OK(sdmmc_io_read_bytes(card, 1, scratch_area_reg, dst, len)); - ESP_LOG_BUFFER_HEX(TAG, dst, len); - TEST_ASSERT_EQUAL_UINT8_ARRAY(src, dst, len); + TEST_ESP_OK(sdmmc_io_read_bytes(card, 1, scratch_area_reg, dst, n_bytes)); + ESP_LOG_BUFFER_HEX(TAG, dst, n_bytes); + TEST_ASSERT_EQUAL_UINT8_ARRAY(src, dst, n_bytes); free(src); free(dst); @@ -364,9 +362,16 @@ TEST_CASE("can probe and talk to ESP32 SDIO slave", "[sdio][ignore]") /* Set up standard SDIO registers */ sdio_slave_common_init(card); - for (int repeat = 0; repeat < 10; ++repeat) { + srand(0); + for (int repeat = 0; repeat < 4; ++repeat) { test_cmd52_read_write_single_byte(card); - test_cmd53_read_write_multiple_bytes(card); + test_cmd53_read_write_multiple_bytes(card, 1); + test_cmd53_read_write_multiple_bytes(card, 2); + test_cmd53_read_write_multiple_bytes(card, 3); + test_cmd53_read_write_multiple_bytes(card, 4); + test_cmd53_read_write_multiple_bytes(card, 5); + test_cmd53_read_write_multiple_bytes(card, 23); + test_cmd53_read_write_multiple_bytes(card, 24); } sdio_slave_set_blocksize(card, 0, 512); From 9379d7b9f906df732a466c610e856139ba668f46 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 20 Apr 2018 17:48:34 +0800 Subject: [PATCH 090/187] sdmmc: wait for command done event even if data transfer is over This fixes errors logged on the console: sdmmc_req: handle_idle_state_events unhandled: 00000004 00000000 The issue happens if "data done" event occurs before "command done". State machine code did not check *which* event occurred in SENDING_CMD state, and went to IDLE or SENDING_DATA state on any non-error event. In this case, we can't process "data done" event until command has completed. This change introduces "unhandled event" mask, which is carried over from one run of process_events to the other. This allows waiting for the "command done" event to complete, and then process "data done" event. Ref TW17126. --- components/driver/sdmmc_transaction.c | 49 +++++++++++++++++++-------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/components/driver/sdmmc_transaction.c b/components/driver/sdmmc_transaction.c index c53b4b11c4..8abf9bb923 100644 --- a/components/driver/sdmmc_transaction.c +++ b/components/driver/sdmmc_transaction.c @@ -74,8 +74,10 @@ static esp_pm_lock_handle_t s_pm_lock; static esp_err_t handle_idle_state_events(); static sdmmc_hw_cmd_t make_hw_cmd(sdmmc_command_t* cmd); -static esp_err_t handle_event(sdmmc_command_t* cmd, sdmmc_req_state_t* pstate); -static esp_err_t process_events(sdmmc_event_t evt, sdmmc_command_t* cmd, sdmmc_req_state_t* pstate); +static esp_err_t handle_event(sdmmc_command_t* cmd, sdmmc_req_state_t* state, + sdmmc_event_t* unhandled_events); +static esp_err_t process_events(sdmmc_event_t evt, sdmmc_command_t* cmd, + sdmmc_req_state_t* pstate, sdmmc_event_t* unhandled_events); static void process_command_response(uint32_t status, sdmmc_command_t* cmd); static void fill_dma_descriptors(size_t num_desc); static size_t get_free_descriptors_count(); @@ -157,8 +159,9 @@ esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo) // process events until transfer is complete cmdinfo->error = ESP_OK; sdmmc_req_state_t state = SDMMC_SENDING_CMD; + sdmmc_event_t unhandled_events = { 0 }; while (state != SDMMC_IDLE) { - ret = handle_event(cmdinfo, &state); + ret = handle_event(cmdinfo, &state, &unhandled_events); if (ret != ESP_OK) { break; } @@ -247,10 +250,11 @@ static esp_err_t handle_idle_state_events() } -static esp_err_t handle_event(sdmmc_command_t* cmd, sdmmc_req_state_t* state) +static esp_err_t handle_event(sdmmc_command_t* cmd, sdmmc_req_state_t* state, + sdmmc_event_t* unhandled_events) { - sdmmc_event_t evt; - esp_err_t err = sdmmc_host_wait_for_event(cmd->timeout_ms / portTICK_PERIOD_MS, &evt); + sdmmc_event_t event; + esp_err_t err = sdmmc_host_wait_for_event(cmd->timeout_ms / portTICK_PERIOD_MS, &event); if (err != ESP_OK) { ESP_LOGE(TAG, "sdmmc_host_wait_for_event returned 0x%x", err); if (err == ESP_ERR_TIMEOUT) { @@ -258,8 +262,13 @@ static esp_err_t handle_event(sdmmc_command_t* cmd, sdmmc_req_state_t* state) } return err; } - ESP_LOGV(TAG, "sdmmc_handle_event: evt %08x %08x", evt.sdmmc_status, evt.dma_status); - process_events(evt, cmd, state); + ESP_LOGV(TAG, "sdmmc_handle_event: event %08x %08x, unhandled %08x %08x", + event.sdmmc_status, event.dma_status, + unhandled_events->sdmmc_status, unhandled_events->dma_status); + event.sdmmc_status |= unhandled_events->sdmmc_status; + event.dma_status |= unhandled_events->dma_status; + process_events(event, cmd, state, unhandled_events); + ESP_LOGV(TAG, "sdmmc_handle_event: events unhandled: %08x %08x", unhandled_events->sdmmc_status, unhandled_events->dma_status); return ESP_OK; } @@ -365,7 +374,8 @@ static inline bool mask_check_and_clear(uint32_t* state, uint32_t mask) { return ret; } -static esp_err_t process_events(sdmmc_event_t evt, sdmmc_command_t* cmd, sdmmc_req_state_t* pstate) +static esp_err_t process_events(sdmmc_event_t evt, sdmmc_command_t* cmd, + sdmmc_req_state_t* pstate, sdmmc_event_t* unhandled_events) { const char* const s_state_names[] __attribute__((unused)) = { "IDLE", @@ -374,7 +384,8 @@ static esp_err_t process_events(sdmmc_event_t evt, sdmmc_command_t* cmd, sdmmc_r "BUSY" }; sdmmc_event_t orig_evt = evt; - ESP_LOGV(TAG, "%s: state=%s", __func__, s_state_names[*pstate]); + ESP_LOGV(TAG, "%s: state=%s evt=%x dma=%x", __func__, s_state_names[*pstate], + evt.sdmmc_status, evt.dma_status); sdmmc_req_state_t next_state = *pstate; sdmmc_req_state_t state = (sdmmc_req_state_t) -1; while (next_state != state) { @@ -388,12 +399,19 @@ static esp_err_t process_events(sdmmc_event_t evt, sdmmc_command_t* cmd, sdmmc_r process_command_response(orig_evt.sdmmc_status, cmd); break; // Need to wait for the CMD_DONE interrupt } - process_command_response(orig_evt.sdmmc_status, cmd); - if (cmd->error != ESP_OK || cmd->data == NULL) { - next_state = SDMMC_IDLE; - break; + if (mask_check_and_clear(&evt.sdmmc_status, SDMMC_INTMASK_CMD_DONE)) { + process_command_response(orig_evt.sdmmc_status, cmd); + if (cmd->error != ESP_OK) { + next_state = SDMMC_IDLE; + break; + } + + if (cmd->data == NULL) { + next_state = SDMMC_IDLE; + } else { + next_state = SDMMC_SENDING_DATA; + } } - next_state = SDMMC_SENDING_DATA; break; @@ -431,6 +449,7 @@ static esp_err_t process_events(sdmmc_event_t evt, sdmmc_command_t* cmd, sdmmc_r ESP_LOGV(TAG, "%s state=%s next_state=%s", __func__, s_state_names[state], s_state_names[next_state]); } *pstate = state; + *unhandled_events = evt; return ESP_OK; } From 79de77107f6f87b3673cb5a877e4635ae807bb55 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 10 May 2018 18:19:30 +0800 Subject: [PATCH 091/187] docs: update list of third-party libraries, copyrights, and licenses --- docs/en/COPYRIGHT.rst | 68 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/docs/en/COPYRIGHT.rst b/docs/en/COPYRIGHT.rst index 65980b7ec8..8068d135d6 100644 --- a/docs/en/COPYRIGHT.rst +++ b/docs/en/COPYRIGHT.rst @@ -4,23 +4,24 @@ Copyrights and Licenses Software Copyrights =================== -All original source code in this repository is Copyright (C) 2015-2016 -Espressif Systems. This source code is licensed under the Apache -License 2.0 as described in the file LICENSE. +All original source code in this repository is Copyright (C) 2015-2018 Espressif Systems. This source code is licensed under the Apache License 2.0 as described in the file LICENSE. -Additional third party copyrighted code is included under the following licenses: +Additional third party copyrighted code is included under the following licenses. -* Newlib_ (components/newlib) is licensed under the BSD License and is Copyright of various parties, as described in the file components/newlib/COPYING.NEWLIB. +Where source code headers specify Copyright & License information, this information takes precedence over the summaries made here. -* Xtensa header files (components/esp32/include/xtensa) are Copyright (C) 2013 Tensilica Inc and are licensed under the MIT License as reproduce in the individual header files. +Firmware Components +------------------- -* `esptool.py`_ (components/esptool_py/esptool) is Copyright (C) 2014-2016 Fredrik Ahlberg, Angus Gratton and is licensed under the GNU General Public License v2, as described in the file components/esptool_py/LICENSE. +These third party libraries can be included into the application (firmware) produced by ESP-IDF. -* Original parts of FreeRTOS_ (components/freertos) are Copyright (C) 2015 Real Time Engineers Ltd and is licensed under the GNU General Public License V2 with the FreeRTOS Linking Exception, as described in the file components/freertos/license.txt. +* :component:`Newlib ` is licensed under the BSD License and is Copyright of various parties, as described in :component_file:`COPYING.NEWLIB`. -* Original parts of LWIP_ (components/lwip) are Copyright (C) 2001, 2002 Swedish Institute of Computer Science and are licensed under the BSD License as described in the file components/lwip/COPYING. +* :component:`Xtensa header files` are Copyright (C) 2013 Tensilica Inc and are licensed under the MIT License as reproduced in the individual header files. -* KConfig (tools/kconfig) is Copyright (C) 2002 Roman Zippel and others, and is licensed under the GNU General Public License V2. +* Original parts of FreeRTOS_ (components/freertos) are Copyright (C) 2015 Real Time Engineers Ltd and is licensed under the GNU General Public License V2 with the FreeRTOS Linking Exception, as described in :component_file:`license.txt`. + +* Original parts of LWIP_ (components/lwip) are Copyright (C) 2001, 2002 Swedish Institute of Computer Science and are licensed under the BSD License as described in :component_file:`COPYING file`. * `wpa_supplicant`_ Copyright (c) 2003-2005 Jouni Malinen and licensed under the BSD license. @@ -28,18 +29,46 @@ Additional third party copyrighted code is included under the following licenses * `JSMN`_ JSON Parser (components/jsmn) Copyright (c) 2010 Serge A. Zaitsev and licensed under the MIT license. -* `argtable3`_ arugment parsing library Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann and licensed under 3-clause BSD license. +* `argtable3`_ argument parsing library Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann and licensed under 3-clause BSD license. -* `linenoise`_ line editing library Copyright (c) 2010-2014, Salvatore Sanfilippo , Copyright (c) 2010-2013, Pieter Noordhuis , licensed under 2-clause BSD license. +* `linenoise`_ line editing library Copyright (c) 2010-2014 Salvatore Sanfilippo, Copyright (c) 2010-2013 Pieter Noordhuis, licensed under 2-clause BSD license. + +* `libcoap`_ COAP library Copyright (c) 2010-2017 Olaf Bergmann and others, is licensed under 2-clause BSD license. + +* `libexpat`_ XML parsing library Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper, Copyright (c) 2001-2016 Expat maintainers, is licensed under MIT license. + +* `FatFS`_ library, Copyright (C) 2017 ChaN, is licensed under :component_file:`a BSD-style license `. + +* `cJSON`_ library, Copyright (c) 2009-2017 Dave Gamble and cJSON contributors, is licensed under MIT license. + +* `libsodium`_ library, Copyright (c) 2013-2018 Frank Denis, is licensed under ISC license. + +* `micro-ecc`_ library, Copyright (c) 2014 Kenneth MacKay, is licensed under 2-clause BSD license. + +* `nghttp2`_ library, Copyright (c) 2012, 2014, 2015, 2016 Tatsuhiro Tsujikawa, Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors, is licensed under MIT license. + +* `Mbed TLS`_ library, Copyright (C) 2006-2018 ARM Limited, is licensed under Apache License 2.0. + +* `SPIFFS`_ library, Copyright (c) 2013-2017 Peter Andersson, is licensed under MIT license. + +* :component_file:`SD/MMC driver ` is derived from `OpenBSD SD/MMC driver`_, Copyright (c) 2006 Uwe Stuehler, and is licensed under BSD license. + +Build Tools +----------- + +This is the list of licenses for tools included in this repository, which are used to build applications. The tools do not become part of the application (firmware), so their license does not affect licensing of the application. + +* :component:`esptool.py ` is Copyright (C) 2014-2016 Fredrik Ahlberg, Angus Gratton and is licensed under the GNU General Public License v2, as described in :component_file:`LICENSE file`. + +* :idf:`KConfig ` is Copyright (C) 2002 Roman Zippel and others, and is licensed under the GNU General Public License V2. -Where source code headers specify Copyright & License information, this information takes precedence over the summaries made here. ROM Source Code Copyrights ========================== ESP32 mask ROM hardware includes binaries compiled from portions of the following third party software: -* Newlib_, as licensed under the BSD License and Copyright of various parties, as described in the file components/newlib/COPYING.NEWLIB. +* :component:`Newlib `, licensed under the BSD License and is Copyright of various parties, as described in :component_file:`COPYING.NEWLIB`. * Xtensa libhal, Copyright (c) Tensilica Inc and licensed under the MIT license (see below). @@ -88,6 +117,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI TJpgDec License =============== + TJpgDec - Tiny JPEG Decompressor R0.01 (C)ChaN, 2011 The TJpgDec is a generic JPEG decompressor module for tiny embedded systems. This is a free software that opened for education, research and commercial @@ -112,4 +142,14 @@ Copyright (C) 2011, ChaN, all right reserved. .. _JSMN: http://zserge.com/jsmn.html .. _argtable3: https://github.com/argtable/argtable3 .. _linenoise: https://github.com/antirez/linenoise +.. _libcoap: https://github.com/obgm/libcoap +.. _fatfs: http://elm-chan.org/fsw/ff/00index_e.html +.. _cJSON: https://github.com/DaveGamble/cJSON +.. _libsodium: https://github.com/jedisct1/libsodium +.. _libexpat: https://github.com/libexpat/libexpat +.. _micro-ecc: https://github.com/kmackay/micro-ecc +.. _nghttp2: https://github.com/nghttp2/nghttp2 +.. _OpenBSD SD/MMC driver: https://github.com/openbsd/src/blob/f303646/sys/dev/sdmmc/sdmmc.c +.. _Mbed TLS: https://github.com/ARMmbed/mbedtls +.. _spiffs: https://github.com/pellepl/spiffs From 3b3a915552de45e93f0b593134c8301d92280a6c Mon Sep 17 00:00:00 2001 From: He Yin Ling Date: Sun, 7 Jan 2018 20:24:38 +0800 Subject: [PATCH 092/187] tiny-test-fw: implement `env.get_pc_nic_info`: this method is used to get mac/ipv4/ipv6 address for one NIC --- tools/tiny-test-fw/Env.py | 31 +++++++++++++++++++++++++------ tools/tiny-test-fw/docs/index.rst | 1 + 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/tools/tiny-test-fw/Env.py b/tools/tiny-test-fw/Env.py index da5c0b5982..fa194d10c9 100644 --- a/tools/tiny-test-fw/Env.py +++ b/tools/tiny-test-fw/Env.py @@ -17,6 +17,8 @@ import os import threading import functools +import netifaces + import EnvConfig @@ -130,17 +132,34 @@ class Env(object): """ return self.config.get_variable(variable_name) + PROTO_MAP = { + "ipv4": netifaces.AF_INET, + "ipv6": netifaces.AF_INET6, + "mac": netifaces.AF_LINK, + } + @_synced - def get_pc_nic_info(self, nic_name="pc_nic"): + def get_pc_nic_info(self, nic_name="pc_nic", proto="ipv4"): """ get_pc_nic_info(nic_name="pc_nic") - try to get nic info (ip address, ipv6 address, mac address) + try to get info of a specified NIC and protocol. - :param nic_name: pc nic name. allows passing variable name, nic name value or omitted (to get default nic info). - :return: a dict of address ("ipv4", "ipv6", "mac") if successfully found. otherwise None. + :param nic_name: pc nic name. allows passing variable name, nic name value. + :param proto: "ipv4", "ipv6" or "mac" + :return: a dict of nic info if successfully found. otherwise None. + nic info keys could be different for different protocols. + key "addr" is available for both mac, ipv4 and ipv6 pic info. """ - # TODO: need to implement auto get nic info method - return self.config.get_variable("nic_info/" + nic_name) + interfaces = netifaces.interfaces() + if nic_name in interfaces: + # the name is in the interface list, we regard it as NIC name + if_addr = netifaces.ifaddresses(nic_name) + else: + # it's not in interface name list, we assume it's variable name + _nic_name = self.get_variable(nic_name) + if_addr = netifaces.ifaddresses(_nic_name) + + return if_addr[self.PROTO_MAP[proto]][0] @_synced def close(self): diff --git a/tools/tiny-test-fw/docs/index.rst b/tools/tiny-test-fw/docs/index.rst index a70e6bf328..22cfd73a86 100644 --- a/tools/tiny-test-fw/docs/index.rst +++ b/tools/tiny-test-fw/docs/index.rst @@ -128,6 +128,7 @@ The following 3rd party lib is required: * pyserial * pyyaml * xunitgen + * netifaces To build document, we need to install ``Sphinx`` and ``sphinx-rtd-theme`` (you may replace this with your own theme). From 98d1f05ab520e16cfa9861f57dcdf285178b4d56 Mon Sep 17 00:00:00 2001 From: He Yin Ling Date: Thu, 11 Jan 2018 17:49:27 +0800 Subject: [PATCH 093/187] tiny-test-fw: add utilities: 1. Attenuator: control programmable attenuator 2. PowerControl: control APC PDU to power on/off devices 3. LineChart: use matplotlib to draw line chart --- tools/tiny-test-fw/Utility/Attenuator.py | 70 ++++++++++++++++ tools/tiny-test-fw/Utility/LineChart.py | 50 ++++++++++++ tools/tiny-test-fw/Utility/PowerControl.py | 95 ++++++++++++++++++++++ tools/tiny-test-fw/docs/index.rst | 1 + 4 files changed, 216 insertions(+) create mode 100644 tools/tiny-test-fw/Utility/Attenuator.py create mode 100644 tools/tiny-test-fw/Utility/LineChart.py create mode 100644 tools/tiny-test-fw/Utility/PowerControl.py diff --git a/tools/tiny-test-fw/Utility/Attenuator.py b/tools/tiny-test-fw/Utility/Attenuator.py new file mode 100644 index 0000000000..451c488112 --- /dev/null +++ b/tools/tiny-test-fw/Utility/Attenuator.py @@ -0,0 +1,70 @@ +# 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. + +""" +Internal use only. + +This file provide method to control programmable attenuator. +""" + +import time +import serial + + +def set_att(port, att, att_fix=False): + """ + set attenuation value on the attenuator + + :param port: serial port for attenuator + :param att: attenuation value we want to set + :param att_fix: fix the deviation with experience value + :return: True or False + """ + + assert 0 <= att <= 62 + # fix att + if att_fix: + if att >= 33 and (att - 30 + 1) % 4 == 0: + att_t = att - 1 + elif att >= 33 and (att - 30) % 4 == 0: + att_t = att + 1 + else: + att_t = att + else: + att_t = att + + serial_port = serial.Serial(port, baudrate=9600, rtscts=False, timeout=0.1) + if serial_port.isOpen() is False: + raise IOError("attenuator control, failed to open att port") + + cmd_hex = "7e7e10{:02x}{:x}".format(att_t, 0x10 + att_t) + exp_res_hex = "7e7e20{:02x}00{:x}".format(att_t, 0x20 + att_t) + + cmd = cmd_hex.decode("hex") + exp_res = exp_res_hex.decode("hex") + + serial_port.write(cmd) + res = "" + + for i in range(5): + res += serial_port.read(20) + if res == exp_res: + result = True + break + time.sleep(0.1) + else: + result = False + + serial_port.close() + return result diff --git a/tools/tiny-test-fw/Utility/LineChart.py b/tools/tiny-test-fw/Utility/LineChart.py new file mode 100644 index 0000000000..fd5d4b5e65 --- /dev/null +++ b/tools/tiny-test-fw/Utility/LineChart.py @@ -0,0 +1,50 @@ +# 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. + +import matplotlib +# fix can't draw figure with docker +matplotlib.use('Agg') +import matplotlib.pyplot as plt + + +# candidate colors +LINE_STYLE_CANDIDATE = ['b-o', 'r-o', 'k-o', 'm-o', 'c-o', 'g-o', 'y-o', + 'b-s', 'r-s', 'k-s', 'm-s', 'c-s', 'g-s', 'y-s'] + + +def draw_line_chart(file_name, title, x_label, y_label, data_list): + """ + draw line chart and save to file. + + :param file_name: abs/relative file name to save chart figure + :param title: chart title + :param x_label: x-axis label + :param y_label: y-axis label + :param data_list: a list of line data. + each line is a dict of ("x-axis": list, "y-axis": list, "label": string) + """ + + plt.figure(figsize=(12, 6)) + plt.grid(True) + + for i, data in enumerate(data_list): + plt.plot(data["x-axis"], data["y-axis"], LINE_STYLE_CANDIDATE[i], label=data["label"]) + + plt.xlabel(x_label) + plt.ylabel(y_label) + plt.legend(fontsize=12) + plt.title(title) + plt.tight_layout(pad=3, w_pad=3, h_pad=3) + plt.savefig(file_name) + plt.close() diff --git a/tools/tiny-test-fw/Utility/PowerControl.py b/tools/tiny-test-fw/Utility/PowerControl.py new file mode 100644 index 0000000000..5b7df4c4f0 --- /dev/null +++ b/tools/tiny-test-fw/Utility/PowerControl.py @@ -0,0 +1,95 @@ +# 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. + +""" +Internal use only. + +This file implements controlling APC PDU via telnet. +""" + +import telnetlib + + +class Control(object): + """ control APC via telnet """ + + @classmethod + def apc_telnet_make_choice(cls, telnet, choice): + """ select a choice """ + telnet.read_until("Event Log") + telnet.read_until(">") + telnet.write(choice + "\r\n") + + @classmethod + def apc_telnet_common_action(cls, telnet, check_str, action): + """ wait until a pattern and then write a line """ + telnet.read_until(check_str) + telnet.write(action + "\r\n") + + @classmethod + def control(cls, apc_ip, control_dict): + """ + control APC + + :param apc_ip: IP of APC + :param control_dict: dict with outlet ID and "ON" or "OFF" + """ + + for _outlet in control_dict: + assert 0 < _outlet < 9 + assert control_dict[_outlet] in ["ON", "OFF"] + + # telnet + # set timeout as 2s so that it won't waste time even can't access APC + tn = telnetlib.Telnet(host=apc_ip, timeout=5) + # log on + cls.apc_telnet_common_action(tn, "User Name :", "apc") + cls.apc_telnet_common_action(tn, "Password :", "apc") + # go to Device Manager + cls.apc_telnet_make_choice(tn, "1") + # go to Outlet Management + cls.apc_telnet_make_choice(tn, "2") + # go to Outlet Control/Configuration + cls.apc_telnet_make_choice(tn, "1") + + # do select Outlet and control + for _outlet in control_dict: + # choose Outlet + cls.apc_telnet_make_choice(tn, str(_outlet)) + # choose Control Outlet + cls.apc_telnet_make_choice(tn, "1") + # choose action + _action = control_dict[_outlet] + if "ON" in _action: + cls.apc_telnet_make_choice(tn, "1") + else: + cls.apc_telnet_make_choice(tn, "2") + # do confirm + cls.apc_telnet_common_action(tn, "cancel :", "YES") + cls.apc_telnet_common_action(tn, "continue...", "") + # return to Outlet Control/Configuration + cls.apc_telnet_make_choice(tn, "\033") + cls.apc_telnet_make_choice(tn, "\033") + + # exit to main menu and logout + tn.write("\033\r\n") + tn.write("\033\r\n") + tn.write("\033\r\n") + tn.write("4\r\n") + + @classmethod + def control_rest(cls, apc_ip, outlet, action): + outlet_list = range(1, 9) + outlet_list.remove(outlet) + cls.control(apc_ip, dict.fromkeys(outlet_list, action)) diff --git a/tools/tiny-test-fw/docs/index.rst b/tools/tiny-test-fw/docs/index.rst index 22cfd73a86..bc3a3f5f82 100644 --- a/tools/tiny-test-fw/docs/index.rst +++ b/tools/tiny-test-fw/docs/index.rst @@ -129,6 +129,7 @@ The following 3rd party lib is required: * pyyaml * xunitgen * netifaces + * matplotlib (if use Utility.LineChart) To build document, we need to install ``Sphinx`` and ``sphinx-rtd-theme`` (you may replace this with your own theme). From 2b068f3cebcf31c2f93fcae6314d0813bccf1d84 Mon Sep 17 00:00:00 2001 From: He Yin Ling Date: Tue, 16 Jan 2018 22:16:03 +0800 Subject: [PATCH 094/187] tiny-test-fw: fix misc bugs: 1. configs are not functional * decorator will be executed when search case, need to set default config before search case. 2. fix DUT encode/decode errors * python3 serial don't support write string/unicode, need to convert to bytes first. * python2 string could failed to encode/decode non-acsii chars 3. fix bug that log folder not created 4. fix bug that test suite name is not correctly passed: * the keyward arg should be `test_suite_name` not `test_name` 5. fix bug that test stopped on failed case 6. fix DUT `read` don't return all data cache * `_DataCache.get_data` should first copy all data from queue to data cache and then return to user. 7. fix bug that `expect_all` failed even all expected item passed 8. optimize error info for expect * print pattern for regular expression when match failed 9. fix bug that set default config doesn't work --- tools/tiny-test-fw/App.py | 9 ++++-- tools/tiny-test-fw/DUT.py | 46 ++++++++++++++++++++++++------- tools/tiny-test-fw/Env.py | 4 +-- tools/tiny-test-fw/EnvConfig.py | 2 +- tools/tiny-test-fw/Runner.py | 14 ++++++---- tools/tiny-test-fw/TinyFW.py | 12 ++++---- tools/tiny-test-fw/docs/index.rst | 2 +- tools/tiny-test-fw/example.py | 2 +- 8 files changed, 62 insertions(+), 29 deletions(-) diff --git a/tools/tiny-test-fw/App.py b/tools/tiny-test-fw/App.py index 84e8716a17..1dbadf85af 100644 --- a/tools/tiny-test-fw/App.py +++ b/tools/tiny-test-fw/App.py @@ -78,9 +78,12 @@ class BaseApp(object): if not test_suite_name: test_suite_name = os.path.splitext(os.path.basename(sys.modules['__main__'].__file__))[0] sdk_path = cls.get_sdk_path() - return os.path.join(sdk_path, "TEST_LOGS", - test_suite_name + - time.strftime("_%m%d_%H_%M_%S", time.localtime(LOG_FOLDER_TIMESTAMP))) + log_folder = os.path.join(sdk_path, "TEST_LOGS", + test_suite_name + + time.strftime("_%m%d_%H_%M_%S", time.localtime(LOG_FOLDER_TIMESTAMP))) + if not os.path.exists(log_folder): + os.makedirs(log_folder) + return log_folder def process_app_info(self): """ diff --git a/tools/tiny-test-fw/DUT.py b/tools/tiny-test-fw/DUT.py index 1cfd2c7d53..882afa1f99 100644 --- a/tools/tiny-test-fw/DUT.py +++ b/tools/tiny-test-fw/DUT.py @@ -85,6 +85,14 @@ def _decode_data(data): return data +def _pattern_to_string(pattern): + try: + ret = "RegEx: " + pattern.pattern + except AttributeError: + ret = pattern + return ret + + class _DataCache(_queue.Queue): """ Data cache based on Queue. Allow users to process data cache based on bytes instead of Queue." @@ -94,6 +102,21 @@ class _DataCache(_queue.Queue): _queue.Queue.__init__(self, maxsize=maxsize) self.data_cache = str() + def _move_from_queue_to_cache(self): + """ + move all of the available data in the queue to cache + + :return: True if moved any item from queue to data cache, else False + """ + ret = False + while True: + try: + self.data_cache += _decode_data(self.get(0)) + ret = True + except _queue.Empty: + break + return ret + def get_data(self, timeout=0): """ get a copy of data from cache. @@ -105,12 +128,16 @@ class _DataCache(_queue.Queue): if timeout < 0: timeout = 0 - try: - data = self.get(timeout=timeout) - self.data_cache += _decode_data(data) - except _queue.Empty: - # don't do anything when on update for cache - pass + ret = self._move_from_queue_to_cache() + + if not ret: + # we only wait for new data if we can't provide a new data_cache + try: + data = self.get(timeout=timeout) + self.data_cache += _decode_data(data) + except _queue.Empty: + # don't do anything when on update for cache + pass return copy.deepcopy(self.data_cache) def flush(self, index=0xFFFFFFFF): @@ -417,7 +444,7 @@ class BaseDUT(object): data = self.data_cache.get_data(time.time() + timeout - start_time) if ret is None: - raise ExpectTimeout(self.name + ": " + str(pattern)) + raise ExpectTimeout(self.name + ": " + _pattern_to_string(pattern)) return ret def _expect_multi(self, expect_all, expect_item_list, timeout): @@ -457,12 +484,11 @@ class BaseDUT(object): if expect_item["ret"] is not None: # match succeed for one item matched_expect_items.append(expect_item) - break # if expect all, then all items need to be matched, # else only one item need to matched if expect_all: - match_succeed = (matched_expect_items == expect_items) + match_succeed = len(matched_expect_items) == len(expect_items) else: match_succeed = True if matched_expect_items else False @@ -482,7 +508,7 @@ class BaseDUT(object): # flush already matched data self.data_cache.flush(slice_index) else: - raise ExpectTimeout(self.name + ": " + str(expect_items)) + raise ExpectTimeout(self.name + ": " + str([_pattern_to_string(x) for x in expect_items])) @_expect_lock def expect_any(self, *expect_items, **timeout): diff --git a/tools/tiny-test-fw/Env.py b/tools/tiny-test-fw/Env.py index fa194d10c9..b623847edb 100644 --- a/tools/tiny-test-fw/Env.py +++ b/tools/tiny-test-fw/Env.py @@ -49,12 +49,12 @@ class Env(object): dut=None, env_tag=None, env_config_file=None, - test_name=None, + test_suite_name=None, **kwargs): self.app_cls = app self.default_dut_cls = dut self.config = EnvConfig.Config(env_config_file, env_tag) - self.log_path = self.app_cls.get_log_folder(test_name) + self.log_path = self.app_cls.get_log_folder(test_suite_name) if not os.path.exists(self.log_path): os.makedirs(self.log_path) diff --git a/tools/tiny-test-fw/EnvConfig.py b/tools/tiny-test-fw/EnvConfig.py index 2ce28d811e..79de6bd3f8 100644 --- a/tools/tiny-test-fw/EnvConfig.py +++ b/tools/tiny-test-fw/EnvConfig.py @@ -53,7 +53,7 @@ class Config(object): try: with open(config_file) as f: configs = yaml.load(f)[env_name] - except (OSError, TypeError): + except (OSError, TypeError, IOError): configs = dict() return configs diff --git a/tools/tiny-test-fw/Runner.py b/tools/tiny-test-fw/Runner.py index 0adf441fe0..70f60eb354 100644 --- a/tools/tiny-test-fw/Runner.py +++ b/tools/tiny-test-fw/Runner.py @@ -40,18 +40,22 @@ class Runner(threading.Thread): def __init__(self, test_case, case_config, env_config_file=None): super(Runner, self).__init__() self.setDaemon(True) - test_methods = SearchCases.Search.search_test_cases(test_case) - self.test_cases = CaseConfig.Parser.apply_config(test_methods, case_config) - self.test_result = True if case_config: test_suite_name = os.path.splitext(os.path.basename(case_config))[0] else: test_suite_name = "TestRunner" TinyFW.set_default_config(env_config_file=env_config_file, test_suite_name=test_suite_name) + test_methods = SearchCases.Search.search_test_cases(test_case) + self.test_cases = CaseConfig.Parser.apply_config(test_methods, case_config) + self.test_result = [] def run(self): for case in self.test_cases: - self.test_result = self.test_result and case.run() + result = case.run() + self.test_result.append(result) + + def get_test_result(self): + return self.test_result and all(self.test_result) if __name__ == '__main__': @@ -76,5 +80,5 @@ if __name__ == '__main__': except KeyboardInterrupt: print("exit by Ctrl-C") break - if not runner.test_result: + if not runner.get_test_result(): sys.exit(1) diff --git a/tools/tiny-test-fw/TinyFW.py b/tools/tiny-test-fw/TinyFW.py index 09b950c583..b227cf7aad 100644 --- a/tools/tiny-test-fw/TinyFW.py +++ b/tools/tiny-test-fw/TinyFW.py @@ -132,12 +132,6 @@ def test_method(**kwargs): case_info["name"] = test_func.__name__ case_info.update(kwargs) - # create env instance - env_config = DefaultEnvConfig.get_default_config() - for key in kwargs: - if key in env_config: - env_config[key] = kwargs[key] - @functools.wraps(test_func) def handle_test(extra_data=None, **overwrite): """ @@ -147,6 +141,12 @@ def test_method(**kwargs): :param overwrite: args that runner or main want to overwrite :return: None """ + # create env instance + env_config = DefaultEnvConfig.get_default_config() + for key in kwargs: + if key in env_config: + env_config[key] = kwargs[key] + env_config.update(overwrite) env_inst = Env.Env(**env_config) # prepare for xunit test results diff --git a/tools/tiny-test-fw/docs/index.rst b/tools/tiny-test-fw/docs/index.rst index bc3a3f5f82..b83254cb18 100644 --- a/tools/tiny-test-fw/docs/index.rst +++ b/tools/tiny-test-fw/docs/index.rst @@ -69,7 +69,7 @@ Let's first check a simple simple:: if __name__ == '__main__': - TinyFW.set_default_config(config_file="EnvConfigTemplate.yml") + TinyFW.set_default_config(env_config_file="EnvConfigTemplate.yml") test_examples_protocol_https_request() diff --git a/tools/tiny-test-fw/example.py b/tools/tiny-test-fw/example.py index df1b25576e..324c904383 100644 --- a/tools/tiny-test-fw/example.py +++ b/tools/tiny-test-fw/example.py @@ -47,5 +47,5 @@ def test_examples_protocol_https_request(env, extra_data): if __name__ == '__main__': - TinyFW.set_default_config(config_file="EnvConfigTemplate.yml", dut=IDF.IDFDUT) + TinyFW.set_default_config(env_config_file="EnvConfigTemplate.yml", dut=IDF.IDFDUT) test_examples_protocol_https_request() From f7bb5c8f42721ea963d02634080447c0cae24581 Mon Sep 17 00:00:00 2001 From: He Yin Ling Date: Fri, 9 Mar 2018 17:42:08 +0800 Subject: [PATCH 095/187] iperf example: add cmd to trace max heap usage --- examples/wifi/iperf/main/cmd_wifi.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/examples/wifi/iperf/main/cmd_wifi.c b/examples/wifi/iperf/main/cmd_wifi.c index e26900dfb7..3407e99e98 100644 --- a/examples/wifi/iperf/main/cmd_wifi.c +++ b/examples/wifi/iperf/main/cmd_wifi.c @@ -314,6 +314,13 @@ static int restart(int argc, char** argv) ESP_LOGI(TAG, "Restarting"); esp_restart(); } + +static int heap_size(int argc, char** argv) +{ + uint32_t heap_size = heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT); + ESP_LOGI(TAG, "min heap size: %u", heap_size); + return 0; +} void register_wifi() { @@ -378,4 +385,12 @@ void register_wifi() }; ESP_ERROR_CHECK( esp_console_cmd_register(&iperf_cmd) ); + + const esp_console_cmd_t heap_cmd = { + .command = "heap", + .help = "get min free heap size druing test", + .hint = NULL, + .func = &heap_size, + }; + ESP_ERROR_CHECK( esp_console_cmd_register(&heap_cmd) ); } From 7e4c2cc46bf24d94c669768c48e7ba6a10a24263 Mon Sep 17 00:00:00 2001 From: He Yin Ling Date: Thu, 11 Jan 2018 14:18:29 +0800 Subject: [PATCH 096/187] iperf example: add scan command to get AP rssi --- examples/wifi/iperf/main/cmd_wifi.c | 75 +++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/examples/wifi/iperf/main/cmd_wifi.c b/examples/wifi/iperf/main/cmd_wifi.c index 3407e99e98..c2af645949 100644 --- a/examples/wifi/iperf/main/cmd_wifi.c +++ b/examples/wifi/iperf/main/cmd_wifi.c @@ -37,7 +37,14 @@ typedef struct { struct arg_str *password; struct arg_end *end; } wifi_args_t; + +typedef struct { + struct arg_str *ssid; + struct arg_end *end; +} wifi_scan_arg_t; + static wifi_args_t sta_args; +static wifi_scan_arg_t scan_args; static wifi_args_t ap_args; static bool reconnect = true; static const char *TAG="iperf"; @@ -46,6 +53,27 @@ static EventGroupHandle_t wifi_event_group; const int CONNECTED_BIT = BIT0; const int DISCONNECTED_BIT = BIT1; +static void scan_done_handler(void) +{ + uint16_t sta_number = 0; + uint8_t i; + wifi_ap_record_t *ap_list_buffer; + + esp_wifi_scan_get_ap_num(&sta_number); + ap_list_buffer = malloc(sta_number * sizeof(wifi_ap_record_t)); + if (ap_list_buffer == NULL) { + ESP_LOGE(TAG, "Failed to malloc buffer to print scan results"); + return; + } + + if (esp_wifi_scan_get_ap_records(&sta_number,(wifi_ap_record_t *)ap_list_buffer) == ESP_OK) { + for(i=0; ievent_id) { @@ -53,6 +81,10 @@ static esp_err_t event_handler(void *ctx, system_event_t *event) xEventGroupClearBits(wifi_event_group, DISCONNECTED_BIT); xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); break; + case SYSTEM_EVENT_SCAN_DONE: + scan_done_handler(); + ESP_LOGI(TAG, "sta scan done"); + break; case SYSTEM_EVENT_STA_DISCONNECTED: if (reconnect) { ESP_LOGI(TAG, "sta disconnect, reconnect..."); @@ -131,6 +163,35 @@ static int wifi_cmd_sta(int argc, char** argv) return 0; } +static bool wifi_cmd_sta_scan(const char* ssid) +{ + wifi_scan_config_t scan_config = { 0 }; + scan_config.ssid = (uint8_t *) ssid; + + ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) ); + ESP_ERROR_CHECK( esp_wifi_scan_start(&scan_config, false) ); + + return true; +} + +static int wifi_cmd_scan(int argc, char** argv) +{ + int nerrors = arg_parse(argc, argv, (void**) &scan_args); + + if (nerrors != 0) { + arg_print_errors(stderr, scan_args.end, argv[0]); + return 1; + } + + ESP_LOGI(TAG, "sta start to scan"); + if ( scan_args.ssid->count == 1 ) { + wifi_cmd_sta_scan(scan_args.ssid->sval[0]); + } else { + wifi_cmd_sta_scan(NULL); + } + return 0; +} + static bool wifi_cmd_ap_set(const char* ssid, const char* pass) { @@ -338,10 +399,24 @@ void register_wifi() ESP_ERROR_CHECK( esp_console_cmd_register(&sta_cmd) ); + scan_args.ssid = arg_str0(NULL, NULL, "", "SSID of AP want to be scanned"); + scan_args.end = arg_end(1); + + const esp_console_cmd_t scan_cmd = { + .command = "scan", + .help = "WiFi is station mode, start scan ap", + .hint = NULL, + .func = &wifi_cmd_scan, + .argtable = &scan_args + }; + ap_args.ssid = arg_str1(NULL, NULL, "", "SSID of AP"); ap_args.password = arg_str0(NULL, NULL, "", "password of AP"); ap_args.end = arg_end(2); + + ESP_ERROR_CHECK( esp_console_cmd_register(&scan_cmd) ); + const esp_console_cmd_t ap_cmd = { .command = "ap", .help = "AP mode, configure ssid and password", From 9ad0760b9d3cb615ab01c067c083bb232e05f296 Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Fri, 30 Mar 2018 17:14:29 +0500 Subject: [PATCH 097/187] esp32/clk:Fix starting rtc oscillator if it is bad If the RTC crystal is bad or has no matched capacitance, then you do not need to start such the crystal. It is necessary to determine this case, output an error (about impossibility to start from the oscillator) and start from the internal RC of the chain. Reduced the default value of the number of bootstrap cycles. Because we can oscillating the oscillator which then stops. (in Kconfig). Changed from 100 to 5. The number of calibration cycles has been increased. It is the main criterion for estimating the launch of an oscillator. A large increase leads to an increase in the load time, as well as the stability of recognition of this case. (in Kconfig). Changed from 1024 to 3000. --- components/esp32/Kconfig | 18 +++- components/esp32/clk.c | 36 +++---- components/soc/esp32/test/test_rtc_clk.c | 115 +++++++++++++++++++++-- 3 files changed, 139 insertions(+), 30 deletions(-) diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index c820ba7028..b12c4ae5c4 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -685,7 +685,8 @@ endchoice config ESP32_RTC_CLK_CAL_CYCLES int "Number of cycles for RTC_SLOW_CLK calibration" - default 1024 + default 3000 if ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL + default 1024 if ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC range 0 125000 help When the startup code initializes RTC_SLOW_CLK, it can perform @@ -698,18 +699,27 @@ config ESP32_RTC_CLK_CAL_CYCLES When this option is set to 0, clock calibration will not be performed at startup, and approximate clock frequencies will be assumed: - - 150000 Hz if internal RC oscillator is used as clock source - - 32768 Hz if the 32k crystal oscillator is used + - 150000 Hz if internal RC oscillator is used as clock source. For this use value 1024. + - 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more. + In case more value will help improve the definition of the launch of the crystal. + If the crystal could not start, it will be switched to internal RC. config ESP32_RTC_XTAL_BOOTSTRAP_CYCLES int "Bootstrap cycles for external 32kHz crystal" - default 100 + depends on ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL + default 5 range 0 32768 help To reduce the startup time of an external RTC crystal, we bootstrap it with a 32kHz square wave for a fixed number of cycles. Setting 0 will disable bootstrapping (if disabled, the crystal may take longer to start up or fail to oscillate under some conditions). + + If this value is too high, a faulty crystal may initially start and then fail. + If this value is too low, an otherwise good crystal may not start. + + To accurately determine if the crystal has started, + set a larger "Number of cycles for RTC_SLOW_CLK calibration" (about 3000). config ESP32_DEEP_SLEEP_WAKEUP_DELAY int "Extra delay in deep sleep wake stub (in us)" diff --git a/components/esp32/clk.c b/components/esp32/clk.c index ec8d73c9bb..49cba58109 100644 --- a/components/esp32/clk.c +++ b/components/esp32/clk.c @@ -36,7 +36,6 @@ * Larger values increase startup delay. Smaller values may cause false positive * detection (i.e. oscillator runs for a few cycles and then stops). */ -#define XTAL_32K_DETECT_CYCLES 32 #define SLOW_CLK_CAL_CYCLES CONFIG_ESP32_RTC_CLK_CAL_CYCLES #define MHZ (1000000) @@ -128,6 +127,9 @@ void IRAM_ATTR ets_update_cpu_frequency(uint32_t ticks_per_us) static void select_rtc_slow_clk(rtc_slow_freq_t slow_clk) { uint32_t cal_val = 0; + uint32_t wait = 0; + const uint32_t warning_timeout = 3 /* sec */ * 32768 /* Hz */ / (2 * SLOW_CLK_CAL_CYCLES); + bool changing_clock_to_150k = false; do { if (slow_clk == RTC_SLOW_FREQ_32K_XTAL) { /* 32k XTAL oscillator needs to be enabled and running before it can @@ -137,24 +139,23 @@ static void select_rtc_slow_clk(rtc_slow_freq_t slow_clk) * oscillator cycles. If the 32k XTAL has not started up, calibration * will time out, returning 0. */ - uint32_t wait = 0; - // increment of 'wait' counter equivalent to 3 seconds - const uint32_t warning_timeout = 3 /* sec */ * 32768 /* Hz */ / (2 * XTAL_32K_DETECT_CYCLES); ESP_EARLY_LOGD(TAG, "waiting for 32k oscillator to start up"); - do { - ++wait; - rtc_clk_32k_enable(true); - cal_val = rtc_clk_cal(RTC_CAL_32K_XTAL, XTAL_32K_DETECT_CYCLES); - if (wait % warning_timeout == 0) { - ESP_EARLY_LOGW(TAG, "still waiting for 32k oscillator to start up"); - } - if(cal_val == 0){ - rtc_clk_32k_enable(false); - rtc_clk_32k_bootstrap(CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES); - } - } while (cal_val == 0); + rtc_clk_32k_enable(true); + cal_val = rtc_clk_cal(RTC_CAL_32K_XTAL, SLOW_CLK_CAL_CYCLES); + if(cal_val == 0 || cal_val < 15000000L){ + ESP_EARLY_LOGE(TAG, "RTC: Not found External 32 kHz XTAL. Switching to Internal 150 kHz RC chain"); + slow_clk = RTC_SLOW_FREQ_RTC; + changing_clock_to_150k = true; + } } rtc_clk_slow_freq_set(slow_clk); + if (changing_clock_to_150k == true && wait > 1){ + // This helps when there are errors when switching the clock from External 32 kHz XTAL to Internal 150 kHz RC chain. + rtc_clk_32k_enable(false); + uint32_t min_bootstrap = 5; // Min bootstrapping for continue switching the clock. + rtc_clk_32k_bootstrap(min_bootstrap); + rtc_clk_32k_enable(true); + } if (SLOW_CLK_CAL_CYCLES > 0) { /* TODO: 32k XTAL oscillator has some frequency drift at startup. @@ -165,6 +166,9 @@ static void select_rtc_slow_clk(rtc_slow_freq_t slow_clk) const uint64_t cal_dividend = (1ULL << RTC_CLK_CAL_FRACT) * 1000000ULL; cal_val = (uint32_t) (cal_dividend / rtc_clk_slow_freq_get_hz()); } + if (++wait % warning_timeout == 0) { + ESP_EARLY_LOGW(TAG, "still waiting for source selection RTC"); + } } while (cal_val == 0); ESP_EARLY_LOGD(TAG, "RTC_SLOW_CLK calibration value: %d", cal_val); esp_clk_slowclk_cal_set(cal_val); diff --git a/components/soc/esp32/test/test_rtc_clk.c b/components/soc/esp32/test/test_rtc_clk.c index ee076e04d5..9efad4a1e4 100644 --- a/components/soc/esp32/test/test_rtc_clk.c +++ b/components/soc/esp32/test/test_rtc_clk.c @@ -13,6 +13,7 @@ #include "freertos/task.h" #include "freertos/semphr.h" #include "../esp_clk_internal.h" +#include "esp_clk.h" @@ -134,7 +135,7 @@ TEST_CASE("Test fast switching between PLL and XTAL", "[rtc_clk]") } #define COUNT_TEST 10 -#define TIMEOUT_TEST_MS 50 +#define TIMEOUT_TEST_MS (5 + CONFIG_ESP32_RTC_CLK_CAL_CYCLES / 16) void stop_rtc_external_quartz(){ const uint8_t pin_32 = 32; @@ -151,6 +152,68 @@ void stop_rtc_external_quartz(){ gpio_output_set_high(0, 0, 0, mask_32 | mask_33); // disable pins } +static void start_freq(rtc_slow_freq_t required_src_freq, uint32_t start_delay_ms) +{ + int i = 0, fail = 0; + uint32_t start_time; + uint32_t end_time; + rtc_slow_freq_t selected_src_freq; + stop_rtc_external_quartz(); +#ifdef CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL + uint32_t bootstrap_cycles = CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES; + printf("Test is started. Kconfig settings:\n External 32K crystal is selected,\n Oscillation cycles = %d,\n Calibration cycles = %d.\n", + bootstrap_cycles, + CONFIG_ESP32_RTC_CLK_CAL_CYCLES); +#else + uint32_t bootstrap_cycles = 5; + printf("Test is started. Kconfig settings:\n Internal RC is selected,\n Oscillation cycles = %d,\n Calibration cycles = %d.\n", + bootstrap_cycles, + CONFIG_ESP32_RTC_CLK_CAL_CYCLES); +#endif + if (start_delay_ms == 0 && CONFIG_ESP32_RTC_CLK_CAL_CYCLES < 1500){ + start_delay_ms = 50; + printf("Recommended increase Number of cycles for RTC_SLOW_CLK calibration to 3000!\n"); + } + while(i < COUNT_TEST){ + start_time = xTaskGetTickCount() * (1000 / configTICK_RATE_HZ); + i++; + printf("attempt #%d/%d...", i, COUNT_TEST); + rtc_clk_32k_bootstrap(bootstrap_cycles); + ets_delay_us(start_delay_ms * 1000); + rtc_clk_select_rtc_slow_clk(); + selected_src_freq = rtc_clk_slow_freq_get(); + end_time = xTaskGetTickCount() * (1000 / configTICK_RATE_HZ); + printf(" [time=%d] ", (end_time - start_time) - start_delay_ms); + if(selected_src_freq != required_src_freq){ + printf("FAIL. Time measurement..."); + fail = 1; + } else { + printf("PASS. Time measurement..."); + } + uint64_t clk_rtc_time; + uint32_t fail_measure = 0; + for (int j = 0; j < 3; ++j) { + clk_rtc_time = esp_clk_rtc_time(); + ets_delay_us(1000000); + uint64_t delta = esp_clk_rtc_time() - clk_rtc_time; + if (delta < 900000LL || delta > 1100000){ + printf("FAIL"); + fail = 1; + fail_measure = 1; + break; + } + } + if(fail_measure == 0) { + printf("PASS"); + } + printf(" [calibration val = %d] \n", esp_clk_slowclk_cal_get()); + stop_rtc_external_quartz(); + ets_delay_us(500000); + } + TEST_ASSERT_MESSAGE(fail == 0, "Test failed"); + printf("Test passed successfully\n"); +} + #ifdef CONFIG_SPIRAM_SUPPORT // PSRAM tests run on ESP-WROVER-KIT boards, which have the 32k XTAL installed. // Other tests may run on DevKitC boards, which don't have a 32k XTAL. @@ -159,16 +222,29 @@ TEST_CASE("Test starting external RTC quartz", "[rtc_clk]") int i = 0, fail = 0; uint32_t start_time; uint32_t end_time; - stop_rtc_external_quartz(); - printf("Start test. Number of oscillation cycles = %d\n", CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES); +#ifdef CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL + uint32_t bootstrap_cycles = CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES; + printf("Test is started. Kconfig settings:\n External 32K crystal is selected,\n Oscillation cycles = %d,\n Calibration cycles = %d.\n", + bootstrap_cycles, + CONFIG_ESP32_RTC_CLK_CAL_CYCLES); +#else + uint32_t bootstrap_cycles = 5; + printf("Test is started. Kconfig settings:\n Internal RC is selected,\n Oscillation cycles = %d,\n Calibration cycles = %d.\n", + bootstrap_cycles, + CONFIG_ESP32_RTC_CLK_CAL_CYCLES); +#endif + if (CONFIG_ESP32_RTC_CLK_CAL_CYCLES < 1500){ + printf("Recommended increase Number of cycles for RTC_SLOW_CLK calibration to 3000!\n"); + } while(i < COUNT_TEST){ start_time = xTaskGetTickCount() * (1000 / configTICK_RATE_HZ); i++; printf("attempt #%d/%d...", i, COUNT_TEST); - rtc_clk_32k_bootstrap(CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES); + rtc_clk_32k_bootstrap(bootstrap_cycles); rtc_clk_select_rtc_slow_clk(); end_time = xTaskGetTickCount() * (1000 / configTICK_RATE_HZ); + printf(" [time=%d] ", end_time - start_time); if((end_time - start_time) > TIMEOUT_TEST_MS){ printf("FAIL\n"); fail = 1; @@ -178,11 +254,30 @@ TEST_CASE("Test starting external RTC quartz", "[rtc_clk]") stop_rtc_external_quartz(); ets_delay_us(100000); } - if (fail == 1){ - printf("Test failed\n"); - TEST_ASSERT(false); - } else { - printf("Test passed successfully\n"); - } + TEST_ASSERT_MESSAGE(fail == 0, "Test failed"); + printf("Test passed successfully\n"); } + +TEST_CASE("Test starting 'External 32kHz XTAL' on the board with it.", "[rtc_clk]") +{ + start_freq(RTC_SLOW_FREQ_32K_XTAL, 200); + start_freq(RTC_SLOW_FREQ_32K_XTAL, 0); +} + +#else + +TEST_CASE("Test starting 'External 32kHz XTAL' on the board without it.", "[rtc_clk]") +{ + printf("Tries to start the 'External 32kHz XTAL' on the board without it. " + "Clock switching to 'Internal 150 kHz RC oscillator'.\n"); + + printf("This test will be successful for boards without an external crystal or non-working crystal. " + "First, there will be an attempt to start from the external crystal after a failure " + "will switch to the internal RC circuit. If the switch to the internal RC circuit " + "was successful then the test succeeded.\n"); + + start_freq(RTC_SLOW_FREQ_RTC, 200); + start_freq(RTC_SLOW_FREQ_RTC, 0); +} + #endif // CONFIG_SPIRAM_SUPPORT From e8dd203e47e4d100ddf85612a718fa45c1ea3073 Mon Sep 17 00:00:00 2001 From: He Yin Ling Date: Sun, 7 Jan 2018 20:28:09 +0800 Subject: [PATCH 098/187] example test: add test case for iperf example --- components/idf_test/include/idf_performance.h | 6 +- examples/wifi/iperf/iperf_test.py | 663 ++++++++++++++++++ examples/wifi/iperf/sdkconfig.defaults | 2 + examples/wifi/iperf/sdkconfig.defaults.00 | 6 + examples/wifi/iperf/sdkconfig.defaults.01 | 25 + examples/wifi/iperf/sdkconfig.defaults.02 | 25 + examples/wifi/iperf/sdkconfig.defaults.03 | 25 + examples/wifi/iperf/sdkconfig.defaults.04 | 25 + examples/wifi/iperf/sdkconfig.defaults.05 | 29 + examples/wifi/iperf/sdkconfig.defaults.06 | 26 + examples/wifi/iperf/sdkconfig.defaults.07 | 30 + examples/wifi/iperf/sdkconfig.defaults.99 | 30 + examples/wifi/iperf/test_report.py | 245 +++++++ 13 files changed, 1136 insertions(+), 1 deletion(-) create mode 100644 examples/wifi/iperf/iperf_test.py create mode 100644 examples/wifi/iperf/sdkconfig.defaults.00 create mode 100644 examples/wifi/iperf/sdkconfig.defaults.01 create mode 100644 examples/wifi/iperf/sdkconfig.defaults.02 create mode 100644 examples/wifi/iperf/sdkconfig.defaults.03 create mode 100644 examples/wifi/iperf/sdkconfig.defaults.04 create mode 100644 examples/wifi/iperf/sdkconfig.defaults.05 create mode 100644 examples/wifi/iperf/sdkconfig.defaults.06 create mode 100644 examples/wifi/iperf/sdkconfig.defaults.07 create mode 100644 examples/wifi/iperf/sdkconfig.defaults.99 create mode 100644 examples/wifi/iperf/test_report.py diff --git a/components/idf_test/include/idf_performance.h b/components/idf_test/include/idf_performance.h index cd5a463d75..40c733f03a 100644 --- a/components/idf_test/include/idf_performance.h +++ b/components/idf_test/include/idf_performance.h @@ -17,4 +17,8 @@ #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 30 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 27 #define IDF_PERFORMANCE_MAX_VFS_OPEN_WRITE_CLOSE_TIME 20000 - +// throughput performance by iperf +#define IDF_PERFORMANCE_MIN_TCP_RX_THROUGHPUT 50 +#define IDF_PERFORMANCE_MIN_TCP_TX_THROUGHPUT 40 +#define IDF_PERFORMANCE_MIN_UDP_RX_THROUGHPUT 80 +#define IDF_PERFORMANCE_MIN_UDP_TX_THROUGHPUT 50 diff --git a/examples/wifi/iperf/iperf_test.py b/examples/wifi/iperf/iperf_test.py new file mode 100644 index 0000000000..5782d299ab --- /dev/null +++ b/examples/wifi/iperf/iperf_test.py @@ -0,0 +1,663 @@ +""" +Test case for iperf example. + +This test case might have problem running on windows: + +1. direct use of `make` +2. use `sudo killall iperf` to force kill iperf, didn't implement windows version + +The test env Example_ShieldBox do need the following config:: + + Example_ShieldBox: + ap_list: + - ssid: "ssid" + password: "password" + outlet: 1 + apc_ip: "192.168.1.88" + attenuator_port: "/dev/ttyUSB0" + iperf: "/dev/ttyUSB1" + apc_ip: "192.168.1.88" + pc_nic: "eth0" +""" +import re +import os +import sys +import time +import subprocess + +# add current folder to system path for importing test_report +sys.path.append(os.path.dirname(__file__)) +# this is a test case write with tiny-test-fw. +# to run test cases outside tiny-test-fw, +# we need to set environment variable `TEST_FW_PATH`, +# then get and insert `TEST_FW_PATH` to sys path before import FW module +test_fw_path = os.getenv("TEST_FW_PATH") +if test_fw_path and test_fw_path not in sys.path: + sys.path.insert(0, test_fw_path) + +import IDF +import DUT +import Utility +from Utility import (Attenuator, PowerControl, LineChart) +from test_report import (ThroughputForConfigsReport, ThroughputVsRssiReport) + +# configurations +TEST_TIME = TEST_TIMEOUT = 60 +WAIT_AP_POWER_ON_TIMEOUT = 90 +SCAN_TIMEOUT = 3 +SCAN_RETRY_COUNT = 3 +RETRY_COUNT_FOR_BEST_PERFORMANCE = 2 +ATTEN_VALUE_LIST = range(0, 60, 2) + +# constants +FAILED_TO_SCAN_RSSI = -97 +INVALID_HEAP_SIZE = 0xFFFFFFFF + +PC_IPERF_TEMP_LOG_FILE = ".tmp_iperf.log" +CONFIG_NAME_PATTERN = re.compile(r"sdkconfig\.defaults\.(.+)") + +# We need to auto compare the difference between adjacent configs (01 -> 00, 02 -> 01, ...) and put them to reports. +# Using numbers for config will make this easy. +# Use default value `99` for config with best performance. +BEST_PERFORMANCE_CONFIG = "99" + + +class TestResult(object): + """ record, analysis test result and convert data to output format """ + + PC_BANDWIDTH_LOG_PATTERN = re.compile(r"(\d+).0\s*-\s*(\d+).0\s+sec\s+[\d.]+\s+MBytes\s+([\d.]+)\s+Mbits/sec") + DUT_BANDWIDTH_LOG_PATTERN = re.compile(r"(\d+)-\s+(\d+)\s+sec\s+([\d.]+)\s+Mbits/sec") + + ZERO_POINT_THRESHOLD = -88 # RSSI, dbm + ZERO_THROUGHPUT_THRESHOLD = -92 # RSSI, dbm + BAD_POINT_RSSI_THRESHOLD = -85 # RSSI, dbm + BAD_POINT_MIN_THRESHOLD = 3 # Mbps + BAD_POINT_PERCENTAGE_THRESHOLD = 0.3 + + # we need at least 1/2 valid points to qualify the test result + THROUGHPUT_QUALIFY_COUNT = TEST_TIME / 2 + + def __init__(self, proto, direction, config_name): + self.proto = proto + self.direction = direction + self.config_name = config_name + self.throughput_by_rssi = dict() + self.throughput_by_att = dict() + self.att_rssi_map = dict() + self.heap_size = INVALID_HEAP_SIZE + self.error_list = [] + + def _save_result(self, throughput, ap_ssid, att, rssi, heap_size): + """ + save the test results: + + * record the better throughput if att/rssi is the same. + * record the min heap size. + """ + if ap_ssid not in self.att_rssi_map: + # for new ap, create empty dict() + self.throughput_by_att[ap_ssid] = dict() + self.throughput_by_rssi[ap_ssid] = dict() + self.att_rssi_map[ap_ssid] = dict() + + self.att_rssi_map[ap_ssid][att] = rssi + + def record_throughput(database, key_value): + try: + # we save the larger value for same att + if throughput > database[ap_ssid][key_value]: + database[ap_ssid][key_value] = throughput + except KeyError: + database[ap_ssid][key_value] = throughput + + record_throughput(self.throughput_by_att, att) + record_throughput(self.throughput_by_rssi, rssi) + + if int(heap_size) < self.heap_size: + self.heap_size = int(heap_size) + + def add_result(self, raw_data, ap_ssid, att, rssi, heap_size): + """ + add result for one test + + :param raw_data: iperf raw data + :param ap_ssid: ap ssid that tested + :param att: attenuate value + :param rssi: AP RSSI + :param heap_size: min heap size during test + :return: throughput + """ + fall_to_0_recorded = 0 + throughput_list = [] + result_list = self.PC_BANDWIDTH_LOG_PATTERN.findall(raw_data) + if not result_list: + # failed to find raw data by PC pattern, it might be DUT pattern + result_list = self.DUT_BANDWIDTH_LOG_PATTERN.findall(raw_data) + + for result in result_list: + if int(result[1]) - int(result[0]) != 1: + # this could be summary, ignore this + continue + throughput_list.append(float(result[2])) + if float(result[2]) == 0 and rssi > self.ZERO_POINT_THRESHOLD \ + and fall_to_0_recorded < 1: + # throughput fall to 0 error. we only record 1 records for one test + self.error_list.append("[Error][fall to 0][{}][att: {}][rssi: {}]: 0 throughput interval: {}-{}" + .format(ap_ssid, att, rssi, result[0], result[1])) + fall_to_0_recorded += 1 + + if len(throughput_list) > self.THROUGHPUT_QUALIFY_COUNT: + throughput = sum(throughput_list) / len(throughput_list) + else: + throughput = 0.0 + + if throughput == 0 and rssi > self.ZERO_THROUGHPUT_THRESHOLD: + self.error_list.append("[Error][Fatal][{}][att: {}][rssi: {}]: No throughput data found" + .format(ap_ssid, att, rssi)) + + self._save_result(throughput, ap_ssid, att, rssi, heap_size) + + return throughput + + def post_analysis(self): + """ + some rules need to be checked after we collected all test raw data: + + 1. throughput value 30% worse than the next point with lower RSSI + 2. throughput value 30% worse than the next point with larger attenuate + """ + def analysis_bad_point(data, index_type): + for ap_ssid in data: + result_dict = data[ap_ssid] + index_list = result_dict.keys() + index_list.sort() + if index_type == "att": + index_list.reverse() + + for i, index_value in enumerate(index_list[1:]): + if index_value < self.BAD_POINT_RSSI_THRESHOLD or \ + result_dict[index_list[i]] < self.BAD_POINT_MIN_THRESHOLD: + continue + _percentage = result_dict[index_value] / result_dict[index_list[i]] + if _percentage < 1 - self.BAD_POINT_PERCENTAGE_THRESHOLD: + self.error_list.append("[Error][Bad point][{}][{}: {}]: drop {:.02f}%" + .format(ap_ssid, index_type, index_value, + (1 - _percentage) * 100)) + + analysis_bad_point(self.throughput_by_rssi, "rssi") + analysis_bad_point(self.throughput_by_att, "att") + + @staticmethod + def _convert_to_draw_format(data, label): + keys = data.keys() + keys.sort() + return { + "x-axis": keys, + "y-axis": [data[x] for x in keys], + "label": label, + } + + def draw_throughput_figure(self, path, ap_ssid, draw_type): + """ + :param path: folder to save figure. make sure the folder is already created. + :param ap_ssid: ap ssid string or a list of ap ssid string + :param draw_type: "att" or "rssi" + :return: file_name + """ + if draw_type == "rssi": + type_name = "RSSI" + data = self.throughput_by_rssi + elif draw_type == "att": + type_name = "Att" + data = self.throughput_by_att + else: + raise AssertionError("draw type not supported") + if isinstance(ap_ssid, list): + file_name = "ThroughputVs{}_{}_{}_{}.png".format(type_name, self.proto, self.direction, + hash(ap_ssid)[:6]) + data_list = [self._convert_to_draw_format(data[_ap_ssid], _ap_ssid) + for _ap_ssid in ap_ssid] + else: + file_name = "ThroughputVs{}_{}_{}_{}.png".format(type_name, self.proto, self.direction, ap_ssid) + data_list = [self._convert_to_draw_format(data[ap_ssid], ap_ssid)] + + LineChart.draw_line_chart(os.path.join(path, file_name), + "Throughput Vs {} ({} {})".format(type_name, self.proto, self.direction), + "Throughput (Mbps)", + "{} (dbm)".format(type_name), + data_list) + return file_name + + def draw_rssi_vs_att_figure(self, path, ap_ssid): + """ + :param path: folder to save figure. make sure the folder is already created. + :param ap_ssid: ap to use + :return: file_name + """ + if isinstance(ap_ssid, list): + file_name = "AttVsRSSI_{}.png".format(hash(ap_ssid)[:6]) + data_list = [self._convert_to_draw_format(self.att_rssi_map[_ap_ssid], _ap_ssid) + for _ap_ssid in ap_ssid] + else: + file_name = "AttVsRSSI_{}.png".format(ap_ssid) + data_list = [self._convert_to_draw_format(self.att_rssi_map[ap_ssid], ap_ssid)] + LineChart.draw_line_chart(os.path.join(path, file_name), + "Att Vs RSSI", + "Att (dbm)", + "RSSI (dbm)", + data_list) + return file_name + + def get_best_throughput(self): + """ get the best throughput during test """ + best_for_aps = [max(self.throughput_by_att[ap_ssid].values()) + for ap_ssid in self.throughput_by_att] + return max(best_for_aps) + + def __str__(self): + """ + returns summary for this test: + + 1. test result (success or fail) + 2. best performance for each AP + 3. min free heap size during test + """ + if self.throughput_by_att: + ret = "[{}_{}][{}]: {}\r\n\r\n".format(self.proto, self.direction, self.config_name, + "Fail" if self.error_list else "Success") + ret += "Performance for each AP:\r\n" + for ap_ssid in self.throughput_by_att: + ret += "[{}]: {:.02f} Mbps\r\n".format(ap_ssid, max(self.throughput_by_att[ap_ssid].values())) + if self.heap_size != INVALID_HEAP_SIZE: + ret += "Minimum heap size: {}".format(self.heap_size) + else: + ret = "" + return ret + + +class IperfTestUtility(object): + """ iperf test implementation """ + + def __init__(self, dut, config_name, ap_ssid, ap_password, + pc_nic_ip, pc_iperf_log_file, test_result=None): + self.config_name = config_name + self.dut = dut + + self.pc_iperf_log_file = pc_iperf_log_file + self.ap_ssid = ap_ssid + self.ap_password = ap_password + self.pc_nic_ip = pc_nic_ip + + if test_result: + self.test_result = test_result + else: + self.test_result = { + "tcp_tx": TestResult("tcp", "tx", config_name), + "tcp_rx": TestResult("tcp", "rx", config_name), + "udp_tx": TestResult("udp", "tx", config_name), + "udp_rx": TestResult("udp", "rx", config_name), + } + + def setup(self): + """ + setup iperf test: + + 1. kill current iperf process + 2. reboot DUT (currently iperf is not very robust, need to reboot DUT) + 3. scan to get AP RSSI + 4. connect to AP + """ + try: + subprocess.check_output("sudo killall iperf 2>&1 > /dev/null", shell=True) + except subprocess.CalledProcessError: + pass + self.dut.write("restart") + self.dut.expect("esp32>") + self.dut.write("scan {}".format(self.ap_ssid)) + for _ in range(SCAN_RETRY_COUNT): + try: + rssi = int(self.dut.expect(re.compile(r"\[{}]\[rssi=(-\d+)]".format(self.ap_ssid)), + timeout=SCAN_TIMEOUT)[0]) + break + except DUT.ExpectTimeout: + continue + else: + raise AssertionError("Failed to scan AP") + self.dut.write("sta {} {}".format(self.ap_ssid, self.ap_password)) + dut_ip = self.dut.expect(re.compile(r"event: sta ip: ([\d.]+), mask: ([\d.]+), gw: ([\d.]+)"))[0] + return dut_ip, rssi + + def _save_test_result(self, test_case, raw_data, att, rssi, heap_size): + return self.test_result[test_case].add_result(raw_data, self.ap_ssid, att, rssi, heap_size) + + def _test_once(self, proto, direction): + """ do measure once for one type """ + # connect and scan to get RSSI + dut_ip, rssi = self.setup() + + assert direction in ["rx", "tx"] + assert proto in ["tcp", "udp"] + + # run iperf test + if direction == "tx": + with open(PC_IPERF_TEMP_LOG_FILE, "w") as f: + if proto == "tcp": + process = subprocess.Popen(["iperf", "-s", "-B", self.pc_nic_ip, + "-t", str(TEST_TIME), "-i", "1", "-f", "m"], + stdout=f, stderr=f) + self.dut.write("iperf -c {} -i 1 -t {}".format(self.pc_nic_ip, TEST_TIME)) + else: + process = subprocess.Popen(["iperf", "-s", "-u", "-B", self.pc_nic_ip, + "-t", str(TEST_TIME), "-i", "1", "-f", "m"], + stdout=f, stderr=f) + self.dut.write("iperf -c {} -u -i 1 -t {}".format(self.pc_nic_ip, TEST_TIME)) + + for _ in range(TEST_TIMEOUT): + if process.poll() is not None: + break + time.sleep(1) + else: + process.terminate() + + with open(PC_IPERF_TEMP_LOG_FILE, "r") as f: + pc_raw_data = server_raw_data = f.read() + else: + with open(PC_IPERF_TEMP_LOG_FILE, "w") as f: + if proto == "tcp": + self.dut.write("iperf -s -i 1 -t {}".format(TEST_TIME)) + process = subprocess.Popen(["iperf", "-c", dut_ip, + "-t", str(TEST_TIME), "-f", "m"], + stdout=f, stderr=f) + else: + self.dut.write("iperf -s -u -i 1 -t {}".format(TEST_TIME)) + process = subprocess.Popen(["iperf", "-c", dut_ip, "-u", "-b", "100M", + "-t", str(TEST_TIME), "-f", "m"], + stdout=f, stderr=f) + + for _ in range(TEST_TIMEOUT): + if process.poll() is not None: + break + time.sleep(1) + else: + process.terminate() + + server_raw_data = self.dut.read() + with open(PC_IPERF_TEMP_LOG_FILE, "r") as f: + pc_raw_data = f.read() + + # save PC iperf logs to console + with open(self.pc_iperf_log_file, "a+") as f: + f.write("## [{}] `{}`\r\n##### {}" + .format(self.config_name, + "{}_{}".format(proto, direction), + time.strftime("%m-%d %H:%M:%S", time.localtime(time.time())))) + f.write('\r\n```\r\n\r\n' + pc_raw_data + '\r\n```\r\n') + self.dut.write("heap") + heap_size = self.dut.expect(re.compile(r"min heap size: (\d+)\D"))[0] + + # return server raw data (for parsing test results) and RSSI + return server_raw_data, rssi, heap_size + + def run_test(self, proto, direction, atten_val): + """ + run test for one type, with specified atten_value and save the test result + + :param proto: tcp or udp + :param direction: tx or rx + :param atten_val: attenuate value + """ + rssi = FAILED_TO_SCAN_RSSI + heap_size = INVALID_HEAP_SIZE + try: + server_raw_data, rssi, heap_size = self._test_once(proto, direction) + throughput = self._save_test_result("{}_{}".format(proto, direction), + server_raw_data, atten_val, + rssi, heap_size) + Utility.console_log("[{}][{}_{}][{}][{}]: {:.02f}" + .format(self.config_name, proto, direction, rssi, self.ap_ssid, throughput)) + except Exception as e: + self._save_test_result("{}_{}".format(proto, direction), "", atten_val, rssi, heap_size) + Utility.console_log("Failed during test: {}".format(e)) + + def run_all_cases(self, atten_val): + """ + run test for all types (udp_tx, udp_rx, tcp_tx, tcp_rx). + + :param atten_val: attenuate value + """ + self.run_test("tcp", "tx", atten_val) + self.run_test("tcp", "rx", atten_val) + self.run_test("udp", "tx", atten_val) + self.run_test("udp", "rx", atten_val) + + def wait_ap_power_on(self): + """ + AP need to take sometime to power on. It changes for different APs. + This method will scan to check if the AP powers on. + + :return: True or False + """ + self.dut.write("restart") + self.dut.expect("esp32>") + for _ in range(WAIT_AP_POWER_ON_TIMEOUT // SCAN_TIMEOUT): + try: + self.dut.write("scan {}".format(self.ap_ssid)) + self.dut.expect(re.compile(r"\[{}]\[rssi=(-\d+)]".format(self.ap_ssid)), + timeout=SCAN_TIMEOUT) + ret = True + break + except DUT.ExpectTimeout: + pass + else: + ret = False + return ret + + +def build_iperf_with_config(config_name): + """ + we need to build iperf example with different configurations. + + :param config_name: sdkconfig we want to build + """ + + # switch to iperf example path before build when we're running test with Runner + example_path = os.path.dirname(__file__) + cwd = os.getcwd() + if cwd != example_path and example_path: + os.chdir(example_path) + try: + subprocess.check_call("make clean > /dev/null", shell=True) + subprocess.check_call(["cp", "sdkconfig.defaults.{}".format(config_name), "sdkconfig.defaults"]) + subprocess.check_call(["rm", "-f", "sdkconfig"]) + subprocess.check_call("make defconfig > /dev/null", shell=True) + # save sdkconfig to generate config comparision report + subprocess.check_call(["cp", "sdkconfig", "sdkconfig.{}".format(config_name)]) + subprocess.check_call("make -j5 > /dev/null", shell=True) + subprocess.check_call("make print_flash_cmd | tail -n 1 > build/download.config", shell=True) + finally: + os.chdir(cwd) + + +def get_configs(env): + att_port = env.get_variable("attenuator_port") + ap_list = env.get_variable("ap_list") + pc_nic_ip = env.get_pc_nic_info("pc_nic", "ipv4")["addr"] + apc_ip = env.get_variable("apc_ip") + pc_iperf_log_file = os.path.join(env.log_path, "pc_iperf_log.md") + return att_port, ap_list, pc_nic_ip, apc_ip, pc_iperf_log_file + + +@IDF.idf_example_test(env_tag="Example_ShieldBox", category="stress") +def test_wifi_throughput_with_different_configs(env, extra_data): + """ + steps: | + 1. build iperf with specified configs + 2. test throughput for all routers + """ + att_port, ap_list, pc_nic_ip, apc_ip, pc_iperf_log_file = get_configs(env) + ap_info = ap_list[0] + + config_names_raw = subprocess.check_output(["ls", os.path.dirname(os.path.abspath(__file__))]) + + test_result = dict() + sdkconfig_files = dict() + + for config_name in CONFIG_NAME_PATTERN.findall(config_names_raw): + # 1. build config + build_iperf_with_config(config_name) + sdkconfig_files[config_name] = os.path.join(os.path.dirname(__file__), + "sdkconfig.{}".format(config_name)) + + # 2. get DUT and download + dut = env.get_dut("iperf", "examples/wifi/iperf") + dut.start_app() + dut.expect("esp32>") + + # 3. run test for each required att value + test_result[config_name] = { + "tcp_tx": TestResult("tcp", "tx", config_name), + "tcp_rx": TestResult("tcp", "rx", config_name), + "udp_tx": TestResult("udp", "tx", config_name), + "udp_rx": TestResult("udp", "rx", config_name), + } + + test_utility = IperfTestUtility(dut, config_name, ap_info["ssid"], + ap_info["password"], pc_nic_ip, pc_iperf_log_file, test_result[config_name]) + + PowerControl.Control.control_rest(apc_ip, ap_info["outlet"], "OFF") + PowerControl.Control.control(apc_ip, {ap_info["outlet"]: "ON"}) + assert Attenuator.set_att(att_port, 0) is True + + if not test_utility.wait_ap_power_on(): + Utility.console_log("[{}] failed to power on, skip testing this AP" + .format(ap_info["ssid"]), color="red") + + for _ in range(RETRY_COUNT_FOR_BEST_PERFORMANCE): + test_utility.run_all_cases(0) + + for result_type in test_result[config_name]: + summary = str(test_result[config_name][result_type]) + if summary: + Utility.console_log(summary, color="orange") + + # 4. check test results + env.close_dut("iperf") + + # 5. generate report + report = ThroughputForConfigsReport(os.path.join(env.log_path, "ThroughputForConfigsReport"), + ap_info["ssid"], test_result, sdkconfig_files) + report.generate_report() + + +@IDF.idf_example_test(env_tag="Example_ShieldBox", category="stress") +def test_wifi_throughput_vs_rssi(env, extra_data): + """ + steps: | + 1. build with best performance config + 2. switch on one router + 3. set attenuator value from 0-60 for each router + 4. test TCP tx rx and UDP tx rx throughput + """ + att_port, ap_list, pc_nic_ip, apc_ip, pc_iperf_log_file = get_configs(env) + + pc_iperf_log_file = os.path.join(env.log_path, "pc_iperf_log.md") + + test_result = { + "tcp_tx": TestResult("tcp", "tx", BEST_PERFORMANCE_CONFIG), + "tcp_rx": TestResult("tcp", "rx", BEST_PERFORMANCE_CONFIG), + "udp_tx": TestResult("udp", "tx", BEST_PERFORMANCE_CONFIG), + "udp_rx": TestResult("udp", "rx", BEST_PERFORMANCE_CONFIG), + } + + # 1. build config + build_iperf_with_config(BEST_PERFORMANCE_CONFIG) + + # 2. get DUT and download + dut = env.get_dut("iperf", "examples/wifi/iperf") + dut.start_app() + dut.expect("esp32>") + + # 3. run test for each required att value + for ap_info in ap_list: + test_utility = IperfTestUtility(dut, BEST_PERFORMANCE_CONFIG, ap_info["ssid"], ap_info["password"], + pc_nic_ip, pc_iperf_log_file, test_result) + + PowerControl.Control.control_rest(apc_ip, ap_info["outlet"], "OFF") + PowerControl.Control.control(apc_ip, {ap_info["outlet"]: "ON"}) + Attenuator.set_att(att_port, 0) + + if not test_utility.wait_ap_power_on(): + Utility.console_log("[{}] failed to power on, skip testing this AP" + .format(ap_info["ssid"]), color="red") + continue + + for atten_val in ATTEN_VALUE_LIST: + assert Attenuator.set_att(att_port, atten_val) is True + test_utility.run_all_cases(atten_val) + + # 4. check test results + env.close_dut("iperf") + + # 5. generate report + report = ThroughputVsRssiReport(os.path.join(env.log_path, "ThroughputVsRssiReport"), + test_result) + report.generate_report() + + +@IDF.idf_example_test(env_tag="Example_ShieldBox") +def test_wifi_throughput_basic(env, extra_data): + """ + steps: | + 1. test TCP tx rx and UDP tx rx throughput + 2. compare with the pre-defined pass standard + """ + att_port, ap_list, pc_nic_ip, apc_ip, pc_iperf_log_file = get_configs(env) + ap_info = ap_list[0] + + # 1. build iperf with best config + build_iperf_with_config(BEST_PERFORMANCE_CONFIG) + + # 2. get DUT + dut = env.get_dut("iperf", "examples/wifi/iperf") + dut.start_app() + dut.expect("esp32>") + + # 3. preparing + test_result = { + "tcp_tx": TestResult("tcp", "tx", BEST_PERFORMANCE_CONFIG), + "tcp_rx": TestResult("tcp", "rx", BEST_PERFORMANCE_CONFIG), + "udp_tx": TestResult("udp", "tx", BEST_PERFORMANCE_CONFIG), + "udp_rx": TestResult("udp", "rx", BEST_PERFORMANCE_CONFIG), + } + + test_utility = IperfTestUtility(dut, BEST_PERFORMANCE_CONFIG, ap_info["ssid"], + ap_info["password"], pc_nic_ip, pc_iperf_log_file, test_result) + + PowerControl.Control.control_rest(apc_ip, ap_info["outlet"], "OFF") + PowerControl.Control.control(apc_ip, {ap_info["outlet"]: "ON"}) + assert Attenuator.set_att(att_port, 0) is True + + if not test_utility.wait_ap_power_on(): + Utility.console_log("[{}] failed to power on, skip testing this AP" + .format(ap_info["ssid"]), color="red") + + # 4. run test for TCP Tx, Rx and UDP Tx, Rx + for _ in range(RETRY_COUNT_FOR_BEST_PERFORMANCE): + test_utility.run_all_cases(0) + + # 5. log performance and compare with pass standard + for throughput_type in test_result: + IDF.log_performance("{}_throughput".format(throughput_type), + "{:.02f} Mbps".format(test_result[throughput_type].get_best_throughput())) + # do check after logging, otherwise test will exit immediately if check fail, some performance can't be logged. + for throughput_type in test_result: + IDF.check_performance("{}_throughput".format(throughput_type), + test_result[throughput_type].get_best_throughput()) + + env.close_dut("iperf") + + +if __name__ == '__main__': + test_wifi_throughput_basic(env_config_file="EnvConfig.yml") + test_wifi_throughput_with_different_configs(env_config_file="EnvConfig.yml") + test_wifi_throughput_vs_rssi(env_config_file="EnvConfig.yml") diff --git a/examples/wifi/iperf/sdkconfig.defaults b/examples/wifi/iperf/sdkconfig.defaults index 9c03a72861..613b73f3f8 100644 --- a/examples/wifi/iperf/sdkconfig.defaults +++ b/examples/wifi/iperf/sdkconfig.defaults @@ -2,6 +2,8 @@ CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 CONFIG_MEMMAP_SMP=y +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096 + CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=16 CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=64 CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=64 diff --git a/examples/wifi/iperf/sdkconfig.defaults.00 b/examples/wifi/iperf/sdkconfig.defaults.00 new file mode 100644 index 0000000000..448cc6270d --- /dev/null +++ b/examples/wifi/iperf/sdkconfig.defaults.00 @@ -0,0 +1,6 @@ +CONFIG_MEMMAP_SMP=y + +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096 + +CONFIG_INT_WDT= +CONFIG_TASK_WDT= diff --git a/examples/wifi/iperf/sdkconfig.defaults.01 b/examples/wifi/iperf/sdkconfig.defaults.01 new file mode 100644 index 0000000000..846ff9efe3 --- /dev/null +++ b/examples/wifi/iperf/sdkconfig.defaults.01 @@ -0,0 +1,25 @@ +CONFIG_MEMMAP_SMP=y + +CONFIG_INT_WDT= +CONFIG_TASK_WDT= + +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096 + +CONFIG_FREERTOS_UNICORE= +CONFIG_FREERTOS_HZ=1000 + +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=12 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=48 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=48 +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=12 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=12 + +CONFIG_TCP_SND_BUF_DEFAULT=11488 +CONFIG_TCP_WND_DEFAULT=11488 +CONFIG_TCP_RECVMBOX_SIZE=12 +CONFIG_UDP_RECVMBOX_SIZE=12 +CONFIG_TCPIP_RECVMBOX_SIZE=48 +CONFIG_LWIP_ETHARP_TRUST_IP_MAC= + diff --git a/examples/wifi/iperf/sdkconfig.defaults.02 b/examples/wifi/iperf/sdkconfig.defaults.02 new file mode 100644 index 0000000000..60020741e7 --- /dev/null +++ b/examples/wifi/iperf/sdkconfig.defaults.02 @@ -0,0 +1,25 @@ +CONFIG_MEMMAP_SMP=y + +CONFIG_INT_WDT= +CONFIG_TASK_WDT= + +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096 + +CONFIG_FREERTOS_UNICORE= +CONFIG_FREERTOS_HZ=1000 + +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=64 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=64 +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=32 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=32 + +CONFIG_TCP_SND_BUF_DEFAULT=11488 +CONFIG_TCP_WND_DEFAULT=11488 +CONFIG_TCP_RECVMBOX_SIZE=12 +CONFIG_UDP_RECVMBOX_SIZE=12 +CONFIG_TCPIP_RECVMBOX_SIZE=48 +CONFIG_LWIP_ETHARP_TRUST_IP_MAC= + diff --git a/examples/wifi/iperf/sdkconfig.defaults.03 b/examples/wifi/iperf/sdkconfig.defaults.03 new file mode 100644 index 0000000000..9c5a4e41bc --- /dev/null +++ b/examples/wifi/iperf/sdkconfig.defaults.03 @@ -0,0 +1,25 @@ +CONFIG_MEMMAP_SMP=y + +CONFIG_INT_WDT= +CONFIG_TASK_WDT= + +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096 + +CONFIG_FREERTOS_UNICORE= +CONFIG_FREERTOS_HZ=1000 + +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=64 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=64 +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=32 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=32 + +CONFIG_TCP_SND_BUF_DEFAULT=32768 +CONFIG_TCP_WND_DEFAULT=32768 +CONFIG_TCP_RECVMBOX_SIZE=64 +CONFIG_UDP_RECVMBOX_SIZE=64 +CONFIG_TCPIP_RECVMBOX_SIZE=64 +CONFIG_LWIP_ETHARP_TRUST_IP_MAC= + diff --git a/examples/wifi/iperf/sdkconfig.defaults.04 b/examples/wifi/iperf/sdkconfig.defaults.04 new file mode 100644 index 0000000000..01b30232cf --- /dev/null +++ b/examples/wifi/iperf/sdkconfig.defaults.04 @@ -0,0 +1,25 @@ +CONFIG_MEMMAP_SMP=y + +CONFIG_INT_WDT= +CONFIG_TASK_WDT= + +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096 + +CONFIG_FREERTOS_UNICORE= +CONFIG_FREERTOS_HZ=1000 + +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=64 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=64 +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=32 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=32 + +CONFIG_TCP_SND_BUF_DEFAULT=65535 +CONFIG_TCP_WND_DEFAULT=65535 +CONFIG_TCP_RECVMBOX_SIZE=64 +CONFIG_UDP_RECVMBOX_SIZE=64 +CONFIG_TCPIP_RECVMBOX_SIZE=64 +CONFIG_LWIP_ETHARP_TRUST_IP_MAC= + diff --git a/examples/wifi/iperf/sdkconfig.defaults.05 b/examples/wifi/iperf/sdkconfig.defaults.05 new file mode 100644 index 0000000000..0c6fc87abf --- /dev/null +++ b/examples/wifi/iperf/sdkconfig.defaults.05 @@ -0,0 +1,29 @@ +CONFIG_MEMMAP_SMP=y + +CONFIG_INT_WDT= +CONFIG_TASK_WDT= + +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096 + +CONFIG_FREERTOS_UNICORE= +CONFIG_FREERTOS_HZ=1000 + +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=64 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=64 +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=32 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=32 + +CONFIG_TCP_SND_BUF_DEFAULT=65535 +CONFIG_TCP_WND_DEFAULT=65535 +CONFIG_TCP_RECVMBOX_SIZE=64 +CONFIG_UDP_RECVMBOX_SIZE=64 +CONFIG_TCPIP_RECVMBOX_SIZE=64 +CONFIG_LWIP_ETHARP_TRUST_IP_MAC= + +CONFIG_FLASHMODE_QIO=y +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_LWIP_IRAM_OPTIMIZATION=y + diff --git a/examples/wifi/iperf/sdkconfig.defaults.06 b/examples/wifi/iperf/sdkconfig.defaults.06 new file mode 100644 index 0000000000..3d016f9544 --- /dev/null +++ b/examples/wifi/iperf/sdkconfig.defaults.06 @@ -0,0 +1,26 @@ +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096 + +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=64 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=64 +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=32 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=32 + +CONFIG_FREERTOS_UNICORE=y +CONFIG_FREERTOS_HZ=1000 + +CONFIG_INT_WDT= +CONFIG_TASK_WDT= + +CONFIG_TCP_SND_BUF_DEFAULT=65535 +CONFIG_TCP_WND_DEFAULT=65535 +CONFIG_TCP_RECVMBOX_SIZE=64 +CONFIG_UDP_RECVMBOX_SIZE=64 +CONFIG_TCPIP_RECVMBOX_SIZE=64 +CONFIG_LWIP_ETHARP_TRUST_IP_MAC= + +CONFIG_FLASHMODE_QIO=y +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_LWIP_IRAM_OPTIMIZATION=y diff --git a/examples/wifi/iperf/sdkconfig.defaults.07 b/examples/wifi/iperf/sdkconfig.defaults.07 new file mode 100644 index 0000000000..12460b84be --- /dev/null +++ b/examples/wifi/iperf/sdkconfig.defaults.07 @@ -0,0 +1,30 @@ +CONFIG_ESP32_DEFAULT_CPU_FREQ_80=y +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=80 +CONFIG_MEMMAP_SMP=y + +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096 + +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=64 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=64 +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=32 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=32 + +CONFIG_FREERTOS_UNICORE= +CONFIG_FREERTOS_HZ=1000 + +CONFIG_INT_WDT= +CONFIG_TASK_WDT= + +CONFIG_TCP_SND_BUF_DEFAULT=65535 +CONFIG_TCP_WND_DEFAULT=65535 +CONFIG_TCP_RECVMBOX_SIZE=64 +CONFIG_UDP_RECVMBOX_SIZE=64 +CONFIG_TCPIP_RECVMBOX_SIZE=64 +CONFIG_LWIP_ETHARP_TRUST_IP_MAC= + +CONFIG_FLASHMODE_QIO=y +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_LWIP_IRAM_OPTIMIZATION=y diff --git a/examples/wifi/iperf/sdkconfig.defaults.99 b/examples/wifi/iperf/sdkconfig.defaults.99 new file mode 100644 index 0000000000..dd516ba176 --- /dev/null +++ b/examples/wifi/iperf/sdkconfig.defaults.99 @@ -0,0 +1,30 @@ +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 +CONFIG_MEMMAP_SMP=y + +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=4096 + +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=16 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=64 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=64 +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=32 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=32 + +CONFIG_FREERTOS_UNICORE= +CONFIG_FREERTOS_HZ=1000 + +CONFIG_INT_WDT= +CONFIG_TASK_WDT= + +CONFIG_TCP_SND_BUF_DEFAULT=65535 +CONFIG_TCP_WND_DEFAULT=65535 +CONFIG_TCP_RECVMBOX_SIZE=64 +CONFIG_UDP_RECVMBOX_SIZE=64 +CONFIG_TCPIP_RECVMBOX_SIZE=64 +CONFIG_LWIP_ETHARP_TRUST_IP_MAC= + +CONFIG_FLASHMODE_QIO=y +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +CONFIG_LWIP_IRAM_OPTIMIZATION=y diff --git a/examples/wifi/iperf/test_report.py b/examples/wifi/iperf/test_report.py new file mode 100644 index 0000000000..aed33a53ce --- /dev/null +++ b/examples/wifi/iperf/test_report.py @@ -0,0 +1,245 @@ +""" +this module generates markdown format test report for throughput test. + +The test report contains 2 parts: + +1. throughput with different configs +2. throughput with RSSI +""" +import os + + +class ThroughputForConfigsReport(object): + THROUGHPUT_TYPES = ["tcp_tx", "tcp_rx", "udp_tx", "udp_rx"] + + REPORT_FILE_NAME = "ThroughputForConfigs.md" + + def __init__(self, output_path, ap_ssid, throughput_results, sdkconfig_files): + """ + :param ap_ssid: the ap we expected to use + :param throughput_results: config with the following type:: + { + "config_name": { + "tcp_tx": result, + "tcp_rx": result, + "udp_tx": result, + "udp_rx": result, + }, + "config_name2": {}, + } + """ + self.output_path = output_path + self.ap_ssid = ap_ssid + self.results = throughput_results + self.sdkconfigs = dict() + for config_name in sdkconfig_files: + self.sdkconfigs[config_name] = self._parse_config_file(sdkconfig_files[config_name]) + if not os.path.exists(output_path): + os.makedirs(output_path) + self.sort_order = self.sdkconfigs.keys() + self.sort_order.sort() + + @staticmethod + def _parse_config_file(config_file_path): + sdkconfig = {} + with open(config_file_path, "r") as f: + for line in f: + if not line.isspace(): + if line[0] == "#": + continue + name, value = line.split("=") + value = value.strip("\r\n") + sdkconfig[name] = value if value else "n" + return sdkconfig + + def _generate_the_difference_between_configs(self): + """ + generate markdown list for different configs:: + + default: esp-idf default + low: + * `config name 1`: old value -> new value + * `config name 2`: old value -> new value + * ... + ... + + """ + + data = "## Config Definition:\r\n\r\n" + + def find_difference(base, new): + _difference = {} + all_configs = set(base.keys()) + all_configs.update(set(new.keys())) + for _config in all_configs: + try: + _base_value = base[_config] + except KeyError: + _base_value = "null" + try: + _new_value = new[_config] + except KeyError: + _new_value = "null" + if _base_value != _new_value: + _difference[_config] = "{} -> {}".format(_base_value, _new_value) + return _difference + + for i, _config_name in enumerate(self.sort_order): + current_config = self.sdkconfigs[_config_name] + + if i > 0: + previous_config_name = self.sort_order[i-1] + previous_config = self.sdkconfigs[previous_config_name] + else: + previous_config = previous_config_name = None + + if previous_config: + # log the difference + difference = find_difference(previous_config, current_config) + data += "* {} (compared to {}):\r\n".format(_config_name, previous_config_name) + for diff_name in difference: + data += " * `{}`: {}\r\n".format(diff_name, difference[diff_name]) + return data + + def _generate_report_for_one_type(self, throughput_type): + """ + generate markdown table with the following format:: + + | config name | throughput (Mbps) | free heap size (bytes) | + |-------------|-------------------|------------------------| + | default | 32.11 | 147500 | + | low | 32.11 | 147000 | + | medium | 33.22 | 120000 | + | high | 43.11 | 100000 | + | max | 45.22 | 79000 | + """ + empty = True + + ret = "\r\n### {} {}\r\n\r\n".format(*throughput_type.split("_")) + ret += "| config name | throughput (Mbps) | free heap size (bytes) |\r\n" + ret += "|-------------|-------------------|------------------------|\r\n" + for config in self.sort_order: + try: + result = self.results[config][throughput_type] + throughput = "{:.02f}".format(max(result.throughput_by_att[self.ap_ssid].values())) + heap_size = str(result.heap_size) + # although markdown table will do alignment + # do align here for better text editor presentation + ret += "| {:<12}| {:<18}| {:<23}|\r\n".format(config, throughput, heap_size) + empty = False + except KeyError: + pass + return ret if not empty else "" + + def generate_report(self): + data = "# Throughput for different configs\r\n" + data += "\r\nAP: {}\r\n".format(self.ap_ssid) + + for throughput_type in self.THROUGHPUT_TYPES: + data += self._generate_report_for_one_type(throughput_type) + data += "\r\n------\r\n" + + data += self._generate_the_difference_between_configs() + + with open(os.path.join(self.output_path, self.REPORT_FILE_NAME), "w") as f: + f.write(data) + + +class ThroughputVsRssiReport(object): + + REPORT_FILE_NAME = "ThroughputVsRssi.md" + + def __init__(self, output_path, throughput_results): + """ + :param throughput_results: config with the following type:: + { + "tcp_tx": result, + "tcp_rx": result, + "udp_tx": result, + "udp_rx": result, + } + """ + self.output_path = output_path + self.raw_data_path = os.path.join(output_path, "raw_data") + self.results = throughput_results + self.throughput_types = self.results.keys() + self.throughput_types.sort() + if not os.path.exists(self.raw_data_path): + os.makedirs(self.raw_data_path) + + def _generate_summary(self): + """ + generate summary with the following format:: + + | item | curve analysis | max throughput (Mbps) | + |---------|----------------|-----------------------| + | tcp tx | Success | 32.11 | + | tcp rx | Success | 32.11 | + | udp tx | Success | 45.22 | + | udp rx | Failed | 55.44 | + """ + + ret = "\r\n### Summary\r\n\r\n" + ret += "| item | curve analysis | max throughput (Mbps) |\r\n" + ret += "|---------|----------------|-----------------------|\r\n" + + for _type in self.throughput_types: + result = self.results[_type] + max_throughput = 0.0 + curve_analysis = "Failed" if result.error_list else "Success" + for ap_ssid in result.throughput_by_att: + _max_for_ap = max(result.throughput_by_rssi[ap_ssid].values()) + if _max_for_ap > max_throughput: + max_throughput = _max_for_ap + max_throughput = "{:.02f}".format(max_throughput) + ret += "| {:<8}| {:<15}| {:<22}|\r\n".format("{}_{}".format(result.proto, result.direction), + curve_analysis, max_throughput) + return ret + + def _generate_report_for_one_type(self, result): + """ + generate markdown table with the following format:: + + ### tcp rx + + Errors: + + * detected error 1 + * ... + + AP: ap_ssid + + ![throughput Vs RSSI](path to figure) + + AP: ap_ssid + + ![throughput Vs RSSI](path to figure) + + """ + result.post_analysis() + ret = "\r\n### {} {}\r\n".format(result.proto, result.direction) + if result.error_list: + ret += "\r\nErrors:\r\n\r\n" + for error in result.error_list: + ret += "* " + error + "\r\n" + for ap_ssid in result.throughput_by_rssi: + ret += "\r\nAP: {}\r\n".format(ap_ssid) + # draw figure + file_name = result.draw_throughput_figure(self.raw_data_path, ap_ssid, "rssi") + result.draw_throughput_figure(self.raw_data_path, ap_ssid, "att") + result.draw_rssi_vs_att_figure(self.raw_data_path, ap_ssid) + + ret += "\r\n![throughput Vs RSSI]({})\r\n".format(os.path.join("raw_data", file_name)) + + return ret + + def generate_report(self): + data = "# Throughput Vs RSSI\r\n" + + data += self._generate_summary() + + for _type in self.throughput_types: + data += self._generate_report_for_one_type(self.results[_type]) + + with open(os.path.join(self.output_path, self.REPORT_FILE_NAME), "w") as f: + f.write(data) From 9e7a69be88cbc46e2bb3a6f165895918a822d57e Mon Sep 17 00:00:00 2001 From: He Yin Ling Date: Mon, 8 Jan 2018 20:33:09 +0800 Subject: [PATCH 099/187] example test: integrate wifi throughput test to CI --- .gitlab-ci.yml | 23 ++++++++++++++++++++-- tools/tiny-test-fw/TinyFW.py | 1 + tools/tiny-test-fw/Utility/CIAssignTest.py | 14 +++++++++---- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d5491a64d3..f7bff45e30 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -493,10 +493,17 @@ check_submodule_sync: - git submodule update --init --recursive assign_test: - <<: *build_template + tags: + - assign_test + image: $CI_DOCKER_REGISTRY/ubuntu-test-env$BOT_DOCKER_IMAGE_TAG stage: assign_test # gitlab ci do not support match job with RegEx or wildcard now in dependencies. # we have a lot build example jobs. now we don't use dependencies, just download all artificats of build stage. + dependencies: + - build_ssc_00 + - build_ssc_01 + - build_ssc_02 + - build_esp_idf_tests variables: UT_BIN_PATH: "tools/unit-test-app/output" OUTPUT_BIN_PATH: "test_bins/ESP32_IDF" @@ -548,12 +555,17 @@ assign_test: TEST_CASE_PATH: "$CI_PROJECT_DIR/examples" CONFIG_FILE: "$CI_PROJECT_DIR/examples/test_configs/$CI_JOB_NAME.yml" LOG_PATH: "$CI_PROJECT_DIR/TEST_LOGS" + ENV_FILE: "$CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/EnvConfig.yml" script: # first test if config file exists, if not exist, exit 0 - test -e $CONFIG_FILE || exit 0 + # clone test env configs + - git clone $TEST_ENV_CONFIG_REPOSITORY + - cd ci-test-runner-configs + - python $CHECKOUT_REF_SCRIPT ci-test-runner-configs - cd $TEST_FW_PATH # run test - - python Runner.py $TEST_CASE_PATH -c $CONFIG_FILE + - python Runner.py $TEST_CASE_PATH -c $CONFIG_FILE -e $ENV_FILE .unit_test_template: &unit_test_template <<: *example_test_template @@ -565,6 +577,7 @@ assign_test: TEST_CASE_PATH: "$CI_PROJECT_DIR/tools/unit-test-app" CONFIG_FILE: "$CI_PROJECT_DIR/components/idf_test/unit_test/CIConfigs/$CI_JOB_NAME.yml" LOG_PATH: "$CI_PROJECT_DIR/TEST_LOGS" + ENV_FILE: "$CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/EnvConfig.yml" .test_template: &test_template stage: test @@ -638,6 +651,12 @@ example_test_001_01: - ESP32 - Example_WIFI +example_test_002_01: + <<: *example_test_template + tags: + - ESP32 + - Example_ShieldBox + UT_001_01: <<: *unit_test_template tags: diff --git a/tools/tiny-test-fw/TinyFW.py b/tools/tiny-test-fw/TinyFW.py index b227cf7aad..34463b2857 100644 --- a/tools/tiny-test-fw/TinyFW.py +++ b/tools/tiny-test-fw/TinyFW.py @@ -106,6 +106,7 @@ get_passed_cases = TestResult.get_passed_cases MANDATORY_INFO = { "execution_time": 1, "env_tag": "default", + "category": "function", } diff --git a/tools/tiny-test-fw/Utility/CIAssignTest.py b/tools/tiny-test-fw/Utility/CIAssignTest.py index 04e43f076e..3e570cc31a 100644 --- a/tools/tiny-test-fw/Utility/CIAssignTest.py +++ b/tools/tiny-test-fw/Utility/CIAssignTest.py @@ -122,6 +122,10 @@ class AssignTest(object): """ # subclass need to rewrite CI test job pattern, to filter all test jobs CI_TEST_JOB_PATTERN = re.compile(r"^test_.+") + # by default we only run function in CI, as other tests could take long time + DEFAULT_FILTER = { + "category": "function", + } def __init__(self, test_case_path, ci_config_file, case_group=Group): self.test_case_path = test_case_path @@ -140,15 +144,17 @@ class AssignTest(object): job_list.append(GitlabCIJob.Job(ci_config[job_name], job_name)) return job_list - @staticmethod - def _search_cases(test_case_path, case_filter=None): + def _search_cases(self, test_case_path, case_filter=None): """ :param test_case_path: path contains test case folder - :param case_filter: filter for test cases + :param case_filter: filter for test cases. the filter to use is default filter updated with case_filter param. :return: filtered test case list """ + _case_filter = self.DEFAULT_FILTER.copy() + if case_filter: + _case_filter.update(case_filter) test_methods = SearchCases.Search.search_test_cases(test_case_path) - return CaseConfig.filter_test_cases(test_methods, case_filter if case_filter else dict()) + return CaseConfig.filter_test_cases(test_methods, _case_filter) def _group_cases(self): """ From 05e09a5bacb231f3699815801feff035a0e26a0a Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 15 May 2018 14:37:04 +0800 Subject: [PATCH 100/187] ci: Only run XTAL unit tests assuming board has an XTAL, run less repeats --- components/soc/esp32/test/test_rtc_clk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/soc/esp32/test/test_rtc_clk.c b/components/soc/esp32/test/test_rtc_clk.c index 9efad4a1e4..39c3ac7fd0 100644 --- a/components/soc/esp32/test/test_rtc_clk.c +++ b/components/soc/esp32/test/test_rtc_clk.c @@ -134,7 +134,7 @@ TEST_CASE("Test fast switching between PLL and XTAL", "[rtc_clk]") test_clock_switching(rtc_clk_cpu_freq_set_fast); } -#define COUNT_TEST 10 +#define COUNT_TEST 3 #define TIMEOUT_TEST_MS (5 + CONFIG_ESP32_RTC_CLK_CAL_CYCLES / 16) void stop_rtc_external_quartz(){ @@ -266,7 +266,7 @@ TEST_CASE("Test starting 'External 32kHz XTAL' on the board with it.", "[rtc_clk #else -TEST_CASE("Test starting 'External 32kHz XTAL' on the board without it.", "[rtc_clk]") +TEST_CASE("Test starting 'External 32kHz XTAL' on the board without it.", "[rtc_clk][ignore]") { printf("Tries to start the 'External 32kHz XTAL' on the board without it. " "Clock switching to 'Internal 150 kHz RC oscillator'.\n"); From 3d92c6cccd44cdfad6824b2d1a5057ecec422517 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 15 May 2018 18:02:28 +0800 Subject: [PATCH 101/187] nvs README: Remove section about encryption capability --- components/nvs_flash/README.rst | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/components/nvs_flash/README.rst b/components/nvs_flash/README.rst index f04ac592ce..b58a0b2a4a 100644 --- a/components/nvs_flash/README.rst +++ b/components/nvs_flash/README.rst @@ -49,17 +49,7 @@ Security, tampering, and robustness NVS library doesn't implement tamper prevention measures. It is possible for anyone with physical access to the flash chip to alter, erase, or add key-value pairs. -NVS is compatible with the ESP32 flash encryption system, and it can store key-value pairs in an encrypted form. Some metadata, like page state and write/erase flags of individual entries can not be encrypted as they are represented as bits of flash memory for efficient access and manipulation. Flash encryption can prevent some forms of modification: - -- replacing keys or values with arbitrary data -- changing data types of values - -The following forms of modification are still possible when flash encryption is used: - -- erasing a page completely, removing all key-value pairs which were stored in that page -- corrupting data in a page, which will cause the page to be erased automatically when such condition is detected -- rolling back the contents of flash memory to an earlier snapshot -- merging two snapshots of flash memory, rolling back some key-value pairs to an earlier state (although this is possible to mitigate with the current design — TODO) +NVS is not currently compatible with the ESP32 flash encryption system. The library does try to recover from conditions when flash memory is in an inconsistent state. In particular, one should be able to power off the device at any point and time and then power it back on. This should not result in loss of data, expect for the new key-value pair if it was being written at the moment of power off. The library should also be able to initialize properly with any random data present in flash memory. From 6722a78684dfa33670cfdcade5f98e931b69aab4 Mon Sep 17 00:00:00 2001 From: Wenderson Oliveira Date: Thu, 10 May 2018 19:49:17 -0300 Subject: [PATCH 102/187] Fix git command. Merges https://github.com/espressif/esp-idf/pull/1943 --- docs/en/api-guides/jtag-debugging/building-openocd-windows.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/api-guides/jtag-debugging/building-openocd-windows.rst b/docs/en/api-guides/jtag-debugging/building-openocd-windows.rst index 4f0419135c..61dab53deb 100644 --- a/docs/en/api-guides/jtag-debugging/building-openocd-windows.rst +++ b/docs/en/api-guides/jtag-debugging/building-openocd-windows.rst @@ -13,7 +13,7 @@ Download Sources of OpenOCD The sources for the ESP32-enabled variant of OpenOCD are available from Espressif GitHub under https://github.com/espressif/openocd-esp32. To download the sources, use the following commands:: cd ~/esp - git clone –recursive https://github.com/espressif/openocd-esp32.git + git clone --recursive https://github.com/espressif/openocd-esp32.git The clone of sources should be now saved in ``~/esp/openocd-esp32`` directory. From d19dbea059cf21c1fe9bbf2f371c5ede29d434f6 Mon Sep 17 00:00:00 2001 From: krzychb Date: Fri, 11 May 2018 20:08:55 +0200 Subject: [PATCH 103/187] Fixed git command --- docs/en/api-guides/jtag-debugging/building-openocd-macos.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/api-guides/jtag-debugging/building-openocd-macos.rst b/docs/en/api-guides/jtag-debugging/building-openocd-macos.rst index 349fd882c3..b56696732d 100644 --- a/docs/en/api-guides/jtag-debugging/building-openocd-macos.rst +++ b/docs/en/api-guides/jtag-debugging/building-openocd-macos.rst @@ -12,7 +12,7 @@ Download Sources of OpenOCD The sources for the ESP32-enabled variant of OpenOCD are available from Espressif GitHub under https://github.com/espressif/openocd-esp32. To download the sources, use the following commands:: cd ~/esp - git clone –recursive https://github.com/espressif/openocd-esp32.git + git clone --recursive https://github.com/espressif/openocd-esp32.git The clone of sources should be now saved in ``~/esp/openocd-esp32`` directory. From 846b848bfc987389336fe18b229651983dfa783a Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Mon, 26 Feb 2018 13:29:52 +0800 Subject: [PATCH 104/187] esp32/docs: fully support esp_wifi_80211_tx Closes https://github.com/espressif/esp-idf/issues/1256 Closes https://github.com/espressif/esp-idf/issues/1332 --- components/esp32/include/esp_wifi.h | 26 ++++++ components/esp32/lib | 2 +- docs/en/api-guides/wifi.rst | 132 ++++++++++------------------ 3 files changed, 75 insertions(+), 85 deletions(-) diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h index 79d6bd4b50..77ee218279 100755 --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -929,6 +929,32 @@ esp_err_t esp_wifi_set_event_mask(uint32_t mask); */ esp_err_t esp_wifi_get_event_mask(uint32_t *mask); +/** + * @brief Send raw ieee80211 data + * + * @attention Currently only support for sending beacon/probe request/probe response/action and non-QoS + * data frame + * + * @param ifx interface if the Wi-Fi mode is Station, the ifx should be WIFI_IF_STA. If the Wi-Fi + * mode is SoftAP, the ifx should be WIFI_IF_AP. If the Wi-Fi mode is Station+SoftAP, the + * ifx should be WIFI_IF_STA or WIFI_IF_AP. If the ifx is wrong, the API returns ESP_ERR_WIFI_IF. + * @param buffer raw ieee80211 buffer + * @param len the length of raw buffer, the len must be <= 1500 Bytes and >= 24 Bytes + * @param en_sys_seq indicate whether use the internal sequence number. If en_sys_seq is false, the + * sequence in raw buffer is unchanged, otherwise it will be overwritten by WiFi driver with + * the system sequence number. + * Generally, if esp_wifi_80211_tx is called before the Wi-Fi connection has been set up, both + * en_sys_seq==true and en_sys_seq==false are fine. However, if the API is called after the Wi-Fi + * connection has been set up, en_sys_seq must be true, otherwise ESP_ERR_WIFI_ARG is returned. + * + * @return + * - ESP_OK: success + * - ESP_ERR_WIFI_IF: Invalid interface + * - ESP_ERR_INVALID_ARG: Invalid parameter + * - ESP_ERR_WIFI_NO_MEM: out of memory + */ + +esp_err_t esp_wifi_80211_tx(wifi_interface_t ifx, const void *buffer, int len, bool en_sys_seq); #ifdef __cplusplus } diff --git a/components/esp32/lib b/components/esp32/lib index a93e18a06e..c581fa9bed 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit a93e18a06ef30002a92522054d7cd13206e30d4d +Subproject commit c581fa9beda86d1a2ef3d05fd4fcb2fb04895c13 diff --git a/docs/en/api-guides/wifi.rst b/docs/en/api-guides/wifi.rst index 6b8fe90867..8afdf88aa3 100755 --- a/docs/en/api-guides/wifi.rst +++ b/docs/en/api-guides/wifi.rst @@ -1295,51 +1295,9 @@ Wi-Fi 80211 Packet Send The esp_wifi_80211_tx API can be used to: - Send the beacon, probe request, probe response, action frame. - - Send the QoS and non-QoS data frame. + - Send the non-QoS data frame. -It cannot be used for sending cryptographic frames. - -Parameters of esp_wifi_80211_tx -+++++++++++++++++++++++++++++++++++++++++++ - -+-----------------------------+---------------------------------------------------+ -| Parameter | Description | -+=============================+===================================================+ -| ifx | Wi-Fi interface ID: if the Wi-Fi mode is Station, | -| | the ifx should be WIFI_IF_STA. If the Wi-Fi | -| | mode is SoftAP, the ifx should be WIFI_IF_AP. If | -| | the Wi-Fi mode is Station+SoftAP, the ifx should | -| | be WIFI_IF_STA or WIFI_IF_AP. | -| | If the ifx is wrong, the API returns | -| | ESP_ERR_WIFI_IF. | -+-----------------------------+---------------------------------------------------+ -| buffer | Raw 802.11 buffer. For building the correct | -| | buffer, refer to the following sections: | -| | | -| | If the buffer is wrong, or violates the Wi-Fi | -| | driver's restrictions, the API returns | -| | ESP_ERR_INVALID_ARG or results in unexpected | -| | behavior. **Please read the following section | -| | carefully to make sure you understand the | -| | restrictions on encapsulating the buffer.** | -| | | -+-----------------------------+---------------------------------------------------+ -| len | The length must be <= 1500; otherwise, the API | -| | will return ESP_ERR_INVALID_ARG. | -| | | -+-----------------------------+---------------------------------------------------+ -| en_sys_seq | If en_sys_seq is true, it means that the Wi-Fi | -| | driver will rewrite the sequence number in the | -| | buffer; otherwise, it will not rewrite the | -| | sequence number. | -| | Generally, if esp_wifi_80211_tx is called before | -| | the Wi-Fi connection has been set up, both | -| | en_sys_seq==true and en_sys_seq==false are fine. | -| | However, if the API is called after the Wi-Fi | -| | connection has been set up, en_sys_seq should be | -| | true. For more details, read the following section| -| | about the sequence configuration. | -+-----------------------------+---------------------------------------------------+ +It cannot be used for sending encrypted or QoS frames. Preconditions of Using esp_wifi_80211_tx ++++++++++++++++++++++++++++++++++++++++++++ @@ -1348,6 +1306,12 @@ Preconditions of Using esp_wifi_80211_tx - Either esp_wifi_set_promiscuous(true), or esp_wifi_start(), or both of these APIs return ESP_OK. This is because we need to make sure that Wi-Fi hardware is initialized before esp_wifi_80211_tx() is called. In ESP32, both esp_wifi_set_promiscuous(true) and esp_wifi_start() can trigger the initialization of Wi-Fi hardware. - The parameters of esp_wifi_80211_tx are hereby correctly provided. +Data rate ++++++++++++++++++++++++++++++++++++++++++++++++ + + - If there is no WiFi connection, the data rate is 1Mbps. + - If there is WiFi connection and the packet is from station to SoftAP or from SoftAP to station, the data rate is same as the WiFi connection. Otherwise the data rate is 1Mbps. + Side-Effects to Avoid in Different Scenarios +++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -1356,10 +1320,10 @@ Theoretically, if we do not consider the side-effects the API imposes on the Wi- +-----------------------------+---------------------------------------------------+ | Scenario | Description | +=============================+===================================================+ -| NO_CONN_MGMT | In this scenario, no Wi-Fi connection is set up, | +| No WiFi connection | In this scenario, no Wi-Fi connection is set up, | | | so there are no side-effects on the Wi-Fi driver. | -| - No Wi-Fi connection | If en_sys_seq==true, the Wi-Fi driver is | -| - Can send management frame| responsible for the sequence control. If | +| | If en_sys_seq==true, the Wi-Fi driver is | +| | responsible for the sequence control. If | | | en_sys_seq==false, the application needs to ensure| | | that the buffer has the correct sequence. | | | | @@ -1394,48 +1358,48 @@ Theoretically, if we do not consider the side-effects the API imposes on the Wi- | | side-effects and can be ignored when there are | | | good reasons for doing this. | +-----------------------------+---------------------------------------------------+ -| NO_CONN_NON_QOS | Same as in NO_CONN_MGMT | -| | | -| - No Wi-Fi connection | | -| - Can send non-QoS frame | | -| | | -+-----------------------------+---------------------------------------------------+ -| NO_CONN_QOS | Same as in NO_CONN_MGMT | -| | | -| - No Wi-Fi connection | | -| - Can send QoS frame | | -| | | -+-----------------------------+---------------------------------------------------+ -| CONN_MGMT | When the Wi-Fi connection is already set up, and | +| Have WiFi connection | When the Wi-Fi connection is already set up, and | | | the sequence is controlled by the application, the| -| - Have Wi-Fi connection | latter may impact the sequence control of the | -| - Send management frame | Wi-Fi connection, as a whole. So, the | -| only | recommendation is that en_sys_seq be true. | -| | The MAC-address recommendations in the | -| | NO_CONN_MGMT scenario also apply to the CONN_MGMT | -| | scenario. | -+-----------------------------+---------------------------------------------------+ -| CONN_NON_QOS | Generally, we should use a socket API, instead of | -| | this one, in order to send the data frame when | -| - Have Wi-Fi connection | the Wi-Fi connection is already set up. | -| - Can send non-QoS frame | | -| | However, if you have any special reasons for using| -| | this particular API, then en_sys_seq must be true;| -| | otherwise, you may impact the internal sequence | -| | control of the Wi-Fi connection described | -| | in CONN_MGMT. | -| | The MAC-address recommendations in the | -| | NO_CONN_MGMT scenario also apply to the CONN_MGMT | -| | scenario. | -+-----------------------------+---------------------------------------------------+ -| CONN_QOS | Same as in CONN_NON_QOS | +| | latter may impact the sequence control of the | +| | Wi-Fi connection, as a whole. So, the | +| | en_sys_seq need to be true, otherwise | +| | ESP_ERR_WIFI_ARG is returned. | | | | -| - Have Wi-Fi connection | | -| - Can send non-QoS frame | | +| | The MAC-address recommendations in the | +| | "No WiFi connection" scenario also apply to this | +| | scenario. | | | | +| | If the WiFi mode is station mode and the MAC | +| | address1 is the MAC of AP to which the station is | +| | connected, the MAC address2 is the MAC of station | +| | interface, we say the packets is from the station | +| | to SoftAP. On the other hand, if the WiFi mode is | +| | SoftAP mode and the MAC address1 is the MAC of | +| | the station who connects to this SoftAP, the MAC | +| | address2 is the MAC of SoftAP interface, we say | +| | the packet is from the SoftAP to station. | +| | To avoid conflicting with WiFi connections, the | +| | following checks are applied: | +| | | +| | - If the packet type is data and is from the | +| | station to SoftAP, the ToDS bit in ieee80211 | +| | frame control should be 1, the FromDS bit | +| | should be 0, otherwise the packet will be | +| | discarded by WiFi driver. | +| | - If the packet type is data and is from the | +| | softAP to station, the ToDS bit in ieee80211 | +| | frame control should be 0, the FromDS bit | +| | should be 1, otherwise the packet will be | +| | discarded by WiFi driver. | +| | - If the packet is from station to SoftAP or | +| | from SoftAP to station, the Power Management, | +| | More Data, Re-Transmission bits should be 0, | +| | otherwise the packet will be discarded by WiFi | +| | driver. | +| | | +| | ESP_ERR_WIFI_ARG is returned if any check fails. | +-----------------------------+---------------------------------------------------+ - Wi-Fi Sniffer Mode --------------------------- From 460c4fa486c6b8b5c6f6503009e58eb405db90fd Mon Sep 17 00:00:00 2001 From: Chen Wu Date: Mon, 12 Mar 2018 15:16:17 +0800 Subject: [PATCH 105/187] bugfix(ota): update ota to download valid bin file --- examples/system/ota/main/ota_example_main.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/examples/system/ota/main/ota_example_main.c b/examples/system/ota/main/ota_example_main.c index 3d8a3008d1..b5e0f60625 100644 --- a/examples/system/ota/main/ota_example_main.c +++ b/examples/system/ota/main/ota_example_main.c @@ -245,16 +245,22 @@ static void ota_example_task(void *pvParameter) } ESP_LOGI(TAG, "esp_ota_begin succeeded"); - bool resp_body_start = false, flag = true; + bool resp_body_start = false, socket_flag = true, http_200_flag = false; /*deal with all receive packet*/ - while (flag) { + while (socket_flag) { memset(text, 0, TEXT_BUFFSIZE); memset(ota_write_data, 0, BUFFSIZE); int buff_len = recv(socket_id, text, TEXT_BUFFSIZE, 0); if (buff_len < 0) { /*receive error*/ ESP_LOGE(TAG, "Error: receive data error! errno=%d", errno); task_fatal_error(); - } else if (buff_len > 0 && !resp_body_start) { /*deal with response header*/ + } else if (buff_len > 0 && !resp_body_start) { /*deal with response header*/ + // only start ota when server response 200 state code + if (strstr(text, "200") == NULL && !http_200_flag) { + ESP_LOGE(TAG, "ota url is invalid or bin is not exist"); + task_fatal_error(); + } + http_200_flag = true; memcpy(ota_write_data, text, buff_len); resp_body_start = read_past_http_header(text, buff_len, update_handle); } else if (buff_len > 0 && resp_body_start) { /*deal with response body*/ @@ -267,7 +273,7 @@ static void ota_example_task(void *pvParameter) binary_file_length += buff_len; ESP_LOGI(TAG, "Have written image length %d", binary_file_length); } else if (buff_len == 0) { /*packet over*/ - flag = false; + socket_flag = false; ESP_LOGI(TAG, "Connection closed, all packets received"); close(socket_id); } else { From 50f82a1aa563304bfdd8f82cdebb25c2372f02a4 Mon Sep 17 00:00:00 2001 From: baohongde Date: Tue, 15 May 2018 16:35:48 +0800 Subject: [PATCH 106/187] component/bt: Change scan mode after connected or disconnected --- examples/bluetooth/a2dp_sink/main/bt_app_av.c | 5 +++++ examples/bluetooth/a2dp_source/main/main.c | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/bluetooth/a2dp_sink/main/bt_app_av.c b/examples/bluetooth/a2dp_sink/main/bt_app_av.c index b1c432c576..b43456a663 100644 --- a/examples/bluetooth/a2dp_sink/main/bt_app_av.c +++ b/examples/bluetooth/a2dp_sink/main/bt_app_av.c @@ -97,6 +97,11 @@ static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param) uint8_t *bda = a2d->conn_stat.remote_bda; ESP_LOGI(BT_AV_TAG, "A2DP connection state: %s, [%02x:%02x:%02x:%02x:%02x:%02x]", m_a2d_conn_state_str[a2d->conn_stat.state], bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) { + esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE); + } else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTED){ + esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_NONE); + } break; } case ESP_A2D_AUDIO_STATE_EVT: { diff --git a/examples/bluetooth/a2dp_source/main/main.c b/examples/bluetooth/a2dp_source/main/main.c index a03080923a..eb63362301 100644 --- a/examples/bluetooth/a2dp_source/main/main.c +++ b/examples/bluetooth/a2dp_source/main/main.c @@ -386,7 +386,7 @@ static void bt_app_av_state_connecting(uint16_t event, void *param) ESP_LOGI(BT_AV_TAG, "a2dp connected"); m_a2d_state = APP_AV_STATE_CONNECTED; m_media_state = APP_AV_MEDIA_STATE_IDLE; - + esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_NONE); } else if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) { m_a2d_state = APP_AV_STATE_UNCONNECTED; } @@ -482,6 +482,7 @@ static void bt_app_av_state_connected(uint16_t event, void *param) if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) { ESP_LOGI(BT_AV_TAG, "a2dp disconnected"); m_a2d_state = APP_AV_STATE_UNCONNECTED; + esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE); } break; } @@ -515,6 +516,7 @@ static void bt_app_av_state_disconnecting(uint16_t event, void *param) if (a2d->conn_stat.state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) { ESP_LOGI(BT_AV_TAG, "a2dp disconnected"); m_a2d_state = APP_AV_STATE_UNCONNECTED; + esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE); } break; } From 40efc36849901ef6d2e4f2bb62eda1fa3089dfbf Mon Sep 17 00:00:00 2001 From: XiaXiaotian Date: Wed, 16 May 2018 18:50:28 +0800 Subject: [PATCH 107/187] Fix a few WiFi bugs 1. remove rc when ap not found closes issue: https://github.com/espressif/esp-idf/issues/1797 2. allocate mimo packet to internal memory 3. use FRC2 timer instead of WDEV_NOW() for modem sleep to calculate TBTT time. It fixes the bug that TBTT will be incorrect if beacon is lost. --- components/esp32/lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp32/lib b/components/esp32/lib index c581fa9bed..618fa4eb59 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit c581fa9beda86d1a2ef3d05fd4fcb2fb04895c13 +Subproject commit 618fa4eb596c07521d9cdcc1ba019fe5cd42cec6 From 174501ff3525b44d2932c73e4affeb6d1275edd2 Mon Sep 17 00:00:00 2001 From: baohongde Date: Wed, 16 May 2018 18:58:13 +0800 Subject: [PATCH 108/187] component/bt: modify BT GAP structure 1. Separate the upward and the downward 2. Cancel use of msg.aid when call btc_transfer_context --- .../bt/bluedroid/bta/include/bta/bta_api.h | 16 +- components/bt/bluedroid/btc/core/btc_dm.c | 22 +- .../btc/profile/std/gap/btc_gap_bt.c | 271 ++++++++++-------- .../btc/profile/std/include/btc_gap_bt.h | 15 +- 4 files changed, 187 insertions(+), 137 deletions(-) diff --git a/components/bt/bluedroid/bta/include/bta/bta_api.h b/components/bt/bluedroid/bta/include/bta/bta_api.h index ae645f5753..74ed278778 100644 --- a/components/bt/bluedroid/bta/include/bta/bta_api.h +++ b/components/bt/bluedroid/bta/include/bta/bta_api.h @@ -1022,7 +1022,7 @@ typedef struct { /* If the device name is known to application BTA skips the remote name request */ BOOLEAN is_limited; /* TRUE, if the limited inquiry bit is set in the CoD */ INT8 rssi; /* The rssi value */ - UINT8 *p_eir; /* received EIR */ + UINT8 *p_eir; /* Received EIR */ #if (BLE_INCLUDED == TRUE) UINT8 inq_result_type; UINT8 ble_addr_type; @@ -1054,7 +1054,7 @@ typedef struct { tBTA_SERVICE_MASK services; /* Services found on peer device. */ // btla-specific ++ UINT8 *p_raw_data; /* Raw data for discovery DB */ - UINT32 raw_data_size; /* size of raw data */ + UINT32 raw_data_size; /* Size of raw data */ tBT_DEVICE_TYPE device_type; /* device type in case it is BLE device */ UINT32 num_uuids; UINT8 *p_uuid_list; @@ -1075,11 +1075,17 @@ typedef union { tBTA_DM_INQ_RES inq_res; /* Inquiry result for a peer device. */ tBTA_DM_INQ_CMPL inq_cmpl; /* Inquiry complete. */ tBTA_DM_DISC_RES disc_res; /* Discovery result for a peer device. */ - tBTA_DM_DISC_BLE_RES disc_ble_res; /* discovery result for GATT based service */ + tBTA_DM_DISC_BLE_RES disc_ble_res; /* Discovery result for GATT based service */ tBTA_DM_DI_DISC_CMPL di_disc; /* DI discovery result for a peer device */ - } tBTA_DM_SEARCH; +/* Structure of search callback event and structures */ +typedef struct { + tBTA_DM_SEARCH_EVT event; /* Search callback events */ + UINT16 len; /* Length of p_data */ + tBTA_DM_SEARCH *p_data; /* Union of all search callback structures */ +} tBTA_DM_SEARCH_PARAM; + /* Search callback */ typedef void (tBTA_DM_SEARCH_CBACK)(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data); @@ -1089,7 +1095,7 @@ typedef void (tBTA_DM_EXEC_CBACK) (void *p_param); /* Encryption callback*/ typedef void (tBTA_DM_ENCRYPT_CBACK) (BD_ADDR bd_addr, tBTA_TRANSPORT transport, tBTA_STATUS result); -/* relate to ESP_BLE_SEC_xxx in esp_gatt_defs.h */ +/* Relate to ESP_BLE_SEC_xxx in esp_gatt_defs.h */ #if BLE_INCLUDED == TRUE #define BTA_DM_BLE_SEC_NONE BTM_BLE_SEC_NONE #define BTA_DM_BLE_SEC_ENCRYPT BTM_BLE_SEC_ENCRYPT diff --git a/components/bt/bluedroid/btc/core/btc_dm.c b/components/bt/bluedroid/btc/core/btc_dm.c index 89ca9e0be0..1ed93a725e 100644 --- a/components/bt/bluedroid/btc/core/btc_dm.c +++ b/components/bt/bluedroid/btc/core/btc_dm.c @@ -32,14 +32,6 @@ #if (BTC_GAP_BT_INCLUDED == TRUE) #include "btc_gap_bt.h" - -static inline void btc_gap_bt_cb_to_app(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param) -{ - esp_bt_gap_cb_t cb = (esp_bt_gap_cb_t)btc_profile_cb_get(BTC_PID_GAP_BT); - if (cb) { - cb(event, param); - } -} #endif /* BTC_GAP_BT_INCLUDED == TRUE */ /****************************************************************************** ** Constants & Macros @@ -360,10 +352,22 @@ static void btc_dm_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl) } #if (BTC_GAP_BT_INCLUDED == TRUE) esp_bt_gap_cb_param_t param; + bt_status_t ret; + btc_msg_t msg; + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BT; + msg.act = BTC_GAP_BT_AUTH_CMPL_EVT; param.auth_cmpl.stat = status; memcpy(param.auth_cmpl.bda, p_auth_cmpl->bd_addr, ESP_BD_ADDR_LEN); memcpy(param.auth_cmpl.device_name, p_auth_cmpl->bd_name, ESP_BT_GAP_MAX_BDNAME_LEN + 1); - btc_gap_bt_cb_to_app(ESP_BT_GAP_AUTH_CMPL_EVT, ¶m); + + ret = btc_transfer_context(&msg, ¶m, + sizeof(esp_bt_gap_cb_param_t), NULL); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_DEBUG("%s btc_transfer_context failed\n", __func__); + } + #endif /* BTC_GAP_BT_INCLUDED == TRUE */ (void) status; } diff --git a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c index 6c2a6d5f14..c6a5a0894a 100644 --- a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c +++ b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_bt.c @@ -138,31 +138,35 @@ static void btc_gap_bt_get_remote_service_record(btc_gap_bt_args_t *arg) *******************************************************************************/ static void search_devices_copy_cb(btc_msg_t *msg, void *p_dest, void *p_src) { - tBTA_DM_SEARCH *p_dest_data = (tBTA_DM_SEARCH *) p_dest; - tBTA_DM_SEARCH *p_src_data = (tBTA_DM_SEARCH *) p_src; - + tBTA_DM_SEARCH_PARAM *p_dest_data = (tBTA_DM_SEARCH_PARAM *) p_dest; + tBTA_DM_SEARCH_PARAM *p_src_data = (tBTA_DM_SEARCH_PARAM *) p_src; if (!p_src) { return; } + p_dest_data->p_data = (void *)osi_malloc(p_dest_data->len); + memset(p_dest_data->p_data, 0x00, p_dest_data->len); + memcpy(p_dest_data->p_data, p_src_data->p_data, p_dest_data->len); - switch (msg->aid) { - case BTA_DM_INQ_RES_EVT: { - if (p_src_data->inq_res.p_eir) { - p_dest_data->inq_res.p_eir = (UINT8 *)(p_dest + sizeof(tBTA_DM_SEARCH)); - memcpy(p_dest_data->inq_res.p_eir, p_src_data->inq_res.p_eir, HCI_EXT_INQ_RESPONSE_LEN); + if ( p_dest_data->len > sizeof(tBTA_DM_SEARCH)){ + switch (p_dest_data->event) { + case BTA_DM_INQ_RES_EVT: { + if (p_src_data->p_data->inq_res.p_eir) { + p_dest_data->p_data->inq_res.p_eir = (UINT8 *)(p_dest_data->p_data + sizeof(tBTA_DM_SEARCH)); + memcpy(p_dest_data->p_data->inq_res.p_eir, p_src_data->p_data->inq_res.p_eir, HCI_EXT_INQ_RESPONSE_LEN); + } } - } - break; + break; - case BTA_DM_DISC_RES_EVT: { - if (p_src_data->disc_res.raw_data_size && p_src_data->disc_res.p_raw_data) { - p_dest_data->disc_res.p_raw_data = (UINT8 *)(p_dest + sizeof(tBTA_DM_SEARCH)); - memcpy(p_dest_data->disc_res.p_raw_data, - p_src_data->disc_res.p_raw_data, - p_src_data->disc_res.raw_data_size); + case BTA_DM_DISC_RES_EVT: { + if (p_src_data->p_data->disc_res.raw_data_size && p_src_data->p_data->disc_res.p_raw_data) { + p_dest_data->p_data->disc_res.p_raw_data = (UINT8 *)(p_dest_data->p_data + sizeof(tBTA_DM_SEARCH)); + memcpy(p_dest_data->p_data->disc_res.p_raw_data, + p_src_data->p_data->disc_res.p_raw_data, + p_src_data->p_data->disc_res.raw_data_size); + } + } + break; } - } - break; } } @@ -177,26 +181,30 @@ static void search_devices_copy_cb(btc_msg_t *msg, void *p_dest, void *p_src) *******************************************************************************/ static void search_service_record_copy_cb(btc_msg_t *msg, void *p_dest, void *p_src) { - tBTA_DM_SEARCH *p_dest_data = (tBTA_DM_SEARCH *) p_dest; - tBTA_DM_SEARCH *p_src_data = (tBTA_DM_SEARCH *) p_src; + tBTA_DM_SEARCH_PARAM *p_dest_data = (tBTA_DM_SEARCH_PARAM *) p_dest; + tBTA_DM_SEARCH_PARAM *p_src_data = (tBTA_DM_SEARCH_PARAM *) p_src; if (!p_src) { return; } - - switch (msg->aid) { - case BTA_DM_DISC_RES_EVT: { - if (p_src_data->disc_res.p_raw_data && p_src_data->disc_res.raw_data_size > 0) { - p_dest_data->disc_res.p_raw_data = (UINT8 *)(p_dest + sizeof(tBTA_DM_SEARCH)); - memcpy(p_dest_data->disc_res.p_raw_data, - p_src_data->disc_res.p_raw_data, - p_src_data->disc_res.raw_data_size); + p_dest_data->p_data = osi_malloc(p_dest_data->len); + memset(p_dest_data->p_data, 0x00, p_dest_data->len); + memcpy(p_dest_data->p_data, p_src_data->p_data, p_dest_data->len); + if ( p_dest_data->len > sizeof(tBTA_DM_SEARCH)){ + switch (p_dest_data->event) { + case BTA_DM_DISC_RES_EVT: { + if (p_src_data->p_data->disc_res.p_raw_data && p_src_data->p_data->disc_res.raw_data_size > 0) { + p_dest_data->p_data->disc_res.p_raw_data = (UINT8 *)(p_dest_data->p_data + sizeof(tBTA_DM_SEARCH)); + memcpy(p_dest_data->p_data->disc_res.p_raw_data, + p_src_data->p_data->disc_res.p_raw_data, + p_src_data->p_data->disc_res.raw_data_size); + } } - } - break; - - default: break; + + default: + break; + } } } @@ -255,6 +263,10 @@ static BOOLEAN check_eir_remote_name(tBTA_DM_SEARCH *p_search_data, *******************************************************************************/ static void bte_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data) { + tBTA_DM_SEARCH_PARAM search; + search.event = event; + search.p_data = p_data; + UINT16 param_len = 0; if (p_data) { @@ -282,31 +294,30 @@ static void bte_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_d p_data->inq_res.remt_name_not_required = check_eir_remote_name(p_data, NULL, NULL); } + search.len = param_len; do { btc_msg_t msg; - msg.sig = BTC_SIG_API_CALL; + msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_GAP_BT; - msg.act = BTC_GAP_BT_ACT_SEARCH_DEVICES; - msg.aid = event; + msg.act = BTC_GAP_BT_SEARCH_DEVICES_EVT; - btc_transfer_context(&msg, p_data, param_len, - (param_len > sizeof(tBTA_DM_SEARCH)) ? search_devices_copy_cb : NULL); + btc_transfer_context(&msg, &search, sizeof(tBTA_DM_SEARCH_PARAM), search_devices_copy_cb); } while (0); } -static void btc_gap_bt_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data) +static void btc_gap_bt_search_devices_evt(tBTA_DM_SEARCH_PARAM *p_data) { - switch (event) { + switch (p_data->event) { case BTA_DM_DISC_RES_EVT: { /* remote name update */ - uint32_t bdname_len = strlen((const char *)p_data->disc_res.bd_name); + uint32_t bdname_len = strlen((const char *)p_data->p_data->disc_res.bd_name); if (bdname_len) { esp_bt_gap_dev_prop_t prop[1]; - BTC_STORAGE_FILL_PROPERTY(&prop[0], ESP_BT_GAP_DEV_PROP_BDNAME, bdname_len + 1, p_data->disc_res.bd_name); + BTC_STORAGE_FILL_PROPERTY(&prop[0], ESP_BT_GAP_DEV_PROP_BDNAME, bdname_len + 1, p_data->p_data->disc_res.bd_name); esp_bt_gap_cb_param_t param; - bdcpy(param.disc_res.bda, p_data->disc_res.bd_addr); + bdcpy(param.disc_res.bda, p_data->p_data->disc_res.bd_addr); param.disc_res.num_prop = 1; param.disc_res.prop = prop; btc_gap_bt_cb_to_app(ESP_BT_GAP_DISC_RES_EVT, ¶m); @@ -315,7 +326,7 @@ static void btc_gap_bt_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEAR } case BTA_DM_INQ_RES_EVT: { /* inquiry result */ - uint32_t cod = devclass2uint (p_data->inq_res.dev_class); + uint32_t cod = devclass2uint (p_data->p_data->inq_res.dev_class); if (cod == 0) { BTC_TRACE_DEBUG("%s cod is 0, set as unclassified", __func__); @@ -330,17 +341,17 @@ static void btc_gap_bt_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEAR BTC_STORAGE_FILL_PROPERTY(&prop[0], ESP_BT_GAP_DEV_PROP_COD, sizeof(cod), &cod); num_prop++; - BTC_STORAGE_FILL_PROPERTY(&prop[1], ESP_BT_GAP_DEV_PROP_RSSI, 1, &(p_data->inq_res.rssi)); + BTC_STORAGE_FILL_PROPERTY(&prop[1], ESP_BT_GAP_DEV_PROP_RSSI, 1, &(p_data->p_data->inq_res.rssi)); num_prop++; - if (p_data->inq_res.p_eir) { - BTC_STORAGE_FILL_PROPERTY(&prop[2], ESP_BT_GAP_DEV_PROP_EIR, HCI_EXT_INQ_RESPONSE_LEN, p_data->inq_res.p_eir); + if (p_data->p_data->inq_res.p_eir) { + BTC_STORAGE_FILL_PROPERTY(&prop[2], ESP_BT_GAP_DEV_PROP_EIR, HCI_EXT_INQ_RESPONSE_LEN, p_data->p_data->inq_res.p_eir); num_prop++; } /* Callback to notify upper layer of device */ esp_bt_gap_cb_param_t param; - bdcpy(param.disc_res.bda, p_data->inq_res.bd_addr); + bdcpy(param.disc_res.bda, p_data->p_data->inq_res.bd_addr); param.disc_res.num_prop = num_prop; param.disc_res.prop = prop; btc_gap_bt_cb_to_app(ESP_BT_GAP_DISC_RES_EVT, ¶m); @@ -382,18 +393,18 @@ static void btc_gap_bt_search_devices_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEAR ** Returns void ** *******************************************************************************/ -static void btc_gap_bt_search_service_record(UINT16 event, char *p_param) +static void btc_gap_bt_search_service_record(char *p_param) { - tBTA_DM_SEARCH *p_data = (tBTA_DM_SEARCH *)p_param; + tBTA_DM_SEARCH_PARAM *p_data = (tBTA_DM_SEARCH_PARAM *)p_param; - switch (event) { + switch (p_data->event) { case BTA_DM_DISC_RES_EVT: { esp_bt_gap_cb_param_t param; - memcpy(param.rmt_srvcs.bda, p_data->disc_res.bd_addr, BD_ADDR_LEN); - if (p_data->disc_res.p_raw_data && p_data->disc_res.raw_data_size > 0) { + memcpy(param.rmt_srvcs.bda, p_data->p_data->disc_res.bd_addr, BD_ADDR_LEN); + if (p_data->p_data->disc_res.p_raw_data && p_data->p_data->disc_res.raw_data_size > 0) { param.rmt_srvc_rec.stat = ESP_BT_STATUS_SUCCESS; - // param.rmt_srvc_rec.raw_data_size = p_data->disc_res.raw_data_size; - // param.rmt_srvc_rec.raw_data = p_data->disc_res.p_raw_data; + // param.rmt_srvc_rec.raw_data_size = p_data->p_data->disc_res.raw_data_size; + // param.rmt_srvc_rec.raw_data = p_data->p_data->disc_res.p_raw_data; } else { param.rmt_srvc_rec.stat = ESP_BT_STATUS_FAIL; // param.rmt_srvc_rec.raw_data_size = 0; @@ -421,6 +432,9 @@ static void btc_gap_bt_search_service_record(UINT16 event, char *p_param) *******************************************************************************/ static void bte_dm_remote_service_record_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data) { + tBTA_DM_SEARCH_PARAM search; + search.event = event; + search.p_data = p_data; UINT16 param_len = 0; if (p_data) { @@ -432,17 +446,13 @@ static void bte_dm_remote_service_record_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_S param_len += p_data->disc_res.raw_data_size; } } - + search.len = param_len; do { btc_msg_t msg; - msg.sig = BTC_SIG_API_CALL; + msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_GAP_BT; - msg.act = BTC_GAP_BT_ACT_SEARCH_SERVICE_RECORD; - msg.aid = event; - - btc_transfer_context(&msg, p_data, param_len, - (param_len > sizeof(tBTA_DM_SEARCH)) ? search_service_record_copy_cb : NULL); - + msg.act = BTC_GAP_BT_SEARCH_SERVICE_RECORD_EVT; + btc_transfer_context(&msg, &search, sizeof(tBTA_DM_SEARCH_PARAM), search_service_record_copy_cb); } while (0); } @@ -456,27 +466,27 @@ static void bte_dm_remote_service_record_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_S ** Returns void ** *******************************************************************************/ -static void btc_gap_bt_search_services(UINT16 event, char *p_param) +static void btc_gap_bt_search_services(char *p_param) { - tBTA_DM_SEARCH *p_data = (tBTA_DM_SEARCH *)p_param; + tBTA_DM_SEARCH_PARAM *p_data = (tBTA_DM_SEARCH_PARAM *)p_param; - switch (event) { + switch (p_data->event) { case BTA_DM_DISC_RES_EVT: { esp_bt_gap_cb_param_t param; esp_bt_uuid_t *uuid_list = NULL; - memcpy(param.rmt_srvcs.bda, p_data->disc_res.bd_addr, BD_ADDR_LEN); + memcpy(param.rmt_srvcs.bda, p_data->p_data->disc_res.bd_addr, BD_ADDR_LEN); param.rmt_srvcs.stat = ESP_BT_STATUS_FAIL; - if (p_data->disc_res.result == BTA_SUCCESS) { - uuid_list = malloc(sizeof(esp_bt_uuid_t) * p_data->disc_res.num_uuids); + if (p_data->p_data->disc_res.result == BTA_SUCCESS) { + uuid_list = malloc(sizeof(esp_bt_uuid_t) * p_data->p_data->disc_res.num_uuids); if (uuid_list) { param.rmt_srvcs.stat = ESP_BT_STATUS_SUCCESS; - param.rmt_srvcs.num_uuids = p_data->disc_res.num_uuids; + param.rmt_srvcs.num_uuids = p_data->p_data->disc_res.num_uuids; param.rmt_srvcs.uuid_list = uuid_list; // copy UUID list - uint8_t *i_uu = (uint8_t *)p_data->disc_res.p_uuid_list; + uint8_t *i_uu = (uint8_t *)p_data->p_data->disc_res.p_uuid_list; esp_bt_uuid_t *o_uu = uuid_list; - for (int i = 0; i < p_data->disc_res.num_uuids; i++, i_uu += ESP_UUID_LEN_128, o_uu++) { + for (int i = 0; i < p_data->p_data->disc_res.num_uuids; i++, i_uu += ESP_UUID_LEN_128, o_uu++) { uuid128_be_to_esp_uuid(o_uu, i_uu); } } @@ -513,6 +523,10 @@ static void btc_gap_bt_search_services(UINT16 event, char *p_param) *******************************************************************************/ static void bte_dm_search_services_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data) { + tBTA_DM_SEARCH_PARAM search; + search.event = event; + search.p_data = p_data; + UINT16 param_len = 0; if (p_data) { param_len += sizeof(tBTA_DM_SEARCH); @@ -525,46 +539,46 @@ static void bte_dm_search_services_evt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH } } break; } - - /* TODO: The only other member that needs a deep copy is the p_raw_data. But not sure - * if raw_data is needed. */ + search.len = param_len; do { btc_msg_t msg; - msg.sig = BTC_SIG_API_CALL; + msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_GAP_BT; - msg.act = BTC_GAP_BT_ACT_SEARCH_SERVICES; - msg.aid = event; - - btc_transfer_context(&msg, p_data, param_len, - (param_len > sizeof(tBTA_DM_SEARCH)) ? search_services_copy_cb : NULL); + msg.act = BTC_GAP_BT_SEARCH_SERVICES_EVT; + btc_transfer_context(&msg, &search, sizeof(tBTA_DM_SEARCH_PARAM), search_services_copy_cb); } while (0); } static void search_services_copy_cb(btc_msg_t *msg, void *p_dest, void *p_src) { - tBTA_DM_SEARCH *p_dest_data = (tBTA_DM_SEARCH *) p_dest; - tBTA_DM_SEARCH *p_src_data = (tBTA_DM_SEARCH *) p_src; + tBTA_DM_SEARCH_PARAM *p_dest_data = (tBTA_DM_SEARCH_PARAM *) p_dest; + tBTA_DM_SEARCH_PARAM *p_src_data = (tBTA_DM_SEARCH_PARAM *) p_src; if (!p_src) { return; } + p_dest_data->p_data = osi_malloc(p_dest_data->len); + memset(p_dest_data->p_data, 0x00, p_dest_data->len); + memcpy(p_dest_data->p_data, p_src_data->p_data, p_dest_data->len); - switch (msg->aid) { - case BTA_DM_DISC_RES_EVT: { - if (p_src_data->disc_res.result == BTA_SUCCESS) { - if (p_src_data->disc_res.num_uuids > 0) { - p_dest_data->disc_res.p_uuid_list = (UINT8 *)(p_dest + sizeof(tBTA_DM_SEARCH)); - memcpy(p_dest_data->disc_res.p_uuid_list, p_src_data->disc_res.p_uuid_list, - p_src_data->disc_res.num_uuids * MAX_UUID_SIZE); - osi_free(p_src_data->disc_res.p_uuid_list); - p_src_data->disc_res.p_uuid_list = NULL; - } - if (p_src_data->disc_res.p_raw_data != NULL) { - osi_free(p_src_data->disc_res.p_raw_data); - p_src_data->disc_res.p_raw_data = NULL; + if ( p_dest_data->len > sizeof(tBTA_DM_SEARCH)){ + switch (p_dest_data->event) { + case BTA_DM_DISC_RES_EVT: { + if (p_src_data->p_data->disc_res.result == BTA_SUCCESS) { + if (p_src_data->p_data->disc_res.num_uuids > 0) { + p_dest_data->p_data->disc_res.p_uuid_list = (UINT8 *)(p_dest_data->p_data + sizeof(tBTA_DM_SEARCH)); + memcpy(p_dest_data->p_data->disc_res.p_uuid_list, p_src_data->p_data->disc_res.p_uuid_list, + p_src_data->p_data->disc_res.num_uuids * MAX_UUID_SIZE); + osi_free(p_src_data->p_data->disc_res.p_uuid_list); + p_src_data->p_data->disc_res.p_uuid_list = NULL; + } + if (p_src_data->p_data->disc_res.p_raw_data != NULL) { + osi_free(p_src_data->p_data->disc_res.p_raw_data); + p_src_data->p_data->disc_res.p_raw_data = NULL; + } } + } break; } - } break; } } @@ -603,7 +617,7 @@ static void btc_gap_bt_read_rssi_delta_cmpl_callback(void *p_data) btc_msg_t msg; msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_GAP_BT; - msg.act = ESP_BT_GAP_READ_RSSI_DELTA_EVT; + msg.act = BTC_GAP_BT_READ_RSSI_DELTA_EVT; memcpy(param.read_rssi_delta.bda, result->rem_bda, sizeof(BD_ADDR)); param.read_rssi_delta.stat = btc_btm_status_to_esp_status(result->status); param.read_rssi_delta.rssi_delta = result->rssi; @@ -612,7 +626,7 @@ static void btc_gap_bt_read_rssi_delta_cmpl_callback(void *p_data) sizeof(esp_bt_gap_cb_param_t), NULL); if (ret != BT_STATUS_SUCCESS) { - LOG_ERROR("%s btc_transfer_context failed\n", __func__); + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); } } @@ -645,10 +659,6 @@ void btc_gap_bt_call_handler(btc_msg_t *msg) btc_gap_bt_start_discovery(msg->arg); break; } - case BTC_GAP_BT_ACT_SEARCH_DEVICES: { - btc_gap_bt_search_devices_evt(msg->aid, msg->arg); - break; - } case BTC_GAP_BT_ACT_CANCEL_DISCOVERY: { btc_gap_bt_cancel_discovery(); break; @@ -657,18 +667,10 @@ void btc_gap_bt_call_handler(btc_msg_t *msg) btc_gap_bt_get_remote_services(msg->arg); break; } - case BTC_GAP_BT_ACT_SEARCH_SERVICES: { - btc_gap_bt_search_services(msg->aid, msg->arg); - break; - } case BTC_GAP_BT_ACT_GET_REMOTE_SERVICE_RECORD: { btc_gap_bt_get_remote_service_record(msg->arg); break; } - case BTC_GAP_BT_ACT_SEARCH_SERVICE_RECORD: { - btc_gap_bt_search_service_record(msg->aid, msg->arg); - break; - } case BTC_GAP_BT_ACT_SET_COD: { btc_gap_bt_set_cod(msg->arg); break; @@ -704,15 +706,50 @@ void btc_gap_bt_busy_level_updated(uint8_t bl_flags) } } +void btc_gap_bt_cb_deep_free(btc_msg_t *msg) +{ + switch (msg->act) { + case BTC_GAP_BT_SEARCH_DEVICES_EVT: + case BTC_GAP_BT_SEARCH_SERVICES_EVT: + case BTC_GAP_BT_SEARCH_SERVICE_RECORD_EVT: + osi_free(((tBTA_DM_SEARCH_PARAM *) (msg->arg)) ->p_data); + break; + case BTC_GAP_BT_READ_RSSI_DELTA_EVT: + case BTC_GAP_BT_AUTH_CMPL_EVT: + break; + default: + BTC_TRACE_ERROR("%s: Unhandled event (%d)!\n", __FUNCTION__, msg->act); + break; + } +} + void btc_gap_bt_cb_handler(btc_msg_t *msg) { - esp_bt_gap_cb_param_t *param = (esp_bt_gap_cb_param_t *)msg->arg; - - if (msg->act < ESP_BT_GAP_EVT_MAX) { - btc_gap_bt_cb_to_app(msg->act, param); - } else { - LOG_ERROR("%s, unknow msg->act = %d", __func__, msg->act); + switch (msg->act) { + case BTC_GAP_BT_SEARCH_DEVICES_EVT: { + btc_gap_bt_search_devices_evt(msg->arg); + break; } - + case BTC_GAP_BT_SEARCH_SERVICES_EVT: { + btc_gap_bt_search_services(msg->arg); + break; + } + case BTC_GAP_BT_SEARCH_SERVICE_RECORD_EVT: { + btc_gap_bt_search_service_record(msg->arg); + break; + } + case BTC_GAP_BT_READ_RSSI_DELTA_EVT:{ + btc_gap_bt_cb_to_app(ESP_BT_GAP_READ_RSSI_DELTA_EVT, (esp_bt_gap_cb_param_t *)msg->arg); + break; + } + case BTC_GAP_BT_AUTH_CMPL_EVT:{ + btc_gap_bt_cb_to_app(ESP_BT_GAP_AUTH_CMPL_EVT, (esp_bt_gap_cb_param_t *)msg->arg); + break; + } + default: + BTC_TRACE_ERROR("%s: Unhandled event (%d)!\n", __FUNCTION__, msg->act); + break; + } + btc_gap_bt_cb_deep_free(msg); } #endif /* (BTC_GAP_BT_INCLUDED == TRUE) */ diff --git a/components/bt/bluedroid/btc/profile/std/include/btc_gap_bt.h b/components/bt/bluedroid/btc/profile/std/include/btc_gap_bt.h index d33ab9182e..41674956cb 100644 --- a/components/bt/bluedroid/btc/profile/std/include/btc_gap_bt.h +++ b/components/bt/bluedroid/btc/profile/std/include/btc_gap_bt.h @@ -22,17 +22,20 @@ #include "bta/utl.h" #if (BTC_GAP_BT_INCLUDED == TRUE) +typedef enum { + BTC_GAP_BT_SEARCH_DEVICES_EVT = 0, + BTC_GAP_BT_SEARCH_SERVICES_EVT, + BTC_GAP_BT_SEARCH_SERVICE_RECORD_EVT, + BTC_GAP_BT_READ_RSSI_DELTA_EVT, + BTC_GAP_BT_AUTH_CMPL_EVT, +}btc_gap_bt_evt_t; typedef enum { BTC_GAP_BT_ACT_SET_SCAN_MODE = 0, - BTC_GAP_BT_ACT_REG_CB, BTC_GAP_BT_ACT_START_DISCOVERY, - BTC_GAP_BT_ACT_SEARCH_DEVICES, BTC_GAP_BT_ACT_CANCEL_DISCOVERY, BTC_GAP_BT_ACT_GET_REMOTE_SERVICES, - BTC_GAP_BT_ACT_SEARCH_SERVICES, BTC_GAP_BT_ACT_GET_REMOTE_SERVICE_RECORD, - BTC_GAP_BT_ACT_SEARCH_SERVICE_RECORD, BTC_GAP_BT_ACT_SET_COD, BTC_GAP_BT_ACT_READ_RSSI_DELTA, BTC_GAP_BT_ACT_REMOVE_BOND_DEVICE, @@ -52,10 +55,10 @@ typedef union { uint8_t num_rsps; } start_disc; - // BTC_BT_GAP_ACT_GET_REMOTE_SERVICES + // BTC_GAP_BT_ACT_GET_REMOTE_SERVICES bt_bdaddr_t bda; - // BTC_BT_GAP_ACT_GET_REMTOE_SERVICE_RECORD + // BTC_GAP_BT_ACT_GET_REMOTE_SERVICE_RECORD struct get_rmt_srv_rcd_args { bt_bdaddr_t bda; esp_bt_uuid_t uuid; From f6927ccde97b2a3c8831ed05b7ab9e7d2f518051 Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Tue, 15 May 2018 17:14:52 +0800 Subject: [PATCH 109/187] bootloader(flash): fix flash QIO mode configuration error. reported from github: https://github.com/espressif/esp-idf/issues/1944 1. Add SPI register setup in execute_flash_command. 2. Save and recover the SPI ctrl register in execute_flash_command. --- .../bootloader_support/src/flash_qio_mode.c | 30 +++++++------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/components/bootloader_support/src/flash_qio_mode.c b/components/bootloader_support/src/flash_qio_mode.c index e01ad6a1ed..361e3d4ada 100644 --- a/components/bootloader_support/src/flash_qio_mode.c +++ b/components/bootloader_support/src/flash_qio_mode.c @@ -116,21 +116,13 @@ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8 extern uint8_t g_rom_spiflash_dummy_len_plus[]; uint32_t bootloader_read_flash_id() { - uint32_t old_ctrl_reg = SPIFLASH.ctrl.val; - SPIFLASH.ctrl.val = SPI_WP_REG; // keep WP high while idle, otherwise leave DIO mode - SPIFLASH.user.usr_dummy = 0; - SPIFLASH.user.usr_addr = 0; - SPIFLASH.user.usr_command = 1; - SPIFLASH.user2.usr_command_bitlen = 7; uint32_t id = execute_flash_command(CMD_RDID, 0, 0, 24); - SPIFLASH.ctrl.val = old_ctrl_reg; id = ((id & 0xff) << 16) | ((id >> 16) & 0xff) | (id & 0xff00); return id; } void bootloader_enable_qio_mode(void) { - uint32_t old_ctrl_reg; uint32_t raw_flash_id; uint8_t mfg_id; uint16_t flash_id; @@ -139,10 +131,6 @@ void bootloader_enable_qio_mode(void) ESP_LOGD(TAG, "Probing for QIO mode enable..."); esp_rom_spiflash_wait_idle(&g_rom_flashchip); - /* Set up some of the SPIFLASH user/ctrl variables which don't change - while we're probing using execute_flash_command() */ - old_ctrl_reg = SPIFLASH.ctrl.val; - raw_flash_id = g_rom_flashchip.device_id; ESP_LOGD(TAG, "Raw SPI flash chip id 0x%x", raw_flash_id); @@ -162,13 +150,9 @@ void bootloader_enable_qio_mode(void) ESP_LOGI(TAG, "Enabling default flash chip QIO"); } - esp_err_t res = enable_qio_mode(chip_data[i].read_status_fn, - chip_data[i].write_status_fn, - chip_data[i].status_qio_bit); - if (res != ESP_OK) { - // Restore SPI flash CTRL setting, to keep us in DIO/DOUT mode - SPIFLASH.ctrl.val = old_ctrl_reg; - } + enable_qio_mode(chip_data[i].read_status_fn, + chip_data[i].write_status_fn, + chip_data[i].status_qio_bit); } static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn, @@ -264,6 +248,13 @@ static void write_status_16b_wrsr(unsigned new_status) static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len) { + uint32_t old_ctrl_reg = SPIFLASH.ctrl.val; + SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode + SPIFLASH.user.usr_dummy = 0; + SPIFLASH.user.usr_addr = 0; + SPIFLASH.user.usr_command = 1; + SPIFLASH.user2.usr_command_bitlen = 7; + SPIFLASH.user2.usr_command_value = command; SPIFLASH.user.usr_miso = miso_len > 0; SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0; @@ -286,5 +277,6 @@ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8 while(SPIFLASH.cmd.usr != 0) { } + SPIFLASH.ctrl.val = old_ctrl_reg; return SPIFLASH.data_buf[0]; } From 5ecf717e40ae1f067821c9779b0c7f8144b066f4 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 15 May 2018 15:49:10 +0200 Subject: [PATCH 110/187] DhcpFuzzer: dhcp client addded --- components/lwip/test_afl_host/Makefile | 27 ++- components/lwip/test_afl_host/dhcp_di.h | 32 +++ components/lwip/test_afl_host/dhcpserver_di.h | 1 + .../lwip/test_afl_host/in_client/data0.bin | Bin 0 -> 548 bytes .../lwip/test_afl_host/in_client/data1.bin | Bin 0 -> 548 bytes .../lwip/test_afl_host/in_client/data2.bin | Bin 0 -> 548 bytes .../lwip/test_afl_host/in_client/data3.bin | Bin 0 -> 548 bytes .../lwip/test_afl_host/in_client/data4.bin | Bin 0 -> 548 bytes .../lwip/test_afl_host/in_client/data5.bin | Bin 0 -> 548 bytes .../lwip/test_afl_host/in_client/data6.bin | Bin 0 -> 548 bytes .../lwip/test_afl_host/in_client/data7.bin | Bin 0 -> 548 bytes .../lwip/test_afl_host/in_client/data8.bin | Bin 0 -> 548 bytes .../test_afl_host/{in => in_server}/data0.bin | Bin .../test_afl_host/{in => in_server}/data1.bin | Bin .../test_afl_host/{in => in_server}/data2.bin | Bin .../test_afl_host/{in => in_server}/data3.bin | Bin .../test_afl_host/{in => in_server}/data4.bin | Bin .../test_afl_host/{in => in_server}/data5.bin | Bin .../test_afl_host/{in => in_server}/data6.bin | Bin components/lwip/test_afl_host/network_mock.c | 70 +++++- components/lwip/test_afl_host/no_warn_host.h | 5 + components/lwip/test_afl_host/sdkconfig.h | 220 ++++++++++++++++++ components/lwip/test_afl_host/test_client.c | 84 +++++++ .../test_afl_host/{test.c => test_server.c} | 29 ++- 24 files changed, 449 insertions(+), 19 deletions(-) create mode 100644 components/lwip/test_afl_host/dhcp_di.h create mode 100644 components/lwip/test_afl_host/in_client/data0.bin create mode 100644 components/lwip/test_afl_host/in_client/data1.bin create mode 100644 components/lwip/test_afl_host/in_client/data2.bin create mode 100644 components/lwip/test_afl_host/in_client/data3.bin create mode 100644 components/lwip/test_afl_host/in_client/data4.bin create mode 100644 components/lwip/test_afl_host/in_client/data5.bin create mode 100644 components/lwip/test_afl_host/in_client/data6.bin create mode 100644 components/lwip/test_afl_host/in_client/data7.bin create mode 100644 components/lwip/test_afl_host/in_client/data8.bin rename components/lwip/test_afl_host/{in => in_server}/data0.bin (100%) rename components/lwip/test_afl_host/{in => in_server}/data1.bin (100%) rename components/lwip/test_afl_host/{in => in_server}/data2.bin (100%) rename components/lwip/test_afl_host/{in => in_server}/data3.bin (100%) rename components/lwip/test_afl_host/{in => in_server}/data4.bin (100%) rename components/lwip/test_afl_host/{in => in_server}/data5.bin (100%) rename components/lwip/test_afl_host/{in => in_server}/data6.bin (100%) create mode 100644 components/lwip/test_afl_host/no_warn_host.h create mode 100644 components/lwip/test_afl_host/sdkconfig.h create mode 100644 components/lwip/test_afl_host/test_client.c rename components/lwip/test_afl_host/{test.c => test_server.c} (70%) diff --git a/components/lwip/test_afl_host/Makefile b/components/lwip/test_afl_host/Makefile index 1762fc6faf..a3da02e11e 100644 --- a/components/lwip/test_afl_host/Makefile +++ b/components/lwip/test_afl_host/Makefile @@ -1,28 +1,39 @@ COMPONENTS_DIR=../.. -CFLAGS=-std=gnu99 -Og -ggdb -ffunction-sections -fdata-sections -nostdlib -Wall -Werror=all -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wextra -Wno-unused-parameter -Wno-sign-compare -Wno-address -Wno-unused-variable -DESP_PLATFORM -D IDF_VER=\"v3.1-dev-961-ga2556229-dirty\" -MMD -MP -DWITH_POSIX \ --DIRAM_ATTR='' -D__ESP_ATTR_H__ +CFLAGS=-std=gnu99 -Og -ggdb -ffunction-sections -fdata-sections -nostdlib -Wall -Werror=all -Wno-int-to-pointer-cast -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wextra \ +-Wno-unused-parameter -Wno-sign-compare -Wno-address -Wno-unused-variable -DESP_PLATFORM -D IDF_VER=\"v3.1\" -MMD -MP -DWITH_POSIX INC_DIRS=-I . -I $(COMPONENTS_DIR)/lwip/include/lwip -I $(COMPONENTS_DIR)/lwip/include/lwip/port -I $(COMPONENTS_DIR)/lwip/include/lwip/posix -I $(COMPONENTS_DIR)/lwip/apps/ping -I $(COMPONENTS_DIR)/app_trace/include -I $(COMPONENTS_DIR)/app_update/include -I $(COMPONENTS_DIR)/bootloader_support/include -I $(COMPONENTS_DIR)/bt/include -I $(COMPONENTS_DIR)/coap/port/include -I $(COMPONENTS_DIR)/coap/port/include/coap -I $(COMPONENTS_DIR)/coap/libcoap/include -I \ $(COMPONENTS_DIR)/coap/libcoap/include/coap -I $(COMPONENTS_DIR)/console -I $(COMPONENTS_DIR)/cxx/include -I $(COMPONENTS_DIR)/driver/include -I $(COMPONENTS_DIR)/esp-tls -I $(COMPONENTS_DIR)/esp32/include -I $(COMPONENTS_DIR)/esp_adc_cal/include -I $(COMPONENTS_DIR)/ethernet/include -I $(COMPONENTS_DIR)/expat/port/include -I $(COMPONENTS_DIR)/expat/include/expat -I $(COMPONENTS_DIR)/fatfs/src -I $(COMPONENTS_DIR)/freertos/include -I $(COMPONENTS_DIR)/heap/include -I \ $(COMPONENTS_DIR)/idf_test/include -I $(COMPONENTS_DIR)/jsmn/include -I $(COMPONENTS_DIR)/json/cJSON -I $(COMPONENTS_DIR)/libsodium/libsodium/src/libsodium/include -I $(COMPONENTS_DIR)/libsodium/port_include -I $(COMPONENTS_DIR)/log/include -I /home/david/esp/esp-idf/examples/wifi/simple_wifi/main/include -I $(COMPONENTS_DIR)/mbedtls/port/include -I $(COMPONENTS_DIR)/mbedtls/include -I $(COMPONENTS_DIR)/mdns/include -I $(COMPONENTS_DIR)/micro-ecc/micro-ecc -I \ $(COMPONENTS_DIR)/newlib/platform_include -I $(COMPONENTS_DIR)/newlib/include -I $(COMPONENTS_DIR)/nghttp/port/include -I $(COMPONENTS_DIR)/nghttp/nghttp2/lib/includes -I $(COMPONENTS_DIR)/nvs_flash/include -I $(COMPONENTS_DIR)/openssl/include -I $(COMPONENTS_DIR)/pthread/include -I $(COMPONENTS_DIR)/sdmmc/include -I $(COMPONENTS_DIR)/smartconfig/include -I $(COMPONENTS_DIR)/soc/esp32/include -I $(COMPONENTS_DIR)/soc/include -I $(COMPONENTS_DIR)/spi_flash/include -I \ $(COMPONENTS_DIR)/spiffs/include -I $(COMPONENTS_DIR)/tcpip_adapter/include -I $(COMPONENTS_DIR)/ulp/include -I $(COMPONENTS_DIR)/vfs/include -I $(COMPONENTS_DIR)/wear_levelling/include -I $(COMPONENTS_DIR)/wpa_supplicant/include -I $(COMPONENTS_DIR)/wpa_supplicant/port/include -I $(COMPONENTS_DIR)/esp32/include -I $(COMPONENTS_DIR)/xtensa-debug-module/include TEST_NAME=test FUZZ=afl-fuzz LD=$(CC) -DHCPSERVER_C_DEPENDENCY_INJECTION=-include dhcpserver_di.h +ifeq ($(MODE),client) + DHCP_C_DEPENDENCY_INJECTION=-include dhcp_di.h + OBJECTS=dhcp.o network_mock.o test_client.o + SAMPLE_PACKETS=in_client +else + DHCP_C_DEPENDENCY_INJECTION=-include dhcpserver_di.h + OBJECTS=dhcpserver.o test_server.o network_mock.o + SAMPLE_PACKETS=in_server +endif -ifeq ($(MODE),sim) +ifeq ($(INSTR),off) CC=gcc - CFLAGS+=-DSIM + CFLAGS+=-DINSTR_IS_OFF TEST_NAME=test_sim else CC=afl-clang-fast endif CFLAGS+=$(INC_DIRS) -OBJECTS=dhcpserver.o test.o network_mock.o all: $(TEST_NAME) +dhcp.o: ../core/ipv4/dhcp.c + @echo "[CC] $<" + @$(CC) $(CFLAGS) $(DHCP_C_DEPENDENCY_INJECTION) -c $< -o $@ + dhcpserver.o: ../apps/dhcpserver.c @echo "[CC] $<" - $(CC) $(CFLAGS) $(DHCPSERVER_C_DEPENDENCY_INJECTION) -c $< -o $@ + @$(CC) $(CFLAGS) $(DHCP_C_DEPENDENCY_INJECTION) -c $< -o $@ %.o: %.c @echo "[CC] $<" @@ -33,4 +44,4 @@ $(TEST_NAME): $(OBJECTS) @$(LD) $(OBJECTS) -o $@ $(LDLIBS) fuzz: $(TEST_NAME) - @$(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME) + @$(FUZZ) -t 500 -i "$(SAMPLE_PACKETS)" -o "out" -- ./$(TEST_NAME) diff --git a/components/lwip/test_afl_host/dhcp_di.h b/components/lwip/test_afl_host/dhcp_di.h new file mode 100644 index 0000000000..5e7d9606f6 --- /dev/null +++ b/components/lwip/test_afl_host/dhcp_di.h @@ -0,0 +1,32 @@ +#include "no_warn_host.h" +#include "lwip/opt.h" +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/def.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/dns.h" +#include "netif/etharp.h" + +void __assert_func(const char *file, int line, const char *func, const char *expr) +{ + printf("Assert failed in %s, %s:%d (%s)", func, file, line, expr); + abort(); +} + +static void dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); + +void (*dhcp_test_static_dhcp_recv)(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) = NULL; + +void dhcp_test_init_di() +{ + dhcp_test_static_dhcp_recv = dhcp_recv; +} + +void dhcp_test_dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + dhcp_test_static_dhcp_recv(arg, pcb, p, addr, port); +} diff --git a/components/lwip/test_afl_host/dhcpserver_di.h b/components/lwip/test_afl_host/dhcpserver_di.h index 4e5224eea4..4b38aa5a48 100644 --- a/components/lwip/test_afl_host/dhcpserver_di.h +++ b/components/lwip/test_afl_host/dhcpserver_di.h @@ -2,6 +2,7 @@ * dhcpserver dependecy injection -- preincluded to inject interface test functions into static variables * */ +#include "no_warn_host.h" #include "lwip/pbuf.h" #include "lwip/udp.h" #include "tcpip_adapter.h" diff --git a/components/lwip/test_afl_host/in_client/data0.bin b/components/lwip/test_afl_host/in_client/data0.bin new file mode 100644 index 0000000000000000000000000000000000000000..afd14b5305cca31b377f2baa35e859cf0cb35a88 GIT binary patch literal 548 zcmZQ#WMlBHo$kiK(7*r!2Uf5!ff+!eg%qhvh(7*r!2Uf5!gBd^~<+ihnXf%vB^y%cL;AB%qCPtS3|Nk=>voJ8o pD44MTJg%qhvh(7*r!2Uf5!gBd^~<+ihnXf%vB^y%cL;AB%qRz{Zp|Nk=>voJ8o pD44MTJc4LVERAwJx_rT0FeF^$p8QV literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/in_client/data6.bin b/components/lwip/test_afl_host/in_client/data6.bin new file mode 100644 index 0000000000000000000000000000000000000000..65695216c9c01db080a91148cd3e56df0bc4c6b2 GIT binary patch literal 548 zcmZQ#WMj}gUB$q_&;Y~?3c4LVERAwJx_rT0F;yz%m4rY literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/in_client/data7.bin b/components/lwip/test_afl_host/in_client/data7.bin new file mode 100644 index 0000000000000000000000000000000000000000..6e26d917cc6777b845409aa2e5e3ff24077fe854 GIT binary patch literal 548 zcmZQ#WMf#XEt${2(7*r!2Uf7Kf*C-f +#include "no_warn_host.h" #include "lwip/opt.h" #include "lwip/def.h" #include "lwip/pbuf.h" #include "lwip/udp.h" #include "tcpip_adapter.h" #include +#include + +const ip_addr_t ip_addr_any; +const ip_addr_t ip_addr_broadcast; +struct ip_globals ip_data; +struct netif *netif_list; + u16_t lwip_htons(u16_t n) { @@ -53,11 +60,15 @@ err_t udp_sendto(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u void udp_remove(struct udp_pcb *pcb) { + if (pcb == NULL) + { + free(pcb); + } } struct udp_pcb *udp_new(void) { - return NULL; + return malloc(sizeof(struct udp_pcb)); } err_t udp_bind(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) @@ -72,3 +83,58 @@ void udp_recv(struct udp_pcb *pcb, udp_recv_fn recv, void *recv_arg) void udp_disconnect(struct udp_pcb *pcb) { } + +void dns_setserver(u8_t numdns, const ip_addr_t *dnsserver) +{ +} + +uint32_t esp_random(void) +{ + return 0; +} + +err_t etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q) +{ + return ESP_OK; +} + +u32_t lwip_ntohl(u32_t x) +{ + return 0; +} + +void netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, + const ip4_addr_t *gw) +{ +} + +void pbuf_realloc(struct pbuf *p, u16_t size) +{ + if (p != NULL) + { + uint8_t *buf = malloc(size); + free(p->payload); + p->payload = buf; + p->len = size; + p->tot_len = size; + } +} + +u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset) +{ + return 0; +} +err_t udp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) +{ + return ESP_OK; +} + +err_t udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif) +{ + return ESP_OK; +} + +err_t udp_sendto_if_src(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif, const ip_addr_t *src_ip) +{ + return ESP_OK; +} \ No newline at end of file diff --git a/components/lwip/test_afl_host/no_warn_host.h b/components/lwip/test_afl_host/no_warn_host.h new file mode 100644 index 0000000000..37ab01ebec --- /dev/null +++ b/components/lwip/test_afl_host/no_warn_host.h @@ -0,0 +1,5 @@ +// Note: these undefs and defines are used to suppress warnings and errors when compiling esp32 idf on host gcc/clang +#undef __nonnull +#define __warning__ deprecated +#define IRAM_ATTR +#define __ESP_ATTR_H__ diff --git a/components/lwip/test_afl_host/sdkconfig.h b/components/lwip/test_afl_host/sdkconfig.h new file mode 100644 index 0000000000..6f14a269a1 --- /dev/null +++ b/components/lwip/test_afl_host/sdkconfig.h @@ -0,0 +1,220 @@ +/* + * + * Automatically generated file; DO NOT EDIT. + * Espressif IoT Development Framework Configuration + * + */ +#define CONFIG_ESP32_PHY_MAX_TX_POWER 20 +#define CONFIG_TRACEMEM_RESERVE_DRAM 0x0 +#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16 +#define CONFIG_FATFS_LFN_NONE 1 +#define CONFIG_TCP_RECVMBOX_SIZE 6 +#define CONFIG_FATFS_CODEPAGE_437 1 +#define CONFIG_LWIP_ETHARP_TRUST_IP_MAC 1 +#define CONFIG_TCP_WND_DEFAULT 5744 +#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 +#define CONFIG_IPC_TASK_STACK_SIZE 1024 +#define CONFIG_FATFS_PER_FILE_CACHE 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ "40m" +#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1 +#define CONFIG_UDP_RECVMBOX_SIZE 6 +#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0 +#define CONFIG_MBEDTLS_AES_C 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1 +#define CONFIG_MBEDTLS_GCM_C 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE "2MB" +#define CONFIG_HEAP_POISONING_DISABLED 1 +#define CONFIG_SPIFFS_CACHE_WR 1 +#define CONFIG_BROWNOUT_DET_LVL_SEL_0 1 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1 +#define CONFIG_SPIFFS_CACHE 1 +#define CONFIG_INT_WDT 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1 1 +#define CONFIG_MBEDTLS_ECDSA_C 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ_40M 1 +#define CONFIG_LOG_BOOTLOADER_LEVEL_INFO 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE_2MB 1 +#define CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE 0 +#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1 +#define CONFIG_MBEDTLS_ECDH_C 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1 +#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 10 +#define CONFIG_MBEDTLS_SSL_ALPN 1 +#define CONFIG_MBEDTLS_PEM_WRITE_C 1 +#define CONFIG_LOG_DEFAULT_LEVEL_INFO 1 +#define CONFIG_BT_RESERVE_DRAM 0x0 +#define CONFIG_FATFS_FS_LOCK 0 +#define CONFIG_IP_LOST_TIMER_INTERVAL 120 +#define CONFIG_SPIFFS_META_LENGTH 4 +#define CONFIG_ESP32_PANIC_PRINT_REBOOT 1 +#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1 +#define CONFIG_CONSOLE_UART_BAUDRATE 115200 +#define CONFIG_LWIP_MAX_SOCKETS 10 +#define CONFIG_LWIP_NETIF_LOOPBACK 1 +#define CONFIG_ESP_WIFI_MODE_AP 1 +#define CONFIG_EMAC_TASK_PRIORITY 20 +#define CONFIG_TIMER_TASK_STACK_DEPTH 2048 +#define CONFIG_TCP_MSS 1436 +#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1 +#define CONFIG_FATFS_CODEPAGE 437 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_160 1 +#define CONFIG_ULP_COPROC_RESERVE_MEM 0 +#define CONFIG_LWIP_MAX_UDP_PCBS 16 +#define CONFIG_ESPTOOLPY_BAUD 115200 +#define CONFIG_INT_WDT_CHECK_CPU1 1 +#define CONFIG_ADC_CAL_LUT_ENABLE 1 +#define CONFIG_FLASHMODE_DIO 1 +#define CONFIG_ESPTOOLPY_AFTER_RESET 1 +#define CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED 1 +#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8 +#define CONFIG_TOOLPREFIX "xtensa-esp32-elf-" +#define CONFIG_MBEDTLS_ECP_C 1 +#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1024 +#define CONFIG_MBEDTLS_RC4_DISABLED 1 +#define CONFIG_CONSOLE_UART_NUM 0 +#define CONFIG_ESP32_APPTRACE_LOCK_ENABLE 1 +#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC 1 +#define CONFIG_ESPTOOLPY_BAUD_115200B 1 +#define CONFIG_TCP_OVERSIZE_MSS 1 +#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS 1 +#define CONFIG_CONSOLE_UART_DEFAULT 1 +#define CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN 16384 +#define CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS 4 +#define CONFIG_ESPTOOLPY_FLASHSIZE_DETECT 1 +#define CONFIG_TIMER_TASK_STACK_SIZE 3584 +#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE 1 +#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1 +#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60 +#define CONFIG_SPIFFS_USE_MAGIC 1 +#define CONFIG_TCPIP_TASK_STACK_SIZE 2048 +#define CONFIG_TASK_WDT 1 +#define CONFIG_MAIN_TASK_STACK_SIZE 3584 +#define CONFIG_SPIFFS_PAGE_CHECK 1 +#define CONFIG_LWIP_MAX_ACTIVE_TCP 16 +#define CONFIG_TASK_WDT_TIMEOUT_S 5 +#define CONFIG_INT_WDT_TIMEOUT_MS 300 +#define CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES 100 +#define CONFIG_ESPTOOLPY_FLASHMODE "dio" +#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1 +#define CONFIG_ESPTOOLPY_BEFORE "default_reset" +#define CONFIG_ADC2_DISABLE_DAC 1 +#define CONFIG_LOG_DEFAULT_LEVEL 3 +#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1 +#define CONFIG_TIMER_QUEUE_LENGTH 10 +#define CONFIG_MAKE_WARN_UNDEFINED_VARIABLES 1 +#define CONFIG_FATFS_TIMEOUT_MS 10000 +#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 32 +#define CONFIG_MAX_STA_CONN 4 +#define CONFIG_MBEDTLS_CCM_C 1 +#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20 +#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024 +#define CONFIG_ESP32_WIFI_TX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_NVS_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1 +#define CONFIG_LIBSODIUM_USE_MBEDTLS_SHA 1 +#define CONFIG_DMA_RX_BUF_NUM 10 +#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1 +#define CONFIG_TCP_SYNMAXRTX 6 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1 +#define CONFIG_ESP_WIFI_SSID "myssid" +#define CONFIG_PYTHON "python" +#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1 +#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 1 +#define CONFIG_ESPTOOLPY_COMPRESSED 1 +#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" +#define CONFIG_TCP_SND_BUF_DEFAULT 5744 +#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 1 +#define CONFIG_TCP_MSL 60000 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_1 1 +#define CONFIG_LWIP_SO_REUSE_RXTOALL 1 +#define CONFIG_PARTITION_TABLE_SINGLE_APP 1 +#define CONFIG_ESP32_WIFI_RX_BA_WIN 6 +#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1 +#define CONFIG_SPIFFS_USE_MTIME 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1 +#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1 +#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE 2304 +#define CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V 1 +#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000 +#define CONFIG_BROWNOUT_DET_LVL 0 +#define CONFIG_MBEDTLS_PEM_PARSE_C 1 +#define CONFIG_SPIFFS_GC_MAX_RUNS 10 +#define CONFIG_ESP_WIFI_PASSWORD "mypassword" +#define CONFIG_ESP32_APPTRACE_DEST_NONE 1 +#define CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET 0x10000 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA 1 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32 +#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1 +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 1 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 160 +#define CONFIG_MBEDTLS_HARDWARE_AES 1 +#define CONFIG_FREERTOS_HZ 100 +#define CONFIG_LOG_COLORS 1 +#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1 +#define CONFIG_STACK_CHECK_NONE 1 +#define CONFIG_ADC_CAL_EFUSE_TP_ENABLE 1 +#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1 +#define CONFIG_BROWNOUT_DET 1 +#define CONFIG_ESP32_XTAL_FREQ 40 +#define CONFIG_MONITOR_BAUD_115200B 1 +#define CONFIG_LOG_BOOTLOADER_LEVEL 3 +#define CONFIG_MBEDTLS_TLS_ENABLED 1 +#define CONFIG_LWIP_MAX_RAW_PCBS 16 +#define CONFIG_MBEDTLS_SSL_SESSION_TICKETS 1 +#define CONFIG_SPIFFS_MAX_PARTITIONS 3 +#define CONFIG_ESP_ERR_TO_NAME_LOOKUP 1 +#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1 +#define CONFIG_ESPTOOLPY_BEFORE_RESET 1 +#define CONFIG_ESPTOOLPY_BAUD_OTHER_VAL 115200 +#define CONFIG_SPIFFS_OBJ_NAME_LEN 32 +#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT 5 +#define CONFIG_PARTITION_TABLE_MD5 1 +#define CONFIG_TCPIP_RECVMBOX_SIZE 32 +#define CONFIG_TCP_MAXRTX 12 +#define CONFIG_ESPTOOLPY_AFTER "hard_reset" +#define CONFIG_LWIP_SO_REUSE 1 +#define CONFIG_ESP32_XTAL_FREQ_40 1 +#define CONFIG_DMA_TX_BUF_NUM 10 +#define CONFIG_LWIP_MAX_LISTENING_TCP 16 +#define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1 +#define CONFIG_WL_SECTOR_SIZE 4096 +#define CONFIG_ESP32_DEBUG_OCDAWARE 1 +#define CONFIG_TIMER_TASK_PRIORITY 1 +#define CONFIG_MBEDTLS_TLS_CLIENT 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1 +#define CONFIG_MONITOR_BAUD 115200 +#define CONFIG_FREERTOS_CORETIMER_0 1 +#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" +#define CONFIG_MBEDTLS_HAVE_TIME 1 +#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 +#define CONFIG_TCP_QUEUE_OOSEQ 1 +#define CONFIG_ADC_CAL_EFUSE_VREF_ENABLE 1 +#define CONFIG_MBEDTLS_TLS_SERVER 1 +#define CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT 1 +#define CONFIG_FREERTOS_ISR_STACKSIZE 1536 +#define CONFIG_OPENSSL_ASSERT_DO_NOTHING 1 +#define CONFIG_WL_SECTOR_SIZE_4096 1 +#define CONFIG_OPTIMIZATION_LEVEL_DEBUG 1 +#define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1 +#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE 32 +#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1 +#define CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED 1 +#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8 +#define CONFIG_APP_OFFSET 0x10000 +#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 +#define CONFIG_SPIFFS_PAGE_SIZE 256 +#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1 +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 1 +#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT 3072 +#define CONFIG_MONITOR_BAUD_OTHER_VAL 115200 +#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1 +#define CONFIG_ESPTOOLPY_PORT "/dev/ttyUSB0" +#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS 1 +#define CONFIG_ESP_WIFI_IS_SOFTAP 1 diff --git a/components/lwip/test_afl_host/test_client.c b/components/lwip/test_afl_host/test_client.c new file mode 100644 index 0000000000..fee5d01b19 --- /dev/null +++ b/components/lwip/test_afl_host/test_client.c @@ -0,0 +1,84 @@ +#include "no_warn_host.h" +#include "lwip/opt.h" +#include "lwip/stats.h" +#include "lwip/mem.h" +#include "lwip/udp.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "lwip/def.h" +#include "lwip/dhcp.h" +#include "lwip/autoip.h" +#include "lwip/dns.h" +#include "netif/etharp.h" +#include + +const ip_addr_t ip_addr_any; +const ip_addr_t ip_addr_broadcast; +struct ip_globals ip_data; +struct netif *netif_list; +struct netif mynetif; +ip4_addr_t server_ip; + +// +// Dependency injected test functions +void dhcp_test_dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); +void dhcp_test_init_di(); + +// +// Test starts here +// +int main(int argc, char** argv) +{ + uint8_t *buf; + struct pbuf *p; + FILE *file; + size_t len = 1460; + + dhcp_test_init_di(); + + mynetif.flags = NETIF_FLAG_UP | NETIF_FLAG_ETHARP; + mynetif.mtu = 576; + + + IP4_ADDR(&server_ip, 192,168,4,1); + dhcp_start(&mynetif); + + ip_data.current_input_netif = &mynetif; + ip_data.current_netif = &mynetif; + +#ifdef INSTR_IS_OFF + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + buf = p->payload; + memset(buf, 0, 1460); + if (argc != 2) + { + printf("Non-instrumentation mode: please supply a file name created by AFL to reproduce crash\n"); + return 1; + } + // + // Note: parameter1 is a file (mangled packet) which caused the crash + file = fopen(argv[1], "r"); + if (file) { + len = fread(buf, 1, 1460, file); + } + fclose(file); + int i; + for (i=0; i<1; i++) { +#else + while (__AFL_LOOP(1000)) { + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + buf = p->payload; + memset(buf, 0, 1460); + size_t len = read(0, buf, 1460); +#endif + p->len = len; + p->tot_len = len; + p->next = NULL; + + dhcp_test_dhcp_recv(NULL, NULL, p, &ip_addr_any, 0); + } + + + + return 0; +} diff --git a/components/lwip/test_afl_host/test.c b/components/lwip/test_afl_host/test_server.c similarity index 70% rename from components/lwip/test_afl_host/test.c rename to components/lwip/test_afl_host/test_server.c index 821e56f57f..4ed3792bf1 100644 --- a/components/lwip/test_afl_host/test.c +++ b/components/lwip/test_afl_host/test_server.c @@ -1,8 +1,9 @@ -#include +#include "no_warn_host.h" #include "lwip/pbuf.h" #include "lwip/udp.h" #include "tcpip_adapter.h" #include +#include const ip_addr_t ip_addr_any; ip4_addr_t server_ip; @@ -12,8 +13,10 @@ struct netif mynetif; void dhcp_test_handle_dhcp(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); void dhcp_test_init_di(); -// Starting the test -int main() +// +// Test starts here +// +int main(int argc, char** argv) { uint8_t *buf; struct pbuf *p; @@ -22,24 +25,32 @@ int main() dhcp_test_init_di(); - p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); - buf = p->payload; - IP4_ADDR(&server_ip, 192,168,4,1); dhcps_start(&mynetif, server_ip); -#ifdef SIM +#ifdef INSTR_IS_OFF + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + buf = p->payload; memset(buf, 0, 1460); - - file = fopen("in/data1.bin", "r"); + if (argc != 2) + { + printf("Non-instrumentation mode: please supply a file name created by AFL to reproduce crash\n"); + return 1; + } + // + // Note: parameter1 is a file (mangled packet) which caused the crash + file = fopen(argv[1], "r"); if (file) { len = fread(buf, 1, 1460, file); } fclose(file); + int i; for (i=0; i<1; i++) { #else while (__AFL_LOOP(1000)) { + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + buf = p->payload; memset(buf, 0, 1460); size_t len = read(0, buf, 1460); #endif From 4719bab2f3d28a4f42c0a966b103d23958b8474d Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 17 May 2018 10:14:26 +0800 Subject: [PATCH 111/187] freertos: Bump default idle task stack size to 1536 bytes In situations where idle task runs a lot of idle hooks or cleanup code (due to pthread local storage, etc) it can use more than 1KB of stack. (I think the trigger is if a context switch happens at the right point in the TLS cleanup). Also removes an sdkconfig.default which accidentally set all config items, including this stack size. --- components/freertos/Kconfig | 9 +- .../peripherals/i2s_adc_dac/sdkconfig.default | 333 ------------------ 2 files changed, 6 insertions(+), 336 deletions(-) delete mode 100644 examples/peripherals/i2s_adc_dac/sdkconfig.default diff --git a/components/freertos/Kconfig b/components/freertos/Kconfig index 26a2e16839..c469d679d9 100644 --- a/components/freertos/Kconfig +++ b/components/freertos/Kconfig @@ -146,11 +146,14 @@ endchoice config FREERTOS_IDLE_TASK_STACKSIZE int "Idle Task stack size" range 768 32768 - default 1024 + default 1536 help The idle task has its own stack, sized in bytes. The default size is enough for most uses. Size can be reduced - to 768 bytes if no (or simple) FreeRTOS idle hooks are used. The stack size may need to be increased above the - default if the app installs idle hooks that use a lot of stack memory. + to 768 bytes if no (or simple) FreeRTOS idle hooks are used and pthread local storage or FreeRTOS local storage + cleanup callbacks are not used. + + The stack size may need to be increased above the default if the app installs idle or thread local storage + cleanup hooks that use a lot of stack memory. config FREERTOS_ISR_STACKSIZE int "ISR stack size" diff --git a/examples/peripherals/i2s_adc_dac/sdkconfig.default b/examples/peripherals/i2s_adc_dac/sdkconfig.default deleted file mode 100644 index 3a4f180f68..0000000000 --- a/examples/peripherals/i2s_adc_dac/sdkconfig.default +++ /dev/null @@ -1,333 +0,0 @@ -# -# Automatically generated file; DO NOT EDIT. -# Espressif IoT Development Framework Configuration -# - -# -# SDK tool configuration -# -CONFIG_TOOLPREFIX="xtensa-esp32-elf-" -CONFIG_PYTHON="python" - -# -# Bootloader config -# -# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set -# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set -# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set -# CONFIG_LOG_BOOTLOADER_LEVEL_INFO is not set -CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG=y -# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set -CONFIG_LOG_BOOTLOADER_LEVEL=4 -# CONFIG_BOOTLOADER_LTO is not set - -# -# Security features -# -# CONFIG_SECURE_BOOT_ENABLED is not set -# CONFIG_FLASH_ENCRYPTION_ENABLED is not set - -# -# Serial flasher config -# -CONFIG_ESPTOOLPY_PORT="/dev/ttyUSB1" -# CONFIG_ESPTOOLPY_BAUD_115200B is not set -# CONFIG_ESPTOOLPY_BAUD_230400B is not set -CONFIG_ESPTOOLPY_BAUD_921600B=y -# CONFIG_ESPTOOLPY_BAUD_2MB is not set -# CONFIG_ESPTOOLPY_BAUD_OTHER is not set -CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 -CONFIG_ESPTOOLPY_BAUD=921600 -CONFIG_ESPTOOLPY_COMPRESSED=y -# CONFIG_FLASHMODE_QIO is not set -# CONFIG_FLASHMODE_QOUT is not set -CONFIG_FLASHMODE_DIO=y -# CONFIG_FLASHMODE_DOUT is not set -CONFIG_ESPTOOLPY_FLASHMODE="dio" -# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set -CONFIG_ESPTOOLPY_FLASHFREQ_40M=y -# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set -CONFIG_ESPTOOLPY_FLASHFREQ="40m" -# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set -# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set -CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y -# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set -# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set -CONFIG_ESPTOOLPY_FLASHSIZE="4MB" -CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y -CONFIG_ESPTOOLPY_BEFORE_RESET=y -# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set -CONFIG_ESPTOOLPY_BEFORE="default_reset" -CONFIG_ESPTOOLPY_AFTER_RESET=y -# CONFIG_ESPTOOLPY_AFTER_NORESET is not set -CONFIG_ESPTOOLPY_AFTER="hard_reset" -# CONFIG_MONITOR_BAUD_9600B is not set -# CONFIG_MONITOR_BAUD_57600B is not set -CONFIG_MONITOR_BAUD_115200B=y -# CONFIG_MONITOR_BAUD_230400B is not set -# CONFIG_MONITOR_BAUD_921600B is not set -# CONFIG_MONITOR_BAUD_2MB is not set -# CONFIG_MONITOR_BAUD_OTHER is not set -CONFIG_MONITOR_BAUD_OTHER_VAL=115200 -CONFIG_MONITOR_BAUD=115200 - -# -# Partition Table -# -# CONFIG_PARTITION_TABLE_SINGLE_APP is not set -# CONFIG_PARTITION_TABLE_TWO_OTA is not set -CONFIG_PARTITION_TABLE_CUSTOM=y -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_adc_dac_example.csv" -CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000 -CONFIG_PARTITION_TABLE_FILENAME="partitions_adc_dac_example.csv" -CONFIG_APP_OFFSET=0x10000 - -# -# Compiler options -# -CONFIG_OPTIMIZATION_LEVEL_DEBUG=y -# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set -CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y -# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set -# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set - -# -# Component config -# - -# -# Application Level Tracing -# -# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set -CONFIG_ESP32_APPTRACE_DEST_NONE=y -# CONFIG_ESP32_APPTRACE_ENABLE is not set -CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y - -# -# FreeRTOS SystemView Tracing -# -# CONFIG_AWS_IOT_SDK is not set -# CONFIG_BT_ENABLED is not set -CONFIG_BT_RESERVE_DRAM=0 - -# -# Touch pad driver -# -# CONFIG_TOUCH_PAD_FILTER_EN is not set - -# -# ESP32-specific -# -CONFIG_ESP32_DEFAULT_CPU_FREQ_80=y -# CONFIG_ESP32_DEFAULT_CPU_FREQ_160 is not set -# CONFIG_ESP32_DEFAULT_CPU_FREQ_240 is not set -CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=80 -CONFIG_MEMMAP_SMP=y -# CONFIG_MEMMAP_TRACEMEM is not set -# CONFIG_MEMMAP_TRACEMEM_TWOBANKS is not set -# CONFIG_ESP32_TRAX is not set -CONFIG_TRACEMEM_RESERVE_DRAM=0x0 -# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set -# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set -CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y -# CONFIG_ESP32_ENABLE_COREDUMP is not set -# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set -CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y -CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 -CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 -CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2048 -CONFIG_MAIN_TASK_STACK_SIZE=4096 -CONFIG_IPC_TASK_STACK_SIZE=1024 -CONFIG_NEWLIB_STDOUT_ADDCR=y -# CONFIG_NEWLIB_NANO_FORMAT is not set -CONFIG_CONSOLE_UART_DEFAULT=y -# CONFIG_CONSOLE_UART_CUSTOM is not set -# CONFIG_CONSOLE_UART_NONE is not set -CONFIG_CONSOLE_UART_NUM=0 -CONFIG_CONSOLE_UART_BAUDRATE=115200 -# CONFIG_ULP_COPROC_ENABLED is not set -CONFIG_ULP_COPROC_RESERVE_MEM=0 -# CONFIG_ESP32_PANIC_PRINT_HALT is not set -CONFIG_ESP32_PANIC_PRINT_REBOOT=y -# CONFIG_ESP32_PANIC_SILENT_REBOOT is not set -# CONFIG_ESP32_PANIC_GDBSTUB is not set -CONFIG_ESP32_DEBUG_OCDAWARE=y -# CONFIG_INT_WDT is not set -# CONFIG_TASK_WDT is not set -CONFIG_BROWNOUT_DET=y -CONFIG_BROWNOUT_DET_LVL_SEL_0=y -# CONFIG_BROWNOUT_DET_LVL_SEL_1 is not set -# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set -# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set -# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set -# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set -# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set -# CONFIG_BROWNOUT_DET_LVL_SEL_7 is not set -CONFIG_BROWNOUT_DET_LVL=0 -# CONFIG_ESP32_TIME_SYSCALL_USE_RTC is not set -CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y -# CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 is not set -# CONFIG_ESP32_TIME_SYSCALL_USE_NONE is not set -CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y -# CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL is not set -CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 -CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=0 -# CONFIG_ESP32_XTAL_FREQ_40 is not set -# CONFIG_ESP32_XTAL_FREQ_26 is not set -CONFIG_ESP32_XTAL_FREQ_AUTO=y -CONFIG_ESP32_XTAL_FREQ=0 -CONFIG_WIFI_ENABLED=y -CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 -CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 -# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y -CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 -CONFIG_ESP32_WIFI_AMPDU_ENABLED=y -CONFIG_ESP32_WIFI_TX_BA_WIN=6 -CONFIG_ESP32_WIFI_RX_BA_WIN=6 -CONFIG_ESP32_WIFI_NVS_ENABLED=y -CONFIG_PHY_ENABLED=y - -# -# PHY -# -CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y -# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set -CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 -CONFIG_ESP32_PHY_MAX_TX_POWER=20 -# CONFIG_ETHERNET is not set - -# -# FAT Filesystem support -# -CONFIG_FATFS_CODEPAGE_ASCII=y -# CONFIG_FATFS_CODEPAGE_437 is not set -# CONFIG_FATFS_CODEPAGE_720 is not set -# CONFIG_FATFS_CODEPAGE_737 is not set -# CONFIG_FATFS_CODEPAGE_771 is not set -# CONFIG_FATFS_CODEPAGE_775 is not set -# CONFIG_FATFS_CODEPAGE_850 is not set -# CONFIG_FATFS_CODEPAGE_852 is not set -# CONFIG_FATFS_CODEPAGE_855 is not set -# CONFIG_FATFS_CODEPAGE_857 is not set -# CONFIG_FATFS_CODEPAGE_860 is not set -# CONFIG_FATFS_CODEPAGE_861 is not set -# CONFIG_FATFS_CODEPAGE_862 is not set -# CONFIG_FATFS_CODEPAGE_863 is not set -# CONFIG_FATFS_CODEPAGE_864 is not set -# CONFIG_FATFS_CODEPAGE_865 is not set -# CONFIG_FATFS_CODEPAGE_866 is not set -# CONFIG_FATFS_CODEPAGE_869 is not set -# CONFIG_FATFS_CODEPAGE_932 is not set -# CONFIG_FATFS_CODEPAGE_936 is not set -# CONFIG_FATFS_CODEPAGE_949 is not set -# CONFIG_FATFS_CODEPAGE_950 is not set -CONFIG_FATFS_CODEPAGE=1 -CONFIG_FATFS_MAX_LFN=255 - -# -# FreeRTOS -# -CONFIG_FREERTOS_UNICORE=y -CONFIG_FREERTOS_CORETIMER_0=y -# CONFIG_FREERTOS_CORETIMER_1 is not set -CONFIG_FREERTOS_HZ=100 -CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y -CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE=y -# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set -# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY is not set -# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set -CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 -CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y -# CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE is not set -# CONFIG_FREERTOS_ASSERT_DISABLE is not set -CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG=y -# CONFIG_ENABLE_MEMORY_DEBUG is not set -CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024 -CONFIG_FREERTOS_ISR_STACKSIZE=1536 -# CONFIG_FREERTOS_LEGACY_HOOKS is not set -CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 -# CONFIG_SUPPORT_STATIC_ALLOCATION is not set -CONFIG_TIMER_TASK_PRIORITY=1 -CONFIG_TIMER_TASK_STACK_DEPTH=2048 -CONFIG_TIMER_QUEUE_LENGTH=10 -# CONFIG_FREERTOS_DEBUG_INTERNALS is not set - -# -# Log output -# -# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set -# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set -# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set -# CONFIG_LOG_DEFAULT_LEVEL_INFO is not set -CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y -# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set -CONFIG_LOG_DEFAULT_LEVEL=4 -CONFIG_LOG_COLORS=y - -# -# LWIP -# -# CONFIG_L2_TO_L3_COPY is not set -CONFIG_LWIP_MAX_SOCKETS=10 -CONFIG_LWIP_THREAD_LOCAL_STORAGE_INDEX=0 -# CONFIG_LWIP_SO_REUSE is not set -# CONFIG_LWIP_SO_RCVBUF is not set -CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 -# CONFIG_LWIP_IP_FRAG is not set -# CONFIG_LWIP_IP_REASSEMBLY is not set - -# -# TCP -# -CONFIG_TCP_MAXRTX=12 -CONFIG_TCP_SYNMAXRTX=6 -CONFIG_TCP_MSS=1436 -CONFIG_TCP_SND_BUF_DEFAULT=5744 -CONFIG_TCP_WND_DEFAULT=5744 -CONFIG_TCP_RECVMBOX_SIZE=6 -CONFIG_TCP_QUEUE_OOSEQ=y -CONFIG_TCP_OVERSIZE_MSS=y -# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set -# CONFIG_TCP_OVERSIZE_DISABLE is not set - -# -# UDP -# -CONFIG_UDP_RECVMBOX_SIZE=6 -CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y -CONFIG_TCPIP_TASK_STACK_SIZE=2560 -# CONFIG_PPP_SUPPORT is not set - -# -# ICMP -# -# CONFIG_LWIP_MULTICAST_PING is not set -# CONFIG_LWIP_BROADCAST_PING is not set - -# -# mbedTLS -# -CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 -# CONFIG_MBEDTLS_DEBUG is not set -CONFIG_MBEDTLS_HARDWARE_AES=y -CONFIG_MBEDTLS_HARDWARE_MPI=y -CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y -CONFIG_MBEDTLS_HARDWARE_SHA=y -CONFIG_MBEDTLS_HAVE_TIME=y -# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set - -# -# OpenSSL -# -# CONFIG_OPENSSL_DEBUG is not set -CONFIG_OPENSSL_ASSERT_DO_NOTHING=y -# CONFIG_OPENSSL_ASSERT_EXIT is not set - -# -# SPI Flash driver -# -# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set -CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y From 9deb58859c5b65bef8d9db85bbe9219143ef0407 Mon Sep 17 00:00:00 2001 From: Zhang Zhao Xiang Date: Wed, 11 Apr 2018 19:37:31 +0800 Subject: [PATCH 112/187] fix i2s mix result and error code --- components/driver/i2s.c | 190 ++++++++++-------- components/driver/include/driver/i2s.h | 133 +++++++----- examples/bluetooth/a2dp_sink/main/bt_app_av.c | 3 +- .../peripherals/i2s/main/i2s_example_main.c | 23 ++- .../peripherals/i2s_adc_dac/main/app_main.c | 7 +- 5 files changed, 199 insertions(+), 157 deletions(-) mode change 100755 => 100644 components/driver/i2s.c mode change 100755 => 100644 components/driver/include/driver/i2s.h mode change 100755 => 100644 examples/peripherals/i2s_adc_dac/main/app_main.c diff --git a/components/driver/i2s.c b/components/driver/i2s.c old mode 100755 new mode 100644 index b3d296af8e..65b83c9e77 --- a/components/driver/i2s.c +++ b/components/driver/i2s.c @@ -226,7 +226,7 @@ static float i2s_apll_get_fi2s(int bits_per_sample, int sdm0, int sdm1, int sdm2 * @param[out] sdm2 The sdm 2 * @param[out] odir The odir * - * @return ESP_FAIL or ESP_OK + * @return ESP_ERR_INVALID_ARG or ESP_OK */ static esp_err_t i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, int *sdm1, int *sdm2, int *odir) @@ -303,7 +303,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b if (p_i2s_obj[i2s_num] == NULL) { ESP_LOGE(I2S_TAG, "Not initialized yet"); - return ESP_FAIL; + return ESP_ERR_INVALID_ARG; } p_i2s_obj[i2s_num]->sample_rate = rate; double clkmdiv = (double)I2S_BASE_CLK / (rate * factor); @@ -541,21 +541,26 @@ static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma) int bux_idx; if (p_i2s_obj[i2s_num] == NULL) { ESP_LOGE(I2S_TAG, "Not initialized yet"); - return ESP_FAIL; + return ESP_ERR_INVALID_ARG; } if (dma == NULL) { - return ESP_FAIL; + ESP_LOGE(I2S_TAG, "dma is NULL"); + return ESP_ERR_INVALID_ARG; } for (bux_idx = 0; bux_idx < p_i2s_obj[i2s_num]->dma_buf_count; bux_idx++) { - if (dma->desc && dma->desc[bux_idx]) + if (dma->desc && dma->desc[bux_idx]) { free(dma->desc[bux_idx]); - if (dma->buf && dma->buf[bux_idx]) + } + if (dma->buf && dma->buf[bux_idx]) { free(dma->buf[bux_idx]); + } } - if (dma->buf) + if (dma->buf) { free(dma->buf); - if (dma->desc) + } + if (dma->desc) { free(dma->desc); + } vQueueDelete(dma->queue); vSemaphoreDelete(dma->mux); free(dma); @@ -999,10 +1004,11 @@ esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num) } } if (p_i2s_obj[i2s_num]->tx && p_i2s_obj[i2s_num]->tx->buf != NULL && p_i2s_obj[i2s_num]->tx->buf_size != 0) { - int bytes_left = (p_i2s_obj[i2s_num]->tx->buf_size - p_i2s_obj[i2s_num]->tx->rw_pos) % 4; + int bytes_left = 0; + bytes_left = (p_i2s_obj[i2s_num]->tx->buf_size - p_i2s_obj[i2s_num]->tx->rw_pos) % 4; if (bytes_left) { - int zero_bytes = 0; - i2s_write_bytes(i2s_num, (const char *)&zero_bytes, bytes_left, portMAX_DELAY); + size_t zero_bytes = 0, bytes_written; + i2s_write(i2s_num, (void *)&zero_bytes, bytes_left, &bytes_written, portMAX_DELAY); } for (int i = 0; i < p_i2s_obj[i2s_num]->dma_buf_count; i++) { memset(p_i2s_obj[i2s_num]->tx->buf[i], 0, p_i2s_obj[i2s_num]->tx->buf_size); @@ -1113,14 +1119,28 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num) return ESP_OK; } -int i2s_write_bytes(i2s_port_t i2s_num, const char *src, size_t size, TickType_t ticks_to_wait) +int i2s_write_bytes(i2s_port_t i2s_num, const void *src, size_t size, TickType_t ticks_to_wait) { - char *data_ptr; - int bytes_can_write, bytes_writen = 0; - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL); - I2S_CHECK((size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_FAIL); - I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_FAIL); + size_t bytes_written = 0; + int res = 0; + res = i2s_write(i2s_num, src, size, &bytes_written, ticks_to_wait); + if (res != ESP_OK) { + return ESP_FAIL; + } else { + return bytes_written; + } +} + +esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *bytes_written, TickType_t ticks_to_wait) +{ + char *data_ptr, *src_byte; + int bytes_can_write; + *bytes_written = 0; + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK((size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG); + I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_ERR_INVALID_ARG); xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); + src_byte = (char *)src; while (size > 0) { if (p_i2s_obj[i2s_num]->tx->rw_pos == p_i2s_obj[i2s_num]->tx->buf_size || p_i2s_obj[i2s_num]->tx->curr_ptr == NULL) { if (xQueueReceive(p_i2s_obj[i2s_num]->tx->queue, &p_i2s_obj[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) { @@ -1135,14 +1155,14 @@ int i2s_write_bytes(i2s_port_t i2s_num, const char *src, size_t size, TickType_t if (bytes_can_write > size) { bytes_can_write = size; } - memcpy(data_ptr, src, bytes_can_write); + memcpy(data_ptr, src_byte, bytes_can_write); size -= bytes_can_write; - src += bytes_can_write; + src_byte += bytes_can_write; p_i2s_obj[i2s_num]->tx->rw_pos += bytes_can_write; - bytes_writen += bytes_can_write; + (*bytes_written) += bytes_can_write; } xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux); - return bytes_writen; + return ESP_OK; } esp_err_t i2s_adc_enable(i2s_port_t i2s_num) @@ -1166,33 +1186,37 @@ esp_err_t i2s_adc_disable(i2s_port_t i2s_num) return ESP_OK; } -int i2s_write_expand(i2s_port_t i2s_num, const char *src, int size, int src_bits, int aim_bits, TickType_t ticks_to_wait) +esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, size_t src_bits, size_t aim_bits, size_t *bytes_written, TickType_t ticks_to_wait) { char *data_ptr; - int bytes_can_write, bytes_writen = 0, tail; - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL); - I2S_CHECK((size > 0), "size must greater than zero", ESP_FAIL); - I2S_CHECK((aim_bits * size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_FAIL); - I2S_CHECK((aim_bits >= src_bits), "aim_bits musn't less than src_bits", ESP_FAIL); - I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_FAIL); + int bytes_can_write, tail; + int src_bytes, aim_bytes, zero_bytes; + *bytes_written = 0; + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK((size > 0), "size must greater than zero", ESP_ERR_INVALID_ARG); + I2S_CHECK((aim_bits * size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG); + I2S_CHECK((aim_bits >= src_bits), "aim_bits musn't less than src_bits", ESP_ERR_INVALID_ARG); + I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_ERR_INVALID_ARG); if (src_bits < I2S_BITS_PER_SAMPLE_8BIT || aim_bits < I2S_BITS_PER_SAMPLE_8BIT) { ESP_LOGE(I2S_TAG,"bits musn't be less than 8, src_bits %d aim_bits %d", src_bits, aim_bits); - return ESP_FAIL; + return ESP_ERR_INVALID_ARG; } if (src_bits > I2S_BITS_PER_SAMPLE_32BIT || aim_bits > I2S_BITS_PER_SAMPLE_32BIT) { ESP_LOGE(I2S_TAG,"bits musn't be greater than 32, src_bits %d aim_bits %d", src_bits, aim_bits); - return ESP_FAIL; + return ESP_ERR_INVALID_ARG; } if ((src_bits == I2S_BITS_PER_SAMPLE_16BIT || src_bits == I2S_BITS_PER_SAMPLE_32BIT) && (size % 2 != 0)) { ESP_LOGE(I2S_TAG,"size must be a even number while src_bits is even, src_bits %d size %d", src_bits, size); - return ESP_FAIL; + return ESP_ERR_INVALID_ARG; } if (src_bits == I2S_BITS_PER_SAMPLE_24BIT && (size % 3 != 0)) { ESP_LOGE(I2S_TAG,"size must be a multiple of 3 while src_bits is 24, size %d", size); - return ESP_FAIL; + return ESP_ERR_INVALID_ARG; } - int src_bytes = src_bits / 8, aim_bytes = aim_bits / 8; - int zero_bytes = aim_bytes - src_bytes; + + src_bytes = src_bits / 8; + aim_bytes = aim_bits / 8; + zero_bytes = aim_bytes - src_bytes; xSemaphoreTake(p_i2s_obj[i2s_num]->tx->mux, (portTickType)portMAX_DELAY); size = size * aim_bytes / src_bytes; ESP_LOGD(I2S_TAG,"aim_bytes %d src_bytes %d size %d", aim_bytes, src_bytes, size); @@ -1215,23 +1239,37 @@ int i2s_write_expand(i2s_port_t i2s_num, const char *src, int size, int src_bits memset(data_ptr, 0, bytes_can_write); for (int j = 0; j < bytes_can_write; j += (aim_bytes - zero_bytes)) { j += zero_bytes; - memcpy(&data_ptr[j], &src[bytes_writen], aim_bytes - zero_bytes); - bytes_writen += (aim_bytes - zero_bytes); + memcpy(&data_ptr[j], (const char *)(src + *bytes_written), aim_bytes - zero_bytes); + (*bytes_written) += (aim_bytes - zero_bytes); } size -= bytes_can_write; p_i2s_obj[i2s_num]->tx->rw_pos += bytes_can_write; } xSemaphoreGive(p_i2s_obj[i2s_num]->tx->mux); - return bytes_writen; + return ESP_OK; } -int i2s_read_bytes(i2s_port_t i2s_num, char* dest, size_t size, TickType_t ticks_to_wait) +int i2s_read_bytes(i2s_port_t i2s_num, void *dest, size_t size, TickType_t ticks_to_wait) { - char *data_ptr; - int bytes_can_read, byte_read = 0; - I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL); - I2S_CHECK((size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_FAIL); - I2S_CHECK((p_i2s_obj[i2s_num]->rx), "rx NULL", ESP_FAIL); + size_t bytes_read = 0; + int res = 0; + res = i2s_read(i2s_num, dest, size, &bytes_read, ticks_to_wait); + if (res != ESP_OK) { + return ESP_FAIL; + } else { + return bytes_read; + } +} + +esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait) +{ + char *data_ptr, *dest_byte; + int bytes_can_read; + *bytes_read = 0; + dest_byte = (char *)dest; + I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG); + I2S_CHECK((size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG); + I2S_CHECK((p_i2s_obj[i2s_num]->rx), "rx NULL", ESP_ERR_INVALID_ARG); xSemaphoreTake(p_i2s_obj[i2s_num]->rx->mux, (portTickType)portMAX_DELAY); while (size > 0) { if (p_i2s_obj[i2s_num]->rx->rw_pos == p_i2s_obj[i2s_num]->rx->buf_size || p_i2s_obj[i2s_num]->rx->curr_ptr == NULL) { @@ -1246,62 +1284,40 @@ int i2s_read_bytes(i2s_port_t i2s_num, char* dest, size_t size, TickType_t ticks if (bytes_can_read > size) { bytes_can_read = size; } - memcpy(dest, data_ptr, bytes_can_read); + memcpy(dest_byte, data_ptr, bytes_can_read); size -= bytes_can_read; - dest += bytes_can_read; + dest_byte += bytes_can_read; p_i2s_obj[i2s_num]->rx->rw_pos += bytes_can_read; - byte_read += bytes_can_read; + (*bytes_read) += bytes_can_read; } xSemaphoreGive(p_i2s_obj[i2s_num]->rx->mux); - return byte_read; + return ESP_OK; } -int i2s_push_sample(i2s_port_t i2s_num, const char *sample, TickType_t ticks_to_wait) +int i2s_push_sample(i2s_port_t i2s_num, const void *sample, TickType_t ticks_to_wait) { - int i, bytes_to_push = 0; - char *data_ptr; + size_t bytes_push = 0; + int res = 0; I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL); - if (p_i2s_obj[i2s_num]->tx->rw_pos == p_i2s_obj[i2s_num]->tx->buf_size || p_i2s_obj[i2s_num]->tx->curr_ptr == NULL) { - if (xQueueReceive(p_i2s_obj[i2s_num]->tx->queue, &p_i2s_obj[i2s_num]->tx->curr_ptr, ticks_to_wait) == pdFALSE) { - return bytes_to_push; - } - ESP_LOGD(I2S_TAG, "rw_pos: %d, buf_size: %d, curr_ptr: %d", p_i2s_obj[i2s_num]->tx->rw_pos, p_i2s_obj[i2s_num]->tx->buf_size, (int)p_i2s_obj[i2s_num]->tx->curr_ptr); - p_i2s_obj[i2s_num]->tx->rw_pos = 0; + res = i2s_write(i2s_num, sample, p_i2s_obj[i2s_num]->bytes_per_sample, &bytes_push, ticks_to_wait); + if (res != ESP_OK) { + return ESP_FAIL; + } else { + return bytes_push; } - data_ptr = (char*)p_i2s_obj[i2s_num]->tx->curr_ptr; - data_ptr += p_i2s_obj[i2s_num]->tx->rw_pos; - for (i = 0; i < p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num; i++) { - *data_ptr++ = *sample++; - bytes_to_push ++; - } - p_i2s_obj[i2s_num]->tx->rw_pos += bytes_to_push; - return bytes_to_push; } -int i2s_pop_sample(i2s_port_t i2s_num, char *sample, TickType_t ticks_to_wait) +int i2s_pop_sample(i2s_port_t i2s_num, void *sample, TickType_t ticks_to_wait) { - int i, bytes_to_pop = 0; - char *data_ptr; + size_t bytes_pop = 0; + int res = 0; I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_FAIL); - if (p_i2s_obj[i2s_num]->rx->rw_pos == p_i2s_obj[i2s_num]->rx->buf_size || p_i2s_obj[i2s_num]->rx->curr_ptr == NULL) { - if (xQueueReceive(p_i2s_obj[i2s_num]->rx->queue, &p_i2s_obj[i2s_num]->rx->curr_ptr, ticks_to_wait) == pdFALSE) { - return bytes_to_pop; - } - p_i2s_obj[i2s_num]->rx->rw_pos = 0; + res = i2s_read(i2s_num, sample, p_i2s_obj[i2s_num]->bytes_per_sample, &bytes_pop, ticks_to_wait); + if (res != ESP_OK) { + return ESP_FAIL; + } else { + return bytes_pop; } - data_ptr = (char*)p_i2s_obj[i2s_num]->rx->curr_ptr; - data_ptr += p_i2s_obj[i2s_num]->rx->rw_pos; - for (i = 0; i < p_i2s_obj[i2s_num]->bytes_per_sample; i++) { - *sample++ = *data_ptr++; - bytes_to_pop++; - } - if (p_i2s_obj[i2s_num]->channel_num == 2) { - for (i = 0; i < p_i2s_obj[i2s_num]->bytes_per_sample; i++) { - *sample++ = *data_ptr++; - bytes_to_pop++; - } - } - - p_i2s_obj[i2s_num]->rx->rw_pos += p_i2s_obj[i2s_num]->bytes_per_sample * p_i2s_obj[i2s_num]->channel_num; - return bytes_to_pop; } + + diff --git a/components/driver/include/driver/i2s.h b/components/driver/include/driver/i2s.h old mode 100755 new mode 100644 index 338e6ca378..1cd454796f --- a/components/driver/include/driver/i2s.h +++ b/components/driver/include/driver/i2s.h @@ -263,42 +263,55 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num); /** * @brief Write data to I2S DMA transmit buffer. * - * @param i2s_num I2S_NUM_0, I2S_NUM_1 + * This function is deprecated. Use 'i2s_write' instead. + * This definition will be removed in a future release. * - * @param src Source address to write from + * @return + * - The amount of bytes written, if timeout, the result will be less than the size passed in. + * - ESP_FAIL Parameter error + */ +int i2s_write_bytes(i2s_port_t i2s_num, const void *src, size_t size, TickType_t ticks_to_wait) __attribute__ ((deprecated)); + +/** + * @brief Write data to I2S DMA transmit buffer. * - * @param size Size of data in bytes + * @param i2s_num I2S_NUM_0, I2S_NUM_1 * - * @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this + * @param src Source address to write from + * + * @param size Size of data in bytes + * + * @param[out] bytes_written Number of bytes written, if timeout, the result will be less than the size passed in. + * + * @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this * many ticks pass without space becoming available in the DMA * transmit buffer, then the function will return (note that if the * data is written to the DMA buffer in pieces, the overall operation * may still take longer than this timeout.) Pass portMAX_DELAY for no * timeout. * - * Format of the data in source buffer is determined by the I2S - * configuration (see i2s_config_t). - * * @return - * - Number of bytes written, if timeout occurred, bytes written will be less than the size passed. - * - ESP_FAIL Parameter error. + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error */ -int i2s_write_bytes(i2s_port_t i2s_num, const char *src, size_t size, TickType_t ticks_to_wait); +esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *bytes_written, TickType_t ticks_to_wait); /** * @brief Write data to I2S DMA transmit buffer while expanding the number of bits per sample. For example, expanding 16-bit PCM to 32-bit PCM. * - * @param i2s_num I2S_NUM_0, I2S_NUM_1 + * @param i2s_num I2S_NUM_0, I2S_NUM_1 * - * @param src Source address to write from + * @param src Source address to write from * - * @param size Size of data in bytes + * @param size Size of data in bytes * - * @param src_bits Source audio bit + * @param src_bits Source audio bit * - * @param aim_bits Bit wanted, no more than 32, and must be greater than src_bits + * @param aim_bits Bit wanted, no more than 32, and must be greater than src_bits * - * @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this + * @param[out] bytes_written Number of bytes written, if timeout, the result will be less than the size passed in. + * + * @param ticks_to_wait TX buffer wait timeout in RTOS ticks. If this * many ticks pass without space becoming available in the DMA * transmit buffer, then the function will return (note that if the * data is written to the DMA buffer in pieces, the overall operation @@ -309,67 +322,80 @@ int i2s_write_bytes(i2s_port_t i2s_num, const char *src, size_t size, TickType_t * configuration (see i2s_config_t). * * @return - * - Number of bytes written, if timeout occurred, bytes written will be less than the size passed. - * - ESP_FAIL Parameter error. + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error */ -int i2s_write_expand(i2s_port_t i2s_num, const char *src, int size, int src_bits, int aim_bits, TickType_t ticks_to_wait); +esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, size_t src_bits, size_t aim_bits, size_t *bytes_written, TickType_t ticks_to_wait); /** * @brief Read data from I2S DMA receive buffer * - * @param i2s_num I2S_NUM_0, I2S_NUM_1 + * This function is deprecated. Use 'i2s_read' instead. + * This definition will be removed in a future release. * - * @param dest Destination address to read into + * @return + * - The amount of bytes read, if timeout, bytes read will be less than the size passed in + * - ESP_FAIL Parameter error + */ +int i2s_read_bytes(i2s_port_t i2s_num, void *dest, size_t size, TickType_t ticks_to_wait) __attribute__ ((deprecated)); + +/** + * @brief Read data from I2S DMA receive buffer * - * @param size Size of data in bytes + * @param i2s_num I2S_NUM_0, I2S_NUM_1 * - * @param ticks_to_wait RX buffer wait timeout in RTOS ticks. If this many ticks pass without bytes becoming available in the DMA receive buffer, then the function will return (note that if data is read from the DMA buffer in pieces, the overall operation may still take longer than this timeout.) Pass portMAX_DELAY for no timeout. + * @param dest Destination address to read into + * + * @param size Size of data in bytes + * + * @param[out] bytes_read Number of bytes read, if timeout, bytes read will be less than the size passed in. + * + * @param ticks_to_wait RX buffer wait timeout in RTOS ticks. If this many ticks pass without bytes becoming available in the DMA receive buffer, then the function will return (note that if data is read from the DMA buffer in pieces, the overall operation may still take longer than this timeout.) Pass portMAX_DELAY for no timeout. * - * Format of the data in source buffer is determined by the I2S - * configuration (see i2s_config_t). * @note If the built-in ADC mode is enabled, we should call i2s_adc_start and i2s_adc_stop around the whole reading process, * to prevent the data getting corrupted. * * @return - * - Number of bytes read, if timeout occurred, bytes written will be less than the size passed. - * - ESP_FAIL Parameter error. + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error */ -int i2s_read_bytes(i2s_port_t i2s_num, char* dest, size_t size, TickType_t ticks_to_wait); +esp_err_t i2s_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait); /** - * @brief Push (write) a single sample to the I2S DMA TX buffer. + * @brief Write a single sample to the I2S DMA TX buffer. * - * Size of the sample is determined by the channel_format (mono or stereo)) & bits_per_sample configuration (see i2s_config_t). + * This function is deprecated. Use 'i2s_write' instead. + * This definition will be removed in a future release. * - * @param i2s_num I2S_NUM_0, I2S_NUM_1 + * @param i2s_num I2S_NUM_0, I2S_NUM_1 * - * @param sample Pointer to buffer containing sample to write. Size of buffer (in bytes) = (number of channels) * bits_per_sample / 8. + * @param sample Buffer to read data. Size of buffer (in bytes) = bits_per_sample / 8. * - * @param ticks_to_wait Push timeout in RTOS ticks. If space is not available in the DMA TX buffer within this period, no data is written and function returns 0. + * @param ticks_to_wait Timeout in RTOS ticks. If a sample is not available in the DMA buffer within this period, no data is read and function returns zero. * * @return - * - Number of bytes successfully pushed to DMA buffer, will be either zero or the size of configured sample buffer. - * - ESP_FAIL Parameter error. + * - Number of bytes successfully pushed to DMA buffer, will be either zero or the size of configured sample buffer (in bytes). + * - ESP_FAIL Parameter error */ -int i2s_push_sample(i2s_port_t i2s_num, const char *sample, TickType_t ticks_to_wait); +int i2s_push_sample(i2s_port_t i2s_num, const void *sample, TickType_t ticks_to_wait) __attribute__ ((deprecated)); /** - * @brief Pop (read) a single sample from the I2S DMA RX buffer. + * @brief Read a single sample from the I2S DMA RX buffer. * - * Size of the sample is determined by the channel_format (mono or stereo)) & bits_per_sample configuration (see i2s_config_t). + * This function is deprecated. Use 'i2s_read' instead. + * This definition will be removed in a future release. * - * @param i2s_num I2S_NUM_0, I2S_NUM_1 + * @param i2s_num I2S_NUM_0, I2S_NUM_1 * - * @param sample Buffer sample data will be read into. Size of buffer (in bytes) = (number of channels) * bits_per_sample / 8. + * @param sample Buffer to write data. Size of buffer (in bytes) = bits_per_sample / 8. * - * @param ticks_to_wait Pop timeout in RTOS ticks. If a sample is not available in the DMA buffer within this period, no data is read and function returns zero. + * @param ticks_to_wait Timeout in RTOS ticks. If a sample is not available in the DMA buffer within this period, no data is read and function returns zero. * * @return - * - Number of bytes successfully read from DMA buffer, will be either zero or the size of configured sample buffer. - * - ESP_FAIL Parameter error. + * - Number of bytes successfully read from DMA buffer, will be either zero or the size of configured sample buffer (in bytes). + * - ESP_FAIL Parameter error */ -int i2s_pop_sample(i2s_port_t i2s_num, char *sample, TickType_t ticks_to_wait); - +int i2s_pop_sample(i2s_port_t i2s_num, void *sample, TickType_t ticks_to_wait) __attribute__ ((deprecated)); /** * @brief Set sample rate used for I2S RX and TX. @@ -385,7 +411,6 @@ int i2s_pop_sample(i2s_port_t i2s_num, char *sample, TickType_t ticks_to_wait); * @return * - ESP_OK Success * - ESP_ERR_INVALID_ARG Parameter error - * - ESP_FAIL I2s is not initialized * - ESP_ERR_NO_MEM Out of memory */ esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate); @@ -445,7 +470,6 @@ esp_err_t i2s_zero_dma_buffer(i2s_port_t i2s_num); * * @return * - ESP_OK Success - * - ESP_FAIL Not initialized * - ESP_ERR_INVALID_ARG Parameter error * - ESP_ERR_NO_MEM Out of memory */ @@ -454,7 +478,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b /** * @brief Set built-in ADC mode for I2S DMA, this function will initialize ADC pad, * and set ADC parameters. - * @param adc_unit SAR ADC unit index + * @param adc_unit SAR ADC unit index * @param adc_channel ADC channel index * @return * - ESP_OK Success @@ -469,10 +493,9 @@ esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel); * * @param i2s_num i2s port index * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG Parameter error - * - ESP_ERR_INVALID_STATE driver state error - * - ESP_FAIL Internal driver error + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_INVALID_STATE Driver state error */ esp_err_t i2s_adc_enable(i2s_port_t i2s_num); @@ -481,9 +504,9 @@ esp_err_t i2s_adc_enable(i2s_port_t i2s_num); * @param i2s_num i2s port index * @note This function would release the lock of ADC so that other tasks can use ADC. * @return - * - ESP_OK Success - * - ESP_ERR_INVALID_ARG Parameter error - * - ESP_ERR_INVALID_STATE driver state error + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_INVALID_STATE Driver state error */ esp_err_t i2s_adc_disable(i2s_port_t i2s_num); diff --git a/examples/bluetooth/a2dp_sink/main/bt_app_av.c b/examples/bluetooth/a2dp_sink/main/bt_app_av.c index b1c432c576..f07279947a 100644 --- a/examples/bluetooth/a2dp_sink/main/bt_app_av.c +++ b/examples/bluetooth/a2dp_sink/main/bt_app_av.c @@ -53,7 +53,8 @@ void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len) { - i2s_write_bytes(0, (const char *)data, len, portMAX_DELAY); + size_t bytes_written; + i2s_write(0, data, len, &bytes_written, portMAX_DELAY); if (++m_pkt_cnt % 100 == 0) { ESP_LOGI(BT_AV_TAG, "Audio packet count %u", m_pkt_cnt); } diff --git a/examples/peripherals/i2s/main/i2s_example_main.c b/examples/peripherals/i2s/main/i2s_example_main.c index cf49a0885e..8c0c54d45f 100644 --- a/examples/peripherals/i2s/main/i2s_example_main.c +++ b/examples/peripherals/i2s/main/i2s_example_main.c @@ -1,7 +1,7 @@ /* I2S Example - + This example code will output 100Hz sine wave and triangle wave to 2-channel of I2S driver - Every 5 seconds, it will change bits_per_sample [16, 24, 32] for i2s data + Every 5 seconds, it will change bits_per_sample [16, 24, 32] for i2s data This example code is in the Public Domain (or CC0 licensed, at your option.) @@ -29,11 +29,12 @@ static void setup_triangle_sine_waves(int bits) int *samples_data = malloc(((bits+8)/16)*SAMPLE_PER_CYCLE*4); unsigned int i, sample_val; double sin_float, triangle_float, triangle_step = (double) pow(2, bits) / SAMPLE_PER_CYCLE; + size_t i2s_bytes_write = 0; printf("\r\nTest bits=%d free mem=%d, written data=%d\n", bits, esp_get_free_heap_size(), ((bits+8)/16)*SAMPLE_PER_CYCLE*4); triangle_float = -(pow(2, bits)/2 - 1); - + for(i = 0; i < SAMPLE_PER_CYCLE; i++) { sin_float = sin(i * PI / 180.0); if(sin_float >= 0) @@ -56,7 +57,7 @@ static void setup_triangle_sine_waves(int bits) samples_data[i*2] = ((int) triangle_float); samples_data[i*2 + 1] = ((int) sin_float); } - + } i2s_set_clk(I2S_NUM, SAMPLE_RATE, bits, 2); @@ -68,12 +69,12 @@ static void setup_triangle_sine_waves(int bits) // i2s_push_sample(0, &samples_data[i*2], 100); // } // or write - i2s_write_bytes(I2S_NUM, (const char *)samples_data, ((bits+8)/16)*SAMPLE_PER_CYCLE*4, 100); - + i2s_write(I2S_NUM, samples_data, ((bits+8)/16)*SAMPLE_PER_CYCLE*4, &i2s_bytes_write, 100); + free(samples_data); } void app_main() -{ +{ //for 36Khz sample rates, we create 100Hz sine wave, every cycle need 36000/100 = 360 samples (4-bytes or 8-bytes each sample) //depend on bits_per_sample //using 6 buffers, we need 60-samples per buffer @@ -82,7 +83,7 @@ void app_main() i2s_config_t i2s_config = { .mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX .sample_rate = SAMPLE_RATE, - .bits_per_sample = 16, + .bits_per_sample = 16, .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB, .dma_buf_count = 6, @@ -106,7 +107,7 @@ void app_main() test_bits += 8; if(test_bits > 32) test_bits = 16; - - } - + + } + } diff --git a/examples/peripherals/i2s_adc_dac/main/app_main.c b/examples/peripherals/i2s_adc_dac/main/app_main.c old mode 100755 new mode 100644 index 44f80d23de..25335bb61e --- a/examples/peripherals/i2s_adc_dac/main/app_main.c +++ b/examples/peripherals/i2s_adc_dac/main/app_main.c @@ -205,6 +205,7 @@ void example_i2s_adc_dac(void*arg) example_erase_flash(); int i2s_read_len = EXAMPLE_I2S_READ_LEN; int flash_wr_size = 0; + size_t bytes_read, bytes_written; //2. Record audio from ADC and save in flash #if RECORD_IN_FLASH_EN @@ -213,7 +214,7 @@ void example_i2s_adc_dac(void*arg) i2s_adc_enable(EXAMPLE_I2S_NUM); while (flash_wr_size < FLASH_RECORD_SIZE) { //read data from I2S bus, in this case, from ADC. - i2s_read_bytes(EXAMPLE_I2S_NUM, (char*) i2s_read_buff, i2s_read_len, portMAX_DELAY); + i2s_read(EXAMPLE_I2S_NUM, (void*) i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY); example_disp_buf((uint8_t*) i2s_read_buff, 64); //save original data from I2S(ADC) into flash. esp_partition_write(data_partition, flash_wr_size, i2s_read_buff, i2s_read_len); @@ -239,7 +240,7 @@ void example_i2s_adc_dac(void*arg) //process data and scale to 8bit for I2S DAC. example_i2s_adc_data_scale(i2s_write_buff, flash_read_buff, FLASH_SECTOR_SIZE); //send data - i2s_write_bytes(EXAMPLE_I2S_NUM, (char*) i2s_write_buff, FLASH_SECTOR_SIZE, portMAX_DELAY); + i2s_write(EXAMPLE_I2S_NUM, i2s_write_buff, FLASH_SECTOR_SIZE, &bytes_written, portMAX_DELAY); printf("playing: %d %%\n", rd_offset * 100 / flash_wr_size); } #endif @@ -252,7 +253,7 @@ void example_i2s_adc_dac(void*arg) while (offset < tot_size) { int play_len = ((tot_size - offset) > (4 * 1024)) ? (4 * 1024) : (tot_size - offset); int i2s_wr_len = example_i2s_dac_data_scale(i2s_write_buff, (uint8_t*)(audio_table + offset), play_len); - i2s_write_bytes(EXAMPLE_I2S_NUM, (const char*) i2s_write_buff, i2s_wr_len, portMAX_DELAY); + i2s_write(EXAMPLE_I2S_NUM, i2s_write_buff, i2s_wr_len, &bytes_written, portMAX_DELAY); offset += play_len; example_disp_buf((uint8_t*) i2s_write_buff, 32); } From 54d9a392e416bedfe6ea732e7bd11bc8856dd588 Mon Sep 17 00:00:00 2001 From: Deng Xin Date: Mon, 14 May 2018 10:58:19 +0800 Subject: [PATCH 113/187] wifi: add set factory information feature by customer in wps --- components/esp32/include/esp_wps.h | 21 ++++++++++++++++++++- components/esp32/lib | 2 +- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/components/esp32/include/esp_wps.h b/components/esp32/include/esp_wps.h index efe37bd028..9bd61cc3af 100644 --- a/components/esp32/include/esp_wps.h +++ b/components/esp32/include/esp_wps.h @@ -56,14 +56,33 @@ typedef enum wps_type { extern const wps_crypto_funcs_t g_wifi_default_wps_crypto_funcs; +#define WPS_MAX_MANUFACTURER_LEN 65 +#define WPS_MAX_MODEL_NUMBER_LEN 33 +#define WPS_MAX_MODEL_NAME_LEN 33 +#define WPS_MAX_DEVICE_NAME_LEN 33 + +typedef struct { + char manufacturer[WPS_MAX_MANUFACTURER_LEN]; /*!< Manufacturer, null-terminated string. The default manufcturer is used if the string is empty */ + char model_number[WPS_MAX_MODEL_NUMBER_LEN]; /*!< Model number, null-terminated string. The default model number is used if the string is empty */ + char model_name[WPS_MAX_MODEL_NAME_LEN]; /*!< Model name, null-terminated string. The default model name is used if the string is empty */ + char device_name[WPS_MAX_DEVICE_NAME_LEN]; /*!< Device name, null-terminated string. The default device name is used if the string is empty */ +} wps_factory_information_t; + typedef struct { wps_type_t wps_type; const wps_crypto_funcs_t *crypto_funcs; -}esp_wps_config_t; + wps_factory_information_t factory_info; +} esp_wps_config_t; #define WPS_CONFIG_INIT_DEFAULT(type) { \ .wps_type = type, \ .crypto_funcs = &g_wifi_default_wps_crypto_funcs, \ + .factory_info = { \ + .manufacturer = "ESPRESSIF", \ + .model_number = "ESP32", \ + .model_name = "ESPRESSIF IOT", \ + .device_name = "ESP STATION", \ + } \ } /** diff --git a/components/esp32/lib b/components/esp32/lib index 618fa4eb59..3b4ce03f46 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 618fa4eb596c07521d9cdcc1ba019fe5cd42cec6 +Subproject commit 3b4ce03f4634ed8837868bb45094d0ec3ee1deb5 From a2241fb4bc33375ffeb1cb479e464d87ce1c8cb6 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 17 May 2018 19:12:45 +0800 Subject: [PATCH 114/187] tests: Increase performance threshold for VFS running with PSRAM Cache effects on microbenchmarks in cached flash can be significant, depending on linker layout in flash. --- components/idf_test/include/idf_performance.h | 3 +++ components/vfs/test/test_vfs_fd.c | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/components/idf_test/include/idf_performance.h b/components/idf_test/include/idf_performance.h index 40c733f03a..f98f75c317 100644 --- a/components/idf_test/include/idf_performance.h +++ b/components/idf_test/include/idf_performance.h @@ -16,7 +16,10 @@ #define IDF_PERFORMANCE_MAX_ESP_TIMER_GET_TIME_PER_CALL 1000 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 30 #define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 27 +/* Due to code size & linker layout differences interacting with cache, VFS + microbenchmark currently runs slower with PSRAM enabled. */ #define IDF_PERFORMANCE_MAX_VFS_OPEN_WRITE_CLOSE_TIME 20000 +#define IDF_PERFORMANCE_MAX_VFS_OPEN_WRITE_CLOSE_TIME_PSRAM 40000 // throughput performance by iperf #define IDF_PERFORMANCE_MIN_TCP_RX_THROUGHPUT 50 #define IDF_PERFORMANCE_MIN_TCP_TX_THROUGHPUT 40 diff --git a/components/vfs/test/test_vfs_fd.c b/components/vfs/test/test_vfs_fd.c index a3c6236534..c4292d3fca 100644 --- a/components/vfs/test/test_vfs_fd.c +++ b/components/vfs/test/test_vfs_fd.c @@ -257,5 +257,10 @@ TEST_CASE("Open & write & close through VFS passes performance test", "[vfs]") const int64_t time_diff_us = esp_timer_get_time() - begin; const int ns_per_iter = (int) (time_diff_us * 1000 / iter_count); TEST_ESP_OK( esp_vfs_unregister(VFS_PREF1) ); +#ifdef CONFIG_SPIRAM_SUPPORT + TEST_PERFORMANCE_LESS_THAN(VFS_OPEN_WRITE_CLOSE_TIME_PSRAM, "%dns", ns_per_iter); +#else TEST_PERFORMANCE_LESS_THAN(VFS_OPEN_WRITE_CLOSE_TIME, "%dns", ns_per_iter); +#endif + } From 4e9ea812080ceeddbd77a57f7073aa5634ef4431 Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Thu, 3 May 2018 17:02:44 +0800 Subject: [PATCH 115/187] esp32: support to create wifi task on any core Support to create WiFi task on any core. Closes https://github.com/espressif/esp-idf/issues/968 --- components/esp32/Kconfig | 13 +++++++++++++ components/esp32/include/esp_wifi.h | 8 ++++++++ components/esp32/lib | 2 +- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index b12c4ae5c4..7ef096a2cd 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -997,6 +997,19 @@ config ESP32_WIFI_NVS_ENABLED help Select this option to enable WiFi NVS flash +choice ESP32_WIFI_TASK_CORE_ID + depends on !FREERTOS_UNICORE + prompt "WiFi Task Core ID" + default ESP32_WIFI_TASK_PINNED_TO_CORE_0 + help + Pinned WiFi task to core 0 or core 1. + +config ESP32_WIFI_TASK_PINNED_TO_CORE_0 + bool "Core 0" +config ESP32_WIFI_TASK_PINNED_TO_CORE_1 + bool "Core 1" +endchoice + endmenu # Wi-Fi menu PHY diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h index 77ee218279..f3333eebd9 100755 --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -105,6 +105,7 @@ typedef struct { int nano_enable; /**< Nano option for printf/scan family enable flag */ int tx_ba_win; /**< WiFi Block Ack TX window size */ int rx_ba_win; /**< WiFi Block Ack RX window size */ + int wifi_task_core_id; /**< WiFi Task Core ID */ int magic; /**< WiFi init magic number, it should be the last field */ } wifi_init_config_t; @@ -160,6 +161,12 @@ extern const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs; #define WIFI_DEFAULT_RX_BA_WIN 0 /* unused if ampdu_rx_enable == false */ #endif +#if CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 +#define WIFI_TASK_CORE_ID 1 +#else +#define WIFI_TASK_CORE_ID 0 +#endif + #define WIFI_INIT_CONFIG_DEFAULT() { \ .event_handler = &esp_event_send, \ .wpa_crypto_funcs = g_wifi_default_wpa_crypto_funcs, \ @@ -174,6 +181,7 @@ extern const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs; .nano_enable = WIFI_NANO_FORMAT_ENABLED,\ .tx_ba_win = WIFI_DEFAULT_TX_BA_WIN,\ .rx_ba_win = WIFI_DEFAULT_RX_BA_WIN,\ + .wifi_task_core_id = WIFI_TASK_CORE_ID,\ .magic = WIFI_INIT_CONFIG_MAGIC\ }; diff --git a/components/esp32/lib b/components/esp32/lib index 3b4ce03f46..ba4c4ce08e 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 3b4ce03f4634ed8837868bb45094d0ec3ee1deb5 +Subproject commit ba4c4ce08e64ec848360afe25796fbdf45e24c9a From 028fbb58e8e97071285111919f91f17bd59a7256 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 12 Apr 2018 18:18:45 +0800 Subject: [PATCH 116/187] freertos,esp32: automatic light sleep support --- components/esp32/freertos_hooks.c | 4 + components/esp32/pm_esp32.c | 69 ++++- components/esp32/pm_trace.c | 1 + components/esp32/pm_trace.h | 1 + components/esp32/test/test_pm.c | 259 ++++++++++++++++++ components/freertos/Kconfig | 25 ++ .../include/freertos/FreeRTOSConfig.h | 4 + .../freertos/include/freertos/portmacro.h | 4 + components/freertos/tasks.c | 45 ++- 9 files changed, 404 insertions(+), 8 deletions(-) diff --git a/components/esp32/freertos_hooks.c b/components/esp32/freertos_hooks.c index d2b24e9952..328ef36e26 100644 --- a/components/esp32/freertos_hooks.c +++ b/components/esp32/freertos_hooks.c @@ -59,6 +59,10 @@ void esp_vApplicationIdleHook() #ifdef CONFIG_PM_ENABLE esp_pm_impl_idle_hook(); #endif +} + +extern void esp_vApplicationWaitiHook( void ) +{ asm("waiti 0"); } diff --git a/components/esp32/pm_esp32.c b/components/esp32/pm_esp32.c index 11a4d3c0db..f75b3fe811 100644 --- a/components/esp32/pm_esp32.c +++ b/components/esp32/pm_esp32.c @@ -22,10 +22,12 @@ #include "esp_pm.h" #include "esp_log.h" #include "esp_crosscore_int.h" +#include "esp_clk.h" #include "soc/rtc.h" #include "freertos/FreeRTOS.h" +#include "freertos/task.h" #include "freertos/xtensa_timer.h" #include "xtensa/core-macros.h" @@ -39,6 +41,16 @@ */ #define CCOMPARE_UPDATE_TIMEOUT 1000000 +/* When changing CCOMPARE, don't allow changes if the difference is less + * than this. This is to prevent setting CCOMPARE below CCOUNT. + */ +#define CCOMPARE_MIN_CYCLES_IN_FUTURE 1000 + +/* When light sleep is used, wake this number of microseconds earlier than + * the next tick. + */ +#define LIGHT_SLEEP_EARLY_WAKEUP_US 100 + #ifdef CONFIG_PM_PROFILING #define WITH_PROFILING #endif @@ -107,7 +119,7 @@ static const char* s_freq_names[] __attribute__((unused)) = { [RTC_CPU_FREQ_2M] = "2" }; -/* Whether automatic light sleep is enabled. Currently always false */ +/* Whether automatic light sleep is enabled */ static bool s_light_sleep_en = false; /* When configuration is changed, current frequency may not match the @@ -177,9 +189,11 @@ esp_err_t esp_pm_configure(const void* vconfig) #endif const esp_pm_config_esp32_t* config = (const esp_pm_config_esp32_t*) vconfig; +#ifndef CONFIG_FREERTOS_USE_TICKLESS_IDLE if (config->light_sleep_enable) { return ESP_ERR_NOT_SUPPORTED; } +#endif if (config->min_cpu_freq == RTC_CPU_FREQ_2M) { /* Minimal APB frequency to achieve 1MHz REF_TICK frequency is 5 MHz */ @@ -401,10 +415,9 @@ static void IRAM_ATTR do_switch(pm_mode_t new_mode) */ static void IRAM_ATTR update_ccompare() { - const uint32_t ccompare_min_cycles_in_future = 1000; uint32_t ccount = XTHAL_GET_CCOUNT(); uint32_t ccompare = XTHAL_GET_CCOMPARE(XT_TIMER_INDEX); - if ((ccompare - ccompare_min_cycles_in_future) - ccount < UINT32_MAX / 2) { + if ((ccompare - CCOMPARE_MIN_CYCLES_IN_FUTURE) - ccount < UINT32_MAX / 2) { uint32_t diff = ccompare - ccount; uint32_t diff_scaled = (diff * s_ccount_mul + s_ccount_div - 1) / s_ccount_div; if (diff_scaled < _xt_tick_divisor) { @@ -453,6 +466,56 @@ void IRAM_ATTR esp_pm_impl_isr_hook() ESP_PM_TRACE_EXIT(ISR_HOOK, core_id); } +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE + +bool IRAM_ATTR vApplicationSleep( TickType_t xExpectedIdleTime ) +{ + bool result = false; + portENTER_CRITICAL(&s_switch_lock); + if (s_mode == PM_MODE_LIGHT_SLEEP && !s_is_switching) { + /* Calculate how much we can sleep */ + int64_t next_esp_timer_alarm = esp_timer_get_next_alarm(); + int64_t now = esp_timer_get_time(); + int64_t time_until_next_alarm = next_esp_timer_alarm - now; + int64_t wakeup_delay_us = portTICK_PERIOD_MS * 1000LL * xExpectedIdleTime; + int64_t sleep_time_us = MIN(wakeup_delay_us, time_until_next_alarm); + if (sleep_time_us >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP * portTICK_PERIOD_MS * 1000LL) { + esp_sleep_enable_timer_wakeup(sleep_time_us - LIGHT_SLEEP_EARLY_WAKEUP_US); +#ifdef CONFIG_PM_TRACE + /* to force tracing GPIOs to keep state */ + esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); +#endif + /* Enter sleep */ + int core_id = xPortGetCoreID(); + ESP_PM_TRACE_ENTER(SLEEP, core_id); + int64_t sleep_start = esp_timer_get_time(); + esp_light_sleep_start(); + int64_t slept_us = esp_timer_get_time() - sleep_start; + ESP_PM_TRACE_EXIT(SLEEP, core_id); + + uint32_t slept_ticks = slept_us / (portTICK_PERIOD_MS * 1000LL); + if (slept_ticks > 0) { + /* Adjust RTOS tick count based on the amount of time spent in sleep */ + vTaskStepTick(slept_ticks); + + /* Trigger tick interrupt, since sleep time was longer + * than portTICK_PERIOD_MS. Note that setting INTSET does not + * work for timer interrupt, and changing CCOMPARE would clear + * the interrupt flag. + */ + XTHAL_SET_CCOUNT(XTHAL_GET_CCOMPARE(XT_TIMER_INDEX) - 16); + while (!(XTHAL_GET_INTERRUPT() & BIT(XT_TIMER_INTNUM))) { + ; + } + } + result = true; + } + } + portEXIT_CRITICAL(&s_switch_lock); + return result; +} +#endif //CONFIG_FREERTOS_USE_TICKLESS_IDLE + #ifdef WITH_PROFILING void esp_pm_impl_dump_stats(FILE* out) { diff --git a/components/esp32/pm_trace.c b/components/esp32/pm_trace.c index c1f240017e..eddaec3843 100644 --- a/components/esp32/pm_trace.c +++ b/components/esp32/pm_trace.c @@ -27,6 +27,7 @@ static const int DRAM_ATTR s_trace_io[] = { BIT(18), BIT(18), // ESP_PM_TRACE_FREQ_SWITCH BIT(19), BIT(19), // ESP_PM_TRACE_CCOMPARE_UPDATE BIT(25), BIT(26), // ESP_PM_TRACE_ISR_HOOK + BIT(27), BIT(27), // ESP_PM_TRACE_SLEEP }; void esp_pm_trace_init() diff --git a/components/esp32/pm_trace.h b/components/esp32/pm_trace.h index 1aff1ac806..20eebb0d69 100644 --- a/components/esp32/pm_trace.h +++ b/components/esp32/pm_trace.h @@ -22,6 +22,7 @@ typedef enum { ESP_PM_TRACE_FREQ_SWITCH, ESP_PM_TRACE_CCOMPARE_UPDATE, ESP_PM_TRACE_ISR_HOOK, + ESP_PM_TRACE_SLEEP, ESP_PM_TRACE_TYPE_MAX } esp_pm_trace_event_t; diff --git a/components/esp32/test/test_pm.c b/components/esp32/test/test_pm.c index 7033238a04..fa432eddc9 100644 --- a/components/esp32/test/test_pm.c +++ b/components/esp32/test/test_pm.c @@ -7,7 +7,14 @@ #include "esp_clk.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "freertos/semphr.h" #include "esp_log.h" +#include "driver/timer.h" +#include "driver/rtc_io.h" +#include "esp32/ulp.h" +#include "soc/rtc_io_reg.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/rtc_gpio_channel.h" TEST_CASE("Can dump power management lock stats", "[pm]") { @@ -48,4 +55,256 @@ TEST_CASE("Can switch frequency using esp_pm_configure", "[pm]") switch_freq(orig_freq_mhz); } +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE + +static void light_sleep_enable() +{ + const esp_pm_config_esp32_t pm_config = { + .max_cpu_freq = rtc_clk_cpu_freq_get(), + .min_cpu_freq = RTC_CPU_FREQ_XTAL, + .light_sleep_enable = true + }; + ESP_ERROR_CHECK( esp_pm_configure(&pm_config) ); +} + +static void light_sleep_disable() +{ + const esp_pm_config_esp32_t pm_config = { + .max_cpu_freq = rtc_clk_cpu_freq_get(), + .min_cpu_freq = rtc_clk_cpu_freq_get(), + }; + ESP_ERROR_CHECK( esp_pm_configure(&pm_config) ); +} + +TEST_CASE("Automatic light occurs when tasks are suspended", "[pm]") +{ + /* To figure out if light sleep takes place, use Timer Group timer. + * It will stop working while in light sleep. + */ + timer_config_t config = { + .counter_dir = TIMER_COUNT_UP, + .divider = 80 /* 1 us per tick */ + }; + timer_init(TIMER_GROUP_0, TIMER_0, &config); + timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0); + timer_start(TIMER_GROUP_0, TIMER_0); + + light_sleep_enable(); + + for (int ticks_to_delay = CONFIG_FREERTOS_IDLE_TIME_BEFORE_SLEEP; + ticks_to_delay < CONFIG_FREERTOS_IDLE_TIME_BEFORE_SLEEP * 10; + ++ticks_to_delay) { + + /* Wait until next tick */ + vTaskDelay(1); + + /* The following delay should cause light sleep to start */ + uint64_t count_start; + timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &count_start); + vTaskDelay(ticks_to_delay); + uint64_t count_end; + timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &count_end); + + + int timer_diff_us = (int) (count_end - count_start); + const int us_per_tick = 1 * portTICK_PERIOD_MS * 1000; + + printf("%d %d\n", ticks_to_delay * us_per_tick, timer_diff_us); + TEST_ASSERT(timer_diff_us < ticks_to_delay * us_per_tick); + } + + light_sleep_disable(); +} + + +TEST_CASE("Can wake up from automatic light sleep by GPIO", "[pm]") +{ + assert(CONFIG_ULP_COPROC_RESERVE_MEM >= 16 && "this test needs ULP_COPROC_RESERVE_MEM option set in menuconfig"); + + /* Set up GPIO used to wake up RTC */ + const int ext1_wakeup_gpio = 25; + const int ext_rtc_io = RTCIO_GPIO25_CHANNEL; + TEST_ESP_OK(rtc_gpio_init(ext1_wakeup_gpio)); + rtc_gpio_set_direction(ext1_wakeup_gpio, RTC_GPIO_MODE_INPUT_OUTPUT); + rtc_gpio_set_level(ext1_wakeup_gpio, 0); + + /* Enable wakeup */ + TEST_ESP_OK(esp_sleep_enable_ext1_wakeup(1ULL << ext1_wakeup_gpio, ESP_EXT1_WAKEUP_ANY_HIGH)); + + /* To simplify test environment, we'll use a ULP program to set GPIO high */ + ulp_insn_t ulp_code[] = { + I_DELAY(65535), /* about 8ms, given 8MHz ULP clock */ + I_WR_REG_BIT(RTC_CNTL_HOLD_FORCE_REG, RTC_CNTL_PDAC1_HOLD_FORCE_S, 0), + I_WR_REG_BIT(RTC_GPIO_OUT_REG, ext_rtc_io + RTC_GPIO_OUT_DATA_S, 1), + I_DELAY(1000), + I_WR_REG_BIT(RTC_GPIO_OUT_REG, ext_rtc_io + RTC_GPIO_OUT_DATA_S, 0), + I_WR_REG_BIT(RTC_CNTL_HOLD_FORCE_REG, RTC_CNTL_PDAC1_HOLD_FORCE_S, 1), + I_END(), + I_HALT() + }; + TEST_ESP_OK(ulp_set_wakeup_period(0, 1000 /* us */)); + size_t size = sizeof(ulp_code)/sizeof(ulp_insn_t); + TEST_ESP_OK(ulp_process_macros_and_load(0, ulp_code, &size)); + + light_sleep_enable(); + + for (int i = 0; i < 10; ++i) { + /* Set GPIO low */ + REG_CLR_BIT(rtc_gpio_desc[ext1_wakeup_gpio].reg, rtc_gpio_desc[ext1_wakeup_gpio].hold_force); + rtc_gpio_set_level(ext1_wakeup_gpio, 0); + REG_SET_BIT(rtc_gpio_desc[ext1_wakeup_gpio].reg, rtc_gpio_desc[ext1_wakeup_gpio].hold_force); + + /* Wait for the next tick */ + vTaskDelay(1); + + /* Start ULP program */ + ulp_run(0); + + const int delay_ms = 200; + const int delay_ticks = delay_ms / portTICK_PERIOD_MS; + + int64_t start_rtc = esp_clk_rtc_time(); + int64_t start_hs = esp_timer_get_time(); + uint32_t start_tick = xTaskGetTickCount(); + /* Will enter sleep here */ + vTaskDelay(delay_ticks); + int64_t end_rtc = esp_clk_rtc_time(); + int64_t end_hs = esp_timer_get_time(); + uint32_t end_tick = xTaskGetTickCount(); + + printf("%lld %lld %u\n", end_rtc - start_rtc, end_hs - start_hs, end_tick - start_tick); + + TEST_ASSERT_INT32_WITHIN(3, delay_ticks, end_tick - start_tick); + TEST_ASSERT_INT32_WITHIN(2 * portTICK_PERIOD_MS * 1000, delay_ms * 1000, end_hs - start_hs); + TEST_ASSERT_INT32_WITHIN(2 * portTICK_PERIOD_MS * 1000, delay_ms * 1000, end_rtc - start_rtc); + } + REG_CLR_BIT(rtc_gpio_desc[ext1_wakeup_gpio].reg, rtc_gpio_desc[ext1_wakeup_gpio].hold_force); + rtc_gpio_deinit(ext1_wakeup_gpio); + + light_sleep_disable(); +} + + +typedef struct { + int delay_us; + int result; + SemaphoreHandle_t done; +} delay_test_arg_t; + +static void test_delay_task(void* p) +{ + delay_test_arg_t* arg = (delay_test_arg_t*) p; + vTaskDelay(1); + + uint64_t start = esp_clk_rtc_time(); + vTaskDelay(arg->delay_us / portTICK_PERIOD_MS / 1000); + uint64_t stop = esp_clk_rtc_time(); + + arg->result = (int) (stop - start); + xSemaphoreGive(arg->done); + vTaskDelete(NULL); +} + +TEST_CASE("vTaskDelay duration is correct with light sleep enabled", "[pm]") +{ + light_sleep_enable(); + + delay_test_arg_t args = { + .done = xSemaphoreCreateBinary() + }; + + const int delays[] = { 10, 20, 50, 100, 150, 200, 250 }; + const int delays_count = sizeof(delays) / sizeof(delays[0]); + + for (int i = 0; i < delays_count; ++i) { + int delay_ms = delays[i]; + args.delay_us = delay_ms * 1000; + + xTaskCreatePinnedToCore(test_delay_task, "", 2048, (void*) &args, 3, NULL, 0); + TEST_ASSERT( xSemaphoreTake(args.done, delay_ms * 10 / portTICK_PERIOD_MS) ); + printf("CPU0: %d %d\n", args.delay_us, args.result); + TEST_ASSERT_INT32_WITHIN(1000 * portTICK_PERIOD_MS * 2, args.delay_us, args.result); + +#if portNUM_PROCESSORS == 2 + xTaskCreatePinnedToCore(test_delay_task, "", 2048, (void*) &args, 3, NULL, 1); + TEST_ASSERT( xSemaphoreTake(args.done, delay_ms * 10 / portTICK_PERIOD_MS) ); + printf("CPU1: %d %d\n", args.delay_us, args.result); + TEST_ASSERT_INT32_WITHIN(1000 * portTICK_PERIOD_MS * 2, args.delay_us, args.result); +#endif + } + vSemaphoreDelete(args.done); + + light_sleep_disable(); +} + +/* This test is similar to the one in test_esp_timer.c, but since we can't use + * ref_clock, this test uses RTC clock for timing. Also enables automatic + * light sleep. + */ +TEST_CASE("esp_timer produces correct delays with light sleep", "[pm]") +{ + // no, we can't make this a const size_t (§6.7.5.2) +#define NUM_INTERVALS 16 + + typedef struct { + esp_timer_handle_t timer; + size_t cur_interval; + int intervals[NUM_INTERVALS]; + int64_t t_start; + SemaphoreHandle_t done; + } test_args_t; + + void timer_func(void* arg) + { + test_args_t* p_args = (test_args_t*) arg; + int64_t t_end = esp_clk_rtc_time(); + int32_t ms_diff = (t_end - p_args->t_start) / 1000; + printf("timer #%d %dms\n", p_args->cur_interval, ms_diff); + p_args->intervals[p_args->cur_interval++] = ms_diff; + // Deliberately make timer handler run longer. + // We check that this doesn't affect the result. + ets_delay_us(10*1000); + if (p_args->cur_interval == NUM_INTERVALS) { + printf("done\n"); + TEST_ESP_OK(esp_timer_stop(p_args->timer)); + xSemaphoreGive(p_args->done); + } + } + + light_sleep_enable(); + + const int delay_ms = 100; + test_args_t args = {0}; + esp_timer_handle_t timer1; + esp_timer_create_args_t create_args = { + .callback = &timer_func, + .arg = &args, + .name = "timer1", + }; + TEST_ESP_OK(esp_timer_create(&create_args, &timer1)); + + args.timer = timer1; + args.t_start = esp_clk_rtc_time(); + args.done = xSemaphoreCreateBinary(); + TEST_ESP_OK(esp_timer_start_periodic(timer1, delay_ms * 1000)); + + TEST_ASSERT(xSemaphoreTake(args.done, delay_ms * NUM_INTERVALS * 2)); + + TEST_ASSERT_EQUAL_UINT32(NUM_INTERVALS, args.cur_interval); + for (size_t i = 0; i < NUM_INTERVALS; ++i) { + TEST_ASSERT_INT32_WITHIN(portTICK_PERIOD_MS, (i + 1) * delay_ms, args.intervals[i]); + } + + TEST_ESP_OK( esp_timer_dump(stdout) ); + + TEST_ESP_OK( esp_timer_delete(timer1) ); + vSemaphoreDelete(args.done); + + light_sleep_disable(); + +#undef NUM_INTERVALS +} + +#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE + #endif // CONFIG_PM_ENABLE diff --git a/components/freertos/Kconfig b/components/freertos/Kconfig index c469d679d9..1a037377c8 100644 --- a/components/freertos/Kconfig +++ b/components/freertos/Kconfig @@ -357,6 +357,31 @@ config FREERTOS_RUN_TIME_STATS_USING_CPU_CLK endchoice +config FREERTOS_USE_TICKLESS_IDLE + bool "Tickless idle support" + depends on PM_ENABLE + default n + help + If power management support is enabled, FreeRTOS will be able to put + the system into light sleep mode when no tasks need to run for a number + of ticks. This number can be set using FREERTOS_IDLE_TIME_BEFORE_SLEEP option. + This feature is also known as "automatic light sleep". + + Note that timers created using esp_timer APIs may prevent the system from + entering sleep mode, even when no tasks need to run. + + If disabled, automatic light sleep support will be disabled. + +config FREERTOS_IDLE_TIME_BEFORE_SLEEP + int "Minimum number of ticks to enter sleep mode for" + depends on FREERTOS_USE_TICKLESS_IDLE + default 3 + range 2 4294967295 + # Minimal value is 2 because of a check in FreeRTOS.h (search configEXPECTED_IDLE_TIME_BEFORE_SLEEP) + help + FreeRTOS will enter light sleep mode if no tasks need to run for this number + of ticks. + menuconfig FREERTOS_DEBUG_INTERNALS bool "Debug FreeRTOS internals" default n diff --git a/components/freertos/include/freertos/FreeRTOSConfig.h b/components/freertos/include/freertos/FreeRTOSConfig.h index 37912a66ce..c52bc927cf 100644 --- a/components/freertos/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/include/freertos/FreeRTOSConfig.h @@ -289,6 +289,10 @@ extern void vPortCleanUpTCB ( void *pxTCB ); #define INCLUDE_eTaskGetState 1 #define configUSE_QUEUE_SETS 1 +#define configUSE_TICKLESS_IDLE CONFIG_FREERTOS_USE_TICKLESS_IDLE +#if configUSE_TICKLESS_IDLE +#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP CONFIG_FREERTOS_IDLE_TIME_BEFORE_SLEEP +#endif //configUSE_TICKLESS_IDLE #define configXT_BOARD 1 /* Board mode */ #define configXT_SIMULATOR 0 diff --git a/components/freertos/include/freertos/portmacro.h b/components/freertos/include/freertos/portmacro.h index 93d2071ba5..df5c071d17 100644 --- a/components/freertos/include/freertos/portmacro.h +++ b/components/freertos/include/freertos/portmacro.h @@ -365,9 +365,13 @@ typedef struct { #define PRIVILEGED_DATA #endif +extern void esp_vApplicationIdleHook( void ); +extern void esp_vApplicationWaitiHook( void ); void _xt_coproc_release(volatile void * coproc_sa_base); +bool vApplicationSleep( TickType_t xExpectedIdleTime ); +#define portSUPPRESS_TICKS_AND_SLEEP( idleTime ) vApplicationSleep( idleTime ) // porttrace #if configUSE_TRACE_FACILITY_2 diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 980699ffce..fe081975dd 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -2151,6 +2151,23 @@ void vTaskSuspendAll( void ) #if ( configUSE_TICKLESS_IDLE != 0 ) + static BaseType_t xHaveReadyTasks() + { + for (int i = tskIDLE_PRIORITY + 1; i < configMAX_PRIORITIES; ++i) + { + if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ i ] ) ) > 0 ) + { + return pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + return pdFALSE; + } + + static TickType_t prvGetExpectedIdleTime( void ) { TickType_t xReturn; @@ -2161,7 +2178,18 @@ void vTaskSuspendAll( void ) { xReturn = 0; } - else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 ) +#if portNUM_PROCESSORS > 1 + /* This function is called from Idle task; in single core case this + * means that no higher priority tasks are ready to run, and we can + * enter sleep. In SMP case, there might be ready tasks waiting for + * the other CPU, so need to check all ready lists. + */ + else if( xHaveReadyTasks() ) + { + xReturn = 0; + } +#endif // portNUM_PROCESSORS > 1 + else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > portNUM_PROCESSORS ) { /* There are other idle priority tasks in the ready state. If time slicing is used then the very next tick interrupt must be @@ -3405,7 +3433,6 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) #endif /* configUSE_IDLE_HOOK */ { /* Call the esp-idf hook system */ - extern void esp_vApplicationIdleHook( void ); esp_vApplicationIdleHook(); } @@ -3417,6 +3444,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) #if ( configUSE_TICKLESS_IDLE != 0 ) { TickType_t xExpectedIdleTime; + BaseType_t xEnteredSleep = pdFALSE; /* It is not desirable to suspend then resume the scheduler on each iteration of the idle task. Therefore, a preliminary @@ -3427,7 +3455,6 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) { -// vTaskSuspendAll(); taskENTER_CRITICAL(&xTaskQueueMutex); { /* Now the scheduler is suspended, the expected idle @@ -3439,7 +3466,7 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) { traceLOW_POWER_IDLE_BEGIN(); - portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); + xEnteredSleep = portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); traceLOW_POWER_IDLE_END(); } else @@ -3448,13 +3475,21 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters ) } } taskEXIT_CRITICAL(&xTaskQueueMutex); -// ( void ) xTaskResumeAll(); } else { mtCOVERAGE_TEST_MARKER(); } + /* It might be possible to enter tickless idle again, so skip + * the fallback sleep hook if tickless idle was successful + */ + if ( !xEnteredSleep ) + { + esp_vApplicationWaitiHook(); + } } + #else + esp_vApplicationWaitiHook(); #endif /* configUSE_TICKLESS_IDLE */ } } From 45d3b1f4b1b491f29bae7de316470bda6a929158 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 4 May 2018 01:59:54 +0800 Subject: [PATCH 117/187] docs: update information about automatic light sleep --- .../api-reference/system/power_management.rst | 17 ++++++++++++++--- docs/en/api-reference/system/sleep_modes.rst | 4 ++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/docs/en/api-reference/system/power_management.rst b/docs/en/api-reference/system/power_management.rst index 28263477d7..9ad1e16a99 100644 --- a/docs/en/api-reference/system/power_management.rst +++ b/docs/en/api-reference/system/power_management.rst @@ -20,11 +20,15 @@ Power management can be enabled at compile time, using :ref:`CONFIG_PM_ENABLE` o Enabling power management features comes at the cost of increased interrupt latency. Extra latency depends on a number of factors, among which are CPU frequency, single/dual core mode, whether frequency switch needs to be performed or not. Minimal extra latency is 0.2us (when CPU frequency is 240MHz, and frequency scaling is not enabled), maximum extra latency is 40us (when frequency scaling is enabled, and a switch from 40MHz to 80MHz is performed on interrupt entry). -Dynamic frequency scaling (DFS) can be enabled in the application by calling :cpp:func:`esp_pm_configure` function. Its argument is a structure defining frequency scaling settings (for ESP32, minimum and maximum CPU frequencies). Alternatively, :ref:`CONFIG_PM_DFS_INIT_AUTO` option can be enabled in menuconfig. If enabled, maximal CPU frequency is determined by :ref:`CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ` setting, and minimal CPU frequency is set to the XTAL frequency. +Dynamic frequency scaling (DFS) and automatic light sleep can be enabled in the application by calling :cpp:func:`esp_pm_configure` function. Its argument is a structure defining frequency scaling settings (for ESP32, minimum and maximum CPU frequencies). Alternatively, :ref:`CONFIG_PM_DFS_INIT_AUTO` option can be enabled in menuconfig. If enabled, maximal CPU frequency is determined by :ref:`CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ` setting, and minimal CPU frequency is set to the XTAL frequency. .. note:: - :cpp:func:`esp_pm_configure` function also has provisions for enabling automatic light sleep mode. However this feature is not fully supported yet, so `esp_pm_configure` will return an `ESP_ERR_NOT_SUPPORTED` if automatic light sleep is requested. + Automatic light sleep is based on FreeRTOS Tickless Idle functionality. :cpp:func:`esp_pm_configure` will return an `ESP_ERR_NOT_SUPPORTED` error if :ref:`CONFIG_FREERTOS_USE_TICKLESS_IDLE` option is not enabled in menuconfig, but automatic light sleep is requested. + +.. note:: + + In light sleep, peripherals are clock gated, and interrupts (from GPIOs and internal peripherals) will not be generated. Wakeup source described in :doc:`Sleep Modes ` documentation can be used to wake from light sleep state. For example, EXT0 and EXT1 wakeup source can be used to wake up from a GPIO. Power Management Locks ---------------------- @@ -42,7 +46,7 @@ In ESP32, three types of locks are supported: Requests APB frequency to be at the maximal supported value. For ESP32, this is 80 MHz. ``ESP_PM_NO_LIGHT_SLEEP`` - Prevents automatic light sleep from being used. Note: currently taking this lock has no effect, as automatic light sleep is never used. + Prevents automatic light sleep from being used. Power Management Algorithm for the ESP32 @@ -70,6 +74,13 @@ When dynamic frequency scaling is enabled, CPU frequency will be switched as fol 2. Otherwise, frequency will be switched to the minimal value set using :cpp:func:`esp_pm_configure` (usually, XTAL). +- When none of the locks are aquired, and light sleep is enabled in a call to :cpp:func:`esp_pm_configure`, the system will go into light sleep mode. The duration of light sleep will be determined by: + + - FreeRTOS tasks blocked with finite timeouts + - Timers registered with :doc:`High resolution timer ` APIs + + Light sleep will duration will be chosen to wake up before the nearest event (task being unblocked, or timer elapses). + Dynamic Frequency Scaling and Peripheral Drivers ------------------------------------------------ diff --git a/docs/en/api-reference/system/sleep_modes.rst b/docs/en/api-reference/system/sleep_modes.rst index 8b7a2dc2c5..bc0033abcb 100644 --- a/docs/en/api-reference/system/sleep_modes.rst +++ b/docs/en/api-reference/system/sleep_modes.rst @@ -19,9 +19,9 @@ Once wakeup sources are configured, application can enter sleep mode using :cpp: WiFi/BT and sleep modes ----------------------- -In deep sleep mode, wireless peripherals are powered down. Before entering sleep mode, applications must disable WiFi and BT using appropriate calls ( :cpp:func:`esp_bluedroid_disable`, :cpp:func:`esp_bt_controller_disable`, :cpp:func:`esp_wifi_stop`). +In deep sleep and light sleep modes, wireless peripherals are powered down. Before entering deep sleep or light sleep modes, applications must disable WiFi and BT using appropriate calls (:cpp:func:`esp_bluedroid_disable`, :cpp:func:`esp_bt_controller_disable`, :cpp:func:`esp_wifi_stop`). WiFi and BT connections will not be maintained in deep sleep or light sleep, even if these functions are not called. -WiFi can coexist with light sleep mode, allowing the chip to go into light sleep mode when there is no network activity, and waking up the chip from light sleep mode when required. However **APIs described in this section can not be used for that purpose**. :cpp:func:`esp_light_sleep_start` forces the chip to enter light sleep mode, regardless of whether WiFi is active or not. Automatic entry into light sleep mode, coordinated with WiFi driver, will be supported using a separate set of APIs. +If WiFi connection needs to be maintained, enable WiFi modem sleep, and enable automatic light sleep feature (see :doc:`Power Management APIs `). This will allow the system to wake up from sleep automatically when required by WiFi driver, thereby maintaining connection to the AP. Wakeup sources -------------- From 12230b7292ee75da3dedc9d38be8c1be6e3f65d0 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 4 May 2018 01:31:15 +0800 Subject: [PATCH 118/187] examples/wifi/power_save: enable tickless idle --- examples/wifi/power_save/main/power_save.c | 5 ++++- examples/wifi/power_save/sdkconfig.defaults | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/wifi/power_save/main/power_save.c b/examples/wifi/power_save/main/power_save.c index 507994b2cc..f40b898bcf 100644 --- a/examples/wifi/power_save/main/power_save.c +++ b/examples/wifi/power_save/main/power_save.c @@ -102,7 +102,10 @@ void app_main() rtc_clk_cpu_freq_from_mhz(CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ, &max_freq); esp_pm_config_esp32_t pm_config = { .max_cpu_freq = max_freq, - .min_cpu_freq = RTC_CPU_FREQ_XTAL + .min_cpu_freq = RTC_CPU_FREQ_XTAL, +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE + .light_sleep_enable = true +#endif }; ESP_ERROR_CHECK( esp_pm_configure(&pm_config) ); #endif // CONFIG_PM_ENABLE diff --git a/examples/wifi/power_save/sdkconfig.defaults b/examples/wifi/power_save/sdkconfig.defaults index 0c212b1df6..d39e7c8321 100644 --- a/examples/wifi/power_save/sdkconfig.defaults +++ b/examples/wifi/power_save/sdkconfig.defaults @@ -2,5 +2,7 @@ CONFIG_ESP32_DEFAULT_CPU_FREQ_80=y # Enable support for power management CONFIG_PM_ENABLE=y +# Enable tickless idle mode +CONFIG_FREERTOS_USE_TICKLESS_IDLE=y # Use RTC timer as reference CONFIG_PM_USE_RTC_TIMER_REF=y From 8b389419abf8b838346d170d6d7f1192422e717a Mon Sep 17 00:00:00 2001 From: Deng Xin Date: Fri, 11 May 2018 14:49:16 +0800 Subject: [PATCH 119/187] (wifi): Add more information about wifi config 1. Update libphy.a to v3900 2. Update librtc.a to v238 3. add scan_method, sort_method and threshold when invoke esp_wifi_get_config() 4. add rssi of each STA in softAP list 5. add country information in scan result 6. add noise floor in rx pkt Closes https://github.com/espressif/esp-idf/issues/1095 Closes https://github.com/espressif/esp-idf/issues/1723 Closes https://github.com/espressif/esp-idf/issues/1483 --- components/esp32/include/esp_wifi_types.h | 3 +++ components/esp32/lib | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/components/esp32/include/esp_wifi_types.h b/components/esp32/include/esp_wifi_types.h index 4f1c4cd71e..4797209969 100755 --- a/components/esp32/include/esp_wifi_types.h +++ b/components/esp32/include/esp_wifi_types.h @@ -49,6 +49,7 @@ typedef struct { char cc[3]; /**< country code string */ uint8_t schan; /**< start channel */ uint8_t nchan; /**< total channel number */ + int8_t max_tx_power; /**< maximum tx power */ wifi_country_policy_t policy; /**< country policy */ } wifi_country_t; @@ -155,6 +156,7 @@ typedef struct { uint32_t phy_lr:1; /**< bit: 3 flag to identify if low rate is enabled or not */ uint32_t wps:1; /**< bit: 4 flag to identify if WPS is supported or not */ uint32_t reserved:27; /**< bit: 5..31 reserved */ + wifi_country_t country; /**< country information of AP */ } wifi_ap_record_t; typedef enum { @@ -230,6 +232,7 @@ typedef union { /** @brief Description of STA associated with AP */ typedef struct { uint8_t mac[6]; /**< mac address */ + int8_t rssi; /**< current average rssi of sta connected */ uint32_t phy_11b:1; /**< bit: 0 flag to identify if 11b mode is enabled or not */ uint32_t phy_11g:1; /**< bit: 1 flag to identify if 11g mode is enabled or not */ uint32_t phy_11n:1; /**< bit: 2 flag to identify if 11n mode is enabled or not */ diff --git a/components/esp32/lib b/components/esp32/lib index ba4c4ce08e..04e656c303 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit ba4c4ce08e64ec848360afe25796fbdf45e24c9a +Subproject commit 04e656c303d129c479b5c019ea364e11c6f96f4d From 2aa9c15906b259dd188e88c144cb422eaa091b27 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Fri, 11 May 2018 15:56:53 +0200 Subject: [PATCH 120/187] VFS: allow to find free file descriptors & register them --- components/bt/bluedroid/api/esp_spp_api.c | 3 +- .../btc/profile/std/include/btc_spp.h | 4 +- .../bluedroid/btc/profile/std/spp/btc_spp.c | 111 +++++++----------- components/vfs/include/esp_vfs.h | 48 ++++++++ components/vfs/vfs.c | 52 ++++++++ 5 files changed, 147 insertions(+), 71 deletions(-) diff --git a/components/bt/bluedroid/api/esp_spp_api.c b/components/bt/bluedroid/api/esp_spp_api.c index 3fce8c1f8f..46878d659e 100644 --- a/components/bt/bluedroid/api/esp_spp_api.c +++ b/components/bt/bluedroid/api/esp_spp_api.c @@ -168,8 +168,7 @@ esp_err_t esp_spp_vfs_register() { ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED); - btc_spp_vfs_register(); - return ESP_OK; + return btc_spp_vfs_register(); } #endif ///defined BTC_SPP_INCLUDED && BTC_SPP_INCLUDED == TRUE diff --git a/components/bt/bluedroid/btc/profile/std/include/btc_spp.h b/components/bt/bluedroid/btc/profile/std/include/btc_spp.h index 69001d507c..a8b409e0af 100644 --- a/components/bt/bluedroid/btc/profile/std/include/btc_spp.h +++ b/components/bt/bluedroid/btc/profile/std/include/btc_spp.h @@ -87,6 +87,6 @@ void btc_spp_call_handler(btc_msg_t *msg); void btc_spp_cb_handler(btc_msg_t *msg); void btc_spp_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src); -void btc_spp_vfs_register(void); +esp_err_t btc_spp_vfs_register(void); #endif ///defined BTC_SPP_INCLUDED && BTC_SPP_INCLUDED == TRUE -#endif ///__BTC_SPP_H__ \ No newline at end of file +#endif ///__BTC_SPP_H__ diff --git a/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c b/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c index ef3287ce89..b28d8cf58c 100644 --- a/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c +++ b/components/bt/bluedroid/btc/profile/std/spp/btc_spp.c @@ -29,12 +29,6 @@ #include #include "esp_vfs.h" #include "esp_vfs_dev.h" -#include "lwip/opt.h" // just for LWIP_SOCKET_OFFSET - -/** - * BTC_SPP_FDS is the number of file descriptors this VFS driver registers - */ -#define BTC_SPP_FDS 32 #if (defined BTC_SPP_INCLUDED && BTC_SPP_INCLUDED == TRUE) @@ -65,10 +59,8 @@ static struct spp_local_param_t { spp_slot_t *spp_slots[BTA_JV_MAX_RFC_SR_SESSION + 1]; uint32_t spp_slot_id; esp_spp_mode_t spp_mode; - int spp_max_fd; - int spp_min_fd; - int spp_fd; osi_mutex_t spp_slot_mutex; + esp_vfs_id_t spp_vfs_id; } spp_local_param; static void spp_osi_free(void *p) @@ -76,25 +68,7 @@ static void spp_osi_free(void *p) osi_free(p); } -static int find_free_fd() -{ - spp_local_param.spp_fd = 1; - if (spp_local_param.spp_fd < spp_local_param.spp_min_fd || spp_local_param.spp_fd > spp_local_param.spp_max_fd){ - spp_local_param.spp_fd = spp_local_param.spp_min_fd; - } - for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) { - if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->fd == spp_local_param.spp_fd) { - i = 1; - spp_local_param.spp_fd++; - if (spp_local_param.spp_fd < spp_local_param.spp_min_fd || spp_local_param.spp_fd > spp_local_param.spp_max_fd){ - spp_local_param.spp_fd = spp_local_param.spp_min_fd; - } - } - } - return spp_local_param.spp_fd++; -} - -static spp_slot_t *malloc_spp_slot(void) +static spp_slot_t *spp_malloc_slot(void) { if (++spp_local_param.spp_slot_id == 0) { spp_local_param.spp_slot_id = 1; @@ -112,7 +86,10 @@ static spp_slot_t *malloc_spp_slot(void) spp_local_param.spp_slots[i]->list = list_new(spp_osi_free); if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) { spp_local_param.spp_slots[i]->incoming_list = list_new(spp_osi_free); - spp_local_param.spp_slots[i]->fd = find_free_fd(); + if (esp_vfs_register_fd(spp_local_param.spp_vfs_id, &spp_local_param.spp_slots[i]->fd) != ESP_OK) { + osi_free(spp_local_param.spp_slots[i]); + return NULL; + } spp_local_param.spp_slots[i]->ringbuf_read = xRingbufferCreate(ESP_SPP_RINGBUF_SIZE, RINGBUF_TYPE_BYTEBUF); spp_local_param.spp_slots[i]->ringbuf_write = xRingbufferCreate(ESP_SPP_RINGBUF_SIZE, RINGBUF_TYPE_BYTEBUF); } @@ -122,7 +99,7 @@ static spp_slot_t *malloc_spp_slot(void) return NULL; } -static spp_slot_t *find_slot_by_id(uint32_t id) +static spp_slot_t *spp_find_slot_by_id(uint32_t id) { for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) { if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->id == id) { @@ -132,7 +109,7 @@ static spp_slot_t *find_slot_by_id(uint32_t id) return NULL; } -static spp_slot_t *find_slot_by_handle(uint32_t handle) +static spp_slot_t *spp_find_slot_by_handle(uint32_t handle) { for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) { if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->rfc_handle == handle) { @@ -142,7 +119,7 @@ static spp_slot_t *find_slot_by_handle(uint32_t handle) return NULL; } -static spp_slot_t *find_slot_by_fd(int fd) +static spp_slot_t *spp_find_slot_by_fd(int fd) { for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) { if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->fd == fd) { @@ -152,7 +129,7 @@ static spp_slot_t *find_slot_by_fd(int fd) return NULL; } -static void free_spp_slot(spp_slot_t *slot) +static void spp_free_slot(spp_slot_t *slot) { if (!slot) { return; @@ -160,6 +137,7 @@ static void free_spp_slot(spp_slot_t *slot) spp_local_param.spp_slots[slot->serial] = NULL; list_free(slot->list); if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) { + (void) esp_vfs_unregister_fd(spp_local_param.spp_vfs_id, slot->fd); list_free(slot->incoming_list); vRingbufferDelete(slot->ringbuf_read); vRingbufferDelete(slot->ringbuf_write); @@ -202,12 +180,12 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); switch (event) { case BTA_JV_RFCOMM_SRV_OPEN_EVT: - slot = find_slot_by_id(id); + slot = spp_find_slot_by_id(id); if (!slot) { BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); break; } - slot_new = malloc_spp_slot(); + slot_new = spp_malloc_slot(); if (!slot_new) { BTC_TRACE_ERROR("%s unable to malloc RFCOMM slot!", __func__); break; @@ -228,7 +206,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(p_data->rfc_srv_open.handle); break; case BTA_JV_RFCOMM_OPEN_EVT: - slot = find_slot_by_id(id); + slot = spp_find_slot_by_id(id); if (!slot) { BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); break; @@ -238,7 +216,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(p_data->rfc_open.handle); break; case BTA_JV_RFCOMM_CLOSE_EVT: - slot = find_slot_by_id(id); + slot = spp_find_slot_by_id(id); if (!slot) { BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); break; @@ -246,7 +224,7 @@ static void *btc_spp_rfcomm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *u if (slot->connected) { BTA_JvRfcommClose(slot->rfc_handle, (void *)slot->id); } - free_spp_slot(slot); + spp_free_slot(slot); p_data->rfc_close.status = BTA_JV_SUCCESS; break; case BTA_JV_RFCOMM_DATA_IND_EVT: @@ -279,7 +257,7 @@ static void btc_spp_dm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d switch (event) { case BTA_JV_GET_SCN_EVT: osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - slot = find_slot_by_id(id); + slot = spp_find_slot_by_id(id); if (!slot) { BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -288,7 +266,7 @@ static void btc_spp_dm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d if (p_data->scn == 0) { BTC_TRACE_ERROR("%s unable to get scn, start server fail!", __func__); btc_create_server_fail_cb(); - free_spp_slot(slot); + spp_free_slot(slot); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); break; } @@ -299,7 +277,7 @@ static void btc_spp_dm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d break; case BTA_JV_CREATE_RECORD_EVT: osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - slot = find_slot_by_id(id); + slot = spp_find_slot_by_id(id); if (!slot) { BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -313,7 +291,7 @@ static void btc_spp_dm_inter_cb(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_d BTC_TRACE_ERROR("%s unable to create record, start server fail!", __func__); btc_create_server_fail_cb(); BTA_JvFreeChannel(slot->scn, BTA_JV_CONN_TYPE_RFCOMM); - free_spp_slot(slot); + spp_free_slot(slot); } osi_mutex_unlock(&spp_local_param.spp_slot_mutex); break; @@ -347,7 +325,7 @@ static void btc_spp_uninit(void) for (size_t i = 1; i <= BTA_JV_MAX_RFC_SR_SESSION; i++) { if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->connected) { BTA_JvRfcommClose(spp_local_param.spp_slots[i]->rfc_handle, (void *)spp_local_param.spp_slots[i]->id); - free_spp_slot(spp_local_param.spp_slots[i]); + spp_free_slot(spp_local_param.spp_slots[i]); spp_local_param.spp_slots[i] = NULL; } } @@ -356,7 +334,7 @@ static void btc_spp_uninit(void) BTA_JvRfcommStopServer(spp_local_param.spp_slots[i]->sdp_handle, (void *)spp_local_param.spp_slots[i]->id); BTA_JvDeleteRecord(spp_local_param.spp_slots[i]->sdp_handle); BTA_JvFreeChannel(spp_local_param.spp_slots[i]->scn, BTA_JV_CONN_TYPE_RFCOMM); - free_spp_slot(spp_local_param.spp_slots[i]); + spp_free_slot(spp_local_param.spp_slots[i]); spp_local_param.spp_slots[i] = NULL; } } @@ -374,7 +352,7 @@ static void btc_spp_start_discovery(btc_spp_args_t *arg) static void btc_spp_connect(btc_spp_args_t *arg) { osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - spp_slot_t *slot = malloc_spp_slot(); + spp_slot_t *slot = spp_malloc_slot(); if (!slot) { BTC_TRACE_ERROR("%s unable to malloc RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -392,7 +370,7 @@ static void btc_spp_connect(btc_spp_args_t *arg) static void btc_spp_disconnect(btc_spp_args_t *arg) { osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - spp_slot_t *slot = find_slot_by_handle(arg->disconnect.handle); + spp_slot_t *slot = spp_find_slot_by_handle(arg->disconnect.handle); if (!slot) { BTC_TRACE_ERROR("%s unable to find RFCOMM slot! disconnect fail!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -400,14 +378,14 @@ static void btc_spp_disconnect(btc_spp_args_t *arg) } BTA_JvRfcommClose(arg->disconnect.handle, (void *)slot->id); btc_disconnect_cb(slot->rfc_handle); - free_spp_slot(slot); + spp_free_slot(slot); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); } static void btc_spp_start_srv(btc_spp_args_t *arg) { osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - spp_slot_t *slot = malloc_spp_slot(); + spp_slot_t *slot = spp_malloc_slot(); if (!slot) { BTC_TRACE_ERROR("%s unable to malloc RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -426,7 +404,7 @@ static void btc_spp_start_srv(btc_spp_args_t *arg) static void btc_spp_write(btc_spp_args_t *arg) { osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - spp_slot_t *slot = find_slot_by_handle(arg->write.handle); + spp_slot_t *slot = spp_find_slot_by_handle(arg->write.handle); if (!slot) { BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -555,7 +533,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) case BTA_JV_RFCOMM_OPEN_EVT: if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) { osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - slot = find_slot_by_handle(p_data->rfc_open.handle); + slot = spp_find_slot_by_handle(p_data->rfc_open.handle); if (!slot) { BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -579,7 +557,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) case BTA_JV_RFCOMM_SRV_OPEN_EVT: if (spp_local_param.spp_mode == ESP_SPP_MODE_VFS) { osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - slot = find_slot_by_handle(p_data->rfc_srv_open.handle); + slot = spp_find_slot_by_handle(p_data->rfc_srv_open.handle); if (!slot) { BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -596,7 +574,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) break; case BTA_JV_RFCOMM_WRITE_EVT: osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - slot = find_slot_by_handle(p_data->rfc_write.handle); + slot = spp_find_slot_by_handle(p_data->rfc_write.handle); if (!slot) { BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -648,7 +626,7 @@ void btc_spp_cb_handler(btc_msg_t *msg) btc_spp_cb_to_app(ESP_SPP_CONG_EVT, ¶m); } else { osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - slot = find_slot_by_handle(p_data->rfc_cong.handle); + slot = spp_find_slot_by_handle(p_data->rfc_cong.handle); if (!slot) { BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -721,7 +699,7 @@ int bta_co_rfc_data_incoming(void *user_data, BT_HDR *p_buf) uint32_t id = (uintptr_t)user_data; osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - spp_slot_t *slot = find_slot_by_id(id); + spp_slot_t *slot = spp_find_slot_by_id(id); if (!slot) { BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -767,7 +745,7 @@ int bta_co_rfc_data_outgoing(void *user_data, uint8_t *buf, uint16_t size) static ssize_t spp_vfs_write(int fd, const void * data, size_t size) { osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - spp_slot_t *slot = find_slot_by_fd(fd); + spp_slot_t *slot = spp_find_slot_by_fd(fd); if (!slot) { BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -786,7 +764,7 @@ static ssize_t spp_vfs_write(int fd, const void * data, size_t size) static int spp_vfs_close(int fd) { osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - spp_slot_t *slot = find_slot_by_fd(fd); + spp_slot_t *slot = spp_find_slot_by_fd(fd); if (!slot) { BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -814,7 +792,7 @@ static bool incoming_list_2_ringbuf_read(spp_slot_t *slot) static ssize_t spp_vfs_read(int fd, void * dst, size_t size) { osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT); - spp_slot_t *slot = find_slot_by_fd(fd); + spp_slot_t *slot = spp_find_slot_by_fd(fd); if (!slot) { BTC_TRACE_ERROR("%s unable to find RFCOMM slot!", __func__); osi_mutex_unlock(&spp_local_param.spp_slot_mutex); @@ -831,7 +809,7 @@ static ssize_t spp_vfs_read(int fd, void * dst, size_t size) return item_size; } -void btc_spp_vfs_register() +esp_err_t btc_spp_vfs_register() { esp_vfs_t vfs = { .flags = ESP_VFS_FLAG_DEFAULT, @@ -842,15 +820,14 @@ void btc_spp_vfs_register() .read = spp_vfs_read, .fcntl = NULL }; - // File descriptors from LWIP_SOCKET_OFFSET to MAX_FDS-1 are registered - // for sockets. So here we register from (LWIP_SOCKET_OFFSET - BTC_SPP_FDS) - // to (LWIP_SOCKET_OFFSET-1) leaving unregistered from 0 to - // .(LWIP_SOCKET_OFFSET - BTC_SPP_FDS - 1). - spp_local_param.spp_min_fd = LWIP_SOCKET_OFFSET - BTC_SPP_FDS; - assert(spp_local_param.spp_min_fd >= 0); //TODO return error instead - spp_local_param.spp_max_fd = LWIP_SOCKET_OFFSET; - ESP_ERROR_CHECK(esp_vfs_register_fd_range(&vfs, NULL, spp_local_param.spp_min_fd, spp_local_param.spp_max_fd));//TODO return error if fails - spp_local_param.spp_fd = spp_local_param.spp_min_fd; + + // No FD range is registered here: spp_vfs_id is used to register/unregister + // file descriptors + if (esp_vfs_register_with_id(&vfs, NULL, &spp_local_param.spp_vfs_id) != ESP_OK) { + return ESP_FAIL; + } + + return ESP_OK; } #endif ///defined BTC_SPP_INCLUDED && BTC_SPP_INCLUDED == TRUE diff --git a/components/vfs/include/esp_vfs.h b/components/vfs/include/esp_vfs.h index 202be24859..ca667a76fc 100644 --- a/components/vfs/include/esp_vfs.h +++ b/components/vfs/include/esp_vfs.h @@ -55,6 +55,11 @@ extern "C" { */ #define ESP_VFS_FLAG_CONTEXT_PTR 1 +/* + * @brief VFS identificator used for esp_vfs_register_with_id() + */ +typedef int esp_vfs_id_t; + /** * @brief VFS definition structure * @@ -209,6 +214,24 @@ esp_err_t esp_vfs_register(const char* base_path, const esp_vfs_t* vfs, void* ct */ esp_err_t esp_vfs_register_fd_range(const esp_vfs_t *vfs, void *ctx, int min_fd, int max_fd); +/** + * Special case function for registering a VFS that uses a method other than + * open() to open new file descriptors. In comparison with + * esp_vfs_register_fd_range, this function doesn't pre-registers an interval + * of file descriptors. File descriptors can be registered later, by using + * esp_vfs_register_fd. + * + * @param vfs Pointer to esp_vfs_t. Meaning is the same as for esp_vfs_register(). + * @param ctx Pointer to context structure. Meaning is the same as for esp_vfs_register(). + * @param vfs_id Here will be written the VFS ID which can be passed to + * esp_vfs_register_fd for registering file descriptors. + * + * @return ESP_OK if successful, ESP_ERR_NO_MEM if too many VFSes are + * registered, ESP_ERR_INVALID_ARG if the file descriptor boundaries + * are incorrect. + */ +esp_err_t esp_vfs_register_with_id(const esp_vfs_t *vfs, void *ctx, esp_vfs_id_t *vfs_id); + /** * Unregister a virtual filesystem for given path prefix * @@ -218,6 +241,31 @@ esp_err_t esp_vfs_register_fd_range(const esp_vfs_t *vfs, void *ctx, int min_fd, */ esp_err_t esp_vfs_unregister(const char* base_path); +/** + * Special function for registering another file descriptor for a VFS registered + * by esp_vfs_register_with_id. + * + * @param vfs_id VFS identificator returned by esp_vfs_register_with_id. + * @param fd The registered file descriptor will be written to this address. + * + * @return ESP_OK if the registration is successful, + * ESP_ERR_NO_MEM if too many file descriptors are registered, + * ESP_ERR_INVALID_ARG if the arguments are incorrect. + */ +esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int *fd); + +/** + * Special function for unregistering a file descriptor belonging to a VFS + * registered by esp_vfs_register_with_id. + * + * @param vfs_id VFS identificator returned by esp_vfs_register_with_id. + * @param fd File descriptor which should be unregistered. + * + * @return ESP_OK if the registration is successful, + * ESP_ERR_INVALID_ARG if the arguments are incorrect. + */ +esp_err_t esp_vfs_unregister_fd(esp_vfs_id_t vfs_id, int fd); + /** * These functions are to be used in newlib syscall table. They will be called by * newlib when it needs to use any of the syscalls. diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index d7ca283ec3..e8cc5deee2 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -138,6 +138,16 @@ esp_err_t esp_vfs_register_fd_range(const esp_vfs_t *vfs, void *ctx, int min_fd, return ret; } +esp_err_t esp_vfs_register_with_id(const esp_vfs_t *vfs, void *ctx, esp_vfs_id_t *vfs_id) +{ + if (vfs_id == NULL) { + return ESP_ERR_INVALID_ARG; + } + + *vfs_id = -1; + return esp_vfs_register_common("", LEN_PATH_PREFIX_IGNORED, vfs, ctx, vfs_id); +} + esp_err_t esp_vfs_unregister(const char* base_path) { for (size_t i = 0; i < s_vfs_count; ++i) { @@ -164,6 +174,48 @@ esp_err_t esp_vfs_unregister(const char* base_path) return ESP_ERR_INVALID_STATE; } +esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int *fd) +{ + if (vfs_id < 0 || vfs_id >= s_vfs_count || fd == NULL) { + return ESP_ERR_INVALID_ARG; + } + + esp_err_t ret = ESP_ERR_NO_MEM; + _lock_acquire(&s_fd_table_lock); + for (int i = 0; i < MAX_FDS; ++i) { + if (s_fd_table[i].vfs_index == -1) { + s_fd_table[i].permanent = true; + s_fd_table[i].vfs_index = vfs_id; + s_fd_table[i].local_fd = i; + *fd = i; + ret = ESP_OK; + break; + } + } + _lock_release(&s_fd_table_lock); + + return ret; +} + +esp_err_t esp_vfs_unregister_fd(esp_vfs_id_t vfs_id, int fd) +{ + esp_err_t ret = ESP_ERR_INVALID_ARG; + + if (vfs_id < 0 || vfs_id >= s_vfs_count || fd < 0 || fd >= MAX_FDS) { + return ret; + } + + _lock_acquire(&s_fd_table_lock); + fd_table_t *item = s_fd_table + fd; + if (item->permanent == true && item->vfs_index == vfs_id && item->local_fd == fd) { + *item = FD_TABLE_ENTRY_UNUSED; + ret = ESP_OK; + } + _lock_release(&s_fd_table_lock); + + return ret; +} + static inline const vfs_entry_t *get_vfs_for_index(int index) { if (index < 0 || index >= s_vfs_count) { From 18e83bcd53f2aacd667959af755f8a443fb2a57e Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Thu, 3 May 2018 10:41:10 +0200 Subject: [PATCH 121/187] Allow VFS file descriptors in select() --- .../driver/include/driver/uart_select.h | 49 +++ components/driver/uart.c | 36 +++ components/lwip/include/lwip/lwip/sockets.h | 5 + components/lwip/include/lwip/lwip/sys.h | 4 + components/lwip/port/freertos/sys_arch.c | 9 + components/lwip/port/vfs_lwip.c | 45 ++- components/newlib/include/sys/select.h | 31 ++ components/newlib/select.c | 21 ++ components/vfs/README.rst | 29 ++ components/vfs/include/esp_vfs.h | 56 ++++ components/vfs/test/test_vfs_select.c | 284 ++++++++++++++++++ components/vfs/vfs.c | 230 ++++++++++++++ components/vfs/vfs_uart.c | 113 +++++++ docs/en/api-reference/peripherals/uart.rst | 2 + examples/peripherals/uart_select/Makefile | 8 + examples/peripherals/uart_select/README.md | 13 + .../peripherals/uart_select/main/component.mk | 3 + .../main/uart_select_example_main.c | 90 ++++++ .../main/udp_multicast_example_main.c | 2 +- examples/system/select/Makefile | 9 + examples/system/select/README.md | 11 + examples/system/select/main/component.mk | 5 + examples/system/select/main/select_example.c | 207 +++++++++++++ tools/unit-test-app/main/app_main.c | 5 + 24 files changed, 1250 insertions(+), 17 deletions(-) create mode 100644 components/driver/include/driver/uart_select.h create mode 100644 components/newlib/include/sys/select.h create mode 100644 components/newlib/select.c create mode 100644 components/vfs/test/test_vfs_select.c create mode 100644 examples/peripherals/uart_select/Makefile create mode 100644 examples/peripherals/uart_select/README.md create mode 100644 examples/peripherals/uart_select/main/component.mk create mode 100644 examples/peripherals/uart_select/main/uart_select_example_main.c create mode 100644 examples/system/select/Makefile create mode 100644 examples/system/select/README.md create mode 100644 examples/system/select/main/component.mk create mode 100644 examples/system/select/main/select_example.c diff --git a/components/driver/include/driver/uart_select.h b/components/driver/include/driver/uart_select.h new file mode 100644 index 0000000000..24f06c1de6 --- /dev/null +++ b/components/driver/include/driver/uart_select.h @@ -0,0 +1,49 @@ + +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _UART_SELECT_H_ +#define _UART_SELECT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "driver/uart.h" + +typedef enum { + UART_SELECT_READ_NOTIF, + UART_SELECT_WRITE_NOTIF, + UART_SELECT_ERROR_NOTIF, +} uart_select_notif_t; + +typedef void (*uart_select_notif_callback_t)(uart_port_t uart_num, uart_select_notif_t uart_select_notif, BaseType_t *task_woken); + +/** + * @brief Set notification callback function for select() events + * @param uart_num UART port number + * @param uart_select_notif_callback callback function + */ +void uart_set_select_notif_callback(uart_port_t uart_num, uart_select_notif_callback_t uart_select_notif_callback); + +/** + * @brief Get mutex guarding select() notifications + */ +portMUX_TYPE *uart_get_selectlock(); + +#ifdef __cplusplus +} +#endif + +#endif //_UART_SELECT_H_ diff --git a/components/driver/uart.c b/components/driver/uart.c index 9cec59bf08..e32023047e 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -29,6 +29,7 @@ #include "soc/uart_struct.h" #include "driver/uart.h" #include "driver/gpio.h" +#include "driver/uart_select.h" #define XOFF (char)0x13 #define XON (char)0x11 @@ -100,12 +101,14 @@ typedef struct { uint8_t tx_brk_flg; /*!< Flag to indicate to send a break signal in the end of the item sending procedure */ uint8_t tx_brk_len; /*!< TX break signal cycle length/number */ uint8_t tx_waiting_brk; /*!< Flag to indicate that TX FIFO is ready to send break signal after FIFO is empty, do not push data into TX FIFO right now.*/ + uart_select_notif_callback_t uart_select_notif_callback; /*!< Notification about select() events */ } uart_obj_t; static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0}; /* DRAM_ATTR is required to avoid UART array placed in flash, due to accessed from ISR */ static DRAM_ATTR uart_dev_t* const UART[UART_NUM_MAX] = {&UART0, &UART1, &UART2}; static portMUX_TYPE uart_spinlock[UART_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED}; +static portMUX_TYPE uart_selectlock = portMUX_INITIALIZER_UNLOCKED; esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit) { @@ -835,6 +838,11 @@ static void uart_rx_intr_handler_default(void *param) uart_clear_intr_status(uart_num, UART_RXFIFO_TOUT_INT_CLR_M | UART_RXFIFO_FULL_INT_CLR_M); uart_event.type = UART_DATA; uart_event.size = rx_fifo_len; + UART_ENTER_CRITICAL_ISR(&uart_selectlock); + if (p_uart->uart_select_notif_callback) { + p_uart->uart_select_notif_callback(uart_num, UART_SELECT_READ_NOTIF, &HPTaskAwoken); + } + UART_EXIT_CRITICAL_ISR(&uart_selectlock); } p_uart->rx_stash_len = rx_fifo_len; //If we fail to push data to ring buffer, we will have to stash the data, and send next time. @@ -893,15 +901,30 @@ static void uart_rx_intr_handler_default(void *param) uart_reg->int_clr.rxfifo_ovf = 1; UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); uart_event.type = UART_FIFO_OVF; + UART_ENTER_CRITICAL_ISR(&uart_selectlock); + if (p_uart->uart_select_notif_callback) { + p_uart->uart_select_notif_callback(uart_num, UART_SELECT_ERROR_NOTIF, &HPTaskAwoken); + } + UART_EXIT_CRITICAL_ISR(&uart_selectlock); } else if(uart_intr_status & UART_BRK_DET_INT_ST_M) { uart_reg->int_clr.brk_det = 1; uart_event.type = UART_BREAK; } else if(uart_intr_status & UART_FRM_ERR_INT_ST_M) { uart_reg->int_clr.frm_err = 1; uart_event.type = UART_FRAME_ERR; + UART_ENTER_CRITICAL_ISR(&uart_selectlock); + if (p_uart->uart_select_notif_callback) { + p_uart->uart_select_notif_callback(uart_num, UART_SELECT_ERROR_NOTIF, &HPTaskAwoken); + } + UART_EXIT_CRITICAL_ISR(&uart_selectlock); } else if(uart_intr_status & UART_PARITY_ERR_INT_ST_M) { uart_reg->int_clr.parity_err = 1; uart_event.type = UART_PARITY_ERR; + UART_ENTER_CRITICAL_ISR(&uart_selectlock); + if (p_uart->uart_select_notif_callback) { + p_uart->uart_select_notif_callback(uart_num, UART_SELECT_ERROR_NOTIF, &HPTaskAwoken); + } + UART_EXIT_CRITICAL_ISR(&uart_selectlock); } else if(uart_intr_status & UART_TX_BRK_DONE_INT_ST_M) { UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); uart_reg->conf0.txd_brk = 0; @@ -1259,6 +1282,7 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b p_uart_obj[uart_num]->tx_ring_buf = NULL; p_uart_obj[uart_num]->tx_buf_size = 0; } + p_uart_obj[uart_num]->uart_select_notif_callback = NULL; } else { ESP_LOGE(UART_TAG, "UART driver already installed"); return ESP_FAIL; @@ -1346,3 +1370,15 @@ esp_err_t uart_driver_delete(uart_port_t uart_num) } return ESP_OK; } + +void uart_set_select_notif_callback(uart_port_t uart_num, uart_select_notif_callback_t uart_select_notif_callback) +{ + if (uart_num < UART_NUM_MAX && p_uart_obj[uart_num]) { + p_uart_obj[uart_num]->uart_select_notif_callback = (uart_select_notif_callback_t) uart_select_notif_callback; + } +} + +portMUX_TYPE *uart_get_selectlock() +{ + return &uart_selectlock; +} diff --git a/components/lwip/include/lwip/lwip/sockets.h b/components/lwip/include/lwip/lwip/sockets.h index c3cadd8730..5978b38c49 100755 --- a/components/lwip/include/lwip/lwip/sockets.h +++ b/components/lwip/include/lwip/lwip/sockets.h @@ -38,6 +38,7 @@ #if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ +#include #include /* for size_t */ #include /* for FD_ZERO */ @@ -589,8 +590,10 @@ static inline int sendto(int s,const void *dataptr,size_t size,int flags,const s { return lwip_sendto_r(s,dataptr,size,flags,to,tolen); } static inline int socket(int domain,int type,int protocol) { return lwip_socket(domain,type,protocol); } +#ifndef ESP_PLATFORM static inline int select(int maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,struct timeval *timeout) { return lwip_select(maxfdp1,readset,writeset,exceptset,timeout); } +#endif /* ESP_PLATFORM */ static inline int ioctlsocket(int s,long cmd,void *argp) { return lwip_ioctl_r(s,cmd,argp); } @@ -643,8 +646,10 @@ static inline int sendto(int s,const void *dataptr,size_t size,int flags,const s { return lwip_sendto(s,dataptr,size,flags,to,tolen); } static inline int socket(int domain,int type,int protocol) { return lwip_socket(domain,type,protocol); } +#ifndef ESP_PLATFORM static inline int select(int maxfdp1,fd_set t*readset,fd_set *writeset,fd_set *exceptset,struct timeval *timeout) { return lwip_select(maxfdp1,readset,writeset,exceptset,timeout); } +#endif /* ESP_PLATFORM */ static inline int ioctlsocket(int s,long cmd,void *argp) { return lwip_ioctl(s,cmd,argp); } diff --git a/components/lwip/include/lwip/lwip/sys.h b/components/lwip/include/lwip/lwip/sys.h index 86d0f3b336..67729e3b73 100755 --- a/components/lwip/include/lwip/lwip/sys.h +++ b/components/lwip/include/lwip/lwip/sys.h @@ -148,6 +148,10 @@ err_t sys_sem_new(sys_sem_t *sem, u8_t count); /** Signals a semaphore * @param sem the semaphore to signal */ void sys_sem_signal(sys_sem_t *sem); +/** Signals a semaphore (ISR version) + * @param sem the semaphore to signal + * @return non-zero if a higher priority task has been woken */ +int sys_sem_signal_isr(sys_sem_t *sem); /** Wait for a semaphore for the specified timeout * @param sem the semaphore to wait for * @param timeout timeout in milliseconds to wait (0 = wait forever) diff --git a/components/lwip/port/freertos/sys_arch.c b/components/lwip/port/freertos/sys_arch.c index 77eaef0a11..2c56969ade 100755 --- a/components/lwip/port/freertos/sys_arch.c +++ b/components/lwip/port/freertos/sys_arch.c @@ -133,6 +133,15 @@ sys_sem_signal(sys_sem_t *sem) xSemaphoreGive(*sem); } +/*-----------------------------------------------------------------------------------*/ +// Signals a semaphore (from ISR) +int sys_sem_signal_isr(sys_sem_t *sem) +{ + BaseType_t woken = pdFALSE; + xSemaphoreGiveFromISR(*sem, &woken); + return woken == pdTRUE; +} + /*-----------------------------------------------------------------------------------*/ /* Blocks the thread while waiting for the semaphore to be diff --git a/components/lwip/port/vfs_lwip.c b/components/lwip/port/vfs_lwip.c index 2ce639e4e4..54d71912bb 100644 --- a/components/lwip/port/vfs_lwip.c +++ b/components/lwip/port/vfs_lwip.c @@ -24,15 +24,31 @@ #include "soc/uart_struct.h" #include "lwip/sockets.h" #include "sdkconfig.h" - -/* Non-LWIP file descriptors are from 0 to (LWIP_SOCKET_OFFSET-1). - * LWIP file descriptors are from LWIP_SOCKET_OFFSET to FD_SETSIZE-1. -*/ +#include "lwip/sys.h" _Static_assert(MAX_FDS >= CONFIG_LWIP_MAX_SOCKETS, "MAX_FDS < CONFIG_LWIP_MAX_SOCKETS"); -static int lwip_fcntl_r_wrapper(int fd, int cmd, va_list args); -static int lwip_ioctl_r_wrapper(int fd, int cmd, va_list args); +static void lwip_stop_socket_select() +{ + sys_sem_signal(sys_thread_sem_get()); //socket_select will return +} + +static void lwip_stop_socket_select_isr(BaseType_t *woken) +{ + if (sys_sem_signal_isr(sys_thread_sem_get()) && woken) { + *woken = pdTRUE; + } +} + +static int lwip_fcntl_r_wrapper(int fd, int cmd, va_list args) +{ + return lwip_fcntl_r(fd, cmd, va_arg(args, int)); +} + +static int lwip_ioctl_r_wrapper(int fd, int cmd, va_list args) +{ + return lwip_ioctl_r(fd, cmd, va_arg(args, void *)); +} void esp_vfs_lwip_sockets_register() { @@ -45,17 +61,14 @@ void esp_vfs_lwip_sockets_register() .read = &lwip_read_r, .fcntl = &lwip_fcntl_r_wrapper, .ioctl = &lwip_ioctl_r_wrapper, + .socket_select = &lwip_select, + .stop_socket_select = &lwip_stop_socket_select, + .stop_socket_select_isr = &lwip_stop_socket_select_isr, }; + /* Non-LWIP file descriptors are from 0 to (LWIP_SOCKET_OFFSET-1). LWIP + * file descriptors are registered from LWIP_SOCKET_OFFSET to + * MAX_FDS-1. + */ ESP_ERROR_CHECK(esp_vfs_register_fd_range(&vfs, NULL, LWIP_SOCKET_OFFSET, MAX_FDS)); } - -static int lwip_fcntl_r_wrapper(int fd, int cmd, va_list args) -{ - return lwip_fcntl_r(fd, cmd, va_arg(args, int)); -} - -static int lwip_ioctl_r_wrapper(int fd, int cmd, va_list args) -{ - return lwip_ioctl_r(fd, cmd, va_arg(args, void *)); -} diff --git a/components/newlib/include/sys/select.h b/components/newlib/include/sys/select.h new file mode 100644 index 0000000000..199d48144d --- /dev/null +++ b/components/newlib/include/sys/select.h @@ -0,0 +1,31 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __ESP_SYS_SELECT_H__ +#define __ESP_SYS_SELECT_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif //__ESP_SYS_SELECT_H__ diff --git a/components/newlib/select.c b/components/newlib/select.c new file mode 100644 index 0000000000..dc945eafb4 --- /dev/null +++ b/components/newlib/select.c @@ -0,0 +1,21 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "esp_vfs.h" + +int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout) +{ + return esp_vfs_select(nfds, readfds, writefds, errorfds, timeout); +} diff --git a/components/vfs/README.rst b/components/vfs/README.rst index 7a25ca542d..4644689a93 100644 --- a/components/vfs/README.rst +++ b/components/vfs/README.rst @@ -64,6 +64,35 @@ Case 2: API functions are declared with an extra context pointer (FS driver supp myfs_t* myfs_inst2 = myfs_mount(partition2->offset, partition2->size); ESP_ERROR_CHECK(esp_vfs_register("/data2", &myfs, myfs_inst2)); +Synchronous input/output multiplexing +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you want to use synchronous input/output multiplexing by :cpp:func:`select` +then you need to register the VFS with :cpp:func:`start_select` and +:cpp:func:`end_select` functions similarly to the following example: + +.. highlight:: c + +:: + + // In definition of esp_vfs_t: + .start_select = &uart_start_select, + .end_select = &uart_end_select, + // ... other members initialized + +:cpp:func:`start_select` is called for setting up the environment for +detection of read/write/error conditions on file descriptors belonging to the +given VFS. :cpp:func:`end_select` is called to stop/deinitialize/free the +environment which was setup by :cpp:func:`start_select`. Please refer to the +reference implementation for the UART peripheral in +:component_file:`vfs/vfs_uart.c` and most particularly to functions +:cpp:func:`esp_vfs_dev_uart_register`, :cpp:func:`uart_start_select` and +:cpp:func:`uart_end_select`. + +Examples demonstrating the use of :cpp:func:`select` with VFS file descriptors +are the :example:`peripherals/uart_select` and the :example:`system/select` +examples. + Paths ----- diff --git a/components/vfs/include/esp_vfs.h b/components/vfs/include/esp_vfs.h index 202be24859..d063dba0ac 100644 --- a/components/vfs/include/esp_vfs.h +++ b/components/vfs/include/esp_vfs.h @@ -25,7 +25,9 @@ #include #include #include +#include #include +#include #ifdef __cplusplus extern "C" { @@ -167,6 +169,16 @@ typedef struct int (*access_p)(void* ctx, const char *path, int amode); int (*access)(const char *path, int amode); }; + /** start_select is called for setting up synchronous I/O multiplexing of the desired file descriptors in the given VFS */ + esp_err_t (*start_select)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds); + /** socket select function for socket FDs with the functionality of POSIX select(); this should be set only for the socket VFS */ + int (*socket_select)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout); + /** called by VFS to interrupt the socket_select call when select is activated from a non-socket VFS driver; set only for the socket driver */ + void (*stop_socket_select)(); + /** stop_socket_select which can be called from ISR; set only for the socket driver */ + void (*stop_socket_select_isr)(BaseType_t *woken); + /** end_select is called to stop the I/O multiplexing and deinitialize the environment created by start_select for the given VFS */ + void (*end_select)(); } esp_vfs_t; @@ -235,6 +247,50 @@ int esp_vfs_unlink(struct _reent *r, const char *path); int esp_vfs_rename(struct _reent *r, const char *src, const char *dst); /**@}*/ +/** + * @brief Synchronous I/O multiplexing which implements the functionality of POSIX select() for VFS + * @param nfds Specifies the range of descriptors which should be checked. + * The first nfds descriptors will be checked in each set. + * @param readfds If not NULL, then points to a descriptor set that on input + * specifies which descriptors should be checked for being + * ready to read, and on output indicates which descriptors + * are ready to read. + * @param writefds If not NULL, then points to a descriptor set that on input + * specifies which descriptors should be checked for being + * ready to write, and on output indicates which descriptors + * are ready to write. + * @param errorfds If not NULL, then points to a descriptor set that on input + * specifies which descriptors should be checked for error + * conditions, and on output indicates which descriptors + * have error conditions. + * @param timeout If not NULL, then points to timeval structure which + * specifies the time period after which the functions should + * time-out and return. If it is NULL, then the function will + * not time-out. + * + * @return The number of descriptors set in the descriptor sets, or -1 + * when an error (specified by errno) have occurred. + */ +int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout); + +/** + * @brief Notification from a VFS driver about a read/write/error condition + * + * This function is called when the VFS driver detects a read/write/error + * condition as it was requested by the previous call to start_select. + */ +void esp_vfs_select_triggered(); + +/** + * @brief Notification from a VFS driver about a read/write/error condition (ISR version) + * + * This function is called when the VFS driver detects a read/write/error + * condition as it was requested by the previous call to start_select. + * + * @param woken is set to pdTRUE if the function wakes up a task with higher priority + */ +void esp_vfs_select_triggered_isr(BaseType_t *woken); + #ifdef __cplusplus } // extern "C" #endif diff --git a/components/vfs/test/test_vfs_select.c b/components/vfs/test/test_vfs_select.c new file mode 100644 index 0000000000..5febf39a47 --- /dev/null +++ b/components/vfs/test/test_vfs_select.c @@ -0,0 +1,284 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include "unity.h" +#include "soc/uart_struct.h" +#include "freertos/FreeRTOS.h" +#include "driver/uart.h" +#include "esp_vfs.h" +#include "esp_vfs_dev.h" +#include "lwip/sockets.h" +#include "lwip/netdb.h" + +typedef struct { + int fd; + int delay_ms; + xSemaphoreHandle sem; +} test_task_param_t; + +static const char message[] = "Hello world!"; + +static int socket_init() +{ + const struct addrinfo hints = { + .ai_family = AF_INET, + .ai_socktype = SOCK_DGRAM, + }; + struct addrinfo *res; + int err; + struct sockaddr_in saddr = { 0 }; + int socket_fd = -1; + + err = getaddrinfo("localhost", "80", &hints, &res); + TEST_ASSERT_EQUAL(err, 0); + TEST_ASSERT_NOT_NULL(res); + + socket_fd = socket(res->ai_family, res->ai_socktype, 0); + TEST_ASSERT(socket_fd >= 0); + + saddr.sin_family = PF_INET; + saddr.sin_port = htons(80); + saddr.sin_addr.s_addr = htonl(INADDR_ANY); + err = bind(socket_fd, (struct sockaddr *) &saddr, sizeof(struct sockaddr_in)); + TEST_ASSERT(err >= 0); + + err = connect(socket_fd, res->ai_addr, res->ai_addrlen); + TEST_ASSERT_EQUAL_MESSAGE(err, 0, "Socket connection failed"); + + freeaddrinfo(res); + + return socket_fd; +} + +static void uart1_init() +{ + uart_config_t uart_config = { + .baud_rate = 115200, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE + }; + uart_param_config(UART_NUM_1, &uart_config); + uart_driver_install(UART_NUM_1, 256, 256, 0, NULL, 0); +} + +static void send_task(void *param) +{ + const test_task_param_t *test_task_param = param; + vTaskDelay(test_task_param->delay_ms / portTICK_PERIOD_MS); + write(test_task_param->fd, message, sizeof(message)); + if (test_task_param->sem) { + xSemaphoreGive(test_task_param->sem); + } + vTaskDelete(NULL); +} + +static inline void start_task(const test_task_param_t *test_task_param) +{ + xTaskCreate(send_task, "send_task", 4*1024, (void *) test_task_param, 5, NULL); +} + +static void init(int *uart_fd, int *socket_fd) +{ + uart1_init(); + UART1.conf0.loopback = 1; + + *uart_fd = open("/dev/uart/1", O_RDWR); + TEST_ASSERT_NOT_EQUAL_MESSAGE(*uart_fd, -1, "Cannot open UART"); + + esp_vfs_dev_uart_use_driver(1); + + *socket_fd = socket_init(); +} + +static void deinit(int uart_fd, int socket_fd) +{ + esp_vfs_dev_uart_use_nonblocking(1); + close(uart_fd); + UART1.conf0.loopback = 0; + uart_driver_delete(UART_NUM_1); + + close(socket_fd); +} + +TEST_CASE("UART can do select()", "[vfs]") +{ + int uart_fd; + int socket_fd; + struct timeval tv = { + .tv_sec = 0, + .tv_usec = 100000, + }; + char recv_message[sizeof(message)]; + + init(&uart_fd, &socket_fd); + + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(uart_fd, &rfds); + //without socket in rfds it will not use the same signalization + + const test_task_param_t test_task_param = { + .fd = uart_fd, + .delay_ms = 50, + .sem = xSemaphoreCreateBinary(), + }; + TEST_ASSERT_NOT_NULL(test_task_param.sem); + start_task(&test_task_param); + + int s = select(uart_fd + 1, &rfds, NULL, NULL, &tv); + TEST_ASSERT_EQUAL(s, 1); + TEST_ASSERT(FD_ISSET(uart_fd, &rfds)); + TEST_ASSERT_UNLESS(FD_ISSET(socket_fd, &rfds)); + + int read_bytes = read(uart_fd, recv_message, sizeof(message)); + TEST_ASSERT_EQUAL(read_bytes, sizeof(message)); + TEST_ASSERT_EQUAL_MEMORY(message, recv_message, sizeof(message)); + + TEST_ASSERT_EQUAL(xSemaphoreTake(test_task_param.sem, 1000 / portTICK_PERIOD_MS), pdTRUE); + + FD_ZERO(&rfds); + FD_SET(uart_fd, &rfds); + FD_SET(socket_fd, &rfds); + + start_task(&test_task_param); + + s = select(MAX(uart_fd, socket_fd) + 1, &rfds, NULL, NULL, &tv); + TEST_ASSERT_EQUAL(s, 1); + TEST_ASSERT(FD_ISSET(uart_fd, &rfds)); + TEST_ASSERT_UNLESS(FD_ISSET(socket_fd, &rfds)); + + read_bytes = read(uart_fd, recv_message, sizeof(message)); + TEST_ASSERT_EQUAL(read_bytes, sizeof(message)); + TEST_ASSERT_EQUAL_MEMORY(message, recv_message, sizeof(message)); + + TEST_ASSERT_EQUAL(xSemaphoreTake(test_task_param.sem, 1000 / portTICK_PERIOD_MS), pdTRUE); + vSemaphoreDelete(test_task_param.sem); + + deinit(uart_fd, socket_fd); +} + +TEST_CASE("socket can do select()", "[vfs]") +{ + int uart_fd; + int socket_fd; + struct timeval tv = { + .tv_sec = 0, + .tv_usec = 100000, + }; + char recv_message[sizeof(message)]; + + init(&uart_fd, &socket_fd); + + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(uart_fd, &rfds); + FD_SET(socket_fd, &rfds); + + const test_task_param_t test_task_param = { + .fd = socket_fd, + .delay_ms = 50, + .sem = xSemaphoreCreateBinary(), + }; + TEST_ASSERT_NOT_NULL(test_task_param.sem); + start_task(&test_task_param); + + const int s = select(MAX(uart_fd, socket_fd) + 1, &rfds, NULL, NULL, &tv); + TEST_ASSERT_EQUAL(s, 1); + TEST_ASSERT_UNLESS(FD_ISSET(uart_fd, &rfds)); + TEST_ASSERT(FD_ISSET(socket_fd, &rfds)); + + int read_bytes = read(socket_fd, recv_message, sizeof(message)); + TEST_ASSERT_EQUAL(read_bytes, sizeof(message)); + TEST_ASSERT_EQUAL_MEMORY(message, recv_message, sizeof(message)); + + TEST_ASSERT_EQUAL(xSemaphoreTake(test_task_param.sem, 1000 / portTICK_PERIOD_MS), pdTRUE); + vSemaphoreDelete(test_task_param.sem); + + deinit(uart_fd, socket_fd); +} + +TEST_CASE("select() timeout", "[vfs]") +{ + int uart_fd; + int socket_fd; + struct timeval tv = { + .tv_sec = 0, + .tv_usec = 100000, + }; + + init(&uart_fd, &socket_fd); + + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(uart_fd, &rfds); + FD_SET(socket_fd, &rfds); + + int s = select(MAX(uart_fd, socket_fd) + 1, &rfds, NULL, NULL, &tv); + TEST_ASSERT_EQUAL(s, 0); + TEST_ASSERT_UNLESS(FD_ISSET(uart_fd, &rfds)); + TEST_ASSERT_UNLESS(FD_ISSET(socket_fd, &rfds)); + + FD_ZERO(&rfds); + + s = select(MAX(uart_fd, socket_fd) + 1, &rfds, NULL, NULL, &tv); + TEST_ASSERT_EQUAL(s, 0); + TEST_ASSERT_UNLESS(FD_ISSET(uart_fd, &rfds)); + TEST_ASSERT_UNLESS(FD_ISSET(socket_fd, &rfds)); + + deinit(uart_fd, socket_fd); +} + +static void select_task(void *param) +{ + const test_task_param_t *test_task_param = param; + struct timeval tv = { + .tv_sec = 0, + .tv_usec = 100000, + }; + + int s = select(1, NULL, NULL, NULL, &tv); + TEST_ASSERT_EQUAL(s, 0); //timeout + + if (test_task_param->sem) { + xSemaphoreGive(test_task_param->sem); + } + vTaskDelete(NULL); +} + +TEST_CASE("concurent select() fails", "[vfs]") +{ + struct timeval tv = { + .tv_sec = 0, + .tv_usec = 100000,//irrelevant + }; + const test_task_param_t test_task_param = { + .sem = xSemaphoreCreateBinary(), + }; + TEST_ASSERT_NOT_NULL(test_task_param.sem); + xTaskCreate(select_task, "select_task", 4*1024, (void *) &test_task_param, 5, NULL); + vTaskDelay(10 / portTICK_PERIOD_MS); //make sure the task has started and waits in select() + + int s = select(1, NULL, NULL, NULL, &tv); + TEST_ASSERT_EQUAL(s, -1); //this select should fail because the other one is "waiting" + TEST_ASSERT_EQUAL(errno, EINTR); + + TEST_ASSERT_EQUAL(xSemaphoreTake(test_task_param.sem, 1000 / portTICK_PERIOD_MS), pdTRUE); + vSemaphoreDelete(test_task_param.sem); +} diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index d7ca283ec3..7ea36b0391 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -20,7 +20,10 @@ #include #include #include +#include #include +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" #include "esp_vfs.h" #include "esp_log.h" @@ -49,12 +52,28 @@ typedef struct vfs_entry_ { int offset; // index of this structure in s_vfs array } vfs_entry_t; +typedef struct { + bool isset; // none or at least one bit is set in the following 3 fd sets + fd_set readfds; + fd_set writefds; + fd_set errorfds; +} fds_triple_t; + static vfs_entry_t* s_vfs[VFS_MAX_COUNT] = { 0 }; static size_t s_vfs_count = 0; static fd_table_t s_fd_table[MAX_FDS] = { [0 ... MAX_FDS-1] = FD_TABLE_ENTRY_UNUSED }; static _lock_t s_fd_table_lock; +/* Semaphore used for waiting select events from other VFS drivers when socket + * select is not used (not registered or socket FDs are not observed by the + * given call of select) + */ +static SemaphoreHandle_t s_select_sem = NULL; + +/* Lock ensuring that select is called from only one task at the time */ +static _lock_t s_one_select_lock; + static esp_err_t esp_vfs_register_common(const char* base_path, size_t len, const esp_vfs_t* vfs, void* ctx, int *vfs_index) { if (len != LEN_PATH_PREFIX_IGNORED) { @@ -637,3 +656,214 @@ int access(const char *path, int amode) CHECK_AND_CALL(ret, r, vfs, access, path_within_vfs, amode); return ret; } + +static void call_end_selects(int end_index, const fds_triple_t *vfs_fds_triple) +{ + for (int i = 0; i < end_index; ++i) { + const vfs_entry_t *vfs = get_vfs_for_index(i); + const fds_triple_t *item = &vfs_fds_triple[i]; + if (vfs && vfs->vfs.end_select && item->isset) { + vfs->vfs.end_select(); + } + } +} + +static int set_global_fd_sets(const fds_triple_t *vfs_fds_triple, int size, fd_set *readfds, fd_set *writefds, fd_set *errorfds) +{ + int ret = 0; + + for (int i = 0; i < size; ++i) { + const fds_triple_t *item = &vfs_fds_triple[i]; + if (item->isset) { + for (int fd = 0; fd < MAX_FDS; ++fd) { + const int local_fd = s_fd_table[fd].local_fd; // single read -> no locking is required + if (readfds && FD_ISSET(local_fd, &item->readfds)) { + FD_SET(fd, readfds); + ++ret; + } + if (writefds && FD_ISSET(local_fd, &item->writefds)) { + FD_SET(fd, writefds); + ++ret; + } + if (errorfds && FD_ISSET(local_fd, &item->errorfds)) { + FD_SET(fd, errorfds); + ++ret; + } + } + } + } + + return ret; +} + +int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout) +{ + int ret = 0; + struct _reent* r = __getreent(); + + if (nfds > MAX_FDS || nfds < 0) { + __errno_r(r) = EINVAL; + return -1; + } + + if (_lock_try_acquire(&s_one_select_lock)) { + __errno_r(r) = EINTR; + return -1; + } + + fds_triple_t *vfs_fds_triple; + if ((vfs_fds_triple = calloc(s_vfs_count, sizeof(fds_triple_t))) == NULL) { + __errno_r(r) = ENOMEM; + _lock_release(&s_one_select_lock); + return -1; + } + + int (*socket_select)(int, fd_set *, fd_set *, fd_set *, struct timeval *) = NULL; + for (int fd = 0; fd < nfds; ++fd) { + _lock_acquire(&s_fd_table_lock); + const bool is_socket_fd = s_fd_table[fd].permanent; + const int vfs_index = s_fd_table[fd].vfs_index; + const int local_fd = s_fd_table[fd].local_fd; + _lock_release(&s_fd_table_lock); + + if (vfs_index < 0) { + continue; + } + + if (!socket_select && is_socket_fd) { + // no socket_select found yet and the fd is for a socket so take a look + if ((readfds && FD_ISSET(fd, readfds)) || + (writefds && FD_ISSET(fd, writefds)) || + (errorfds && FD_ISSET(fd, errorfds))) { + const vfs_entry_t *vfs = s_vfs[vfs_index]; + socket_select = vfs->vfs.socket_select; + } + continue; + } + + fds_triple_t *item = &vfs_fds_triple[vfs_index]; // FD sets for VFS which belongs to fd + if (readfds && FD_ISSET(fd, readfds)) { + item->isset = true; + FD_SET(local_fd, &item->readfds); + FD_CLR(fd, readfds); + } + if (writefds && FD_ISSET(fd, writefds)) { + item->isset = true; + FD_SET(local_fd, &item->writefds); + FD_CLR(fd, writefds); + } + if (errorfds && FD_ISSET(fd, errorfds)) { + item->isset = true; + FD_SET(local_fd, &item->errorfds); + FD_CLR(fd, errorfds); + } + } + + // all non-socket VFSs have their FD sets in vfs_fds_triple + // the global readfds, writefds and errorfds contain only socket FDs (if + // there any) + + if (!socket_select) { + // There is no socket VFS registered or select() wasn't called for + // any socket. Therefore, we will use our own signalization. + if ((s_select_sem = xSemaphoreCreateBinary()) == NULL) { + free(vfs_fds_triple); + __errno_r(r) = ENOMEM; + _lock_release(&s_one_select_lock); + return -1; + } + } + + for (int i = 0; i < s_vfs_count; ++i) { + const vfs_entry_t *vfs = get_vfs_for_index(i); + fds_triple_t *item = &vfs_fds_triple[i]; + + if (vfs && vfs->vfs.start_select && item->isset) { + // call start_select for all non-socket VFSs with has at least one FD set in readfds, writefds, or errorfds + // note: it can point to socket VFS but item->isset will be false for that + esp_err_t err = vfs->vfs.start_select(nfds, &item->readfds, &item->writefds, &item->errorfds); + + if (err != ESP_OK) { + call_end_selects(i, vfs_fds_triple); + (void) set_global_fd_sets(vfs_fds_triple, s_vfs_count, readfds, writefds, errorfds); + if (s_select_sem) { + vSemaphoreDelete(s_select_sem); + s_select_sem = NULL; + } + free(vfs_fds_triple); + __errno_r(r) = ENOMEM; + _lock_release(&s_one_select_lock); + return -1; + } + } + } + + if (socket_select) { + ret = socket_select(nfds, readfds, writefds, errorfds, timeout); + } else { + if (readfds) { + FD_ZERO(readfds); + } + if (writefds) { + FD_ZERO(writefds); + } + if (errorfds) { + FD_ZERO(errorfds); + } + + TickType_t ticks_to_wait = portMAX_DELAY; + if (timeout) { + uint32_t timeout_ms = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; + ticks_to_wait = timeout_ms / portTICK_PERIOD_MS; + } + xSemaphoreTake(s_select_sem, ticks_to_wait); + } + + call_end_selects(s_vfs_count, vfs_fds_triple); // for VFSs for start_select was called before + if (ret >= 0) { + ret += set_global_fd_sets(vfs_fds_triple, s_vfs_count, readfds, writefds, errorfds); + } + if (s_select_sem) { + vSemaphoreDelete(s_select_sem); + s_select_sem = NULL; + } + free(vfs_fds_triple); + _lock_release(&s_one_select_lock); + return ret; +} + +void esp_vfs_select_triggered() +{ + if (s_select_sem) { + xSemaphoreGive(s_select_sem); + } else { + // Another way would be to go through s_fd_table and find the VFS + // which has a permanent FD. But in order to avoid to lock + // s_fd_table_lock we go through the VFS table. + for (int i = 0; i < s_vfs_count; ++i) { + const vfs_entry_t *vfs = s_vfs[i]; + if (vfs != NULL && vfs->vfs.stop_socket_select != NULL) { + vfs->vfs.stop_socket_select(); + break; + } + } + } +} + +void esp_vfs_select_triggered_isr(BaseType_t *woken) +{ + if (s_select_sem) { + xSemaphoreGiveFromISR(s_select_sem, woken); + } else { + // Another way would be to go through s_fd_table and find the VFS + // which has a permanent FD. But in order to avoid to lock + // s_fd_table_lock we go through the VFS table. + for (int i = 0; i < s_vfs_count; ++i) { + const vfs_entry_t *vfs = s_vfs[i]; + if (vfs != NULL && vfs->vfs.stop_socket_select_isr != NULL) { + vfs->vfs.stop_socket_select_isr(woken); + break; + } + } + } +} diff --git a/components/vfs/vfs_uart.c b/components/vfs/vfs_uart.c index 83e89acc34..c1c12066cb 100644 --- a/components/vfs/vfs_uart.c +++ b/components/vfs/vfs_uart.c @@ -18,12 +18,14 @@ #include #include #include +#include #include "esp_vfs.h" #include "esp_vfs_dev.h" #include "esp_attr.h" #include "soc/uart_struct.h" #include "driver/uart.h" #include "sdkconfig.h" +#include "driver/uart_select.h" // TODO: make the number of UARTs chip dependent #define UART_NUM 3 @@ -56,6 +58,13 @@ static int s_peek_char[UART_NUM] = { NONE, NONE, NONE }; // driver is used. static bool s_non_blocking[UART_NUM]; +static fd_set *_readfds = NULL; +static fd_set *_writefds = NULL; +static fd_set *_errorfds = NULL; +static fd_set *_readfds_orig = NULL; +static fd_set *_writefds_orig = NULL; +static fd_set *_errorfds_orig = NULL; + // Newline conversion mode when transmitting static esp_line_endings_t s_tx_mode = #if CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF @@ -288,6 +297,108 @@ static int uart_access(const char *path, int amode) return ret; } +static void select_notif_callback(uart_port_t uart_num, uart_select_notif_t uart_select_notif, BaseType_t *task_woken) +{ + switch (uart_select_notif) { + case UART_SELECT_READ_NOTIF: + if (FD_ISSET(uart_num, _readfds_orig)) { + FD_SET(uart_num, _readfds); + esp_vfs_select_triggered_isr(task_woken); + } + break; + case UART_SELECT_WRITE_NOTIF: + if (FD_ISSET(uart_num, _writefds_orig)) { + FD_SET(uart_num, _writefds); + esp_vfs_select_triggered_isr(task_woken); + } + break; + case UART_SELECT_ERROR_NOTIF: + if (FD_ISSET(uart_num, _errorfds_orig)) { + FD_SET(uart_num, _errorfds); + esp_vfs_select_triggered_isr(task_woken); + } + break; + } +} + +static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds) +{ + const int max_fds = MIN(nfds, UART_NUM); + + taskENTER_CRITICAL(uart_get_selectlock()); + + if (_readfds || _writefds || _errorfds || _readfds_orig || _writefds_orig || _errorfds_orig) { + taskEXIT_CRITICAL(uart_get_selectlock()); + return ESP_ERR_INVALID_STATE; + } + + if ((_readfds_orig = malloc(sizeof(fd_set))) == NULL) { + taskEXIT_CRITICAL(uart_get_selectlock()); + return ESP_ERR_NO_MEM; + } + + if ((_writefds_orig = malloc(sizeof(fd_set))) == NULL) { + taskEXIT_CRITICAL(uart_get_selectlock()); + return ESP_ERR_NO_MEM; + } + + if ((_errorfds_orig = malloc(sizeof(fd_set))) == NULL) { + taskEXIT_CRITICAL(uart_get_selectlock()); + return ESP_ERR_NO_MEM; + } + + //uart_set_select_notif_callback set the callbacks in UART ISR + for (int i = 0; i < max_fds; ++i) { + if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds)) { + uart_set_select_notif_callback(i, select_notif_callback); + } + } + + _readfds = readfds; + _writefds = writefds; + _errorfds = exceptfds; + + *_readfds_orig = *readfds; + *_writefds_orig = *writefds; + *_errorfds_orig = *exceptfds; + + FD_ZERO(readfds); + FD_ZERO(writefds); + FD_ZERO(exceptfds); + + taskEXIT_CRITICAL(uart_get_selectlock()); + + return ESP_OK; +} + +static void uart_end_select() +{ + taskENTER_CRITICAL(uart_get_selectlock()); + for (int i = 0; i < UART_NUM; ++i) { + uart_set_select_notif_callback(i, NULL); + } + + _readfds = NULL; + _writefds = NULL; + _errorfds = NULL; + + if (_readfds_orig) { + free(_readfds_orig); + _readfds_orig = NULL; + } + + if (_writefds_orig) { + free(_writefds_orig); + _writefds_orig = NULL; + } + + if (_errorfds_orig) { + free(_errorfds_orig); + _errorfds_orig = NULL; + } + taskEXIT_CRITICAL(uart_get_selectlock()); +} + void esp_vfs_dev_uart_register() { esp_vfs_t vfs = { @@ -299,6 +410,8 @@ void esp_vfs_dev_uart_register() .read = &uart_read, .fcntl = &uart_fcntl, .access = &uart_access, + .start_select = &uart_start_select, + .end_select = &uart_end_select, }; ESP_ERROR_CHECK(esp_vfs_register("/dev/uart", &vfs, NULL)); } diff --git a/docs/en/api-reference/peripherals/uart.rst b/docs/en/api-reference/peripherals/uart.rst index d7c82c37ed..ea2e9615b7 100644 --- a/docs/en/api-reference/peripherals/uart.rst +++ b/docs/en/api-reference/peripherals/uart.rst @@ -142,6 +142,8 @@ Demonstration of how to report various communication events and how to use pater Transmitting and receiveing with the same UART in two separate FreeRTOS tasks: :example:`peripherals/uart_async_rxtxtasks`. +Using synchronous I/O multiplexing for UART file descriptors: :example:`peripherals/uart_select`. + API Reference ------------- diff --git a/examples/peripherals/uart_select/Makefile b/examples/peripherals/uart_select/Makefile new file mode 100644 index 0000000000..010458f74c --- /dev/null +++ b/examples/peripherals/uart_select/Makefile @@ -0,0 +1,8 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := uart_select + +include $(IDF_PATH)/make/project.mk diff --git a/examples/peripherals/uart_select/README.md b/examples/peripherals/uart_select/README.md new file mode 100644 index 0000000000..966e98644e --- /dev/null +++ b/examples/peripherals/uart_select/README.md @@ -0,0 +1,13 @@ +# UART Select Example + +The UART select example is for demonstrating the use of `select()` for +synchronous I/O multiplexing on the UART interface. The example waits for a +character from UART using `select()` until a blocking read without delay or a +successful non-blocking read is possible. + +Please note that the same result can be achieved by using `uart_read_bytes()` +but the use of `select()` allows to use it together with other virtual +file system (VFS) drivers, e.g. LWIP sockets. For a more comprehensive example +please refer to `system/select`. + +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/peripherals/uart_select/main/component.mk b/examples/peripherals/uart_select/main/component.mk new file mode 100644 index 0000000000..44bd2b5273 --- /dev/null +++ b/examples/peripherals/uart_select/main/component.mk @@ -0,0 +1,3 @@ +# +# Main Makefile. This is basically the same as a component makefile. +# diff --git a/examples/peripherals/uart_select/main/uart_select_example_main.c b/examples/peripherals/uart_select/main/uart_select_example_main.c new file mode 100644 index 0000000000..62bca5698c --- /dev/null +++ b/examples/peripherals/uart_select/main/uart_select_example_main.c @@ -0,0 +1,90 @@ +/* UART Select Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "esp_vfs.h" +#include "esp_vfs_dev.h" +#include "driver/uart.h" + +static const char* TAG = "uart_select_example"; + +static void uart_select_task() +{ + uart_config_t uart_config = { + .baud_rate = 115200, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE + }; + uart_param_config(UART_NUM_0, &uart_config); + uart_driver_install(UART_NUM_0, 2*1024, 0, 0, NULL, 0); + + while (1) { + int fd; + + if ((fd = open("/dev/uart/0", O_RDWR)) == -1) { + ESP_LOGE(TAG, "Cannot open UART"); + vTaskDelay(5000 / portTICK_PERIOD_MS); + continue; + } + + // We have a driver now installed so set up the read/write functions to use driver also. + esp_vfs_dev_uart_use_driver(0); + + while (1) { + int s; + fd_set rfds; + struct timeval tv = { + .tv_sec = 5, + .tv_usec = 0, + }; + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + s = select(fd + 1, &rfds, NULL, NULL, &tv); + + if (s < 0) { + ESP_LOGE(TAG, "Select failed: errno %d", errno); + break; + } else if (s == 0) { + ESP_LOGI(TAG, "Timeout has been reached and nothing has been received"); + } else { + if (FD_ISSET(fd, &rfds)) { + char buf; + if (read(fd, &buf, 1) > 0) { + ESP_LOGI(TAG, "Received: %c", buf); + } else { + ESP_LOGE(TAG, "UART read error"); + break; + } + } else { + ESP_LOGE(TAG, "No FD has been set in select()"); + break; + } + } + } + + close(fd); + } + + vTaskDelete(NULL); +} + +void app_main() +{ + xTaskCreate(uart_select_task, "uart_select_task", 4*1024, NULL, 5, NULL); +} diff --git a/examples/protocols/udp_multicast/main/udp_multicast_example_main.c b/examples/protocols/udp_multicast/main/udp_multicast_example_main.c index 830b00e07f..18678d0ea0 100644 --- a/examples/protocols/udp_multicast/main/udp_multicast_example_main.c +++ b/examples/protocols/udp_multicast/main/udp_multicast_example_main.c @@ -420,7 +420,7 @@ static void mcast_example_task(void *pvParameters) FD_ZERO(&rfds); FD_SET(sock, &rfds); - int s = lwip_select(sock + 1, &rfds, NULL, NULL, &tv); + int s = select(sock + 1, &rfds, NULL, NULL, &tv); if (s < 0) { ESP_LOGE(TAG, "Select failed: errno %d", errno); err = -1; diff --git a/examples/system/select/Makefile b/examples/system/select/Makefile new file mode 100644 index 0000000000..0b30811ee2 --- /dev/null +++ b/examples/system/select/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := select-example + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/system/select/README.md b/examples/system/select/README.md new file mode 100644 index 0000000000..888d46109c --- /dev/null +++ b/examples/system/select/README.md @@ -0,0 +1,11 @@ +# Synchronous I/O multiplexing example + +The example demonstrates the use of synchronous I/O multiplexing by the select() +function with UART and socket file descriptors. The example starts three tasks: +1. The first task writes periodically to the UART1 file descriptor. +2. The second task writes periodically to the socket descriptor. +3. Both UART1 and the socket are configured to act as loopbacks. The third + task detects by the use of select() whether it is possible to read from + UART1 or the socket, and receives the sent messages from the other tasks. + +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/system/select/main/component.mk b/examples/system/select/main/component.mk new file mode 100644 index 0000000000..0b9d7585e7 --- /dev/null +++ b/examples/system/select/main/component.mk @@ -0,0 +1,5 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + diff --git a/examples/system/select/main/select_example.c b/examples/system/select/main/select_example.c new file mode 100644 index 0000000000..57daf8fd83 --- /dev/null +++ b/examples/system/select/main/select_example.c @@ -0,0 +1,207 @@ +/* Select Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include +#include +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "esp_vfs.h" +#include "esp_vfs_dev.h" +#include "driver/uart.h" +#include "tcpip_adapter.h" +#include "lwip/sockets.h" +#include "lwip/netdb.h" + +static const char* TAG = "uart_select_example"; + +static int uart_fd = -1; +static int socket_fd = -1; + +static void socket_deinit() +{ + close(socket_fd); + socket_fd = -1; +} + +static void socket_init() +{ + const struct addrinfo hints = { + .ai_family = AF_INET, + .ai_socktype = SOCK_DGRAM, + }; + struct addrinfo *res; + int err; + struct sockaddr_in saddr = { 0 }; + + tcpip_adapter_init(); + + err = getaddrinfo("localhost", "80", &hints, &res); + + if (err != 0 || res == NULL) { + ESP_LOGE(TAG, "DNS lookup failed: %d", errno); + return; + } + + socket_fd = socket(res->ai_family, res->ai_socktype, 0); + + if (socket_fd < 0) { + ESP_LOGE(TAG, "Failed to allocate socket."); + freeaddrinfo(res); + return; + } + + saddr.sin_family = PF_INET; + saddr.sin_port = htons(80); + saddr.sin_addr.s_addr = htonl(INADDR_ANY); + err = bind(socket_fd, (struct sockaddr *) &saddr, sizeof(struct sockaddr_in)); + if (err < 0) { + ESP_LOGE(TAG, "Failed to bind socket"); + freeaddrinfo(res); + socket_deinit(); + return; + } + + if (connect(socket_fd, res->ai_addr, res->ai_addrlen) != 0) { + ESP_LOGE(TAG, "Socket connection failed: %d", errno); + freeaddrinfo(res); + socket_deinit(); + return; + } + + freeaddrinfo(res); +} + +static void uart1_deinit() +{ + close(uart_fd); + uart_fd = -1; + uart_driver_delete(UART_NUM_1); + UART1.conf0.loopback = 0; +} + +static void uart1_init() +{ + uart_config_t uart_config = { + .baud_rate = 115200, + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE + }; + uart_param_config(UART_NUM_1, &uart_config); + uart_driver_install(UART_NUM_1, 256, 0, 0, NULL, 0); + UART1.conf0.loopback = 1; + + if ((uart_fd = open("/dev/uart/1", O_RDWR | O_NONBLOCK)) == -1) { + ESP_LOGE(TAG, "Cannot open UART1"); + uart1_deinit(); + } + + esp_vfs_dev_uart_use_driver(1); +} + +static void uart1_write_task(void *param) +{ + char buf[20]; + + uart1_init(); + + for (uint8_t i = 1;; ++i) { + vTaskDelay(4000 / portTICK_PERIOD_MS); + + snprintf(buf, sizeof(buf), "UART message U%d", i); + int write_bytes = write(uart_fd, buf, strlen(buf)); + if (write_bytes < 0) { + ESP_LOGE(TAG, "UART1 write error"); + } else { + ESP_LOGI(TAG, "%d bytes were sent to UART1: %s", write_bytes, buf); + } + } + + uart1_deinit(uart_fd); + vTaskDelete(NULL); +} + +static void socket_write_task(void *param) +{ + char buf[20]; + + socket_init(); + + for (uint8_t i = 1;; ++i) { + vTaskDelay(3000 / portTICK_PERIOD_MS); + + snprintf(buf, sizeof(buf), "Socket message S%d", i); + int write_bytes = write(socket_fd, buf, strlen(buf)); + if (write_bytes < 0) { + ESP_LOGE(TAG, "Socket write error"); + } else { + ESP_LOGI(TAG, "%d bytes were written to socket: %s", write_bytes, buf); + } + } + + socket_deinit(); + vTaskDelete(NULL); +} + +static void check_and_print(int fd, const fd_set *rfds, const char *src_msg) +{ + char buf[100]; + int read_bytes; + + if (FD_ISSET(fd, rfds)) { + if ((read_bytes = read(fd, buf, sizeof(buf)-1)) > 0) { + buf[read_bytes] = '\0'; + ESP_LOGI(TAG, "%d bytes were received through %s: %s", read_bytes, src_msg, buf); + } else { + ESP_LOGE(TAG, "%s read error", src_msg); + } + } +} + +static void select_task(void *param) +{ + while (1) { + int s; + fd_set rfds; + struct timeval tv = { + .tv_sec = 1, + .tv_usec = 0, + }; + + FD_ZERO(&rfds); + FD_SET(uart_fd, &rfds); + FD_SET(socket_fd, &rfds); + + s = select(MAX(uart_fd, socket_fd) + 1, &rfds, NULL, NULL, &tv); + + if (s < 0) { + ESP_LOGE(TAG, "Select failed: errno %d", errno); + } else if (s == 0) { + ESP_LOGI(TAG, "Timeout has been reached and nothing has been received"); + } else { + check_and_print(socket_fd, &rfds, "socket"); + check_and_print(uart_fd, &rfds, "UART1"); + } + } + + vTaskDelete(NULL); +} + +void app_main() +{ + xTaskCreate(uart1_write_task, "uart1_write_task", 4*1024, NULL, 5, NULL); + xTaskCreate(socket_write_task, "socket_write_task", 4*1024, NULL, 5, NULL); + vTaskDelay(1000 / portTICK_PERIOD_MS); + xTaskCreate(select_task, "select_task", 4*1024, NULL, 5, NULL); +} diff --git a/tools/unit-test-app/main/app_main.c b/tools/unit-test-app/main/app_main.c index a7a7e87542..f1c18fcbfb 100644 --- a/tools/unit-test-app/main/app_main.c +++ b/tools/unit-test-app/main/app_main.c @@ -3,6 +3,7 @@ #include "freertos/task.h" #include "unity.h" #include "unity_config.h" +#include "tcpip_adapter.h" void unityTask(void *pvParameters) { @@ -12,6 +13,10 @@ void unityTask(void *pvParameters) void app_main() { + // TCP/IP adapter is initialized here because it leaks memory so the + // initialization in test cases would make the test fail because of leak. + tcpip_adapter_init(); + // Note: if unpinning this task, change the way run times are calculated in // unity_platform xTaskCreatePinnedToCore(unityTask, "unityTask", 8192, NULL, From ef39c09bc12206cb68816c7660c7641dd21dfde1 Mon Sep 17 00:00:00 2001 From: kooho <2229179028@qq.com> Date: Fri, 18 May 2018 11:12:19 +0800 Subject: [PATCH 122/187] driver: reset communication peripherals when the cpu starts. --- components/driver/uart.c | 3 +++ components/esp32/clk.c | 39 ++++++++++++++++++++------------------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/components/driver/uart.c b/components/driver/uart.c index 9cec59bf08..5d66aa7669 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -648,6 +648,9 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf r = uart_set_tx_idle_num(uart_num, UART_TX_IDLE_NUM_DEFAULT); if (r != ESP_OK) return r; r = uart_set_stop_bits(uart_num, uart_config->stop_bits); + //A hardware reset does not reset the fifo, + //so we need to reset the fifo manually. + uart_reset_rx_fifo(uart_num); return r; } diff --git a/components/esp32/clk.c b/components/esp32/clk.c index 7c8d8f1772..41b24c6ed9 100644 --- a/components/esp32/clk.c +++ b/components/esp32/clk.c @@ -215,31 +215,12 @@ void esp_perip_clk_init(void) } else { common_perip_clk = DPORT_WDG_CLK_EN | - DPORT_I2S0_CLK_EN | -#if CONFIG_CONSOLE_UART_NUM != 0 - DPORT_UART_CLK_EN | -#endif -#if CONFIG_CONSOLE_UART_NUM != 1 - DPORT_UART1_CLK_EN | -#endif -#if CONFIG_CONSOLE_UART_NUM != 2 - DPORT_UART2_CLK_EN | -#endif - DPORT_SPI2_CLK_EN | - DPORT_I2C_EXT0_CLK_EN | - DPORT_UHCI0_CLK_EN | - DPORT_RMT_CLK_EN | DPORT_PCNT_CLK_EN | DPORT_LEDC_CLK_EN | - DPORT_UHCI1_CLK_EN | DPORT_TIMERGROUP1_CLK_EN | - DPORT_SPI3_CLK_EN | DPORT_PWM0_CLK_EN | - DPORT_I2C_EXT1_CLK_EN | DPORT_CAN_CLK_EN | DPORT_PWM1_CLK_EN | - DPORT_I2S1_CLK_EN | - DPORT_SPI_DMA_CLK_EN | DPORT_PWM2_CLK_EN | DPORT_PWM3_CLK_EN; hwcrypto_perip_clk = DPORT_PERI_EN_AES | @@ -255,6 +236,26 @@ void esp_perip_clk_init(void) DPORT_WIFI_CLK_EMAC_EN; } + //Reset the communication peripherals like I2C, SPI, UART, I2S and bring them to known state. + common_perip_clk |= DPORT_I2S0_CLK_EN | +#if CONFIG_CONSOLE_UART_NUM != 0 + DPORT_UART_CLK_EN | +#endif +#if CONFIG_CONSOLE_UART_NUM != 1 + DPORT_UART1_CLK_EN | +#endif +#if CONFIG_CONSOLE_UART_NUM != 2 + DPORT_UART2_CLK_EN | +#endif + DPORT_SPI2_CLK_EN | + DPORT_I2C_EXT0_CLK_EN | + DPORT_UHCI0_CLK_EN | + DPORT_RMT_CLK_EN | + DPORT_UHCI1_CLK_EN | + DPORT_SPI3_CLK_EN | + DPORT_I2C_EXT1_CLK_EN | + DPORT_I2S1_CLK_EN | + DPORT_SPI_DMA_CLK_EN; #if CONFIG_SPIRAM_SPEED_80M //80MHz SPIRAM uses SPI3 as well; it's initialized before this is called. Because it is used in From 33b99caf5091f5edb966d0f497e5ca8399ccfded Mon Sep 17 00:00:00 2001 From: kooho <2229179028@qq.com> Date: Fri, 18 May 2018 15:47:02 +0800 Subject: [PATCH 123/187] driver(uart):Fix the bug that uart buffer_full flag is true all the time. --- components/driver/uart.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/components/driver/uart.c b/components/driver/uart.c index e32023047e..7aa3ce1a2a 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -1159,8 +1159,8 @@ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickTyp if(res == pdTRUE) { UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); p_uart_obj[uart_num]->rx_buffered_len += p_uart_obj[uart_num]->rx_stash_len; - UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); p_uart_obj[uart_num]->rx_buffer_full_flg = false; + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num); } } @@ -1205,6 +1205,14 @@ esp_err_t uart_flush_input(uart_port_t uart_num) } data = (uint8_t*) xRingbufferReceive(p_uart->rx_ring_buf, &size, (portTickType) 0); if(data == NULL) { + if( p_uart_obj[uart_num]->rx_buffered_len != 0 ) { + ESP_LOGE(UART_TAG, "rx_buffered_len error"); + p_uart_obj[uart_num]->rx_buffered_len = 0; + } + //We also need to clear the `rx_buffer_full_flg` here. + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + p_uart_obj[uart_num]->rx_buffer_full_flg = false; + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); break; } UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); @@ -1217,8 +1225,8 @@ esp_err_t uart_flush_input(uart_port_t uart_num) if(res == pdTRUE) { UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); p_uart_obj[uart_num]->rx_buffered_len += p_uart_obj[uart_num]->rx_stash_len; - UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); p_uart_obj[uart_num]->rx_buffer_full_flg = false; + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); } } } From b2ec58af1c011f8d7829a532ffa122a384a17908 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Fri, 18 May 2018 17:09:53 +0530 Subject: [PATCH 124/187] docs: fix link for FTDI VCP drivers Signed-off-by: Mahavir Jain --- docs/en/get-started/establish-serial-connection.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/get-started/establish-serial-connection.rst b/docs/en/get-started/establish-serial-connection.rst index 22e08b0fc1..d4c0943a44 100644 --- a/docs/en/get-started/establish-serial-connection.rst +++ b/docs/en/get-started/establish-serial-connection.rst @@ -13,7 +13,7 @@ Below are the links to drivers for ESP32 boards produced by Espressif: * ESP32-PICO-KIT and ESP32-DevKitC - `CP210x USB to UART Bridge VCP Drivers `_ -* ESP32-WROVER-KIT and ESP32 Demo Board - `FTDI Virtual COM Port Drivers `_ +* ESP32-WROVER-KIT and ESP32 Demo Board - `FTDI Virtual COM Port Drivers `_ Above drivers are primarily for reference. They should already be bundled with the operating system and installed automatically once one of listed boards is connected to the PC. From c1b6a37bb1287dc5e1767ea2647e11db3df9dd6c Mon Sep 17 00:00:00 2001 From: Alexey Gerenkov Date: Thu, 15 Feb 2018 20:09:03 +0300 Subject: [PATCH 125/187] esp32: Adds GCOV debug stubs support Adds the following functionality - Debug stubs infrastructure - Stub for retrieveing GCOV data without user source code modification --- components/app_trace/Kconfig | 8 ++ components/app_trace/app_trace.c | 60 +++++++++++- components/app_trace/gcov/gcov_rtio.c | 115 ++++++++++++++++++++--- components/app_trace/host_file_io.c | 47 +++++---- components/esp32/Kconfig | 7 ++ components/esp32/cpu_start.c | 4 + components/esp32/dbg_stubs.c | 95 +++++++++++++++++++ components/esp32/include/esp_dbg_stubs.h | 50 ++++++++++ examples/system/gcov/README.md | 99 +++++++++++++------ examples/system/gcov/main/gcov_example.c | 25 ++--- 10 files changed, 437 insertions(+), 73 deletions(-) create mode 100644 components/esp32/dbg_stubs.c create mode 100644 components/esp32/include/esp_dbg_stubs.h diff --git a/components/app_trace/Kconfig b/components/app_trace/Kconfig index 9426c7539a..d80331996b 100644 --- a/components/app_trace/Kconfig +++ b/components/app_trace/Kconfig @@ -190,4 +190,12 @@ config SYSVIEW_EVT_TIMER_EXIT_ENABLE Enables "Timer Exit" event. endmenu + +config ESP32_GCOV_ENABLE + bool "GCOV to Host Enable" + depends on ESP32_DEBUG_STUBS_ENABLE && ESP32_APPTRACE_ENABLE && !SYSVIEW_ENABLE + default y + help + Enables support for GCOV data transfer to host. + endmenu diff --git a/components/app_trace/app_trace.c b/components/app_trace/app_trace.c index d5a56471b3..5552fe5e2a 100644 --- a/components/app_trace/app_trace.c +++ b/components/app_trace/app_trace.c @@ -336,6 +336,8 @@ typedef struct { uint8_t *(*get_down_buffer)(uint32_t *, esp_apptrace_tmo_t *); esp_err_t (*put_down_buffer)(uint8_t *, esp_apptrace_tmo_t *); bool (*host_is_connected)(void); + esp_err_t (*status_reg_set)(uint32_t val); + esp_err_t (*status_reg_get)(uint32_t *val); } esp_apptrace_hw_t; static uint32_t esp_apptrace_trax_down_buffer_write_nolock(uint8_t *data, uint32_t size); @@ -345,6 +347,8 @@ static esp_err_t esp_apptrace_trax_put_buffer(uint8_t *ptr, esp_apptrace_tmo_t * static bool esp_apptrace_trax_host_is_connected(void); static uint8_t *esp_apptrace_trax_down_buffer_get(uint32_t *size, esp_apptrace_tmo_t *tmo); static esp_err_t esp_apptrace_trax_down_buffer_put(uint8_t *ptr, esp_apptrace_tmo_t *tmo); +static esp_err_t esp_apptrace_trax_status_reg_set(uint32_t val); +static esp_err_t esp_apptrace_trax_status_reg_get(uint32_t *val); static esp_apptrace_hw_t s_trace_hw[ESP_APPTRACE_HW_MAX] = { { @@ -353,7 +357,9 @@ static esp_apptrace_hw_t s_trace_hw[ESP_APPTRACE_HW_MAX] = { .flush_up_buffer = esp_apptrace_trax_flush, .get_down_buffer = esp_apptrace_trax_down_buffer_get, .put_down_buffer = esp_apptrace_trax_down_buffer_put, - .host_is_connected = esp_apptrace_trax_host_is_connected + .host_is_connected = esp_apptrace_trax_host_is_connected, + .status_reg_set = esp_apptrace_trax_status_reg_set, + .status_reg_get = esp_apptrace_trax_status_reg_get } }; @@ -416,6 +422,8 @@ static void esp_apptrace_trax_init() eri_write(ERI_TRAX_TRAXCTRL, TRAXCTRL_TRSTP); eri_write(ERI_TRAX_TRAXCTRL, TRAXCTRL_TMEN); eri_write(ESP_APPTRACE_TRAX_CTRL_REG, ESP_APPTRACE_TRAX_BLOCK_ID(ESP_APPTRACE_TRAX_INBLOCK_START)); + // this is for OpenOCD to let him know where stub entries vector is resided + // must be read by host before any transfer using TRAX eri_write(ESP_APPTRACE_TRAX_STAT_REG, 0); ESP_APPTRACE_LOGI("Initialized TRAX on CPU%d", xPortGetCoreID()); @@ -828,6 +836,18 @@ static bool esp_apptrace_trax_host_is_connected(void) return eri_read(ESP_APPTRACE_TRAX_CTRL_REG) & ESP_APPTRACE_TRAX_HOST_CONNECT ? true : false; } +static esp_err_t esp_apptrace_trax_status_reg_set(uint32_t val) +{ + eri_write(ESP_APPTRACE_TRAX_STAT_REG, val); + return ESP_OK; +} + +static esp_err_t esp_apptrace_trax_status_reg_get(uint32_t *val) +{ + *val = eri_read(ESP_APPTRACE_TRAX_STAT_REG); + return ESP_OK; +} + static esp_err_t esp_apptrace_trax_dest_init() { for (int i = 0; i < ESP_APPTRACE_TRAX_BLOCKS_NUM; i++) { @@ -1159,6 +1179,24 @@ bool esp_apptrace_host_is_connected(esp_apptrace_dest_t dest) { esp_apptrace_hw_t *hw = NULL; + if (dest == ESP_APPTRACE_DEST_TRAX) { +#if CONFIG_ESP32_APPTRACE_DEST_TRAX + hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX); +#else + ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!"); + return false; +#endif + } else { + ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!"); + return false; + } + return hw->host_is_connected(); +} + +esp_err_t esp_apptrace_status_reg_set(esp_apptrace_dest_t dest, uint32_t val) +{ + esp_apptrace_hw_t *hw = NULL; + if (dest == ESP_APPTRACE_DEST_TRAX) { #if CONFIG_ESP32_APPTRACE_DEST_TRAX hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX); @@ -1170,7 +1208,25 @@ bool esp_apptrace_host_is_connected(esp_apptrace_dest_t dest) ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!"); return ESP_ERR_NOT_SUPPORTED; } - return hw->host_is_connected(); + return hw->status_reg_set(val); +} + +esp_err_t esp_apptrace_status_reg_get(esp_apptrace_dest_t dest, uint32_t *val) +{ + esp_apptrace_hw_t *hw = NULL; + + if (dest == ESP_APPTRACE_DEST_TRAX) { +#if CONFIG_ESP32_APPTRACE_DEST_TRAX + hw = ESP_APPTRACE_HW(ESP_APPTRACE_HW_TRAX); +#else + ESP_APPTRACE_LOGE("Application tracing via TRAX is disabled in menuconfig!"); + return ESP_ERR_NOT_SUPPORTED; +#endif + } else { + ESP_APPTRACE_LOGE("Trace destinations other then TRAX are not supported yet!"); + return ESP_ERR_NOT_SUPPORTED; + } + return hw->status_reg_get(val); } #endif diff --git a/components/app_trace/gcov/gcov_rtio.c b/components/app_trace/gcov/gcov_rtio.c index 5e0b7e913e..e53eb64315 100644 --- a/components/app_trace/gcov/gcov_rtio.c +++ b/components/app_trace/gcov/gcov_rtio.c @@ -21,20 +21,92 @@ #include "soc/timer_group_struct.h" #include "soc/timer_group_reg.h" #include "esp_app_trace.h" +#include "esp_dbg_stubs.h" -#if CONFIG_ESP32_APPTRACE_ENABLE +#if CONFIG_ESP32_GCOV_ENABLE + +#define ESP_GCOV_DOWN_BUF_SIZE 4200 #define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL #include "esp_log.h" const static char *TAG = "esp_gcov_rtio"; static void (*s_gcov_exit)(void); -static uint8_t s_gcov_down_buf[256]; + +/* TODO: remove code extracted from GCC when IDF toolchain will be updated */ +/*=============== GCC CODE START ====================*/ +/* Root of a program/shared-object state */ +struct gcov_root +{ + void *list; + unsigned dumped : 1; /* counts have been dumped. */ + unsigned run_counted : 1; /* run has been accounted for. */ + struct gcov_root *next; + struct gcov_root *prev; +}; + +/* Per-dynamic-object gcov state. */ +extern struct gcov_root __gcov_root; + +static void esp_gcov_reset_status(void) +{ + __gcov_root.dumped = 0; + __gcov_root.run_counted = 0; +} +/*=============== GCC CODE END ====================*/ + +static int esp_dbg_stub_gcov_dump_do(void) +{ + int ret = ESP_OK; + + ESP_EARLY_LOGV(TAG, "Check for dump handler %p", s_gcov_exit); + if (s_gcov_exit) { + ESP_EARLY_LOGV(TAG, "Alloc apptrace down buf %d bytes", ESP_GCOV_DOWN_BUF_SIZE); + void *down_buf = malloc(ESP_GCOV_DOWN_BUF_SIZE); + if (down_buf == NULL) { + ESP_EARLY_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", ret); + return ESP_ERR_NO_MEM; + } + ESP_EARLY_LOGV(TAG, "Config apptrace down buf"); + esp_apptrace_down_buffer_config(down_buf, ESP_GCOV_DOWN_BUF_SIZE); + ESP_EARLY_LOGV(TAG, "Dump data... %p", s_gcov_exit); + s_gcov_exit(); + ESP_EARLY_LOGV(TAG, "Free apptrace down buf"); + free(down_buf); + } + ESP_EARLY_LOGV(TAG, "Finish file transfer session"); + ret = esp_apptrace_fstop(ESP_APPTRACE_DEST_TRAX); + if (ret != ESP_OK) { + ESP_EARLY_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", ret); + } + return ret; +} + +/** + * @brief Triggers gcov info dump. + * This function is to be called by OpenOCD, not by normal user code. + * TODO: what about interrupted flash access (when cache disabled)??? + * + * @return ESP_OK on success, otherwise see esp_err_t + */ +static int esp_dbg_stub_gcov_entry(void) +{ + int ret = ESP_OK; + + // disable IRQs on this CPU, other CPU is halted by OpenOCD + unsigned irq_state = portENTER_CRITICAL_NESTED(); + ret = esp_dbg_stub_gcov_dump_do(); + // reset dump status to allow incremental data accumulation + esp_gcov_reset_status(); + portEXIT_CRITICAL_NESTED(irq_state); + return ret; +} void esp_gcov_dump() { #if CONFIG_FREERTOS_UNICORE == 0 - esp_cpu_stall(!xPortGetCoreID()); + int other_core = xPortGetCoreID() ? 0 : 1; + esp_cpu_stall(other_core); #endif while (!esp_apptrace_host_is_connected(ESP_APPTRACE_DEST_TRAX)) { @@ -48,46 +120,59 @@ void esp_gcov_dump() TIMERG1.wdt_wprotect=0; } - if (s_gcov_exit) { - esp_apptrace_down_buffer_config(s_gcov_down_buf, sizeof(s_gcov_down_buf)); - s_gcov_exit(); - } - - int ret = esp_apptrace_fstop(ESP_APPTRACE_DEST_TRAX); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!\n", ret); - } + esp_dbg_stub_gcov_dump_do(); + // reset dump status to allow incremental data accumulation + esp_gcov_reset_status(); +#if CONFIG_FREERTOS_UNICORE == 0 + esp_cpu_unstall(other_core); +#endif } int gcov_rtio_atexit(void (*function)(void)) { + ESP_EARLY_LOGV(TAG, "%s %p", __FUNCTION__, function); s_gcov_exit = function; + esp_dbg_stub_entry_set(ESP_DBG_STUB_ENTRY_GCOV, (uint32_t)&esp_dbg_stub_gcov_entry); return 0; } void *gcov_rtio_fopen(const char *path, const char *mode) { + ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__); return esp_apptrace_fopen(ESP_APPTRACE_DEST_TRAX, path, mode); } int gcov_rtio_fclose(void *stream) { + ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__); return esp_apptrace_fclose(ESP_APPTRACE_DEST_TRAX, stream); } +size_t gcov_rtio_fread(void *ptr, size_t size, size_t nmemb, void *stream) +{ + ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__); + return esp_apptrace_fread(ESP_APPTRACE_DEST_TRAX, ptr, size, nmemb, stream); +} + size_t gcov_rtio_fwrite(const void *ptr, size_t size, size_t nmemb, void *stream) { + ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__); return esp_apptrace_fwrite(ESP_APPTRACE_DEST_TRAX, ptr, size, nmemb, stream); } int gcov_rtio_fseek(void *stream, long offset, int whence) { - return esp_apptrace_fseek(ESP_APPTRACE_DEST_TRAX, stream, offset, whence); + ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__); + int ret = esp_apptrace_fseek(ESP_APPTRACE_DEST_TRAX, stream, offset, whence); + ESP_EARLY_LOGV(TAG, "%s EXIT", __FUNCTION__); + return ret; } long gcov_rtio_ftell(void *stream) { - return esp_apptrace_ftell(ESP_APPTRACE_DEST_TRAX, stream); + ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__); + long ret = esp_apptrace_ftell(ESP_APPTRACE_DEST_TRAX, stream); + ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__); + return ret; } - #endif diff --git a/components/app_trace/host_file_io.c b/components/app_trace/host_file_io.c index d3cf2447b8..a6dd35c08c 100644 --- a/components/app_trace/host_file_io.c +++ b/components/app_trace/host_file_io.c @@ -87,6 +87,7 @@ static esp_err_t esp_apptrace_file_cmd_send(esp_apptrace_dest_t dest, uint8_t cm esp_err_t ret; esp_apptrace_fcmd_hdr_t *hdr; + ESP_EARLY_LOGV(TAG, "%s %d", __func__, cmd); uint8_t *ptr = esp_apptrace_buffer_get(dest, sizeof(*hdr) + args_len, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo if (ptr == NULL) { return ESP_ERR_NO_MEM; @@ -101,13 +102,13 @@ static esp_err_t esp_apptrace_file_cmd_send(esp_apptrace_dest_t dest, uint8_t cm // now indicate that this buffer is ready to be sent off to host ret = esp_apptrace_buffer_put(dest, ptr, ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to put apptrace buffer (%d)!", ret); + ESP_EARLY_LOGE(TAG, "Failed to put apptrace buffer (%d)!", ret); return ret; } ret = esp_apptrace_flush(dest, ESP_APPTRACE_TMO_INFINITE);//TODO: finite tmo if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to flush apptrace buffer (%d)!", ret); + ESP_EARLY_LOGE(TAG, "Failed to flush apptrace buffer (%d)!", ret); return ret; } @@ -119,11 +120,12 @@ static esp_err_t esp_apptrace_file_rsp_recv(esp_apptrace_dest_t dest, uint8_t *b uint32_t tot_rd = 0; while (tot_rd < buf_len) { uint32_t rd_size = buf_len - tot_rd; - esp_err_t ret = esp_apptrace_read(dest, buf, &rd_size, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo + esp_err_t ret = esp_apptrace_read(dest, buf + tot_rd, &rd_size, ESP_APPTRACE_TMO_INFINITE); //TODO: finite tmo if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to read response (%d)!", ret); + ESP_EARLY_LOGE(TAG, "Failed to read (%d)!", ret); return ret; } + ESP_EARLY_LOGV(TAG, "%s read %d bytes", __FUNCTION__, rd_size); tot_rd += rd_size; } @@ -142,6 +144,8 @@ void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char { esp_apptrace_fopen_args_t cmd_args; + ESP_EARLY_LOGV(TAG, "esp_apptrace_fopen '%s' '%s'", path, mode); + cmd_args.path = path; cmd_args.path_len = strlen(path) + 1; cmd_args.mode = mode; @@ -150,7 +154,7 @@ void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FOPEN, esp_apptrace_fopen_args_prepare, &cmd_args, cmd_args.path_len+cmd_args.mode_len); if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret); + ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret); return NULL; } @@ -158,7 +162,7 @@ void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char void *resp; ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp)); if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to read response (%d)!", ret); + ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret); return NULL; } @@ -180,7 +184,7 @@ int esp_apptrace_fclose(esp_apptrace_dest_t dest, void *stream) esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FCLOSE, esp_apptrace_fclose_args_prepare, &cmd_args, sizeof(cmd_args)); if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret); + ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret); return EOF; } @@ -188,7 +192,7 @@ int esp_apptrace_fclose(esp_apptrace_dest_t dest, void *stream) int resp; ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp)); if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to read response (%d)!", ret); + ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret); return EOF; } @@ -207,13 +211,15 @@ size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t siz { esp_apptrace_fwrite_args_t cmd_args; + ESP_EARLY_LOGV(TAG, "esp_apptrace_fwrite f %p l %d", stream, size*nmemb); + cmd_args.buf = (void *)ptr; cmd_args.size = size * nmemb; cmd_args.file = stream; esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FWRITE, esp_apptrace_fwrite_args_prepare, &cmd_args, sizeof(cmd_args.file)+cmd_args.size); if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret); + ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret); return 0; } @@ -221,7 +227,7 @@ size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t siz size_t resp; ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp)); if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to read response (%d)!", ret); + ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret); return 0; } @@ -240,12 +246,14 @@ size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size { esp_apptrace_fread_args_t cmd_args; + ESP_EARLY_LOGV(TAG, "esp_apptrace_fread f %p l %d", stream, size*nmemb); + cmd_args.size = size * nmemb; cmd_args.file = stream; esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FREAD, esp_apptrace_fread_args_prepare, &cmd_args, sizeof(cmd_args)); if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret); + ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret); return 0; } @@ -253,13 +261,13 @@ size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size size_t resp; ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp)); if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to read response (%d)!", ret); + ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret); return 0; } if (resp > 0) { ret = esp_apptrace_file_rsp_recv(dest, ptr, resp); if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to read file data (%d)!", ret); + ESP_EARLY_LOGE(TAG, "Failed to read file data (%d)!", ret); return 0; } } @@ -277,13 +285,15 @@ int esp_apptrace_fseek(esp_apptrace_dest_t dest, void *stream, long offset, int { esp_apptrace_fseek_args_t cmd_args; + ESP_EARLY_LOGV(TAG, "esp_apptrace_fseek f %p o 0x%lx w %d", stream, offset, whence); + cmd_args.file = stream; cmd_args.offset = offset; cmd_args.whence = whence; esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FSEEK, esp_apptrace_fseek_args_prepare, &cmd_args, sizeof(cmd_args)); if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret); + ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret); return -1; } @@ -291,7 +301,7 @@ int esp_apptrace_fseek(esp_apptrace_dest_t dest, void *stream, long offset, int int resp; ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp)); if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to read response (%d)!", ret); + ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret); return -1; } @@ -313,7 +323,7 @@ int esp_apptrace_ftell(esp_apptrace_dest_t dest, void *stream) esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FTELL, esp_apptrace_ftell_args_prepare, &cmd_args, sizeof(cmd_args)); if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to send file cmd (%d)!", ret); + ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret); return -1; } @@ -321,7 +331,7 @@ int esp_apptrace_ftell(esp_apptrace_dest_t dest, void *stream) int resp; ret = esp_apptrace_file_rsp_recv(dest, (uint8_t *)&resp, sizeof(resp)); if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to read response (%d)!", ret); + ESP_EARLY_LOGE(TAG, "Failed to read response (%d)!", ret); return -1; } @@ -330,9 +340,10 @@ int esp_apptrace_ftell(esp_apptrace_dest_t dest, void *stream) int esp_apptrace_fstop(esp_apptrace_dest_t dest) { + ESP_EARLY_LOGV(TAG, "%s", __func__); esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_STOP, NULL, NULL, 0); if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", ret); + ESP_EARLY_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", ret); } return ret; } diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index 3c94b0e958..fcdb019104 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -511,6 +511,13 @@ config ESP32_DEBUG_OCDAWARE The FreeRTOS panic and unhandled exception handers can detect a JTAG OCD debugger and instead of panicking, have the debugger stop on the offending instruction. +config ESP32_DEBUG_STUBS_ENABLE + bool "OpenOCD debug stubs" + default OPTIMIZATION_LEVEL_DEBUG + depends on !ESP32_TRAX + help + Debug stubs are used by OpenOCD to execute pre-compiled onboard code which does some useful debugging, + e.g. GCOV data dump. config INT_WDT bool "Interrupt watchdog" diff --git a/components/esp32/cpu_start.c b/components/esp32/cpu_start.c index 0454e3ac2d..4d907f333c 100644 --- a/components/esp32/cpu_start.c +++ b/components/esp32/cpu_start.c @@ -61,6 +61,7 @@ #include "esp_panic.h" #include "esp_core_dump.h" #include "esp_app_trace.h" +#include "esp_dbg_stubs.h" #include "esp_efuse.h" #include "esp_spiram.h" #include "esp_clk_internal.h" @@ -332,6 +333,9 @@ void start_cpu0_default(void) #endif #if CONFIG_SYSVIEW_ENABLE SEGGER_SYSVIEW_Conf(); +#endif +#if CONFIG_ESP32_DEBUG_STUBS_ENABLE + esp_dbg_stubs_init(); #endif err = esp_pthread_init(); assert(err == ESP_OK && "Failed to init pthread module!"); diff --git a/components/esp32/dbg_stubs.c b/components/esp32/dbg_stubs.c new file mode 100644 index 0000000000..51e9749b06 --- /dev/null +++ b/components/esp32/dbg_stubs.c @@ -0,0 +1,95 @@ +// 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. + +// This module implements debug/trace stubs. The stub is a piece of special code which can invoked by OpenOCD +// Currently one stub is used for GCOV functionality +// + +#include "eri.h" +#include "xtensa-debug-module.h" +#include "esp_dbg_stubs.h" +#include "esp_attr.h" + +#if CONFIG_ESP32_DEBUG_STUBS_ENABLE +/* + Debug stubs is actually a table of 4-byte entries. Every entry is equal to zero or must contain meaningfull data. + The first entry is a service one and has the followinf format: + - tramp_addr, 4 bytes; Address of buffer for trampoline/code. Max size is ESP_DBG_STUBS_CODE_BUF_SIZE. + - min_stack_addr, 4 bytes; Start of the buffer for minimal onboard stack or data. Max size is ESP_DBG_STUBS_STACK_MIN_SIZE. + - data_alloc, 4 bytes; Address of function to allocate memory on target. + - data_free, 4 bytes; Address of function to free target memory. + This entry is used by OpenOCD code to invoke other stub entries and allocate memory for them. + */ + +#define LOG_LOCAL_LEVEL CONFIG_LOG_DEFAULT_LEVEL +#include "esp_log.h" +const static char *TAG = "esp_dbg_stubs"; + +#define ESP_DBG_STUBS_TRAX_REG ERI_TRAX_TRIGGERPC +#define ESP_DBG_STUBS_CODE_BUF_SIZE 32 +#define ESP_DBG_STUBS_STACK_MIN_SIZE 2048 + +#define DBG_STUB_TRAMP_ATTR IRAM_ATTR + +static struct { + uint32_t tramp_addr; + uint32_t min_stack_addr; // minimal stack addr + uint32_t data_alloc; + uint32_t data_free; +} s_dbg_stubs_ctl_data; + +static uint32_t s_stub_entry[ESP_DBG_STUB_ENTRY_MAX]; +static uint8_t s_stub_min_stack[ESP_DBG_STUBS_STACK_MIN_SIZE]; +static DBG_STUB_TRAMP_ATTR uint8_t s_stub_code_buf[ESP_DBG_STUBS_CODE_BUF_SIZE]; + +// TODO: all called funcs should be in IRAM to work with disabled flash cache +static void * esp_dbg_stubs_data_alloc(uint32_t size) +{ + ESP_LOGV(TAG, "%s %d", __func__, size); + void *p = malloc(size); + ESP_LOGV(TAG, "%s EXIT %p", __func__, p); + return p; +} + +static void esp_dbg_stubs_data_free(void *addr) +{ + ESP_LOGV(TAG, "%s %p", __func__, addr); + free(addr); + ESP_LOGV(TAG, "%s EXIT %p", __func__, addr); +} + +void esp_dbg_stubs_init() +{ + s_dbg_stubs_ctl_data.tramp_addr = (uint32_t)s_stub_code_buf; + s_dbg_stubs_ctl_data.min_stack_addr = (uint32_t)s_stub_min_stack; + s_dbg_stubs_ctl_data.data_alloc = (uint32_t)esp_dbg_stubs_data_alloc; + s_dbg_stubs_ctl_data.data_free = (uint32_t)esp_dbg_stubs_data_free; + + s_stub_entry[ESP_DBG_STUB_CONTROL_DATA] = (uint32_t)&s_dbg_stubs_ctl_data; + eri_write(ESP_DBG_STUBS_TRAX_REG, (uint32_t)s_stub_entry); + ESP_LOGV(TAG, "%s stubs %x", __func__, eri_read(ESP_DBG_STUBS_TRAX_REG)); +} + +esp_err_t esp_dbg_stub_entry_set(esp_dbg_stub_id_t id, uint32_t entry) +{ + if (id < ESP_DBG_STUB_ENTRY_FIRST || id >= ESP_DBG_STUB_ENTRY_MAX) { + ESP_LOGE(TAG, "Invalid stub id %d!", id); + return ESP_ERR_INVALID_ARG; + } + s_stub_entry[id] = entry; + + return ESP_OK; +} + +#endif diff --git a/components/esp32/include/esp_dbg_stubs.h b/components/esp32/include/esp_dbg_stubs.h new file mode 100644 index 0000000000..899dfa56ed --- /dev/null +++ b/components/esp32/include/esp_dbg_stubs.h @@ -0,0 +1,50 @@ +// 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_DBG_STUBS_H_ +#define ESP_DBG_STUBS_H_ + +#include "esp_err.h" + +/** + * Debug stubs entries IDs + */ +typedef enum { + ESP_DBG_STUB_CONTROL_DATA, ///< stubs descriptor entry + ESP_DBG_STUB_ENTRY_FIRST, + ESP_DBG_STUB_ENTRY_GCOV ///< GCOV entry + = ESP_DBG_STUB_ENTRY_FIRST, + ESP_DBG_STUB_ENTRY_MAX +} esp_dbg_stub_id_t; + +/** + * @brief Initializes debug stubs. + * + * @note Must be called after esp_apptrace_init() if app tracing is enabled. + */ +void esp_dbg_stubs_init(void); + +/** + * @brief Initializes application tracing module. + * + * @note Should be called before any esp_apptrace_xxx call. + * + * @param id Stub ID. + * @param entry Stub entry. Usually it is stub entry function address, + * but can be any value meaningfull for OpenOCD command/code. + * + * @return ESP_OK on success, otherwise see esp_err_t + */ +esp_err_t esp_dbg_stub_entry_set(esp_dbg_stub_id_t id, uint32_t entry); + +#endif //ESP_DBG_STUBS_H_ \ No newline at end of file diff --git a/examples/system/gcov/README.md b/examples/system/gcov/README.md index effc75b2f1..5eefed2d52 100644 --- a/examples/system/gcov/README.md +++ b/examples/system/gcov/README.md @@ -4,53 +4,98 @@ See the README.md file in the upper level 'examples' directory for more informat GCC has useful feature which allows to generate code coverage information. Generated data show how many times every program execution paths has been taken. Basing on coverage data developers can detect untested pieces of code and also it gives valuable information about critical (frequently used) execution paths. -In general case when coverage option is enabled GCC generates additional code to accumulate necessary data and save them into files. File system is not always available -in ESP32 based projects or size of the file storage can be very limited to keep all the coverage data. To overcome those limitations IDF provides functionality -to transfer the data to the host and save them on host file system. The data transfer is done via JTAG. +In general case when coverage option is enabled GCC generates additional code to accumulate necessary data and save them into files. File system is not always available in ESP32 based projects or size of the file storage can be very limited to keep all the coverage data. To overcome those limitations IDF provides functionality to transfer the data to host and save them on its file system. Data transfer is done via JTAG. This example shows how to generate coverage information for the program. - ## How To Gather Coverage Info -Below are the steps which should be performed to obtain coverage info. Steps 1-3 are already done for this example project. They should be performed if user wants to fork new IDF-based project and needs to collect coverage info. +There are two ways to collect gcov data: +* Hard-coded call to `esp_gcov_dump`. +* Instant run-time dumping w/o changes in your code via IDF's gcov debug stub. + +### Generic Steps + +Below are generic steps which should be performed to obtain coverage info. The steps are already done for this example project. 1. Enable application tracing module in menuconfig. Choose `Trace memory` in `Component config -> Application Level Tracing -> Data Destination`. -2. Enable coverage info generation for necessary source files. To do this add the following line to the 'component.mk' files of your project: +2. Enable GCOV to host interface in menuconfig `Component config -> Application Level Tracing -> GCOV to Host Enable`. +3. Enable coverage info generation for necessary source files. To do this add the following line to the 'component.mk' files of your project: `CFLAGS += --coverage` -It will enable coverage info for all source files of your component. If you need to enable the option only for certain files you need to add the following line for every file of interest: +It will enable coverage info for all source files of your component. If you need to enable the option only for certain files the following line should be added for every file of interest: `gcov_example.o: CFLAGS += --coverage` Replace `gcov_example.o` with path to your file. -3. Add call to `esp_gcov_dump` function in your program. This function will wait for command from the host and dump coverage data. The exact place where to put call to `esp_gcov_dump` depends on the program. -Usually it should be placed at the end of the program execution (at exit). See `gcov_example.c` for example. -4. Build, flash and run program. -5. Wait until `esp_gcov_dump` is called. To detect this a call to `printf` can be used (see `gcov_example.c`) or, for example, you can use a LED to indicate the readiness to dump data. -6. Connect OpenOCD to the target and start telnet session with it. -7. Run the following OpenOCD command: -`esp32 gcov` -Example of the command output: +### Hard-coded Dump Call + +This method requires `esp_gcov_dump` to be called from your application's code. Below are additional steps which should be performed after the generic ones to obtain coverage info via hard-coded call. Step 1 is already done for this example project. + +1. Add call to `esp_gcov_dump` function in your program. This function will wait for command from host and dump coverage data. The exact place where to put the call depends on the program. +Usually it should be placed at the end of the program execution (at exit). But if you need to generate GCOV data incrementally `esp_gcov_dump` can be called multiple times. See `gcov_example.c` for example. +2. Build, flash and run program. +3. Wait until `esp_gcov_dump` is called. To detect this a call to `printf` can be used (see `gcov_example.c`) or, for example, you can use a LED to indicate the readiness to dump data. +Another way to detect call to `esp_gcov_dump` is to set breakpoint on that function, start target execution and wait for the target to be stopped. See the next section for respective GDB example. +4. Connect OpenOCD to the target and start telnet session with it. +5. Run the following OpenOCD command: `esp32 gcov dump` + +Example of the command output: +``` +> esp32 gcov dump +Total trace memory: 16384 bytes +Connect targets... +Target halted. PRO_CPU: PC=0x40088BC3 (active) APP_CPU: PC=0x400D14E6 +Targets connected. +Open file 0x1 '/home/alexey/projects/esp/esp-idf/examples/system/gcov/build/main/gcov_example.gcda' +Open file 0x1 '/home/alexey/projects/esp/esp-idf/examples/system/gcov/build/main/gcov_example.gcda' +Open file 0x2 '/home/alexey/projects/esp/esp-idf/examples/system/gcov/build/main/gcov_example_func.gcda' +Open file 0x2 '/home/alexey/projects/esp/esp-idf/examples/system/gcov/build/main/gcov_example_func.gcda' +Disconnect targets... +Target halted. PRO_CPU: PC=0x400D14E6 (active) APP_CPU: PC=0x400D14E6 +Targets disconnected. +``` + +#### Dump Using GDB + +As it was said above breakpoint can be used to detect when `esp_gcov_dump` is called. +The following GDB commands can be used to dump data upon call to `esp_gcov_dump` automatically (you can put them into `gdbinit` file): +``` +b esp_gcov_dump +commands +mon esp32 gcov dump +end +``` +Note that all OpenOCD commands should be invoked in gdb as: `mon `. + +### Instant Run-Time Dump + +Instant dump does not require to call `esp_gcov_dump`, so your application's code does not need to be modified. This method stops target at its current state and executes builtin IDF gcov debug stub function. +Having data dumped target resumes its execution. Below are the steps which should be performed to do instant dump. Step 1 is already done for this example project. + +1. Enable OpenOCD debug stubs in menuconfig `Component config -> ESP32-specific -> OpenOCD debug stubs`. +2. Build, flash and run program. +3. Connect OpenOCD to the target and start telnet session with it. +4. Run the following OpenOCD command: `esp32 gcov` + +Example of the command output: ``` > esp32 gcov Total trace memory: 16384 bytes Connect targets... -Target halted. PRO_CPU: PC=0x400D0CDC (active) APP_CPU: PC=0x00000000 -esp32: target state: halted -Resume targets +Target halted. PRO_CPU: PC=0x400D14DA (active) APP_CPU: PC=0x400D14DA Targets connected. -Open file '/home/alexey/projects/esp/esp-idf/examples/system/gcov/build/main/gcov_example.gcda' -Open file '/home/alexey/projects/esp/esp-idf/examples/system/gcov/build/main/gcov_example.gcda' -Open file '/home/alexey/projects/esp/esp-idf/examples/system/gcov/build/main/gcov_example_func.gcda' -Open file '/home/alexey/projects/esp/esp-idf/examples/system/gcov/build/main/gcov_example_func.gcda' +Open file 0x1 '/home/alexey/projects/esp/esp-idf/examples/system/gcov/build/main/gcov_example.gcda' +Open file 0x1 '/home/alexey/projects/esp/esp-idf/examples/system/gcov/build/main/gcov_example.gcda' +Open file 0x2 '/home/alexey/projects/esp/esp-idf/examples/system/gcov/build/main/gcov_example_func.gcda' +Open file 0x2 '/home/alexey/projects/esp/esp-idf/examples/system/gcov/build/main/gcov_example_func.gcda' +Target halted. PRO_CPU: PC=0x400844CE (active) APP_CPU: PC=0x400855E3 Disconnect targets... -Target halted. PRO_CPU: PC=0x400D17CA (active) APP_CPU: PC=0x400D0CDC -esp32: target state: halted -Resume targets Targets disconnected. > ``` -As shown in the output above there can be errors reported. This is because GCOV code tries to open non-existing coverage data files for reading before writing to them. It is normal situation and actually is not an error. -GCOV will save coverage data for every source file in directories for corresponding object files, usually under root build directory `build`. +### Coverage Data Accumulation + +Coverage data from several dumps are automatically accumulated. So the resulting gcov data files contain statistics since the board reset. Every data dump updates files accordingly. +New data collection is started if target has been reset. ## How To Process Coverage Info diff --git a/examples/system/gcov/main/gcov_example.c b/examples/system/gcov/main/gcov_example.c index c323886ef9..1cfa9ea534 100644 --- a/examples/system/gcov/main/gcov_example.c +++ b/examples/system/gcov/main/gcov_example.c @@ -20,9 +20,11 @@ void blink_dummy_func(void); -void blink_task(void *pvParameter) +static void blink_task(void *pvParameter) { - int dump_gcov_after = 2; + // The first two iterations GCOV data are dumped using call to esp_gcov_dump() and OOCD's "esp32 gcov dump" command. + // After that they can be dumped using OOCD's "esp32 gcov" command only. + int dump_gcov_after = -2; /* Configure the IOMUX register for pad BLINK_GPIO (some pads are muxed to GPIO on reset already, but some default to other functions and need to be switched to GPIO. Consult the @@ -32,21 +34,22 @@ void blink_task(void *pvParameter) gpio_pad_select_gpio(BLINK_GPIO); /* Set the GPIO as a push/pull output */ gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); - while(dump_gcov_after-- > 0) { + + while(1) { /* Blink off (output low) */ gpio_set_level(BLINK_GPIO, 0); - vTaskDelay(1000 / portTICK_PERIOD_MS); + vTaskDelay(500 / portTICK_PERIOD_MS); /* Blink on (output high) */ gpio_set_level(BLINK_GPIO, 1); - vTaskDelay(1000 / portTICK_PERIOD_MS); + vTaskDelay(500 / portTICK_PERIOD_MS); blink_dummy_func(); + if (dump_gcov_after++ < 0) { + // Dump gcov data + printf("Ready to dump GCOV data...\n"); + esp_gcov_dump(); + printf("GCOV data have been dumped.\n"); + } } - - // Dump gcov data - printf("Ready to dump GCOV data...\n"); - esp_gcov_dump(); - printf("GCOV data have been dumped.\n"); - while(1); } void app_main() From bb25d0a348c6bc5431f7c5af1c36b4cb24ced819 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 18 May 2018 15:54:08 +0200 Subject: [PATCH 126/187] DnsFuzzer: Added fuzzer test for exercising lwip/dns receiving DNS responses --- components/lwip/test_afl_host/Makefile | 31 +++-- components/lwip/test_afl_host/dns_di.h | 59 ++++++++++ .../{in_client => in_dhcp_client}/data0.bin | Bin .../{in_client => in_dhcp_client}/data1.bin | Bin .../{in_client => in_dhcp_client}/data2.bin | Bin .../{in_client => in_dhcp_client}/data3.bin | Bin .../{in_client => in_dhcp_client}/data4.bin | Bin .../{in_client => in_dhcp_client}/data5.bin | Bin .../{in_client => in_dhcp_client}/data6.bin | Bin .../{in_client => in_dhcp_client}/data7.bin | Bin .../{in_client => in_dhcp_client}/data8.bin | Bin .../{in_server => in_dhcp_server}/data0.bin | Bin .../{in_server => in_dhcp_server}/data1.bin | Bin .../{in_server => in_dhcp_server}/data2.bin | Bin .../{in_server => in_dhcp_server}/data3.bin | Bin .../{in_server => in_dhcp_server}/data4.bin | Bin .../{in_server => in_dhcp_server}/data5.bin | Bin .../{in_server => in_dhcp_server}/data6.bin | Bin components/lwip/test_afl_host/in_dns/out0.bin | Bin 0 -> 77 bytes .../lwip/test_afl_host/in_dns/out10.bin | Bin 0 -> 53 bytes .../lwip/test_afl_host/in_dns/out28.bin | Bin 0 -> 53 bytes .../lwip/test_afl_host/in_dns/out29.bin | Bin 0 -> 135 bytes .../lwip/test_afl_host/in_dns/out30.bin | Bin 0 -> 301 bytes .../lwip/test_afl_host/in_dns/out31.bin | Bin 0 -> 113 bytes .../lwip/test_afl_host/in_dns/out32.bin | Bin 0 -> 117 bytes .../lwip/test_afl_host/in_dns/out33.bin | Bin 0 -> 360 bytes .../lwip/test_afl_host/in_dns/out34.bin | Bin 0 -> 57 bytes .../lwip/test_afl_host/in_dns/out35.bin | Bin 0 -> 85 bytes .../lwip/test_afl_host/in_dns/out36.bin | Bin 0 -> 300 bytes .../lwip/test_afl_host/in_dns/out37.bin | Bin 0 -> 312 bytes .../lwip/test_afl_host/in_dns/out38.bin | Bin 0 -> 164 bytes components/lwip/test_afl_host/network_mock.c | 109 +++++++++++++++++- .../{test_client.c => test_dhcp_client.c} | 0 .../{test_server.c => test_dhcp_server.c} | 0 components/lwip/test_afl_host/test_dns.c | 79 +++++++++++++ 35 files changed, 262 insertions(+), 16 deletions(-) create mode 100644 components/lwip/test_afl_host/dns_di.h rename components/lwip/test_afl_host/{in_client => in_dhcp_client}/data0.bin (100%) rename components/lwip/test_afl_host/{in_client => in_dhcp_client}/data1.bin (100%) rename components/lwip/test_afl_host/{in_client => in_dhcp_client}/data2.bin (100%) rename components/lwip/test_afl_host/{in_client => in_dhcp_client}/data3.bin (100%) rename components/lwip/test_afl_host/{in_client => in_dhcp_client}/data4.bin (100%) rename components/lwip/test_afl_host/{in_client => in_dhcp_client}/data5.bin (100%) rename components/lwip/test_afl_host/{in_client => in_dhcp_client}/data6.bin (100%) rename components/lwip/test_afl_host/{in_client => in_dhcp_client}/data7.bin (100%) rename components/lwip/test_afl_host/{in_client => in_dhcp_client}/data8.bin (100%) rename components/lwip/test_afl_host/{in_server => in_dhcp_server}/data0.bin (100%) rename components/lwip/test_afl_host/{in_server => in_dhcp_server}/data1.bin (100%) rename components/lwip/test_afl_host/{in_server => in_dhcp_server}/data2.bin (100%) rename components/lwip/test_afl_host/{in_server => in_dhcp_server}/data3.bin (100%) rename components/lwip/test_afl_host/{in_server => in_dhcp_server}/data4.bin (100%) rename components/lwip/test_afl_host/{in_server => in_dhcp_server}/data5.bin (100%) rename components/lwip/test_afl_host/{in_server => in_dhcp_server}/data6.bin (100%) create mode 100644 components/lwip/test_afl_host/in_dns/out0.bin create mode 100644 components/lwip/test_afl_host/in_dns/out10.bin create mode 100644 components/lwip/test_afl_host/in_dns/out28.bin create mode 100644 components/lwip/test_afl_host/in_dns/out29.bin create mode 100644 components/lwip/test_afl_host/in_dns/out30.bin create mode 100644 components/lwip/test_afl_host/in_dns/out31.bin create mode 100644 components/lwip/test_afl_host/in_dns/out32.bin create mode 100644 components/lwip/test_afl_host/in_dns/out33.bin create mode 100644 components/lwip/test_afl_host/in_dns/out34.bin create mode 100644 components/lwip/test_afl_host/in_dns/out35.bin create mode 100644 components/lwip/test_afl_host/in_dns/out36.bin create mode 100644 components/lwip/test_afl_host/in_dns/out37.bin create mode 100644 components/lwip/test_afl_host/in_dns/out38.bin rename components/lwip/test_afl_host/{test_client.c => test_dhcp_client.c} (100%) rename components/lwip/test_afl_host/{test_server.c => test_dhcp_server.c} (100%) create mode 100644 components/lwip/test_afl_host/test_dns.c diff --git a/components/lwip/test_afl_host/Makefile b/components/lwip/test_afl_host/Makefile index a3da02e11e..d20537977d 100644 --- a/components/lwip/test_afl_host/Makefile +++ b/components/lwip/test_afl_host/Makefile @@ -5,14 +5,21 @@ INC_DIRS=-I . -I $(COMPONENTS_DIR)/lwip/include/lwip -I $(COMPONENTS_DIR)/lwip/i TEST_NAME=test FUZZ=afl-fuzz LD=$(CC) -ifeq ($(MODE),client) - DHCP_C_DEPENDENCY_INJECTION=-include dhcp_di.h - OBJECTS=dhcp.o network_mock.o test_client.o - SAMPLE_PACKETS=in_client -else - DHCP_C_DEPENDENCY_INJECTION=-include dhcpserver_di.h - OBJECTS=dhcpserver.o test_server.o network_mock.o - SAMPLE_PACKETS=in_server +ifeq ($(MODE),dhcp_client) + DEPENDENCY_INJECTION=-include dhcp_di.h + OBJECTS=dhcp.o network_mock.o test_dhcp_client.o + SAMPLE_PACKETS=in_dhcp_client +else ifeq ($(MODE),dhcp_server) + DEPENDENCY_INJECTION=-include dhcpserver_di.h + OBJECTS=dhcpserver.o test_dhcp_server.o network_mock.o + SAMPLE_PACKETS=in_dhcp_server +else ifeq ($(MODE),dns) + CFLAGS+=-DNOT_MOCK_DNS + DEPENDENCY_INJECTION=-include dns_di.h + OBJECTS=dns.o test_dns.o network_mock.o + SAMPLE_PACKETS=in_dns +else + $(error Please specify MODE: dhcp_server, dhcp_client, dns) endif ifeq ($(INSTR),off) @@ -27,13 +34,17 @@ CFLAGS+=$(INC_DIRS) all: $(TEST_NAME) +dns.o: ../core/dns.c + @echo "[CC] $<" + @$(CC) $(CFLAGS) $(DEPENDENCY_INJECTION) -c $< -o $@ + dhcp.o: ../core/ipv4/dhcp.c @echo "[CC] $<" - @$(CC) $(CFLAGS) $(DHCP_C_DEPENDENCY_INJECTION) -c $< -o $@ + @$(CC) $(CFLAGS) $(DEPENDENCY_INJECTION) -c $< -o $@ dhcpserver.o: ../apps/dhcpserver.c @echo "[CC] $<" - @$(CC) $(CFLAGS) $(DHCP_C_DEPENDENCY_INJECTION) -c $< -o $@ + @$(CC) $(CFLAGS) $(DEPENDENCY_INJECTION) -c $< -o $@ %.o: %.c @echo "[CC] $<" diff --git a/components/lwip/test_afl_host/dns_di.h b/components/lwip/test_afl_host/dns_di.h new file mode 100644 index 0000000000..4cb0b715cf --- /dev/null +++ b/components/lwip/test_afl_host/dns_di.h @@ -0,0 +1,59 @@ +/* + * dns.c dependecy injection -- preincluded to inject interface test functions into static variables + * + */ +#include "no_warn_host.h" + +#include "lwip/opt.h" +#include "lwip/udp.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/dns.h" +#include "lwip/ip_addr.h" + +#define ipaddr_aton(cp, addr) ip4addr_aton(cp, addr) + +extern uint32_t g_random_numbers[8]; +extern uint32_t g_random_numbers_cnt; + +void __assert_func(const char *file, int line, const char *func, const char *expr) +{ + printf("Assert failed in %s, %s:%d (%s)", func, file, line, expr); + abort(); +} + +int ip4addr_aton(const char *cp, ip4_addr_t *addr) +{ + return 0; +} + +static err_t dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, void *callback_arg, u8_t dns_addrtype); +static void dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); + +void (*dns_test_static_dns_recv)(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) = NULL; +err_t (*dns_test_static_dns_enqueue)(const char *name, size_t hostnamelen, dns_found_callback found, void *callback_arg, u8_t dns_addrtype) = NULL; + + +void dns_test_init_di() +{ + dns_test_static_dns_recv = dns_recv; + dns_test_static_dns_enqueue = dns_enqueue; +} + +err_t dns_test_dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, void *callback_arg, u8_t dns_addrtype) +{ + return dns_test_static_dns_enqueue(name, hostnamelen, found, callback_arg, dns_addrtype); +} + +void dns_test_dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) +{ + dns_test_static_dns_recv(s, pcb, p, addr, port); +} + +void dns_test_inject_port_and_txid(int port, int txid) +{ + // inject random numbers + g_random_numbers[0] = port; //for port + g_random_numbers[1] = txid; //for txid + g_random_numbers_cnt = 0; // let's start with the port +} \ No newline at end of file diff --git a/components/lwip/test_afl_host/in_client/data0.bin b/components/lwip/test_afl_host/in_dhcp_client/data0.bin similarity index 100% rename from components/lwip/test_afl_host/in_client/data0.bin rename to components/lwip/test_afl_host/in_dhcp_client/data0.bin diff --git a/components/lwip/test_afl_host/in_client/data1.bin b/components/lwip/test_afl_host/in_dhcp_client/data1.bin similarity index 100% rename from components/lwip/test_afl_host/in_client/data1.bin rename to components/lwip/test_afl_host/in_dhcp_client/data1.bin diff --git a/components/lwip/test_afl_host/in_client/data2.bin b/components/lwip/test_afl_host/in_dhcp_client/data2.bin similarity index 100% rename from components/lwip/test_afl_host/in_client/data2.bin rename to components/lwip/test_afl_host/in_dhcp_client/data2.bin diff --git a/components/lwip/test_afl_host/in_client/data3.bin b/components/lwip/test_afl_host/in_dhcp_client/data3.bin similarity index 100% rename from components/lwip/test_afl_host/in_client/data3.bin rename to components/lwip/test_afl_host/in_dhcp_client/data3.bin diff --git a/components/lwip/test_afl_host/in_client/data4.bin b/components/lwip/test_afl_host/in_dhcp_client/data4.bin similarity index 100% rename from components/lwip/test_afl_host/in_client/data4.bin rename to components/lwip/test_afl_host/in_dhcp_client/data4.bin diff --git a/components/lwip/test_afl_host/in_client/data5.bin b/components/lwip/test_afl_host/in_dhcp_client/data5.bin similarity index 100% rename from components/lwip/test_afl_host/in_client/data5.bin rename to components/lwip/test_afl_host/in_dhcp_client/data5.bin diff --git a/components/lwip/test_afl_host/in_client/data6.bin b/components/lwip/test_afl_host/in_dhcp_client/data6.bin similarity index 100% rename from components/lwip/test_afl_host/in_client/data6.bin rename to components/lwip/test_afl_host/in_dhcp_client/data6.bin diff --git a/components/lwip/test_afl_host/in_client/data7.bin b/components/lwip/test_afl_host/in_dhcp_client/data7.bin similarity index 100% rename from components/lwip/test_afl_host/in_client/data7.bin rename to components/lwip/test_afl_host/in_dhcp_client/data7.bin diff --git a/components/lwip/test_afl_host/in_client/data8.bin b/components/lwip/test_afl_host/in_dhcp_client/data8.bin similarity index 100% rename from components/lwip/test_afl_host/in_client/data8.bin rename to components/lwip/test_afl_host/in_dhcp_client/data8.bin diff --git a/components/lwip/test_afl_host/in_server/data0.bin b/components/lwip/test_afl_host/in_dhcp_server/data0.bin similarity index 100% rename from components/lwip/test_afl_host/in_server/data0.bin rename to components/lwip/test_afl_host/in_dhcp_server/data0.bin diff --git a/components/lwip/test_afl_host/in_server/data1.bin b/components/lwip/test_afl_host/in_dhcp_server/data1.bin similarity index 100% rename from components/lwip/test_afl_host/in_server/data1.bin rename to components/lwip/test_afl_host/in_dhcp_server/data1.bin diff --git a/components/lwip/test_afl_host/in_server/data2.bin b/components/lwip/test_afl_host/in_dhcp_server/data2.bin similarity index 100% rename from components/lwip/test_afl_host/in_server/data2.bin rename to components/lwip/test_afl_host/in_dhcp_server/data2.bin diff --git a/components/lwip/test_afl_host/in_server/data3.bin b/components/lwip/test_afl_host/in_dhcp_server/data3.bin similarity index 100% rename from components/lwip/test_afl_host/in_server/data3.bin rename to components/lwip/test_afl_host/in_dhcp_server/data3.bin diff --git a/components/lwip/test_afl_host/in_server/data4.bin b/components/lwip/test_afl_host/in_dhcp_server/data4.bin similarity index 100% rename from components/lwip/test_afl_host/in_server/data4.bin rename to components/lwip/test_afl_host/in_dhcp_server/data4.bin diff --git a/components/lwip/test_afl_host/in_server/data5.bin b/components/lwip/test_afl_host/in_dhcp_server/data5.bin similarity index 100% rename from components/lwip/test_afl_host/in_server/data5.bin rename to components/lwip/test_afl_host/in_dhcp_server/data5.bin diff --git a/components/lwip/test_afl_host/in_server/data6.bin b/components/lwip/test_afl_host/in_dhcp_server/data6.bin similarity index 100% rename from components/lwip/test_afl_host/in_server/data6.bin rename to components/lwip/test_afl_host/in_dhcp_server/data6.bin diff --git a/components/lwip/test_afl_host/in_dns/out0.bin b/components/lwip/test_afl_host/in_dns/out0.bin new file mode 100644 index 0000000000000000000000000000000000000000..8a68ce66350feb3cb04cd9edc6602d281d7bf717 GIT binary patch literal 77 zcmezNscBmr8 WoCBf<3_-FC3`{}{ENgCxp9264x)VnL literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/in_dns/out10.bin b/components/lwip/test_afl_host/in_dns/out10.bin new file mode 100644 index 0000000000000000000000000000000000000000..e9f8c73fcbd2a911a8677624f6ba4303c5db1cdf GIT binary patch literal 53 zcmYf9Xl!6$1VSKSOV2FHNlfBQEiNcZEiTSXV@l3r07)L;fhb|T#=vqpUUw1zTWk!p literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/in_dns/out28.bin b/components/lwip/test_afl_host/in_dns/out28.bin new file mode 100644 index 0000000000000000000000000000000000000000..92ed4c510b1b63a38cbf20bf85188ef261530906 GIT binary patch literal 53 zcmdm_+t|Rs2!ueumY!LXlbFPrT3k?+T3no&#+01L0Fpew15v^h!N77kUUw1zRpAUP literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/in_dns/out29.bin b/components/lwip/test_afl_host/in_dns/out29.bin new file mode 100644 index 0000000000000000000000000000000000000000..40dc982a03372303489b1d769cfc07bd671e0233 GIT binary patch literal 135 zcmccA)7Zek$iT_~1Y9MVxv9FjiOKoJtce8$IjPLa`MC^0S;hlAKoyJ(4BV0oq8wmV q`Nb8C>FkM#1v#0y=?7#F7=e@l&A7(EBKX(jFB-oVm2Za5{|f-t)*)g5 literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/in_dns/out30.bin b/components/lwip/test_afl_host/in_dns/out30.bin new file mode 100644 index 0000000000000000000000000000000000000000..d7eff8b989a174190e8ad9bd6c238f3e2e844c5e GIT binary patch literal 301 zcmY$dYHVO&WZ+<6VPIe>$jnRUOwLFwDoILBEMd+|Enxu4F&^LnkwE4i1{NcMtLi9x z!Q*#P`JeWq@P+R%pz?!NQ28NcD13oO8m6Y1R0n>F7SNFAjzIrtZQg)WX73T zUYr7C8yPbt=QEXNGaxAvW&=uC8koY=m{=Z=Mv@i-NgEo$r43D)lk;Dd;WMBYcrko`9_>{b2-QpCM_|lXDMgv9zWS_TaIoH_Z)i8&eh#U%`EdHG5CDV0F=Wr;bNDL|7!iueQ=7+5wi Ka9TBhGynkWQ5i=7 literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/in_dns/out33.bin b/components/lwip/test_afl_host/in_dns/out33.bin new file mode 100644 index 0000000000000000000000000000000000000000..dc5b666c7d4bec296dfd366ba6dd4d15e38337d2 GIT binary patch literal 360 zcmYe_(AdDh$iT_K!oa{%l$n>!nUSBIom!b#P{5p*TEYO7V?4mazzU=pSdKCni4>P4 zrev1pmK7xH8kw0|8X6c_SaOyY>!v0am*^TYr{*MaCgvtq<>w`q7c(d4=Q12H0GR4eG>WWLE6`7OwNr9*9hkono-{lAgN_CwO&A-OBJ<6bcI-aj z%D@D&pG}8BoIS5t*U-?=k`w5-6fm1PzbKsnNr@y_iMgdQOo_1(Q*u62X*RMVVK$&% aBV$vT8Y9aCu}Efsr7ew3VA7^W2c!Wy{!@AY literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/in_dns/out34.bin b/components/lwip/test_afl_host/in_dns/out34.bin new file mode 100644 index 0000000000000000000000000000000000000000..55e9f0c3d8c0753d43c8e0a81f9acebb9afd5eea GIT binary patch literal 57 zcmeYiXl!6$1VSL-%1taONiE9FFD~IsEiNcZEiTSXV@l3r04X@Y15w5l!N77kUUw1z Dj+G6D literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/in_dns/out35.bin b/components/lwip/test_afl_host/in_dns/out35.bin new file mode 100644 index 0000000000000000000000000000000000000000..8d7c652e0abbea48110c41e3d9cb43c432191e02 GIT binary patch literal 85 zcmcbs+t|Rs$iTz^1RRM~=4K{FmZnT)`E0qxsmXaM%z3FL3_y9t13V0@K$?LemqCyv jx!A~vxx65mwag$nCGUXz0TYlC1_pK)29_Deg%4F%WZ+<6VPIfREXZUpPEF5E%`0Kb%x3_KGaldpkqitBwhSz0Q#W~|@K116 zq41|Hw?N@fJ===H-?jEQ3V+J?%c%SiGgQ9+(gOkvOi=s9+4G8Z4GoQrITOo^Q$TEE z=KP{`1|%htU?pY-W-uiN7EHV9rY| GVE_Ozr#yK8 literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/in_dns/out37.bin b/components/lwip/test_afl_host/in_dns/out37.bin new file mode 100644 index 0000000000000000000000000000000000000000..9c06a7b29259c34a1ae85cb22042c77e184a5701 GIT binary patch literal 312 zcmaFu+1S9q$iTtC!oa{&U|^}6oS#>cm|RlKl$OewSWu9Ys+*Em%$%26!T?mpcz_2) zGB7aoF|Y{!n9PU9UxCIqLgSmE@rBX&rfB>QG``RQNd_jM{Y*zMGDx!L73&(Bnj3K@ zmKOuvsB2)tl$_60n$3WuNQ@0AVPs(rQ)6t(oSdJFtU?&1!ra6HrozbbfEtnk;$T}0 PjZ9$jhDOZ!Md=Ixa3@J? literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/in_dns/out38.bin b/components/lwip/test_afl_host/in_dns/out38.bin new file mode 100644 index 0000000000000000000000000000000000000000..31bf8c2da53e77c3412444de1050f4ee22c1e5bb GIT binary patch literal 164 zcmZQ-YHVO&WMF0h0^YLX?oNV&=Tm5(c0`#sfSI ztU#K9g_A)~uspH6Sht`kKSehwu~OH-#FDuzvj9~idwFJFN`86q0gVH;5S>gG46>Ly cIg)eoOH&dH3V;gBK^8GE02Q)m1aCVB0JRG)i~s-t literal 0 HcmV?d00001 diff --git a/components/lwip/test_afl_host/network_mock.c b/components/lwip/test_afl_host/network_mock.c index 9e9ae48299..cf35fdb63d 100644 --- a/components/lwip/test_afl_host/network_mock.c +++ b/components/lwip/test_afl_host/network_mock.c @@ -9,23 +9,84 @@ const ip_addr_t ip_addr_any; const ip_addr_t ip_addr_broadcast; +const ip_addr_t ip_addr_any_type; struct ip_globals ip_data; struct netif *netif_list; +struct udp_pcb mock_pcb; +uint32_t g_random_numbers[8] = {0}; +uint32_t g_random_numbers_cnt = 0; +struct pbuf* pbuf_skip(struct pbuf* in, u16_t in_offset, u16_t* out_offset) +{ + u16_t offset_left = in_offset; + struct pbuf* q = in; + + /* get the correct pbuf */ + while ((q != NULL) && (q->len <= offset_left)) { + offset_left -= q->len; + q = q->next; + } + if (out_offset != NULL) { + *out_offset = offset_left; + } + return q; +} + +void pbuf_put_at(struct pbuf* p, u16_t offset, u8_t data) +{ + u16_t q_idx; + struct pbuf* q = pbuf_skip(p, offset, &q_idx); + + /* write requested data if pbuf is OK */ + if ((q != NULL) && (q->len > q_idx)) { + ((u8_t*)q->payload)[q_idx] = data; + } +} + +u8_t pbuf_get_at(struct pbuf* p, u16_t offset) +{ + u16_t q_idx; + struct pbuf* q = pbuf_skip(p, offset, &q_idx); + + /* return requested data if pbuf is OK */ + if ((q != NULL) && (q->len > q_idx)) { + return ((u8_t*)q->payload)[q_idx]; + } + return 0; +} + +err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len) +{ + return ERR_OK; +} + +err_t pbuf_take_at(struct pbuf *buf, const void *dataptr, u16_t len, u16_t offset) +{ + return ERR_OK; +} + +struct udp_pcb * udp_new_ip_type(u8_t type) +{ + return &mock_pcb; +} + u16_t lwip_htons(u16_t n) { - return 0; + return ((n & 0xff) << 8) | ((n & 0xff00) >> 8); } u32_t lwip_htonl(u32_t n) { - return 0; +return ((n & 0xff) << 24) | + ((n & 0xff00) << 8) | + ((n & 0xff0000UL) >> 8) | + ((n & 0xff000000UL) >> 24); } esp_err_t tcpip_adapter_get_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info) { - return ESP_OK; + return ESP_OK; } struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type) @@ -84,13 +145,16 @@ void udp_disconnect(struct udp_pcb *pcb) { } +#ifndef NOT_MOCK_DNS void dns_setserver(u8_t numdns, const ip_addr_t *dnsserver) { } +#endif uint32_t esp_random(void) { - return 0; + // Preparation for injecting favorable random numbers + return g_random_numbers[g_random_numbers_cnt++ % 8]; } err_t etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q) @@ -100,7 +164,7 @@ err_t etharp_query(struct netif *netif, const ip4_addr_t *ipaddr, struct pbuf *q u32_t lwip_ntohl(u32_t x) { - return 0; + return lwip_htonl(x); } void netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, @@ -120,10 +184,43 @@ void pbuf_realloc(struct pbuf *p, u16_t size) } } -u16_t pbuf_copy_partial(struct pbuf *p, void *dataptr, u16_t len, u16_t offset) +u16_t pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset) { + struct pbuf *p; + u16_t left; + u16_t buf_copy_len; + u16_t copied_total = 0; + + LWIP_ERROR("pbuf_copy_partial: invalid buf", (buf != NULL), return 0;); + LWIP_ERROR("pbuf_copy_partial: invalid dataptr", (dataptr != NULL), return 0;); + + left = 0; + + if ((buf == NULL) || (dataptr == NULL)) { return 0; + } + + /* Note some systems use byte copy if dataptr or one of the pbuf payload pointers are unaligned. */ + for (p = buf; len != 0 && p != NULL; p = p->next) { + if ((offset != 0) && (offset >= p->len)) { + /* don't copy from this buffer -> on to the next */ + offset -= p->len; + } else { + /* copy from this buffer. maybe only partially. */ + buf_copy_len = p->len - offset; + if (buf_copy_len > len) + buf_copy_len = len; + /* copy the necessary parts of the buffer */ + MEMCPY(&((char*)dataptr)[left], &((char*)p->payload)[offset], buf_copy_len); + copied_total += buf_copy_len; + left += buf_copy_len; + len -= buf_copy_len; + offset = 0; + } + } + return copied_total; } + err_t udp_connect(struct udp_pcb *pcb, const ip_addr_t *ipaddr, u16_t port) { return ESP_OK; diff --git a/components/lwip/test_afl_host/test_client.c b/components/lwip/test_afl_host/test_dhcp_client.c similarity index 100% rename from components/lwip/test_afl_host/test_client.c rename to components/lwip/test_afl_host/test_dhcp_client.c diff --git a/components/lwip/test_afl_host/test_server.c b/components/lwip/test_afl_host/test_dhcp_server.c similarity index 100% rename from components/lwip/test_afl_host/test_server.c rename to components/lwip/test_afl_host/test_dhcp_server.c diff --git a/components/lwip/test_afl_host/test_dns.c b/components/lwip/test_afl_host/test_dns.c new file mode 100644 index 0000000000..131a8b3ed7 --- /dev/null +++ b/components/lwip/test_afl_host/test_dns.c @@ -0,0 +1,79 @@ +#include "no_warn_host.h" + +#include "lwip/opt.h" +#include "lwip/udp.h" +#include "lwip/mem.h" +#include "lwip/memp.h" +#include "lwip/dns.h" +#include "lwip/ip_addr.h" + +#include + +const ip_addr_t ip_addr_any; +const ip_addr_t ip_addr_broadcast; +struct ip_globals ip_data; +struct netif *netif_list; +struct netif mynetif; +ip4_addr_t server_ip; + +// +// Dependency injected test functions +void dns_test_dns_recv(void *s, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port); +void dns_test_inject_port_and_txid(int port, int txid); + +void dns_test_init_di(); +err_t dns_test_dns_enqueue(const char *name, size_t hostnamelen, dns_found_callback found, void *callback_arg, u8_t dns_addrtype); + +// +// Test starts here +// +int main(int argc, char** argv) +{ + uint8_t *buf; + struct pbuf *p; + FILE *file; + size_t len = 1460; + + dns_test_init_di(); + +#ifdef INSTR_IS_OFF + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + buf = p->payload; + memset(buf, 0, 1460); + if (argc != 2) + { + printf("Non-instrumentation mode: please supply a file name created by AFL to reproduce crash\n"); + return 1; + } + // + // Note: parameter1 is a file (mangled packet) which caused the crash + file = fopen(argv[1], "r"); + if (file) { + len = fread(buf, 1, 1460, file); + } + fclose(file); + int i; + for (i=0; i<1; i++) { +#else + while (__AFL_LOOP(1000)) { + p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); + buf = p->payload; + memset(buf, 0, 1460); + size_t len = read(0, buf, 1460); +#endif + p->len = len; + p->tot_len = len; + p->next = NULL; + + // Pretend that the response is from our pending querries + dns_test_inject_port_and_txid(1024, (buf[0]<<8) + buf[1]); + dns_test_dns_enqueue("test", 4, NULL, NULL, 0); + + // Process the packet + dns_test_dns_recv(NULL, NULL, p, &ip_addr_any, 0); + } + + + + return 0; +} From 3f031cdd9df48f6958eda54812b6f723a8a5c1f8 Mon Sep 17 00:00:00 2001 From: zhangyanjiao Date: Mon, 9 Apr 2018 11:01:44 +0800 Subject: [PATCH 127/187] add event SYSTEM_EVENT_AP_STAIPASSIGNED --- components/esp32/event_default_handlers.c | 4 ++++ components/esp32/include/esp_event.h | 1 + components/esp32/lib | 2 +- components/lwip/apps/dhcpserver.c | 18 ++++++++++++++++++ components/lwip/include/lwip/apps/dhcpserver.h | 3 +++ components/tcpip_adapter/tcpip_adapter_lwip.c | 11 +++++++++++ 6 files changed, 38 insertions(+), 1 deletion(-) diff --git a/components/esp32/event_default_handlers.c b/components/esp32/event_default_handlers.c index 7de0cbb746..6a19b73803 100644 --- a/components/esp32/event_default_handlers.c +++ b/components/esp32/event_default_handlers.c @@ -334,6 +334,10 @@ static esp_err_t esp_system_event_debug(system_event_t *event) MAC2STR(stadisconnected->mac), stadisconnected->aid); break; } + case SYSTEM_EVENT_AP_STAIPASSIGNED: { + ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STAIPASSIGNED"); + break; + } case SYSTEM_EVENT_AP_PROBEREQRECVED: { system_event_ap_probe_req_rx_t *ap_probereqrecved = &event->event_info.ap_probereqrecved; ESP_LOGD(TAG, "SYSTEM_EVENT_AP_PROBEREQRECVED, rssi:%d, mac:" MACSTR, \ diff --git a/components/esp32/include/esp_event.h b/components/esp32/include/esp_event.h index 53c416c29f..3bb2a77b9f 100644 --- a/components/esp32/include/esp_event.h +++ b/components/esp32/include/esp_event.h @@ -44,6 +44,7 @@ typedef enum { SYSTEM_EVENT_AP_STOP, /**< ESP32 soft-AP stop */ SYSTEM_EVENT_AP_STACONNECTED, /**< a station connected to ESP32 soft-AP */ SYSTEM_EVENT_AP_STADISCONNECTED, /**< a station disconnected from ESP32 soft-AP */ + SYSTEM_EVENT_AP_STAIPASSIGNED, /**< ESP32 soft-AP assign an IP to a connected station */ SYSTEM_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */ SYSTEM_EVENT_GOT_IP6, /**< ESP32 station or ap or ethernet interface v6IP addr is preferred */ SYSTEM_EVENT_ETH_START, /**< ESP32 ethernet start */ diff --git a/components/esp32/lib b/components/esp32/lib index 04e656c303..c1d0ac3625 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 04e656c303d129c479b5c019ea364e11c6f96f4d +Subproject commit c1d0ac3625db5da98d1e9c64b8cd0d1261443810 diff --git a/components/lwip/apps/dhcpserver.c b/components/lwip/apps/dhcpserver.c index f43932d4df..a79d0fd638 100644 --- a/components/lwip/apps/dhcpserver.c +++ b/components/lwip/apps/dhcpserver.c @@ -95,6 +95,7 @@ static dhcps_lease_t dhcps_poll; static dhcps_time_t dhcps_lease_time = DHCPS_LEASE_TIME_DEF; //minute static dhcps_offer_t dhcps_offer = 0xFF; static dhcps_offer_t dhcps_dns = 0x00; +static dhcps_cb_t dhcps_cb; /****************************************************************************** * FunctionName : dhcps_option_info @@ -679,6 +680,10 @@ static void send_ack(struct dhcps_msg *m, u16_t len) DHCPS_LOG("dhcps: send_ack>>udp_sendto result %x\n", SendAck_err_t); #endif + if (SendAck_err_t == ERR_OK) { + dhcps_cb(m->yiaddr); + } + if (p->ref != 0) { #if DHCPS_DEBUG DHCPS_LOG("udhcp: send_ack>>free pbuf\n"); @@ -1105,6 +1110,19 @@ static void dhcps_poll_set(u32_t ip) } + +/****************************************************************************** + * FunctionName : dhcps_set_new_lease_cb + * Description : set callback for dhcp server when it assign an IP + * to the connected dhcp client + * Parameters : cb -- callback for dhcp server + * Returns : none +*******************************************************************************/ +void dhcps_set_new_lease_cb(dhcps_cb_t cb) +{ + dhcps_cb = cb; +} + /****************************************************************************** * FunctionName : dhcps_start * Description : start dhcp server function diff --git a/components/lwip/include/lwip/apps/dhcpserver.h b/components/lwip/include/lwip/apps/dhcpserver.h index 015ffe6e09..a6ad51d995 100644 --- a/components/lwip/include/lwip/apps/dhcpserver.h +++ b/components/lwip/include/lwip/apps/dhcpserver.h @@ -70,6 +70,8 @@ typedef struct { dhcps_lease_t dhcps_poll; } dhcps_options_t; +typedef void (*dhcps_cb_t)(u8_t client_ip[4]); + static inline bool dhcps_router_enabled (dhcps_offer_t offer) { return (offer & OFFER_ROUTER) != 0; @@ -87,6 +89,7 @@ void dhcps_set_option_info(u8_t op_id, void *opt_info, u32_t opt_len); bool dhcp_search_ip_on_mac(u8_t *mac, ip4_addr_t *ip); void dhcps_dns_setserver(const ip_addr_t *dnsserver); ip4_addr_t dhcps_dns_getserver(); +void dhcps_set_new_lease_cb(dhcps_cb_t cb); #endif diff --git a/components/tcpip_adapter/tcpip_adapter_lwip.c b/components/tcpip_adapter/tcpip_adapter_lwip.c index d9d6b5a614..8198cb3446 100644 --- a/components/tcpip_adapter/tcpip_adapter_lwip.c +++ b/components/tcpip_adapter/tcpip_adapter_lwip.c @@ -85,6 +85,15 @@ static void tcpip_adapter_api_cb(void* api_msg) return; } +static void tcpip_adapter_dhcps_cb(u8_t client_ip[4]) +{ + ESP_LOGI(TAG,"softAP assign IP to station,IP is: %d.%d.%d.%d", + client_ip[0],client_ip[1],client_ip[2],client_ip[3]); + system_event_t evt; + evt.event_id = SYSTEM_EVENT_AP_STAIPASSIGNED; + esp_event_send(&evt); +} + void tcpip_adapter_init(void) { int ret; @@ -181,6 +190,8 @@ esp_err_t tcpip_adapter_start(tcpip_adapter_if_t tcpip_if, uint8_t *mac, tcpip_a netif_set_up(esp_netif[tcpip_if]); if (dhcps_status == TCPIP_ADAPTER_DHCP_INIT) { + dhcps_set_new_lease_cb(tcpip_adapter_dhcps_cb); + dhcps_start(esp_netif[tcpip_if], ip_info->ip); ESP_LOGD(TAG, "dhcp server start:(ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR ")", From 22e21b38f7a619e70ae2d3c229ae6a6290b92552 Mon Sep 17 00:00:00 2001 From: wangmengyang Date: Sun, 8 Apr 2018 19:19:47 +0800 Subject: [PATCH 128/187] component/bt: implement bluetooth modem sleep mode, one mode for BLE only and another for dual mode bluetooth 1. provide options for bluetooth low power mode 2. provide two options for bluetooth low power clock: main XTAL and external 32kHz XTAL 3. provide function and callbacks to control bluetooth low power mode, including enable/disable sleep, software wakeup request, low power clock settings, check power state, etc 4. modify vhci API vhci_host_send_packet to use blocking mode 5. note that DFS and bluetooth modem sleep can not be used together currently. --- components/bt/Kconfig | 42 ++++ components/bt/bt.c | 237 +++++++++++++++++- components/bt/include/esp_bt.h | 58 ++++- components/bt/lib | 2 +- .../driver/include/driver/periph_ctrl.h | 2 + components/driver/periph_ctrl.c | 8 + components/esp32/ld/esp32.rom.ld | 1 + components/soc/esp32/include/soc/dport_reg.h | 4 + components/soc/esp32/rtc_clk.c | 4 + components/soc/esp32/rtc_time.c | 12 +- 10 files changed, 354 insertions(+), 16 deletions(-) diff --git a/components/bt/Kconfig b/components/bt/Kconfig index 37d660cf98..853265d653 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -64,6 +64,48 @@ config BT_HCI_UART_BAUDRATE UART Baudrate for HCI. Please use standard baudrate. endmenu +menu "MODEM SLEEP Options" + visible if BT_ENABLED + +config BTDM_CONTROLLER_MODEM_SLEEP + bool "Bluetooth modem sleep" + depends on BT_ENABLED + default y + help + Enable/disable bluetooth controller low power mode. + Note that currently there is problem in the combination use of bluetooth modem sleep and Dynamic Frequency Scaling(DFS). So do not enable DFS if bluetooth modem sleep is in use. + +choice BTDM_MODEM_SLEEP_MODE + prompt "Bluetooth Modem sleep mode" + depends on BTDM_CONTROLLER_MODEM_SLEEP + help + To select which strategy to use for modem sleep + +config BTDM_MODEM_SLEEP_MODE_ORIG + bool "ORIG Mode(sleep with low power clock)" + help + ORIG mode is a deep sleep mode that can be used for dual mode controller. In this mode, bluetooth controller sleeps between BR/EDR frames and BLE events. A low power clock is used to maintain bluetooth reference clock. +config BTDM_MODEM_SLEEP_MODE_EVED + bool "EVED Mode " + help + This mode is for BLE only. +endchoice + +choice BTDM_LOW_POWER_CLOCK + prompt "Bluetooth low power clock" + depends on BTDM_MODEM_SLEEP_MODE_ORIG + help + Select the low power clock source for bluetooth controller + +config BTDM_LPCLK_SEL_MAIN_XTAL + bool "Main crystal" +config BTDM_LPCLK_SEL_EXT_32K_XTAL + bool "External 32kHz crystal" + depends on ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL +endchoice + +endmenu + menuconfig BLUEDROID_ENABLED bool "Bluedroid Enable" depends on BTDM_CONTROLLER_HCI_MODE_VHCI diff --git a/components/bt/bt.c b/components/bt/bt.c index 3a274a7033..68f5dee7fd 100644 --- a/components/bt/bt.c +++ b/components/bt/bt.c @@ -39,6 +39,10 @@ #include "esp_pm.h" #include "esp_ipc.h" #include "driver/periph_ctrl.h" +#include "soc/rtc.h" +#include "soc/rtc_cntl_reg.h" +#include "esp_clk.h" + #if CONFIG_BT_ENABLED @@ -61,7 +65,24 @@ extern int btdm_controller_disable(esp_bt_mode_t mode); extern uint8_t btdm_controller_get_mode(void); extern const char *btdm_controller_get_compile_version(void); extern void btdm_rf_bb_init(void); +extern void btdm_controller_enable_sleep(bool enable); +#define BTDM_MODEM_SLEEP_MODE_NONE (0) +#define BTDM_MODEM_SLEEP_MODE_ORIG (1) +#define BTDM_MODEM_SLEEP_MODE_EVED (2) +extern void btdm_controller_set_sleep_mode(uint8_t mode); +extern uint8_t btdm_controller_get_sleep_mode(void); +extern bool btdm_power_state_active(void); +extern void btdm_wakeup_request(void); + +#define BTDM_LPCLK_SEL_XTAL (0) +#define BTDM_LPCLK_SEL_XTAL32K (1) +#define BTDM_LPCLK_SEL_RTC_SLOW (2) +#define BTDM_LPCLK_SEL_8M (3) +extern bool btdm_lpclk_select_src(uint32_t sel); +extern bool btdm_lpclk_set_div(uint32_t div); + +#define BTDM_MIN_SLEEP_DURATION (20) /* VHCI function interface */ typedef struct vhci_host_callback { void (*notify_host_send_available)(void); /*!< callback used to notify that the host can send packet to controller */ @@ -104,7 +125,7 @@ typedef struct { /* the mode column will be modified by release function to indicate the available region */ static btdm_dram_available_region_t btdm_dram_available_region[] = { - //following is .data + //following is .data {ESP_BT_MODE_BTDM, 0x3ffae6e0, 0x3ffaff10}, //following is memory which HW will use {ESP_BT_MODE_BTDM, 0x3ffb0000, 0x3ffb09a8}, @@ -160,14 +181,24 @@ struct osi_funcs_t { int32_t (* _read_efuse_mac)(uint8_t mac[6]); void (* _srand)(unsigned int seed); int (* _rand)(void); + uint32_t (* _btdm_lpcycles_2_us)(uint32_t cycles); + uint32_t (* _btdm_us_2_lpcycles)(uint32_t us); + bool (* _btdm_sleep_check_duration)(uint32_t *slot_cnt); + void (* _btdm_sleep_enter)(void); + void (* _btdm_sleep_exit)(void); /* called from ISR */ }; + /* Static variable declare */ static bool btdm_bb_init_flag = false; static esp_bt_controller_status_t btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; static portMUX_TYPE global_int_mux = portMUX_INITIALIZER_UNLOCKED; +// measured average low power clock period in micro seconds +static uint32_t btdm_lpcycle_us = 0; +static uint8_t btdm_lpcycle_us_frac = 0; // number of fractional bit for btdm_lpcycle_us + #ifdef CONFIG_PM_ENABLE static esp_pm_lock_handle_t s_pm_lock; #endif @@ -539,6 +570,70 @@ static int IRAM_ATTR rand_wrapper(void) return (int)esp_random(); } +static uint32_t IRAM_ATTR btdm_lpcycles_2_us(uint32_t cycles) +{ + // Sanity check. The number of lp cycles should not be too high to avoid overflow. Thrs: 100s (for 32kHz freq) + assert(cycles < 3200000); + + // clock measurement is conducted + uint64_t us = (uint64_t)btdm_lpcycle_us * cycles; + us = (us + (1 << (btdm_lpcycle_us_frac - 1))) >> btdm_lpcycle_us_frac; + return (uint32_t)us; +} + +/* + * @brief Converts a duration in slots into a number of low power clock cycles. + */ +static uint32_t IRAM_ATTR btdm_us_2_lpcycles(uint32_t us) +{ + // Sanity check: the number of sleep duration(us) should not be too high to avoid overflow. Thrs: 100s + assert(us < 100000000); + + // Compute the sleep duration in us to low power clock cycles, with calibration result applied + // clock measurement is conducted + uint64_t cycles = ((uint64_t)(us) << btdm_lpcycle_us_frac) / btdm_lpcycle_us; + + return (uint32_t)cycles; +} + +static bool IRAM_ATTR btdm_sleep_check_duration(uint32_t *slot_cnt) +{ + if (*slot_cnt < BTDM_MIN_SLEEP_DURATION) { + return false; + } + return true; +} + +static void IRAM_ATTR btdm_sleep_enter_wrapper(void) +{ + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + esp_modem_sleep_enter(MODEM_BLE_MODULE); + esp_modem_sleep_enter(MODEM_CLASSIC_BT_MODULE); +#ifdef CONFIG_PM_ENABLE + esp_pm_lock_release(s_pm_lock); +#endif + } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { + esp_modem_sleep_enter(MODEM_BLE_MODULE); + // pause bluetooth baseband + periph_module_disable(PERIPH_BT_BASEBAND_MODULE); + } +} + +static void IRAM_ATTR btdm_sleep_exit_wrapper(void) +{ + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { +#ifdef CONFIG_PM_ENABLE + esp_pm_lock_acquire(s_pm_lock); +#endif + esp_modem_sleep_exit(MODEM_BLE_MODULE); + esp_modem_sleep_exit(MODEM_CLASSIC_BT_MODULE); + } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { + // resume bluetooth baseband + periph_module_enable(PERIPH_BT_BASEBAND_MODULE); + esp_modem_sleep_exit(MODEM_BLE_MODULE); + } +} + static struct osi_funcs_t osi_funcs = { ._set_isr = xt_set_interrupt_handler, ._ints_on = xt_ints_on, @@ -571,6 +666,11 @@ static struct osi_funcs_t osi_funcs = { ._read_efuse_mac = read_mac_wrapper, ._srand = srand_wrapper, ._rand = rand_wrapper, + ._btdm_lpcycles_2_us = btdm_lpcycles_2_us, + ._btdm_us_2_lpcycles = btdm_us_2_lpcycles, + ._btdm_sleep_check_duration = btdm_sleep_check_duration, + ._btdm_sleep_enter = btdm_sleep_enter_wrapper, + ._btdm_sleep_exit = btdm_sleep_exit_wrapper, }; bool esp_vhci_host_check_send_available(void) @@ -580,6 +680,9 @@ bool esp_vhci_host_check_send_available(void) void esp_vhci_host_send_packet(uint8_t *data, uint16_t len) { + if (!btdm_power_state_active()) { + btdm_wakeup_request(); + } API_vhci_host_send_packet(data, len); } @@ -723,6 +826,32 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) periph_module_enable(PERIPH_BT_MODULE); + btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; + btdm_lpcycle_us = 32 << btdm_lpcycle_us_frac; + bool select_src_ret = false; + bool set_div_ret = false; +#if CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG +#if CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL + select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL); + set_div_ret = btdm_lpclk_set_div(rtc_clk_xtal_freq_get() * 32 - 1); + assert(select_src_ret && set_div_ret); + btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; + btdm_lpcycle_us = 32 << btdm_lpcycle_us_frac; +#elif CONFIG_BTDM_LPCLK_SEL_EXT_32K_XTAL + select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL32K); + set_div_ret = btdm_lpclk_set_div(0); + assert(select_src_ret && set_div_ret); + btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; + btdm_lpcycle_us = esp_clk_slowclk_cal_get(); + assert(btdm_lpcycle_us != 0); +#endif // CONFIG_BTDM_LPCLK_SEL_XX + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_ORIG); +#elif CONFIG_BTDM_MODEM_SLEEP_MODE_EVED + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_EVED); +#else + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); +#endif + btdm_cfg_mask = btdm_config_mask_load(); ret = btdm_controller_init(btdm_cfg_mask, cfg); @@ -758,6 +887,8 @@ esp_err_t esp_bt_controller_deinit(void) btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; + btdm_lpcycle_us = 0; + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); #ifdef CONFIG_PM_ENABLE esp_pm_lock_delete(s_pm_lock); s_pm_lock = NULL; @@ -784,12 +915,17 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) #endif esp_phy_load_cal_and_init(PHY_BT_MODULE); - esp_modem_sleep_register(MODEM_BLE_MODULE); - /* TODO: Classic BT should be registered once it supports - * modem sleep */ + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + esp_modem_sleep_register(MODEM_BLE_MODULE); + esp_modem_sleep_register(MODEM_CLASSIC_BT_MODULE); + } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { + esp_modem_sleep_register(MODEM_BLE_MODULE); + } - esp_modem_sleep_exit(MODEM_BLE_MODULE); + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + btdm_controller_enable_sleep(true); + } if (btdm_bb_init_flag == false) { btdm_bb_init_flag = true; @@ -798,7 +934,12 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) ret = btdm_controller_enable(mode); if (ret) { - esp_modem_sleep_deregister(MODEM_BLE_MODULE); + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + esp_modem_sleep_deregister(MODEM_BLE_MODULE); + esp_modem_sleep_deregister(MODEM_CLASSIC_BT_MODULE); + } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { + esp_modem_sleep_deregister(MODEM_BLE_MODULE); + } esp_phy_rf_deinit(PHY_BT_MODULE); return ESP_ERR_INVALID_STATE; } @@ -816,15 +957,29 @@ esp_err_t esp_bt_controller_disable(void) return ESP_ERR_INVALID_STATE; } + // disable modem sleep and wake up from sleep mode + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + btdm_controller_enable_sleep(false); + if (!btdm_power_state_active()) { + btdm_wakeup_request(); + } + while (!btdm_power_state_active()) { + ets_delay_us(1000); + } + } + ret = btdm_controller_disable(btdm_controller_get_mode()); if (ret < 0) { return ESP_ERR_INVALID_STATE; } if (ret == ESP_BT_MODE_IDLE) { - /* TODO: Need to de-register classic BT once it supports - * modem sleep */ - esp_modem_sleep_deregister(MODEM_BLE_MODULE); + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + esp_modem_sleep_deregister(MODEM_BLE_MODULE); + esp_modem_sleep_deregister(MODEM_CLASSIC_BT_MODULE); + } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { + esp_modem_sleep_deregister(MODEM_BLE_MODULE); + } esp_phy_rf_deinit(PHY_BT_MODULE); btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; } @@ -884,4 +1039,68 @@ esp_err_t esp_bredr_tx_power_get(esp_power_level_t *min_power_level, esp_power_l return ESP_OK; } +esp_err_t esp_bt_sleep_enable (void) +{ + esp_err_t status; + if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + esp_modem_sleep_register(MODEM_BLE_MODULE); + esp_modem_sleep_register(MODEM_CLASSIC_BT_MODULE); + btdm_controller_enable_sleep (true); + status = ESP_OK; + } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { + esp_modem_sleep_register(MODEM_BLE_MODULE); + btdm_controller_enable_sleep (true); + status = ESP_OK; + } else { + status = ESP_ERR_NOT_SUPPORTED; + } + + return status; +} + +esp_err_t esp_bt_sleep_disable (void) +{ + esp_err_t status; + if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_ORIG) { + esp_modem_sleep_deregister(MODEM_BLE_MODULE); + esp_modem_sleep_deregister(MODEM_CLASSIC_BT_MODULE); + btdm_controller_enable_sleep (false); + status = ESP_OK; + } else if (btdm_controller_get_sleep_mode() == BTDM_MODEM_SLEEP_MODE_EVED) { + esp_modem_sleep_deregister(MODEM_BLE_MODULE); + btdm_controller_enable_sleep (false); + status = ESP_OK; + } else { + status = ESP_ERR_NOT_SUPPORTED; + } + + return status; +} + +bool esp_bt_controller_is_sleeping(void) +{ + if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED || + btdm_controller_get_sleep_mode() != BTDM_MODEM_SLEEP_MODE_ORIG) { + return false; + } + + return !btdm_power_state_active(); +} + +void esp_bt_controller_wakeup_request(void) +{ + if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED || + btdm_controller_get_sleep_mode() != BTDM_MODEM_SLEEP_MODE_ORIG) { + return; + } + + btdm_wakeup_request(); +} + #endif /* CONFIG_BT_ENABLED */ diff --git a/components/bt/include/esp_bt.h b/components/bt/include/esp_bt.h index 0d85465e16..9924420f6f 100644 --- a/components/bt/include/esp_bt.h +++ b/components/bt/include/esp_bt.h @@ -27,7 +27,7 @@ extern "C" { /** * @brief Controller config options, depend on config mask. - * Config mask indicate which functions enabled, this means + * Config mask indicate which functions enabled, this means * some options or parameters of some functions enabled by config mask. */ typedef struct { @@ -260,6 +260,62 @@ void esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback); */ esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode); +/** + * @brief enable bluetooth to enter modem sleep + * + * Note that this function shall not be invoked before esp_bt_controller_enable() + * + * There are currently two options for bluetooth modem sleep, one is ORIG mode, and another is EVED Mode. EVED Mode is intended for BLE only. + * + * For ORIG mode: + * Bluetooth modem sleep is enabled in controller start up by default if CONFIG_BTDM_CONTROLLER_MODEM_SLEEP is set and "ORIG mode" is selected. In ORIG modem sleep mode, bluetooth controller will switch off some components and pause to work every now and then, if there is no event to process; and wakeup according to the scheduled interval and resume the work. It can also wakeup earlier upon external request using function "esp_bt_controller_wakeup_request". + * Note that currently there is problem in the combination use of bluetooth modem sleep and Dynamic Frequency Scaling(DFS). So do not enable DFS if bluetooth modem sleep is in use. + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_bt_sleep_enable(void); + + +/** + * @brief disable bluetooth modem sleep + * + * Note that this function shall not be invoked before esp_bt_controller_enable() + * + * If esp_bt_sleep_disable() is called, bluetooth controller will not be allowed to enter modem sleep; + * + * If ORIG modem sleep mode is in use, if this function is called, bluetooth controller may not immediately wake up if it is dormant then. + * In this case, esp_bt_controller_wakeup_request() can be used to shorten the time for wakeup. + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_bt_sleep_disable(void); + +/** + * @brief to check whether bluetooth controller is sleeping at the instant, if modem sleep is enabled + * + * Note that this function shall not be invoked before esp_bt_controller_enable() + * This function is supposed to be used ORIG mode of modem sleep + * + * @return true if in modem sleep state, false otherwise + */ +bool esp_bt_controller_is_sleeping(void); + +/** + * @brief request controller to wakeup from sleeping state during sleep mode + * + * Note that this function shall not be invoked before esp_bt_controller_enable() + * Note that this function is supposed to be used ORIG mode of modem sleep + * Note that after this request, bluetooth controller may again enter sleep as long as the modem sleep is enabled + * + * Profiling shows that it takes several milliseconds to wakeup from modem sleep after this request. + * Generally it takes longer if 32kHz XTAL is used than the main XTAL, due to the lower frequncy of the former as the bluetooth low power clock source. + */ +void esp_bt_controller_wakeup_request(void); + #ifdef __cplusplus } #endif diff --git a/components/bt/lib b/components/bt/lib index a3e98f8314..700d2bc914 160000 --- a/components/bt/lib +++ b/components/bt/lib @@ -1 +1 @@ -Subproject commit a3e98f83144ee46c6ec9b53b1c838bcefdf26e97 +Subproject commit 700d2bc914b755b840a0adeaa9d1ff45b398b6fa diff --git a/components/driver/include/driver/periph_ctrl.h b/components/driver/include/driver/periph_ctrl.h index b418100902..82a328d679 100644 --- a/components/driver/include/driver/periph_ctrl.h +++ b/components/driver/include/driver/periph_ctrl.h @@ -53,6 +53,8 @@ typedef enum { PERIPH_WIFI_MODULE, PERIPH_BT_MODULE, PERIPH_WIFI_BT_COMMON_MODULE, + PERIPH_BT_BASEBAND_MODULE, + PERIPH_BT_LC_MODULE, } periph_module_t; /** diff --git a/components/driver/periph_ctrl.c b/components/driver/periph_ctrl.c index 59baf48311..376444a2ca 100644 --- a/components/driver/periph_ctrl.c +++ b/components/driver/periph_ctrl.c @@ -114,6 +114,10 @@ static uint32_t get_clk_en_mask(periph_module_t periph) return DPORT_WIFI_CLK_BT_EN_M; case PERIPH_WIFI_BT_COMMON_MODULE: return DPORT_WIFI_CLK_WIFI_BT_COMMON_M; + case PERIPH_BT_BASEBAND_MODULE: + return DPORT_BT_BASEBAND_EN; + case PERIPH_BT_LC_MODULE: + return DPORT_BT_LC_EN; default: return 0; } @@ -177,6 +181,8 @@ static uint32_t get_rst_en_mask(periph_module_t periph) case PERIPH_WIFI_MODULE: case PERIPH_BT_MODULE: case PERIPH_WIFI_BT_COMMON_MODULE: + case PERIPH_BT_BASEBAND_MODULE: + case PERIPH_BT_LC_MODULE: return 0; default: return 0; @@ -195,6 +201,8 @@ static bool is_wifi_clk_peripheral(periph_module_t periph) case PERIPH_WIFI_MODULE: case PERIPH_BT_MODULE: case PERIPH_WIFI_BT_COMMON_MODULE: + case PERIPH_BT_BASEBAND_MODULE: + case PERIPH_BT_LC_MODULE: return true; default: return false; diff --git a/components/esp32/ld/esp32.rom.ld b/components/esp32/ld/esp32.rom.ld index c1c1df0884..6529aacb97 100644 --- a/components/esp32/ld/esp32.rom.ld +++ b/components/esp32/ld/esp32.rom.ld @@ -169,6 +169,7 @@ PROVIDE ( hci_cmd_desc_tab_testing = 0x3ff97a98 ); PROVIDE ( hci_cmd_desc_tab_vs = 0x3ff97714 ); PROVIDE ( hci_command_handler = 0x4004c928 ); PROVIDE ( hci_env = 0x3ffb9350 ); +PROVIDE ( rwip_env = 0x3ffb8bcc ); PROVIDE ( hci_evt_dbg_desc_tab = 0x3ff9750c ); PROVIDE ( hci_evt_desc_tab = 0x3ff9751c ); PROVIDE ( hci_evt_le_desc_tab = 0x3ff974b4 ); diff --git a/components/soc/esp32/include/soc/dport_reg.h b/components/soc/esp32/include/soc/dport_reg.h index ecb1cf3a29..6c23dfe639 100644 --- a/components/soc/esp32/include/soc/dport_reg.h +++ b/components/soc/esp32/include/soc/dport_reg.h @@ -1061,6 +1061,10 @@ #define DPORT_WIFI_CLK_BT_EN_S 11 /* Mask for clock bits used by both WIFI and Bluetooth, bit 0, 3, 6, 7, 8, 9 */ #define DPORT_WIFI_CLK_WIFI_BT_COMMON_M 0x000003c9 +//bluetooth baseband bit11 +#define DPORT_BT_BASEBAND_EN BIT(11) +//bluetooth LC bit16 and bit17 +#define DPORT_BT_LC_EN (BIT(16)|BIT(17)) /* Remaining single bit clock masks */ #define DPORT_WIFI_CLK_SDIOSLAVE_EN BIT(4) diff --git a/components/soc/esp32/rtc_clk.c b/components/soc/esp32/rtc_clk.c index dc5f71db21..d919bb822d 100644 --- a/components/soc/esp32/rtc_clk.c +++ b/components/soc/esp32/rtc_clk.c @@ -242,6 +242,10 @@ void rtc_clk_apll_enable(bool enable, uint32_t sdm0, uint32_t sdm1, uint32_t sdm void rtc_clk_slow_freq_set(rtc_slow_freq_t slow_freq) { REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq); + + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, + (slow_freq == RTC_SLOW_FREQ_32K_XTAL) ? 1 : 0); + ets_delay_us(DELAY_SLOW_CLK_SWITCH); } diff --git a/components/soc/esp32/rtc_time.c b/components/soc/esp32/rtc_time.c index 6f354f8849..94002f79db 100644 --- a/components/soc/esp32/rtc_time.c +++ b/components/soc/esp32/rtc_time.c @@ -41,9 +41,11 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles) { /* Enable requested clock (150k clock is always on) */ - if (cal_clk == RTC_CAL_32K_XTAL) { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); + int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); + if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) { + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, 1); } + if (cal_clk == RTC_CAL_8MD256) { SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); } @@ -79,9 +81,9 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc timeout_us--; ets_delay_us(1); } - if (cal_clk == RTC_CAL_32K_XTAL) { - CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN); - } + + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, dig_32k_xtal_state); + if (cal_clk == RTC_CAL_8MD256) { CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN); } From bb9e73c864e111861981ba44b91fc94e5c0b2a45 Mon Sep 17 00:00:00 2001 From: qiyueixa Date: Fri, 18 May 2018 12:25:52 +0800 Subject: [PATCH 129/187] mesh: update libs 1. use pbkdf2_sha1() to encrypted mesh ie key. 2. fix esp_mesh_waive_root(). 3. fix esp_mesh_stop(). 4. fix xon issues. --- components/esp32/esp_err_to_name.c | 3 ++ components/esp32/include/esp_mesh.h | 48 ++++++++++------- components/esp32/lib | 2 +- .../internal_transceiver/main/mesh_main.c | 53 +++++++------------ 4 files changed, 54 insertions(+), 52 deletions(-) diff --git a/components/esp32/esp_err_to_name.c b/components/esp32/esp_err_to_name.c index 713252777f..6011689271 100644 --- a/components/esp32/esp_err_to_name.c +++ b/components/esp32/esp_err_to_name.c @@ -359,6 +359,9 @@ static const esp_err_msg_t esp_err_msg_table[] = { # endif # ifdef ESP_ERR_MESH_DISCARD ERR_TBL_IT(ESP_ERR_MESH_DISCARD), /* 16405 0x4015 */ +# endif +# ifdef ESP_ERR_MESH_VOTING + ERR_TBL_IT(ESP_ERR_MESH_VOTING), /* 16406 0x4016 */ # endif // components/tcpip_adapter/include/tcpip_adapter.h # ifdef ESP_ERR_TCPIP_ADAPTER_BASE diff --git a/components/esp32/include/esp_mesh.h b/components/esp32/include/esp_mesh.h index 7c1c166acb..b504149e13 100644 --- a/components/esp32/include/esp_mesh.h +++ b/components/esp32/include/esp_mesh.h @@ -123,6 +123,7 @@ extern "C" { #define ESP_ERR_MESH_INTERFACE (ESP_ERR_MESH_BASE + 19) /**< low-level WiFi interface error */ #define ESP_ERR_MESH_DISCARD_DUPLICATE (ESP_ERR_MESH_BASE + 20) /**< discard the packet due to the duplicate sequence number */ #define ESP_ERR_MESH_DISCARD (ESP_ERR_MESH_BASE + 21) /**< discard the packet */ +#define ESP_ERR_MESH_VOTING (ESP_ERR_MESH_BASE + 22) /**< vote in progress */ /** * @brief flags used with esp_mesh_send() and esp_mesh_recv() @@ -138,7 +139,7 @@ extern "C" { /** * @brief option definitions for esp_mesh_send() and esp_mesh_recv() */ -#define MESH_OPT_SEND_GROUP (7) /**< data transmission by group; used with esp_mesh_send() and must have payload */ +#define MESH_OPT_SEND_GROUP (7) /**< data transmission by group; used with esp_mesh_send() and shall have payload */ #define MESH_OPT_RECV_DS_ADDR (8) /**< return a remote IP address; used with esp_mesh_send() and esp_mesh_recv() */ /******************************************************* @@ -438,11 +439,21 @@ typedef struct { } mesh_cfg_t; /** - * @brief vote + * @brief vote address configuration */ typedef union { - int attempts; /**< max vote attempts */ - mesh_addr_t rc_addr; /**< root address specified by users for API esp_mesh_waive_root() */ + int attempts; /**< max vote attempts before a new root is elected automatically by mesh network. (min:15, 15 by default) */ + mesh_addr_t rc_addr; /**< a new root address specified by users for API esp_mesh_waive_root() */ +} mesh_rc_config_t; + +/** + * @brief vote + */ +typedef struct { + float percentage; /**< vote percentage threshold for approval of being a root */ + bool is_rc_specified; /**< if true, rc_addr shall be specified(Unimplemented). + if false, attempts value shall be specified to make network start root election. */ + mesh_rc_config_t config; /**< vote address configuration */ } mesh_vote_t; /** @@ -1080,8 +1091,8 @@ bool esp_mesh_is_root_conflicts_allowed(void); /** * @brief set group ID addresses * - * @param addr pointer to new addresses - * @param num number of addresses + * @param addr pointer to new group ID addresses + * @param num the number of group ID addresses * * @return * - ESP_OK @@ -1092,8 +1103,8 @@ esp_err_t esp_mesh_set_group_id(const mesh_addr_t *addr, const int num); /** * @brief delete group ID addresses * - * @param addr pointer to deleted address - * @param num number of addresses + * @param addr pointer to deleted group ID address + * @param num the number of group ID addresses * * @return * - ESP_OK @@ -1111,8 +1122,8 @@ int esp_mesh_get_group_num(void); /** * @brief get group ID addresses * - * @param addr pointer to group address - * @param num number of addresses + * @param addr pointer to group ID addresses + * @param num the number of group ID addresses * * @return * - ESP_OK @@ -1161,29 +1172,30 @@ esp_err_t esp_mesh_set_ie_crypto_funcs(const mesh_crypto_funcs_t *crypto_funcs); /** * @brief set mesh ie crypto key * - * @attention This API should be called before esp_mesh_start(). + * @attention This API should be called after esp_mesh_set_config() and before esp_mesh_start(). * - * @param key crypto key - * @param len the present implementation only supports 32 + * @param key ASCII crypto key + * @param len length in bytes, range:8~64 * * @return * - ESP_OK * - ESP_ERR_MESH_NOT_ALLOWED + * - ESP_ERR_MESH_NOT_CONFIG * - ESP_MESH_ERR_ARGUMENT */ -esp_err_t esp_mesh_set_ie_crypto_key(const uint8_t *key, int len); +esp_err_t esp_mesh_set_ie_crypto_key(const char *key, int len); /** * @brief get mesh ie crypto key * - * @param key crypto key - * @param len the present implementation only supports 32 + * @param key ASCII crypto key + * @param len length in bytes, range:8~64 * * @return * - ESP_OK * - ESP_MESH_ERR_ARGUMENT */ -esp_err_t esp_mesh_get_ie_crypto_key(uint8_t *key, int len); +esp_err_t esp_mesh_get_ie_crypto_key(char *key, int len); /** * @brief set delay time before starting root healing @@ -1215,7 +1227,7 @@ esp_err_t esp_mesh_set_event_cb(const mesh_event_cb_t event_cb); /** * @brief set Root Fixed setting for nodes * If Root Fixed setting of nodes is enabled, they won't compete to be a root. - * If a scenario needs a fixed root, all nodes in this network must enable this setting. + * If a scenario needs a fixed root, all nodes in this network shall enable this setting. * * @param enable enable or not * diff --git a/components/esp32/lib b/components/esp32/lib index c1d0ac3625..0503727b12 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit c1d0ac3625db5da98d1e9c64b8cd0d1261443810 +Subproject commit 0503727b12bf40e5578959c6d9478f25312cdc81 diff --git a/examples/mesh/internal_transceiver/main/mesh_main.c b/examples/mesh/internal_transceiver/main/mesh_main.c index bfdfa6f63b..6cbdfc713f 100644 --- a/examples/mesh/internal_transceiver/main/mesh_main.c +++ b/examples/mesh/internal_transceiver/main/mesh_main.c @@ -99,12 +99,11 @@ void esp_mesh_p2p_tx_main(void *arg) is_running = true; while (is_running) { - /* normal nodes rather than root do nothing but print */ + /* non-root do nothing but print */ if (!esp_mesh_is_root()) { - ESP_LOGI(MESH_TAG, "layer:%d, rtableSize:%d, %s%s", mesh_layer, + ESP_LOGI(MESH_TAG, "layer:%d, rtableSize:%d, %s", mesh_layer, esp_mesh_get_routing_table_size(), - is_mesh_connected ? "CONNECT" : "DISCONNECT", - esp_mesh_is_root() ? "" : "[NODE]"); + (is_mesh_connected && esp_mesh_is_root()) ? "ROOT" : is_mesh_connected ? "NODE" : "DISCONNECT"); vTaskDelay(10 * 1000 / portTICK_RATE_MS); continue; } @@ -213,15 +212,18 @@ void esp_mesh_event_handler(mesh_event_t event) mesh_addr_t group; #endif static uint8_t last_layer = 0; - static int disconnect_count = 0; ESP_LOGD(MESH_TAG, "esp_event_handler:%d", event.id); switch (event.id) { case MESH_EVENT_STARTED: - ESP_LOGI(MESH_TAG, ""); + ESP_LOGI(MESH_TAG, "heap:%d", esp_get_free_heap_size()); + is_mesh_connected = false; + mesh_layer = esp_mesh_get_layer(); break; case MESH_EVENT_STOPPED: - ESP_LOGI(MESH_TAG, ""); + ESP_LOGI(MESH_TAG, "heap:%d", esp_get_free_heap_size()); + is_mesh_connected = false; + mesh_layer = esp_mesh_get_layer(); break; case MESH_EVENT_CHILD_CONNECTED: ESP_LOGI(MESH_TAG, "aid:%d, "MACSTR"", @@ -238,28 +240,24 @@ void esp_mesh_event_handler(mesh_event_t event) event.info.routing_table.rt_size_change, event.info.routing_table.rt_size_new); break; - case MESH_EVENT_ROUTING_TABLE_REMOVE: ESP_LOGW(MESH_TAG, "remove %d, new:%d", event.info.routing_table.rt_size_change, event.info.routing_table.rt_size_new); break; - case MESH_EVENT_NO_PARNET_FOUND: ESP_LOGI(MESH_TAG, "scan times:%d", event.info.no_parent.scan_times); /* TODO handler for the failure */ break; - case MESH_EVENT_PARENT_CONNECTED: mesh_layer = event.info.connected.self_layer; memcpy(&mesh_parent_addr.addr, event.info.connected.connected.bssid, 6); ESP_LOGI(MESH_TAG, - "layer:%d-->%d, parent:"MACSTR"%s, discnx:%d", + "layer:%d-->%d, parent:"MACSTR"%s", last_layer, mesh_layer, MAC2STR(mesh_parent_addr.addr), esp_mesh_is_root() ? "" : - (mesh_layer == 2) ? "" : "", disconnect_count); - disconnect_count = 0; + (mesh_layer == 2) ? "" : ""); last_layer = mesh_layer; mesh_connected_indicator(mesh_layer); is_mesh_connected = true; @@ -277,18 +275,13 @@ void esp_mesh_event_handler(mesh_event_t event) #endif esp_mesh_comm_p2p_start(); break; - case MESH_EVENT_PARENT_DISCONNECTED: ESP_LOGI(MESH_TAG, - "reason:%d, count:%d", - event.info.disconnected.reason, disconnect_count); - if (event.info.disconnected.reason == 201) { - disconnect_count++; - } + "reason:%d", + event.info.disconnected.reason); is_mesh_connected = false; mesh_disconnected_indicator(); break; - case MESH_EVENT_LAYER_CHANGE: mesh_layer = event.info.layer_change.new_layer; ESP_LOGI(MESH_TAG, "layer:%d-->%d%s", @@ -298,12 +291,10 @@ void esp_mesh_event_handler(mesh_event_t event) last_layer = mesh_layer; mesh_connected_indicator(mesh_layer); break; - case MESH_EVENT_ROOT_ADDRESS: - ESP_LOGI(MESH_TAG, "rc_addr:"MACSTR"", + ESP_LOGI(MESH_TAG, "root address:"MACSTR"", MAC2STR(event.info.root_addr.addr)); break; - case MESH_EVENT_ROOT_GOT_IP: /* root starts to connect to server */ ESP_LOGI(MESH_TAG, @@ -312,11 +303,9 @@ void esp_mesh_event_handler(mesh_event_t event) IP2STR(&event.info.got_ip.ip_info.netmask), IP2STR(&event.info.got_ip.ip_info.gw)); break; - case MESH_EVENT_ROOT_LOST_IP: ESP_LOGI(MESH_TAG, ""); break; - case MESH_EVENT_VOTE_STARTED: ESP_LOGI(MESH_TAG, "attempts:%d, reason:%d, rc_addr:"MACSTR"", @@ -324,34 +313,32 @@ void esp_mesh_event_handler(mesh_event_t event) event.info.vote_started.reason, MAC2STR(event.info.vote_started.rc_addr.addr)); break; - case MESH_EVENT_VOTE_STOPPED: - ESP_LOGI(MESH_TAG, ""); + ESP_LOGI(MESH_TAG, ""); break; - case MESH_EVENT_ROOT_SWITCH_REQ: ESP_LOGI(MESH_TAG, "reason:%d, rc_addr:"MACSTR"", event.info.switch_req.reason, MAC2STR( event.info.switch_req.rc_addr.addr)); break; - case MESH_EVENT_ROOT_SWITCH_ACK: - ESP_LOGI(MESH_TAG, ""); + /* new root */ + mesh_layer = esp_mesh_get_layer(); + esp_mesh_get_parent_bssid(&mesh_parent_addr); + ESP_LOGI(MESH_TAG, "layer:%d, parent:"MACSTR"", mesh_layer, MAC2STR(mesh_parent_addr.addr)); break; case MESH_EVENT_TODS_STATE: ESP_LOGI(MESH_TAG, "state:%d", event.info.toDS_state); break; - case MESH_EVENT_ROOT_FIXED: ESP_LOGI(MESH_TAG, "%s", event.info.root_fixed.is_fixed ? "fixed" : "not fixed"); break; - default: - ESP_LOGI(MESH_TAG, "unknown"); + ESP_LOGI(MESH_TAG, "unknown id:%d", event.id); break; } } From 7f8811ea14583b17ea7d85a281d54bdc47ed7f3a Mon Sep 17 00:00:00 2001 From: Xia Xiaotian Date: Wed, 9 May 2018 16:44:06 +0800 Subject: [PATCH 130/187] add Channel State Information(CSI) support --- components/esp32/Kconfig | 8 +++ components/esp32/include/esp_wifi.h | 61 +++++++++++++++++++++++ components/esp32/include/esp_wifi_types.h | 36 +++++++++++-- components/esp32/lib | 2 +- 4 files changed, 101 insertions(+), 6 deletions(-) mode change 100644 => 100755 components/esp32/Kconfig diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig old mode 100644 new mode 100755 index 7ef096a2cd..8fe485e32c --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -956,6 +956,14 @@ config ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM can deliver frames faster than WiFi layer can transmit. In these cases, we may run out of TX buffers. +config ESP32_WIFI_CSI_ENABLED + bool "WiFi CSI(Channel State Information)" + default n + help + Select this option to enable CSI(Channel State Information) feature. CSI takes about + CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM KB of RAM. If CSI is not used, it is better to disable + this feature in order to save memory. + config ESP32_WIFI_AMPDU_TX_ENABLED bool "WiFi AMPDU TX" default y diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h index f3333eebd9..bacfb13c67 100755 --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -99,6 +99,7 @@ typedef struct { int tx_buf_type; /**< WiFi TX buffer type */ int static_tx_buf_num; /**< WiFi static TX buffer number */ int dynamic_tx_buf_num; /**< WiFi dynamic TX buffer number */ + int csi_enable; /**< WiFi channel state information enable flag */ int ampdu_rx_enable; /**< WiFi AMPDU RX feature enable flag */ int ampdu_tx_enable; /**< WiFi AMPDU TX feature enable flag */ int nvs_enable; /**< WiFi NVS flash enable flag */ @@ -121,6 +122,12 @@ typedef struct { #define WIFI_DYNAMIC_TX_BUFFER_NUM 0 #endif +#if CONFIG_ESP32_WIFI_CSI_ENABLED +#define WIFI_CSI_ENABLED 1 +#else +#define WIFI_CSI_ENABLED 0 +#endif + #if CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED #define WIFI_AMPDU_RX_ENABLED 1 #else @@ -175,6 +182,7 @@ extern const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs; .tx_buf_type = CONFIG_ESP32_WIFI_TX_BUFFER_TYPE,\ .static_tx_buf_num = WIFI_STATIC_TX_BUFFER_NUM,\ .dynamic_tx_buf_num = WIFI_DYNAMIC_TX_BUFFER_NUM,\ + .csi_enable = WIFI_CSI_ENABLED,\ .ampdu_rx_enable = WIFI_AMPDU_RX_ENABLED,\ .ampdu_tx_enable = WIFI_AMPDU_TX_ENABLED,\ .nvs_enable = WIFI_NVS_ENABLED,\ @@ -964,6 +972,59 @@ esp_err_t esp_wifi_get_event_mask(uint32_t *mask); esp_err_t esp_wifi_80211_tx(wifi_interface_t ifx, const void *buffer, int len, bool en_sys_seq); +/** + * @brief The RX callback function of Channel State Information(CSI) data. + * + * Each time a CSI data is received, the callback function will be called. + * + * @param ctx context argument, passed to esp_wifi_set_csi_rx_cb() when registering callback function. + * @param data CSI data received. + * + */ +typedef void (* wifi_csi_cb_t)(void *ctx, wifi_csi_info_t *data); + + +/** + * @brief Register the RX callback function of CSI data. + * + * Each time a CSI data is received, the callback function will be called. + * + * @param cb callback + * @param ctx context argument, passed to callback function + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + */ + +esp_err_t esp_wifi_set_csi_rx_cb(wifi_csi_cb_t cb, void *ctx); + +/** + * @brief Set CSI data configuration + * + * @param config configuration + * + * return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + * - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start or promiscuous mode is not enabled + * - ESP_ERR_INVALID_ARG: invalid argument + */ +esp_err_t esp_wifi_set_csi_config(const wifi_csi_config_t *config); + +/** + * @brief Enable or disable CSI + * + * @param en true - enable, false - disable + * + * return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + * - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start or promiscuous mode is not enabled + * - ESP_ERR_INVALID_ARG: invalid argument + */ +esp_err_t esp_wifi_set_csi(bool en); + #ifdef __cplusplus } #endif diff --git a/components/esp32/include/esp_wifi_types.h b/components/esp32/include/esp_wifi_types.h index 4797209969..be4a68c289 100755 --- a/components/esp32/include/esp_wifi_types.h +++ b/components/esp32/include/esp_wifi_types.h @@ -308,13 +308,15 @@ typedef struct { unsigned stbc:2; /**< STBC */ unsigned fec_coding:1; /**< Flag is set for 11n packets which are LDPC */ unsigned sgi:1; /**< SGI */ - unsigned noise_floor:8; /**< noise floor */ + signed noise_floor:8; /**< noise floor */ unsigned ampdu_cnt:8; /**< ampdu cnt */ - unsigned channel:4; /**< which channel this packet in */ - unsigned :12; /**< reserve */ - unsigned timestamp:32; /**< timestamp */ - unsigned :32; /**< reserve */ + unsigned channel:4; /**< which primary channel this packet in */ + unsigned second_channel:4;/**< which second channel this packet in */ + unsigned :8; /**< reserve */ + unsigned timestamp:32; /**< timestamp, unit: microsecond */ unsigned :32; /**< reserve */ + unsigned :31; /**< reserve */ + unsigned ant:1; /**< antenna number from which this packet is received */ unsigned sig_len:12; /**< length of packet */ unsigned :12; /**< reserve */ unsigned rx_state:8; /**< rx state */ @@ -369,6 +371,30 @@ typedef struct { #define WIFI_EVENT_MASK_NONE (0) /**< mask none of the WiFi events */ #define WIFI_EVENT_MASK_AP_PROBEREQRECVED (BIT(0)) /**< mask SYSTEM_EVENT_AP_PROBEREQRECVED event */ +/** + * @brief Channel state information(CSI) configuration type + * + */ +typedef struct { + bool lltf_en; /**< enable to receive legacy long training field(lltf) data */ + bool htltf_en; /**< enable to receive HT long training field(htltf) data */ + bool stbcltf2_en; /**< enable to receive space time block code long training field(stbcltf2) data */ + bool manu_scale; /**< manually scale the CSI data by left shifting or automatically scale the CSI data. If set true, please set the shift bits. false: automatically. true: manually */ + uint8_t shift; /**< manually left shift bits of the scale of the CSI data. The range of the left shift bits is 0~15 */ +} wifi_csi_config_t; + +/** + * @brief CSI data type + * + */ +typedef struct { + wifi_pkt_rx_ctrl_t rx_ctrl;/**< received packet radio metadata header of the CSI data */ + uint8_t mac[6]; /**< source MAC address of the CSI data */ + bool last_word_invalid; /**< last four bytes of the CSI data is invalid or not */ + uint8_t *buf; /**< buffer of CSI data */ + uint16_t len; /**< length of CSI data */ +} wifi_csi_info_t; + #ifdef __cplusplus } #endif diff --git a/components/esp32/lib b/components/esp32/lib index 0503727b12..8b2f4de9d7 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 0503727b12bf40e5578959c6d9478f25312cdc81 +Subproject commit 8b2f4de9d779f72829a6ce54be2b7b5f1d9add09 From 6e77e68c96c16dd8743c6143e7b55376daf58843 Mon Sep 17 00:00:00 2001 From: Lin Meiling Date: Thu, 29 Mar 2018 14:21:15 +0800 Subject: [PATCH 131/187] Update idf-monitor.rst --- docs/en/get-started/idf-monitor.rst | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/en/get-started/idf-monitor.rst b/docs/en/get-started/idf-monitor.rst index e1ec23cb3d..cf1deec354 100644 --- a/docs/en/get-started/idf-monitor.rst +++ b/docs/en/get-started/idf-monitor.rst @@ -2,11 +2,11 @@ IDF Monitor *********** -The idf_monitor tool is a Python program which runs when the ``make monitor`` target is invoked in IDF. +The IDF Monitor tool is a Python program which runs when the ``make monitor`` target is invoked in IDF. -It is mainly a serial terminal program which relays serial data to and from the target device's serial port, but it has some other IDF-specific xfeatures. +It is mainly a serial terminal program which relays serial data to and from the target device's serial port, but it has some other IDF-specific features. -Interacting With idf_monitor +Interacting With IDF Monitor ============================ - ``Ctrl-]`` will exit the monitor. @@ -16,7 +16,7 @@ Interacting With idf_monitor Automatically Decoding Addresses ================================ -Any time esp-idf prints a hexadecimal code address of the form ``0x4_______``, idf_monitor will use addr2line_ to look up the source code location and function name. +Any time esp-idf prints a hexadecimal code address of the form ``0x4_______``, IDF Monitor will use addr2line_ to look up the source code location and function name. .. highlight:: none @@ -33,7 +33,7 @@ When an esp-idf app crashes and panics a register dump and backtrace such as thi Backtrace: 0x400f360d:0x3ffb7e00 0x400dbf56:0x3ffb7e20 0x400dbf5e:0x3ffb7e40 0x400dbf82:0x3ffb7e60 0x400d071d:0x3ffb7e90 -idf_monitor will augment the dump:: +IDF Monitor will augment the dump:: Guru Meditation Error of type StoreProhibited occurred on core 0. Exception was unhandled. Register dump: @@ -54,7 +54,7 @@ idf_monitor will augment the dump:: 0x400dbf82: app_main at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:33 0x400d071d: main_task at /home/gus/esp/32/idf/components/esp32/./cpu_start.c:254 -Behind the scenes, the command idf_monitor runs to decode each address is:: +Behind the scenes, the command IDF Monitor runs to decode each address is:: xtensa-esp32-elf-addr2line -pfiaC -e build/PROJECT.elf ADDRESS @@ -68,9 +68,9 @@ Optionally, the panic handler can be configured to run a serial "gdb stub" which To enable the gdbstub, run ``make menuconfig`` and set :ref:`CONFIG_ESP32_PANIC` option to ``Invoke GDBStub``. -If this option is enabled and idf_monitor sees the gdb stub has loaded, it will automatically pause serial monitoring and run GDB with the correct arguments. After GDB exits, the board will be reset via the RTS serial line (if this is connected.) +If this option is enabled and IDF Monitor sees the gdb stub has loaded, it will automatically pause serial monitoring and run GDB with the correct arguments. After GDB exits, the board will be reset via the RTS serial line (if this is connected.) -Behind the scenes, the command idf_monitor runs is:: +Behind the scenes, the command IDF Monitor runs is:: xtensa-esp32-elf-gdb -ex "set serial baud BAUD" -ex "target remote PORT" -ex interrupt build/PROJECT.elf @@ -78,9 +78,9 @@ Behind the scenes, the command idf_monitor runs is:: Quick Compile and Flash ======================= -The keyboard shortcut ``Ctrl-T Ctrl-F`` will pause idf_monitor, run the ``make flash`` target, then resume idf_monitor. Any changed source files will be recompiled before re-flashing. +The keyboard shortcut ``Ctrl-T Ctrl-F`` will pause IDF Monitor, run the ``make flash`` target, then resume IDF Monitor. Any changed source files will be recompiled before re-flashing. -The keyboard shortcut ``Ctrl-T Ctrl-A`` will pause idf-monitor, run the ``make app-flash`` target, then resume idf_monitor. This is similar to ``make flash``, but only the main app is compiled and reflashed. +The keyboard shortcut ``Ctrl-T Ctrl-A`` will pause IDF Monitor, run the ``make app-flash`` target, then resume IDF Monitor. This is similar to ``make flash``, but only the main app is compiled and reflashed. Quick Reset @@ -112,10 +112,10 @@ Earlier versions of ESP-IDF used the pySerial_ command line program miniterm_ as This program can still be run, via ``make simple_monitor``. -idf_monitor is based on miniterm and shares the same basic keyboard shortcuts. +IDF Monitor is based on miniterm and shares the same basic keyboard shortcuts. -Known Issues with idf_monitor +Known Issues with IDF Monitor ============================= Issues Observed on Windows From 32e838ddb658bf8e06ae431596bf6707e4769a34 Mon Sep 17 00:00:00 2001 From: "Ing. Jaroslav Safka" Date: Fri, 2 Mar 2018 23:17:32 +0100 Subject: [PATCH 132/187] Add xRingbufferCanRead, xRingbufferCanWrite Add function xRingbufferCanRead & xRingbufferCanWrite to be able use queue sets. Without it is not possible to check to which ringbuffer returned semaphore belongs. --- .../freertos/include/freertos/ringbuf.h | 27 +++++++++ components/freertos/ringbuf.c | 60 ++++++++++++------- 2 files changed, 66 insertions(+), 21 deletions(-) diff --git a/components/freertos/include/freertos/ringbuf.h b/components/freertos/include/freertos/ringbuf.h index 0f23a44e6b..8eae4061c6 100644 --- a/components/freertos/include/freertos/ringbuf.h +++ b/components/freertos/include/freertos/ringbuf.h @@ -297,6 +297,33 @@ BaseType_t xRingbufferAddToQueueSetRead(RingbufHandle_t ringbuf, QueueSetHandle_ */ BaseType_t xRingbufferAddToQueueSetWrite(RingbufHandle_t ringbuf, QueueSetHandle_t xQueueSet); +/** + * @brief Check if the selected queue set member is the ringbuffer's read semaphore + * + * This API checks if queue set member returned from xQueueSelectFromSet + * is the read semaphore of this ring buffer. If so, this indicates the ring buffer + * has items waiting to be read. + * + * @param ringbuf Ring buffer which should be checked + * @param member Member returned from xQueueSelectFromSet + * + * @return pdTRUE when semaphore belongs to ringbuffer, pdFALSE otherwise. + */ +BaseType_t xRingbufferCanRead(RingbufHandle_t ringbuf, QueueSetMemberHandle_t member); + +/** + * @brief Check if the selected queue set member is the ringbuffer's write semaphore + * + * This API checks if queue set member returned from xQueueSelectFromSet + * is the write semaphore of this ring buffer. If so, this indicates the ring buffer + * has items waiting for write. + * + * @param ringbuf Ring buffer which should be checked + * @param member Member returned from xQueueSelectFromSet + * + * @return pdTRUE when semaphore belongs to ringbuffer, pdFALSE otherwise. + */ +BaseType_t xRingbufferCanWrite(RingbufHandle_t ringbuf, QueueSetMemberHandle_t member); /** * @brief Remove the ringbuffer from a queue set. diff --git a/components/freertos/ringbuf.c b/components/freertos/ringbuf.c index 7cb24a5cae..2f1998bfe6 100644 --- a/components/freertos/ringbuf.c +++ b/components/freertos/ringbuf.c @@ -75,11 +75,11 @@ typedef struct { //Calculate space free in the buffer -static int ringbufferFreeMem(ringbuf_t *rb) +static int ringbufferFreeMem(ringbuf_t *rb) { int free_size = rb->free_ptr-rb->write_ptr; if (free_size <= 0) free_size += rb->size; - //Reserve one byte. If we do not do this and the entire buffer is filled, we get a situation + //Reserve one byte. If we do not do this and the entire buffer is filled, we get a situation //where read_ptr == free_ptr, messing up the next calculation. return free_size-1; } @@ -89,19 +89,19 @@ static int ringbufferFreeMem(ringbuf_t *rb) //success, pdFALSE if it can't make the item fit and the calling routine needs to retry //later or fail. //This function by itself is not threadsafe, always call from within a muxed section. -static BaseType_t copyItemToRingbufNoSplit(ringbuf_t *rb, uint8_t *buffer, size_t buffer_size) +static BaseType_t copyItemToRingbufNoSplit(ringbuf_t *rb, uint8_t *buffer, size_t buffer_size) { size_t rbuffer_size; rbuffer_size=(buffer_size+3)&~3; //Payload length, rounded to next 32-bit value configASSERT(((int)rb->write_ptr&3)==0); //write_ptr needs to be 32-bit aligned - configASSERT(rb->write_ptr-(rb->data+rb->size) >= sizeof(buf_entry_hdr_t)); //need to have at least the size + configASSERT(rb->write_ptr-(rb->data+rb->size) >= sizeof(buf_entry_hdr_t)); //need to have at least the size //of a header to the end of the ringbuff size_t rem_len=(rb->data + rb->size) - rb->write_ptr; //length remaining until end of ringbuffer - + //See if we have enough contiguous space to write the buffer. if (rem_len < rbuffer_size + sizeof(buf_entry_hdr_t)) { - //Buffer plus header is not going to fit in the room from wr_pos to the end of the - //ringbuffer... but we're not allowed to split the buffer. We need to fill the + //Buffer plus header is not going to fit in the room from wr_pos to the end of the + //ringbuffer... but we're not allowed to split the buffer. We need to fill the //rest of the ringbuffer with a dummy item so we can place the data at the _start_ of //the ringbuffer.. //First, find out if we actually have enough space at the start of the ringbuffer to @@ -141,7 +141,7 @@ static BaseType_t copyItemToRingbufNoSplit(ringbuf_t *rb, uint8_t *buffer, size_ //The buffer will wrap around if we don't have room for a header anymore. if ((rb->data+rb->size)-rb->write_ptr < sizeof(buf_entry_hdr_t)) { //'Forward' the write buffer until we are at the start of the ringbuffer. - //The read pointer will always be at the start of a full header, which cannot + //The read pointer will always be at the start of a full header, which cannot //exist at the point of the current write pointer, so there's no chance of overtaking //that. rb->write_ptr=rb->data; @@ -154,29 +154,29 @@ static BaseType_t copyItemToRingbufNoSplit(ringbuf_t *rb, uint8_t *buffer, size_ //success, pdFALSE if it can't make the item fit and the calling routine needs to retry //later or fail. //This function by itself is not threadsafe, always call from within a muxed section. -static BaseType_t copyItemToRingbufAllowSplit(ringbuf_t *rb, uint8_t *buffer, size_t buffer_size) +static BaseType_t copyItemToRingbufAllowSplit(ringbuf_t *rb, uint8_t *buffer, size_t buffer_size) { size_t rbuffer_size; rbuffer_size=(buffer_size+3)&~3; //Payload length, rounded to next 32-bit value configASSERT(((int)rb->write_ptr&3)==0); //write_ptr needs to be 32-bit aligned - configASSERT(rb->write_ptr-(rb->data+rb->size) >= sizeof(buf_entry_hdr_t)); //need to have at least the size + configASSERT(rb->write_ptr-(rb->data+rb->size) >= sizeof(buf_entry_hdr_t)); //need to have at least the size //of a header to the end of the ringbuff size_t rem_len=(rb->data + rb->size) - rb->write_ptr; //length remaining until end of ringbuffer - + //See if we have enough contiguous space to write the buffer. if (rem_len < rbuffer_size + sizeof(buf_entry_hdr_t)) { //The buffer can't be contiguously written to the ringbuffer, but needs special handling. Do //that depending on how the ringbuffer is configured. //The code here is also expected to check if the buffer, mangled in whatever way is implemented, //will still fit, and return pdFALSE if that is not the case. - //Buffer plus header is not going to fit in the room from wr_pos to the end of the + //Buffer plus header is not going to fit in the room from wr_pos to the end of the //ringbuffer... we need to split the write in two. //First, see if this will fit at all. if (ringbufferFreeMem(rb) < (sizeof(buf_entry_hdr_t)*2)+rbuffer_size) { //Will not fit. return pdFALSE; } - //Because the code at the end of the function makes sure we always have + //Because the code at the end of the function makes sure we always have //room for a header, this should never assert. configASSERT(rem_len>=sizeof(buf_entry_hdr_t)); //Okay, it should fit. Write everything. @@ -233,7 +233,7 @@ static BaseType_t copyItemToRingbufAllowSplit(ringbuf_t *rb, uint8_t *buffer, si //The buffer will wrap around if we don't have room for a header anymore. if ((rb->data+rb->size)-rb->write_ptr < sizeof(buf_entry_hdr_t)) { //'Forward' the write buffer until we are at the start of the ringbuffer. - //The read pointer will always be at the start of a full header, which cannot + //The read pointer will always be at the start of a full header, which cannot //exist at the point of the current write pointer, so there's no chance of overtaking //that. rb->write_ptr=rb->data; @@ -247,10 +247,10 @@ static BaseType_t copyItemToRingbufAllowSplit(ringbuf_t *rb, uint8_t *buffer, si //success, pdFALSE if it can't make the item fit and the calling routine needs to retry //later or fail. //This function by itself is not threadsafe, always call from within a muxed section. -static BaseType_t copyItemToRingbufByteBuf(ringbuf_t *rb, uint8_t *buffer, size_t buffer_size) +static BaseType_t copyItemToRingbufByteBuf(ringbuf_t *rb, uint8_t *buffer, size_t buffer_size) { size_t rem_len=(rb->data + rb->size) - rb->write_ptr; //length remaining until end of ringbuffer - + //See if we have enough contiguous space to write the buffer. if (rem_len < buffer_size) { //...Nope. Write the data bit that fits. @@ -409,6 +409,24 @@ static void returnItemToRingbufBytebuf(ringbuf_t *rb, void *item) { //Free the read memory. rb->free_ptr=rb->read_ptr; } +/* + Check if the selected queue set member is the ringbuffer's read semaphore +*/ +BaseType_t xRingbufferCanRead(RingbufHandle_t ringbuf, QueueSetMemberHandle_t member) +{ + ringbuf_t *rb=(ringbuf_t *)ringbuf; + configASSERT(rb); + return (rb->items_buffered_sem == member)? pdTRUE : pdFALSE; +} +/* + Check if the selected queue set member is the ringbuffer's write semaphore +*/ +BaseType_t xRingbufferCanWrite(RingbufHandle_t ringbuf, QueueSetMemberHandle_t member) +{ + ringbuf_t *rb=(ringbuf_t *)ringbuf; + configASSERT(rb); + return (rb->free_space_sem == member)? pdTRUE : pdFALSE; +} void xRingbufferPrintInfo(RingbufHandle_t ringbuf) { @@ -631,7 +649,7 @@ BaseType_t xRingbufferSend(RingbufHandle_t ringbuf, void *data, size_t dataSize, } -BaseType_t xRingbufferSendFromISR(RingbufHandle_t ringbuf, void *data, size_t dataSize, BaseType_t *higher_prio_task_awoken) +BaseType_t xRingbufferSendFromISR(RingbufHandle_t ringbuf, void *data, size_t dataSize, BaseType_t *higher_prio_task_awoken) { ringbuf_t *rb=(ringbuf_t *)ringbuf; BaseType_t write_succeeded; @@ -652,7 +670,7 @@ BaseType_t xRingbufferSendFromISR(RingbufHandle_t ringbuf, void *data, size_t da } -static void *xRingbufferReceiveGeneric(RingbufHandle_t ringbuf, size_t *item_size, TickType_t ticks_to_wait, size_t wanted_size) +static void *xRingbufferReceiveGeneric(RingbufHandle_t ringbuf, size_t *item_size, TickType_t ticks_to_wait, size_t wanted_size) { ringbuf_t *rb=(ringbuf_t *)ringbuf; uint8_t *itemData; @@ -685,7 +703,7 @@ void *xRingbufferReceive(RingbufHandle_t ringbuf, size_t *item_size, TickType_t } -void *xRingbufferReceiveFromISR(RingbufHandle_t ringbuf, size_t *item_size) +void *xRingbufferReceiveFromISR(RingbufHandle_t ringbuf, size_t *item_size) { ringbuf_t *rb=(ringbuf_t *)ringbuf; uint8_t *itemData; @@ -717,7 +735,7 @@ void *xRingbufferReceiveUpToFromISR(RingbufHandle_t ringbuf, size_t *item_size, } -void vRingbufferReturnItem(RingbufHandle_t ringbuf, void *item) +void vRingbufferReturnItem(RingbufHandle_t ringbuf, void *item) { ringbuf_t *rb=(ringbuf_t *)ringbuf; portENTER_CRITICAL(&rb->mux); @@ -727,7 +745,7 @@ void vRingbufferReturnItem(RingbufHandle_t ringbuf, void *item) } -void vRingbufferReturnItemFromISR(RingbufHandle_t ringbuf, void *item, BaseType_t *higher_prio_task_awoken) +void vRingbufferReturnItemFromISR(RingbufHandle_t ringbuf, void *item, BaseType_t *higher_prio_task_awoken) { ringbuf_t *rb=(ringbuf_t *)ringbuf; portENTER_CRITICAL_ISR(&rb->mux); From 4bfa30967ff4ef7fff20180436f761e448c119b8 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Thu, 19 Apr 2018 01:20:34 +0800 Subject: [PATCH 133/187] freeRTOS/Re-factor ring buffers This fixes multiple bugs with ring buffers and re-factors the code. The public API has not changed, however the underlying implementation have various private functions have been changed. The following behavioral changes have been made - Size of ring buffers for No-Split/Allow-Split buffers will not be rounded up to the nearest 32-bit aligned size. This was done to simplify the implementation - Item size for No-Split/Allow-Split buffers will also be rounded up to the nearest 32-bit aligned size. The following bugs have been fixed - In copyItemToRingbufAllowSplit(), when copying an item where the aligned size is smaller than the remaining length, the function does not consider the case where the true size of the item is less than 4 bytes. - The copy functions will automatically wrap around the write pointers when the remaining length of the buffer is not large enough to fit a header, but does not consider if wrapping around will cause an overlap with the read pointer. This will make a full buffer be mistaken for an empty buffer closes #1711 - xRingbufferSend() can get stuck in a infinite loop when the size of the free memory is larger than the needed_size, but too small to fit in the ring buffer due to alignment and extra overhead of wrapping around. closes #1846 - Fixed documentation with ring buffer queue set API - Adding and removing from queue set does not consider the case where the read/write semaphores actually hold a value. The following functions have been deprecated - xRingbufferIsNextItemWrapped() due to lack of thread safety - xRingbufferAddToQueueSetWrite() and xRingbufferRemoveFromQueueSetWrite() as adding the queue sets only work under receive operations. The following functions have been added - xRingbufferReceiveSplit() and xRingbufferReceiveSplitFromISR() as a thread safe way to receive from allow-split buffers - vRingbufferGetInfo() Documentation for ring buffers has also been added. --- .../freertos/include/freertos/ringbuf.h | 533 ++--- components/freertos/ringbuf.c | 1747 ++++++++++------- components/freertos/test/test_ringbuf.c | 791 ++++++-- .../ring_buffer_read_ret_byte_buf.diag | 30 + .../ring_buffer_read_ret_non_byte_buf.diag | 86 + .../ring_buffer_send_byte_buf.diag | 21 + .../ring_buffer_send_non_byte_buf.diag | 30 + .../ring_buffer_wrap_allow_split.diag | 37 + .../ring_buffer_wrap_byte_buf.diag | 23 + .../ring_buffer_wrap_no_split.diag | 35 + docs/en/api-guides/freertos-smp.rst | 7 +- docs/en/api-reference/system/freertos.rst | 7 +- .../system/freertos_additions.rst | 403 ++++ docs/en/api-reference/system/hooks.rst | 51 - docs/en/api-reference/system/index.rst | 2 +- .../system/freertos_additions.rst | 1 + docs/zh_CN/api-reference/system/hooks.rst | 1 - 17 files changed, 2619 insertions(+), 1186 deletions(-) create mode 100644 docs/_static/diagrams/ring-buffer/ring_buffer_read_ret_byte_buf.diag create mode 100644 docs/_static/diagrams/ring-buffer/ring_buffer_read_ret_non_byte_buf.diag create mode 100644 docs/_static/diagrams/ring-buffer/ring_buffer_send_byte_buf.diag create mode 100644 docs/_static/diagrams/ring-buffer/ring_buffer_send_non_byte_buf.diag create mode 100644 docs/_static/diagrams/ring-buffer/ring_buffer_wrap_allow_split.diag create mode 100644 docs/_static/diagrams/ring-buffer/ring_buffer_wrap_byte_buf.diag create mode 100644 docs/_static/diagrams/ring-buffer/ring_buffer_wrap_no_split.diag create mode 100644 docs/en/api-reference/system/freertos_additions.rst delete mode 100644 docs/en/api-reference/system/hooks.rst create mode 100644 docs/zh_CN/api-reference/system/freertos_additions.rst delete mode 100644 docs/zh_CN/api-reference/system/hooks.rst diff --git a/components/freertos/include/freertos/ringbuf.h b/components/freertos/include/freertos/ringbuf.h index 8eae4061c6..de8a369095 100644 --- a/components/freertos/include/freertos/ringbuf.h +++ b/components/freertos/include/freertos/ringbuf.h @@ -1,3 +1,17 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #ifndef FREERTOS_RINGBUF_H #define FREERTOS_RINGBUF_H @@ -11,71 +25,48 @@ extern "C" { #include -//An opaque handle for a ringbuff object. +/** + * Type by which ring buffers are referenced. For example, a call to xRingbufferCreate() + * returns a RingbufHandle_t variable that can then be used as a parameter to + * xRingbufferSend(), xRingbufferReceive(), etc. + */ typedef void * RingbufHandle_t; -/** - * @brief The various types of buffer - * - * A ringbuffer instantiated by these functions essentially acts like a - * FreeRTOS queue, with the difference that it's strictly FIFO and with - * the main advantage that you can put in randomly-sized items. The capacity, - * accordingly, isn't measured in the amount of items, but the amount of - * memory that is used for storing the items. Dependent on the size of - * the items, more or less of them will fit in the ring buffer. - * - * This ringbuffer tries to be efficient with memory: when inserting an item, - * the item data will be copied to the ringbuffer memory. When retrieving - * an item, however, a reference to ringbuffer memory will be returned. - * The returned memory is guaranteed to be 32-bit aligned and contiguous. - * The application can use this memory, but as long as it does, ringbuffer - * writes that would write to this bit of memory will block. - * - * The requirement for items to be contiguous is slightly problematic when - * the only way to place the next item would involve a wraparound from the end - * to the beginning of the ringbuffer. This can be solved (or not) in a few ways, - * see descriptions of possible ringbuf_type_t types below. - * - * The maximum size of an item will be affected by ringbuffer type. - * When split items are allowed, it is acceptable to push items of - * (buffer_size)-16 bytes into the buffer. - * When it's not allowed, the maximum size is (buffer_size/2)-8 bytes. - * The bytebuf can fill the entire buffer with data, it has no overhead. - */ typedef enum { - /** The insertion code will leave the room at the end of the ringbuffer - * unused and instead will put the entire item at the start of the ringbuffer, - * as soon as there is enough free space. + /** + * No-split buffers will only store an item in contiguous memory and will + * never split an item. Each item requires an 8 byte overhead for a header + * and will always internally occupy a 32-bit aligned size of space. */ RINGBUF_TYPE_NOSPLIT = 0, - /** The insertion code will split the item in two items; one which fits - * in the space left at the end of the ringbuffer, one that contains - * the remaining data which is placed in the beginning. - * Two xRingbufferReceive calls will be needed to retrieve the data. + /** + * Allow-split buffers will split an item into two parts if necessary in + * order to store it. Each item requires an 8 byte overhead for a header, + * splitting incurs an extra header. Each item will always internally occupy + * a 32-bit aligned size of space. */ RINGBUF_TYPE_ALLOWSPLIT, - /** This is your conventional byte-based ringbuffer. It does have no - * overhead, but it has no item contiguousness either: a read will just - * give you the entire written buffer space, or the space up to the end - * of the buffer, and writes can be broken up in any way possible. - * Note that this type cannot do a 2nd read before returning the memory - * of the 1st. + /** + * Byte buffers store data as a sequence of bytes and do not maintain separate + * items, therefore byte buffers have no overhead. All data is stored as a + * sequence of byte and any number of bytes can be sent or retrieved each + * time. */ RINGBUF_TYPE_BYTEBUF } ringbuf_type_t; - /** - * @brief Create a ring buffer + * @brief Create a ring buffer * - * @param buf_length Length of circular buffer, in bytes. Each entry will - * take up its own length, plus a header that at the moment - * is equal to sizeof(size_t). - * @param type Type of ring buffer, see ringbuf_type_t. + * @param[in] xBufferSize Size of the buffer in bytes. Note that items require + * space for overhead in no-split/allow-split buffers + * @param[in] xBufferType Type of ring buffer, see documentation. * - * @return A RingbufHandle_t handle to the created ringbuffer, or NULL in case of error. + * @note xBufferSize of no-split/allow-split buffers will be rounded up to the nearest 32-bit aligned size. + * + * @return A handle to the created ring buffer, or NULL in case of error. */ -RingbufHandle_t xRingbufferCreate(size_t buf_length, ringbuf_type_t type); +RingbufHandle_t xRingbufferCreate(size_t xBufferSize, ringbuf_type_t xBufferType); /** * @brief Create a ring buffer of type RINGBUF_TYPE_NOSPLIT for a fixed item_size @@ -83,282 +74,338 @@ RingbufHandle_t xRingbufferCreate(size_t buf_length, ringbuf_type_t type); * This API is similar to xRingbufferCreate(), but it will internally allocate * additional space for the headers. * - * @param item_size Size of each item to be put into the ring buffer - * @param num_item Maximum number of items the buffer needs to hold simultaneously + * @param[in] xItemSize Size of each item to be put into the ring buffer + * @param[in] xItemNum Maximum number of items the buffer needs to hold simultaneously * - * @return A RingbufHandle_t handle to the created ringbuffer, or NULL in case of error. + * @return A RingbufHandle_t handle to the created ring buffer, or NULL in case of error. */ -RingbufHandle_t xRingbufferCreateNoSplit(size_t item_size, size_t num_item); +RingbufHandle_t xRingbufferCreateNoSplit(size_t xItemSize, size_t xItemNum); /** - * @brief Delete a ring buffer + * @brief Insert an item into the ring buffer * - * @param ringbuf Ring buffer to delete - */ -void vRingbufferDelete(RingbufHandle_t ringbuf); - - -/** - * @brief Get maximum size of an item that can be placed in the ring buffer + * Attempt to insert an item into the ring buffer. This function will block until + * enough free space is available or until it timesout. * - * @param ringbuf Ring buffer to query + * @param[in] xRingbuffer Ring buffer to insert the item into + * @param[in] pvItem Pointer to data to insert. NULL is allowed if xItemSize is 0. + * @param[in] xItemSize Size of data to insert. + * @param[in] xTicksToWait Ticks to wait for room in the ring buffer. * - * @return Maximum size, in bytes, of an item that can be placed in a ring buffer. - */ -size_t xRingbufferGetMaxItemSize(RingbufHandle_t ringbuf); - -/** - * @brief Get current free size available in the buffer - * - * This gives the real time free space available in the ring buffer. So basically, - * this will be the maximum size of the entry that can be sent into the buffer. - * - * @note This API is not thread safe. So, if multiple threads are accessing the same - * ring buffer, it is the application's responsibility to ensure atomic access to this - * API and the subsequent Send - * - * @param ringbuf - Ring buffer to query - * - * @return Current free size, in bytes, available for an entry - */ -size_t xRingbufferGetCurFreeSize(RingbufHandle_t ringbuf); - -/** - * @brief Check if the next item is wrapped - * - * This API tells if the next item that is available for a Receive is wrapped - * or not. This is valid only if the ring buffer type is RINGBUF_TYPE_ALLOWSPLIT - * - * @note This API is not thread safe. So, if multiple threads are accessing the same - * ring buffer, it is the application's responsibility to ensure atomic access to this - * API and the subsequent Receive - * - * @param ringbuf - Ring buffer to query - * - * @return true if the next item is wrapped around - * @return false if the next item is not wrapped - */ -bool xRingbufferIsNextItemWrapped(RingbufHandle_t ringbuf); - -/** - * @brief Insert an item into the ring buffer - * - * @param ringbuf Ring buffer to insert the item into - * @param data Pointer to data to insert. NULL is allowed if data_size is 0. - * @param data_size Size of data to insert. A value of 0 is allowed. - * @param ticks_to_wait Ticks to wait for room in the ringbuffer. + * @note For no-split/allow-split ring buffers, the actual size of memory that + * the item will occupy will be rounded up to the nearest 32-bit aligned + * size. This is done to ensure all items are always stored in 32-bit + * aligned fashion. * * @return * - pdTRUE if succeeded - * - pdFALSE on time-out or when the buffer is larger than indicated - * by xRingbufferGetMaxItemSize(ringbuf). + * - pdFALSE on time-out or when the data is larger than the maximum permissible size of the buffer */ -BaseType_t xRingbufferSend(RingbufHandle_t ringbuf, void *data, size_t data_size, TickType_t ticks_to_wait); - +BaseType_t xRingbufferSend(RingbufHandle_t xRingbuffer, const void *pvItem, size_t xItemSize, TickType_t xTicksToWait); /** - * @brief Insert an item into the ring buffer from an ISR + * @brief Insert an item into the ring buffer in an ISR * - * @param ringbuf Ring buffer to insert the item into - * @param data Pointer to data to insert. NULL is allowed if data_size is 0. - * @param data_size Size of data to insert. A value of 0 is allowed. - * @param[out] higher_prio_task_awoken Value pointed to will be set to pdTRUE - * if the push woke up a higher priority task. + * Attempt to insert an item into the ring buffer from an ISR. This function + * will return immediately if there is insufficient free space in the buffer. * - * @return pdTRUE if succeeded, pdFALSE when the ring buffer does not have space. - */ -BaseType_t xRingbufferSendFromISR(RingbufHandle_t ringbuf, void *data, size_t data_size, BaseType_t *higher_prio_task_awoken); - -/** - * @brief Retrieve an item from the ring buffer + * @param[in] xRingbuffer Ring buffer to insert the item into + * @param[in] pvItem Pointer to data to insert. NULL is allowed if xItemSize is 0. + * @param[in] xItemSize Size of data to insert. + * @param[out] pxHigherPriorityTaskWoken Value pointed to will be set to pdTRUE if the function woke up a higher priority task. * - * @note A call to vRingbufferReturnItem() is required after this to free up - * the data received. - * - * @param ringbuf Ring buffer to retrieve the item from - * @param[out] item_size Pointer to a variable to which the size of the - * retrieved item will be written. - * @param ticks_to_wait Ticks to wait for items in the ringbuffer. + * @note For no-split/allow-split ring buffers, the actual size of memory that + * the item will occupy will be rounded up to the nearest 32-bit aligned + * size. This is done to ensure all items are always stored in 32-bit + * aligned fashion. * * @return - * - pointer to the retrieved item on success; *item_size filled with - * the length of the item. - * - NULL on timeout, *item_size is untouched in that case. + * - pdTRUE if succeeded + * - pdFALSE when the ring buffer does not have space. */ -void *xRingbufferReceive(RingbufHandle_t ringbuf, size_t *item_size, TickType_t ticks_to_wait); - +BaseType_t xRingbufferSendFromISR(RingbufHandle_t xRingbuffer, const void *pvItem, size_t xItemSize, BaseType_t *pxHigherPriorityTaskWoken); /** - * @brief Retrieve an item from the ring buffer from an ISR + * @brief Retrieve an item from the ring buffer * - * @note A call to vRingbufferReturnItemFromISR() is required after this to - * free up the data received + * Attempt to retrieve an item from the ring buffer. This function will block + * until an item is available or until it timesout. * - * @param ringbuf Ring buffer to retrieve the item from - * @param[out] item_size Pointer to a variable to which the size of the - * retrieved item will be written. + * @param[in] xRingbuffer Ring buffer to retrieve the item from + * @param[out] pxItemSize Pointer to a variable to which the size of the retrieved item will be written. + * @param[in] xTicksToWait Ticks to wait for items in the ring buffer. + * + * @note A call to vRingbufferReturnItem() is required after this to free the item retrieved. * * @return - * - Pointer to the retrieved item on success; *item_size filled with - * the length of the item. - * - NULL when the ringbuffer is empty, *item_size is untouched in that case. + * - Pointer to the retrieved item on success; *pxItemSize filled with the length of the item. + * - NULL on timeout, *pxItemSize is untouched in that case. */ -void *xRingbufferReceiveFromISR(RingbufHandle_t ringbuf, size_t *item_size); - +void *xRingbufferReceive(RingbufHandle_t xRingbuffer, size_t *pxItemSize, TickType_t xTicksToWait); /** - * @brief Retrieve bytes from a ByteBuf type of ring buffer, - * specifying the maximum amount of bytes to return + * @brief Retrieve an item from the ring buffer in an ISR * - * @note A call to vRingbufferReturnItem() is required after this to free up - * the data received. + * Attempt to retrieve an item from the ring buffer. This function returns immediately + * if there are no items available for retrieval * - * @param ringbuf Ring buffer to retrieve the item from - * @param[out] item_size Pointer to a variable to which the size - * of the retrieved item will be written. - * @param ticks_to_wait Ticks to wait for items in the ringbuffer. - * @param wanted_size Maximum number of bytes to return. + * @param[in] xRingbuffer Ring buffer to retrieve the item from + * @param[out] pxItemSize Pointer to a variable to which the size of the + * retrieved item will be written. + * + * @note A call to vRingbufferReturnItemFromISR() is required after this to free the item retrieved. + * @note Byte buffers do not allow multiple retrievals before returning an item * * @return - * - Pointer to the retrieved item on success; *item_size filled with - * the length of the item. - * - NULL on timeout, *item_size is untouched in that case. + * - Pointer to the retrieved item on success; *pxItemSize filled with the length of the item. + * - NULL when the ring buffer is empty, *pxItemSize is untouched in that case. */ -void *xRingbufferReceiveUpTo(RingbufHandle_t ringbuf, size_t *item_size, TickType_t ticks_to_wait, size_t wanted_size); - +void *xRingbufferReceiveFromISR(RingbufHandle_t xRingbuffer, size_t *pxItemSize); /** - * @brief Retrieve bytes from a ByteBuf type of ring buffer, - * specifying the maximum amount of bytes to return. Call this from an ISR. + * @brief Retrieve a split item from an allow-split ring buffer * - * @note A call to vRingbufferReturnItemFromISR() is required after this - * to free up the data received. + * Attempt to retrieve a split item from an allow-split ring buffer. If the item + * is not split, only a single item is retried. If the item is split, both parts + * will be retrieved. This function will block until an item is available or + * until it timesout. * - * @param ringbuf Ring buffer to retrieve the item from - * @param[out] item_size Pointer to a variable to which the size of the - * retrieved item will be written. - * @param wanted_size Maximum number of bytes to return. + * @param[in] xRingbuffer Ring buffer to retrieve the item from + * @param[out] ppvHeadItem Double pointer to first part (set to NULL if no items were retrieved) + * @param[out] ppvTailItem Double pointer to second part (set to NULL if item is not split) + * @param[out] pxHeadItemSize Pointer to size of first part (unmodified if no items were retrieved) + * @param[out] pxTailItemSize Pointer to size of second part (unmodified if item is not split) + * @param[in] xTicksToWait Ticks to wait for items in the ring buffer. + * + * @note Call(s) to vRingbufferReturnItem() is required after this to free up the item(s) retrieved. + * @note This function should only be called on allow-split buffers * * @return - * - Pointer to the retrieved item on success; *item_size filled with + * - pdTRUE if an item (split or unsplit) was retrieved + * - pdFALSE when no item was retrieved + */ +BaseType_t xRingbufferReceiveSplit(RingbufHandle_t xRingbuffer, void **ppvHeadItem, void **ppvTailItem, size_t *pxHeadItemSize, size_t *pxTailItemSize, TickType_t xTicksToWait); + +/** + * @brief Retrieve a split item from an allow-split ring buffer in an ISR + * + * Attempt to retrieve a split item from an allow-split ring buffer. If the item + * is not split, only a single item is retried. If the item is split, both parts + * will be retrieved. This function returns immediately if there are no items + * available for retrieval + * + * @param[in] xRingbuffer Ring buffer to retrieve the item from + * @param[out] ppvHeadItem Double pointer to first part (set to NULL if no items were retrieved) + * @param[out] ppvTailItem Double pointer to second part (set to NULL if item is not split) + * @param[out] pxHeadItemSize Pointer to size of first part (unmodified if no items were retrieved) + * @param[out] pxTailItemSize Pointer to size of second part (unmodified if item is not split) + * + * @note Calls to vRingbufferReturnItemFromISR() is required after this to free up the item(s) retrieved. + * @note This function should only be called on allow-split buffers + * + * @return + * - pdTRUE if an item (split or unsplit) was retrieved + * - pdFALSE when no item was retrieved + */ +BaseType_t xRingbufferReceiveSplitFromISR(RingbufHandle_t xRingbuffer, void **ppvHeadItem, void **ppvTailItem, size_t *pxHeadItemSize, size_t *pxTailItemSize); + +/** + * @brief Retrieve bytes from a byte buffer, specifying the maximum amount of bytes to retrieve + * + * Attempt to retrieve data from a byte buffer whilst specifying a maximum number + * of bytes to retrieve. This function will block until there is data available + * for retrieval or until it timesout. + * + * @param[in] xRingbuffer Ring buffer to retrieve the item from + * @param[out] pxItemSize Pointer to a variable to which the size of the retrieved item will be written. + * @param[in] xTicksToWait Ticks to wait for items in the ring buffer. + * @param[in] xMaxSize Maximum number of bytes to return. + * + * @note A call to vRingbufferReturnItem() is required after this to free up the data retrieved. + * @note This function should only be called on byte buffers + * @note Byte buffers do not allow multiple retrievals before returning an item + * + * @return + * - Pointer to the retrieved item on success; *pxItemSize filled with * the length of the item. - * - NULL when the ringbuffer is empty, *item_size is untouched in that case. + * - NULL on timeout, *pxItemSize is untouched in that case. */ -void *xRingbufferReceiveUpToFromISR(RingbufHandle_t ringbuf, size_t *item_size, size_t wanted_size); - - +void *xRingbufferReceiveUpTo(RingbufHandle_t xRingbuffer, size_t *pxItemSize, TickType_t xTicksToWait, size_t xMaxSize); /** - * @brief Return a previously-retrieved item to the ringbuffer + * @brief Retrieve bytes from a byte buffer, specifying the maximum amount of + * bytes to retrieve. Call this from an ISR. * - * @param ringbuf Ring buffer the item was retrieved from - * @param item Item that was received earlier + * Attempt to retrieve bytes from a byte buffer whilst specifying a maximum number + * of bytes to retrieve. This function will return immediately if there is no data + * available for retrieval. + * + * @param[in] xRingbuffer Ring buffer to retrieve the item from + * @param[out] pxItemSize Pointer to a variable to which the size of the retrieved item will be written. + * @param[in] xMaxSize Maximum number of bytes to return. + * + * @note A call to vRingbufferReturnItemFromISR() is required after this to free up the data received. + * @note This function should only be called on byte buffers + * @note Byte buffers do not allow multiple retrievals before returning an item + * + * @return + * - Pointer to the retrieved item on success; *pxItemSize filled with + * the length of the item. + * - NULL when the ring buffer is empty, *pxItemSize is untouched in that case. */ -void vRingbufferReturnItem(RingbufHandle_t ringbuf, void *item); - - +void *xRingbufferReceiveUpToFromISR(RingbufHandle_t xRingbuffer, size_t *pxItemSize, size_t xMaxSize); /** - * @brief Return a previously-retrieved item to the ringbuffer from an ISR + * @brief Return a previously-retrieved item to the ring buffer * - * @param ringbuf Ring buffer the item was retrieved from - * @param item Item that was received earlier - * @param[out] higher_prio_task_awoken Value pointed to will be set to pdTRUE - * if the push woke up a higher priority task. + * @param[in] xRingbuffer Ring buffer the item was retrieved from + * @param[in] pvItem Item that was received earlier + * + * @note If a split item is retrieved, both parts should be returned by calling this function twice */ -void vRingbufferReturnItemFromISR(RingbufHandle_t ringbuf, void *item, BaseType_t *higher_prio_task_awoken); - +void vRingbufferReturnItem(RingbufHandle_t xRingbuffer, void *pvItem); /** - * @brief Add the ringbuffer to a queue set. + * @brief Return a previously-retrieved item to the ring buffer from an ISR * - * This specifically adds the semaphore that indicates more space - * has become available in the ringbuffer. + * @param[in] xRingbuffer Ring buffer the item was retrieved from + * @param[in] pvItem Item that was received earlier + * @param[out] pxHigherPriorityTaskWoken Value pointed to will be set to pdTRUE + * if the function woke up a higher priority task. * - * @param ringbuf Ring buffer to add to the queue set - * @param xQueueSet Queue set to add the ringbuffer to + * @note If a split item is retrieved, both parts should be returned by calling this function twice + */ +void vRingbufferReturnItemFromISR(RingbufHandle_t xRingbuffer, void *pvItem, BaseType_t *pxHigherPriorityTaskWoken); + +/** + * @brief Delete a ring buffer + * + * @param[in] xRingbuffer Ring buffer to delete + */ +void vRingbufferDelete(RingbufHandle_t xRingbuffer); + +/** + * @brief Get maximum size of an item that can be placed in the ring buffer + * + * This function returns the maximum size an item can have if it was placed in + * an empty ring buffer. + * + * @param[in] xRingbuffer Ring buffer to query + * + * @return Maximum size, in bytes, of an item that can be placed in a ring buffer. + */ +size_t xRingbufferGetMaxItemSize(RingbufHandle_t xRingbuffer); + +/** + * @brief Get current free size available for an item/data in the buffer + * + * This gives the real time free space available for an item/data in the ring + * buffer. This represents the maximum size an item/data can have if it was + * currently sent to the ring buffer. + * + * @warning This API is not thread safe. So, if multiple threads are accessing + * the same ring buffer, it is the application's responsibility to + * ensure atomic access to this API and the subsequent Send + * + * @param[in] xRingbuffer Ring buffer to query + * + * @return Current free size, in bytes, available for an entry + */ +size_t xRingbufferGetCurFreeSize(RingbufHandle_t xRingbuffer); + +/** + * @brief Add the ring buffer's read semaphore to a queue set. + * + * The ring buffer's read semaphore indicates that data has been written + * to the ring buffer. This function adds the ring buffer's read semaphore to + * a queue set. + * + * @param[in] xRingbuffer Ring buffer to add to the queue set + * @param[in] xQueueSet Queue set to add the ring buffer's read semaphore to * * @return * - pdTRUE on success, pdFALSE otherwise */ -BaseType_t xRingbufferAddToQueueSetRead(RingbufHandle_t ringbuf, QueueSetHandle_t xQueueSet); +BaseType_t xRingbufferAddToQueueSetRead(RingbufHandle_t xRingbuffer, QueueSetHandle_t xQueueSet); /** - * @brief Add the ringbuffer to a queue set. + * @brief Check if the selected queue set member is the ring buffer's read semaphore * - * This specifically adds the semaphore that indicates something has been - * written into the ringbuffer. - * - * @param ringbuf Ring buffer to add to the queue set - * @param xQueueSet Queue set to add the ringbuffer to - * - * @return pdTRUE on success, pdFALSE otherwise - */ -BaseType_t xRingbufferAddToQueueSetWrite(RingbufHandle_t ringbuf, QueueSetHandle_t xQueueSet); - -/** - * @brief Check if the selected queue set member is the ringbuffer's read semaphore - * - * This API checks if queue set member returned from xQueueSelectFromSet + * This API checks if queue set member returned from xQueueSelectFromSet() * is the read semaphore of this ring buffer. If so, this indicates the ring buffer - * has items waiting to be read. + * has items waiting to be retrieved. * - * @param ringbuf Ring buffer which should be checked - * @param member Member returned from xQueueSelectFromSet + * @param[in] xRingbuffer Ring buffer which should be checked + * @param[in] xMember Member returned from xQueueSelectFromSet * - * @return pdTRUE when semaphore belongs to ringbuffer, pdFALSE otherwise. + * @return + * - pdTRUE when semaphore belongs to ring buffer + * - pdFALSE otherwise. */ -BaseType_t xRingbufferCanRead(RingbufHandle_t ringbuf, QueueSetMemberHandle_t member); +BaseType_t xRingbufferCanRead(RingbufHandle_t xRingbuffer, QueueSetMemberHandle_t xMember); /** - * @brief Check if the selected queue set member is the ringbuffer's write semaphore + * @brief Remove the ring buffer's read semaphore from a queue set. * - * This API checks if queue set member returned from xQueueSelectFromSet - * is the write semaphore of this ring buffer. If so, this indicates the ring buffer - * has items waiting for write. + * This specifically removes a ring buffer's read semaphore from a queue set. The + * read semaphore is used to indicate when data has been written to the ring buffer * - * @param ringbuf Ring buffer which should be checked - * @param member Member returned from xQueueSelectFromSet + * @param[in] xRingbuffer Ring buffer to remove from the queue set + * @param[in] xQueueSet Queue set to remove the ring buffer's read semaphore from * - * @return pdTRUE when semaphore belongs to ringbuffer, pdFALSE otherwise. + * @return + * - pdTRUE on success + * - pdFALSE otherwise */ -BaseType_t xRingbufferCanWrite(RingbufHandle_t ringbuf, QueueSetMemberHandle_t member); +BaseType_t xRingbufferRemoveFromQueueSetRead(RingbufHandle_t xRingbuffer, QueueSetHandle_t xQueueSet); /** - * @brief Remove the ringbuffer from a queue set. + * @brief Get information about ring buffer status * - * This specifically removes the semaphore that indicates more space - * has become available in the ringbuffer. + * Get information of the a ring buffer's current status such as + * free/read/write pointer positions, and number of items waiting to be retrieved. + * Arguments can be set to NULL if they are not required. * - * @param ringbuf Ring buffer to remove from the queue set - * @param xQueueSet Queue set to remove the ringbuffer from - * - * @return pdTRUE on success, pdFALSE otherwise + * @param[in] xRingbuffer Ring buffer to remove from the queue set + * @param[out] uxFree Pointer use to store free pointer position + * @param[out] uxRead Pointer use to store read pointer position + * @param[out] uxWrite Pointer use to store write pointer position + * @param[out] uxItemsWaiting Pointer use to store number of items (bytes for byte buffer) waiting to be retrieved */ -BaseType_t xRingbufferRemoveFromQueueSetRead(RingbufHandle_t ringbuf, QueueSetHandle_t xQueueSet); - +void vRingbufferGetInfo(RingbufHandle_t xRingbuffer, UBaseType_t *uxFree, UBaseType_t *uxRead, UBaseType_t *uxWrite, UBaseType_t *uxItemsWaiting); /** - * @brief Remove the ringbuffer from a queue set. + * @brief Debugging function to print the internal pointers in the ring buffer * - * This specifically removes the semaphore that indicates something - * has been written to the ringbuffer. - * - * @param ringbuf Ring buffer to remove from the queue set - * @param xQueueSet Queue set to remove the ringbuffer from - * - * @return pdTRUE on success, pdFALSE otherwise + * @param xRingbuffer Ring buffer to show */ -BaseType_t xRingbufferRemoveFromQueueSetWrite(RingbufHandle_t ringbuf, QueueSetHandle_t xQueueSet); +void xRingbufferPrintInfo(RingbufHandle_t xRingbuffer); +/* -------------------------------- Deprecated Functions --------------------------- */ -/** - * @brief Debugging function to print the internal pointers in the ring buffer - * - * @param ringbuf Ring buffer to show +/** @cond */ //Doxygen command to hide deprecated function from API Reference +/* + * Deprecated as function is not thread safe and does not check if an item is + * actually available for retrieval. Use xRingbufferReceiveSplit() instead for + * thread safe method of retrieve a split item. */ -void xRingbufferPrintInfo(RingbufHandle_t ringbuf); +bool xRingbufferIsNextItemWrapped(RingbufHandle_t xRingbuffer) __attribute__((deprecated)); + +/* + * Deprecated as queue sets are not meant to be used for writing to buffers. Adding + * the ring buffer write semaphore to a queue set will break queue set usage rules, + * as every read of a semaphore must be preceded by a call to xQueueSelectFromSet(). + * QueueSetWrite no longer supported. + */ +BaseType_t xRingbufferAddToQueueSetWrite(RingbufHandle_t xRingbuffer, QueueSetHandle_t xQueueSet) __attribute__((deprecated)); + +/* + * Deprecated as queue sets are not meant to be used for writing to buffers. + * QueueSetWrite no longer supported. + */ +BaseType_t xRingbufferRemoveFromQueueSetWrite(RingbufHandle_t xRingbuffer, QueueSetHandle_t xQueueSet) __attribute__((deprecated)); +/** @endcond */ #ifdef __cplusplus } diff --git a/components/freertos/ringbuf.c b/components/freertos/ringbuf.c index 2f1998bfe6..606cea148d 100644 --- a/components/freertos/ringbuf.c +++ b/components/freertos/ringbuf.c @@ -1,4 +1,4 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,776 +12,1173 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" -#include "freertos/queue.h" -#include "freertos/xtensa_api.h" -#include "freertos/ringbuf.h" -#include "esp_attr.h" -#include -#include #include -#include +#include +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" +#include "ringbuf.h" -typedef enum { - flag_allowsplit = 1, - flag_bytebuf = 2, -} rbflag_t; +//32-bit alignment macros +#define rbALIGN_SIZE( xSize ) ( ( xSize + portBYTE_ALIGNMENT_MASK ) & ~portBYTE_ALIGNMENT_MASK ) +#define rbCHECK_ALIGNED( pvPtr ) ( ( ( UBaseType_t ) pvPtr & portBYTE_ALIGNMENT_MASK ) == 0 ) -typedef enum { - iflag_free = 1, //Buffer is not read and given back by application, free to overwrite - iflag_dummydata = 2, //Data from here to end of ringbuffer is dummy. Restart reading at start of ringbuffer. - iflag_wrap = 4, //Valid for RINGBUF_TYPE_ALLOWSPLIT, indicating that rest of the data is wrapped around -} itemflag_t; +//Ring buffer flags +#define rbALLOW_SPLIT_FLAG ( ( UBaseType_t ) 1 ) //The ring buffer allows items to be split +#define rbBYTE_BUFFER_FLAG ( ( UBaseType_t ) 2 ) //The ring buffer is a byte buffer +#define rbBUFFER_FULL_FLAG ( ( UBaseType_t ) 4 ) //The ring buffer is currently full (write pointer == free pointer) +//Item flags +#define rbITEM_FREE_FLAG ( ( UBaseType_t ) 1 ) //Item has been retrieved and returned by application, free to overwrite +#define rbITEM_DUMMY_DATA_FLAG ( ( UBaseType_t ) 2 ) //Data from here to end of the ring buffer is dummy data. Restart reading at start of head of the buffer +#define rbITEM_SPLIT_FLAG ( ( UBaseType_t ) 4 ) //Valid for RINGBUF_TYPE_ALLOWSPLIT, indicating that rest of the data is wrapped around -typedef struct ringbuf_t ringbuf_t; +typedef struct { + //This size of this structure must be 32-bit aligned + size_t xItemLen; + UBaseType_t uxItemFlags; +} ItemHeader_t; -//The ringbuffer structure -struct ringbuf_t { - SemaphoreHandle_t free_space_sem; //Binary semaphore, wakes up writing threads when there's more free space - SemaphoreHandle_t items_buffered_sem; //Binary semaphore, indicates there are new packets in the circular buffer. See remark. - size_t size; //Size of the data storage - uint8_t *write_ptr; //Pointer where the next item is written - uint8_t *read_ptr; //Pointer from where the next item is read - uint8_t *free_ptr; //Pointer to the last block that hasn't been given back to the ringbuffer yet - uint8_t *data; //Data storage - portMUX_TYPE mux; //Spinlock for actual data/ptr/struct modification - rbflag_t flags; - size_t maxItemSize; - //The following keep function pointers to hold different implementations for ringbuffer management. - BaseType_t (*copyItemToRingbufImpl)(ringbuf_t *rb, uint8_t *buffer, size_t buffer_size); - uint8_t *(*getItemFromRingbufImpl)(ringbuf_t *rb, size_t *length, int wanted_length); - void (*returnItemToRingbufImpl)(ringbuf_t *rb, void *item); - size_t (*getFreeSizeImpl)(ringbuf_t *rb); +#define rbHEADER_SIZE sizeof(ItemHeader_t) +typedef struct Ringbuffer_t Ringbuffer_t; +typedef BaseType_t (*CheckItemFitsFunction_t)(Ringbuffer_t *pxRingbuffer, size_t xItemSize); +typedef void (*CopyItemFunction_t)(Ringbuffer_t *pxRingbuffer, const uint8_t *pcItem, size_t xItemSize); +typedef BaseType_t (*CheckItemAvailFunction_t) (Ringbuffer_t *pxRingbuffer); +typedef void *(*GetItemFunction_t)(Ringbuffer_t *pxRingbuffer, BaseType_t *pxIsSplit, size_t xMaxSize, size_t *pxItemSize); +typedef void (*ReturnItemFunction_t)(Ringbuffer_t *pxRingbuffer, uint8_t *pvItem); +typedef size_t (*GetCurMaxSizeFunction_t)(Ringbuffer_t *pxRingbuffer); + +struct Ringbuffer_t { + size_t xSize; //Size of the data storage + UBaseType_t uxRingbufferFlags; //Flags to indicate the type and status of ring buffer + size_t xMaxItemSize; //Maximum item size + + CheckItemFitsFunction_t xCheckItemFits; //Function to check if item can currently fit in ring buffer + CopyItemFunction_t vCopyItem; //Function to copy item to ring buffer + GetItemFunction_t pvGetItem; //Function to get item from ring buffer + ReturnItemFunction_t vReturnItem; //Function to return item to ring buffer + GetCurMaxSizeFunction_t xGetCurMaxSize; //Function to get current free size + + uint8_t *pucWrite; //Write Pointer. Points to where the next item should be written + uint8_t *pucRead; //Read Pointer. Points to where the next item should be read from + uint8_t *pucFree; //Free Pointer. Points to the last item that has yet to be returned to the ring buffer + uint8_t *pucHead; //Pointer to the start of the ring buffer storage area + uint8_t *pucTail; //Pointer to the end of the ring buffer storage area + + BaseType_t xItemsWaiting; //Number of items/bytes(for byte buffers) currently in ring buffer that have not yet been read + SemaphoreHandle_t xFreeSpaceSemaphore; //Binary semaphore, wakes up writing threads when more free space becomes available or when another thread times out attempting to write + SemaphoreHandle_t xItemsBufferedSemaphore; //Binary semaphore, indicates there are new packets in the circular buffer. See remark. + portMUX_TYPE mux; //Spinlock required for SMP }; - - /* Remark: A counting semaphore for items_buffered_sem would be more logical, but counting semaphores in FreeRTOS need a maximum count, and allocate more memory the larger the maximum count is. Here, we -would need to set the maximum to the maximum amount of times a null-byte unit firs in the buffer, +would need to set the maximum to the maximum amount of times a null-byte unit first in the buffer, which is quite high and so would waste a fair amount of memory. */ +/* ------------------------------------------------ Static Declarations ------------------------------------------ */ +/* + * WARNING: All of the following static functions (except generic functions) + * ARE NOT THREAD SAFE. Therefore they should only be called within a critical + * section (using spin locks) + */ -//The header prepended to each ringbuffer entry. Size is assumed to be a multiple of 32bits. -typedef struct { - size_t len; - itemflag_t flags; -} buf_entry_hdr_t; +//Calculate current amount of free space (in bytes) in the ring buffer +static size_t prvGetFreeSize(Ringbuffer_t *pxRingbuffer); +//Checks if an item/data is currently available for retrieval +static BaseType_t prvCheckItemAvail(Ringbuffer_t *pxRingbuffer); -//Calculate space free in the buffer -static int ringbufferFreeMem(ringbuf_t *rb) +//Checks if an item will currently fit in a no-split/allow-split ring buffer +static BaseType_t prvCheckItemFitsDefault( Ringbuffer_t *pxRingbuffer, size_t xItemSize); + +//Checks if an item will currently fit in a byte buffer +static BaseType_t prvCheckItemFitsByteBuffer( Ringbuffer_t *pxRingbuffer, size_t xItemSize); + +//Copies an item to a no-split ring buffer. Only call this function after calling prvCheckItemFitsDefault() +static void prvCopyItemNoSplit(Ringbuffer_t *pxRingbuffer, const uint8_t *pucItem, size_t xItemSize); + +//Copies an item to a allow-split ring buffer. Only call this function after calling prvCheckItemFitsDefault() +static void prvCopyItemAllowSplit(Ringbuffer_t *pxRingbuffer, const uint8_t *pucItem, size_t xItemSize); + +//Copies an item to a byte buffer. Only call this function after calling prvCheckItemFitsByteBuffer() +static void prvCopyItemByteBuf(Ringbuffer_t *pxRingbuffer, const uint8_t *pucItem, size_t xItemSize); + +//Retrieve item from no-split/allow-split ring buffer. *pxIsSplit is set to pdTRUE if the retrieved item is split +static void *prvGetItemDefault(Ringbuffer_t *pxRingbuffer, BaseType_t *pxIsSplit, size_t xUnusedParam, size_t *pxItemSize); + +//Retrieve data from byte buffer. If xMaxSize is 0, all continuous data is retrieved +static void *prvGetItemByteBuf(Ringbuffer_t *pxRingbuffer, BaseType_t *pxUnusedParam ,size_t xMaxSize, size_t *pxItemSize); + +//Return an item to a split/no-split ring buffer +static void prvReturnItemDefault(Ringbuffer_t *pxRingbuffer, uint8_t *pucItem); + +//Return data to a byte buffer +static void prvReturnItemByteBuf(Ringbuffer_t *pxRingbuffer, uint8_t *pucItem); + +//Get the maximum size an item that can currently have if sent to a no-split ring buffer +static size_t prvGetCurMaxSizeNoSplit(Ringbuffer_t *pxRingbuffer); + +//Get the maximum size an item that can currently have if sent to a allow-split ring buffer +static size_t prvGetCurMaxSizeAllowSplit(Ringbuffer_t *pxRingbuffer); + +//Get the maximum size an item that can currently have if sent to a byte buffer +static size_t prvGetCurMaxSizeByteBuf(Ringbuffer_t *pxRingbuffer); + +/** + * Generic function used to retrieve an item/data from ring buffers. If called on + * an allow-split buffer, and pvItem2 and xItemSize2 are not NULL, both parts of + * a split item will be retrieved. xMaxSize will only take effect if called on + * byte buffers. + */ +static BaseType_t prvReceiveGeneric(Ringbuffer_t *pxRingbuffer, void **pvItem1, void **pvItem2, size_t *xItemSize1, size_t *xItemSize2, size_t xMaxSize, TickType_t xTicksToWait); + +//Generic function used to retrieve an item/data from ring buffers in an ISR +static BaseType_t prvReceiveGenericFromISR(Ringbuffer_t *pxRingbuffer, void **pvItem1, void **pvItem2, size_t *xItemSize1, size_t *xItemSize2, size_t xMaxSize); + +/* ------------------------------------------------ Static Definitions ------------------------------------------- */ + +static size_t prvGetFreeSize(Ringbuffer_t *pxRingbuffer) { - int free_size = rb->free_ptr-rb->write_ptr; - if (free_size <= 0) free_size += rb->size; - //Reserve one byte. If we do not do this and the entire buffer is filled, we get a situation - //where read_ptr == free_ptr, messing up the next calculation. - return free_size-1; -} - -//Copies a single item to the ring buffer; refuses to split items. Assumes there is space in the ringbuffer and -//the ringbuffer is locked. Increases write_ptr to the next item. Returns pdTRUE on -//success, pdFALSE if it can't make the item fit and the calling routine needs to retry -//later or fail. -//This function by itself is not threadsafe, always call from within a muxed section. -static BaseType_t copyItemToRingbufNoSplit(ringbuf_t *rb, uint8_t *buffer, size_t buffer_size) -{ - size_t rbuffer_size; - rbuffer_size=(buffer_size+3)&~3; //Payload length, rounded to next 32-bit value - configASSERT(((int)rb->write_ptr&3)==0); //write_ptr needs to be 32-bit aligned - configASSERT(rb->write_ptr-(rb->data+rb->size) >= sizeof(buf_entry_hdr_t)); //need to have at least the size - //of a header to the end of the ringbuff - size_t rem_len=(rb->data + rb->size) - rb->write_ptr; //length remaining until end of ringbuffer - - //See if we have enough contiguous space to write the buffer. - if (rem_len < rbuffer_size + sizeof(buf_entry_hdr_t)) { - //Buffer plus header is not going to fit in the room from wr_pos to the end of the - //ringbuffer... but we're not allowed to split the buffer. We need to fill the - //rest of the ringbuffer with a dummy item so we can place the data at the _start_ of - //the ringbuffer.. - //First, find out if we actually have enough space at the start of the ringbuffer to - //make this work (Again, we need 4 bytes extra because otherwise read_ptr==free_ptr) - if (rb->free_ptr-rb->data < rbuffer_size+sizeof(buf_entry_hdr_t)+4) { - //Will not fit. - return pdFALSE; - } - //If the read buffer hasn't wrapped around yet, there's no way this will work either. - if (rb->free_ptr > rb->write_ptr) { - //No luck. - return pdFALSE; - } - - //Okay, it will fit. Mark the rest of the ringbuffer space with a dummy packet. - buf_entry_hdr_t *hdr=(buf_entry_hdr_t *)rb->write_ptr; - hdr->flags=iflag_dummydata; - //Reset the write pointer to the start of the ringbuffer so the code later on can - //happily write the data. - rb->write_ptr=rb->data; + size_t xReturn; + if (pxRingbuffer->uxRingbufferFlags & rbBUFFER_FULL_FLAG) { + xReturn = 0; } else { - //No special handling needed. Checking if it's gonna fit probably still is a good idea. - if (ringbufferFreeMem(rb) < sizeof(buf_entry_hdr_t)+rbuffer_size) { - //Buffer is not going to fit, period. - return pdFALSE; + BaseType_t xFreeSize = pxRingbuffer->pucFree - pxRingbuffer->pucWrite; + //Check if xFreeSize has underflowed + if (xFreeSize <= 0) { + xFreeSize += pxRingbuffer->xSize; } + xReturn = xFreeSize; } - - //If we are here, the buffer is guaranteed to fit in the space starting at the write pointer. - buf_entry_hdr_t *hdr=(buf_entry_hdr_t *)rb->write_ptr; - hdr->len=buffer_size; - hdr->flags=0; - rb->write_ptr+=sizeof(buf_entry_hdr_t); - memcpy(rb->write_ptr, buffer, buffer_size); - rb->write_ptr+=rbuffer_size; - - //The buffer will wrap around if we don't have room for a header anymore. - if ((rb->data+rb->size)-rb->write_ptr < sizeof(buf_entry_hdr_t)) { - //'Forward' the write buffer until we are at the start of the ringbuffer. - //The read pointer will always be at the start of a full header, which cannot - //exist at the point of the current write pointer, so there's no chance of overtaking - //that. - rb->write_ptr=rb->data; - } - return pdTRUE; + configASSERT(xReturn <= pxRingbuffer->xSize); + return xReturn; } -//Copies a single item to the ring buffer; allows split items. Assumes there is space in the ringbuffer and -//the ringbuffer is locked. Increases write_ptr to the next item. Returns pdTRUE on -//success, pdFALSE if it can't make the item fit and the calling routine needs to retry -//later or fail. -//This function by itself is not threadsafe, always call from within a muxed section. -static BaseType_t copyItemToRingbufAllowSplit(ringbuf_t *rb, uint8_t *buffer, size_t buffer_size) +static BaseType_t prvCheckItemFitsDefault( Ringbuffer_t *pxRingbuffer, size_t xItemSize) { - size_t rbuffer_size; - rbuffer_size=(buffer_size+3)&~3; //Payload length, rounded to next 32-bit value - configASSERT(((int)rb->write_ptr&3)==0); //write_ptr needs to be 32-bit aligned - configASSERT(rb->write_ptr-(rb->data+rb->size) >= sizeof(buf_entry_hdr_t)); //need to have at least the size - //of a header to the end of the ringbuff - size_t rem_len=(rb->data + rb->size) - rb->write_ptr; //length remaining until end of ringbuffer + //Check arguments and buffer state + configASSERT(rbCHECK_ALIGNED(pxRingbuffer->pucWrite)); //pucWrite is always aligned in no-split ring buffers + configASSERT(pxRingbuffer->pucWrite >= pxRingbuffer->pucHead && pxRingbuffer->pucWrite < pxRingbuffer->pucTail); //Check write pointer is within bounds - //See if we have enough contiguous space to write the buffer. - if (rem_len < rbuffer_size + sizeof(buf_entry_hdr_t)) { - //The buffer can't be contiguously written to the ringbuffer, but needs special handling. Do - //that depending on how the ringbuffer is configured. - //The code here is also expected to check if the buffer, mangled in whatever way is implemented, - //will still fit, and return pdFALSE if that is not the case. - //Buffer plus header is not going to fit in the room from wr_pos to the end of the - //ringbuffer... we need to split the write in two. - //First, see if this will fit at all. - if (ringbufferFreeMem(rb) < (sizeof(buf_entry_hdr_t)*2)+rbuffer_size) { - //Will not fit. - return pdFALSE; + size_t xTotalItemSize = rbALIGN_SIZE(xItemSize) + rbHEADER_SIZE; //Rounded up aligned item size with header + if (pxRingbuffer->pucWrite == pxRingbuffer->pucFree) { + //Buffer is either complete empty or completely full + return (pxRingbuffer->uxRingbufferFlags & rbBUFFER_FULL_FLAG) ? pdFALSE : pdTRUE; + } + if (pxRingbuffer->pucFree > pxRingbuffer->pucWrite) { + //Free space does not wrap around + return (xTotalItemSize <= pxRingbuffer->pucFree - pxRingbuffer->pucWrite) ? pdTRUE : pdFALSE; + } + //Free space wraps around + if (xTotalItemSize <= pxRingbuffer->pucTail - pxRingbuffer->pucWrite) { + return pdTRUE; //Item fits without wrapping around + } + //Check if item fits by wrapping + if (pxRingbuffer->uxRingbufferFlags & rbALLOW_SPLIT_FLAG) { + //Allow split wrapping incurs an extra header + return (xTotalItemSize + rbHEADER_SIZE <= pxRingbuffer->xSize - (pxRingbuffer->pucWrite - pxRingbuffer->pucFree)) ? pdTRUE : pdFALSE; + } else { + return (xTotalItemSize <= pxRingbuffer->pucFree - pxRingbuffer->pucHead) ? pdTRUE : pdFALSE; + } +} + +static BaseType_t prvCheckItemFitsByteBuffer( Ringbuffer_t *pxRingbuffer, size_t xItemSize) +{ + //Check arguments and buffer state + configASSERT(pxRingbuffer->pucWrite >= pxRingbuffer->pucHead && pxRingbuffer->pucWrite < pxRingbuffer->pucTail); //Check write pointer is within bounds + + if (pxRingbuffer->pucWrite == pxRingbuffer->pucFree) { + //Buffer is either complete empty or completely full + return (pxRingbuffer->uxRingbufferFlags & rbBUFFER_FULL_FLAG) ? pdFALSE : pdTRUE; + } + if (pxRingbuffer->pucFree > pxRingbuffer->pucWrite) { + //Free space does not wrap around + return (xItemSize <= pxRingbuffer->pucFree - pxRingbuffer->pucWrite) ? pdTRUE : pdFALSE; + } + //Free space wraps around + return (xItemSize <= pxRingbuffer->xSize - (pxRingbuffer->pucWrite - pxRingbuffer->pucFree)) ? pdTRUE : pdFALSE; +} + +static void prvCopyItemNoSplit(Ringbuffer_t *pxRingbuffer, const uint8_t *pucItem, size_t xItemSize) +{ + //Check arguments and buffer state + size_t xAlignedItemSize = rbALIGN_SIZE(xItemSize); //Rounded up aligned item size + size_t xRemLen = pxRingbuffer->pucTail - pxRingbuffer->pucWrite; //Length from pucWrite until end of buffer + configASSERT(rbCHECK_ALIGNED(pxRingbuffer->pucWrite)); //pucWrite is always aligned in no-split ring buffers + configASSERT(pxRingbuffer->pucWrite >= pxRingbuffer->pucHead && pxRingbuffer->pucWrite < pxRingbuffer->pucTail); //Check write pointer is within bounds + configASSERT(xRemLen >= rbHEADER_SIZE); //Remaining length must be able to at least fit an item header + + //If remaining length can't fit item, set as dummy data and wrap around + if (xRemLen < xAlignedItemSize + rbHEADER_SIZE) { + ItemHeader_t *pxDummy = (ItemHeader_t *)pxRingbuffer->pucWrite; + pxDummy->uxItemFlags = rbITEM_DUMMY_DATA_FLAG; //Set remaining length as dummy data + pxDummy->xItemLen = 0; //Dummy data should have no length + pxRingbuffer->pucWrite = pxRingbuffer->pucHead; //Reset write pointer to wrap around + } + + //Item should be guaranteed to fit at this point. Set item header and copy data + ItemHeader_t *pxHeader = (ItemHeader_t *)pxRingbuffer->pucWrite; + pxHeader->xItemLen = xItemSize; + pxHeader->uxItemFlags = 0; + pxRingbuffer->pucWrite += rbHEADER_SIZE; //Advance pucWrite past header + memcpy(pxRingbuffer->pucWrite, pucItem, xItemSize); + pxRingbuffer->xItemsWaiting++; + pxRingbuffer->pucWrite += xAlignedItemSize; //Advance pucWrite past item to next aligned address + + //If current remaining length can't fit a header, wrap around write pointer + if (pxRingbuffer->pucTail - pxRingbuffer->pucWrite < rbHEADER_SIZE) { + pxRingbuffer->pucWrite = pxRingbuffer->pucHead; //Wrap around pucWrite + } + //Check if buffer is full + if (pxRingbuffer->pucWrite == pxRingbuffer->pucFree) { + //Mark the buffer as full to distinguish with an empty buffer + pxRingbuffer->uxRingbufferFlags |= rbBUFFER_FULL_FLAG; + } +} + +static void prvCopyItemAllowSplit(Ringbuffer_t *pxRingbuffer, const uint8_t *pucItem, size_t xItemSize) +{ + //Check arguments and buffer state + size_t xAlignedItemSize = rbALIGN_SIZE(xItemSize); //Rounded up aligned item size + size_t xRemLen = pxRingbuffer->pucTail - pxRingbuffer->pucWrite; //Length from pucWrite until end of buffer + configASSERT(rbCHECK_ALIGNED(pxRingbuffer->pucWrite)); //pucWrite is always aligned in split ring buffers + configASSERT(pxRingbuffer->pucWrite >= pxRingbuffer->pucHead && pxRingbuffer->pucWrite < pxRingbuffer->pucTail); //Check write pointer is within bounds + configASSERT(xRemLen >= rbHEADER_SIZE); //Remaining length must be able to at least fit an item header + + //Split item if necessary + if (xRemLen < xAlignedItemSize + rbHEADER_SIZE) { + //Write first part of the item + ItemHeader_t *pxFirstHeader = (ItemHeader_t *)pxRingbuffer->pucWrite; + pxFirstHeader->uxItemFlags = 0; + pxFirstHeader->xItemLen = xRemLen - rbHEADER_SIZE; //Fill remaining length with first part + pxRingbuffer->pucWrite += rbHEADER_SIZE; //Advance pucWrite past header + xRemLen -= rbHEADER_SIZE; + if (xRemLen > 0) { + memcpy(pxRingbuffer->pucWrite, pucItem, xRemLen); + pxRingbuffer->xItemsWaiting++; + //Update item arguments to account for data already copied + pucItem += xRemLen; + xItemSize -= xRemLen; + xAlignedItemSize -= xRemLen; + pxFirstHeader->uxItemFlags |= rbITEM_SPLIT_FLAG; //There must be more data + } else { + //Remaining length was only large enough to fit header + pxFirstHeader->uxItemFlags |= rbITEM_DUMMY_DATA_FLAG; //Item will completely be stored in 2nd part } - //Because the code at the end of the function makes sure we always have - //room for a header, this should never assert. - configASSERT(rem_len>=sizeof(buf_entry_hdr_t)); - //Okay, it should fit. Write everything. - //First, place bit of buffer that does fit. Write header first... - buf_entry_hdr_t *hdr=(buf_entry_hdr_t *)rb->write_ptr; - hdr->flags=0; - hdr->len=rem_len-sizeof(buf_entry_hdr_t); - rb->write_ptr+=sizeof(buf_entry_hdr_t); - rem_len-=sizeof(buf_entry_hdr_t); - if (rem_len!=0) { - //..then write the data bit that fits. - memcpy(rb->write_ptr, buffer, rem_len); - //Update vars so the code later on will write the rest of the data. - buffer+=rem_len; - buffer_size-=rem_len; - //Re-adjust the rbuffer value to be 4 byte aligned - rbuffer_size=(buffer_size+3)&~3; - //It is possible that we are here because we checked for 4byte aligned - //size, but actual data was smaller. - //Eg. For buffer_size = 34, rbuffer_size will be 36. Suppose we had only - //42 bytes of memory available, the top level check will fail, as it will - //check for availability of 36 + 8 = 44 bytes. - //However, the 42 bytes available memory is sufficient for 34 + 8 bytes data - //and so, we can return after writing the data. Hence, this check - if (buffer_size == 0) { - rb->write_ptr=rb->data; - return pdTRUE; + pxRingbuffer->pucWrite = pxRingbuffer->pucHead; //Reset write pointer to start of buffer + } + + //Item (whole or second part) should be guaranteed to fit at this point + ItemHeader_t *pxSecondHeader = (ItemHeader_t *)pxRingbuffer->pucWrite; + pxSecondHeader->xItemLen = xItemSize; + pxSecondHeader->uxItemFlags = 0; + pxRingbuffer->pucWrite += rbHEADER_SIZE; //Advance write pointer past header + memcpy(pxRingbuffer->pucWrite, pucItem, xItemSize); + pxRingbuffer->xItemsWaiting++; + pxRingbuffer->pucWrite += xAlignedItemSize; //Advance pucWrite past item to next aligned address + + //If current remaining length can't fit a header, wrap around write pointer + if (pxRingbuffer->pucTail - pxRingbuffer->pucWrite < rbHEADER_SIZE) { + pxRingbuffer->pucWrite = pxRingbuffer->pucHead; //Wrap around pucWrite + } + //Check if buffer is full + if (pxRingbuffer->pucWrite == pxRingbuffer->pucFree) { + //Mark the buffer as full to distinguish with an empty buffer + pxRingbuffer->uxRingbufferFlags |= rbBUFFER_FULL_FLAG; + } +} + +static void prvCopyItemByteBuf(Ringbuffer_t *pxRingbuffer, const uint8_t *pucItem, size_t xItemSize) +{ + //Check arguments and buffer state + configASSERT(pxRingbuffer->pucWrite >= pxRingbuffer->pucHead && pxRingbuffer->pucWrite < pxRingbuffer->pucTail); //Check write pointer is within bounds + + size_t xRemLen = pxRingbuffer->pucTail - pxRingbuffer->pucWrite; //Length from pucWrite until end of buffer + if (xRemLen < xItemSize) { + //Copy as much as possible into remaining length + memcpy(pxRingbuffer->pucWrite, pucItem, xRemLen); + pxRingbuffer->xItemsWaiting += xRemLen; + //Update item arguments to account for data already written + pucItem += xRemLen; + xItemSize -= xRemLen; + pxRingbuffer->pucWrite = pxRingbuffer->pucHead; //Reset write pointer to start of buffer + } + //Copy all or remaining portion of the item + memcpy(pxRingbuffer->pucWrite, pucItem, xItemSize); + pxRingbuffer->xItemsWaiting += xItemSize; + pxRingbuffer->pucWrite += xItemSize; + + //Wrap around pucWrite if it reaches the end + if (pxRingbuffer->pucWrite == pxRingbuffer->pucTail) { + pxRingbuffer->pucWrite = pxRingbuffer->pucHead; + } + //Check if buffer is full + if (pxRingbuffer->pucWrite == pxRingbuffer->pucFree) { + pxRingbuffer->uxRingbufferFlags |= rbBUFFER_FULL_FLAG; //Mark the buffer as full to avoid confusion with an empty buffer + } +} + +static BaseType_t prvCheckItemAvail(Ringbuffer_t *pxRingbuffer) +{ + if ((pxRingbuffer->uxRingbufferFlags & rbBYTE_BUFFER_FLAG) && pxRingbuffer->pucRead != pxRingbuffer->pucFree) { + return pdFALSE; //Byte buffers do not allow multiple retrievals before return + } + if ((pxRingbuffer->xItemsWaiting > 0) && ((pxRingbuffer->pucRead != pxRingbuffer->pucWrite) || (pxRingbuffer->uxRingbufferFlags & rbBUFFER_FULL_FLAG))) { + return pdTRUE; //Items/data available for retrieval + } else { + return pdFALSE; //No items/data available for retrieval + } +} + +static void *prvGetItemDefault(Ringbuffer_t *pxRingbuffer, BaseType_t *pxIsSplit, size_t xUnusedParam, size_t *pxItemSize) +{ + //Check arguments and buffer state + ItemHeader_t *pxHeader = (ItemHeader_t *)pxRingbuffer->pucRead; + configASSERT(pxIsSplit != NULL); + configASSERT((pxRingbuffer->xItemsWaiting > 0) && ((pxRingbuffer->pucRead != pxRingbuffer->pucWrite) || (pxRingbuffer->uxRingbufferFlags & rbBUFFER_FULL_FLAG))); //Check there are items to be read + configASSERT(rbCHECK_ALIGNED(pxRingbuffer->pucRead)); //pucRead is always aligned in split ring buffers + configASSERT(pxRingbuffer->pucRead >= pxRingbuffer->pucHead && pxRingbuffer->pucRead < pxRingbuffer->pucTail); //Check read pointer is within bounds + configASSERT((pxHeader->xItemLen <= pxRingbuffer->xMaxItemSize) || (pxHeader->uxItemFlags & rbITEM_DUMMY_DATA_FLAG)); + + uint8_t *pcReturn; + //Wrap around if dummy data (dummy data indicates wrap around in no-split buffers) + if (pxHeader->uxItemFlags & rbITEM_DUMMY_DATA_FLAG) { + pxRingbuffer->pucRead = pxRingbuffer->pucHead; + //Check for errors with the next item + pxHeader = (ItemHeader_t *)pxRingbuffer->pucRead; + configASSERT(pxHeader->xItemLen <= pxRingbuffer->xMaxItemSize); + } + pcReturn = pxRingbuffer->pucRead + rbHEADER_SIZE; //Get pointer to part of item containing data (point past the header) + if (pxHeader->xItemLen == 0) { + //Inclusive of pucTail for special case where item of zero length just fits at the end of the buffer + configASSERT(pcReturn >= pxRingbuffer->pucHead && pcReturn <= pxRingbuffer->pucTail); + } else { + //Exclusive of pucTali if length is larger than zero, pcReturn should never point to pucTail + configASSERT(pcReturn >= pxRingbuffer->pucHead && pcReturn < pxRingbuffer->pucTail); + } + *pxItemSize = pxHeader->xItemLen; //Get length of item + pxRingbuffer->xItemsWaiting --; //Update item count + *pxIsSplit = (pxHeader->uxItemFlags & rbITEM_SPLIT_FLAG) ? pdTRUE : pdFALSE; + + pxRingbuffer->pucRead += rbHEADER_SIZE + rbALIGN_SIZE(pxHeader->xItemLen); //Update pucRead + //Check if pucRead requires wrap around + if ((pxRingbuffer->pucTail - pxRingbuffer->pucRead) < rbHEADER_SIZE) { + pxRingbuffer->pucRead = pxRingbuffer->pucHead; + } + return (void *)pcReturn; +} + +static void *prvGetItemByteBuf(Ringbuffer_t *pxRingbuffer, BaseType_t *pxUnusedParam ,size_t xMaxSize, size_t *pxItemSize) +{ + //Check arguments and buffer state + configASSERT((pxRingbuffer->xItemsWaiting > 0) && ((pxRingbuffer->pucRead != pxRingbuffer->pucWrite) || (pxRingbuffer->uxRingbufferFlags & rbBUFFER_FULL_FLAG))); //Check there are items to be read + configASSERT(pxRingbuffer->pucRead >= pxRingbuffer->pucHead && pxRingbuffer->pucRead < pxRingbuffer->pucTail); //Check read pointer is within bounds + configASSERT(pxRingbuffer->pucRead == pxRingbuffer->pucFree); + + uint8_t *ret = pxRingbuffer->pucRead; + if ((pxRingbuffer->pucRead > pxRingbuffer->pucWrite) || (pxRingbuffer->uxRingbufferFlags & rbBUFFER_FULL_FLAG)) { //Available data wraps around + //Return contiguous piece from read pointer until buffer tail, or xMaxSize + if (xMaxSize == 0 || pxRingbuffer->pucTail - pxRingbuffer->pucRead <= xMaxSize) { + //All contiguous data from read pointer to tail + *pxItemSize = pxRingbuffer->pucTail - pxRingbuffer->pucRead; + pxRingbuffer->xItemsWaiting -= pxRingbuffer->pucTail - pxRingbuffer->pucRead; + pxRingbuffer->pucRead = pxRingbuffer->pucHead; //Wrap around read pointer + } else { + //Return xMaxSize amount of data + *pxItemSize = xMaxSize; + pxRingbuffer->xItemsWaiting -= xMaxSize; + pxRingbuffer->pucRead += xMaxSize; //Advance read pointer past retrieved data + } + } else { //Available data is contiguous between read and write pointer + if (xMaxSize == 0 || pxRingbuffer->pucWrite - pxRingbuffer->pucRead <= xMaxSize) { + //Return all contiguous data from read to write pointer + *pxItemSize = pxRingbuffer->pucWrite - pxRingbuffer->pucRead; + pxRingbuffer->xItemsWaiting -= pxRingbuffer->pucWrite - pxRingbuffer->pucRead; + pxRingbuffer->pucRead = pxRingbuffer->pucWrite; + } else { + //Return xMaxSize data from read pointer + *pxItemSize = xMaxSize; + pxRingbuffer->xItemsWaiting -= xMaxSize; + pxRingbuffer->pucRead += xMaxSize; //Advance read pointer past retrieved data + + } + } + return (void *)ret; +} + +static void prvReturnItemDefault(Ringbuffer_t *pxRingbuffer, uint8_t *pucItem) +{ + //Check arguments and buffer state + configASSERT(rbCHECK_ALIGNED(pucItem)); + configASSERT(pucItem >= pxRingbuffer->pucHead); + configASSERT(pucItem <= pxRingbuffer->pucTail); //Inclusive of pucTail in the case of zero length item at the very end + + //Get and check header of the item + ItemHeader_t *pxCurHeader = (ItemHeader_t *)(pucItem - rbHEADER_SIZE); + configASSERT(pxCurHeader->xItemLen <= pxRingbuffer->xMaxItemSize); + configASSERT((pxCurHeader->uxItemFlags & rbITEM_DUMMY_DATA_FLAG) == 0); //Dummy items should never have been read + configASSERT((pxCurHeader->uxItemFlags & rbITEM_FREE_FLAG) == 0); //Indicates item has already been returned before + pxCurHeader->uxItemFlags &= ~rbITEM_SPLIT_FLAG; //Clear wrap flag if set (not strictly necessary) + pxCurHeader->uxItemFlags |= rbITEM_FREE_FLAG; //Mark as free + + /* + * Items might not be returned in the order they were retrieved. Move the free pointer + * up to the next item that has not been marked as free (by free flag) or up + * till the read pointer. When advancing the free pointer, items that have already been + * freed or items with dummy data should be skipped over + */ + pxCurHeader = (ItemHeader_t *)pxRingbuffer->pucFree; + //Skip over Items that have already been freed or are dummy items + while (((pxCurHeader->uxItemFlags & rbITEM_FREE_FLAG) || (pxCurHeader->uxItemFlags & rbITEM_DUMMY_DATA_FLAG)) && pxRingbuffer->pucFree != pxRingbuffer->pucRead) { + if (pxCurHeader->uxItemFlags & rbITEM_DUMMY_DATA_FLAG) { + pxCurHeader->uxItemFlags |= rbITEM_FREE_FLAG; //Mark as freed (not strictly necessary but adds redundancy) + pxRingbuffer->pucFree = pxRingbuffer->pucHead; //Wrap around due to dummy data + } else { + //Item with data that has already been freed, advance free pointer past this item + size_t xAlignedItemSize = rbALIGN_SIZE(pxCurHeader->xItemLen); + pxRingbuffer->pucFree += xAlignedItemSize + rbHEADER_SIZE; + //Redundancy check to ensure free pointer has not overshot buffer bounds + configASSERT(pxRingbuffer->pucFree <= pxRingbuffer->pucHead + pxRingbuffer->xSize); + } + //Check if pucRead requires wrap around + if ((pxRingbuffer->pucTail - pxRingbuffer->pucFree) < rbHEADER_SIZE) { + pxRingbuffer->pucFree = pxRingbuffer->pucHead; + } + pxCurHeader = (ItemHeader_t *)pxRingbuffer->pucFree; //Update header to point to item + } + + //Check if the buffer full flag should be reset + if (pxRingbuffer->uxRingbufferFlags & rbBUFFER_FULL_FLAG) { + if (pxRingbuffer->pucFree != pxRingbuffer->pucWrite) { + pxRingbuffer->uxRingbufferFlags &= ~rbBUFFER_FULL_FLAG; + } else if (pxRingbuffer->pucFree == pxRingbuffer->pucWrite && pxRingbuffer->pucFree == pxRingbuffer->pucRead) { + //Special case where a full buffer is completely freed in one go + pxRingbuffer->uxRingbufferFlags &= ~rbBUFFER_FULL_FLAG; + } + } +} + +static void prvReturnItemByteBuf(Ringbuffer_t *pxRingbuffer, uint8_t *pucItem) +{ + //Check pointer points to address inside buffer + configASSERT((uint8_t *)pucItem >= pxRingbuffer->pucHead); + configASSERT((uint8_t *)pucItem < pxRingbuffer->pucTail); + //Free the read memory. Simply moves free pointer to read pointer as byte buffers do not allow multiple outstanding reads + pxRingbuffer->pucFree = pxRingbuffer->pucRead; + //If buffer was full before, reset full flag as free pointer has moved + if (pxRingbuffer->uxRingbufferFlags & rbBUFFER_FULL_FLAG) { + pxRingbuffer->uxRingbufferFlags &= ~rbBUFFER_FULL_FLAG; + } +} + +static size_t prvGetCurMaxSizeNoSplit(Ringbuffer_t *pxRingbuffer) +{ + BaseType_t xFreeSize; + //Check if buffer is full + if (pxRingbuffer->uxRingbufferFlags & rbBUFFER_FULL_FLAG) { + return 0; + } + if (pxRingbuffer->pucWrite < pxRingbuffer->pucFree) { + //Free space is contiguous between pucWrite and pucFree + xFreeSize = pxRingbuffer->pucFree - pxRingbuffer->pucWrite; + } else { + //Free space wraps around (or overlapped at pucHead), select largest + //contiguous free space as no-split items require contiguous space + size_t xSize1 = pxRingbuffer->pucTail - pxRingbuffer->pucWrite; + size_t xSize2 = pxRingbuffer->pucFree - pxRingbuffer->pucHead; + xFreeSize = (xSize1 > xSize2) ? xSize1 : xSize2; + } + + //No-split ring buffer items need space for a header + xFreeSize -= rbHEADER_SIZE; + //Limit free size to be within bounds + if (xFreeSize > pxRingbuffer->xMaxItemSize) { + xFreeSize = pxRingbuffer->xMaxItemSize; + } else if (xFreeSize < 0) { + //Occurs when free space is less than header size + xFreeSize = 0; + } + return xFreeSize; +} + +static size_t prvGetCurMaxSizeAllowSplit(Ringbuffer_t *pxRingbuffer) +{ + BaseType_t xFreeSize; + //Check if buffer is full + if (pxRingbuffer->uxRingbufferFlags & rbBUFFER_FULL_FLAG) { + return 0; + } + if (pxRingbuffer->pucWrite == pxRingbuffer->pucHead && pxRingbuffer->pucFree == pxRingbuffer->pucHead) { + //Check for special case where pucWrite and pucFree are both at pucHead + xFreeSize = pxRingbuffer->xSize - rbHEADER_SIZE; + } else if (pxRingbuffer->pucWrite < pxRingbuffer->pucFree) { + //Free space is contiguous between pucWrite and pucFree, requires single header + xFreeSize = (pxRingbuffer->pucFree - pxRingbuffer->pucWrite) - rbHEADER_SIZE; + } else { + //Free space wraps around, requires two headers + xFreeSize = (pxRingbuffer->pucFree - pxRingbuffer->pucHead) + + (pxRingbuffer->pucTail - pxRingbuffer->pucWrite) - + (rbHEADER_SIZE * 2); + } + + //Limit free size to be within bounds + if (xFreeSize > pxRingbuffer->xMaxItemSize) { + xFreeSize = pxRingbuffer->xMaxItemSize; + } else if (xFreeSize < 0) { + xFreeSize = 0; + } + return xFreeSize; +} + +static size_t prvGetCurMaxSizeByteBuf(Ringbuffer_t *pxRingbuffer) +{ + BaseType_t xFreeSize; + //Check if buffer is full + if (pxRingbuffer->uxRingbufferFlags & rbBUFFER_FULL_FLAG) { + return 0; + } + + /* + * Return whatever space is available depending on relative positions of the free + * pointer and write pointer. There is no overhead of headers in this mode + */ + xFreeSize = pxRingbuffer->pucFree - pxRingbuffer->pucWrite; + if (xFreeSize <= 0) { + xFreeSize += pxRingbuffer->xSize; + } + return xFreeSize; +} + +static BaseType_t prvReceiveGeneric(Ringbuffer_t *pxRingbuffer, void **pvItem1, void **pvItem2, size_t *xItemSize1, size_t *xItemSize2, size_t xMaxSize, TickType_t xTicksToWait) +{ + BaseType_t xReturn = pdFALSE; + BaseType_t xReturnSemaphore = pdFALSE; + TickType_t xTicksEnd = xTaskGetTickCount() + xTicksToWait; + TickType_t xTicksRemaining = xTicksToWait; + while (xTicksRemaining <= xTicksToWait) { //xTicksToWait will underflow once xTaskGetTickCount() > ticks_end + //Block until more free space becomes available or timeout + if (xSemaphoreTake(pxRingbuffer->xItemsBufferedSemaphore, xTicksRemaining) != pdTRUE) { + xReturn = pdFALSE; //Timed out attempting to get semaphore + break; + } + + //Semaphore obtained, check if item can be retrieved + taskENTER_CRITICAL(&pxRingbuffer->mux); + if (prvCheckItemAvail(pxRingbuffer) == pdTRUE) { + //Item is available for retrieval + BaseType_t xIsSplit; + if (pxRingbuffer->uxRingbufferFlags & rbBYTE_BUFFER_FLAG) { + //Second argument (pxIsSplit) is unused for byte buffers + *pvItem1 = pxRingbuffer->pvGetItem(pxRingbuffer, NULL, xMaxSize, xItemSize1); } else { - /* Indicate the wrapping */ - hdr->flags|=iflag_wrap; + //Third argument (xMaxSize) is unused for no-split/allow-split buffers + *pvItem1 = pxRingbuffer->pvGetItem(pxRingbuffer, &xIsSplit, 0, xItemSize1); } + //Check for item split if configured to do so + if ((pxRingbuffer->uxRingbufferFlags & rbALLOW_SPLIT_FLAG) && (pvItem2 != NULL) && (xItemSize2 != NULL)) { + if (xIsSplit == pdTRUE) { + *pvItem2 = pxRingbuffer->pvGetItem(pxRingbuffer, &xIsSplit, 0, xItemSize2); + configASSERT(*pvItem2 < *pvItem1); //Check wrap around has occurred + configASSERT(xIsSplit == pdFALSE); //Second part should not have wrapped flag + } else { + *pvItem2 = NULL; + } + } + xReturn = pdTRUE; + if (pxRingbuffer->xItemsWaiting > 0) { + xReturnSemaphore = pdTRUE; + } + taskEXIT_CRITICAL(&pxRingbuffer->mux); + break; + } + //No item available for retrieval, adjust ticks and take the semaphore again + if (xTicksToWait != portMAX_DELAY) { + xTicksRemaining = xTicksEnd - xTaskGetTickCount(); + } + taskEXIT_CRITICAL(&pxRingbuffer->mux); + /* + * Gap between critical section and re-acquiring of the semaphore. If + * semaphore is given now, priority inversion might occur (see docs) + */ + } + + if (xReturnSemaphore == pdTRUE) { + xSemaphoreGive(pxRingbuffer->xItemsBufferedSemaphore); //Give semaphore back so other tasks can retrieve + } + return xReturn; +} + +static BaseType_t prvReceiveGenericFromISR(Ringbuffer_t *pxRingbuffer, void **pvItem1, void **pvItem2, size_t *xItemSize1, size_t *xItemSize2, size_t xMaxSize) +{ + BaseType_t xReturn = pdFALSE; + BaseType_t xReturnSemaphore = pdFALSE; + + taskENTER_CRITICAL_ISR(&pxRingbuffer->mux); + if(prvCheckItemAvail(pxRingbuffer) == pdTRUE) { + BaseType_t xIsSplit; + if (pxRingbuffer->uxRingbufferFlags & rbBYTE_BUFFER_FLAG) { + //Second argument (pxIsSplit) is unused for byte buffers + *pvItem1 = pxRingbuffer->pvGetItem(pxRingbuffer, NULL, xMaxSize, xItemSize1); } else { - //Huh, only the header fit. Mark as dummy so the receive function doesn't receive - //an useless zero-byte packet. - hdr->flags|=iflag_dummydata; + //Third argument (xMaxSize) is unused for no-split/allow-split buffers + *pvItem1 = pxRingbuffer->pvGetItem(pxRingbuffer, &xIsSplit, 0, xItemSize1); } - rb->write_ptr=rb->data; - } else { - //No special handling needed. Checking if it's gonna fit probably still is a good idea. - if (ringbufferFreeMem(rb) < sizeof(buf_entry_hdr_t)+rbuffer_size) { - //Buffer is not going to fit, period. - return pdFALSE; - } - } - - //If we are here, the buffer is guaranteed to fit in the space starting at the write pointer. - buf_entry_hdr_t *hdr=(buf_entry_hdr_t *)rb->write_ptr; - hdr->len=buffer_size; - hdr->flags=0; - rb->write_ptr+=sizeof(buf_entry_hdr_t); - memcpy(rb->write_ptr, buffer, buffer_size); - rb->write_ptr+=rbuffer_size; - - //The buffer will wrap around if we don't have room for a header anymore. - if ((rb->data+rb->size)-rb->write_ptr < sizeof(buf_entry_hdr_t)) { - //'Forward' the write buffer until we are at the start of the ringbuffer. - //The read pointer will always be at the start of a full header, which cannot - //exist at the point of the current write pointer, so there's no chance of overtaking - //that. - rb->write_ptr=rb->data; - } - return pdTRUE; -} - - -//Copies a bunch of daya to the ring bytebuffer. Assumes there is space in the ringbuffer and -//the ringbuffer is locked. Increases write_ptr to the next item. Returns pdTRUE on -//success, pdFALSE if it can't make the item fit and the calling routine needs to retry -//later or fail. -//This function by itself is not threadsafe, always call from within a muxed section. -static BaseType_t copyItemToRingbufByteBuf(ringbuf_t *rb, uint8_t *buffer, size_t buffer_size) -{ - size_t rem_len=(rb->data + rb->size) - rb->write_ptr; //length remaining until end of ringbuffer - - //See if we have enough contiguous space to write the buffer. - if (rem_len < buffer_size) { - //...Nope. Write the data bit that fits. - memcpy(rb->write_ptr, buffer, rem_len); - //Update vars so the code later on will write the rest of the data. - buffer+=rem_len; - buffer_size-=rem_len; - rb->write_ptr=rb->data; - } - - //If we are here, the buffer is guaranteed to fit in the space starting at the write pointer. - memcpy(rb->write_ptr, buffer, buffer_size); - rb->write_ptr+=buffer_size; - //The buffer will wrap around if we're at the end. - if ((rb->data+rb->size)==rb->write_ptr) { - rb->write_ptr=rb->data; - } - return pdTRUE; -} - -//Retrieves a pointer to the data of the next item, or NULL if this is not possible. -//This function by itself is not threadsafe, always call from within a muxed section. -//Because we always return one item, this function ignores the wanted_length variable. -static uint8_t *getItemFromRingbufDefault(ringbuf_t *rb, size_t *length, int wanted_length) -{ - uint8_t *ret; - configASSERT(((int)rb->read_ptr&3)==0); - if (rb->read_ptr == rb->write_ptr) { - //No data available. - return NULL; - } - //The item written at the point of the read pointer may be a dummy item. - //We need to skip past it first, if that's the case. - buf_entry_hdr_t *hdr=(buf_entry_hdr_t *)rb->read_ptr; - configASSERT((hdr->len < rb->size) || (hdr->flags & iflag_dummydata)); - if (hdr->flags & iflag_dummydata) { - //Hdr is dummy data. Reset to start of ringbuffer. - rb->read_ptr=rb->data; - //Get real header - hdr=(buf_entry_hdr_t *)rb->read_ptr; - configASSERT(hdr->len < rb->size); - //No need to re-check if the ringbuffer is empty: the write routine will - //always write a dummy item plus the real data item in one go, so now we must - //be at the real data item by definition. - } - //Okay, pass the data back. - ret=rb->read_ptr+sizeof(buf_entry_hdr_t); - *length=hdr->len; - //...and move the read pointer past the data. - rb->read_ptr+=sizeof(buf_entry_hdr_t)+((hdr->len+3)&~3); - //The buffer will wrap around if we don't have room for a header anymore. - //Integer typecasting is used because the first operand can result into a -ve - //value for cases wherein the ringbuffer size is not a multiple of 4, but the - //implementation logic aligns read_ptr to 4-byte boundary - if ((int)((rb->data + rb->size) - rb->read_ptr) < (int)sizeof(buf_entry_hdr_t)) { - rb->read_ptr=rb->data; - } - return ret; -} - -//Retrieves a pointer to the data in the buffer, or NULL if this is not possible. -//This function by itself is not threadsafe, always call from within a muxed section. -//This function honours the wanted_length and will never return more data than this. -static uint8_t *getItemFromRingbufByteBuf(ringbuf_t *rb, size_t *length, int wanted_length) -{ - uint8_t *ret; - if (rb->read_ptr != rb->free_ptr) { - //This type of ringbuff does not support multiple outstanding buffers. - return NULL; - } - if (rb->read_ptr == rb->write_ptr) { - //No data available. - return NULL; - } - ret=rb->read_ptr; - if (rb->read_ptr > rb->write_ptr) { - //Available data wraps around. Give data until the end of the buffer. - *length=rb->size-(rb->read_ptr - rb->data); - if (wanted_length != 0 && *length > wanted_length) { - *length=wanted_length; - rb->read_ptr+=wanted_length; - } else { - rb->read_ptr=rb->data; - } - } else { - //Return data up to write pointer. - *length=rb->write_ptr -rb->read_ptr; - if (wanted_length != 0 && *length > wanted_length) { - *length=wanted_length; - rb->read_ptr+=wanted_length; - } else { - rb->read_ptr=rb->write_ptr; - } - } - return ret; -} - - -//Returns an item to the ringbuffer. Will mark the item as free, and will see if the free pointer -//can be increase. -//This function by itself is not threadsafe, always call from within a muxed section. -static void returnItemToRingbufDefault(ringbuf_t *rb, void *item) { - uint8_t *data=(uint8_t*)item; - configASSERT(((int)rb->free_ptr&3)==0); - configASSERT(data >= rb->data); - configASSERT(data <= rb->data+rb->size); - //Grab the buffer entry that preceeds the buffer - buf_entry_hdr_t *hdr=(buf_entry_hdr_t*)(data-sizeof(buf_entry_hdr_t)); - configASSERT(hdr->len < rb->size); - configASSERT((hdr->flags & iflag_dummydata)==0); - configASSERT((hdr->flags & iflag_free)==0); - //Mark the buffer as free. - hdr->flags&=~iflag_wrap; - hdr->flags|=iflag_free; - - //Do a cleanup pass. - hdr=(buf_entry_hdr_t *)rb->free_ptr; - //basically forward free_ptr until we run into either a block that is still in use or the write pointer. - while (((hdr->flags & iflag_free) || (hdr->flags & iflag_dummydata)) && rb->free_ptr != rb->write_ptr) { - if (hdr->flags & iflag_dummydata) { - //Rest is dummy data. Reset to start of ringbuffer. - rb->free_ptr=rb->data; - } else { - //Skip past item - rb->free_ptr+=sizeof(buf_entry_hdr_t); - //Check if the free_ptr overshoots the buffer. - //Checking this before aligning free_ptr since it is possible that alignment - //will cause pointer to overshoot, if the ringbuf size is not a multiple of 4 - configASSERT(rb->free_ptr+hdr->len<=rb->data+rb->size); - //Align free_ptr to 4 byte boundary. Overshoot condition will result in wrap around below - size_t len=(hdr->len+3)&~3; - rb->free_ptr+=len; - } - //The buffer will wrap around if we don't have room for a header anymore. - //Integer typecasting is used because the first operand can result into a -ve - //value for cases wherein the ringbuffer size is not a multiple of 4, but the - //implementation logic aligns free_ptr to 4-byte boundary - if ((int)((rb->data+rb->size)-rb->free_ptr) < (int)sizeof(buf_entry_hdr_t)) { - rb->free_ptr=rb->data; - } - //The free_ptr can not exceed read_ptr, otherwise write_ptr might overwrite read_ptr. - //Read_ptr can not set to rb->data with free_ptr, otherwise write_ptr might wrap around to rb->data. - if(rb->free_ptr == rb->read_ptr) break; - //Next header - hdr=(buf_entry_hdr_t *)rb->free_ptr; - } -} - - -//Returns an item to the ringbuffer. Will mark the item as free, and will see if the free pointer -//can be increase. -//This function by itself is not threadsafe, always call from within a muxed section. -static void returnItemToRingbufBytebuf(ringbuf_t *rb, void *item) { - configASSERT((uint8_t *)item >= rb->data); - configASSERT((uint8_t *)item < rb->data+rb->size); - //Free the read memory. - rb->free_ptr=rb->read_ptr; -} -/* - Check if the selected queue set member is the ringbuffer's read semaphore -*/ -BaseType_t xRingbufferCanRead(RingbufHandle_t ringbuf, QueueSetMemberHandle_t member) -{ - ringbuf_t *rb=(ringbuf_t *)ringbuf; - configASSERT(rb); - return (rb->items_buffered_sem == member)? pdTRUE : pdFALSE; -} -/* - Check if the selected queue set member is the ringbuffer's write semaphore -*/ -BaseType_t xRingbufferCanWrite(RingbufHandle_t ringbuf, QueueSetMemberHandle_t member) -{ - ringbuf_t *rb=(ringbuf_t *)ringbuf; - configASSERT(rb); - return (rb->free_space_sem == member)? pdTRUE : pdFALSE; -} - -void xRingbufferPrintInfo(RingbufHandle_t ringbuf) -{ - ringbuf_t *rb=(ringbuf_t *)ringbuf; - configASSERT(rb); - ets_printf("Rb size %d free %d rptr %d freeptr %d wptr %d\n", - rb->size, ringbufferFreeMem(rb), rb->read_ptr-rb->data, rb->free_ptr-rb->data, rb->write_ptr-rb->data); -} - - -size_t xRingbufferGetCurFreeSize(RingbufHandle_t ringbuf) -{ - ringbuf_t *rb=(ringbuf_t *)ringbuf; - configASSERT(rb); - configASSERT(rb->getFreeSizeImpl); - int free_size = rb->getFreeSizeImpl(rb); - //Reserve one byte. If we do not do this and the entire buffer is filled, we get a situation - //where read_ptr == free_ptr, messing up the next calculation. - return free_size - 1; -} - -static size_t getCurFreeSizeByteBuf(ringbuf_t *rb) -{ - //Return whatever space is available depending on relative positions of - //the free pointer and write pointer. There is no overhead of headers in - //this mode - int free_size = rb->free_ptr-rb->write_ptr; - if (free_size <= 0) - free_size += rb->size; - return free_size; -} - -static size_t getCurFreeSizeAllowSplit(ringbuf_t *rb) -{ - int free_size; - //If Both, the write and free pointer are at the start. Hence, the entire buffer - //is available (minus the space for the header) - if (rb->write_ptr == rb->free_ptr && rb->write_ptr == rb->data) { - free_size = rb->size - sizeof(buf_entry_hdr_t); - } else if (rb->write_ptr < rb->free_ptr) { - //Else if the free pointer is beyond the write pointer, only the space between - //them would be available (minus the space for the header) - free_size = rb->free_ptr - rb->write_ptr - sizeof(buf_entry_hdr_t); - } else { - //Else the data can wrap around and 2 headers will be required - free_size = rb->free_ptr - rb->write_ptr + rb->size - (2 * sizeof(buf_entry_hdr_t)); - } - return free_size; -} - -static size_t getCurFreeSizeNoSplit(ringbuf_t *rb) -{ - int free_size; - //If the free pointer is beyond the write pointer, only the space between - //them would be available - if (rb->write_ptr < rb->free_ptr) { - free_size = rb->free_ptr - rb->write_ptr; - } else { - //Else check which one is bigger amongst the below 2 - //1) Space from the write pointer to the end of buffer - int size1 = rb->data + rb->size - rb->write_ptr; - //2) Space from the start of buffer to the free pointer - int size2 = rb->free_ptr - rb->data; - //And then select the larger of the two - free_size = size1 > size2 ? size1 : size2; - } - //In any case, a single header will be used, so subtracting the space that - //would be required for it - return free_size - sizeof(buf_entry_hdr_t); -} - - -RingbufHandle_t xRingbufferCreate(size_t buf_length, ringbuf_type_t type) -{ - ringbuf_t *rb = malloc(sizeof(ringbuf_t)); - if (rb==NULL) goto err; - memset(rb, 0, sizeof(ringbuf_t)); - rb->data = malloc(buf_length); - if (rb->data == NULL) goto err; - rb->size = buf_length; - rb->free_ptr = rb->data; - rb->read_ptr = rb->data; - rb->write_ptr = rb->data; - rb->free_space_sem = xSemaphoreCreateBinary(); - rb->items_buffered_sem = xSemaphoreCreateBinary(); - rb->flags=0; - if (type==RINGBUF_TYPE_ALLOWSPLIT) { - rb->flags|=flag_allowsplit; - rb->copyItemToRingbufImpl=copyItemToRingbufAllowSplit; - rb->getItemFromRingbufImpl=getItemFromRingbufDefault; - rb->returnItemToRingbufImpl=returnItemToRingbufDefault; - //Calculate max item size. Worst case, we need to split an item into two, which means two headers of overhead. - rb->maxItemSize=rb->size-(sizeof(buf_entry_hdr_t)*2)-4; - rb->getFreeSizeImpl=getCurFreeSizeAllowSplit; - } else if (type==RINGBUF_TYPE_BYTEBUF) { - rb->flags|=flag_bytebuf; - rb->copyItemToRingbufImpl=copyItemToRingbufByteBuf; - rb->getItemFromRingbufImpl=getItemFromRingbufByteBuf; - rb->returnItemToRingbufImpl=returnItemToRingbufBytebuf; - //Calculate max item size. We have no headers and can split anywhere -> size is total size minus one. - rb->maxItemSize=rb->size-1; - rb->getFreeSizeImpl=getCurFreeSizeByteBuf; - } else if (type==RINGBUF_TYPE_NOSPLIT) { - rb->copyItemToRingbufImpl=copyItemToRingbufNoSplit; - rb->getItemFromRingbufImpl=getItemFromRingbufDefault; - rb->returnItemToRingbufImpl=returnItemToRingbufDefault; - //Calculate max item size. Worst case, we have the write ptr in such a position that we are lacking four bytes of free - //memory to put an item into the rest of the memory. If this happens, we have to dummy-fill - //(item_data-4) bytes of buffer, then we only have (size-(item_data-4) bytes left to fill - //with the real item. (item size being header+data) - rb->maxItemSize=(rb->size/2)-sizeof(buf_entry_hdr_t)-4; - rb->getFreeSizeImpl=getCurFreeSizeNoSplit; + //Check for item split if configured to do so + if ((pxRingbuffer->uxRingbufferFlags & rbALLOW_SPLIT_FLAG) && pvItem2 != NULL && xItemSize2 != NULL) { + if (xIsSplit == pdTRUE) { + *pvItem2 = pxRingbuffer->pvGetItem(pxRingbuffer, &xIsSplit, 0, xItemSize2); + configASSERT(*pvItem2 < *pvItem1); //Check wrap around has occurred + configASSERT(xIsSplit == pdFALSE); //Second part should not have wrapped flag + } else { + *pvItem2 = NULL; + } + } + xReturn = pdTRUE; + if (pxRingbuffer->xItemsWaiting > 0) { + xReturnSemaphore = pdTRUE; + } + } + taskEXIT_CRITICAL_ISR(&pxRingbuffer->mux); + + if (xReturnSemaphore == pdTRUE) { + xSemaphoreGiveFromISR(pxRingbuffer->xItemsBufferedSemaphore, NULL); //Give semaphore back so other tasks can retrieve + } + return xReturn; +} + +/* ------------------------------------------------- Public Definitions -------------------------------------------- */ + +RingbufHandle_t xRingbufferCreate(size_t xBufferSize, ringbuf_type_t xBufferType) +{ + //Allocate memory + Ringbuffer_t *pxRingbuffer = calloc(1, sizeof(Ringbuffer_t)); + if (pxRingbuffer == NULL) { + goto err; + } + if (xBufferType != RINGBUF_TYPE_BYTEBUF) { + xBufferSize = rbALIGN_SIZE(xBufferSize); //xBufferSize is rounded up for no-split/allow-split buffers + } + pxRingbuffer->pucHead = malloc(xBufferSize); + if (pxRingbuffer->pucHead == NULL) { + goto err; + } + + //Initialize values + pxRingbuffer->xSize = xBufferSize; + pxRingbuffer->pucTail = pxRingbuffer->pucHead + xBufferSize; + pxRingbuffer->pucFree = pxRingbuffer->pucHead; + pxRingbuffer->pucRead = pxRingbuffer->pucHead; + pxRingbuffer->pucWrite = pxRingbuffer->pucHead; + pxRingbuffer->xItemsWaiting = 0; + pxRingbuffer->xFreeSpaceSemaphore = xSemaphoreCreateBinary(); + pxRingbuffer->xItemsBufferedSemaphore = xSemaphoreCreateBinary(); + pxRingbuffer->uxRingbufferFlags = 0; + + //Initialize type dependent values and function pointers + if (xBufferType == RINGBUF_TYPE_NOSPLIT) { + pxRingbuffer->xCheckItemFits = prvCheckItemFitsDefault; + pxRingbuffer->vCopyItem = prvCopyItemNoSplit; + pxRingbuffer->pvGetItem = prvGetItemDefault; + pxRingbuffer->vReturnItem = prvReturnItemDefault; + /* + * Buffer lengths are always aligned. No-split buffer (read/write/free) + * pointers are also always aligned. Therefore worse case scenario is + * the write pointer is at the most aligned halfway point. + */ + pxRingbuffer->xMaxItemSize = rbALIGN_SIZE(pxRingbuffer->xSize / 2) - rbHEADER_SIZE; + pxRingbuffer->xGetCurMaxSize = prvGetCurMaxSizeNoSplit; + } else if (xBufferType == RINGBUF_TYPE_ALLOWSPLIT) { + pxRingbuffer->uxRingbufferFlags |= rbALLOW_SPLIT_FLAG; + pxRingbuffer->xCheckItemFits = prvCheckItemFitsDefault; + pxRingbuffer->vCopyItem = prvCopyItemAllowSplit; + pxRingbuffer->pvGetItem = prvGetItemDefault; + pxRingbuffer->vReturnItem = prvReturnItemDefault; + //Worst case an item is split into two, incurring two headers of overhead + pxRingbuffer->xMaxItemSize = pxRingbuffer->xSize - (sizeof(ItemHeader_t) * 2); + pxRingbuffer->xGetCurMaxSize = prvGetCurMaxSizeAllowSplit; + } else if (xBufferType == RINGBUF_TYPE_BYTEBUF) { + pxRingbuffer->uxRingbufferFlags |= rbBYTE_BUFFER_FLAG; + pxRingbuffer->xCheckItemFits = prvCheckItemFitsByteBuffer; + pxRingbuffer->vCopyItem = prvCopyItemByteBuf; + pxRingbuffer->pvGetItem = prvGetItemByteBuf; + pxRingbuffer->vReturnItem = prvReturnItemByteBuf; + //Byte buffers do not incur any overhead + pxRingbuffer->xMaxItemSize = pxRingbuffer->xSize; + pxRingbuffer->xGetCurMaxSize = prvGetCurMaxSizeByteBuf; } else { + //Unsupported type configASSERT(0); } - if (rb->free_space_sem == NULL || rb->items_buffered_sem == NULL) goto err; - vPortCPUInitializeMutex(&rb->mux); - return (RingbufHandle_t)rb; + if (pxRingbuffer->xFreeSpaceSemaphore == NULL || pxRingbuffer->xItemsBufferedSemaphore == NULL) { + goto err; + } + xSemaphoreGive(pxRingbuffer->xFreeSpaceSemaphore); + vPortCPUInitializeMutex(&pxRingbuffer->mux); + + return (RingbufHandle_t)pxRingbuffer; err: //Some error has happened. Free/destroy all allocated things and return NULL. - if (rb) { - free(rb->data); - if (rb->free_space_sem) vSemaphoreDelete(rb->free_space_sem); - if (rb->items_buffered_sem) vSemaphoreDelete(rb->items_buffered_sem); + if (pxRingbuffer) { + free(pxRingbuffer->pucHead); + if (pxRingbuffer->xFreeSpaceSemaphore) { + vSemaphoreDelete(pxRingbuffer->xFreeSpaceSemaphore); + } + if (pxRingbuffer->xItemsBufferedSemaphore) { + vSemaphoreDelete(pxRingbuffer->xItemsBufferedSemaphore); + } } - free(rb); + free(pxRingbuffer); return NULL; } -RingbufHandle_t xRingbufferCreateNoSplit(size_t item_size, size_t num_item) +RingbufHandle_t xRingbufferCreateNoSplit(size_t xItemSize, size_t xItemNum) { - size_t aligned_size = (item_size+3)&~3; - return xRingbufferCreate((aligned_size + sizeof(buf_entry_hdr_t)) * num_item, RINGBUF_TYPE_NOSPLIT); + return xRingbufferCreate((rbALIGN_SIZE(xItemSize) + rbHEADER_SIZE) * xItemNum, RINGBUF_TYPE_NOSPLIT); } -void vRingbufferDelete(RingbufHandle_t ringbuf) { - ringbuf_t *rb=(ringbuf_t *)ringbuf; - if (rb) { - free(rb->data); - if (rb->free_space_sem) vSemaphoreDelete(rb->free_space_sem); - if (rb->items_buffered_sem) vSemaphoreDelete(rb->items_buffered_sem); +BaseType_t xRingbufferSend(RingbufHandle_t xRingbuffer, const void *pvItem, size_t xItemSize, TickType_t xTicksToWait) +{ + //Check arguments + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + configASSERT(pvItem != NULL || xItemSize == 0); + if (xItemSize > pxRingbuffer->xMaxItemSize) { + return pdFALSE; //Data will never ever fit in the queue. } - free(rb); + if ((pxRingbuffer->uxRingbufferFlags & rbBYTE_BUFFER_FLAG) && xItemSize == 0) { + return pdTRUE; //Sending 0 bytes to byte buffer has no effect + } + + //Attempt to send an item + BaseType_t xReturn = pdFALSE; + BaseType_t xReturnSemaphore = pdFALSE; + TickType_t xTicksEnd = xTaskGetTickCount() + xTicksToWait; + TickType_t xTicksRemaining = xTicksToWait; + while (xTicksRemaining <= xTicksToWait) { //xTicksToWait will underflow once xTaskGetTickCount() > ticks_end + //Block until more free space becomes available or timeout + if (xSemaphoreTake(pxRingbuffer->xFreeSpaceSemaphore, xTicksRemaining) != pdTRUE) { + xReturn = pdFALSE; + break; + } + //Semaphore obtained, check if item can fit + taskENTER_CRITICAL(&pxRingbuffer->mux); + if(pxRingbuffer->xCheckItemFits(pxRingbuffer, xItemSize) == pdTRUE) { + //Item will fit, copy item + pxRingbuffer->vCopyItem(pxRingbuffer, pvItem, xItemSize); + xReturn = pdTRUE; + //Check if the free semaphore should be returned to allow other tasks to send + if (prvGetFreeSize(pxRingbuffer) > 0) { + xReturnSemaphore = pdTRUE; + } + taskEXIT_CRITICAL(&pxRingbuffer->mux); + break; + } + //Item doesn't fit, adjust ticks and take the semaphore again + if (xTicksToWait != portMAX_DELAY) { + xTicksRemaining = xTicksEnd - xTaskGetTickCount(); + } + taskEXIT_CRITICAL(&pxRingbuffer->mux); + /* + * Gap between critical section and re-acquiring of the semaphore. If + * semaphore is given now, priority inversion might occur (see docs) + */ + } + + if (xReturn == pdTRUE) { + //Indicate item was successfully sent + xSemaphoreGive(pxRingbuffer->xItemsBufferedSemaphore); + } + if (xReturnSemaphore == pdTRUE) { + xSemaphoreGive(pxRingbuffer->xFreeSpaceSemaphore); //Give back semaphore so other tasks can send + } + return xReturn; } -size_t xRingbufferGetMaxItemSize(RingbufHandle_t ringbuf) +BaseType_t xRingbufferSendFromISR(RingbufHandle_t xRingbuffer, const void *pvItem, size_t xItemSize, BaseType_t *pxHigherPriorityTaskWoken) { - ringbuf_t *rb=(ringbuf_t *)ringbuf; - configASSERT(rb); - return rb->maxItemSize; + //Check arguments + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + configASSERT(pvItem != NULL || xItemSize == 0); + if (xItemSize > pxRingbuffer->xMaxItemSize) { + return pdFALSE; //Data will never ever fit in the queue. + } + if ((pxRingbuffer->uxRingbufferFlags & rbBYTE_BUFFER_FLAG) && xItemSize == 0) { + return pdTRUE; //Sending 0 bytes to byte buffer has no effect + } + + //Attempt to send an item + BaseType_t xReturn; + BaseType_t xReturnSemaphore = pdFALSE; + taskENTER_CRITICAL_ISR(&pxRingbuffer->mux); + if (pxRingbuffer->xCheckItemFits(xRingbuffer, xItemSize) == pdTRUE) { + pxRingbuffer->vCopyItem(xRingbuffer, pvItem, xItemSize); + xReturn = pdTRUE; + //Check if the free semaphore should be returned to allow other tasks to send + if (prvGetFreeSize(pxRingbuffer) > 0) { + xReturnSemaphore = pdTRUE; + } + } else { + xReturn = pdFALSE; + } + taskEXIT_CRITICAL_ISR(&pxRingbuffer->mux); + + if (xReturn == pdTRUE) { + //Indicate item was successfully sent + xSemaphoreGiveFromISR(pxRingbuffer->xItemsBufferedSemaphore, pxHigherPriorityTaskWoken); + } + if (xReturnSemaphore == pdTRUE) { + xSemaphoreGiveFromISR(pxRingbuffer->xFreeSpaceSemaphore, pxHigherPriorityTaskWoken); //Give back semaphore so other tasks can send + } + return xReturn; } -bool xRingbufferIsNextItemWrapped(RingbufHandle_t ringbuf) +void *xRingbufferReceive(RingbufHandle_t xRingbuffer, size_t *pxItemSize, TickType_t xTicksToWait) { - ringbuf_t *rb=(ringbuf_t *)ringbuf; - configASSERT(rb); - buf_entry_hdr_t *hdr=(buf_entry_hdr_t *)rb->read_ptr; - return hdr->flags & iflag_wrap; + //Check arguments + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + + //Attempt to retrieve an item + void *pvTempItem; + size_t xTempSize; + if (prvReceiveGeneric(pxRingbuffer, &pvTempItem, NULL, &xTempSize, NULL, 0, xTicksToWait) == pdTRUE) { + if (pxItemSize != NULL) { + *pxItemSize = xTempSize; + } + return pvTempItem; + } else { + return NULL; + } } - -BaseType_t xRingbufferSend(RingbufHandle_t ringbuf, void *data, size_t dataSize, TickType_t ticks_to_wait) +void *xRingbufferReceiveFromISR(RingbufHandle_t xRingbuffer, size_t *pxItemSize) { - ringbuf_t *rb=(ringbuf_t *)ringbuf; - size_t needed_size=dataSize+sizeof(buf_entry_hdr_t); - BaseType_t done=pdFALSE; - TickType_t ticks_end = xTaskGetTickCount() + ticks_to_wait; - TickType_t ticks_remaining = ticks_to_wait; + //Check arguments + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); - configASSERT(rb); + //Attempt to retrieve an item + void *pvTempItem; + size_t xTempSize; + if (prvReceiveGenericFromISR(pxRingbuffer, &pvTempItem, NULL, &xTempSize, NULL, 0) == pdTRUE) { + if (pxItemSize != NULL) { + *pxItemSize = xTempSize; + } + return pvTempItem; + } else { + return NULL; + } +} - if (dataSize > xRingbufferGetMaxItemSize(ringbuf)) { - //Data will never ever fit in the queue. +BaseType_t xRingbufferReceiveSplit(RingbufHandle_t xRingbuffer, void **ppvHeadItem, void **ppvTailItem, size_t *pxHeadItemSize, size_t *pxTailItemSize, TickType_t xTicksToWait) +{ + //Check arguments + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + configASSERT(pxRingbuffer->uxRingbufferFlags & rbALLOW_SPLIT_FLAG); + configASSERT(ppvHeadItem != NULL && ppvTailItem != NULL); + + //Attempt to retrieve multiple items + void *pvTempHeadItem, *pvTempTailItem; + size_t xTempHeadSize, xTempTailSize; + if (prvReceiveGeneric(pxRingbuffer, &pvTempHeadItem, &pvTempTailItem, &xTempHeadSize, &xTempTailSize, 0, xTicksToWait) == pdTRUE) { + //At least one item was retrieved + *ppvHeadItem = pvTempHeadItem; + if(pxHeadItemSize != NULL){ + *pxHeadItemSize = xTempHeadSize; + } + //Check to see if a second item was also retrieved + if (pvTempTailItem != NULL) { + *ppvTailItem = pvTempTailItem; + if (pxTailItemSize != NULL) { + *pxTailItemSize = xTempTailSize; + } + } else { + *ppvTailItem = NULL; + } + return pdTRUE; + } else { + //No items retrieved + *ppvHeadItem = NULL; + *ppvTailItem = NULL; return pdFALSE; } - - while (!done) { - //Check if there is enough room in the buffer. If not, wait until there is. - do { - if (ringbufferFreeMem(rb) < needed_size) { - //Data does not fit yet. Wait until the free_space_sem is given, then re-evaluate. - - BaseType_t r = xSemaphoreTake(rb->free_space_sem, ticks_remaining); - if (r == pdFALSE) { - //Timeout. - return pdFALSE; - } - //Adjust ticks_remaining; we may have waited less than that and in the case the free memory still is not enough, - //we will need to wait some more. - if (ticks_to_wait != portMAX_DELAY) { - ticks_remaining = ticks_end - xTaskGetTickCount(); - - // ticks_remaining will always be less than or equal to the original ticks_to_wait, - // unless the timeout is reached - in which case it unsigned underflows to a much - // higher value. - // - // (Check is written this non-intuitive way to allow for the case where xTaskGetTickCount() - // has overflowed but the ticks_end value has not overflowed.) - if(ticks_remaining > ticks_to_wait) { - //Timeout, but there is not enough free space for the item that need to be sent. - xSemaphoreGive(rb->free_space_sem); - return pdFALSE; - } - } - - } - } while (ringbufferFreeMem(rb) < needed_size); - - //Lock the mux in order to make sure no one else is messing with the ringbuffer and do the copy. - portENTER_CRITICAL(&rb->mux); - //Another thread may have been able to sneak its write first. Check again now we locked the ringbuff, and retry - //everything if this is the case. Otherwise, we can write and are done. - done=rb->copyItemToRingbufImpl(rb, data, dataSize); - portEXIT_CRITICAL(&rb->mux); - } - xSemaphoreGive(rb->items_buffered_sem); - return pdTRUE; } - -BaseType_t xRingbufferSendFromISR(RingbufHandle_t ringbuf, void *data, size_t dataSize, BaseType_t *higher_prio_task_awoken) +BaseType_t xRingbufferReceiveSplitFromISR(RingbufHandle_t xRingbuffer, void **ppvHeadItem, void **ppvTailItem, size_t *pxHeadItemSize, size_t *pxTailItemSize) { - ringbuf_t *rb=(ringbuf_t *)ringbuf; - BaseType_t write_succeeded; - configASSERT(rb); - size_t needed_size=dataSize+sizeof(buf_entry_hdr_t); - portENTER_CRITICAL_ISR(&rb->mux); - if (needed_size>ringbufferFreeMem(rb)) { - //Does not fit in the remaining space in the ringbuffer. - write_succeeded=pdFALSE; + //Check arguments + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + configASSERT(pxRingbuffer->uxRingbufferFlags & rbALLOW_SPLIT_FLAG); + configASSERT(ppvHeadItem != NULL && ppvTailItem != NULL); + + //Attempt to retrieve multiple items + void *pvTempHeadItem, *pvTempTailItem; + size_t xTempHeadSize, xTempTailSize; + if (prvReceiveGenericFromISR(pxRingbuffer, &pvTempHeadItem, &pvTempTailItem, &xTempHeadSize, &xTempTailSize, 0) == pdTRUE) { + //At least one item was received + *ppvHeadItem = pvTempHeadItem; + if (pxHeadItemSize != NULL) { + *pxHeadItemSize = xTempHeadSize; + } + //Check to see if a second item was also retrieved + if (pvTempTailItem != NULL) { + *ppvTailItem = pvTempTailItem; + if (pxTailItemSize != NULL) { + *pxTailItemSize = xTempTailSize; + } + } else { + *ppvTailItem = NULL; + } + return pdTRUE; } else { - write_succeeded = rb->copyItemToRingbufImpl(rb, data, dataSize); + *ppvHeadItem = NULL; + *ppvTailItem = NULL; + return pdFALSE; } - portEXIT_CRITICAL_ISR(&rb->mux); - if (write_succeeded) { - xSemaphoreGiveFromISR(rb->items_buffered_sem, higher_prio_task_awoken); - } - return write_succeeded; } - -static void *xRingbufferReceiveGeneric(RingbufHandle_t ringbuf, size_t *item_size, TickType_t ticks_to_wait, size_t wanted_size) +void *xRingbufferReceiveUpTo(RingbufHandle_t xRingbuffer, size_t *pxItemSize, TickType_t xTicksToWait, size_t xMaxSize) { - ringbuf_t *rb=(ringbuf_t *)ringbuf; - uint8_t *itemData; - BaseType_t done=pdFALSE; - configASSERT(rb); - while(!done) { - //See if there's any data available. If not, wait until there is. - while (rb->read_ptr == rb->write_ptr) { - BaseType_t r=xSemaphoreTake(rb->items_buffered_sem, ticks_to_wait); - if (r == pdFALSE) { - //Timeout. - return NULL; - } + //Check arguments + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + configASSERT(pxRingbuffer->uxRingbufferFlags & rbBYTE_BUFFER_FLAG); //This function should only be called for byte buffers + if (xMaxSize == 0) { + return NULL; + } + + //Attempt to retrieve up to xMaxSize bytes + void *pvTempItem; + size_t xTempSize; + if (prvReceiveGeneric(pxRingbuffer, &pvTempItem, NULL, &xTempSize, NULL, xMaxSize, xTicksToWait) == pdTRUE) { + if (pxItemSize != NULL) { + *pxItemSize = xTempSize; } - //Okay, we seem to have data in the buffer. Grab the mux and copy it out if it's still there. - portENTER_CRITICAL(&rb->mux); - itemData=rb->getItemFromRingbufImpl(rb, item_size, wanted_size); - portEXIT_CRITICAL(&rb->mux); - if (itemData) { - //We managed to get an item. - done=pdTRUE; + return pvTempItem; + } else { + return NULL; + } +} + +void *xRingbufferReceiveUpToFromISR(RingbufHandle_t xRingbuffer, size_t *pxItemSize, size_t xMaxSize) +{ + //Check arguments + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + configASSERT(pxRingbuffer->uxRingbufferFlags & rbBYTE_BUFFER_FLAG); //This function should only be called for byte buffers + if (xMaxSize == 0) { + return NULL; + } + + //Attempt to retrieve up to xMaxSize bytes + void *pvTempItem; + size_t xTempSize; + if (prvReceiveGenericFromISR(pxRingbuffer, &pvTempItem, NULL, &xTempSize, NULL, xMaxSize) == pdTRUE) { + if (pxItemSize != NULL) { + *pxItemSize = xTempSize; + } + return pvTempItem; + } else { + return NULL; + } +} + +void vRingbufferReturnItem(RingbufHandle_t xRingbuffer, void *pvItem) +{ + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + configASSERT(pvItem != NULL); + + taskENTER_CRITICAL(&pxRingbuffer->mux); + pxRingbuffer->vReturnItem(pxRingbuffer, (uint8_t *)pvItem); + taskEXIT_CRITICAL(&pxRingbuffer->mux); + xSemaphoreGive(pxRingbuffer->xFreeSpaceSemaphore); +} + +void vRingbufferReturnItemFromISR(RingbufHandle_t xRingbuffer, void *pvItem, BaseType_t *pxHigherPriorityTaskWoken) +{ + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + configASSERT(pvItem != NULL); + + taskENTER_CRITICAL_ISR(&pxRingbuffer->mux); + pxRingbuffer->vReturnItem(pxRingbuffer, (uint8_t *)pvItem); + taskEXIT_CRITICAL_ISR(&pxRingbuffer->mux); + xSemaphoreGiveFromISR(pxRingbuffer->xFreeSpaceSemaphore, pxHigherPriorityTaskWoken); +} + +void vRingbufferDelete(RingbufHandle_t xRingbuffer) +{ + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + + if (pxRingbuffer) { + free(pxRingbuffer->pucHead); + if (pxRingbuffer->xFreeSpaceSemaphore) { + vSemaphoreDelete(pxRingbuffer->xFreeSpaceSemaphore); + } + if (pxRingbuffer->xItemsBufferedSemaphore) { + vSemaphoreDelete(pxRingbuffer->xItemsBufferedSemaphore); } } - return (void*)itemData; + free(pxRingbuffer); } -void *xRingbufferReceive(RingbufHandle_t ringbuf, size_t *item_size, TickType_t ticks_to_wait) +size_t xRingbufferGetMaxItemSize(RingbufHandle_t xRingbuffer) { - return xRingbufferReceiveGeneric(ringbuf, item_size, ticks_to_wait, 0); + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + return pxRingbuffer->xMaxItemSize; } - -void *xRingbufferReceiveFromISR(RingbufHandle_t ringbuf, size_t *item_size) +size_t xRingbufferGetCurFreeSize(RingbufHandle_t xRingbuffer) { - ringbuf_t *rb=(ringbuf_t *)ringbuf; - uint8_t *itemData; - configASSERT(rb); - portENTER_CRITICAL_ISR(&rb->mux); - itemData=rb->getItemFromRingbufImpl(rb, item_size, 0); - portEXIT_CRITICAL_ISR(&rb->mux); - return (void*)itemData; + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + + size_t xFreeSize; + taskENTER_CRITICAL(&pxRingbuffer->mux); + xFreeSize = pxRingbuffer->xGetCurMaxSize(pxRingbuffer); + taskEXIT_CRITICAL(&pxRingbuffer->mux); + return xFreeSize; } -void *xRingbufferReceiveUpTo(RingbufHandle_t ringbuf, size_t *item_size, TickType_t ticks_to_wait, size_t wanted_size) { - if (wanted_size == 0) return NULL; - configASSERT(ringbuf); - configASSERT(((ringbuf_t *)ringbuf)->flags & flag_bytebuf); - return xRingbufferReceiveGeneric(ringbuf, item_size, ticks_to_wait, wanted_size); -} - -void *xRingbufferReceiveUpToFromISR(RingbufHandle_t ringbuf, size_t *item_size, size_t wanted_size) +BaseType_t xRingbufferAddToQueueSetRead(RingbufHandle_t xRingbuffer, QueueSetHandle_t xQueueSet) { - ringbuf_t *rb=(ringbuf_t *)ringbuf; - uint8_t *itemData; - if (wanted_size == 0) return NULL; - configASSERT(rb); - configASSERT(rb->flags & flag_bytebuf); - portENTER_CRITICAL_ISR(&rb->mux); - itemData=rb->getItemFromRingbufImpl(rb, item_size, wanted_size); - portEXIT_CRITICAL_ISR(&rb->mux); - return (void*)itemData; + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + + BaseType_t xReturn; + taskENTER_CRITICAL(&pxRingbuffer->mux); + //Cannot add semaphore to queue set if semaphore is not empty. Temporarily hold semaphore + BaseType_t xHoldSemaphore = xSemaphoreTake(pxRingbuffer->xItemsBufferedSemaphore, 0); + xReturn = xQueueAddToSet(pxRingbuffer->xItemsBufferedSemaphore, xQueueSet); + if (xHoldSemaphore == pdTRUE) { + //Return semaphore if temporarily held + configASSERT(xSemaphoreGive(pxRingbuffer->xItemsBufferedSemaphore) == pdTRUE); + } + taskEXIT_CRITICAL(&pxRingbuffer->mux); + return xReturn; } - -void vRingbufferReturnItem(RingbufHandle_t ringbuf, void *item) +BaseType_t xRingbufferCanRead(RingbufHandle_t xRingbuffer, QueueSetMemberHandle_t xMember) { - ringbuf_t *rb=(ringbuf_t *)ringbuf; - portENTER_CRITICAL(&rb->mux); - rb->returnItemToRingbufImpl(rb, item); - portEXIT_CRITICAL(&rb->mux); - xSemaphoreGive(rb->free_space_sem); + //Check if the selected queue set member is the ring buffer's read semaphore + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + return (pxRingbuffer->xItemsBufferedSemaphore == xMember) ? pdTRUE : pdFALSE; } - -void vRingbufferReturnItemFromISR(RingbufHandle_t ringbuf, void *item, BaseType_t *higher_prio_task_awoken) +BaseType_t xRingbufferRemoveFromQueueSetRead(RingbufHandle_t xRingbuffer, QueueSetHandle_t xQueueSet) { - ringbuf_t *rb=(ringbuf_t *)ringbuf; - portENTER_CRITICAL_ISR(&rb->mux); - rb->returnItemToRingbufImpl(rb, item); - portEXIT_CRITICAL_ISR(&rb->mux); - xSemaphoreGiveFromISR(rb->free_space_sem, higher_prio_task_awoken); + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + + BaseType_t xReturn; + taskENTER_CRITICAL(&pxRingbuffer->mux); + //Cannot remove semaphore from queue set if semaphore is not empty. Temporarily hold semaphore + BaseType_t xHoldSemaphore = xSemaphoreTake(pxRingbuffer->xItemsBufferedSemaphore, 0); + xReturn = xQueueRemoveFromSet(pxRingbuffer->xItemsBufferedSemaphore, xQueueSet); + if (xHoldSemaphore == pdTRUE) { + //Return semaphore if temporarily held + configASSERT(xSemaphoreGive(pxRingbuffer->xItemsBufferedSemaphore) == pdTRUE); + } + taskEXIT_CRITICAL(&pxRingbuffer->mux); + return xReturn; } - -BaseType_t xRingbufferAddToQueueSetRead(RingbufHandle_t ringbuf, QueueSetHandle_t xQueueSet) +void vRingbufferGetInfo(RingbufHandle_t xRingbuffer, UBaseType_t *uxFree, UBaseType_t *uxRead, UBaseType_t *uxWrite, UBaseType_t *uxItemsWaiting) { - ringbuf_t *rb=(ringbuf_t *)ringbuf; - configASSERT(rb); - return xQueueAddToSet(rb->items_buffered_sem, xQueueSet); + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + + taskENTER_CRITICAL(&pxRingbuffer->mux); + if (uxFree != NULL) { + *uxFree = (UBaseType_t)(pxRingbuffer->pucFree - pxRingbuffer->pucHead); + } + if (uxRead != NULL) { + *uxRead = (UBaseType_t)(pxRingbuffer->pucRead - pxRingbuffer->pucHead); + } + if (uxWrite != NULL) { + *uxWrite = (UBaseType_t)(pxRingbuffer->pucWrite - pxRingbuffer->pucHead); + } + if (uxItemsWaiting != NULL) { + *uxItemsWaiting = (UBaseType_t)(pxRingbuffer->xItemsWaiting); + } + taskEXIT_CRITICAL(&pxRingbuffer->mux); } - -BaseType_t xRingbufferAddToQueueSetWrite(RingbufHandle_t ringbuf, QueueSetHandle_t xQueueSet) +void xRingbufferPrintInfo(RingbufHandle_t xRingbuffer) { - ringbuf_t *rb=(ringbuf_t *)ringbuf; - configASSERT(rb); - return xQueueAddToSet(rb->free_space_sem, xQueueSet); + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + printf("Rb size:%d\tfree: %d\trptr: %d\tfreeptr: %d\twptr: %d\n", + pxRingbuffer->xSize, prvGetFreeSize(pxRingbuffer), + pxRingbuffer->pucRead - pxRingbuffer->pucHead, + pxRingbuffer->pucFree - pxRingbuffer->pucHead, + pxRingbuffer->pucWrite - pxRingbuffer->pucHead); } +/* --------------------------------- Deprecated Functions ------------------------------ */ +//Todo: Remove the following deprecated functions in next release -BaseType_t xRingbufferRemoveFromQueueSetRead(RingbufHandle_t ringbuf, QueueSetHandle_t xQueueSet) +bool xRingbufferIsNextItemWrapped(RingbufHandle_t xRingbuffer) { - ringbuf_t *rb=(ringbuf_t *)ringbuf; - configASSERT(rb); - return xQueueRemoveFromSet(rb->items_buffered_sem, xQueueSet); + //This function is deprecated, use xRingbufferReceiveSplit() instead + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + bool is_wrapped; + + portENTER_CRITICAL(&pxRingbuffer->mux); + ItemHeader_t *xHeader = (ItemHeader_t *)pxRingbuffer->pucRead; + is_wrapped = xHeader->uxItemFlags & rbITEM_SPLIT_FLAG; + portEXIT_CRITICAL(&pxRingbuffer->mux); + return is_wrapped; } -BaseType_t xRingbufferRemoveFromQueueSetWrite(RingbufHandle_t ringbuf, QueueSetHandle_t xQueueSet) +BaseType_t xRingbufferAddToQueueSetWrite(RingbufHandle_t xRingbuffer, QueueSetHandle_t xQueueSet) { - ringbuf_t *rb=(ringbuf_t *)ringbuf; - configASSERT(rb); - return xQueueRemoveFromSet(rb->free_space_sem, xQueueSet); + //This function is deprecated. QueueSetWrite no longer supported + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + + BaseType_t xReturn; + portENTER_CRITICAL(&pxRingbuffer->mux); + //Cannot add semaphore to queue set if semaphore is not empty. Temporary hold semaphore + BaseType_t xHoldSemaphore = xSemaphoreTake(pxRingbuffer->xFreeSpaceSemaphore, 0); + xReturn = xQueueAddToSet(pxRingbuffer->xFreeSpaceSemaphore, xQueueSet); + if (xHoldSemaphore == pdTRUE) { + //Return semaphore is temporarily held + configASSERT(xSemaphoreGive(pxRingbuffer->xFreeSpaceSemaphore) == pdTRUE); + } + portEXIT_CRITICAL(&pxRingbuffer->mux); + return xReturn; +} + +BaseType_t xRingbufferRemoveFromQueueSetWrite(RingbufHandle_t xRingbuffer, QueueSetHandle_t xQueueSet) +{ + //This function is deprecated. QueueSetWrite no longer supported + Ringbuffer_t *pxRingbuffer = (Ringbuffer_t *)xRingbuffer; + configASSERT(pxRingbuffer); + + BaseType_t xReturn; + portENTER_CRITICAL(&pxRingbuffer->mux); + //Cannot remove semaphore from queue set if semaphore is not empty. Temporary hold semaphore + BaseType_t xHoldSemaphore = xSemaphoreTake(pxRingbuffer->xFreeSpaceSemaphore, 0); + xReturn = xQueueRemoveFromSet(pxRingbuffer->xFreeSpaceSemaphore, xQueueSet); + if (xHoldSemaphore == pdTRUE) { + //Return semaphore is temporarily held + configASSERT(xSemaphoreGive(pxRingbuffer->xFreeSpaceSemaphore) == pdTRUE); + } + portEXIT_CRITICAL(&pxRingbuffer->mux); + return xReturn; } diff --git a/components/freertos/test/test_ringbuf.c b/components/freertos/test/test_ringbuf.c index 6a721aae39..e47512d8ec 100644 --- a/components/freertos/test/test_ringbuf.c +++ b/components/freertos/test/test_ringbuf.c @@ -1,227 +1,606 @@ -/* - Test for multicore FreeRTOS ringbuffer. -*/ - -#include #include -#include "rom/ets_sys.h" - +#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/semphr.h" #include "freertos/queue.h" +#include "freertos/semphr.h" #include "freertos/ringbuf.h" -#include "freertos/xtensa_api.h" +#include "driver/timer.h" #include "unity.h" -#include "soc/uart_reg.h" -#include "soc/dport_reg.h" -#include "soc/io_mux_reg.h" -#include "esp_intr_alloc.h" +//Definitions used in multiple test cases +#define TIMEOUT_TICKS 10 +#define NO_OF_RB_TYPES 3 +#define ITEM_HDR_SIZE 8 +#define SMALL_ITEM_SIZE 8 +#define LARGE_ITEM_SIZE (2 * SMALL_ITEM_SIZE) +#define BUFFER_SIZE 160 //4Byte aligned size -static RingbufHandle_t rb; -typedef enum { - TST_MOSTLYFILLED, - TST_MOSTLYEMPTY, - TST_INTTOTASK, - TST_TASKTOINT, -} testtype_t; +static const uint8_t small_item[SMALL_ITEM_SIZE] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; +static const uint8_t large_item[LARGE_ITEM_SIZE] = { 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17}; +static RingbufHandle_t buffer_handles[NO_OF_RB_TYPES]; +static SemaphoreHandle_t done_sem; -static volatile testtype_t testtype; - -intr_handle_t s_intr_handle; - -static void task1(void *arg) +static void send_item_and_check(RingbufHandle_t handle, const uint8_t *item, size_t item_size, TickType_t ticks_to_wait, bool in_isr) { - testtype_t oldtest; - char buf[100]; - int i = 0; - int x, r; - while (1) { - oldtest = testtype; - if (testtype == TST_MOSTLYFILLED || testtype == TST_MOSTLYEMPTY) { - for (x = 0; x < 10; x++) { - sprintf(buf, "This is test %d item %d.", (int)testtype, i++); - ets_printf("TSK w"); - xRingbufferPrintInfo(rb); - r = xRingbufferSend(rb, buf, strlen(buf) + 1, 2000 / portTICK_PERIOD_MS); - if (!r) { - printf("Test %d: Timeout on send!\n", (int)testtype); - } - if (testtype == TST_MOSTLYEMPTY) { - vTaskDelay(300 / portTICK_PERIOD_MS); - } - } - //Send NULL event to stop other side. - r = xRingbufferSend(rb, NULL, 0, 10000 / portTICK_PERIOD_MS); - } - while (oldtest == testtype) { - vTaskDelay(300 / portTICK_PERIOD_MS); - } - } -} - -static void task2(void *arg) -{ - testtype_t oldtest; - char *buf; - size_t len; - while (1) { - oldtest = testtype; - if (testtype == TST_MOSTLYFILLED || testtype == TST_MOSTLYEMPTY) { - while (1) { - ets_printf("TSK r"); - xRingbufferPrintInfo(rb); - buf = xRingbufferReceive(rb, &len, 2000 / portTICK_PERIOD_MS); - if (buf == NULL) { - printf("Test %d: Timeout on recv!\n", (int)testtype); - } else if (len == 0) { - printf("End packet received.\n"); - vRingbufferReturnItem(rb, buf); - break; - } else { - printf("Received: %s (%d bytes, %p)\n", buf, len, buf); - vRingbufferReturnItem(rb, buf); - } - if (testtype == TST_MOSTLYFILLED) { - vTaskDelay(300 / portTICK_PERIOD_MS); - } - } - } - while (oldtest == testtype) { - vTaskDelay(300 / portTICK_PERIOD_MS); - } - } -} - - - -static void uartIsrHdl(void *arg) -{ - char c; - char buf[50]; - char *item; - int r; - size_t len; - BaseType_t xHigherPriorityTaskWoken; - SET_PERI_REG_MASK(UART_INT_CLR_REG(0), UART_RXFIFO_FULL_INT_CLR); - while (READ_PERI_REG(UART_STATUS_REG(0)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) { - c = READ_PERI_REG(UART_FIFO_REG(0)); - if (c == 'r') { - ets_printf("ISR r"); - xRingbufferPrintInfo(rb); - item = xRingbufferReceiveFromISR(rb, &len); - if (item == NULL) { - ets_printf("ISR recv fail!\n"); - } else if (len == 0) { - ets_printf("ISR recv NULL!\n"); - vRingbufferReturnItemFromISR(rb, item, &xHigherPriorityTaskWoken); - } else { - ets_printf("ISR recv '%s' (%d bytes, %p)\n", buf, len, buf); - vRingbufferReturnItemFromISR(rb, item, &xHigherPriorityTaskWoken); - } - } else { - sprintf(buf, "UART: %c", c); - ets_printf("ISR w"); - xRingbufferPrintInfo(rb); - r = xRingbufferSendFromISR(rb, buf, strlen(buf) + 1, &xHigherPriorityTaskWoken); - if (!r) { - ets_printf("ISR send fail\n"); - } - } - } - if (xHigherPriorityTaskWoken) { - portYIELD_FROM_ISR(); - } -} - -static void uartRxInit() -{ - WRITE_PERI_REG(UART_CONF1_REG(0), 1 << UART_RXFIFO_FULL_THRHD_S); - CLEAR_PERI_REG_MASK(UART_INT_ENA_REG(0), UART_TXFIFO_EMPTY_INT_ENA | UART_RXFIFO_TOUT_INT_ENA); - SET_PERI_REG_MASK(UART_INT_ENA_REG(0), UART_RXFIFO_FULL_INT_ENA); - - ESP_ERROR_CHECK(esp_intr_alloc(ETS_UART0_INTR_SOURCE, 0, &uartIsrHdl, NULL, &s_intr_handle)); -} - -static void uartRxDeinit() -{ - esp_intr_free(s_intr_handle); -} - -static void testRingbuffer(int type, bool arbitrary) -{ - TaskHandle_t th[2]; - int i; - /* Arbitrary Length means buffer length which is not a multiple of 4 */ - if (arbitrary) { - rb = xRingbufferCreate(31 * 3, type); + BaseType_t ret; + if (in_isr) { + ret = xRingbufferSendFromISR(handle, (void *)item, item_size, NULL); } else { - rb = xRingbufferCreate(32 * 3, type); + ret = xRingbufferSend(handle, (void *)item, item_size, ticks_to_wait); + } + TEST_ASSERT_MESSAGE(ret == pdTRUE, "Failed to send item"); +} + +static void receive_check_and_return_item_no_split(RingbufHandle_t handle, const uint8_t *expected_data, size_t expected_size, TickType_t ticks_to_wait, bool in_isr) +{ + //Receive item from no-split buffer + size_t item_size; + uint8_t *item; + if (in_isr) { + item = (uint8_t *)xRingbufferReceiveFromISR(handle, &item_size); + } else { + item = (uint8_t *)xRingbufferReceive(handle, &item_size, ticks_to_wait); + } + TEST_ASSERT_MESSAGE(item != NULL, "Failed to receive item"); + TEST_ASSERT_MESSAGE(item_size == expected_size, "Item size is incorrect"); + //Check data of received item + for (int i = 0; i < item_size; i++) { + TEST_ASSERT_MESSAGE(item[i] == expected_data[i], "Item data is invalid"); + } + //Return item + if (in_isr) { + vRingbufferReturnItemFromISR(handle, (void *)item, NULL); + } else { + vRingbufferReturnItem(handle, (void *)item); } - testtype = TST_MOSTLYFILLED; +} - xTaskCreatePinnedToCore(task1, "tskone", 2048, NULL, 3, &th[0], 0); - xTaskCreatePinnedToCore(task2, "tsktwo", 2048, NULL, 3, &th[1], 0); - uartRxInit(); - - printf("Press 'r' to read an event in isr, any other key to write one.\n"); - printf("Test: mostlyfilled; putting 10 items in ringbuff ASAP, reading 1 a second\n"); - vTaskDelay(5000 / portTICK_PERIOD_MS); - printf("Test: mostlyempty; putting 10 items in ringbuff @ 1/sec, reading as fast as possible\n"); - testtype = TST_MOSTLYEMPTY; - vTaskDelay(5000 / portTICK_PERIOD_MS); - - //Shut down all the tasks - for (i = 0; i < 2; i++) { - vTaskDelete(th[i]); +static void receive_check_and_return_item_allow_split(RingbufHandle_t handle, const uint8_t *expected_data, size_t expected_size, TickType_t ticks_to_wait, bool in_isr) +{ + //Receive item + size_t item_size1, item_size2; + uint8_t *item1, *item2; + BaseType_t ret; + if (in_isr) { + ret = xRingbufferReceiveSplitFromISR(handle, (void**)&item1, (void **)&item2, &item_size1, &item_size2); + } else { + ret = xRingbufferReceiveSplit(handle, (void**)&item1, (void **)&item2, &item_size1, &item_size2, ticks_to_wait); } - vRingbufferDelete(rb); - uartRxDeinit(); -} + //= xRingbufferReceiveSplit(handle, (void**)&item1, (void **)&item2, &item_size1, &item_size2, ticks_to_wait); + TEST_ASSERT_MESSAGE(ret == pdTRUE, "Failed to receive item"); + TEST_ASSERT_MESSAGE(item1 != NULL, "Failed to receive item"); -// TODO: split this thing into separate orthogonal tests -TEST_CASE("FreeRTOS ringbuffer test, no splitting items", "[freertos]") -{ - testRingbuffer(0, false); -} - -TEST_CASE("FreeRTOS ringbuffer test, w/ splitting items", "[freertos]") -{ - testRingbuffer(1, false); -} - -TEST_CASE("FreeRTOS ringbuffer test, no splitting items, arbitrary length buffer", "[freertos]") -{ - testRingbuffer(0, true); -} - -TEST_CASE("FreeRTOS ringbuffer test, w/ splitting items, arbitrary length buffer", "[freertos]") -{ - testRingbuffer(1, true); -} - - -TEST_CASE("FreeRTOS ringbuffer test, check if zero-length items are handled correctly", "[freertos]") -{ - rb = xRingbufferCreate(32, 0); - int r; - void *v; - size_t sz; - for (int x=0; x<128; x++) { - if (x!=127) { - //Send an item - r = xRingbufferSend(rb, NULL, 0, 10000 / portTICK_PERIOD_MS); - assert(r==pdTRUE); + //Check data of received item(s) and return them + if (item2 == NULL) { + TEST_ASSERT_MESSAGE(item_size1 == expected_size, "Item size is incorrect"); + for (int i = 0; i < item_size1; i++) { + TEST_ASSERT_MESSAGE(item1[i] == expected_data[i], "Item data is invalid"); } - if (x!=0) { - //Receive an item - v=xRingbufferReceive(rb, &sz, 10000 / portTICK_PERIOD_MS); - assert(sz==0); - vRingbufferReturnItem(rb, v); //actually not needed for NULL data... + //Return item + if (in_isr) { + vRingbufferReturnItemFromISR(handle, (void *)item1, NULL); + } else { + vRingbufferReturnItem(handle, (void *)item1); + } + } else { + //Item was split + TEST_ASSERT_MESSAGE(item_size1 + item_size2 == expected_size, "Total item size is incorrect"); + for (int i = 0; i < item_size1; i++) { + TEST_ASSERT_MESSAGE(item1[i] == expected_data[i], "Head item data is invalid"); + } + for (int i = 0; i < item_size2; i++) { + TEST_ASSERT_MESSAGE(item2[i] == expected_data[item_size1 + i], "Head item data is invalid"); + } + //Return Items + if (in_isr) { + vRingbufferReturnItemFromISR(handle, (void *)item1, NULL); + vRingbufferReturnItemFromISR(handle, (void *)item2, NULL); + } else { + vRingbufferReturnItem(handle, (void *)item1); + vRingbufferReturnItem(handle, (void *)item2); } } - vRingbufferDelete(rb); } +static void receive_check_and_return_item_byte_buffer(RingbufHandle_t handle, const uint8_t *expected_data, size_t expected_size, TickType_t ticks_to_wait, bool in_isr) +{ + //Receive item + size_t item_size; + uint8_t *item; + if (in_isr) { + item = (uint8_t *)xRingbufferReceiveUpToFromISR(handle, &item_size, expected_size); + } else { + item = (uint8_t *)xRingbufferReceiveUpTo(handle, &item_size, ticks_to_wait, expected_size); //Limit amount of bytes returned to the size of one item + } + TEST_ASSERT_MESSAGE(item != NULL, "Failed to receive item"); + + //Check data of received item + for (int i = 0; i < item_size; i++) { + TEST_ASSERT_MESSAGE(item[i] == expected_data[i], "Item data is invalid"); + } + //Return item + if (in_isr) { + vRingbufferReturnItemFromISR(handle, (void *)item, NULL); + } else { + vRingbufferReturnItem(handle, (void *)item); + } + + //Check if item wrapped around + if (item_size < expected_size) { + //Item is wrapped, receive second portion + size_t item_size2; + uint8_t *item2; + if (in_isr) { + item2 = (uint8_t *)xRingbufferReceiveUpToFromISR(handle, &item_size2, expected_size - item_size); + } else { + item2 = (uint8_t *)xRingbufferReceiveUpTo(handle, &item_size2, ticks_to_wait, expected_size - item_size); + } + //= (uint8_t *)xRingbufferReceiveUpTo(handle, &item_size2, ticks_to_wait, expected_size - item_size); + TEST_ASSERT_MESSAGE(item2 != NULL, "Failed to receive item"); + TEST_ASSERT_MESSAGE(item_size + item_size2 == expected_size, "Total item size is incorrect"); + for (int i = 0; i < item_size2; i++) { + TEST_ASSERT_MESSAGE(item2[i] == expected_data[item_size + i], "Item data is invalid"); + } + if (in_isr) { + vRingbufferReturnItemFromISR(handle, (void *)item2, NULL); + } else { + vRingbufferReturnItem(handle, (void *)item2); + } + } else { + TEST_ASSERT_MESSAGE(item_size == expected_size, "Item size is incorrect"); + } +} + +/* ----------------- Basic ring buffer behavior tests cases -------------------- + * The following test cases will test basic send, receive, and wrap around + * behavior of each type of ring buffer. Each test case will do the following + * 1) Send multiple items (nearly fill the buffer) + * 2) Receive and check the sent items (also prepares the buffer for a wrap around + * 3) Send a final item that causes a wrap around + * 4) Receive and check the wrapped item + */ + +TEST_CASE("Test ring buffer No-Split", "[freertos]") +{ + //Create buffer + RingbufHandle_t buffer_handle = xRingbufferCreate(BUFFER_SIZE, RINGBUF_TYPE_NOSPLIT); + TEST_ASSERT_MESSAGE(buffer_handle != NULL, "Failed to create ring buffer"); + //Calculate number of items to send. Aim to almost fill buffer to setup for wrap around + int no_of_items = (BUFFER_SIZE - (ITEM_HDR_SIZE + SMALL_ITEM_SIZE)) / (ITEM_HDR_SIZE + SMALL_ITEM_SIZE); + + //Test sending items + for (int i = 0; i < no_of_items; i++) { + send_item_and_check(buffer_handle, small_item, SMALL_ITEM_SIZE, TIMEOUT_TICKS, false); + } + //Test receiving items + for (int i = 0; i < no_of_items; i++) { + receive_check_and_return_item_no_split(buffer_handle, small_item, SMALL_ITEM_SIZE, TIMEOUT_TICKS, false); + } + + //Write pointer should be near the end, test wrap around + uint32_t write_pos_before, write_pos_after; + vRingbufferGetInfo(buffer_handle, NULL, NULL, &write_pos_before, NULL); + //Send large item that causes wrap around + send_item_and_check(buffer_handle, large_item, LARGE_ITEM_SIZE, TIMEOUT_TICKS, false); + //Receive wrapped item + receive_check_and_return_item_no_split(buffer_handle, large_item, LARGE_ITEM_SIZE, TIMEOUT_TICKS, false); + vRingbufferGetInfo(buffer_handle, NULL, NULL, &write_pos_after, NULL); + TEST_ASSERT_MESSAGE(write_pos_after < write_pos_before, "Failed to wrap around"); + + //Cleanup + vRingbufferDelete(buffer_handle); +} + +TEST_CASE("Test ring buffer Allow-Split", "[freertos]") +{ + //Create buffer + RingbufHandle_t buffer_handle = xRingbufferCreate(BUFFER_SIZE, RINGBUF_TYPE_ALLOWSPLIT); + TEST_ASSERT_MESSAGE(buffer_handle != NULL, "Failed to create ring buffer"); + //Calculate number of items to send. Aim to almost fill buffer to setup for wrap around + int no_of_items = (BUFFER_SIZE - (ITEM_HDR_SIZE + SMALL_ITEM_SIZE)) / (ITEM_HDR_SIZE + SMALL_ITEM_SIZE); + + //Test sending items + for (int i = 0; i < no_of_items; i++) { + send_item_and_check(buffer_handle, small_item, SMALL_ITEM_SIZE, TIMEOUT_TICKS, false); + } + //Test receiving items + for (int i = 0; i < no_of_items; i++) { + receive_check_and_return_item_allow_split(buffer_handle, small_item, SMALL_ITEM_SIZE, TIMEOUT_TICKS, false); + } + + //Write pointer should be near the end, test wrap around + uint32_t write_pos_before, write_pos_after; + vRingbufferGetInfo(buffer_handle, NULL, NULL, &write_pos_before, NULL); + //Send large item that causes wrap around + send_item_and_check(buffer_handle, large_item, LARGE_ITEM_SIZE, TIMEOUT_TICKS, false); + //Receive wrapped item + receive_check_and_return_item_allow_split(buffer_handle, large_item, LARGE_ITEM_SIZE, TIMEOUT_TICKS, false); + vRingbufferGetInfo(buffer_handle, NULL, NULL, &write_pos_after, NULL); + TEST_ASSERT_MESSAGE(write_pos_after < write_pos_before, "Failed to wrap around"); + + //Cleanup + vRingbufferDelete(buffer_handle); +} + +TEST_CASE("Test ring buffer Byte Buffer", "[freertos]") +{ + //Create buffer + RingbufHandle_t buffer_handle = xRingbufferCreate(BUFFER_SIZE, RINGBUF_TYPE_BYTEBUF); + TEST_ASSERT_MESSAGE(buffer_handle != NULL, "Failed to create ring buffer"); + //Calculate number of items to send. Aim to almost fill buffer to setup for wrap around + int no_of_items = (BUFFER_SIZE - SMALL_ITEM_SIZE) / SMALL_ITEM_SIZE; + + //Test sending items + for (int i = 0; i < no_of_items; i++) { + send_item_and_check(buffer_handle, small_item, SMALL_ITEM_SIZE, TIMEOUT_TICKS, false); + } + //Test receiving items + for (int i = 0; i < no_of_items; i++) { + receive_check_and_return_item_byte_buffer(buffer_handle, small_item, SMALL_ITEM_SIZE, TIMEOUT_TICKS, false); + } + + //Write pointer should be near the end, test wrap around + uint32_t write_pos_before, write_pos_after; + vRingbufferGetInfo(buffer_handle, NULL, NULL, &write_pos_before, NULL); + //Send large item that causes wrap around + send_item_and_check(buffer_handle, large_item, LARGE_ITEM_SIZE, TIMEOUT_TICKS, false); + //Receive wrapped item + receive_check_and_return_item_byte_buffer(buffer_handle, large_item, LARGE_ITEM_SIZE, TIMEOUT_TICKS, false); + vRingbufferGetInfo(buffer_handle, NULL, NULL, &write_pos_after, NULL); + TEST_ASSERT_MESSAGE(write_pos_after < write_pos_before, "Failed to wrap around"); + + //Cleanup + vRingbufferDelete(buffer_handle); +} + +/* ----------------------- Ring buffer queue sets test ------------------------ + * The following test case will test receiving from ring buffers that have been + * added to a queue set. The test case will do the following... + * 1) Ring buffer of each type is created and added to the queue set + * 2) A receiving task is created to select from the queue set and read from the appropriate ring buffer + */ + +static void queue_set_receiving_task(void *queue_set_handle) +{ + QueueSetHandle_t queue_set = (QueueSetHandle_t)queue_set_handle; + + //Receive multiple items via queue set + BaseType_t done = pdFALSE; + int no_of_items = BUFFER_SIZE / SMALL_ITEM_SIZE; + int items_rec_count[NO_OF_RB_TYPES] = {0}; + while (done != pdTRUE) { + xQueueSetMemberHandle member = xQueueSelectFromSet(queue_set, TIMEOUT_TICKS); + //Read from selected ring buffer + if (xRingbufferCanRead(buffer_handles[0], member) == pdTRUE) { + //No-split buffer + receive_check_and_return_item_no_split(buffer_handles[0], small_item, SMALL_ITEM_SIZE, 0, false); + items_rec_count[0] ++; + } else if (xRingbufferCanRead(buffer_handles[1], member) == pdTRUE) { + //Allow-split buffer + receive_check_and_return_item_allow_split(buffer_handles[1], small_item, SMALL_ITEM_SIZE, 0, false); + items_rec_count[1] ++; + } else if (xRingbufferCanRead(buffer_handles[2], member) == pdTRUE){ + //Byte buffer + receive_check_and_return_item_byte_buffer(buffer_handles[2], small_item, SMALL_ITEM_SIZE, 0, false); + items_rec_count[2] ++; + } else { + TEST_ASSERT_MESSAGE( false, "Error with queue set member"); + } + + //Check for completion + if (items_rec_count[0] == no_of_items && + items_rec_count[1] == no_of_items && + items_rec_count[2] == no_of_items) { + done = pdTRUE; + } + } + + xSemaphoreGive(done_sem); + vTaskDelete(NULL); +} + +TEST_CASE("Test ring buffer with queue sets", "[freertos]") +{ + QueueSetHandle_t queue_set = xQueueCreateSet(NO_OF_RB_TYPES); + done_sem = xSemaphoreCreateBinary(); + + //Create ring buffer of each type, then add them to a queue set + for (int i = 0; i < NO_OF_RB_TYPES; i++) { + buffer_handles[i] = xRingbufferCreate(BUFFER_SIZE, i); + TEST_ASSERT_MESSAGE(buffer_handles[i] != NULL, "Failed to create ring buffer"); + TEST_ASSERT_MESSAGE(xRingbufferAddToQueueSetRead(buffer_handles[i], queue_set) == pdPASS, "Failed to add to read queue set"); + } + //Create a task to send items to each ring buffer + int no_of_items = BUFFER_SIZE / SMALL_ITEM_SIZE; + xTaskCreatePinnedToCore(queue_set_receiving_task, "rec tsk", 2048, (void *)queue_set, UNITY_FREERTOS_PRIORITY + 1 , NULL, 0); + + //Send multiple items to each type of ring buffer + for (int i = 0; i < no_of_items; i++) { + for (int j = 0; j < NO_OF_RB_TYPES; j++) { + send_item_and_check(buffer_handles[j], small_item, SMALL_ITEM_SIZE, TIMEOUT_TICKS, false); + } + } + + xSemaphoreTake(done_sem, portMAX_DELAY); + vSemaphoreDelete(done_sem); + //Remove and delete ring buffers from queue sets + for (int i = 0; i < NO_OF_RB_TYPES; i++) { + TEST_ASSERT_MESSAGE(xRingbufferRemoveFromQueueSetRead(buffer_handles[i], queue_set) == pdTRUE, "Failed to remove from read queue set"); + vRingbufferDelete(buffer_handles[i]); + } + vQueueDelete(queue_set); +} + +/* -------------------------- Test ring buffer ISR ----------------------------- + * The following test case tests ring buffer ISR API. A timer is used to trigger + * the ISR. The test case will do the following + * 1) ISR will be triggered periodically by timer + * 2) The ISR will iterate through all ring buffer types where each iteration + * will send then receive an item to a ring buffer. + */ + +#define TIMER_GROUP 0 +#define TIMER_NUMBER 0 +#define ISR_ITERATIONS ((BUFFER_SIZE / SMALL_ITEM_SIZE) * 2) + +intr_handle_t ringbuffer_isr_handle; +static int buf_type; +static int iterations; + +static void ringbuffer_isr(void *arg) +{ + //Clear timer interrupt + TIMERG0.int_clr_timers.t0 = 1; + TIMERG0.hw_timer[xPortGetCoreID()].config.alarm_en = 1; + + //Test sending to buffer from ISR from ISR + if (buf_type < NO_OF_RB_TYPES) { + send_item_and_check(buffer_handles[buf_type], (void *)small_item, SMALL_ITEM_SIZE, 0, true); + } + + //Receive item from ISR + if (buf_type == RINGBUF_TYPE_NOSPLIT) { + //Test receive from ISR for no-split buffer + receive_check_and_return_item_no_split(buffer_handles[buf_type], (void *)small_item, SMALL_ITEM_SIZE, 0, true); + buf_type++; + } else if (buf_type == RINGBUF_TYPE_ALLOWSPLIT) { + //Test send from ISR to allow-split buffer + receive_check_and_return_item_allow_split(buffer_handles[buf_type], (void *)small_item, SMALL_ITEM_SIZE, 0, true); + buf_type++; + } else if (buf_type == RINGBUF_TYPE_BYTEBUF) { + //Test receive from ISR for byte buffer + receive_check_and_return_item_byte_buffer(buffer_handles[buf_type], (void *)small_item, SMALL_ITEM_SIZE, 0, true); + buf_type++; + } else if (buf_type == NO_OF_RB_TYPES) { + //Check if all iterations complete + if (iterations < ISR_ITERATIONS) { + iterations++; + buf_type = 0; //Reset and iterate through each buffer type again + return; + } else { + //Signal complete + BaseType_t task_woken = pdFALSE; + xSemaphoreGiveFromISR(done_sem, &task_woken); + if (task_woken == pdTRUE) { + buf_type++; + portYIELD_FROM_ISR(); + } + } + } +} + +static void setup_timer() +{ + //Setup timer for ISR + int timer_group = TIMER_GROUP; + int timer_idx = TIMER_NUMBER; + timer_config_t config; + config.alarm_en = 1; + config.auto_reload = 1; + config.counter_dir = TIMER_COUNT_UP; + config.divider = 10000; + config.intr_type = TIMER_INTR_LEVEL; + config.counter_en = TIMER_PAUSE; + timer_init(timer_group, timer_idx, &config); //Configure timer + timer_pause(timer_group, timer_idx); //Stop timer counter + timer_set_counter_value(timer_group, timer_idx, 0x00000000ULL); //Load counter value + timer_set_alarm_value(timer_group, timer_idx, 20); //Set alarm value + timer_enable_intr(timer_group, timer_idx); //Enable timer interrupt + timer_set_auto_reload(timer_group, timer_idx, 1); //Auto Reload + timer_isr_register(timer_group, timer_idx, ringbuffer_isr, NULL, 0, &ringbuffer_isr_handle); //Set ISR handler +} + +static void cleanup_timer() +{ + timer_disable_intr(TIMER_GROUP, TIMER_NUMBER); + esp_intr_free(ringbuffer_isr_handle); +} + +TEST_CASE("Test ring buffer ISR", "[freertos]") +{ + for (int i = 0; i < NO_OF_RB_TYPES; i++) { + buffer_handles[i] = xRingbufferCreate(BUFFER_SIZE, i); + } + done_sem = xSemaphoreCreateBinary(); + buf_type = 0; + iterations = 0; + setup_timer(); + //Start timer to trigger ISR + timer_start(TIMER_GROUP, TIMER_NUMBER); + //Wait for ISR to complete multiple iterations + xSemaphoreTake(done_sem, portMAX_DELAY); + + //Cleanup + cleanup_timer(); + vSemaphoreDelete(done_sem); + for (int i = 0; i < NO_OF_RB_TYPES; i++) { + vRingbufferDelete(buffer_handles[i]); + } +} + +/* ---------------------------- Test ring buffer SMP --------------------------- + * The following test case tests each type of ring buffer in an SMP fashion. A + * sending task and a receiving task is created. The sending task will split + * a continuous piece of data into items of random length and send it to a ring + * buffer. The receiving task will receive and check those items. + * Every permutation of core pinning of the sending and receiving task will be + * tested. + */ + +#define SRAND_SEED 3 //Arbitrarily chosen srand() seed +#define SMP_TEST_ITERATIONS 4 + +static const char continuous_data[] = {"A_very_long_string_that_will_be_split_into_" + "items_of_random_lengths_and_sent_to_the_ring_" + "buffer._The_maximum_random_length_will_also_" + "be_increased_over_multiple_iterations_in_this" + "_test"}; +#define CONT_DATA_LEN sizeof(continuous_data) +#define CONT_DATA_TEST_BUFF_LEN (CONT_DATA_LEN/2) //This will guarantee that the buffer must do a wrap around at some point + +typedef struct { + RingbufHandle_t buffer; + ringbuf_type_t type; +} task_args_t; + +static SemaphoreHandle_t tasks_done; +static SemaphoreHandle_t tx_done; +static SemaphoreHandle_t rx_done; + +static void send_to_buffer(RingbufHandle_t buffer, size_t max_item_size) +{ + for (int iter = 0; iter < SMP_TEST_ITERATIONS; iter++) { + size_t bytes_sent = 0; //Number of data bytes sent in this iteration + size_t next_item_size; //Size of next item to send + + while (bytes_sent < CONT_DATA_LEN) { + //Get size of next item + next_item_size = rand() % (max_item_size + 1); + if (next_item_size + bytes_sent > CONT_DATA_LEN) { + next_item_size = CONT_DATA_LEN - bytes_sent; + } + + //Send item + TEST_ASSERT_MESSAGE(xRingbufferSend(buffer, (void *)&(continuous_data[bytes_sent]), next_item_size, TIMEOUT_TICKS) == pdTRUE, "Failed to send an item"); + bytes_sent += next_item_size; + } + xSemaphoreGive(tx_done); + xSemaphoreTake(rx_done, portMAX_DELAY); + } +} + +static void read_from_buffer(RingbufHandle_t buffer, ringbuf_type_t buf_type, size_t max_rec_size) +{ + for (int iter = 0; iter < SMP_TEST_ITERATIONS; iter++) { + size_t bytes_rec = 0; //Number of data bytes received in this iteration + while (bytes_rec < CONT_DATA_LEN) { + size_t item_size, item_size2; //Possible for allow split buffers to receive two items + char *item_data, *item_data2; + + //Select appropriate receive function for type of ring buffer + if (buf_type == RINGBUF_TYPE_NOSPLIT) { + item_data = (char *)xRingbufferReceive(buffer, &item_size, TIMEOUT_TICKS); + } else if (buf_type == RINGBUF_TYPE_ALLOWSPLIT) { + BaseType_t ret = xRingbufferReceiveSplit(buffer, (void **)&item_data, (void **)&item_data2, &item_size, &item_size2, TIMEOUT_TICKS); + TEST_ASSERT_MESSAGE(ret == pdTRUE, "Failed to receive any item"); + } else { + item_data = (char *)xRingbufferReceiveUpTo(buffer, &item_size, TIMEOUT_TICKS, max_rec_size); + } + + //Check received item and return it + TEST_ASSERT_MESSAGE(item_data != NULL, "Failed to receive an item"); + if (buf_type == RINGBUF_TYPE_BYTEBUF) { + TEST_ASSERT_MESSAGE(item_size <= max_rec_size, "Received data exceeds max size"); + } + for (int i = 0; i < item_size; i++) { + //Check item_data is valid + TEST_ASSERT_MESSAGE(item_data[i] == continuous_data[bytes_rec + i], "Received data is corrupted"); + } + bytes_rec += item_size; + vRingbufferReturnItem(buffer, item_data); + if (buf_type == RINGBUF_TYPE_ALLOWSPLIT && item_data2 != NULL) { + //Check item_data2 is valid + for (int i = 0; i < item_size2; i++) { + TEST_ASSERT_MESSAGE(item_data2[i] == continuous_data[bytes_rec + i], "Received split data is corrupted"); + } + bytes_rec += item_size2; + vRingbufferReturnItem(buffer, item_data2); + } + } + TEST_ASSERT_MESSAGE(bytes_rec == CONT_DATA_LEN, "Total length of received data is incorrect"); + xSemaphoreGive(rx_done); + xSemaphoreTake(tx_done, portMAX_DELAY); + } +} + +static void send_task(void *args) +{ + RingbufHandle_t buffer = ((task_args_t *)args)->buffer; + size_t max_item_len = xRingbufferGetMaxItemSize(buffer); + + //Test sending short length items + send_to_buffer(buffer, 1); + //Test sending mid length items + send_to_buffer(buffer, max_item_len/2); + //Test sending long length items + send_to_buffer(buffer, max_item_len); + vTaskDelete(NULL); +} + +static void rec_task(void *args) +{ + RingbufHandle_t buffer = ((task_args_t *)args)->buffer; + size_t max_rec_len = xRingbufferGetMaxItemSize(buffer); + + //Test receiving short length items + read_from_buffer(buffer, ((task_args_t *)args)->type, 1); + //Test receiving mid length items + read_from_buffer(buffer, ((task_args_t *)args)->type, max_rec_len/2); + //Test receiving long length items + read_from_buffer(buffer, ((task_args_t *)args)->type, max_rec_len); + + xSemaphoreGive(tasks_done); + vTaskDelete(NULL); +} + +TEST_CASE("Test ring buffer SMP", "[freertos]") +{ + ets_printf("size of buf %d\n", CONT_DATA_LEN); + tx_done = xSemaphoreCreateBinary(); //Semaphore to indicate send is done for a particular iteration + rx_done = xSemaphoreCreateBinary(); //Semaphore to indicate receive is done for a particular iteration + tasks_done = xSemaphoreCreateBinary(); //Semaphore used to to indicate send and receive tasks completed running + srand(SRAND_SEED); //Seed RNG + + //Iterate through buffer types (No split, split, then byte buff) + for (ringbuf_type_t buf_type = 0; buf_type <= RINGBUF_TYPE_BYTEBUF; buf_type++) { + //Create buffer + task_args_t task_args; + task_args.buffer = xRingbufferCreate(CONT_DATA_TEST_BUFF_LEN, buf_type); //Create buffer of selected type + task_args.type = buf_type; + + for (int prior_mod = -1; prior_mod < 2; prior_mod++) { //Test different relative priorities + //Test every permutation of core affinity + for (int send_core = 0; send_core < portNUM_PROCESSORS; send_core++) { + for (int rec_core = 0; rec_core < portNUM_PROCESSORS; rec_core ++) { + ets_printf("Type: %d, PM: %d, SC: %d, RC: %d\n", buf_type, prior_mod, send_core, rec_core); + xTaskCreatePinnedToCore(send_task, "send tsk", 2048, (void *)&task_args, 10 + prior_mod, NULL, send_core); + xTaskCreatePinnedToCore(rec_task, "rec tsk", 2048, (void *)&task_args, 10, NULL, rec_core); + xSemaphoreTake(tasks_done, portMAX_DELAY); + vTaskDelay(5); //Allow idle to clean up + } + } + } + + //Delete ring buffer + vRingbufferDelete(task_args.buffer); + vTaskDelay(10); + } + + //Cleanup + vSemaphoreDelete(tx_done); + vSemaphoreDelete(rx_done); + vSemaphoreDelete(tasks_done); +} diff --git a/docs/_static/diagrams/ring-buffer/ring_buffer_read_ret_byte_buf.diag b/docs/_static/diagrams/ring-buffer/ring_buffer_read_ret_byte_buf.diag new file mode 100644 index 0000000000..9ad33b05f4 --- /dev/null +++ b/docs/_static/diagrams/ring-buffer/ring_buffer_read_ret_byte_buf.diag @@ -0,0 +1,30 @@ +#Diagram demonstrating reading and returning an item in a byte buffer +#Buffer of 128 bytes, with 68 bytes occupied but wrapped. All data is read + +packetdiag ring_buffer_read_ret_byte_buf { + node_width = 6 + node_height = 24 + default_fontsize = 12 + colwidth = 128 + + #Initial + 0-29: 30 [color = lightyellow]; + 30-89: 60 Free + 90-127: 38 [color = lightyellow]; + + #Read all continuous data + 128-157: 30 [color = lightyellow]; + 158-217: 60 Free + 218-255: 38 [color = pink]; + + #Return data + 256-285: 30 [color = lightyellow]; + 286-383: 98 Free + + #Read remaining data + 384-413: 30 [color = pink]; + 414-511: 98 Free + + #Return data + 512-639: 128 Free +} \ No newline at end of file diff --git a/docs/_static/diagrams/ring-buffer/ring_buffer_read_ret_non_byte_buf.diag b/docs/_static/diagrams/ring-buffer/ring_buffer_read_ret_non_byte_buf.diag new file mode 100644 index 0000000000..a7773b9910 --- /dev/null +++ b/docs/_static/diagrams/ring-buffer/ring_buffer_read_ret_non_byte_buf.diag @@ -0,0 +1,86 @@ +#Diagram demonstrating reading and returning an item in a No-Split/Allow-Split ring buffer +#Buffer of 128 bytes, with 4 items of 16, 20, 8 and 24 bytes. First 3 items are read and returned + +packetdiag ring_buffer_read_ret_non_byte_buf { + node_width = 6 + node_height = 24 + default_fontsize = 12 + colwidth = 128 + + #Initial + 0-7: 8 [color = lightblue]; + 8-23: 16 [color = lightyellow]; + 24-31: 8 [color = lightblue]; + 32-51: 20 [color = lightyellow]; + 52-59: 8 [color = lightblue]; + 60-67: 8 [color = lightyellow]; + 68-75: 8 [color = lightblue]; + 76-99: 24 [color = lightyellow]; + 100-127: 28 Free + + #Read item 1 + 128-135: 8 [color = pink]; + 136-151: 16 [color = pink]; + 152-159: 8 [color = lightblue]; + 160-179: 20 [color = lightyellow]; + 180-187: 8 [color = lightblue]; + 188-195: 8 [color = lightyellow]; + 196-203: 8 [color = lightblue]; + 204-227: 24 [color = lightyellow]; + 228-255: 28 Free + + #Read item 2 + 256-263: 8 [color = pink]; + 264-279: 16 [color = pink]; + 280-287: 8 [color = pink]; + 288-307: 20 [color = pink]; + 308-315: 8 [color = lightblue]; + 316-323: 8 [color = lightyellow]; + 324-331: 8 [color = lightblue]; + 332-355: 24 [color = lightyellow]; + 356-383: 28 Free + + #Read item 3 + 384-391: 8 [color = pink]; + 392-407: 16 [color = pink]; + 408-415: 8 [color = pink]; + 416-435: 20 [color = pink]; + 436-443: 8 [color = pink]; + 444-451: 8 [color = pink]; + 452-459: 8 [color = lightblue]; + 460-483: 24 [color = lightyellow]; + 484-511: 28 Free + + #Return item 2 + 512-519: 8 [color = pink]; + 520-535: 16 [color = pink]; + 536-563: Ret [color = lightgrey]; + 564-571: 8 [color = pink]; + 572-579: 8 [color = pink]; + 580-587: 8 [color = lightblue]; + 588-611: 24 [color = lightyellow]; + 612-639: 28 Free + + #Return item 3 + 640-647: 8 [color = pink]; + 648-663: 16 [color = pink]; + 664-691: Ret [color = lightgrey]; + 692-707: Ret [color = lightgrey]; + 708-715: 8 [color = lightblue]; + 716-739: 24 [color = lightyellow]; + 740-767: 28 Free + + #Return item 1 + 768-791: Ret [color = lightgrey]; + 792-819: Ret [color = lightgrey]; + 820-835: Ret [color = lightgrey]; + 836-843: 8 [color = lightblue]; + 844-867: 24 [color = lightyellow]; + 868-895: 28 Free + + #End state + 896-963: 68 Free + 964-971: 8 [color = lightblue]; + 972-995: 24 [color = lightyellow]; + 996-1023: 28 Free +} \ No newline at end of file diff --git a/docs/_static/diagrams/ring-buffer/ring_buffer_send_byte_buf.diag b/docs/_static/diagrams/ring-buffer/ring_buffer_send_byte_buf.diag new file mode 100644 index 0000000000..9bac570422 --- /dev/null +++ b/docs/_static/diagrams/ring-buffer/ring_buffer_send_byte_buf.diag @@ -0,0 +1,21 @@ +#Diagram demonstrating sending in byte buffer +#Buffer of 128 bytes, and 3 items of size 18, 3, and 27 bytes sent + +packetdiag ring_buffer_send_byte_buf { + node_width = 6 + node_height = 24 + default_fontsize = 12 + colwidth = 128 + + #Add 18 byte item + 0-17: 18 [color = lightyellow]; + 18-127: 110 Free + + #Add 3 byte item + 128-148: 21 [color = lightyellow]; + 149-255: 107 Free + + #Add 27 byte item + 256-303: 48 [color = lightyellow]; + 304-383: 80 Free +} \ No newline at end of file diff --git a/docs/_static/diagrams/ring-buffer/ring_buffer_send_non_byte_buf.diag b/docs/_static/diagrams/ring-buffer/ring_buffer_send_non_byte_buf.diag new file mode 100644 index 0000000000..25cb71e797 --- /dev/null +++ b/docs/_static/diagrams/ring-buffer/ring_buffer_send_non_byte_buf.diag @@ -0,0 +1,30 @@ +#Diagram demonstrating sending in a No-Split/Allow-Split ring buffer +#Buffer of 128 bytes, and 3 items of size 18, 3, and 27 bytes sent + +packetdiag ring_buffer_send_non_byte_buf { + node_width = 6 + node_height = 24 + default_fontsize = 12 + colwidth = 128 + + #Add 18 byte item + 0-7: 8 [color = lightblue]; + 8-27: 20 [color = lightyellow]; + 28-127: 100 Free + + #Add 3 byte item + 128-135: 8 [color = lightblue]; + 136-155: 20 [color = lightyellow]; + 156-163: 8 [color = lightblue]; + 164-167: 4 [color = lightyellow]; + 168-255: 88 Free + + #Add 27 byte item + 256-263: 8 [color = lightblue]; + 264-283: 20 [color = lightyellow]; + 284-291: 8 [color = lightblue]; + 292-295: 4 [color = lightyellow]; + 296-303: 8 [color = lightblue]; + 304-331: 28 [color = lightyellow]; + 332-383: 52 Free +} \ No newline at end of file diff --git a/docs/_static/diagrams/ring-buffer/ring_buffer_wrap_allow_split.diag b/docs/_static/diagrams/ring-buffer/ring_buffer_wrap_allow_split.diag new file mode 100644 index 0000000000..94e26e87a9 --- /dev/null +++ b/docs/_static/diagrams/ring-buffer/ring_buffer_wrap_allow_split.diag @@ -0,0 +1,37 @@ +#Diagram demonstrating wrap around in a Allow-Split ring buffer +#Buffer of 128 bytes, with 56 bytes free, and 28 bytes sent + +packetdiag ring_buffer_wrap_allow_split { + node_width = 6 + node_height = 24 + default_fontsize = 12 + colwidth = 128 + + #Initial state + 0-39: 40 Free + 40-47: 8 [color = lightblue]; + 48-63: 16 [color = lightyellow]; + 64-71: 8 [color = lightblue]; + 72-111: 40 [color = lightyellow]; + 112-127: 16 Free + + #Send first part + 128-167: 40 Free + 168-175: 8 [color = lightblue]; + 176-191: 16 [color = lightyellow]; + 192-199: 8 [color = lightblue]; + 200-239: 40 [color = lightyellow]; + 240-247: 8 [color = lightblue]; + 248-255: 8 [color = lightyellow]; + + #Send second part + 256-263: 8 [color = lightblue]; + 264-283: 20 [color = lightyellow]; + 284-295: 12 Free + 296-303: 8 [color = lightblue]; + 304-319: 16 [color = lightyellow]; + 320-327: 8 [color = lightblue]; + 328-367: 40 [color = lightyellow]; + 368-375: 8 [color = lightblue]; + 376-383: 8 [color = lightyellow]; +} \ No newline at end of file diff --git a/docs/_static/diagrams/ring-buffer/ring_buffer_wrap_byte_buf.diag b/docs/_static/diagrams/ring-buffer/ring_buffer_wrap_byte_buf.diag new file mode 100644 index 0000000000..bf693779da --- /dev/null +++ b/docs/_static/diagrams/ring-buffer/ring_buffer_wrap_byte_buf.diag @@ -0,0 +1,23 @@ +#Diagram demonstrating wrap around in byte buffer +#Buffer of 128 bytes, with 56 bytes free, and 28 bytes sent + +packetdiag ring_buffer_wrap_byte_buf { + node_width = 6 + node_height = 24 + default_fontsize = 12 + colwidth = 128 + + #Initial state + 0-39: 40 Free + 40-111: 72 [color = lightyellow]; + 112-127: 16 Free + + #Fill up free space at the end of the buffer + 128-167: 40 Free + 168-255: 88 [color = lightyellow]; + + #Wrap around remaining data + 256-267: 12 [color = lightyellow]; + 268-295: 28 Free + 296-383: 88 [color = lightyellow]; +} \ No newline at end of file diff --git a/docs/_static/diagrams/ring-buffer/ring_buffer_wrap_no_split.diag b/docs/_static/diagrams/ring-buffer/ring_buffer_wrap_no_split.diag new file mode 100644 index 0000000000..ff4a11a8fb --- /dev/null +++ b/docs/_static/diagrams/ring-buffer/ring_buffer_wrap_no_split.diag @@ -0,0 +1,35 @@ +#Diagram demonstrating wrap around in a No-Split ring buffer +#Buffer of 128 bytes, with 56 bytes free, and 28 bytes sent + +packetdiag ring_buffer_wrap_no_split { + node_width = 6 + node_height = 24 + default_fontsize = 12 + colwidth = 128 + + #Initial state + 0-39: 40 Free + 40-47: 8 [color = lightblue]; + 48-63: 16 [color = lightyellow]; + 64-71: 8 [color = lightblue]; + 72-111: 40 [color = lightyellow]; + 112-127: 16 Free + + #Set dummy data + 128-167: 40 Free + 168-175: 8 [color = lightblue]; + 176-191: 16 [color = lightyellow]; + 192-199: 8 [color = lightblue]; + 200-239: 40 [color = lightyellow]; + 240-255: Dummy [color = lightgrey]; + + #Send wrap around item + 256-263: 8 [color = lightblue]; + 264-291: 28 [color = lightyellow]; + 292-295: 4 Free + 296-303: 8 [color = lightblue]; + 304-319: 16 [color = lightyellow]; + 320-327: 8 [color = lightblue]; + 328-367: 40 [color = lightyellow]; + 368-383: Dummy [color = lightgrey]; +} \ No newline at end of file diff --git a/docs/en/api-guides/freertos-smp.rst b/docs/en/api-guides/freertos-smp.rst index 9851929af7..40665d9c5b 100644 --- a/docs/en/api-guides/freertos-smp.rst +++ b/docs/en/api-guides/freertos-smp.rst @@ -16,6 +16,9 @@ of FreeRTOS v8.2.0. This guide outlines the major differences between vanilla FreeRTOS and ESP-IDF FreeRTOS. The API reference for vanilla FreeRTOS can be found via http://www.freertos.org/a00106.html +For information regarding features that are exclusive to ESP-IDF FreeRTOS, +see :doc:`ESP-IDF FreeRTOS Additions<../api-reference/system/freertos_additions>`. + :ref:`backported-features`: Although ESP-IDF FreeRTOS is based on the Xtensa port of FreeRTOS v8.2.0, a number of FreeRTOS v9.0.0 features have been backported to ESP-IDF. @@ -70,10 +73,6 @@ used to free memory pointed to by TLSP. Call :cpp:func:`vTaskSetThreadLocalStoragePointerAndDelCallback()` to set TLSP and Deletion Callbacks. -:ref:`FreeRTOS Hooks`: Vanilla FreeRTOS Hooks were not designed for SMP. -ESP-IDF provides its own Idle and Tick Hooks in addition to the Vanilla FreeRTOS -hooks. For full details, see the ESP-IDF Hooks API Reference. - :ref:`esp-idf-freertos-configuration`: Several aspects of ESP-IDF FreeRTOS can be configured using ``make meunconfig`` such as running ESP-IDF in Unicore Mode, or configuring the number of Thread Local Storage Pointers each task will have. diff --git a/docs/en/api-reference/system/freertos.rst b/docs/en/api-reference/system/freertos.rst index 2b0b0929fb..f5b2b8dc00 100644 --- a/docs/en/api-reference/system/freertos.rst +++ b/docs/en/api-reference/system/freertos.rst @@ -6,7 +6,8 @@ Overview This section contains documentation of FreeRTOS types, functions, and macros. It is automatically generated from FreeRTOS header files. -For more information about FreeRTOS features specific to ESP-IDF, see :doc:`ESP-IDF FreeRTOS SMP Changes<../../api-guides/freertos-smp>`. +For more information about FreeRTOS features specific to ESP-IDF, see :doc:`ESP-IDF FreeRTOS SMP Changes<../../api-guides/freertos-smp>` +and :doc:`ESP-IDF FreeRTOS Additions`. Task API @@ -35,8 +36,4 @@ Event Group API .. include:: /_build/inc/event_groups.inc -Ringbuffer API --------------- - -.. include:: /_build/inc/ringbuf.inc diff --git a/docs/en/api-reference/system/freertos_additions.rst b/docs/en/api-reference/system/freertos_additions.rst new file mode 100644 index 0000000000..57d25e9a79 --- /dev/null +++ b/docs/en/api-reference/system/freertos_additions.rst @@ -0,0 +1,403 @@ +FreeRTOS Additions +================== + +Overview +-------- + +ESP-IDF FreeRTOS is based on the Xtensa port of FreeRTOS v8.2.0 with significant modifications +for SMP compatibility (see :doc:`ESP-IDF FreeRTOS SMP Changes<../../api-guides/freertos-smp>`). +However various features specific to ESP-IDF FreeRTOS have been added. The features are as follows: + +:ref:`ring-buffers`: Ring buffers were added to provide a form of buffer that could accept +entries of arbitrary lengths. + +:ref:`hooks`: ESP-IDF FreeRTOS hooks provides support for registering extra Idle and +Tick hooks at run time. Moreover, the hooks can be asymmetric amongst both CPUs. + + +.. _ring-buffers: + +Ring Buffers +------------ + +The ESP-IDF FreeRTOS ring buffer is a strictly FIFO buffer that supports arbitrarily sized items. +Ring buffers are a more memory efficient alternative to FreeRTOS queues in situations where the +size of items is variable. The capacity of a ring buffer is not measured by the number of items +it can store, but rather by the amount of memory used for storing items. Items are sent to +ring buffers by copy, however for efficiency reasons **items are retrieved by reference**. As a +result, all retrieved items **must also be returned** in order for them to be removed from +the ring buffer completely. The ring buffers are split into the three following types: + +**No-Split** buffers will guarantee that an item is stored in contiguous memory and will not +attempt to split an item under any circumstances. Use no-split buffers when items must occupy +contiguous memory. + +**Allow-Split** buffers will allow an item to be split when wrapping around if doing so will allow +the item to be stored. Allow-split buffers are more memory efficient than no-split buffers but +can return an item in two parts when retrieving. + +**Byte buffers** do not store data as separate items. All data is stored as a sequence of bytes, +and any number of bytes and be sent or retrieved each time. Use byte buffers when separate items +do not need to be maintained (e.g. a byte stream). + +.. note:: + No-split/allow-split buffers will always store items at 32-bit aligned addresses. Therefore when + retrieving an item, the item pointer is guaranteed to be 32-bit aligned. + +.. note:: + Each item stored in no-split/allow-split buffers will **require an additional 8 bytes for a header**. + Item sizes will also be rounded up to a 32-bit aligned size (multiple of 4 bytes), however the true + item size is recorded within the header. The sizes of no-split/allow-split buffers will also + be rounded up when created. + +Usage +^^^^^ + +The following example demonstrates the usage of :cpp:func:`xRingbufferCreate` +and :cpp:func:`xRingbufferSend` to create a ring buffer then send an item to it. + +.. code-block:: c + + #include "freertos/ringbuf.h" + static char tx_item[] = "test_item"; + + ... + + //Create ring buffer + RingbufHandle_t buf_handle; + buf_handle = xRingbufferCreate(1028, RINGBUF_TYPE_NOSPLIT); + if (buf_handle == NULL) { + printf("Failed to create ring buffer\n"); + } + + //Send an item + UBaseType_t res = xRingbufferSend(buf_handle, tx_item, sizeof(tx_item), pdMS_TO_TICKS(1000)); + if (res != pdTRUE) { + printf("Failed to send item\n"); + } + + +The following example demonstrates retrieving and returning an item from a **no-split ring buffer** +using :cpp:func:`xRingbufferReceive` and :cpp:func:`vRingbufferReturnItem` + +.. code-block:: c + + ... + + //Receive an item from no-split ring buffer + size_t item_size; + char *item = (char *)xRingbufferReceive(buf_handle, &item_size, pdMS_TO_TICKS(1000)); + + //Check received item + if (item != NULL) { + //Print item + for (int i = 0; i < item_size; i++) { + printf("%c", item[i]); + } + printf("\n"); + //Return Item + vRingbufferReturnItem(buf_handle, (void *)item); + } else { + //Failed to receive item + printf("Failed to receive item\n"); + } + + +The following example demonstrates retrieving and returning an item from an **allow-split ring buffer** +using :cpp:func:`xRingbufferReceiveSplit` and :cpp:func:`vRingbufferReturnItem` + +.. code-block:: c + + ... + + //Receive an item from allow-split ring buffer + size_t item_size1, item_size2; + char *item1, *item2; + BaseType_t ret = xRingbufferReceiveSplit(buf_handle, (void **)&item1, (void **)&item2, &item_size1, &item_size2, pdMS_TO_TICKS(1000)); + + //Check received item + if (ret == pdTRUE && item1 != NULL) { + for (int i = 0; i < item_size1; i++) { + printf("%c", item1[i]); + } + vRingbufferReturnItem(buf_handle, (void *)item1); + //Check if item was split + if (item2 != NULL) { + for (int i = 0; i < item_size2; i++) { + printf("%c", item2[i]); + } + vRingbufferReturnItem(buf_handle, (void *)item2); + } + printf("\n"); + } else { + //Failed to receive item + printf("Failed to receive item\n"); + } + + +The following example demonstrates retrieving and returning an item from a **byte buffer** +using :cpp:func:`xRingbufferReceiveUpTo` and :cpp:func:`vRingbufferReturnItem` + +.. code-block:: c + + ... + + //Receive data from byte buffer + size_t item_size; + char *item = (char *)xRingbufferReceiveUpTo(buf_handle, &item_size, pdMS_TO_TICKS(1000), sizeof(tx_item)); + + //Check received data + if (item != NULL) { + //Print item + for (int i = 0; i < item_size; i++) { + printf("%c", item[i]); + } + printf("\n"); + //Return Item + vRingbufferReturnItem(buf_handle, (void *)item); + } else { + //Failed to receive item + printf("Failed to receive item\n"); + } + + +For ISR safe versions of the functions used above, call :cpp:func:`xRingbufferSendFromISR`, :cpp:func:`xRingbufferReceiveFromISR`, +:cpp:func:`xRingbufferReceiveSplitFromISR`, :cpp:func:`xRingbufferReceiveUpToFromISR`, and :cpp:func:`vRingbufferReturnItemFromISR` + + +Sending to Ring Buffer +^^^^^^^^^^^^^^^^^^^^^^ + +The following diagrams illustrate the differences between no-split/allow-split buffers +and byte buffers with regards to sending items/data. The diagrams assume that three +items of sizes **18, 3, and 27 bytes** are sent respectively to a **buffer of 128 bytes**. + +.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_send_non_byte_buf.diag + :caption: Sending items to no-split/allow-split ring buffers + :align: center + +For no-split/allow-split buffers, a header of 8 bytes precedes every data item. Furthermore, the space +occupied by each item is **rounded up to the nearest 32-bit aligned size** in order to maintain overall +32-bit alignment. However the true size of the item is recorded inside the header which will be +returned when the item is retrieved. + +Referring to the diagram above, the 18, 3, and 27 byte items are **rounded up to 20, 4, and 28 bytes** +respectively. An 8 byte header is then added in front of each item. + +.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_send_byte_buf.diag + :caption: Sending items to byte buffers + :align: center + +Byte buffers treat data as a sequence of bytes and does not incur any overhead +(no headers). As a result, all data sent to a byte buffer is merged into a single item. + +Referring to the diagram above, the 18, 3, and 27 byte items are sequentially written to the +byte buffer and **merged into a single item of 48 bytes**. + +Wrap around +^^^^^^^^^^^ + +The following diagrams illustrate the differences between no-split, allow-split, and byte +buffers when a sent item requires a wrap around. The diagrams assumes a buffer of **128 bytes** +with **56 bytes of free space that wraps around** and a sent item of **28 bytes**. + +.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_wrap_no_split.diag + :caption: Wrap around in no-split buffers + :align: center + +No-split buffers will **only store an item in continuous free space and will not split +an item under any circumstances**. When the free space at the tail of the buffer is insufficient +to completely store the item and its header, the free space at the tail will be **marked as dummy data**. +The buffer will then wrap around and store the item in the free space at the head of the buffer. + +Referring to the diagram above, the 16 bytes of free space at the tail of the buffer is +insufficient to store the 28 byte item. Therefore the 16 bytes is marked as dummy data and +the item is written to the free space at the head of the buffer instead. + +.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_wrap_allow_split.diag + :caption: Wrap around in allow-split buffers + :align: center + +Allow-split buffers will attempt to **split the item into two parts** when the free space at the tail +of the buffer is insufficient to store the item data and its header. Both parts of the +split item will have their own headers (therefore incurring an extra 8 bytes of overhead). + +Referring to the diagram above, the 16 bytes of free space at the tail of the buffer is insufficient +to store the 28 byte item. Therefore the item is split into two parts (8 and 20 bytes) and written +as two parts to the buffer. + +.. note:: + Allow-split buffers treats the both parts of the split item as two separate items, therefore call + :cpp:func:`xRingbufferReceiveSplit` instead of :cpp:func:`xRingbufferReceive` to receive both + parts of a split item in a thread safe manner. + +.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_wrap_byte_buf.diag + :caption: Wrap around in byte buffers + :align: center + +Byte buffers will **store as much data as possible into the free space at the tail of buffer**. The remaining +data will then be stored in the free space at the head of the buffer. No overhead is incurred when wrapping +around in byte buffers. + +Referring to the diagram above, the 16 bytes of free space at the tail of the buffer is insufficient to +completely store the 28 bytes of data. Therefore the 16 bytes of free space is filled with data, and the +remaining 12 bytes are written to the free space at the head of the buffer. The buffer now contains +data in two separate continuous parts, and each part continuous will be treated as a separate item by the +byte buffer. + +Retrieving/Returning +^^^^^^^^^^^^^^^^^^^^ + +The following diagrams illustrates the differences between no-split/allow-split and +byte buffers in retrieving and returning data. + +.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_read_ret_non_byte_buf.diag + :caption: Retrieving/Returning items in no-split/allow-split ring buffers + :align: center + +Items in no-split/allow-split buffers are **retrieved in strict FIFO order** and **must be returned** +for the occupied space to be freed. Multiple items can be retrieved before returning, and the items +do not necessarily need to be returned in the order they were retrieved. However the freeing of space +must occur in FIFO order, therefore not returning the earliest retrieved item will prevent the space +of subsequent items from being freed. + +Referring to the diagram above, the **16, 20, and 8 byte items are retrieved in FIFO order**. However the items +are not returned in they were retrieved (20, 8, 16). As such, the space is not freed until the first item +(16 byte) is returned. + +.. packetdiag:: ../../../_static/diagrams/ring-buffer/ring_buffer_read_ret_byte_buf.diag + :caption: Retrieving/Returning data in byte buffers + :align: center + +Byte buffers **do not allow multiple retrievals before returning** (every retrieval must be followed by a return +before another retrieval is permitted). When using :cpp:func:`xRingbufferReceive` or +:cpp:func:`xRingbufferReceiveFromISR`, all continuous stored data will be retrieved. :cpp:func:`xRingbufferReceiveUpTo` +or :cpp:func:`xRingbufferReceiveUpToFromISR` can be used to restrict the maximum number of bytes retrieved. Since +every retrieval must be followed by a return, the space will be freed as soon as the data is returned. + +Referring to the diagram above, the 38 bytes of continuous stored data at the tail of the buffer is retrieved, +returned, and freed. The next call to :cpp:func:`xRingbufferReceive` or :cpp:func:`xRingbufferReceiveFromISR` +then wraps around and does the same to the 30 bytes of continuous stored data at the head of the buffer. + +Ring Buffers with Queue Sets +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Ring buffers can be added to FreeRTOS queue sets using :cpp:func:`xRingbufferAddToQueueSetRead` such that every +time a ring buffer receives an item or data, the queue set is notified. Once added to a queue set, every +attempt to retrieve an item from a ring buffer should be preceded by a call to :cpp:func:`xQueueSelectFromSet`. +To check whether the selected queue set member is the ring buffer, call :cpp:func:`xRingbufferCanRead`. + +The following example demonstrates queue set usage with ring buffers. + +.. code-block:: c + + #include "freertos/queue.h" + #include "freertos/ringbuf.h" + + ... + + //Create ring buffer and queue set + RingbufHandle_t buf_handle = xRingbufferCreate(1028, RINGBUF_TYPE_NOSPLIT); + QueueSetHandle_t queue_set = xQueueCreateSet(3); + + //Add ring buffer to queue set + if (xRingbufferAddToQueueSetRead(buf_handle, queue_set) != pdTRUE) { + printf("Failed to add to queue set\n"); + } + + ... + + //Block on queue set + xQueueSetMemberHandle member = xQueueSelectFromSet(queue_set, pdMS_TO_TICKS(1000)); + + //Check if member is ring buffer + if (member != NULL && xRingbufferCanRead(buf_handle, member) == pdTRUE) { + //Member is ring buffer, receive item from ring buffer + size_t item_size; + char *item = (char *)xRingbufferReceive(buf_handle, &item_size, 0); + + //Handle item + ... + + } else { + ... + } + + +Ring Buffer API Reference +------------------------- + +.. note:: + Ideally, ring buffers can be used with multiple tasks in an SMP fashion where the **highest + priority task will always be serviced first.** However due to the usage of binary semaphores + in the ring buffer's underlying implementation, priority inversion may occur under very + specific circumstances. + + The ring buffer governs sending by a binary semaphore which is given whenever space is + freed on the ring buffer. The highest priority task waiting to send will repeatedly take + the semaphore until sufficient free space becomes available or until it times out. Ideally + this should prevent any lower priority tasks from being serviced as the semaphore should + always be given to the highest priority task. + + However in between iterations of acquiring the semaphore, there is a **gap in the critical + section** which may permit another task (on the other core or with an even higher priority) to + free some space on the ring buffer and as a result give the semaphore. Therefore the semaphore + will be given before the highest priority task can re-acquire the semaphore. This will result + in the **semaphore being acquired by the second highest priority task** waiting to send, hence + causing priority inversion. + + This side effect will not affect ring buffer performance drastically given if the number + of tasks using the ring buffer simultaneously is low, and the ring buffer is not operating + near maximum capacity. + +.. include:: /_build/inc/ringbuf.inc + + +.. _hooks: + +Hooks +----- + +FreeRTOS consists of Idle Hooks and Tick Hooks which allow for application +specific functionality to be added to the Idle Task and Tick Interrupt. +ESP-IDF provides its own Idle and Tick Hook API in addition to the hooks +provided by Vanilla FreeRTOS. ESP-IDF hooks have the added benefit of +being run time configurable and asymmetrical. + +Vanilla FreeRTOS Hooks +^^^^^^^^^^^^^^^^^^^^^^ + +Idle and Tick Hooks in vanilla FreeRTOS are implemented by the user +defining the functions ``vApplicationIdleHook()`` and ``vApplicationTickHook()`` +respectively somewhere in the application. Vanilla FreeRTOS will run the user +defined Idle Hook and Tick Hook on every iteration of the Idle Task and Tick +Interrupt respectively. + +Vanilla FreeRTOS hooks are referred to as **Legacy Hooks** in ESP-IDF FreeRTOS. +To enable legacy hooks, :ref:`CONFIG_FREERTOS_LEGACY_HOOKS`, +:ref:`CONFIG_FREERTOS_LEGACY_IDLE_HOOK`, and :ref:`CONFIG_FREERTOS_LEGACY_TICK_HOOK` +should all be enabled in ``make menuconfig``. + +Due to vanilla FreeRTOS being designed for single core, ``vApplicationIdleHook()`` +and ``vApplicationTickHook()`` can only be defined once. However, the ESP32 is dual core +in nature, therefore same Idle Hook and Tick Hook are used for both cores (in other words, +the hooks are symmetrical for both cores). + +ESP-IDF Idle and Tick Hooks +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Due to the the dual core nature of the ESP32, it may be necessary for some +applications to have separate hooks for each core. Furthermore, it may +be necessary for the Idle Tasks or Tick Interrupts to execute multiple hooks +that are configurable at run time. Therefore the ESP-IDF provides it's own hooks +API in addition to the legacy hooks provided by Vanilla FreeRTOS. + +The ESP-IDF tick/idle hooks are registered at run time, and each tick/idle hook +must be registered to a specific CPU. When the idle task runs/tick Interrupt +occurs on a particular CPU, the CPU will run each of its registered idle/tick hooks +in turn. + + +Hooks API Reference +------------------- + +.. include:: /_build/inc/esp_freertos_hooks.inc diff --git a/docs/en/api-reference/system/hooks.rst b/docs/en/api-reference/system/hooks.rst deleted file mode 100644 index 5a65b29a16..0000000000 --- a/docs/en/api-reference/system/hooks.rst +++ /dev/null @@ -1,51 +0,0 @@ -.. _hooks_api_reference: - -FreeRTOS Hooks -============== - -Overview --------- - -FreeRTOS consists of Idle Hooks and Tick Hooks which allow for application -specific funtiionality to be added to the Idle Task and Tick Interrupt. The -ESP32 is dual core in nature, hence the ESP-IDF provides its own Idle and Tick -Hooks that are dual core compatible in addition to the hooks provided by Vanilla -FreeRTOS. - -Vanilla FreeRTOS Hooks ----------------------- - -Idle and Tick Hooks in vanilla FreeRTOS are implemented by defining -implementations for the functions ``vApplicationIdleHook`` and -``vApplicationTickHook`` respectively somewhere in the application. Vanilla -FreeRTOS will run the user defined Idle Hook every iteration of the Idle Task, -whereas the user defined Tick Hook will run once per tick interrupt (given that -there are no pended ticks). - -Due to vanilla FreeRTOS being designed for single core, ``vApplicationIdleHook`` -and ``vApplicationTickHook`` will be run in both cores on the ESP32. In -other words, the same Idle Hook and Tick Hook are used for both cores. - -To enable the vanilla FreeRTOS hooks in ESP-IDF, :ref:`CONFIG_FREERTOS_LEGACY_HOOKS` -must be enabled in ``make menuconfig``. :ref:`CONFIG_FREERTOS_LEGACY_IDLE_HOOK` -and :ref:`CONFIG_FREERTOS_LEGACY_TICK_HOOK` should also be enabled. - -ESP-IDF Idle and Tick Hooks ---------------------------- - -Due to the dual core nature of the ESP32, it may be necessary for some -applications to have seperate Idle Hooks for each core. Furthermore, it may -be necessary for Idle and Tick Hooks to have execute multiple functionalities -that are configurable at run time. Therefore the ESP-IDF provides it's own Idle -and Tick Hooks in addition to the hooks provided by Vanilla FreeRTOS. - -The ESP-IDF Hooks do not operate in the same way as Vanilla FreeRTOS Hooks -where users provide a definition for each of the hooks. Instead, the ESP-IDF -Hooks are predefined to call a list of user registered callbacks specific to -each core. Users can register and deregister callbacks which are run on the -Idle or Tick Hook of a specific core. - -API Reference -------------- - -.. include:: /_build/inc/esp_freertos_hooks.inc \ No newline at end of file diff --git a/docs/en/api-reference/system/index.rst b/docs/en/api-reference/system/index.rst index 7dd9991c45..bdc5d68e22 100644 --- a/docs/en/api-reference/system/index.rst +++ b/docs/en/api-reference/system/index.rst @@ -5,7 +5,7 @@ System API :maxdepth: 1 FreeRTOS - FreeRTOS Hooks + FreeRTOS Additions Heap Memory Allocation Heap Memory Debugging Interrupt Allocation diff --git a/docs/zh_CN/api-reference/system/freertos_additions.rst b/docs/zh_CN/api-reference/system/freertos_additions.rst new file mode 100644 index 0000000000..36e4800fb4 --- /dev/null +++ b/docs/zh_CN/api-reference/system/freertos_additions.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/system/freertos_additions.rst \ No newline at end of file diff --git a/docs/zh_CN/api-reference/system/hooks.rst b/docs/zh_CN/api-reference/system/hooks.rst deleted file mode 100644 index 487fb99107..0000000000 --- a/docs/zh_CN/api-reference/system/hooks.rst +++ /dev/null @@ -1 +0,0 @@ -.. include:: ../../../en/api-reference/system/hooks.rst \ No newline at end of file From f6f9f93a9dd736ed6ee0c281b5f5eb4bc47ca36c Mon Sep 17 00:00:00 2001 From: kooho <2229179028@qq.com> Date: Wed, 2 May 2018 15:27:41 +0800 Subject: [PATCH 134/187] driver(i2c, rmt):Add intr_flag setting to ESP_INTR_FLAG_IRAM support when enable psram. --- components/driver/i2c.c | 87 +++++++++++++++++++++++++- components/driver/include/driver/i2c.h | 10 +++ components/driver/include/driver/rmt.h | 2 + components/driver/rmt.c | 30 +++++++++ 4 files changed, 127 insertions(+), 2 deletions(-) diff --git a/components/driver/i2c.c b/components/driver/i2c.c index 26ef67370b..1d904fdcb7 100644 --- a/components/driver/i2c.c +++ b/components/driver/i2c.c @@ -66,6 +66,7 @@ static DRAM_ATTR i2c_dev_t* const I2C[I2C_NUM_MAX] = { &I2C0, &I2C1 }; #define I2C_GPIO_PULLUP_ERR_STR "this i2c pin does not support internal pull-up" #define I2C_ACK_TYPE_ERR_STR "i2c ack type error" #define I2C_DATA_LEN_ERR_STR "i2c data read length error" +#define I2C_PSRAM_BUFFER_WARN_STR "Using buffer allocated from psram" #define I2C_FIFO_FULL_THRESH_VAL (28) #define I2C_FIFO_EMPTY_THRESH_VAL (5) #define I2C_IO_INIT_LEVEL (1) @@ -124,6 +125,11 @@ typedef struct { i2c_cmd_desc_t cmd_link; /*!< I2C command link */ QueueHandle_t cmd_evt_queue; /*!< I2C command event queue */ +#if CONFIG_SPIRAM_USE_MALLOC + uint8_t* evt_queue_storage; /*!< The buffer that will hold the items in the queue */ + int intr_alloc_flags; /*!< Used to allocate the interrupt */ + StaticQueue_t evt_queue_buffer; /*!< The buffer that will hold the queue structure*/ +#endif xSemaphoreHandle cmd_mux; /*!< semaphore to lock command process */ size_t tx_fifo_remain; /*!< tx fifo remain length, for master mode */ size_t rx_fifo_remain; /*!< rx fifo remain length, for master mode */ @@ -156,7 +162,16 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_ ESP_ERR_INVALID_ARG); uint32_t intr_mask = 0; if (p_i2c_obj[i2c_num] == NULL) { + +#if !CONFIG_SPIRAM_USE_MALLOC p_i2c_obj[i2c_num] = (i2c_obj_t*) calloc(1, sizeof(i2c_obj_t)); +#else + if( !(intr_alloc_flags & ESP_INTR_FLAG_IRAM) ) { + p_i2c_obj[i2c_num] = (i2c_obj_t*) calloc(1, sizeof(i2c_obj_t)); + } else { + p_i2c_obj[i2c_num] = (i2c_obj_t*) heap_caps_calloc(1, sizeof(i2c_obj_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + } +#endif if (p_i2c_obj[i2c_num] == NULL) { ESP_LOGE(I2C_TAG, I2C_DRIVER_MALLOC_ERR_STR); return ESP_FAIL; @@ -168,6 +183,9 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_ p_i2c->rx_cnt = 0; p_i2c->status = I2C_STATUS_IDLE; +#if CONFIG_SPIRAM_USE_MALLOC + p_i2c->intr_alloc_flags = intr_alloc_flags; +#endif p_i2c->rx_fifo_remain = I2C_FIFO_LEN; p_i2c->tx_fifo_remain = I2C_FIFO_LEN; @@ -205,7 +223,21 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_ } else { //semaphore to sync sending process, because we only have 32 bytes for hardware fifo. p_i2c->cmd_mux = xSemaphoreCreateMutex(); +#if !CONFIG_SPIRAM_USE_MALLOC p_i2c->cmd_evt_queue = xQueueCreate(I2C_EVT_QUEUE_LEN, sizeof(i2c_cmd_evt_t)); +#else + if( !(intr_alloc_flags & ESP_INTR_FLAG_IRAM) ) { + p_i2c->cmd_evt_queue = xQueueCreate(I2C_EVT_QUEUE_LEN, sizeof(i2c_cmd_evt_t)); + } else { + p_i2c->evt_queue_storage = (uint8_t *)heap_caps_calloc(I2C_EVT_QUEUE_LEN, sizeof(i2c_cmd_evt_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + if( p_i2c->evt_queue_storage == NULL ) { + ESP_LOGE(I2C_TAG, I2C_DRIVER_MALLOC_ERR_STR); + goto err; + } + memset(&p_i2c->evt_queue_buffer, 0, sizeof(StaticQueue_t)); + p_i2c->cmd_evt_queue = xQueueCreateStatic(I2C_EVT_QUEUE_LEN, sizeof(i2c_cmd_evt_t), p_i2c->evt_queue_storage, &p_i2c->evt_queue_buffer); + } +#endif if (p_i2c->cmd_mux == NULL || p_i2c->cmd_evt_queue == NULL) { ESP_LOGE(I2C_TAG, I2C_SEM_ERR_STR); goto err; @@ -262,6 +294,12 @@ esp_err_t i2c_driver_install(i2c_port_t i2c_num, i2c_mode_t mode, size_t slv_rx_ if (p_i2c_obj[i2c_num]->slv_tx_mux) { vSemaphoreDelete(p_i2c_obj[i2c_num]->slv_tx_mux); } +#if CONFIG_SPIRAM_USE_MALLOC + if (p_i2c_obj[i2c_num]->evt_queue_storage) { + free(p_i2c_obj[i2c_num]->evt_queue_storage); + p_i2c_obj[i2c_num]->evt_queue_storage = NULL; + } +#endif } free(p_i2c_obj[i2c_num]); p_i2c_obj[i2c_num] = NULL; @@ -324,6 +362,12 @@ esp_err_t i2c_driver_delete(i2c_port_t i2c_num) p_i2c->tx_ring_buf = NULL; p_i2c->tx_buf_length = 0; } +#if CONFIG_SPIRAM_USE_MALLOC + if (p_i2c_obj[i2c_num]->evt_queue_storage) { + free(p_i2c_obj[i2c_num]->evt_queue_storage); + p_i2c_obj[i2c_num]->evt_queue_storage = NULL; + } +#endif free(p_i2c_obj[i2c_num]); p_i2c_obj[i2c_num] = NULL; @@ -839,7 +883,11 @@ esp_err_t i2c_set_pin(i2c_port_t i2c_num, int sda_io_num, int scl_io_num, gpio_p i2c_cmd_handle_t i2c_cmd_link_create() { +#if !CONFIG_SPIRAM_USE_MALLOC i2c_cmd_desc_t* cmd_desc = (i2c_cmd_desc_t*) calloc(1, sizeof(i2c_cmd_desc_t)); +#else + i2c_cmd_desc_t* cmd_desc = (i2c_cmd_desc_t*) heap_caps_calloc(1, sizeof(i2c_cmd_desc_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#endif return (i2c_cmd_handle_t) cmd_desc; } @@ -865,7 +913,11 @@ static esp_err_t i2c_cmd_link_append(i2c_cmd_handle_t cmd_handle, i2c_cmd_t* cmd { i2c_cmd_desc_t* cmd_desc = (i2c_cmd_desc_t*) cmd_handle; if (cmd_desc->head == NULL) { - cmd_desc->head = (i2c_cmd_link_t*) malloc(sizeof(i2c_cmd_link_t)); +#if !CONFIG_SPIRAM_USE_MALLOC + cmd_desc->head = (i2c_cmd_link_t*) calloc(1, sizeof(i2c_cmd_link_t)); +#else + cmd_desc->head = (i2c_cmd_link_t*) heap_caps_calloc(1, sizeof(i2c_cmd_link_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#endif if (cmd_desc->head == NULL) { ESP_LOGE(I2C_TAG, I2C_CMD_MALLOC_ERR_STR); goto err; @@ -873,7 +925,11 @@ static esp_err_t i2c_cmd_link_append(i2c_cmd_handle_t cmd_handle, i2c_cmd_t* cmd cmd_desc->cur = cmd_desc->head; cmd_desc->free = cmd_desc->head; } else { - cmd_desc->cur->next = (i2c_cmd_link_t*) malloc(sizeof(i2c_cmd_link_t)); +#if !CONFIG_SPIRAM_USE_MALLOC + cmd_desc->cur->next = (i2c_cmd_link_t*) calloc(1, sizeof(i2c_cmd_link_t)); +#else + cmd_desc->cur->next = (i2c_cmd_link_t*) heap_caps_calloc(1, sizeof(i2c_cmd_link_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); +#endif if (cmd_desc->cur->next == NULL) { ESP_LOGE(I2C_TAG, I2C_CMD_MALLOC_ERR_STR); goto err; @@ -1128,6 +1184,23 @@ static void IRAM_ATTR i2c_master_cmd_begin_static(i2c_port_t i2c_num) return; } +#if CONFIG_SPIRAM_USE_MALLOC +//Check whether read or write buffer in cmd_link is internal. +static bool is_cmd_link_buffer_internal(i2c_cmd_link_t *link) +{ + i2c_cmd_link_t* cmd_link = link; + while(cmd_link != NULL) { + if (cmd_link->cmd.op_code == I2C_CMD_WRITE || cmd_link->cmd.op_code == I2C_CMD_READ) { + if( cmd_link->cmd.data != NULL && !esp_ptr_internal(cmd_link->cmd.data)) { + return false; + } + } + cmd_link = cmd_link->next; + } + return true; +} +#endif + esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, TickType_t ticks_to_wait) { I2C_CHECK(( i2c_num < I2C_NUM_MAX ), I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG); @@ -1135,6 +1208,16 @@ esp_err_t i2c_master_cmd_begin(i2c_port_t i2c_num, i2c_cmd_handle_t cmd_handle, I2C_CHECK(p_i2c_obj[i2c_num]->mode == I2C_MODE_MASTER, I2C_MASTER_MODE_ERR_STR, ESP_ERR_INVALID_STATE); I2C_CHECK(cmd_handle != NULL, I2C_CMD_LINK_INIT_ERR_STR, ESP_ERR_INVALID_ARG); +#if CONFIG_SPIRAM_USE_MALLOC + //If the i2c read or write buffer is not in internal RAM, we will return ESP_FAIL + //to avoid the ISR handler function crashing when the cache is disabled. + if( (p_i2c_obj[i2c_num]->intr_alloc_flags & ESP_INTR_FLAG_IRAM) ) { + if( !is_cmd_link_buffer_internal(((i2c_cmd_desc_t*)cmd_handle)->head) ) { + ESP_LOGE(I2C_TAG, I2C_PSRAM_BUFFER_WARN_STR); + return ESP_ERR_INVALID_ARG; + } + } +#endif // Sometimes when the FSM get stuck, the ACK_ERR interrupt will occur endlessly until we reset the FSM and clear bus. static uint8_t clear_bus_cnt = 0; esp_err_t ret = ESP_FAIL; diff --git a/components/driver/include/driver/i2c.h b/components/driver/include/driver/i2c.h index b7aceb7b13..0f892db5e7 100644 --- a/components/driver/include/driver/i2c.h +++ b/components/driver/include/driver/i2c.h @@ -113,6 +113,10 @@ typedef void* i2c_cmd_handle_t; /*!< I2C command handle */ * Only slave mode will use this value, driver will ignore this value in master mode. * @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred) * ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info. + * @note + * In master mode, if the cache is likely to be disabled(such as write flash) and the slave is time-sensitive, + * `ESP_INTR_FLAG_IRAM` is suggested to be used. In this case, please use the memory allocated from internal RAM in i2c read and write function, + * because we can not access the psram(if psram is enabled) in interrupt handle function when cache is disabled. * * @return * - ESP_OK Success @@ -272,6 +276,8 @@ esp_err_t i2c_master_write_byte(i2c_cmd_handle_t cmd_handle, uint8_t data, bool * * @param cmd_handle I2C cmd link * @param data data to send + * @note + * If the psram is enabled and intr_flag is `ESP_INTR_FLAG_IRAM`, please use the memory allocated from internal RAM. * @param data_len data length * @param ack_en enable ack check for master * @@ -289,6 +295,8 @@ esp_err_t i2c_master_write(i2c_cmd_handle_t cmd_handle, uint8_t* data, size_t da * * @param cmd_handle I2C cmd link * @param data pointer accept the data byte + * @note + * If the psram is enabled and intr_flag is `ESP_INTR_FLAG_IRAM`, please use the memory allocated from internal RAM. * @param ack ack value for read command * * @return @@ -305,6 +313,8 @@ esp_err_t i2c_master_read_byte(i2c_cmd_handle_t cmd_handle, uint8_t* data, i2c_a * * @param cmd_handle I2C cmd link * @param data data buffer to accept the data from bus + * @note + * If the psram is enabled and intr_flag is `ESP_INTR_FLAG_IRAM`, please use the memory allocated from internal RAM. * @param data_len read data length * @param ack ack value for read command * diff --git a/components/driver/include/driver/rmt.h b/components/driver/include/driver/rmt.h index 13d97b91cd..a1bcbe8195 100644 --- a/components/driver/include/driver/rmt.h +++ b/components/driver/include/driver/rmt.h @@ -632,6 +632,7 @@ esp_err_t rmt_fill_tx_items(rmt_channel_t channel, const rmt_item32_t* item, uin * @param rx_buf_size Size of RMT RX ringbuffer. Can be 0 if the RX ringbuffer is not used. * * @param intr_alloc_flags Flags for the RMT driver interrupt handler. Pass 0 for default flags. See esp_intr_alloc.h for details. + * If ESP_INTR_FLAG_IRAM is used, please do not use the memory allocated from psram when calling rmt_write_items. * * @return * - ESP_ERR_INVALID_STATE Driver is already installed, call rmt_driver_uninstall first. @@ -660,6 +661,7 @@ esp_err_t rmt_driver_uninstall(rmt_channel_t channel); * @param channel RMT channel (0 - 7) * * @param rmt_item head point of RMT items array. + * If ESP_INTR_FLAG_IRAM is used, please do not use the memory allocated from psram when calling rmt_write_items. * * @param item_num RMT data item number. * diff --git a/components/driver/rmt.c b/components/driver/rmt.c index 84d7a81db1..ca0dc6a28c 100644 --- a/components/driver/rmt.c +++ b/components/driver/rmt.c @@ -45,6 +45,7 @@ #define RMT_CLK_DIV_ERROR_STR "RMT CLK DIV ERR" #define RMT_DRIVER_ERROR_STR "RMT DRIVER ERR" #define RMT_DRIVER_LENGTH_ERROR_STR "RMT PARAM LEN ERROR" +#define RMT_PSRAM_BUFFER_WARN_STR "Using buffer allocated from psram" static const char* RMT_TAG = "rmt"; static uint8_t s_rmt_driver_channels; // Bitmask (bits 0-7) of installed drivers' channels @@ -70,6 +71,10 @@ typedef struct { rmt_channel_t channel; const rmt_item32_t* tx_data; xSemaphoreHandle tx_sem; +#if CONFIG_SPIRAM_USE_MALLOC + int intr_alloc_flags; + StaticSemaphore_t tx_sem_buffer; +#endif RingbufHandle_t tx_buf; RingbufHandle_t rx_buf; } rmt_obj_t; @@ -690,7 +695,15 @@ esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int intr return ESP_ERR_INVALID_STATE; } +#if !CONFIG_SPIRAM_USE_MALLOC p_rmt_obj[channel] = (rmt_obj_t*) malloc(sizeof(rmt_obj_t)); +#else + if( !(intr_alloc_flags & ESP_INTR_FLAG_IRAM) ) { + p_rmt_obj[channel] = (rmt_obj_t*) malloc(sizeof(rmt_obj_t)); + } else { + p_rmt_obj[channel] = (rmt_obj_t*) heap_caps_calloc(1, sizeof(rmt_obj_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + } +#endif if(p_rmt_obj[channel] == NULL) { ESP_LOGE(RMT_TAG, "RMT driver malloc error"); @@ -706,7 +719,16 @@ esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int intr p_rmt_obj[channel]->wait_done = false; if(p_rmt_obj[channel]->tx_sem == NULL) { +#if !CONFIG_SPIRAM_USE_MALLOC p_rmt_obj[channel]->tx_sem = xSemaphoreCreateBinary(); +#else + p_rmt_obj[channel]->intr_alloc_flags = intr_alloc_flags; + if( !(intr_alloc_flags & ESP_INTR_FLAG_IRAM) ) { + p_rmt_obj[channel]->tx_sem = xSemaphoreCreateBinary(); + } else { + p_rmt_obj[channel]->tx_sem = xSemaphoreCreateBinaryStatic(&p_rmt_obj[channel]->tx_sem_buffer); + } +#endif xSemaphoreGive(p_rmt_obj[channel]->tx_sem); } if(p_rmt_obj[channel]->rx_buf == NULL && rx_buf_size > 0) { @@ -736,6 +758,14 @@ esp_err_t rmt_write_items(rmt_channel_t channel, const rmt_item32_t* rmt_item, i RMT_CHECK(p_rmt_obj[channel] != NULL, RMT_DRIVER_ERROR_STR, ESP_FAIL); RMT_CHECK(rmt_item != NULL, RMT_ADDR_ERROR_STR, ESP_FAIL); RMT_CHECK(item_num > 0, RMT_DRIVER_LENGTH_ERROR_STR, ESP_ERR_INVALID_ARG); +#if CONFIG_SPIRAM_USE_MALLOC + if( p_rmt_obj[channel]->intr_alloc_flags & ESP_INTR_FLAG_IRAM ) { + if( !esp_ptr_internal(rmt_item) ) { + ESP_LOGE(RMT_TAG, RMT_PSRAM_BUFFER_WARN_STR); + return ESP_ERR_INVALID_ARG; + } + } +#endif rmt_obj_t* p_rmt = p_rmt_obj[channel]; int block_num = RMT.conf_ch[channel].conf0.mem_size; int item_block_len = block_num * RMT_MEM_ITEM_NUM; From d754b53ae22784189da5b72ee7b729bad4aaf08e Mon Sep 17 00:00:00 2001 From: krzychb Date: Fri, 16 Mar 2018 02:28:58 +0800 Subject: [PATCH 135/187] Implemented docutils custom role that renders a link to current documentation page on Read The Docs in another language version Provided documentation of the role. --- docs/en/contribute/documenting-code.rst | 14 ++++++++++++ docs/link-roles.py | 30 +++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/docs/en/contribute/documenting-code.rst b/docs/en/contribute/documenting-code.rst index 37f71deeb4..80cbe1cf77 100644 --- a/docs/en/contribute/documenting-code.rst +++ b/docs/en/contribute/documenting-code.rst @@ -165,6 +165,20 @@ How it renders: A check is added to the CI build script, which searches RST files for presence of hard-coded links (identified by tree/master, blob/master, or raw/master part of the URL). This check can be run manually: ``cd docs`` and then ``make gh-linkcheck``. + +Linking Language Versions +------------------------- + +Switching between documentation in different languages may be done using ``:link_to_translation:`` custom role. The role placed on a page of documentation provides a link to the same page in a language specified as a parameter. Examples below show how to enter links to Chinese and English versions of documentation:: + + :link_to_translation:`zh_CN:中文版` + :link_to_translation:`en:English` + +The language is specified using standard abbreviations like ``en`` or ``zh_CN``. The text after last semicolon is not standardized and may be entered depending on the context where the link is placed, e.g.:: + + :link_to_translation:`en:see description in English` + + .. _add-illustrations: Add Illustrations diff --git a/docs/link-roles.py b/docs/link-roles.py index 7bfe353921..9760f49502 100644 --- a/docs/link-roles.py +++ b/docs/link-roles.py @@ -1,6 +1,7 @@ # based on http://protips.readthedocs.io/link-roles.html import re +import os from docutils import nodes from local_util import run_cmd_get_output @@ -13,10 +14,11 @@ def get_github_rev(): path = tag return path - def setup(app): - baseurl = 'https://github.com/espressif/esp-idf' rev = get_github_rev() + + # links to files or folders on the GitHub + baseurl = 'https://github.com/espressif/esp-idf' app.add_role('idf', autolink('{}/tree/{}/%s'.format(baseurl, rev))) app.add_role('idf_file', autolink('{}/blob/{}/%s'.format(baseurl, rev))) app.add_role('idf_raw', autolink('{}/raw/{}/%s'.format(baseurl, rev))) @@ -27,6 +29,19 @@ def setup(app): app.add_role('example_file', autolink('{}/blob/{}/examples/%s'.format(baseurl, rev))) app.add_role('example_raw', autolink('{}/raw/{}/examples/%s'.format(baseurl, rev))) + # link to the current documentation file in specific language version + on_rtd = os.environ.get('READTHEDOCS', None) == 'True' + if on_rtd: + # provide RTD specific commit identification to be included in the link + tag_rev = 'latest' + if (run_cmd_get_output('git rev-parse --short HEAD') != rev): + tag_rev = rev + else: + # if not on the RTD then provide generic identification + tag_rev = run_cmd_get_output('git describe --always') + + app.add_role('link_to_translation', crosslink('%s../../%s/{}/%s.html'.format(tag_rev))) + def autolink(pattern): def role(name, rawtext, text, lineno, inliner, options={}, content=[]): m = re.search('(.*)\s*<(.*)>', text) @@ -40,3 +55,14 @@ def autolink(pattern): node = nodes.reference(rawtext, link_text, refuri=url, **options) return [node], [] return role + +def crosslink(pattern): + def role(name, rawtext, text, lineno, inliner, options={}, content=[]): + (language, link_text) = text.split(':') + docname = inliner.document.settings.env.docname + doc_path = inliner.document.settings.env.doc2path(docname, None, None) + return_path = '../' * doc_path.count('/') + url = pattern % (return_path, language, docname) + node = nodes.reference(rawtext, link_text, refuri=url, **options) + return [node], [] + return role From 2852dd37fb833a86697461c45200bc5f81456967 Mon Sep 17 00:00:00 2001 From: "Michael (Xiao Xufeng)" Date: Wed, 14 Mar 2018 17:03:56 +0800 Subject: [PATCH 136/187] docs: add language link to easily change to Chinese version --- docs/_static/choose_version.png | Bin 0 -> 22448 bytes docs/en/index.rst | 4 ++++ docs/en/languages.rst | 19 +++++++++++++++++++ docs/zh_CN/index.rst | 5 +++++ docs/zh_CN/languages.rst | 1 + 5 files changed, 29 insertions(+) create mode 100644 docs/_static/choose_version.png create mode 100644 docs/en/languages.rst create mode 100644 docs/zh_CN/languages.rst diff --git a/docs/_static/choose_version.png b/docs/_static/choose_version.png new file mode 100644 index 0000000000000000000000000000000000000000..c8927df118dddf510599750fe1da789bb6a48888 GIT binary patch literal 22448 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 NQ-!OPE1Lz7{1-`mq51#- literal 0 HcmV?d00001 diff --git a/docs/en/index.rst b/docs/en/index.rst index 681d526d46..80079de3db 100644 --- a/docs/en/index.rst +++ b/docs/en/index.rst @@ -1,8 +1,11 @@ ESP-IDF Programming Guide ========================= +:link_to_translation:`zh_CN:[中文]` This is the documentation for Espressif IoT Development Framework (`esp-idf `_). ESP-IDF is the official development framework for the `ESP32 `_ chip. +The documentation has different language versions (:link_to_translation:`en:English`, :link_to_translation:`zh_CN:中文版`, :doc:`How to switch between languages? `). However, please refer to the English version if there is any discrepancy. + ================== ================== ================== |Get Started|_ |API Reference|_ |H/W Reference|_ ------------------ ------------------ ------------------ @@ -44,5 +47,6 @@ This is the documentation for Espressif IoT Development Framework (`esp-idf Copyrights About + [语言/Languages] * :ref:`genindex` diff --git a/docs/en/languages.rst b/docs/en/languages.rst new file mode 100644 index 0000000000..b50c8c9b1d --- /dev/null +++ b/docs/en/languages.rst @@ -0,0 +1,19 @@ +Switch Between Languages/切换语言 +================================= + +The documentation now has two language versions, however, please refer to the English version if there is any discrepancy. + +本文档现在有两种语言的版本,如有出入请以英文版本为准。 + +- English/英文 +- Chinese/中文 + +You can easily changed from one language to another by the panel on the sidebar like below. Just click on the **Read +the Docs** title button on the left-bottom conner if it is folded. + +如下图所示,你可使用边栏的面板进行语言的切换。如果该面板被折叠,点击左下角 **Read the Docs** 标题按钮来显示它。 + +.. image:: /../_static/choose_version.png + + + diff --git a/docs/zh_CN/index.rst b/docs/zh_CN/index.rst index 4b773da8ad..9945da9bc5 100644 --- a/docs/zh_CN/index.rst +++ b/docs/zh_CN/index.rst @@ -1,8 +1,11 @@ ESP-IDF 编程指南 ========================= +:link_to_translation:`en:[English]` 这是乐鑫 IoT 开发开发框架 (`esp-idf `_) 的文档. ESP-IDF 是 `ESP32 `_ 芯片的官方开发框架. +本文档提供不同语言的翻译版本 (:link_to_translation:`en:English`, :link_to_translation:`zh_CN:中文版`, :doc:`如何切换语言? `), 如有出入请以英文版本为准。 + ================== ================== ================== |快速入门|_ |API 参考|_ |H/W 参考|_ ------------------ ------------------ ------------------ @@ -44,5 +47,7 @@ ESP-IDF 编程指南 相关资源 版权 关于 + [Languages/语言] + * :ref:`genindex` diff --git a/docs/zh_CN/languages.rst b/docs/zh_CN/languages.rst new file mode 100644 index 0000000000..50879c5f79 --- /dev/null +++ b/docs/zh_CN/languages.rst @@ -0,0 +1 @@ +.. include:: ../en/languages.rst From d4deb9319a93329eeef2f3342e48ff3e87a6892e Mon Sep 17 00:00:00 2001 From: michael Date: Fri, 27 Apr 2018 14:46:13 +0800 Subject: [PATCH 137/187] doc(global): build cross-language links for translated documents --- docs/en/get-started/add-idf_path-to-profile.rst | 1 + docs/en/get-started/eclipse-setup-windows.rst | 1 + docs/en/get-started/eclipse-setup.rst | 1 + docs/en/get-started/establish-serial-connection.rst | 1 + docs/en/get-started/get-started-pico-kit.rst | 1 + docs/en/get-started/idf-monitor.rst | 1 + docs/en/get-started/index.rst | 1 + docs/en/get-started/linux-setup.rst | 1 + docs/en/get-started/macos-setup.rst | 1 + docs/en/get-started/make-project.rst | 1 + docs/en/get-started/windows-setup.rst | 1 + docs/zh_CN/get-started/add-idf_path-to-profile.rst | 3 ++- docs/zh_CN/get-started/eclipse-setup-windows.rst | 3 ++- docs/zh_CN/get-started/eclipse-setup.rst | 1 + docs/zh_CN/get-started/establish-serial-connection.rst | 1 + docs/zh_CN/get-started/get-started-pico-kit.rst | 3 ++- docs/zh_CN/get-started/idf-monitor.rst | 1 + docs/zh_CN/get-started/index.rst | 1 + docs/zh_CN/get-started/linux-setup.rst | 1 + docs/zh_CN/get-started/macos-setup.rst | 1 + docs/zh_CN/get-started/make-project.rst | 1 + docs/zh_CN/get-started/windows-setup.rst | 1 + 22 files changed, 25 insertions(+), 3 deletions(-) diff --git a/docs/en/get-started/add-idf_path-to-profile.rst b/docs/en/get-started/add-idf_path-to-profile.rst index 60ca434814..8ce9a9ae6f 100644 --- a/docs/en/get-started/add-idf_path-to-profile.rst +++ b/docs/en/get-started/add-idf_path-to-profile.rst @@ -1,5 +1,6 @@ Add IDF_PATH to User Profile ============================ +:link_to_translation:`zh_CN:[中文]` To preserve setting of ``IDF_PATH`` environment variable between system restarts, add it to the user profile, following instructions below. diff --git a/docs/en/get-started/eclipse-setup-windows.rst b/docs/en/get-started/eclipse-setup-windows.rst index a924d2dc7a..2728eb2970 100644 --- a/docs/en/get-started/eclipse-setup-windows.rst +++ b/docs/en/get-started/eclipse-setup-windows.rst @@ -1,6 +1,7 @@ ********************** Eclipse IDE on Windows ********************** +:link_to_translation:`zh_CN:[中文]` Configuring Eclipse on Windows requires some different steps. The full configuration steps for Windows are shown below. diff --git a/docs/en/get-started/eclipse-setup.rst b/docs/en/get-started/eclipse-setup.rst index 9ceb3c7791..7d17d6c159 100644 --- a/docs/en/get-started/eclipse-setup.rst +++ b/docs/en/get-started/eclipse-setup.rst @@ -1,6 +1,7 @@ ******************************** Build and Flash with Eclipse IDE ******************************** +:link_to_translation:`zh_CN:[中文]` .. _eclipse-install-steps: diff --git a/docs/en/get-started/establish-serial-connection.rst b/docs/en/get-started/establish-serial-connection.rst index d4c0943a44..e54345d831 100644 --- a/docs/en/get-started/establish-serial-connection.rst +++ b/docs/en/get-started/establish-serial-connection.rst @@ -1,5 +1,6 @@ Establish Serial Connection with ESP32 ====================================== +:link_to_translation:`zh_CN:[中文]` This section provides guidance how to establish serial connection between ESP32 and PC. diff --git a/docs/en/get-started/get-started-pico-kit.rst b/docs/en/get-started/get-started-pico-kit.rst index 831de1ac14..12ff80aed4 100644 --- a/docs/en/get-started/get-started-pico-kit.rst +++ b/docs/en/get-started/get-started-pico-kit.rst @@ -1,5 +1,6 @@ ESP32-PICO-KIT V4 Getting Started Guide ======================================= +:link_to_translation:`zh_CN:[中文]` This user guide shows how to get started with the ESP32-PICO-KIT V4 mini development board. For description of other versions of the ESP32-PICO-KIT check :doc:`../hw-reference/index`. diff --git a/docs/en/get-started/idf-monitor.rst b/docs/en/get-started/idf-monitor.rst index cf1deec354..09291a3d3f 100644 --- a/docs/en/get-started/idf-monitor.rst +++ b/docs/en/get-started/idf-monitor.rst @@ -1,6 +1,7 @@ *********** IDF Monitor *********** +:link_to_translation:`zh_CN:[中文]` The IDF Monitor tool is a Python program which runs when the ``make monitor`` target is invoked in IDF. diff --git a/docs/en/get-started/index.rst b/docs/en/get-started/index.rst index 9a2d3779ca..9e33e63496 100644 --- a/docs/en/get-started/index.rst +++ b/docs/en/get-started/index.rst @@ -1,6 +1,7 @@ *********** Get Started *********** +:link_to_translation:`zh_CN:[中文]` This document is intended to help users set up the software environment for development of applications using hardware based on the Espressif ESP32. Through a simple example we would like to illustrate how to use ESP-IDF (Espressif IoT Development Framework), including the menu based configuration, compiling the ESP-IDF and firmware download to ESP32 boards. diff --git a/docs/en/get-started/linux-setup.rst b/docs/en/get-started/linux-setup.rst index 8004c37ee7..bc4102a856 100644 --- a/docs/en/get-started/linux-setup.rst +++ b/docs/en/get-started/linux-setup.rst @@ -1,6 +1,7 @@ ************************************* Standard Setup of Toolchain for Linux ************************************* +:link_to_translation:`zh_CN:[中文]` Install Prerequisites diff --git a/docs/en/get-started/macos-setup.rst b/docs/en/get-started/macos-setup.rst index 14764601b5..16123cb03a 100644 --- a/docs/en/get-started/macos-setup.rst +++ b/docs/en/get-started/macos-setup.rst @@ -1,6 +1,7 @@ ************************************** Standard Setup of Toolchain for Mac OS ************************************** +:link_to_translation:`zh_CN:[中文]` Install Prerequisites ===================== diff --git a/docs/en/get-started/make-project.rst b/docs/en/get-started/make-project.rst index d85b2a91c0..956b097d04 100644 --- a/docs/en/get-started/make-project.rst +++ b/docs/en/get-started/make-project.rst @@ -1,5 +1,6 @@ Build and Flash with Make ========================= +:link_to_translation:`zh_CN:[中文]` Finding a project diff --git a/docs/en/get-started/windows-setup.rst b/docs/en/get-started/windows-setup.rst index e2adebde29..9b143920b9 100644 --- a/docs/en/get-started/windows-setup.rst +++ b/docs/en/get-started/windows-setup.rst @@ -1,6 +1,7 @@ *************************************** Standard Setup of Toolchain for Windows *************************************** +:link_to_translation:`zh_CN:[中文]` Introduction ============ diff --git a/docs/zh_CN/get-started/add-idf_path-to-profile.rst b/docs/zh_CN/get-started/add-idf_path-to-profile.rst index 1af406efda..61e8d3dbb0 100644 --- a/docs/zh_CN/get-started/add-idf_path-to-profile.rst +++ b/docs/zh_CN/get-started/add-idf_path-to-profile.rst @@ -1,5 +1,6 @@ 在用户配置文件中添加 IDF_PATH ============================== +:link_to_translation:`en:[English]` 为了在系统多次重新启动时保留 “IDF_PATH” 环境变量的设置,请按照以下说明将其添加到用户配置文件中。 @@ -60,4 +61,4 @@ Linux and MacOS export IDF_PATH=~/esp/esp-idf -如果您从 :ref:`get-started-setup-path` 小节跳转到了这里,在安装用于 ESP32 开发的软件时,返回到 :ref:`get-started-start-project` 小节。 \ No newline at end of file +如果您从 :ref:`get-started-setup-path` 小节跳转到了这里,在安装用于 ESP32 开发的软件时,返回到 :ref:`get-started-start-project` 小节。 diff --git a/docs/zh_CN/get-started/eclipse-setup-windows.rst b/docs/zh_CN/get-started/eclipse-setup-windows.rst index ba15bc9dba..4047dc939e 100644 --- a/docs/zh_CN/get-started/eclipse-setup-windows.rst +++ b/docs/zh_CN/get-started/eclipse-setup-windows.rst @@ -1,6 +1,7 @@ ***************************************************** Eclipse IDE 的创建和烧录指南(Windows 平台) ***************************************************** +:link_to_translation:`en:[English]` Windows 平台上的 Eclipse 配置略有不同,具体步骤请见下文。 @@ -78,4 +79,4 @@ Windows 平台的 Eclipse 介绍到此结束,下方将主要将介绍一些关 * 首先,xtensa-esp32-elf-gcc 交叉编译器 *并非* Cygwin 工具链,但我们会在 Eclipse 中指定其为 Cygwin 工具链。主要原因在于:msys2 需要使用 Cygwin,并支持 Unix 风格的路径,即 ``/c/blah``,而非 ``c:/blah`` 或 ``c:\\blah``。特别需要说明的是,``xtensa-esp32-elf-gcc`` 会“告知” Eclipse 的 ``built-in compiler settings`` 功能,其内置 “include” 目录全部位于 ``/usr/`` 路径下,这也是 Eclipse 唯一可以解析的 ``Unix/Cygwin`` 风格路径。通过在 Eclipse 中指定 ``xtensa-esp32-elf-gcc`` 交叉编译器为 Cygwin 编译器,可以让 Eclipse 使用 cygpath 实用程序直接内部解析路径。 -* 在解析 ESP-IDF 的 make 结果时也经常会出现同样的问题。Eclipse 可以解析 make 的结果,查找头文件目录,但是无法脱离 ``cygpath``,直接解析类似 ``/c/blah`` 的目录。``Eclipse Build Output Parser`` 将利用该机制确认是否调用 ``cygpath``,但由于未知原因,目前 ESP-IDF 配置并不会触发该功能。出于这个原因,我们会使用 ``eclipse_make.py`` 包装脚本调用 ``make``,然后使用 ``cygpath`` 处理 Eclipse 的结果。 \ No newline at end of file +* 在解析 ESP-IDF 的 make 结果时也经常会出现同样的问题。Eclipse 可以解析 make 的结果,查找头文件目录,但是无法脱离 ``cygpath``,直接解析类似 ``/c/blah`` 的目录。``Eclipse Build Output Parser`` 将利用该机制确认是否调用 ``cygpath``,但由于未知原因,目前 ESP-IDF 配置并不会触发该功能。出于这个原因,我们会使用 ``eclipse_make.py`` 包装脚本调用 ``make``,然后使用 ``cygpath`` 处理 Eclipse 的结果。 diff --git a/docs/zh_CN/get-started/eclipse-setup.rst b/docs/zh_CN/get-started/eclipse-setup.rst index 8db8639428..e2f7be8a3c 100644 --- a/docs/zh_CN/get-started/eclipse-setup.rst +++ b/docs/zh_CN/get-started/eclipse-setup.rst @@ -1,6 +1,7 @@ **************************** Eclipse IDE 的创建和烧录指南 **************************** +:link_to_translation:`en:[English]` .. _eclipse-install-steps: diff --git a/docs/zh_CN/get-started/establish-serial-connection.rst b/docs/zh_CN/get-started/establish-serial-connection.rst index 38c05344c6..f934dba3d8 100644 --- a/docs/zh_CN/get-started/establish-serial-connection.rst +++ b/docs/zh_CN/get-started/establish-serial-connection.rst @@ -1,5 +1,6 @@ 与 ESP32 创建串口连接 ========================= +:link_to_translation:`en:[English]` 本章节介绍如何在 ESP32 和 PC 之间建立串口连接。 diff --git a/docs/zh_CN/get-started/get-started-pico-kit.rst b/docs/zh_CN/get-started/get-started-pico-kit.rst index d2e44c905b..4ffa78dbc7 100644 --- a/docs/zh_CN/get-started/get-started-pico-kit.rst +++ b/docs/zh_CN/get-started/get-started-pico-kit.rst @@ -1,5 +1,6 @@ ESP32-PICO-KIT V4 入门指南 ============================ +:link_to_translation:`en:[English]` 本指南介绍了如何开始使用 ESP32-PICO-KIT V4 迷你开发板。有关 ESP32-PICO-KIT 其他版本的介绍,请见 :doc:`../hw-reference/index`。 @@ -216,4 +217,4 @@ Header J3 .. toctree:: :hidden: - get-started-pico-kit-v3 \ No newline at end of file + get-started-pico-kit-v3 diff --git a/docs/zh_CN/get-started/idf-monitor.rst b/docs/zh_CN/get-started/idf-monitor.rst index 5e19ff1587..a5b30e2d0a 100644 --- a/docs/zh_CN/get-started/idf-monitor.rst +++ b/docs/zh_CN/get-started/idf-monitor.rst @@ -1,6 +1,7 @@ *********** IDF Monitor *********** +:link_to_translation:`en:[English]` IDF Monitor 工具是在 IDF 中调用 “make monitor” 目标时运行的 Python 程序。 diff --git a/docs/zh_CN/get-started/index.rst b/docs/zh_CN/get-started/index.rst index e2eb3d2eaa..8831d86fd1 100644 --- a/docs/zh_CN/get-started/index.rst +++ b/docs/zh_CN/get-started/index.rst @@ -1,6 +1,7 @@ *********** 快速入门 *********** +:link_to_translation:`en:[English]` 本文档旨在指导用户创建 ESP32 的软件环境。本文将通过一个简单的例子来说明如何使用 ESP-IDF (Espressif IoT Development Framework),包括配置、编译、下载固件到开发板等步骤。 diff --git a/docs/zh_CN/get-started/linux-setup.rst b/docs/zh_CN/get-started/linux-setup.rst index a4dc1d943c..8c5c0cf6ba 100644 --- a/docs/zh_CN/get-started/linux-setup.rst +++ b/docs/zh_CN/get-started/linux-setup.rst @@ -1,6 +1,7 @@ ***************************** Linux 平台工具链的标准设置 ***************************** +:link_to_translation:`en:[English]` 安装前提 ===================== diff --git a/docs/zh_CN/get-started/macos-setup.rst b/docs/zh_CN/get-started/macos-setup.rst index ea5b6c60d3..18c325303b 100644 --- a/docs/zh_CN/get-started/macos-setup.rst +++ b/docs/zh_CN/get-started/macos-setup.rst @@ -1,6 +1,7 @@ ************************************** 在 Mac OS 上安装 ESP32 工具链 ************************************** +:link_to_translation:`en:[English]` 安装准备 ================ diff --git a/docs/zh_CN/get-started/make-project.rst b/docs/zh_CN/get-started/make-project.rst index 6c03bab974..6456d8ef09 100644 --- a/docs/zh_CN/get-started/make-project.rst +++ b/docs/zh_CN/get-started/make-project.rst @@ -1,5 +1,6 @@ 通过 make 指令创建和烧录项目 ============================= +:link_to_translation:`en:[English]` 寻找项目 diff --git a/docs/zh_CN/get-started/windows-setup.rst b/docs/zh_CN/get-started/windows-setup.rst index d83408e3c0..8482b5d9cd 100644 --- a/docs/zh_CN/get-started/windows-setup.rst +++ b/docs/zh_CN/get-started/windows-setup.rst @@ -1,6 +1,7 @@ *************************************** Windows 平台工具链的标准设置 *************************************** +:link_to_translation:`en:[English]` 引言 ============ From ff528d13c7a24f3b5cb7937a41f6e1d8a921a99c Mon Sep 17 00:00:00 2001 From: Tuan PM Date: Tue, 14 Nov 2017 10:16:20 +0700 Subject: [PATCH 138/187] Add esp_http_client Add error handling for http client set ssid password correct with Example_WIFI test, and clear password before free Fixed the CI failure due to HTTP errror names --- components/esp32/esp_err_to_name.c | 23 + components/esp_http_client/Kconfig | 10 + components/esp_http_client/component.mk | 6 + components/esp_http_client/esp_http_client.c | 972 ++++++++++++++++++ .../esp_http_client/include/esp_http_client.h | 343 ++++++ components/esp_http_client/lib/http_auth.c | 151 +++ components/esp_http_client/lib/http_header.c | 239 +++++ components/esp_http_client/lib/http_utils.c | 125 +++ .../esp_http_client/lib/include/http_auth.h | 60 ++ .../esp_http_client/lib/include/http_header.h | 128 +++ .../esp_http_client/lib/include/http_utils.h | 95 ++ .../esp_http_client/lib/include/transport.h | 251 +++++ .../lib/include/transport_ssl.h | 48 + .../lib/include/transport_tcp.h | 36 + components/esp_http_client/lib/transport.c | 232 +++++ .../esp_http_client/lib/transport_ssl.c | 267 +++++ .../esp_http_client/lib/transport_tcp.c | 166 +++ docs/Doxyfile | 1 + .../protocols/esp_http_client.rst | 191 ++++ docs/en/api-reference/protocols/index.rst | 1 + .../protocols/esp_http_client.rst | 1 + examples/protocols/esp_http_client/Makefile | 9 + examples/protocols/esp_http_client/README.md | 3 + .../esp_http_client/esp_http_client_test.py | 51 + .../esp_http_client/main/Kconfig.projbuild | 17 + .../protocols/esp_http_client/main/app_wifi.c | 75 ++ .../protocols/esp_http_client/main/app_wifi.h | 17 + .../esp_http_client/main/component.mk | 8 + .../main/esp_http_client_example.c | 362 +++++++ .../main/howsmyssl_com_root_cert.pem | 27 + 30 files changed, 3915 insertions(+) create mode 100644 components/esp_http_client/Kconfig create mode 100644 components/esp_http_client/component.mk create mode 100644 components/esp_http_client/esp_http_client.c create mode 100644 components/esp_http_client/include/esp_http_client.h create mode 100644 components/esp_http_client/lib/http_auth.c create mode 100644 components/esp_http_client/lib/http_header.c create mode 100644 components/esp_http_client/lib/http_utils.c create mode 100644 components/esp_http_client/lib/include/http_auth.h create mode 100644 components/esp_http_client/lib/include/http_header.h create mode 100644 components/esp_http_client/lib/include/http_utils.h create mode 100644 components/esp_http_client/lib/include/transport.h create mode 100644 components/esp_http_client/lib/include/transport_ssl.h create mode 100644 components/esp_http_client/lib/include/transport_tcp.h create mode 100644 components/esp_http_client/lib/transport.c create mode 100644 components/esp_http_client/lib/transport_ssl.c create mode 100644 components/esp_http_client/lib/transport_tcp.c create mode 100644 docs/en/api-reference/protocols/esp_http_client.rst create mode 100644 docs/zh_CN/api-reference/protocols/esp_http_client.rst create mode 100644 examples/protocols/esp_http_client/Makefile create mode 100644 examples/protocols/esp_http_client/README.md create mode 100644 examples/protocols/esp_http_client/esp_http_client_test.py create mode 100644 examples/protocols/esp_http_client/main/Kconfig.projbuild create mode 100644 examples/protocols/esp_http_client/main/app_wifi.c create mode 100644 examples/protocols/esp_http_client/main/app_wifi.h create mode 100644 examples/protocols/esp_http_client/main/component.mk create mode 100644 examples/protocols/esp_http_client/main/esp_http_client_example.c create mode 100644 examples/protocols/esp_http_client/main/howsmyssl_com_root_cert.pem diff --git a/components/esp32/esp_err_to_name.c b/components/esp32/esp_err_to_name.c index 6011689271..b6743c31ea 100644 --- a/components/esp32/esp_err_to_name.c +++ b/components/esp32/esp_err_to_name.c @@ -10,6 +10,9 @@ #if __has_include("esp_err.h") #include "esp_err.h" #endif +#if __has_include("esp_http_client.h") +#include "esp_http_client.h" +#endif #if __has_include("esp_image_format.h") #include "esp_image_format.h" #endif @@ -397,6 +400,26 @@ static const esp_err_msg_t esp_err_msg_table[] = { # endif # ifdef ESP_ERR_PING_NO_MEM ERR_TBL_IT(ESP_ERR_PING_NO_MEM), /* 24578 0x6002 */ +# endif + // components/esp_http_client/include/esp_http_client.h +# ifdef ESP_ERR_HTTP_BASE + ERR_TBL_IT(ESP_ERR_HTTP_BASE), /* 28672 0x7000 Starting number of HTTP error codes */ +# endif +# ifdef ESP_ERR_HTTP_MAX_REDIRECT + ERR_TBL_IT(ESP_ERR_HTTP_MAX_REDIRECT), /* 28673 0x7001 The error exceeds the number of HTTP redirects */ +# endif +# ifdef ESP_ERR_HTTP_CONNECT + ERR_TBL_IT(ESP_ERR_HTTP_CONNECT), /* 28674 0x7002 Error open the HTTP connection */ +# endif +# ifdef ESP_ERR_HTTP_WRITE_DATA + ERR_TBL_IT(ESP_ERR_HTTP_WRITE_DATA), /* 28675 0x7003 Error write HTTP data */ +# endif +# ifdef ESP_ERR_HTTP_FETCH_HEADER + ERR_TBL_IT(ESP_ERR_HTTP_FETCH_HEADER), /* 28676 0x7004 Error read HTTP header from server */ +# endif +# ifdef ESP_ERR_HTTP_INVALID_TRANSPORT + ERR_TBL_IT(ESP_ERR_HTTP_INVALID_TRANSPORT), /* 28677 0x7005 There are no transport support for the input + scheme */ # endif // components/spi_flash/include/esp_spi_flash.h # ifdef ESP_ERR_FLASH_BASE diff --git a/components/esp_http_client/Kconfig b/components/esp_http_client/Kconfig new file mode 100644 index 0000000000..f4e1d1b0a3 --- /dev/null +++ b/components/esp_http_client/Kconfig @@ -0,0 +1,10 @@ +menu "ESP HTTP client" + + +config ESP_HTTP_CLIENT_ENABLE_HTTPS + bool "Enable https" + default y + help + This option will enable https protocol by linking mbedtls library and initializing SSL transport + +endmenu diff --git a/components/esp_http_client/component.mk b/components/esp_http_client/component.mk new file mode 100644 index 0000000000..96b5b6c4c0 --- /dev/null +++ b/components/esp_http_client/component.mk @@ -0,0 +1,6 @@ +# +# Component Makefile +# + +COMPONENT_SRCDIRS := . lib +COMPONENT_PRIV_INCLUDEDIRS := lib/include diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c new file mode 100644 index 0000000000..60d8857fad --- /dev/null +++ b/components/esp_http_client/esp_http_client.c @@ -0,0 +1,972 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include + +#include "esp_system.h" +#include "esp_log.h" + +#include "http_header.h" +#include "transport.h" +#include "transport_tcp.h" +#include "http_utils.h" +#include "http_auth.h" +#include "sdkconfig.h" +#include "transport.h" +#include "esp_http_client.h" + +#ifdef CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS +#include "transport_ssl.h" +#endif + +static const char *TAG = "HTTP_CLIENT"; + +typedef struct { + char *data; + int len; + char *raw_data; + int raw_len; +} esp_http_buffer_t; +/** + * private HTTP Data structure + */ +typedef struct { + http_header_handle_t headers; /*!< http header */ + esp_http_buffer_t *buffer; /*!< data buffer as linked list */ + int status_code; /*!< status code (integer) */ + int content_length; /*!< data length */ + int data_offset; /*!< offset to http data (Skip header) */ + int data_process; /*!< data processed */ + int method; /*!< http method */ + bool is_chunked; +} esp_http_data_t; + +typedef struct { + char *url; + char *scheme; + char *host; + int port; + char *username; + char *password; + char *path; + char *query; + char *cert_pem; + esp_http_client_method_t method; + esp_http_client_auth_type_t auth_type; + esp_http_client_transport_t transport_type; + int max_store_header_size; +} connection_info_t; + +typedef enum { + HTTP_STATE_UNINIT = 0, + HTTP_STATE_INIT, + HTTP_STATE_CONNECTED, + HTTP_STATE_REQ_COMPLETE_HEADER, + HTTP_STATE_REQ_COMPLETE_DATA, + HTTP_STATE_RES_COMPLETE_HEADER, + HTTP_STATE_RES_COMPLETE_DATA, + HTTP_STATE_CLOSE +} esp_http_state_t; +/** + * HTTP client class + */ +struct esp_http_client { + int redirect_counter; + int max_redirection_count; + int process_again; + struct http_parser *parser; + struct http_parser_settings *parser_settings; + transport_list_handle_t transport_list; + transport_handle_t transport; + esp_http_data_t *request; + esp_http_data_t *response; + void *user_data; + esp_http_auth_data_t *auth_data; + char *post_data; + char *location; + char *auth_header; + char *current_header_key; + char *current_header_value; + int post_len; + connection_info_t connection_info; + bool is_chunk_complete; + esp_http_state_t state; + http_event_handle_cb event_handler; + int timeout_ms; + int buffer_size; + bool disable_auto_redirect; + esp_http_client_event_t event; +}; + +typedef struct esp_http_client esp_http_client_t; + +static esp_err_t _clear_connection_info(esp_http_client_handle_t client); +/** + * Default settings + */ +#define DEFAULT_HTTP_PORT (80) +#define DEFAULT_HTTPS_PORT (443) + +static const char *DEFAULT_HTTP_USER_AGENT = "ESP32 HTTP Client/1.0"; +static const char *DEFAULT_HTTP_PROTOCOL = "HTTP/1.1"; +static const char *DEFAULT_HTTP_PATH = "/"; +static int DEFAULT_MAX_REDIRECT = 10; +static int DEFAULT_TIMEOUT_MS = 5000; + +static const char *HTTP_METHOD_MAPPING[] = { + "GET", + "POST", + "PUT", + "PATCH", + "DELETE" +}; + +static esp_err_t http_dispatch_event(esp_http_client_t *client, esp_http_client_event_id_t event_id, void *data, int len) +{ + esp_http_client_event_t *event = &client->event; + + if (client->event_handler) { + event->event_id = event_id; + event->user_data = client->user_data; + event->data = data; + event->data_len = len; + return client->event_handler(event); + } + return ESP_OK; +} + +static int http_on_message_begin(http_parser *parser) +{ + esp_http_client_t *client = parser->data; + ESP_LOGD(TAG, "on_message_begin"); + + client->response->is_chunked = false; + client->is_chunk_complete = false; + return 0; +} + +static int http_on_url(http_parser *parser, const char *at, size_t length) +{ + ESP_LOGD(TAG, "http_on_url"); + return 0; +} + +static int http_on_status(http_parser *parser, const char *at, size_t length) +{ + return 0; +} + +static int http_on_header_field(http_parser *parser, const char *at, size_t length) +{ + esp_http_client_t *client = parser->data; + http_utils_assign_string(&client->current_header_key, at, length); + + return 0; +} + +static int http_on_header_value(http_parser *parser, const char *at, size_t length) +{ + esp_http_client_handle_t client = parser->data; + if (client->current_header_key == NULL) { + return 0; + } + if (strcasecmp(client->current_header_key, "Location") == 0) { + http_utils_assign_string(&client->location, at, length); + } else if (strcasecmp(client->current_header_key, "Transfer-Encoding") == 0 + && memcmp(at, "chunked", length) == 0) { + client->response->is_chunked = true; + } else if (strcasecmp(client->current_header_key, "WWW-Authenticate") == 0) { + http_utils_assign_string(&client->auth_header, at, length); + } + http_utils_assign_string(&client->current_header_value, at, length); + + ESP_LOGD(TAG, "HEADER=%s:%s", client->current_header_key, client->current_header_value); + client->event.header_key = client->current_header_key; + client->event.header_value = client->current_header_value; + http_dispatch_event(client, HTTP_EVENT_ON_HEADER, NULL, 0); + free(client->current_header_key); + free(client->current_header_value); + client->current_header_key = NULL; + client->current_header_value = NULL; + return 0; +} + +static int http_on_headers_complete(http_parser *parser) +{ + esp_http_client_handle_t client = parser->data; + client->response->status_code = parser->status_code; + client->response->data_offset = parser->nread; + client->response->content_length = parser->content_length; + client->response->data_process = 0; + ESP_LOGD(TAG, "http_on_headers_complete, status=%d, offset=%d, nread=%d", parser->status_code, client->response->data_offset, parser->nread); + client->state = HTTP_STATE_RES_COMPLETE_HEADER; + return 0; +} + +static int http_on_body(http_parser *parser, const char *at, size_t length) +{ + esp_http_client_t *client = parser->data; + ESP_LOGD(TAG, "http_on_body %d", length); + client->response->buffer->raw_data = (char*)at; + client->response->buffer->raw_len = length; + client->response->data_process += length; + http_dispatch_event(client, HTTP_EVENT_ON_DATA, (void *)at, length); + return 0; +} + +static int http_on_message_complete(http_parser *parser) +{ + ESP_LOGD(TAG, "http_on_message_complete, parser=%x", (int)parser); + esp_http_client_handle_t client = parser->data; + client->is_chunk_complete = true; + return 0; +} + +static int http_on_chunk_complete(http_parser *parser) +{ + ESP_LOGD(TAG, "http_on_chunk_complete"); + return 0; +} + +esp_err_t esp_http_client_set_header(esp_http_client_handle_t client, const char *key, const char *value) +{ + return http_header_set(client->request->headers, key, value); +} + +esp_err_t esp_http_client_delete_header(esp_http_client_handle_t client, const char *key) +{ + return http_header_delete(client->request->headers, key); +} + +static esp_err_t _set_config(esp_http_client_handle_t client, esp_http_client_config_t *config) +{ + client->connection_info.method = config->method; + client->connection_info.port = config->port; + client->connection_info.auth_type = config->auth_type; + client->event_handler = config->event_handler; + client->timeout_ms = config->timeout_ms; + client->max_redirection_count = config->max_redirection_count; + client->user_data = config->user_data; + client->buffer_size = config->buffer_size; + client->disable_auto_redirect = config->disable_auto_redirect; + + if (config->buffer_size == 0) { + client->buffer_size = DEFAULT_HTTP_BUF_SIZE; + } + + if (client->max_redirection_count == 0) { + client->max_redirection_count = DEFAULT_MAX_REDIRECT; + } + + if (config->path) { + client->connection_info.path = strdup(config->path); + } else { + client->connection_info.path = strdup(DEFAULT_HTTP_PATH); + } + HTTP_MEM_CHECK(TAG, client->connection_info.path, { + return ESP_ERR_NO_MEM; + }); + + if (config->host) { + client->connection_info.host = strdup(config->host); + + HTTP_MEM_CHECK(TAG, client->connection_info.host, { + _clear_connection_info(client); + return ESP_ERR_NO_MEM; + }); + } + + if (config->query) { + client->connection_info.query = strdup(config->query); + HTTP_MEM_CHECK(TAG, client->connection_info.query, { + _clear_connection_info(client); + return ESP_ERR_NO_MEM; + }); + } + + if (config->username) { + client->connection_info.username = strdup(config->username); + HTTP_MEM_CHECK(TAG, client->connection_info.username, { + _clear_connection_info(client); + return ESP_ERR_NO_MEM; + }); + } + + if (config->password) { + client->connection_info.password = strdup(config->password); + HTTP_MEM_CHECK(TAG, client->connection_info.password, { + _clear_connection_info(client); + return ESP_ERR_NO_MEM; + }); + } + + if (config->transport_type == HTTP_TRANSPORT_OVER_SSL) { + http_utils_assign_string(&client->connection_info.scheme, "https", 0); + if (client->connection_info.port == 0) { + client->connection_info.port = DEFAULT_HTTPS_PORT; + } + } else { + http_utils_assign_string(&client->connection_info.scheme, "http", 0); + if (client->connection_info.port == 0) { + client->connection_info.port = DEFAULT_HTTP_PORT; + } + } + if (client->timeout_ms == 0) { + client->timeout_ms = DEFAULT_TIMEOUT_MS; + } + + return ESP_OK; +} + +static esp_err_t _clear_connection_info(esp_http_client_handle_t client) +{ + free(client->connection_info.path); + free(client->connection_info.host); + free(client->connection_info.query); + free(client->connection_info.username); + if (client->connection_info.password) { + memset(client->connection_info.password, 0, strlen(client->connection_info.password)); + free(client->connection_info.password); + } + free(client->connection_info.scheme); + free(client->connection_info.url); + memset(&client->connection_info, 0, sizeof(connection_info_t)); + return ESP_OK; +} + +static esp_err_t _clear_auth_data(esp_http_client_handle_t client) +{ + if (client->auth_data == NULL) { + return ESP_FAIL; + } + + free(client->auth_data->method); + free(client->auth_data->realm); + free(client->auth_data->algorithm); + free(client->auth_data->qop); + free(client->auth_data->nonce); + free(client->auth_data->opaque); + memset(client->auth_data, 0, sizeof(esp_http_auth_data_t)); + return ESP_OK; +} + +static esp_err_t esp_http_client_prepare(esp_http_client_handle_t client) +{ + client->process_again = 0; + client->response->data_process = 0; + http_parser_init(client->parser, HTTP_RESPONSE); + if (client->connection_info.username) { + char *auth_response = NULL; + + if (client->connection_info.auth_type == HTTP_AUTH_TYPE_BASIC) { + auth_response = http_auth_basic(client->connection_info.username, client->connection_info.password); + } else if (client->connection_info.auth_type == HTTP_AUTH_TYPE_DIGEST && client->auth_data) { + client->auth_data->uri = client->connection_info.path; + client->auth_data->cnonce = ((uint64_t)esp_random() << 32) + esp_random(); + auth_response = http_auth_digest(client->connection_info.username, client->connection_info.password, client->auth_data); + client->auth_data->nc ++; + } + + if (auth_response) { + ESP_LOGD(TAG, "auth_response=%s", auth_response); + esp_http_client_set_header(client, "Authorization", auth_response); + free(auth_response); + } + } + return ESP_OK; +} + +esp_http_client_handle_t esp_http_client_init(esp_http_client_config_t *config) +{ + + esp_http_client_handle_t client; + transport_handle_t tcp; + bool _success; + + _success = ( + (client = calloc(1, sizeof(esp_http_client_t))) && + (client->parser = calloc(1, sizeof(struct http_parser))) && + (client->parser_settings = calloc(1, sizeof(struct http_parser_settings))) && + (client->auth_data = calloc(1, sizeof(esp_http_auth_data_t))) && + (client->request = calloc(1, sizeof(esp_http_data_t))) && + (client->request->headers = http_header_init()) && + (client->request->buffer = calloc(1, sizeof(esp_http_buffer_t))) && + (client->response = calloc(1, sizeof(esp_http_data_t))) && + (client->response->headers = http_header_init()) && + (client->response->buffer = calloc(1, sizeof(esp_http_buffer_t))) + ); + + if (!_success) { + ESP_LOGE(TAG, "Error allocate memory"); + esp_http_client_cleanup(client); + return NULL; + } + + _success = ( + (client->transport_list = transport_list_init()) && + (tcp = transport_tcp_init()) && + (transport_set_default_port(tcp, DEFAULT_HTTP_PORT) == ESP_OK) && + (transport_list_add(client->transport_list, tcp, "http") == ESP_OK) + ); + if (!_success) { + ESP_LOGE(TAG, "Error initialize transport"); + esp_http_client_cleanup(client); + return NULL; + } +#ifdef CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS + transport_handle_t ssl; + _success = ( + (ssl = transport_ssl_init()) && + (transport_set_default_port(ssl, DEFAULT_HTTPS_PORT) == ESP_OK) && + (transport_list_add(client->transport_list, ssl, "https") == ESP_OK) + ); + + if (!_success) { + ESP_LOGE(TAG, "Error initialize SSL Transport"); + esp_http_client_cleanup(client); + return NULL; + } + + if (config->cert_pem) { + transport_ssl_set_cert_data(ssl, config->cert_pem, strlen(config->cert_pem)); + } +#endif + + if (_set_config(client, config) != ESP_OK) { + ESP_LOGE(TAG, "Error set configurations"); + esp_http_client_cleanup(client); + return NULL; + } + _success = ( + (client->request->buffer->data = malloc(client->buffer_size)) && + (client->response->buffer->data = malloc(client->buffer_size)) + ); + + if (!_success) { + ESP_LOGE(TAG, "Allocation failed"); + esp_http_client_cleanup(client); + return NULL; + } + + _success = ( + (esp_http_client_set_url(client, config->url) == ESP_OK) && + (esp_http_client_set_header(client, "User-Agent", DEFAULT_HTTP_USER_AGENT) == ESP_OK) && + (esp_http_client_set_header(client, "Host", client->connection_info.host) == ESP_OK) + ); + + if (!_success) { + ESP_LOGE(TAG, "Error set default configurations"); + esp_http_client_cleanup(client); + return NULL; + } + + client->parser_settings->on_message_begin = http_on_message_begin; + client->parser_settings->on_url = http_on_url; + client->parser_settings->on_status = http_on_status; + client->parser_settings->on_header_field = http_on_header_field; + client->parser_settings->on_header_value = http_on_header_value; + client->parser_settings->on_headers_complete = http_on_headers_complete; + client->parser_settings->on_body = http_on_body; + client->parser_settings->on_message_complete = http_on_message_complete; + client->parser_settings->on_chunk_complete = http_on_chunk_complete; + client->parser->data = client; + client->event.client = client; + + client->state = HTTP_STATE_INIT; + return client; +} + +esp_err_t esp_http_client_cleanup(esp_http_client_handle_t client) +{ + if (client == NULL) { + return ESP_FAIL; + } + esp_http_client_close(client); + transport_list_destroy(client->transport_list); + http_header_destroy(client->request->headers); + free(client->request->buffer->data); + free(client->request->buffer); + free(client->request); + http_header_destroy(client->response->headers); + free(client->response->buffer->data); + free(client->response->buffer); + free(client->response); + + free(client->parser); + free(client->parser_settings); + _clear_connection_info(client); + _clear_auth_data(client); + free(client->auth_data); + free(client->current_header_key); + free(client->location); + free(client->auth_header); + free(client); + return ESP_OK; +} + +static esp_err_t esp_http_check_response(esp_http_client_handle_t client) +{ + char *auth_header = NULL; + + if (client->redirect_counter >= client->max_redirection_count || client->disable_auto_redirect) { + ESP_LOGE(TAG, "Error, reach max_redirection_count count=%d", client->redirect_counter); + return ESP_ERR_HTTP_MAX_REDIRECT; + } + switch (client->response->status_code) { + case 301: + case 302: + ESP_LOGI(TAG, "Redirect to %s", client->location); + esp_http_client_set_url(client, client->location); + client->redirect_counter ++; + client->process_again = 1; + break; + case 401: + auth_header = client->auth_header; + http_utils_trim_whitespace(&auth_header); + ESP_LOGI(TAG, "UNAUTHORIZED: %s", auth_header); + client->redirect_counter ++; + if (auth_header) { + if (http_utils_str_starts_with(auth_header, "Digest") == 0) { + ESP_LOGD(TAG, "type = Digest"); + client->connection_info.auth_type = HTTP_AUTH_TYPE_DIGEST; + } else if (http_utils_str_starts_with(auth_header, "Basic") == 0) { + ESP_LOGD(TAG, "type = Basic"); + client->connection_info.auth_type = HTTP_AUTH_TYPE_BASIC; + } else { + client->connection_info.auth_type = HTTP_AUTH_TYPE_NONE; + ESP_LOGE(TAG, "Unsupport Auth Type"); + break; + } + + _clear_auth_data(client); + + client->auth_data->method = strdup(HTTP_METHOD_MAPPING[client->connection_info.method]); + + client->auth_data->nc = 1; + client->auth_data->realm = http_utils_get_string_between(auth_header, "realm=\"", "\""); + client->auth_data->algorithm = http_utils_get_string_between(auth_header, "algorithm=", ","); + client->auth_data->qop = http_utils_get_string_between(auth_header, "qop=\"", "\""); + client->auth_data->nonce = http_utils_get_string_between(auth_header, "nonce=\"", "\""); + client->auth_data->opaque = http_utils_get_string_between(auth_header, "opaque=\"", "\""); + client->process_again = 1; + } + } + return ESP_OK; +} + +esp_err_t esp_http_client_set_url(esp_http_client_handle_t client, const char *url) +{ + char *old_host = NULL; + struct http_parser_url purl; + int old_port; + + if (client == NULL || url == NULL) { + ESP_LOGE(TAG, "client or url must not NULL"); + return ESP_ERR_INVALID_ARG; + } + + http_parser_url_init(&purl); + + int parser_status = http_parser_parse_url(url, strlen(url), 0, &purl); + + if (parser_status != 0) { + ESP_LOGE(TAG, "Error parse url %s", url); + return ESP_ERR_INVALID_ARG; + } + old_host = client->connection_info.host; + old_port = client->connection_info.port; + + if (purl.field_data[UF_HOST].len) { + http_utils_assign_string(&client->connection_info.host, url + purl.field_data[UF_HOST].off, purl.field_data[UF_HOST].len); + HTTP_MEM_CHECK(TAG, client->connection_info.host, return ESP_ERR_NO_MEM); + } + // Close the connection if host was changed + if (old_host && client->connection_info.host + && strcasecmp(old_host, (const void *)client->connection_info.host) != 0) { + ESP_LOGD(TAG, "New host assign = %s", client->connection_info.host); + if (esp_http_client_set_header(client, "Host", client->connection_info.host) != ESP_OK) { + return ESP_ERR_NO_MEM; + } + esp_http_client_close(client); + } + + if (purl.field_data[UF_SCHEMA].len) { + http_utils_assign_string(&client->connection_info.scheme, url + purl.field_data[UF_SCHEMA].off, purl.field_data[UF_SCHEMA].len); + HTTP_MEM_CHECK(TAG, client->connection_info.scheme, return ESP_ERR_NO_MEM); + + if (strcasecmp(client->connection_info.scheme, "http") == 0) { + client->connection_info.port = DEFAULT_HTTP_PORT; + } else if (strcasecmp(client->connection_info.scheme, "https") == 0) { + client->connection_info.port = DEFAULT_HTTPS_PORT; + } + } + + if (purl.field_data[UF_PORT].len) { + client->connection_info.port = strtol((const char*)(url + purl.field_data[UF_PORT].off), NULL, 10); + } + + if (old_port != client->connection_info.port) { + esp_http_client_close(client); + } + + if (purl.field_data[UF_USERINFO].len) { + char *user_info = NULL; + http_utils_assign_string(&user_info, url + purl.field_data[UF_USERINFO].off, purl.field_data[UF_USERINFO].len); + if (user_info) { + char *username = user_info; + char *password = strchr(user_info, ':'); + if (password) { + *password = 0; + password ++; + http_utils_assign_string(&client->connection_info.password, password, 0); + HTTP_MEM_CHECK(TAG, client->connection_info.password, return ESP_ERR_NO_MEM); + } + http_utils_assign_string(&client->connection_info.username, username, 0); + HTTP_MEM_CHECK(TAG, client->connection_info.username, return ESP_ERR_NO_MEM); + free(user_info); + } else { + return ESP_ERR_NO_MEM; + } + } else { + free(client->connection_info.username); + free(client->connection_info.password); + client->connection_info.username = NULL; + client->connection_info.password = NULL; + } + + + //Reset path and query if there are no information + if (purl.field_data[UF_PATH].len) { + http_utils_assign_string(&client->connection_info.path, url + purl.field_data[UF_PATH].off, purl.field_data[UF_PATH].len); + } else { + http_utils_assign_string(&client->connection_info.path, "/", 0); + } + HTTP_MEM_CHECK(TAG, client->connection_info.path, return ESP_ERR_NO_MEM); + + if (purl.field_data[UF_QUERY].len) { + http_utils_assign_string(&client->connection_info.query, url + purl.field_data[UF_QUERY].off, purl.field_data[UF_QUERY].len); + HTTP_MEM_CHECK(TAG, client->connection_info.query, return ESP_ERR_NO_MEM); + } else if (client->connection_info.query) { + free(client->connection_info.query); + client->connection_info.query = NULL; + } + + return ESP_OK; +} + +esp_err_t esp_http_client_set_method(esp_http_client_handle_t client, esp_http_client_method_t method) +{ + client->connection_info.method = method; + return ESP_OK; +} + +static int esp_http_client_get_data(esp_http_client_handle_t client) +{ + if (client->state < HTTP_STATE_RES_COMPLETE_HEADER) { + return -1; + } + esp_http_buffer_t *res_buffer = client->response->buffer; + + ESP_LOGD(TAG, "data_process=%d, content_length=%d", client->response->data_process, client->response->content_length); + + int rlen = transport_read(client->transport, res_buffer->data, client->buffer_size, client->timeout_ms); + if (rlen >= 0) { + http_parser_execute(client->parser, client->parser_settings, res_buffer->data, rlen); + } + return rlen; +} + +int esp_http_client_read(esp_http_client_handle_t client, char *buffer, int len) +{ + esp_http_buffer_t *res_buffer = client->response->buffer; + + int rlen = -1, ridx = 0; + if (res_buffer->raw_len) { + int remain_len = client->response->buffer->raw_len; + if (remain_len > len) { + remain_len = len; + } + memcpy(buffer, res_buffer->raw_data, remain_len); + res_buffer->raw_len -= remain_len; + res_buffer->raw_data += remain_len; + ridx = remain_len; + } + int need_read = len - ridx; + bool is_data_remain = true; + while (need_read > 0 && is_data_remain) { + if (client->response->is_chunked) { + is_data_remain = !client->is_chunk_complete; + } else { + is_data_remain = client->response->data_process < client->response->content_length; + } + ESP_LOGD(TAG, "is_data_remain=%d, is_chunked=%d", is_data_remain, client->response->is_chunked); + if (!is_data_remain) { + break; + } + int byte_to_read = need_read; + if (byte_to_read > client->buffer_size) { + byte_to_read = client->buffer_size; + } + rlen = transport_read(client->transport, res_buffer->data, byte_to_read, client->timeout_ms); + ESP_LOGD(TAG, "need_read=%d, byte_to_read=%d, rlen=%d, ridx=%d", need_read, byte_to_read, rlen, ridx); + + if (rlen <= 0) { + return ridx; + } + http_parser_execute(client->parser, client->parser_settings, res_buffer->data, rlen); + + if (res_buffer->raw_len) { + memcpy(buffer + ridx, res_buffer->raw_data, res_buffer->raw_len); + ridx += res_buffer->raw_len; + need_read -= res_buffer->raw_len; + } + res_buffer->raw_len = 0; //clear + } + + return ridx; +} + +esp_err_t esp_http_client_perform(esp_http_client_handle_t client) +{ + esp_err_t err; + do { + if ((err = esp_http_client_open(client, client->post_len)) != ESP_OK) { + return err; + } + if (client->post_data && client->post_len) { + if (esp_http_client_write(client, client->post_data, client->post_len) <= 0) { + ESP_LOGE(TAG, "Error upload data"); + return ESP_ERR_HTTP_WRITE_DATA; + } + } + if (esp_http_client_fetch_headers(client) < 0) { + return ESP_ERR_HTTP_FETCH_HEADER; + } + + if ((err = esp_http_check_response(client)) != ESP_OK) { + ESP_LOGE(TAG, "Error response"); + return err; + } + while (client->response->is_chunked && !client->is_chunk_complete) { + if (esp_http_client_get_data(client) <= 0) { + ESP_LOGD(TAG, "Read finish or server requests close"); + break; + } + } + while (client->response->data_process < client->response->content_length) { + if (esp_http_client_get_data(client) <= 0) { + ESP_LOGD(TAG, "Read finish or server requests close"); + break; + } + } + + http_dispatch_event(client, HTTP_EVENT_ON_FINISH, NULL, 0); + + if (!http_should_keep_alive(client->parser)) { + ESP_LOGD(TAG, "Close connection"); + esp_http_client_close(client); + } else { + if (client->state > HTTP_STATE_CONNECTED) { + client->state = HTTP_STATE_CONNECTED; + } + } + } while (client->process_again); + return ESP_OK; +} + + +int esp_http_client_fetch_headers(esp_http_client_handle_t client) +{ + if (client->state < HTTP_STATE_REQ_COMPLETE_HEADER) { + return -1; + } + + client->state = HTTP_STATE_REQ_COMPLETE_DATA; + esp_http_buffer_t *buffer = client->response->buffer; + client->response->status_code = -1; + + while (client->state < HTTP_STATE_RES_COMPLETE_HEADER) { + buffer->len = transport_read(client->transport, buffer->data, client->buffer_size, client->timeout_ms); + if (buffer->len <= 0) { + return -1; + } + http_parser_execute(client->parser, client->parser_settings, buffer->data, buffer->len); + } + ESP_LOGD(TAG, "content_length = %d", client->response->content_length); + if (client->response->content_length <= 0) { + client->response->is_chunked = true; + return 0; + } + return client->response->content_length; +} + +esp_err_t esp_http_client_open(esp_http_client_handle_t client, int write_len) +{ + esp_err_t err; + if (client->state == HTTP_STATE_UNINIT) { + ESP_LOGE(TAG, "Client has not been initialized"); + return ESP_ERR_INVALID_STATE; + } + + if ((err = esp_http_client_prepare(client)) != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize request data"); + esp_http_client_close(client); + return err; + } + + if (client->state < HTTP_STATE_CONNECTED) { + ESP_LOGD(TAG, "Begin connect to: %s://%s:%d", client->connection_info.scheme, client->connection_info.host, client->connection_info.port); + client->transport = transport_list_get_transport(client->transport_list, client->connection_info.scheme); + if (client->transport == NULL) { + ESP_LOGE(TAG, "No transport found"); + return ESP_ERR_HTTP_INVALID_TRANSPORT; + } + if (transport_connect(client->transport, client->connection_info.host, client->connection_info.port, client->timeout_ms) < 0) { + ESP_LOGE(TAG, "Connection failed, sock < 0"); + return ESP_ERR_HTTP_CONNECT; + } + http_dispatch_event(client, HTTP_EVENT_ON_CONNECTED, NULL, 0); + client->state = HTTP_STATE_CONNECTED; + } + + if (write_len >= 0) { + http_header_set_format(client->request->headers, "Content-Length", "%d", write_len); + } else if (write_len < 0) { + esp_http_client_set_header(client, "Transfer-Encoding", "chunked"); + esp_http_client_set_method(client, HTTP_METHOD_POST); + } + + int header_index = 0; + int wlen = client->buffer_size; + + const char *method = HTTP_METHOD_MAPPING[client->connection_info.method]; + + int first_line = snprintf(client->request->buffer->data, + client->buffer_size, "%s %s", + method, + client->connection_info.path); + if (first_line > client->buffer_size) { + ESP_LOGE(TAG, "Out of buffer"); + return ESP_ERR_HTTP_CONNECT; + } + + if (client->connection_info.query) { + first_line += snprintf(client->request->buffer->data + first_line, + client->buffer_size - first_line, "?%s", client->connection_info.query); + if (first_line > client->buffer_size) { + ESP_LOGE(TAG, "Out of buffer"); + return ESP_ERR_HTTP_CONNECT; + } + } + first_line += snprintf(client->request->buffer->data + first_line, + client->buffer_size - first_line, " %s\r\n", DEFAULT_HTTP_PROTOCOL); + if (first_line > client->buffer_size) { + ESP_LOGE(TAG, "Out of buffer"); + return ESP_ERR_HTTP_CONNECT; + } + wlen -= first_line; + + while ((header_index = http_header_generate_string(client->request->headers, header_index, client->request->buffer->data + first_line, &wlen))) { + if (wlen <= 0) { + break; + } + if (first_line) { + wlen += first_line; + first_line = 0; + } + client->request->buffer->data[wlen] = 0; + ESP_LOGD(TAG, "Write header[%d]: %s", header_index, client->request->buffer->data); + if (transport_write(client->transport, client->request->buffer->data, wlen, client->timeout_ms) <= 0) { + ESP_LOGE(TAG, "Error write request"); + esp_http_client_close(client); + return ESP_ERR_HTTP_WRITE_DATA; + } + wlen = client->buffer_size; + } + client->state = HTTP_STATE_REQ_COMPLETE_HEADER; + return ESP_OK; +} + + +int esp_http_client_write(esp_http_client_handle_t client, const char *buffer, int len) +{ + if (client->state < HTTP_STATE_REQ_COMPLETE_HEADER) { + return -1; + } + int need_write; + int wlen = 0, widx = 0; + while (len > 0) { + need_write = len; + if (need_write > client->buffer_size) { + need_write = client->buffer_size; + } + wlen = transport_write(client->transport, buffer + widx, need_write, client->timeout_ms); + if (wlen <= 0) { + return wlen; + } + widx += wlen; + len -= wlen; + } + return widx; +} + +esp_err_t esp_http_client_close(esp_http_client_handle_t client) +{ + if (client->state >= HTTP_STATE_INIT) { + http_dispatch_event(client, HTTP_EVENT_DISCONNECTED, NULL, 0); + client->state = HTTP_STATE_INIT; + return transport_close(client->transport); + } + return ESP_OK; +} + +esp_err_t esp_http_client_set_post_field(esp_http_client_handle_t client, const char *data, int len) +{ + esp_err_t err = ESP_OK; + client->post_data = (char *)data; + client->post_len = len; + ESP_LOGD(TAG, "set post file length = %d", len); + if (client->post_data) { + err = esp_http_client_set_header(client, "Content-Type", "application/x-www-form-urlencoded"); + } else { + client->post_len = 0; + err = esp_http_client_set_header(client, "Content-Type", NULL); + } + return err; +} + +int esp_http_client_get_post_field(esp_http_client_handle_t client, char **data) +{ + if (client->post_data) { + *data = client->post_data; + return client->post_len; + } + return 0; +} + +int esp_http_client_get_status_code(esp_http_client_handle_t client) +{ + return client->response->status_code; +} + +int esp_http_client_get_content_length(esp_http_client_handle_t client) +{ + return client->response->content_length; +} + +bool esp_http_client_is_chunked_response(esp_http_client_handle_t client) +{ + return client->response->is_chunked; +} diff --git a/components/esp_http_client/include/esp_http_client.h b/components/esp_http_client/include/esp_http_client.h new file mode 100644 index 0000000000..2690cfe5d9 --- /dev/null +++ b/components/esp_http_client/include/esp_http_client.h @@ -0,0 +1,343 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _ESP_HTTP_CLIENT_H +#define _ESP_HTTP_CLIENT_H + +#include "freertos/FreeRTOS.h" +#include "http_parser.h" +#include "sdkconfig.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define DEFAULT_HTTP_BUF_SIZE (512) + +typedef struct esp_http_client *esp_http_client_handle_t; +typedef struct esp_http_client_event *esp_http_client_event_handle_t; + +/** + * @brief HTTP Client events id + */ +typedef enum { + HTTP_EVENT_ERROR = 0, /*!< This event occurs when there are any errors during execution */ + HTTP_EVENT_ON_CONNECTED, /*!< Once the HTTP has been connected to the server, no data exchange has been performed */ + HTTP_EVENT_HEADER_SENT, /*!< After sending all the headers to the server */ + HTTP_EVENT_ON_HEADER, /*!< Occurs when receiving each header sent from the server */ + HTTP_EVENT_ON_DATA, /*!< Occurs when receiving data from the server, possibly multiple portions of the packet */ + HTTP_EVENT_ON_FINISH, /*!< Occurs when finish a HTTP session */ + HTTP_EVENT_DISCONNECTED, /*!< The connection has been disconnected */ +} esp_http_client_event_id_t; + +/** + * @brief HTTP Client events data + */ +typedef struct esp_http_client_event { + esp_http_client_event_id_t event_id; /*!< event_id, to know the cause of the event */ + esp_http_client_handle_t client; /*!< esp_http_client_handle_t context */ + void *data; /*!< data of the event */ + int data_len; /*!< data length of data */ + void *user_data; /*!< user_data context, from esp_http_client_config_t user_data */ + char *header_key; /*!< For HTTP_EVENT_ON_HEADER event_id, it's store current http header key */ + char *header_value; /*!< For HTTP_EVENT_ON_HEADER event_id, it's store current http header value */ +} esp_http_client_event_t; + + +/** + * @brief HTTP Client transport + */ +typedef enum { + HTTP_TRANSPORT_UNKNOWN = 0x0, /*!< Unknown */ + HTTP_TRANSPORT_OVER_TCP, /*!< Transport over tcp */ + HTTP_TRANSPORT_OVER_SSL, /*!< Transport over ssl */ +} esp_http_client_transport_t; + +typedef esp_err_t (*http_event_handle_cb)(esp_http_client_event_t *evt); + +/** + * @brief HTTP method + */ +typedef enum { + HTTP_METHOD_GET = 0, /*!< HTTP GET Method */ + HTTP_METHOD_POST, /*!< HTTP POST Method */ + HTTP_METHOD_PUT, /*!< HTTP PUT Method */ + HTTP_METHOD_PATCH, /*!< HTTP PATCH Method */ + HTTP_METHOD_DELETE, /*!< HTTP DELETE Method */ + HTTP_METHOD_MAX, +} esp_http_client_method_t; + +/** + * @brief HTTP Authentication type + */ +typedef enum { + HTTP_AUTH_TYPE_NONE = 0, /*!< No authention */ + HTTP_AUTH_TYPE_BASIC, /*!< HTTP Basic authentication */ + HTTP_AUTH_TYPE_DIGEST, /*!< HTTP Disgest authentication */ +} esp_http_client_auth_type_t; + +/** + * @brief HTTP configuration + */ +typedef struct { + const char *url; /*!< HTTP URL, the information on the URL is most important, it overrides the other fields below, if any */ + const char *host; /*!< Domain or IP as string */ + int port; /*!< Port to connect, default depend on esp_http_client_transport_t (80 or 443) */ + const char *username; /*!< Using for Http authentication */ + const char *password; /*!< Using for Http authentication */ + esp_http_client_auth_type_t auth_type; /*!< Http authentication type, see `esp_http_client_auth_type_t` */ + const char *path; /*!< HTTP Path, if not set, default is `/` */ + const char *query; /*!< HTTP query */ + const char *cert_pem; /*!< SSL Certification, PEM format as string, if the client requires to verify server */ + esp_http_client_method_t method; /*!< HTTP Method */ + int timeout_ms; /*!< Network timeout in milliseconds */ + bool disable_auto_redirect; /*!< Disable HTTP automatic redirects */ + int max_redirection_count; /*!< Max redirection number, using default value if zero*/ + http_event_handle_cb event_handler; /*!< HTTP Event Handle */ + esp_http_client_transport_t transport_type; /*!< HTTP transport type, see `esp_http_client_transport_t` */ + int buffer_size; /*!< HTTP buffer size (both send and receive) */ + void *user_data; /*!< HTTP user_data context */ +} esp_http_client_config_t; + + +#define ESP_ERR_HTTP_BASE (0x7000) /*!< Starting number of HTTP error codes */ +#define ESP_ERR_HTTP_MAX_REDIRECT (ESP_ERR_HTTP_BASE + 1) /*!< The error exceeds the number of HTTP redirects */ +#define ESP_ERR_HTTP_CONNECT (ESP_ERR_HTTP_BASE + 2) /*!< Error open the HTTP connection */ +#define ESP_ERR_HTTP_WRITE_DATA (ESP_ERR_HTTP_BASE + 3) /*!< Error write HTTP data */ +#define ESP_ERR_HTTP_FETCH_HEADER (ESP_ERR_HTTP_BASE + 4) /*!< Error read HTTP header from server */ +#define ESP_ERR_HTTP_INVALID_TRANSPORT (ESP_ERR_HTTP_BASE + 5) /*!< There are no transport support for the input scheme */ + +/** + * @brief Start a HTTP session + * This function must be the first function to call, + * and it returns a esp_http_client_handle_t that you must use as input to other functions in the interface. + * This call MUST have a corresponding call to esp_http_client_cleanup when the operation is complete. + * + * @param[in] config The configurations, see `http_client_config_t` + * + * @return + * - `esp_http_client_handle_t` + * - NULL if any errors + */ +esp_http_client_handle_t esp_http_client_init(esp_http_client_config_t *config); + +/** + * @brief Invoke this function after `esp_http_client_init` and all the options calls are made, and will perform the + * transfer as described in the options. It must be called with the same esp_http_client_handle_t as input as the esp_http_client_init call returned. + * esp_http_client_perform performs the entire request in a blocking manner and returns when done, or if it failed. + * You can do any amount of calls to esp_http_client_perform while using the same esp_http_client_handle_t. The underlying connection may be kept open if the server allows it. + * If you intend to transfer more than one file, you are even encouraged to do so. + * esp_http_client will then attempt to re-use the same connection for the following transfers, thus making the operations faster, less CPU intense and using less network resources. + * Just note that you will have to use `esp_http_client_set_**` between the invokes to set options for the following esp_http_client_perform. + * + * @note You must never call this function simultaneously from two places using the same client handle. + * Let the function return first before invoking it another time. + * If you want parallel transfers, you must use several esp_http_client_handle_t. + * This function include `esp_http_client_open` -> `esp_http_client_write` -> `esp_http_client_fetch_headers` -> `esp_http_client_read` (and option) `esp_http_client_close`. + * + * @param client The esp_http_client handle + * + * @return + * - ESP_OK on successful + * - ESP_FAIL on error + */ +esp_err_t esp_http_client_perform(esp_http_client_handle_t client); + +/** + * @brief Set URL for client, when performing this behavior, the options in the URL will replace the old ones + * + * @param[in] client The esp_http_client handle + * @param[in] url The url + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t esp_http_client_set_url(esp_http_client_handle_t client, const char *url); + +/** + * @brief Set post data, this function must be called before `esp_http_client_finalize_open` or perform + * Note: The data parameter passed to this function is a pointer and this function will not copy the data + * + * @param[in] client The esp_http_client handle + * @param[in] data post data pointer + * @param[in] len post length + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t esp_http_client_set_post_field(esp_http_client_handle_t client, const char *data, int len); + +/** + * @brief Get current post field information + * + * @param[in] client The client + * @param[out] data Point to post data pointer + * + * @return Size of post data + */ +int esp_http_client_get_post_field(esp_http_client_handle_t client, char **data); + +/** + * @brief Set http request header, this function must be called after esp_http_client_init and before any + * perform function + * + * @param[in] client The esp_http_client handle + * @param[in] key The header key + * @param[in] value The header value + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t esp_http_client_set_header(esp_http_client_handle_t client, const char *key, const char *value); + +/** + * @brief Set http request method + * + * @param[in] client The esp_http_client handle + * @param[in] method The method + * + * @return ESP_OK + */ +esp_err_t esp_http_client_set_method(esp_http_client_handle_t client, esp_http_client_method_t method); + +/** + * @brief Delete http request header + * + * @param[in] client The esp_http_client handle + * @param[in] key The key + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t esp_http_client_delete_header(esp_http_client_handle_t client, const char *key); + +/** + * @brief This function will be open the connection, write all header strings and return + * + * @param[in] client The esp_http_client handle + * @param[in] write_len HTTP Content length need to write to the server + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t esp_http_client_open(esp_http_client_handle_t client, int write_len); + +/** + * @brief This function will write data to the HTTP connection previously opened by esp_http_client_open() + * + * @param[in] client The esp_http_client handle + * @param buffer The buffer + * @param[in] len This value must not be larger than the write_len parameter provided to esp_http_client_open() + * + * @return + * - (-1) if any errors + * - Length of data written + */ +int esp_http_client_write(esp_http_client_handle_t client, const char *buffer, int len); + +/** + * @brief This function need to call after esp_http_client_open, it will read from http stream, process all receive headers + * + * @param[in] client The esp_http_client handle + * + * @return + * - (-1) if stream doesn't contain content-length header, or chunked encoding (checked by `esp_http_client_is_chunked` response) + * - Download data length defined by content-length header + */ +int esp_http_client_fetch_headers(esp_http_client_handle_t client); + + +/** + * @brief Check response data is chunked, must call after `esp_http_client_finalize_open` + * + * @param[in] client The esp_http_client handle + * + * @return true or false + */ +bool esp_http_client_is_chunked_response(esp_http_client_handle_t client); + +/** + * @brief Read data from http stream + * + * @param[in] client The esp_http_client handle + * @param buffer The buffer + * @param[in] len The length + * + * @return + * - (-1) if any errors + * - Length of data was read + */ +int esp_http_client_read(esp_http_client_handle_t client, char *buffer, int len); + + +/** + * @brief Get http response status code, the valid value if this function invoke after `esp_http_client_perform` or `esp_http_client_finalize_open` + * + * @param[in] client The esp_http_client handle + * + * @return Status code + */ +int esp_http_client_get_status_code(esp_http_client_handle_t client); + +/** + * @brief Get http response content length (from header Content-Length) + * the valid value if this function invoke after `esp_http_client_perform` or `esp_http_client_finalize_open` + * + * @param[in] client The esp_http_client handle + * + * @return + * - (-1) Chunked transfer + * - Content-Length value as bytes + */ +int esp_http_client_get_content_length(esp_http_client_handle_t client); + +/** + * @brief Close http connection, still kept all http request resources + * + * @param[in] client The esp_http_client handle + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t esp_http_client_close(esp_http_client_handle_t client); + +/** + * @brief This function must be the last function to call for an session. + * It is the opposite of the esp_http_client_init function and must be called with the same handle as input that a esp_http_client_init call returned. + * This might close all connections this handle has used and possibly has kept open until now. + * Don't call this function if you intend to transfer more files, re-using handles is a key to good performance with esp_http_client. + * + * @param[in] client The esp_http_client handle + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t esp_http_client_cleanup(esp_http_client_handle_t client); + + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/components/esp_http_client/lib/http_auth.c b/components/esp_http_client/lib/http_auth.c new file mode 100644 index 0000000000..4e07ce5f3a --- /dev/null +++ b/components/esp_http_client/lib/http_auth.c @@ -0,0 +1,151 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include + +#include "tcpip_adapter.h" +#include "lwip/sockets.h" +#include "rom/md5_hash.h" +#include "mbedtls/base64.h" + +#include "esp_system.h" +#include "esp_log.h" + +#include "http_utils.h" +#include "http_auth.h" + +#define MD5_MAX_LEN (33) +#define HTTP_AUTH_BUF_LEN (1024) + +static const char *TAG = "HTTP_AUTH"; + +/** + * @brief This function hash a formatted string with MD5 and format the result as ascii characters + * + * @param md The buffer will hold the ascii result + * @param[in] fmt The format + * + * @return Length of the result + */ +static int md5_printf(char *md, const char *fmt, ...) +{ + unsigned char *buf; + unsigned char digest[MD5_MAX_LEN]; + int len, i; + struct MD5Context md5_ctx; + va_list ap; + va_start(ap, fmt); + len = vasprintf((char **)&buf, fmt, ap); + if (buf == NULL) { + return -1; + } + + MD5Init(&md5_ctx); + MD5Update(&md5_ctx, buf, len); + MD5Final(digest, &md5_ctx); + + for (i = 0; i < 16; ++i) { + sprintf(&md[i * 2], "%02x", (unsigned int)digest[i]); + } + va_end(ap); + + free(buf); + return MD5_MAX_LEN; +} + +char *http_auth_digest(const char *username, const char *password, esp_http_auth_data_t *auth_data) +{ + char *ha1, *ha2 = NULL; + char *digest = NULL; + char *auth_str = NULL; + + if (username == NULL || + password == NULL || + auth_data->nonce == NULL || + auth_data->uri == NULL || + auth_data->realm == NULL) { + return NULL; + } + + ha1 = calloc(1, MD5_MAX_LEN); + HTTP_MEM_CHECK(TAG, ha1, goto _digest_exit); + + ha2 = calloc(1, MD5_MAX_LEN); + HTTP_MEM_CHECK(TAG, ha2, goto _digest_exit); + + digest = calloc(1, MD5_MAX_LEN); + HTTP_MEM_CHECK(TAG, digest, goto _digest_exit); + + if (md5_printf(ha1, "%s:%s:%s", username, auth_data->realm, password) <= 0) { + goto _digest_exit; + } + + ESP_LOGD(TAG, "%s %s %s %s\r\n", "Digest", username, auth_data->realm, password); + if (strcasecmp(auth_data->algorithm, "md5-sess") == 0) { + if (md5_printf(ha1, "%s:%s:%016llx", ha1, auth_data->nonce, auth_data->cnonce) <= 0) { + goto _digest_exit; + } + } + if (md5_printf(ha2, "%s:%s", auth_data->method, auth_data->uri) <= 0) { + goto _digest_exit; + } + + //support qop = auth + if (auth_data->qop && strcasecmp(auth_data->qop, "auth-int") == 0) { + if (md5_printf(ha2, "%s:%s", ha2, "entity") <= 0) { + goto _digest_exit; + } + } + + if (auth_data->qop) { + // response=MD5(HA1:nonce:nonceCount:cnonce:qop:HA2) + if (md5_printf(digest, "%s:%s:%08x:%016llx:%s:%s", ha1, auth_data->nonce, auth_data->nc, auth_data->cnonce, auth_data->qop, ha2) <= 0) { + goto _digest_exit; + } + } else { + // response=MD5(HA1:nonce:HA2) + if (md5_printf(digest, "%s:%s:%s", ha1, auth_data->nonce, ha2) <= 0) { + goto _digest_exit; + } + } + asprintf(&auth_str, "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", algorithm=\"MD5\", " + "response=\"%s\", opaque=\"%s\", qop=%s, nc=%08x, cnonce=\"%016llx\"", + username, auth_data->realm, auth_data->nonce, auth_data->uri, digest, auth_data->opaque, auth_data->qop, auth_data->nc, auth_data->cnonce); +_digest_exit: + free(ha1); + free(ha2); + free(digest); + return auth_str; +} + +char *http_auth_basic(const char *username, const char *password) +{ + int out; + char *user_info = NULL; + char *digest = calloc(1, MD5_MAX_LEN + 7); + HTTP_MEM_CHECK(TAG, digest, goto _basic_exit); + asprintf(&user_info, "%s:%s", username, password); + HTTP_MEM_CHECK(TAG, user_info, goto _basic_exit); + if (user_info == NULL) { + goto _basic_exit; + } + strcpy(digest, "Basic "); + mbedtls_base64_encode((unsigned char *)digest + 6, MD5_MAX_LEN, (size_t *)&out, (const unsigned char *)user_info, strlen(user_info)); +_basic_exit: + free(user_info); + return digest; +} diff --git a/components/esp_http_client/lib/http_header.c b/components/esp_http_client/lib/http_header.c new file mode 100644 index 0000000000..b771f6f6e9 --- /dev/null +++ b/components/esp_http_client/lib/http_header.c @@ -0,0 +1,239 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include +#include +#include +#include +#include +#include "esp_log.h" +#include "http_header.h" +#include "http_utils.h" + +static const char *TAG = "HTTP_HEADER"; +#define HEADER_BUFFER (1024) + +/** + * dictionary item struct, with key-value pair + */ +typedef struct http_header_item { + char *key; /*!< key */ + char *value; /*!< value */ + STAILQ_ENTRY(http_header_item) next; /*!< Point to next entry */ +} http_header_item_t; + +STAILQ_HEAD(http_header, http_header_item); + + +http_header_handle_t http_header_init() +{ + http_header_handle_t header = calloc(1, sizeof(struct http_header)); + HTTP_MEM_CHECK(TAG, header, return NULL); + STAILQ_INIT(header); + return header; +} + +esp_err_t http_header_destroy(http_header_handle_t header) +{ + esp_err_t err = http_header_clean(header); + free(header); + return err; +} + +http_header_item_handle_t http_header_get_item(http_header_handle_t header, const char *key) +{ + http_header_item_handle_t item; + if (header == NULL || key == NULL) { + return NULL; + } + STAILQ_FOREACH(item, header, next) { + if (strcasecmp(item->key, key) == 0) { + return item; + } + } + return NULL; +} + +esp_err_t http_header_get(http_header_handle_t header, const char *key, char **value) +{ + http_header_item_handle_t item; + + item = http_header_get_item(header, key); + if (item) { + *value = item->value; + } else { + *value = NULL; + } + + return ESP_OK; +} + +static esp_err_t http_header_new_item(http_header_handle_t header, const char *key, const char *value) +{ + http_header_item_handle_t item; + + item = calloc(1, sizeof(http_header_item_t)); + HTTP_MEM_CHECK(TAG, item, return ESP_ERR_NO_MEM); + http_utils_assign_string(&item->key, key, 0); + HTTP_MEM_CHECK(TAG, item->key, goto _header_new_item_exit); + http_utils_trim_whitespace(&item->key); + http_utils_assign_string(&item->value, value, 0); + HTTP_MEM_CHECK(TAG, item->value, goto _header_new_item_exit); + http_utils_trim_whitespace(&item->value); + STAILQ_INSERT_TAIL(header, item, next); + return ESP_OK; +_header_new_item_exit: + free(item->key); + free(item->value); + return ESP_ERR_NO_MEM; +} + +esp_err_t http_header_set(http_header_handle_t header, const char *key, const char *value) +{ + http_header_item_handle_t item; + + if (value == NULL) { + return http_header_delete(header, key); + } + + item = http_header_get_item(header, key); + + if (item) { + free(item->value); + item->value = strdup(value); + http_utils_trim_whitespace(&item->value); + return ESP_OK; + } + return http_header_new_item(header, key, value); +} + +esp_err_t http_header_set_from_string(http_header_handle_t header, const char *key_value_data) +{ + char *eq_ch; + char *p_str; + + p_str = strdup(key_value_data); + HTTP_MEM_CHECK(TAG, p_str, return ESP_ERR_NO_MEM); + eq_ch = strchr(p_str, ':'); + if (eq_ch == NULL) { + free(p_str); + return ESP_ERR_INVALID_ARG; + } + *eq_ch = 0; + + http_header_set(header, p_str, eq_ch + 1); + free(p_str); + return ESP_OK; +} + + +esp_err_t http_header_delete(http_header_handle_t header, const char *key) +{ + http_header_item_handle_t item = http_header_get_item(header, key); + if (item) { + STAILQ_REMOVE(header, item, http_header_item, next); + free(item->key); + free(item->value); + free(item); + } else { + return ESP_ERR_NOT_FOUND; + } + return ESP_OK; +} + + +int http_header_set_format(http_header_handle_t header, const char *key, const char *format, ...) +{ + va_list argptr; + int len = 0; + char *buf = NULL; + va_start(argptr, format); + len = vasprintf(&buf, format, argptr); + HTTP_MEM_CHECK(TAG, buf, return 0); + va_end(argptr); + if (buf == NULL) { + return 0; + } + http_header_set(header, key, buf); + free(buf); + return len; +} + +int http_header_generate_string(http_header_handle_t header, int index, char *buffer, int *buffer_len) +{ + http_header_item_handle_t item; + int siz = 0; + int idx = 0; + int ret_idx = -1; + bool is_end = false; + STAILQ_FOREACH(item, header, next) { + if (item->value && idx >= index) { + siz += strlen(item->key); + siz += strlen(item->value); + siz += 4; //': ' and '\r\n' + } + idx ++; + + if (siz + 1 > *buffer_len - 2) { + ret_idx = idx - 1; + } + } + + if (siz == 0) { + return 0; + } + if (ret_idx < 0) { + ret_idx = idx; + is_end = true; + } + + int str_len = 0; + idx = 0; + STAILQ_FOREACH(item, header, next) { + if (item->value && idx >= index && idx < ret_idx) { + str_len += snprintf(buffer + str_len, *buffer_len - str_len, "%s: %s\r\n", item->key, item->value); + } + idx ++; + } + if (is_end) { + str_len += snprintf(buffer + str_len, *buffer_len - str_len, "\r\n"); + } + *buffer_len = str_len; + return ret_idx; +} + +esp_err_t http_header_clean(http_header_handle_t header) +{ + http_header_item_handle_t item = STAILQ_FIRST(header), tmp; + while (item != NULL) { + tmp = STAILQ_NEXT(item, next); + free(item->key); + free(item->value); + free(item); + item = tmp; + } + STAILQ_INIT(header); + return ESP_OK; +} + +int http_header_count(http_header_handle_t header) +{ + http_header_item_handle_t item; + int count = 0; + STAILQ_FOREACH(item, header, next) { + count ++; + } + return count; +} diff --git a/components/esp_http_client/lib/http_utils.c b/components/esp_http_client/lib/http_utils.c new file mode 100644 index 0000000000..2ccc501313 --- /dev/null +++ b/components/esp_http_client/lib/http_utils.c @@ -0,0 +1,125 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include + +#include "http_utils.h" + +#ifndef mem_check +#define mem_check(x) assert(x) +#endif + +char *http_utils_join_string(const char *first_str, int len_first, const char *second_str, int len_second) +{ + int first_str_len = len_first > 0 ? len_first : strlen(first_str); + int second_str_len = len_second > 0 ? len_second : strlen(second_str); + char *ret = NULL; + if (first_str_len + second_str_len > 0) { + ret = calloc(1, first_str_len + second_str_len + 1); + mem_check(ret); + memcpy(ret, first_str, first_str_len); + memcpy(ret + first_str_len, second_str, second_str_len); + } + return ret; +} + +char *http_utils_assign_string(char **str, const char *new_str, int len) +{ + int l = len; + if (new_str == NULL) { + return NULL; + } + char *old_str = *str; + if (l <= 0) { + l = strlen(new_str); + } + if (old_str) { + old_str = realloc(old_str, l + 1); + mem_check(old_str); + old_str[l] = 0; + } else { + old_str = calloc(1, l + 1); + mem_check(old_str); + } + memcpy(old_str, new_str, l); + *str = old_str; + return old_str; +} + +void http_utils_trim_whitespace(char **str) +{ + char *end; + char *start = *str; + // Trim leading space + while (isspace((unsigned char)*start)) start ++; + + if (*start == 0) { // All spaces? + **str = 0; + return; + } + + // Trim trailing space + end = (char *)(start + strlen(start) - 1); + while (end > start && isspace((unsigned char)*end)) { + end--; + } + + // Write new null terminator + *(end + 1) = 0; + memmove(*str, start, strlen(start) + 1); +} + +char *http_utils_get_string_between(const char *str, const char *begin, const char *end) +{ + char *found = strstr(str, begin); + char *ret = NULL; + if (found) { + found += strlen(begin); + char *found_end = strstr(found, end); + if (found_end) { + ret = calloc(1, found_end - found + 1); + mem_check(ret); + memcpy(ret, found, found_end - found); + return ret; + } + } + return NULL; +} + +int http_utils_str_starts_with(const char *str, const char *start) +{ + int i; + int match_str_len = strlen(str); + int start_len = strlen(start); + + if (start_len > match_str_len) { + return -1; + } + for (i = 0; i < start_len; i++) { + if (str[i] != start[i]) { + return 1; + } + } + return 0; +} + +void http_utils_ms_to_timeval(int timeout_ms, struct timeval *tv) +{ + tv->tv_sec = timeout_ms / 1000; + tv->tv_usec = (timeout_ms - (tv->tv_sec * 1000)) * 1000; +} diff --git a/components/esp_http_client/lib/include/http_auth.h b/components/esp_http_client/lib/include/http_auth.h new file mode 100644 index 0000000000..8835666c2f --- /dev/null +++ b/components/esp_http_client/lib/include/http_auth.h @@ -0,0 +1,60 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#ifndef _HTTP_BASIC_AUTH_H_ +#define _HTTP_BASIC_AUTH_H_ + +/** + * HTTP Digest authentication data + */ +typedef struct { + char *method; /*!< Request method, example: GET */ + char *algorithm; /*!< Authentication algorithm */ + char *uri; /*!< URI of request example: /path/to/file.html */ + char *realm; /*!< Authentication realm */ + char *nonce; /*!< Authentication nonce */ + char *qop; /*!< Authentication qop */ + char *opaque; /*!< Authentication opaque */ + uint64_t cnonce; /*!< Authentication cnonce */ + int nc; /*!< Authentication nc */ +} esp_http_auth_data_t; + +/** + * @brief This use for Http digest authentication method, create http header for digest authentication. + * The returned string need to free after use + * + * @param[in] username The username + * @param[in] password The password + * @param auth_data The auth data + * + * @return + * - HTTP Header value of Authorization, valid for digest authentication, must be freed after usage + * - NULL + */ +char *http_auth_digest(const char *username, const char *password, esp_http_auth_data_t *auth_data); + +/** + * @brief This use for Http basic authentication method, create header value for basic http authentication + * The returned string need to free after use + * + * @param[in] username The username + * @param[in] password The password + * + * @return + * - HTTP Header value of Authorization, valid for basic authentication, must be free after use + * - NULL + */ +char *http_auth_basic(const char *username, const char *password); +#endif diff --git a/components/esp_http_client/lib/include/http_header.h b/components/esp_http_client/lib/include/http_header.h new file mode 100644 index 0000000000..7c680daf7f --- /dev/null +++ b/components/esp_http_client/lib/include/http_header.h @@ -0,0 +1,128 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _HTTP_HEADER_H_ +#define _HTTP_HEADER_H_ + +#include "rom/queue.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct http_header *http_header_handle_t; +typedef struct http_header_item *http_header_item_handle_t; + +/** + * @brief initialize and allocate the memory for the header object + * + * @return + * - http_header_handle_t + * - NULL if any errors + */ +http_header_handle_t http_header_init(); + +/** + * @brief Cleanup and free all http header pairs + * + * @param[in] header The header + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t http_header_clean(http_header_handle_t header); + +/** + * @brief Cleanup with http_header_clean and destroy http header handle object + * + * @param[in] header The header + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t http_header_destroy(http_header_handle_t header); + +/** + * @brief Add a key-value pair of http header to the list, + * note that with value = NULL, this function will remove the header with `key` already exists in the list. + * + * @param[in] header The header + * @param[in] key The key + * @param[in] value The value + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t http_header_set(http_header_handle_t header, const char *key, const char *value); + +/** + * @brief Sample as `http_header_set` but the value can be formated + * + * @param[in] header The header + * @param[in] key The key + * @param[in] format The format + * @param[in] ... format parameters + * + * @return Total length of value + */ +int http_header_set_format(http_header_handle_t header, const char *key, const char *format, ...); + +/** + * @brief Get a value of header in header list + * The address of the value will be assign set to `value` parameter or NULL if no header with the key exists in the list + * + * @param[in] header The header + * @param[in] key The key + * @param[out] value The value + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t http_header_get(http_header_handle_t header, const char *key, char **value); + +/** + * @brief Create HTTP header string from the header with index, output string to buffer with buffer_len + * Also return the last index of header was generated + * + * @param[in] header The header + * @param[in] index The index + * @param buffer The buffer + * @param buffer_len The buffer length + * + * @return The last index of header was generated + */ +int http_header_generate_string(http_header_handle_t header, int index, char *buffer, int *buffer_len); + +/** + * @brief Remove the header with key from the headers list + * + * @param[in] header The header + * @param[in] key The key + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t http_header_delete(http_header_handle_t header, const char *key); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/esp_http_client/lib/include/http_utils.h b/components/esp_http_client/lib/include/http_utils.h new file mode 100644 index 0000000000..9212cac050 --- /dev/null +++ b/components/esp_http_client/lib/include/http_utils.h @@ -0,0 +1,95 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#ifndef _HTTP_UTILS_H_ +#define _HTTP_UTILS_H_ +#include +/** + * @brief Assign new_str to *str pointer, and realloc *str if it not NULL + * + * @param str pointer to string pointer + * @param new_str assign this tring to str + * @param len length of string, 0 if new_str is zero terminated + * + * @return + * - new_str pointer + * - NULL + */ +char *http_utils_assign_string(char **str, const char *new_str, int len); + +/** + * @brief Remove white space at begin and end of string + * + * @param[in] str The string + * + * @return New strings have been trimmed + */ +void http_utils_trim_whitespace(char **str); + +/** + * @brief Gets the string between 2 string. + * It will allocate a new memory space for this string, so you need to free it when no longer use + * + * @param[in] str The source string + * @param[in] begin The begin string + * @param[in] end The end string + * + * @return The string between begin and end + */ +char *http_utils_get_string_between(const char *str, const char *begin, const char *end); + +/** + * @brief Join 2 strings to one + * It will allocate a new memory space for this string, so you need to free it when no longer use + * + * @param[in] first_str The first string + * @param[in] len_first The length first + * @param[in] second_str The second string + * @param[in] len_second The length second + * + * @return + * - New string pointer + * - NULL: Invalid input + */ +char *http_utils_join_string(const char *first_str, int len_first, const char *second_str, int len_second); + +/** + * @brief Check if ``str`` is start with ``start`` + * + * @param[in] str The string + * @param[in] start The start + * + * @return + * - (-1) if length of ``start`` larger than length of ``str`` + * - (1) if ``start`` NOT starts with ``start`` + * - (0) if ``str`` starts with ``start`` + */ +int http_utils_str_starts_with(const char *str, const char *start); + +/** + * @brief Convert milliseconds to timeval struct + * + * @param[in] timeout_ms The timeout milliseconds + * @param[out] tv Timeval struct + */ +void http_utils_ms_to_timeval(int timeout_ms, struct timeval *tv); + +#define HTTP_MEM_CHECK(TAG, a, action) if (!(a)) { \ + ESP_LOGE(TAG,"%s:%d (%s): %s", __FILE__, __LINE__, __FUNCTION__, "Memory exhausted"); \ + action; \ + } + + +#endif diff --git a/components/esp_http_client/lib/include/transport.h b/components/esp_http_client/lib/include/transport.h new file mode 100644 index 0000000000..0509d77332 --- /dev/null +++ b/components/esp_http_client/lib/include/transport.h @@ -0,0 +1,251 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _TRANSPORT_H_ +#define _TRANSPORT_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct transport_list_t* transport_list_handle_t; +typedef struct transport_item_t* transport_handle_t; + +typedef int (*connect_func)(transport_handle_t t, const char *host, int port, int timeout_ms); +typedef int (*io_func)(transport_handle_t t, const char *buffer, int len, int timeout_ms); +typedef int (*io_read_func)(transport_handle_t t, char *buffer, int len, int timeout_ms); +typedef int (*trans_func)(transport_handle_t t); +typedef int (*poll_func)(transport_handle_t t, int timeout_ms); + +/** + * @brief Create transport list + * + * @return A handle can hold all transports + */ +transport_list_handle_t transport_list_init(); + +/** + * @brief Cleanup and free all transports, include itself, + * this function will invoke transport_destroy of every transport have added this the list + * + * @param[in] list The list + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t transport_list_destroy(transport_list_handle_t list); + +/** + * @brief Add a transport to the list, and define a scheme to indentify this transport in the list + * + * @param[in] list The list + * @param[in] t The Transport + * @param[in] scheme The scheme + * + * @return + * - ESP_OK + */ +esp_err_t transport_list_add(transport_list_handle_t list, transport_handle_t t, const char *scheme); + +/** + * @brief This function will remove all transport from the list, + * invoke transport_destroy of every transport have added this the list + * + * @param[in] list The list + * + * @return + * - ESP_OK + * - ESP_ERR_INVALID_ARG + */ +esp_err_t transport_list_clean(transport_list_handle_t list); + +/** + * @brief Get the transport by scheme, which has been defined when calling function `transport_list_add` + * + * @param[in] list The list + * @param[in] tag The tag + * + * @return The transport handle + */ +transport_handle_t transport_list_get_transport(transport_list_handle_t list, const char *scheme); + +/** + * @brief Initialize a transport handle object + * + * @return The transport handle + */ +transport_handle_t transport_init(); + +/** + * @brief Cleanup and free memory the transport + * + * @param[in] t The transport handle + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t transport_destroy(transport_handle_t t); + +/** + * @brief Get default port number used by this transport + * + * @param[in] t The transport handle + * + * @return the port number + */ +int transport_get_default_port(transport_handle_t t); + +/** + * @brief Set default port number that can be used by this transport + * + * @param[in] t The transport handle + * @param[in] port The port number + * + * @return + * - ESP_OK + * - ESP_FAIL + */ +esp_err_t transport_set_default_port(transport_handle_t t, int port); + +/** + * @brief Transport connection function, to make a connection to server + * + * @param t The transport handle + * @param[in] host Hostname + * @param[in] port Port + * @param[in] timeout_ms The timeout milliseconds + * + * @return + * - socket for will use by this transport + * - (-1) if there are any errors, should check errno + */ +int transport_connect(transport_handle_t t, const char *host, int port, int timeout_ms); + +/** + * @brief Transport read function + * + * @param t The transport handle + * @param buffer The buffer + * @param[in] len The length + * @param[in] timeout_ms The timeout milliseconds + * + * @return + * - Number of bytes was read + * - (-1) if there are any errors, should check errno + */ +int transport_read(transport_handle_t t, char *buffer, int len, int timeout_ms); + +/** + * @brief Poll the transport until readable or timeout + * + * @param[in] t The transport handle + * @param[in] timeout_ms The timeout milliseconds + * + * @return + * - 0 Timeout + * - (-1) If there are any errors, should check errno + * - other The transport can read + */ +int transport_poll_read(transport_handle_t t, int timeout_ms); + +/** + * @brief Transport write function + * + * @param t The transport handle + * @param buffer The buffer + * @param[in] len The length + * @param[in] timeout_ms The timeout milliseconds + * + * @return + * - Number of bytes was written + * - (-1) if there are any errors, should check errno + */ +int transport_write(transport_handle_t t, const char *buffer, int len, int timeout_ms); + +/** + * @brief Poll the transport until writeable or timeout + * + * @param[in] t The transport handle + * @param[in] timeout_ms The timeout milliseconds + * + * @return + * - 0 Timeout + * - (-1) If there are any errors, should check errno + * - other The transport can write + */ +int transport_poll_write(transport_handle_t t, int timeout_ms); + +/** + * @brief Transport close + * + * @param t The transport handle + * + * @return + * - 0 if ok + * - (-1) if there are any errors, should check errno + */ +int transport_close(transport_handle_t t); + +/** + * @brief Get user data context of this transport + * + * @param[in] t The transport handle + * + * @return The user data context + */ +void *transport_get_context_data(transport_handle_t t); + +/** + * @brief Set the user context data for this transport + * + * @param[in] t The transport handle + * @param data The user data context + * + * @return + * - ESP_OK + */ +esp_err_t transport_set_context_data(transport_handle_t t, void *data); + +/** + * @brief Set transport functions for the transport handle + * + * @param[in] t The transport handle + * @param[in] _connect The connect function pointer + * @param[in] _read The read function pointer + * @param[in] _write The write function pointer + * @param[in] _close The close function pointer + * @param[in] _poll_read The poll read function pointer + * @param[in] _poll_write The poll write function pointer + * @param[in] _destroy The destroy function pointer + * + * @return + * - ESP_OK + */ +esp_err_t transport_set_func(transport_handle_t t, + connect_func _connect, + io_read_func _read, + io_func _write, + trans_func _close, + poll_func _poll_read, + poll_func _poll_write, + trans_func _destroy); +#ifdef __cplusplus +} +#endif +#endif diff --git a/components/esp_http_client/lib/include/transport_ssl.h b/components/esp_http_client/lib/include/transport_ssl.h new file mode 100644 index 0000000000..a00b36babc --- /dev/null +++ b/components/esp_http_client/lib/include/transport_ssl.h @@ -0,0 +1,48 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _TRANSPORT_SSL_H_ +#define _TRANSPORT_SSL_H_ + +#include "transport.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Create new SSL transport, the transport handle must be release transport_destroy callback + * + * @return the allocated transport_handle_t, or NULL if the handle can not be allocated + */ +transport_handle_t transport_ssl_init(); + +/** + * @brief Set SSL certificate data (as PEM format). + * Note that, this function stores the pointer to data, rather than making a copy. + * So we need to make sure to keep the data lifetime before cleanup the connection + * + * @param t ssl transport + * @param[in] data The pem data + * @param[in] len The length + */ +void transport_ssl_set_cert_data(transport_handle_t t, const char *data, int len); + + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/components/esp_http_client/lib/include/transport_tcp.h b/components/esp_http_client/lib/include/transport_tcp.h new file mode 100644 index 0000000000..e1cc1d3432 --- /dev/null +++ b/components/esp_http_client/lib/include/transport_tcp.h @@ -0,0 +1,36 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _TRANSPORT_TCP_H_ +#define _TRANSPORT_TCP_H_ + +#include "transport.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Create TCP transport, the transport handle must be release transport_destroy callback + * + * @return the allocated transport_handle_t, or NULL if the handle can not be allocated + */ +transport_handle_t transport_tcp_init(); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/esp_http_client/lib/transport.c b/components/esp_http_client/lib/transport.c new file mode 100644 index 0000000000..9351d8378f --- /dev/null +++ b/components/esp_http_client/lib/transport.c @@ -0,0 +1,232 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +#include +#include + +#include "rom/queue.h" +#include "esp_log.h" + +#include "transport.h" +#include "http_utils.h" + +static const char *TAG = "TRANSPORT"; + +/** + * Transport layer structure, which will provide functions, basic properties for transport types + */ +struct transport_item_t { + int port; + int socket; /*!< Socket to use in this transport */ + char *scheme; /*!< Tag name */ + void *context; /*!< Context data */ + void *data; /*!< Additional transport data */ + connect_func _connect; /*!< Connect function of this transport */ + io_read_func _read; /*!< Read */ + io_func _write; /*!< Write */ + trans_func _close; /*!< Close */ + poll_func _poll_read; /*!< Poll and read */ + poll_func _poll_write; /*!< Poll and write */ + trans_func _destroy; /*!< Destroy and free transport */ + STAILQ_ENTRY(transport_item_t) next; +}; + + +/** + * This list will hold all transport available + */ +STAILQ_HEAD(transport_list_t, transport_item_t); + + +transport_list_handle_t transport_list_init() +{ + transport_list_handle_t list = calloc(1, sizeof(struct transport_list_t)); + HTTP_MEM_CHECK(TAG, list, return NULL); + STAILQ_INIT(list); + return list; +} + +esp_err_t transport_list_add(transport_list_handle_t list, transport_handle_t t, const char *scheme) +{ + if (list == NULL || t == NULL) { + return ESP_ERR_INVALID_ARG; + } + t->scheme = calloc(1, strlen(scheme) + 1); + HTTP_MEM_CHECK(TAG, t->scheme, return ESP_ERR_NO_MEM); + strcpy(t->scheme, scheme); + STAILQ_INSERT_TAIL(list, t, next); + return ESP_OK; +} + +transport_handle_t transport_list_get_transport(transport_list_handle_t list, const char *scheme) +{ + if (!list) { + return NULL; + } + if (scheme == NULL) { + return STAILQ_FIRST(list); + } + transport_handle_t item; + STAILQ_FOREACH(item, list, next) { + if (strcasecmp(item->scheme, scheme) == 0) { + return item; + } + } + return NULL; +} + +esp_err_t transport_list_destroy(transport_list_handle_t list) +{ + transport_list_clean(list); + free(list); + return ESP_OK; +} + +esp_err_t transport_list_clean(transport_list_handle_t list) +{ + transport_handle_t item = STAILQ_FIRST(list); + transport_handle_t tmp; + while (item != NULL) { + tmp = STAILQ_NEXT(item, next); + if (item->_destroy) { + item->_destroy(item); + } + transport_destroy(item); + item = tmp; + } + STAILQ_INIT(list); + return ESP_OK; +} + +transport_handle_t transport_init() +{ + transport_handle_t t = calloc(1, sizeof(struct transport_item_t)); + HTTP_MEM_CHECK(TAG, t, return NULL); + return t; +} + +esp_err_t transport_destroy(transport_handle_t t) +{ + if (t->scheme) { + free(t->scheme); + } + free(t); + return ESP_OK; +} + +int transport_connect(transport_handle_t t, const char *host, int port, int timeout_ms) +{ + int ret = -1; + if (t && t->_connect) { + return t->_connect(t, host, port, timeout_ms); + } + return ret; +} + +int transport_read(transport_handle_t t, char *buffer, int len, int timeout_ms) +{ + if (t && t->_read) { + return t->_read(t, buffer, len, timeout_ms); + } + return -1; +} + +int transport_write(transport_handle_t t, const char *buffer, int len, int timeout_ms) +{ + if (t && t->_write) { + return t->_write(t, buffer, len, timeout_ms); + } + return -1; +} + +int transport_poll_read(transport_handle_t t, int timeout_ms) +{ + if (t && t->_poll_read) { + return t->_poll_read(t, timeout_ms); + } + return -1; +} + +int transport_poll_write(transport_handle_t t, int timeout_ms) +{ + if (t && t->_poll_write) { + return t->_poll_write(t, timeout_ms); + } + return -1; +} + +int transport_close(transport_handle_t t) +{ + if (t && t->_close) { + return t->_close(t); + } + return 0; +} + +void *transport_get_context_data(transport_handle_t t) +{ + if (t) { + return t->data; + } + return NULL; +} + +esp_err_t transport_set_context_data(transport_handle_t t, void *data) +{ + if (t) { + t->data = data; + return ESP_OK; + } + return ESP_FAIL; +} + +esp_err_t transport_set_func(transport_handle_t t, + connect_func _connect, + io_read_func _read, + io_func _write, + trans_func _close, + poll_func _poll_read, + poll_func _poll_write, + trans_func _destroy) +{ + if (t == NULL) { + return ESP_FAIL; + } + t->_connect = _connect; + t->_read = _read; + t->_write = _write; + t->_close = _close; + t->_poll_read = _poll_read; + t->_poll_write = _poll_write; + t->_destroy = _destroy; + return ESP_OK; +} + +int transport_get_default_port(transport_handle_t t) +{ + if (t == NULL) { + return -1; + } + return t->port; +} + +esp_err_t transport_set_default_port(transport_handle_t t, int port) +{ + if (t == NULL) { + return ESP_FAIL; + } + t->port = port; + return ESP_OK; +} diff --git a/components/esp_http_client/lib/transport_ssl.c b/components/esp_http_client/lib/transport_ssl.c new file mode 100644 index 0000000000..8a3c49c0ff --- /dev/null +++ b/components/esp_http_client/lib/transport_ssl.c @@ -0,0 +1,267 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "lwip/err.h" +#include "lwip/sockets.h" +#include "lwip/sys.h" +#include "lwip/netdb.h" +#include "lwip/dns.h" + +#include "mbedtls/platform.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/esp_debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" +#include "mbedtls/certs.h" + + +#include "esp_log.h" +#include "esp_system.h" + +#include "transport.h" +#include "transport_ssl.h" +#include "http_utils.h" + +static const char *TAG = "TRANS_SSL"; +/** + * mbedtls specific transport data + */ +typedef struct { + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ctx; + mbedtls_x509_crt cacert; + mbedtls_ssl_config conf; + mbedtls_net_context client_fd; + void *cert_pem_data; + int cert_pem_len; + bool ssl_initialized; + bool verify_server; +} transport_ssl_t; + +static int ssl_close(transport_handle_t t); + +static int ssl_connect(transport_handle_t t, const char *host, int port, int timeout_ms) +{ + int ret = -1, flags; + struct timeval tv; + transport_ssl_t *ssl = transport_get_context_data(t); + + if (!ssl) { + return -1; + } + ssl->ssl_initialized = true; + mbedtls_ssl_init(&ssl->ctx); + mbedtls_ctr_drbg_init(&ssl->ctr_drbg); + mbedtls_ssl_config_init(&ssl->conf); + mbedtls_entropy_init(&ssl->entropy); + + if ((ret = mbedtls_ssl_config_defaults(&ssl->conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned %d", ret); + goto exit; + } + + if ((ret = mbedtls_ctr_drbg_seed(&ssl->ctr_drbg, mbedtls_entropy_func, &ssl->entropy, NULL, 0)) != 0) { + ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned %d", ret); + goto exit; + } + + if (ssl->cert_pem_data) { + mbedtls_x509_crt_init(&ssl->cacert); + ssl->verify_server = true; + if ((ret = mbedtls_x509_crt_parse(&ssl->cacert, ssl->cert_pem_data, ssl->cert_pem_len + 1)) < 0) { + ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x\n\nDATA=%s,len=%d", -ret, (char*)ssl->cert_pem_data, ssl->cert_pem_len); + goto exit; + } + mbedtls_ssl_conf_ca_chain(&ssl->conf, &ssl->cacert, NULL); + mbedtls_ssl_conf_authmode(&ssl->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + + if ((ret = mbedtls_ssl_set_hostname(&ssl->ctx, host)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_set_hostname returned -0x%x", -ret); + goto exit; + } + } else { + mbedtls_ssl_conf_authmode(&ssl->conf, MBEDTLS_SSL_VERIFY_NONE); + } + + + mbedtls_ssl_conf_rng(&ssl->conf, mbedtls_ctr_drbg_random, &ssl->ctr_drbg); + +#ifdef CONFIG_MBEDTLS_DEBUG + mbedtls_esp_enable_debug_log(&ssl->conf, 4); +#endif + + if ((ret = mbedtls_ssl_setup(&ssl->ctx, &ssl->conf)) != 0) { + ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x\n\n", -ret); + goto exit; + } + + mbedtls_net_init(&ssl->client_fd); + + http_utils_ms_to_timeval(timeout_ms, &tv); + + setsockopt(ssl->client_fd.fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + ESP_LOGD(TAG, "Connect to %s:%d", host, port); + char port_str[8] = {0}; + sprintf(port_str, "%d", port); + if ((ret = mbedtls_net_connect(&ssl->client_fd, host, port_str, MBEDTLS_NET_PROTO_TCP)) != 0) { + ESP_LOGE(TAG, "mbedtls_net_connect returned -%x", -ret); + goto exit; + } + + mbedtls_ssl_set_bio(&ssl->ctx, &ssl->client_fd, mbedtls_net_send, mbedtls_net_recv, NULL); + + if((ret = mbedtls_ssl_set_hostname(&ssl->ctx, host)) != 0) { + ESP_LOGE(TAG, " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret); + goto exit; + } + + ESP_LOGD(TAG, "Performing the SSL/TLS handshake..."); + + while ((ret = mbedtls_ssl_handshake(&ssl->ctx)) != 0) { + if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { + ESP_LOGE(TAG, "mbedtls_ssl_handshake returned -0x%x", -ret); + goto exit; + } + } + + ESP_LOGD(TAG, "Verifying peer X.509 certificate..."); + + if ((flags = mbedtls_ssl_get_verify_result(&ssl->ctx)) != 0) { + /* In real life, we probably want to close connection if ret != 0 */ + ESP_LOGW(TAG, "Failed to verify peer certificate!"); + if (ssl->cert_pem_data) { + goto exit; + } + } else { + ESP_LOGD(TAG, "Certificate verified."); + } + + ESP_LOGD(TAG, "Cipher suite is %s", mbedtls_ssl_get_ciphersuite(&ssl->ctx)); + return ret; +exit: + ssl_close(t); + return ret; +} + +static int ssl_poll_read(transport_handle_t t, int timeout_ms) +{ + transport_ssl_t *ssl = transport_get_context_data(t); + fd_set readset; + FD_ZERO(&readset); + FD_SET(ssl->client_fd.fd, &readset); + struct timeval timeout; + http_utils_ms_to_timeval(timeout_ms, &timeout); + + return select(ssl->client_fd.fd + 1, &readset, NULL, NULL, &timeout); +} + +static int ssl_poll_write(transport_handle_t t, int timeout_ms) +{ + transport_ssl_t *ssl = transport_get_context_data(t); + fd_set writeset; + FD_ZERO(&writeset); + FD_SET(ssl->client_fd.fd, &writeset); + struct timeval timeout; + http_utils_ms_to_timeval(timeout_ms, &timeout); + return select(ssl->client_fd.fd + 1, NULL, &writeset, NULL, &timeout); +} + +static int ssl_write(transport_handle_t t, const char *buffer, int len, int timeout_ms) +{ + int poll, ret; + transport_ssl_t *ssl = transport_get_context_data(t); + + if ((poll = transport_poll_write(t, timeout_ms)) <= 0) { + ESP_LOGW(TAG, "Poll timeout or error, errno=%s, fd=%d, timeout_ms=%d", strerror(errno), ssl->client_fd.fd, timeout_ms); + return poll; + } + ret = mbedtls_ssl_write(&ssl->ctx, (const unsigned char *) buffer, len); + if (ret <= 0) { + ESP_LOGE(TAG, "mbedtls_ssl_write error, errno=%s", strerror(errno)); + } + return ret; +} + +static int ssl_read(transport_handle_t t, char *buffer, int len, int timeout_ms) +{ + int ret; + transport_ssl_t *ssl = transport_get_context_data(t); + ret = mbedtls_ssl_read(&ssl->ctx, (unsigned char *)buffer, len); + if (ret == 0) { + return -1; + } + return ret; +} + +static int ssl_close(transport_handle_t t) +{ + int ret = -1; + transport_ssl_t *ssl = transport_get_context_data(t); + if (ssl->ssl_initialized) { + ESP_LOGD(TAG, "Cleanup mbedtls"); + mbedtls_ssl_close_notify(&ssl->ctx); + mbedtls_ssl_session_reset(&ssl->ctx); + mbedtls_net_free(&ssl->client_fd); + mbedtls_ssl_config_free(&ssl->conf); + if (ssl->verify_server) { + mbedtls_x509_crt_free(&ssl->cacert); + } + mbedtls_ctr_drbg_free(&ssl->ctr_drbg); + mbedtls_entropy_free(&ssl->entropy); + mbedtls_ssl_free(&ssl->ctx); + ssl->ssl_initialized = false; + ssl->verify_server = false; + } + return ret; +} + +static int ssl_destroy(transport_handle_t t) +{ + transport_ssl_t *ssl = transport_get_context_data(t); + transport_close(t); + free(ssl); + return 0; +} + +void transport_ssl_set_cert_data(transport_handle_t t, const char *data, int len) +{ + transport_ssl_t *ssl = transport_get_context_data(t); + if (t && ssl) { + ssl->cert_pem_data = (void *)data; + ssl->cert_pem_len = len; + } +} + +transport_handle_t transport_ssl_init() +{ + transport_handle_t t = transport_init(); + transport_ssl_t *ssl = calloc(1, sizeof(transport_ssl_t)); + HTTP_MEM_CHECK(TAG, ssl, return NULL); + mbedtls_net_init(&ssl->client_fd); + transport_set_context_data(t, ssl); + transport_set_func(t, ssl_connect, ssl_read, ssl_write, ssl_close, ssl_poll_read, ssl_poll_write, ssl_destroy); + return t; +} + diff --git a/components/esp_http_client/lib/transport_tcp.c b/components/esp_http_client/lib/transport_tcp.c new file mode 100644 index 0000000000..058fc9fcac --- /dev/null +++ b/components/esp_http_client/lib/transport_tcp.c @@ -0,0 +1,166 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "lwip/sockets.h" +#include "lwip/dns.h" +#include "lwip/netdb.h" + +#include "esp_log.h" +#include "esp_system.h" +#include "esp_err.h" + +#include "http_utils.h" +#include "transport.h" + +static const char *TAG = "TRANS_TCP"; + +typedef struct { + int sock; +} transport_tcp_t; + +static int resolve_dns(const char *host, struct sockaddr_in *ip) { + + struct hostent *he; + struct in_addr **addr_list; + he = gethostbyname(host); + if (he == NULL) { + return ESP_FAIL; + } + addr_list = (struct in_addr **)he->h_addr_list; + if (addr_list[0] == NULL) { + return ESP_FAIL; + } + ip->sin_family = AF_INET; + memcpy(&ip->sin_addr, addr_list[0], sizeof(ip->sin_addr)); + return ESP_OK; +} + +static int tcp_connect(transport_handle_t t, const char *host, int port, int timeout_ms) +{ + struct sockaddr_in remote_ip; + struct timeval tv; + transport_tcp_t *tcp = transport_get_context_data(t); + + bzero(&remote_ip, sizeof(struct sockaddr_in)); + + //if stream_host is not ip address, resolve it AF_INET,servername,&serveraddr.sin_addr + if (inet_pton(AF_INET, host, &remote_ip.sin_addr) != 1) { + if (resolve_dns(host, &remote_ip) < 0) { + return -1; + } + } + + tcp->sock = socket(PF_INET, SOCK_STREAM, 0); + + if (tcp->sock < 0) { + ESP_LOGE(TAG, "Error create socket"); + return -1; + } + + remote_ip.sin_family = AF_INET; + remote_ip.sin_port = htons(port); + + http_utils_ms_to_timeval(timeout_ms, &tv); + + setsockopt(tcp->sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + + ESP_LOGD(TAG, "[sock=%d],connecting to server IP:%s,Port:%d...", + tcp->sock, ipaddr_ntoa((const ip_addr_t*)&remote_ip.sin_addr.s_addr), port); + if (connect(tcp->sock, (struct sockaddr *)(&remote_ip), sizeof(struct sockaddr)) != 0) { + close(tcp->sock); + tcp->sock = -1; + return -1; + } + return tcp->sock; +} + +static int tcp_write(transport_handle_t t, const char *buffer, int len, int timeout_ms) +{ + int poll; + transport_tcp_t *tcp = transport_get_context_data(t); + if ((poll = transport_poll_write(t, timeout_ms)) <= 0) { + return poll; + } + return write(tcp->sock, buffer, len); +} + +static int tcp_read(transport_handle_t t, char *buffer, int len, int timeout_ms) +{ + transport_tcp_t *tcp = transport_get_context_data(t); + int poll = -1; + if ((poll = transport_poll_read(t, timeout_ms)) <= 0) { + return poll; + } + int read_len = read(tcp->sock, buffer, len); + if (read_len == 0) { + return -1; + } + return read_len; +} + +static int tcp_poll_read(transport_handle_t t, int timeout_ms) +{ + transport_tcp_t *tcp = transport_get_context_data(t); + fd_set readset; + FD_ZERO(&readset); + FD_SET(tcp->sock, &readset); + struct timeval timeout; + http_utils_ms_to_timeval(timeout_ms, &timeout); + return select(tcp->sock + 1, &readset, NULL, NULL, &timeout); +} + +static int tcp_poll_write(transport_handle_t t, int timeout_ms) +{ + transport_tcp_t *tcp = transport_get_context_data(t); + fd_set writeset; + FD_ZERO(&writeset); + FD_SET(tcp->sock, &writeset); + struct timeval timeout; + http_utils_ms_to_timeval(timeout_ms, &timeout); + return select(tcp->sock + 1, NULL, &writeset, NULL, &timeout); +} + +static int tcp_close(transport_handle_t t) +{ + transport_tcp_t *tcp = transport_get_context_data(t); + int ret = -1; + if (tcp->sock >= 0) { + ret = close(tcp->sock); + tcp->sock = -1; + } + return ret; +} + +static esp_err_t tcp_destroy(transport_handle_t t) +{ + transport_tcp_t *tcp = transport_get_context_data(t); + transport_close(t); + free(tcp); + return 0; +} + +transport_handle_t transport_tcp_init() +{ + transport_handle_t t = transport_init(); + transport_tcp_t *tcp = calloc(1, sizeof(transport_tcp_t)); + HTTP_MEM_CHECK(TAG, tcp, return NULL); + tcp->sock = -1; + transport_set_func(t, tcp_connect, tcp_read, tcp_write, tcp_close, tcp_poll_read, tcp_poll_write, tcp_destroy); + transport_set_context_data(t, tcp); + + return t; +} diff --git a/docs/Doxyfile b/docs/Doxyfile index 7c1ac334d3..fe5a3e1fd8 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -91,6 +91,7 @@ INPUT = \ ../../components/esp-tls/esp_tls.h \ ## mDNS ../../components/mdns/include/mdns.h \ + ../../components/esp_http_client/include/esp_http_client.h \ ## ## Storage - API Reference ## diff --git a/docs/en/api-reference/protocols/esp_http_client.rst b/docs/en/api-reference/protocols/esp_http_client.rst new file mode 100644 index 0000000000..b54078a00e --- /dev/null +++ b/docs/en/api-reference/protocols/esp_http_client.rst @@ -0,0 +1,191 @@ +ESP HTTP Client +=============== + +Overview +-------- + +``esp_http_client`` provides an API for making HTTP/S requests from ESP-IDF programs. The steps to use this API for an HTTP request are: + + * :cpp:func:`esp_http_client_init`: To use the HTTP client, the first thing we must do is create an :cpp:class:`esp_http_client` by pass into this function with the :cpp:class:`esp_http_client_config_t` configurations. Which configuration values we do not define, the library will use default. + * :cpp:func:`esp_http_client_perform`: The :cpp:class:`esp_http_client` argument created from the init function is needed. This function performs all operations of the esp_http_client, from opening the connection, sending data, downloading data and closing the connection if necessary. All related events will be invoked in the event_handle (defined by :cpp:class:`esp_http_client_config_t`). This function performs its job and blocks the current task until it's done + * :cpp:func:`esp_http_client_cleanup`: After completing our **esp_http_client's** task, this is the last function to be called. It will close the connection (if any) and free up all the memory allocated to the HTTP client + + +Application Example +------------------- + + .. highlight:: c + + :: + + esp_err_t _http_event_handle(esp_http_client_event_t *evt) + { + switch(evt->event_id) { + case HTTP_EVENT_ERROR: + ESP_LOGI(TAG, "HTTP_EVENT_ERROR"); + break; + case HTTP_EVENT_ON_CONNECTED: + ESP_LOGI(TAG, "HTTP_EVENT_ON_CONNECTED"); + break; + case HTTP_EVENT_HEADER_SENT: + ESP_LOGI(TAG, "HTTP_EVENT_HEADER_SENT"); + break; + case HTTP_EVENT_ON_HEADER: + ESP_LOGI(TAG, "HTTP_EVENT_ON_HEADER"); + printf("%.*s", evt->data_len, (char*)evt->data); + break; + case HTTP_EVENT_ON_DATA: + ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); + if (!esp_http_client_is_chunked_response(evt->client)) { + printf("%.*s", evt->data_len, (char*)evt->data); + } + + break; + case HTTP_EVENT_ON_FINISH: + ESP_LOGI(TAG, "HTTP_EVENT_ON_FINISH"); + break; + case HTTP_EVENT_DISCONNECTED: + ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED"); + break; + } + return ESP_OK; + } + + esp_http_client_config_t config = { + .url = "http://httpbin.org/redirect/2", + .event_handle = _http_event_handle, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } + esp_http_client_cleanup(client); + + +Persistent Connections +---------------------- + +Persistent connections means that the HTTP client can re-use the same connection for several transfers. If the server does not request to close the connection with the ``Connection: close`` header, the new transfer with sample ip address, port, and protocol. + +To allow the HTTP client to take full advantage of persistent connections, you should do as many of your file transfers as possible using the same handle. + +Persistent Connections example +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. highlight:: c + +:: + + esp_err_t err; + esp_http_client_config_t config = { + .url = "http://httpbin.org/get", + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + // first request + err = esp_http_client_perform(client); + + // second request + esp_http_client_set_url(client, "http://httpbin.org/anything") + esp_http_client_set_method(client, HTTP_METHOD_DELETE); + esp_http_client_set_header(client, "HeaderKey", "HeaderValue"); + err = esp_http_client_perform(client); + + esp_http_client_cleanup(client); + + +HTTPS +----- + +The HTTP client supports SSL connections using **mbedtls**, with the **url** configuration starting with ``https`` scheme (or ``transport_type = HTTP_TRANSPORT_OVER_SSL``). HTTPS support can be configured via :ref:CONFIG_ENABLE_HTTPS (enabled by default).. + +.. note:: By providing information using HTTPS, the library will use the SSL transport type to connect to the server. If you want to verify server, then need to provide additional certificate in PEM format, and provide to ``cert_pem`` in ``esp_http_client_config_t`` + +HTTPS example +^^^^^^^^^^^^^ + +.. highlight:: c + +:: + + static void https() + { + esp_http_client_config_t config = { + .url = "https://www.howsmyssl.com", + .cert_pem = howsmyssl_com_root_cert_pem_start, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } + esp_http_client_cleanup(client); + } + +HTTP Stream +----------- + +Some applications need to open the connection and control the reading of the data in an active manner. the HTTP client supports some functions to make this easier, of course, once you use these functions you should not use the :cpp:func:`esp_http_client_perform` function with that handle, and :cpp:func:`esp_http_client_init` alway to called first to get the handle. Perform that functions in the order below: + + * :cpp:func:`esp_http_client_init`: to create and handle + * ``esp_http_client_set_*`` or ``esp_http_client_delete_*``: to modify the http connection information (optional) + * :cpp:func:`esp_http_client_open`: Open the http connection with ``write_len`` parameter, ``write_len=0`` if we only need read + * :cpp:func:`esp_http_client_write`: Upload data, max length equal to ``write_len`` of :cpp:func:`esp_http_client_open` function. We may not need to call it if ``write_len=0`` + * :cpp:func:`esp_http_client_fetch_headers`: After sending the headers and write data (if any) to the server, this function will read the HTTP Server response headers. Calling this function will return the ``content-length`` from the Server, and we can call :cpp:func:`esp_http_client_get_status_code` for the HTTP status of the connection. + * :cpp:func:`esp_http_client_read`: Now, we can read the HTTP stream by this function. + * :cpp:func:`esp_http_client_close`: We should the connection after finish + * :cpp:func:`esp_http_client_cleanup`: And release the resources + +Perform HTTP request as Stream reader +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Check the example function ``http_perform_as_stream_reader`` at :example:`protocols/esp_http_client`. + + +HTTP Authentication +------------------- + +The HTTP client supports both **Basic** and **Digest** Authentication. By providing usernames and passwords in ``url`` or in the ``username``, ``password`` of config entry. And with ``auth_type = HTTP_AUTH_TYPE_BASIC``, the HTTP client takes only 1 perform to pass the authentication process. If ``auth_type = HTTP_AUTH_TYPE_NONE``, but there are ``username`` and ``password`` in the configuration, the HTTP client takes 2 performs. The first time it connects to the server and receives the UNAUTHORIZED header. Based on this information, it will know which authentication method to choose, and perform it on the second. + + +Config authentication example with URI +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. highlight:: c + +:: + + esp_http_client_config_t config = { + .url = "http://user:passwd@httpbin.org/basic-auth/user/passwd", + .auth_type = HTTP_AUTH_TYPE_BASIC, + }; + + +Config authentication example with username, password entry +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. highlight:: c + +:: + + esp_http_client_config_t config = { + .url = "http://httpbin.org/basic-auth/user/passwd", + .username = "user", + .password = "passwd", + .auth_type = HTTP_AUTH_TYPE_BASIC, + }; + + +HTTP Client example: :example:`protocols/esp_http_client`. + + +API Reference +------------- + +.. include:: /_build/inc/esp_http_client.inc diff --git a/docs/en/api-reference/protocols/index.rst b/docs/en/api-reference/protocols/index.rst index fb9ca36a76..165fd0ca65 100644 --- a/docs/en/api-reference/protocols/index.rst +++ b/docs/en/api-reference/protocols/index.rst @@ -6,5 +6,6 @@ Protocols API mDNS ESP-TLS + HTTP Client Example code for this API section is provided in :example:`protocols` directory of ESP-IDF examples. diff --git a/docs/zh_CN/api-reference/protocols/esp_http_client.rst b/docs/zh_CN/api-reference/protocols/esp_http_client.rst new file mode 100644 index 0000000000..4876be06ff --- /dev/null +++ b/docs/zh_CN/api-reference/protocols/esp_http_client.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/protocols/esp_http_client.rst diff --git a/examples/protocols/esp_http_client/Makefile b/examples/protocols/esp_http_client/Makefile new file mode 100644 index 0000000000..851c3475df --- /dev/null +++ b/examples/protocols/esp_http_client/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := esp-http-client-example + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/protocols/esp_http_client/README.md b/examples/protocols/esp_http_client/README.md new file mode 100644 index 0000000000..c4225fde25 --- /dev/null +++ b/examples/protocols/esp_http_client/README.md @@ -0,0 +1,3 @@ +# ESP HTTP Client Example + +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/protocols/esp_http_client/esp_http_client_test.py b/examples/protocols/esp_http_client/esp_http_client_test.py new file mode 100644 index 0000000000..c982bb6527 --- /dev/null +++ b/examples/protocols/esp_http_client/esp_http_client_test.py @@ -0,0 +1,51 @@ +import re +import os +import sys + +# this is a test case write with tiny-test-fw. +# to run test cases outside tiny-test-fw, +# we need to set environment variable `TEST_FW_PATH`, +# then get and insert `TEST_FW_PATH` to sys path before import FW module +test_fw_path = os.getenv("TEST_FW_PATH") +if test_fw_path and test_fw_path not in sys.path: + sys.path.insert(0, test_fw_path) + +import TinyFW +import IDF + + +@IDF.idf_example_test(env_tag="Example_WIFI") +def test_examples_protocol_esp_http_client(env, extra_data): + """ + steps: | + 1. join AP + 2. Send HTTP request to httpbin.org + """ + dut1 = env.get_dut("esp_http_client", "examples/protocols/esp_http_client") + # check and log bin size + binary_file = os.path.join(dut1.app.binary_path, "esp-http-client-example.bin") + bin_size = os.path.getsize(binary_file) + IDF.log_performance("esp_http_client_bin_size", "{}KB".format(bin_size//1024)) + IDF.check_performance("esp_http_client_bin_size", bin_size//1024) + # start test + dut1.start_app() + dut1.expect("Connected to AP, begin http example", timeout=30) + dut1.expect(re.compile(r"HTTP GET Status = 200, content_length = (\d)")) + dut1.expect(re.compile(r"HTTP POST Status = 200, content_length = (\d)")) + dut1.expect(re.compile(r"HTTP PUT Status = 200, content_length = (\d)")) + dut1.expect(re.compile(r"HTTP PATCH Status = 200, content_length = (\d)")) + dut1.expect(re.compile(r"HTTP DELETE Status = 200, content_length = (\d)")) + dut1.expect(re.compile(r"HTTP Basic Auth Status = 200, content_length = (\d)")) + dut1.expect(re.compile(r"HTTP Basic Auth redirect Status = 200, content_length = (\d)")) + dut1.expect(re.compile(r"HTTP Digest Auth Status = 200, content_length = (\d)")) + dut1.expect(re.compile(r"HTTP Relative path redirect Status = 200, content_length = (\d)")) + dut1.expect(re.compile(r"HTTP Absolute path redirect Status = 200, content_length = (\d)")) + dut1.expect(re.compile(r"HTTPS Status = 200, content_length = (\d)")) + dut1.expect(re.compile(r"HTTP redirect to HTTPS Status = 200, content_length = (\d)")) + dut1.expect(re.compile(r"HTTP chunk encoding Status = 200, content_length = -1")) + dut1.expect(re.compile(r"HTTP Stream reader Status = 200, content_length = (\d)")) + dut1.expect("Finish http example") + + +if __name__ == '__main__': + test_examples_protocol_esp_http_client() diff --git a/examples/protocols/esp_http_client/main/Kconfig.projbuild b/examples/protocols/esp_http_client/main/Kconfig.projbuild new file mode 100644 index 0000000000..1c7241da32 --- /dev/null +++ b/examples/protocols/esp_http_client/main/Kconfig.projbuild @@ -0,0 +1,17 @@ +menu "Example Configuration" + +config WIFI_SSID + string "WiFi SSID" + default "myssid" + help + SSID (network name) for the example to connect to. + +config WIFI_PASSWORD + string "WiFi Password" + default "mypassword" + help + WiFi password (WPA or WPA2) for the example to use. + + Can be left blank if the network has no security set. + +endmenu diff --git a/examples/protocols/esp_http_client/main/app_wifi.c b/examples/protocols/esp_http_client/main/app_wifi.c new file mode 100644 index 0000000000..da5ac44d50 --- /dev/null +++ b/examples/protocols/esp_http_client/main/app_wifi.c @@ -0,0 +1,75 @@ +/* ESP HTTP Client Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "esp_system.h" +#include "freertos/event_groups.h" +#include "esp_wifi.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "app_wifi.h" + +static const char *TAG = "WIFI"; + +/* FreeRTOS event group to signal when we are connected & ready to make a request */ +static EventGroupHandle_t wifi_event_group; + +/* The event group allows multiple bits for each event, + but we only care about one event - are we connected + to the AP with an IP? */ +const int CONNECTED_BIT = BIT0; + +static esp_err_t event_handler(void *ctx, system_event_t *event) +{ + switch (event->event_id) { + case SYSTEM_EVENT_STA_START: + esp_wifi_connect(); + break; + case SYSTEM_EVENT_STA_GOT_IP: + xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); + break; + case SYSTEM_EVENT_STA_DISCONNECTED: + /* This is a workaround as ESP32 WiFi libs don't currently + auto-reassociate. */ + esp_wifi_connect(); + xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); + break; + default: + break; + } + return ESP_OK; +} + +void app_wifi_initialise(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_storage(WIFI_STORAGE_RAM)); + wifi_config_t wifi_config = { + .sta = { + .ssid = CONFIG_WIFI_SSID, + .password = CONFIG_WIFI_PASSWORD, + }, + }; + ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_start()); + +} + +void app_wifi_wait_connected() +{ + xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); +} diff --git a/examples/protocols/esp_http_client/main/app_wifi.h b/examples/protocols/esp_http_client/main/app_wifi.h new file mode 100644 index 0000000000..91c886d5b8 --- /dev/null +++ b/examples/protocols/esp_http_client/main/app_wifi.h @@ -0,0 +1,17 @@ +/* ESP HTTP Client Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#ifndef _APP_WIFI_H_ +#define _APP_WIFI_H_ + +void app_wifi_initialise(void); +void app_wifi_wait_connected(); + + +#endif diff --git a/examples/protocols/esp_http_client/main/component.mk b/examples/protocols/esp_http_client/main/component.mk new file mode 100644 index 0000000000..cb97ca08ee --- /dev/null +++ b/examples/protocols/esp_http_client/main/component.mk @@ -0,0 +1,8 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + +# embed files from the "certs" directory as binary data symbols +# in the app +COMPONENT_EMBED_TXTFILES := howsmyssl_com_root_cert.pem diff --git a/examples/protocols/esp_http_client/main/esp_http_client_example.c b/examples/protocols/esp_http_client/main/esp_http_client_example.c new file mode 100644 index 0000000000..66abb86d88 --- /dev/null +++ b/examples/protocols/esp_http_client/main/esp_http_client_example.c @@ -0,0 +1,362 @@ +/* ESP HTTP Client Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "esp_system.h" +#include "nvs_flash.h" +#include "app_wifi.h" + +#include "esp_http_client.h" + +#define MAX_HTTP_RECV_BUFFER 512 +static const char *TAG = "HTTP_CLIENT"; + +/* Root cert for howsmyssl.com, taken from howsmyssl_com_root_cert.pem + + The PEM file was extracted from the output of this command: + openssl s_client -showcerts -connect www.howsmyssl.com:443 event_id) { + case HTTP_EVENT_ERROR: + ESP_LOGD(TAG, "HTTP_EVENT_ERROR"); + break; + case HTTP_EVENT_ON_CONNECTED: + ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); + break; + case HTTP_EVENT_HEADER_SENT: + ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT"); + break; + case HTTP_EVENT_ON_HEADER: + ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value); + break; + case HTTP_EVENT_ON_DATA: + ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); + if (!esp_http_client_is_chunked_response(evt->client)) { + // Write out data + // printf("%.*s", evt->data_len, (char*)evt->data); + } + + break; + case HTTP_EVENT_ON_FINISH: + ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH"); + break; + case HTTP_EVENT_DISCONNECTED: + ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED"); + break; + } + return ESP_OK; +} + +static void http_rest() +{ + esp_http_client_config_t config = { + .url = "http://httpbin.org/get", + .event_handler = _http_event_handler, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + + // GET + esp_err_t err = esp_http_client_perform(client); + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err)); + } + + // POST + const char *post_data = "field1=value1&field2=value2"; + esp_http_client_set_url(client, "http://httpbin.org/post"); + esp_http_client_set_method(client, HTTP_METHOD_POST); + esp_http_client_set_post_field(client, post_data, strlen(post_data)); + err = esp_http_client_perform(client); + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP POST Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "HTTP POST request failed: %s", esp_err_to_name(err)); + } + + //PUT + esp_http_client_set_url(client, "http://httpbin.org/put"); + esp_http_client_set_method(client, HTTP_METHOD_PUT); + err = esp_http_client_perform(client); + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP PUT Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "HTTP PUT request failed: %s", esp_err_to_name(err)); + } + + //PATCH + esp_http_client_set_url(client, "http://httpbin.org/patch"); + esp_http_client_set_method(client, HTTP_METHOD_PATCH); + esp_http_client_set_post_field(client, NULL, 0); + err = esp_http_client_perform(client); + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP PATCH Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "HTTP PATCH request failed: %s", esp_err_to_name(err)); + } + + //DELETE + esp_http_client_set_url(client, "http://httpbin.org/delete"); + esp_http_client_set_method(client, HTTP_METHOD_DELETE); + err = esp_http_client_perform(client); + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP DELETE Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "HTTP DELETE request failed: %s", esp_err_to_name(err)); + } + + esp_http_client_cleanup(client); +} + +static void http_auth_basic() +{ + esp_http_client_config_t config = { + .url = "http://user:passwd@httpbin.org/basic-auth/user/passwd", + .event_handler = _http_event_handler, + .auth_type = HTTP_AUTH_TYPE_BASIC, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP Basic Auth Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err)); + } + esp_http_client_cleanup(client); +} + +static void http_auth_basic_redirect() +{ + esp_http_client_config_t config = { + .url = "http://user:passwd@httpbin.org/basic-auth/user/passwd", + .event_handler = _http_event_handler, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP Basic Auth redirect Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err)); + } + esp_http_client_cleanup(client); +} + +static void http_auth_digest() +{ + esp_http_client_config_t config = { + .url = "http://user:passwd@httpbin.org/digest-auth/auth/user/passwd/MD5/never", + .event_handler = _http_event_handler, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP Digest Auth Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err)); + } + esp_http_client_cleanup(client); +} + +static void https() +{ + esp_http_client_config_t config = { + .url = "https://www.howsmyssl.com", + .event_handler = _http_event_handler, + .cert_pem = howsmyssl_com_root_cert_pem_start, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTPS Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err)); + } + esp_http_client_cleanup(client); +} + +static void http_relative_redirect() +{ + esp_http_client_config_t config = { + .url = "http://httpbin.org/relative-redirect/3", + .event_handler = _http_event_handler, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP Relative path redirect Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err)); + } + esp_http_client_cleanup(client); +} + +static void http_absolute_redirect() +{ + esp_http_client_config_t config = { + .url = "http://httpbin.org/absolute-redirect/3", + .event_handler = _http_event_handler, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP Absolute path redirect Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err)); + } + esp_http_client_cleanup(client); +} + +static void http_redirect_to_https() +{ + esp_http_client_config_t config = { + .url = "http://httpbin.org/redirect-to?url=https%3A%2F%2Fwww.howsmyssl.com", + .event_handler = _http_event_handler, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP redirect to HTTPS Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err)); + } + esp_http_client_cleanup(client); +} + + +static void http_download_chunk() +{ + esp_http_client_config_t config = { + .url = "http://httpbin.org/stream-bytes/8912", + .event_handler = _http_event_handler, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err = esp_http_client_perform(client); + + if (err == ESP_OK) { + ESP_LOGI(TAG, "HTTP chunk encoding Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + } else { + ESP_LOGE(TAG, "Error perform http request %s", esp_err_to_name(err)); + } + esp_http_client_cleanup(client); +} + +static void http_perform_as_stream_reader() +{ + char *buffer = malloc(MAX_HTTP_RECV_BUFFER); + if (buffer == NULL) { + ESP_LOGE(TAG, "Cannot malloc http receive buffer"); + return; + } + esp_http_client_config_t config = { + .url = "http://httpbin.org/get", + .event_handler = _http_event_handler, + }; + esp_http_client_handle_t client = esp_http_client_init(&config); + esp_err_t err; + if ((err = esp_http_client_open(client, 0)) != ESP_OK) { + ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err)); + free(buffer); + return; + } + int content_length = esp_http_client_fetch_headers(client); + int total_read_len = 0, read_len; + if (total_read_len < content_length && content_length <= MAX_HTTP_RECV_BUFFER) { + read_len = esp_http_client_read(client, buffer, content_length); + if (read_len <= 0) { + ESP_LOGE(TAG, "Error read data"); + } + buffer[read_len] = 0; + ESP_LOGD(TAG, "read_len = %d", read_len); + } + ESP_LOGI(TAG, "HTTP Stream reader Status = %d, content_length = %d", + esp_http_client_get_status_code(client), + esp_http_client_get_content_length(client)); + esp_http_client_close(client); + esp_http_client_cleanup(client); + free(buffer); +} + +static void http_test_task(void *pvParameters) +{ + app_wifi_wait_connected(); + ESP_LOGI(TAG, "Connected to AP, begin http example"); + http_rest(); + http_auth_basic(); + http_auth_basic_redirect(); + http_auth_digest(); + http_relative_redirect(); + http_absolute_redirect(); + https(); + http_redirect_to_https(); + http_download_chunk(); + http_perform_as_stream_reader(); + ESP_LOGI(TAG, "Finish http example"); + vTaskDelete(NULL); +} + +void app_main() +{ + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + app_wifi_initialise(); + + xTaskCreate(&http_test_task, "http_test_task", 8192, NULL, 5, NULL); +} diff --git a/examples/protocols/esp_http_client/main/howsmyssl_com_root_cert.pem b/examples/protocols/esp_http_client/main/howsmyssl_com_root_cert.pem new file mode 100644 index 0000000000..0002462ce8 --- /dev/null +++ b/examples/protocols/esp_http_client/main/howsmyssl_com_root_cert.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/ +MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT +DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow +SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT +GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF +q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8 +SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0 +Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA +a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj +/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T +AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG +CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv +bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k +c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw +VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC +ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz +MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu +Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF +AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo +uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/ +wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu +X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG +PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6 +KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg== +-----END CERTIFICATE----- From 4c4e143a2f82215694e14f3c21828aba23c62db9 Mon Sep 17 00:00:00 2001 From: wangmengyang Date: Mon, 21 May 2018 11:33:30 +0800 Subject: [PATCH 139/187] component/bt: implement HFP Hands Free Unit Role --- components/bt/Kconfig | 27 + .../bt/bluedroid/api/esp_hf_client_api.c | 476 +++++ .../api/include/api/esp_hf_client_api.h | 635 ++++++ .../bluedroid/api/include/api/esp_hf_defs.h | 181 ++ components/bt/bluedroid/bta/dm/bta_dm_act.c | 28 +- components/bt/bluedroid/bta/dm/bta_dm_cfg.c | 221 +- components/bt/bluedroid/bta/dm/bta_dm_ci.c | 29 - components/bt/bluedroid/bta/dm/bta_dm_co.c | 143 -- components/bt/bluedroid/bta/dm/bta_dm_main.c | 4 +- components/bt/bluedroid/bta/dm/bta_dm_pm.c | 120 +- components/bt/bluedroid/bta/dm/bta_dm_sco.c | 2 +- .../bt/bluedroid/bta/dm/include/bta_dm_int.h | 33 +- .../bta/hf_client/bta_hf_client_act.c | 772 +++++++ .../bta/hf_client/bta_hf_client_api.c | 312 +++ .../bta/hf_client/bta_hf_client_at.c | 1795 +++++++++++++++++ .../bta/hf_client/bta_hf_client_cmd.c | 85 + .../bta/hf_client/bta_hf_client_main.c | 662 ++++++ .../bta/hf_client/bta_hf_client_rfc.c | 246 +++ .../bta/hf_client/bta_hf_client_sco.c | 825 ++++++++ .../bta/hf_client/bta_hf_client_sdp.c | 367 ++++ .../bta/hf_client/include/bta_hf_client_at.h | 117 ++ .../bta/hf_client/include/bta_hf_client_int.h | 296 +++ .../bt/bluedroid/bta/include/bta/bta_dm_ci.h | 12 - .../bt/bluedroid/bta/include/bta/bta_dm_co.h | 89 - .../bta/include/bta/bta_hf_client_api.h | 378 ++++ .../bta/include/bta/bta_hf_client_co.h | 115 ++ .../bluedroid/bta/include/bta/bta_hfp_defs.h | 47 + components/bt/bluedroid/btc/core/btc_dm.c | 8 + components/bt/bluedroid/btc/core/btc_task.c | 6 + .../bt/bluedroid/btc/include/btc/btc_task.h | 3 + .../profile/std/hf_client/bta_hf_client_co.c | 137 ++ .../btc/profile/std/hf_client/btc_hf_client.c | 1089 ++++++++++ .../btc/profile/std/include/btc_hf_client.h | 128 ++ .../common/include/common/bt_target.h | 39 +- components/bt/bluedroid/device/controller.c | 31 +- .../device/include/device/controller.h | 5 + components/bt/bluedroid/hci/hci_audio.c | 7 + .../bt/bluedroid/hci/hci_packet_factory.c | 12 +- .../bt/bluedroid/hci/hci_packet_parser.c | 14 +- .../bt/bluedroid/hci/include/hci/hci_audio.h | 42 + .../hci/include/hci/hci_packet_factory.h | 1 + .../hci/include/hci/hci_packet_parser.h | 6 +- components/bt/bluedroid/main/bte_init.c | 18 +- .../bt/bluedroid/stack/btm/btm_devctl.c | 3 + components/bt/bluedroid/stack/btm/btm_sco.c | 149 +- .../bt/bluedroid/stack/btm/include/btm_int.h | 7 + components/bt/bluedroid/stack/btu/btu_hcif.c | 4 +- .../bluedroid/stack/include/stack/btm_api.h | 4 +- .../bt/bluedroid/stack/rfcomm/port_rfc.c | 4 +- components/bt/bt.c | 10 + components/bt/component.mk | 4 +- components/bt/include/esp_bt.h | 15 + components/bt/lib | 2 +- components/esp32/ld/esp32.rom.ld | 1 + docs/Doxyfile | 2 + .../en/api-reference/bluetooth/classic_bt.rst | 2 + .../api-reference/bluetooth/esp_hf_client.rst | 14 + .../api-reference/bluetooth/esp_hf_defs.rst | 16 + .../api-reference/bluetooth/esp_hf_client.rst | 1 + .../api-reference/bluetooth/esp_hf_defs.rst | 1 + 60 files changed, 9191 insertions(+), 611 deletions(-) create mode 100644 components/bt/bluedroid/api/esp_hf_client_api.c create mode 100644 components/bt/bluedroid/api/include/api/esp_hf_client_api.h create mode 100644 components/bt/bluedroid/api/include/api/esp_hf_defs.h create mode 100644 components/bt/bluedroid/bta/hf_client/bta_hf_client_act.c create mode 100644 components/bt/bluedroid/bta/hf_client/bta_hf_client_api.c create mode 100644 components/bt/bluedroid/bta/hf_client/bta_hf_client_at.c create mode 100644 components/bt/bluedroid/bta/hf_client/bta_hf_client_cmd.c create mode 100644 components/bt/bluedroid/bta/hf_client/bta_hf_client_main.c create mode 100644 components/bt/bluedroid/bta/hf_client/bta_hf_client_rfc.c create mode 100644 components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c create mode 100644 components/bt/bluedroid/bta/hf_client/bta_hf_client_sdp.c create mode 100644 components/bt/bluedroid/bta/hf_client/include/bta_hf_client_at.h create mode 100644 components/bt/bluedroid/bta/hf_client/include/bta_hf_client_int.h create mode 100644 components/bt/bluedroid/bta/include/bta/bta_hf_client_api.h create mode 100644 components/bt/bluedroid/bta/include/bta/bta_hf_client_co.h create mode 100644 components/bt/bluedroid/bta/include/bta/bta_hfp_defs.h create mode 100644 components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c create mode 100644 components/bt/bluedroid/btc/profile/std/hf_client/btc_hf_client.c create mode 100644 components/bt/bluedroid/btc/profile/std/include/btc_hf_client.h create mode 100644 components/bt/bluedroid/hci/hci_audio.c create mode 100644 components/bt/bluedroid/hci/include/hci/hci_audio.h create mode 100644 docs/en/api-reference/bluetooth/esp_hf_client.rst create mode 100644 docs/en/api-reference/bluetooth/esp_hf_defs.rst create mode 100644 docs/zh_CN/api-reference/bluetooth/esp_hf_client.rst create mode 100644 docs/zh_CN/api-reference/bluetooth/esp_hf_defs.rst diff --git a/components/bt/Kconfig b/components/bt/Kconfig index 853265d653..aca5029e73 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -189,6 +189,33 @@ config BT_SPP_ENABLED help This enables the Serial Port Profile +config HFP_ENABLE + bool "Hands Free/Handset Profile" + depends on CLASSIC_BT_ENABLED + default n + +choice HFP_ROLE + prompt "Hands-free Profile Role configuration" + depends on HFP_ENABLE + +config HFP_CLIENT_ENABLE + bool "Hands Free Unit" +endchoice + +choice HFP_AUDIO_DATA_PATH + prompt "audio(SCO) data path" + depends on HFP_ENABLE + +config HFP_AUDIO_DATA_PATH_PCM + bool "PCM" + help + This enables the Serial Port Profile +config HFP_AUDIO_DATA_PATH_HCI + bool "HCI" + help + This enables the Serial Port Profile +endchoice + config GATTS_ENABLE bool "Include GATT server module(GATTS)" depends on BLUEDROID_ENABLED diff --git a/components/bt/bluedroid/api/esp_hf_client_api.c b/components/bt/bluedroid/api/esp_hf_client_api.c new file mode 100644 index 0000000000..fbc5d475cc --- /dev/null +++ b/components/bt/bluedroid/api/esp_hf_client_api.c @@ -0,0 +1,476 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "common/bt_target.h" +#include +#include "esp_err.h" +#include "esp_hf_client_api.h" +#include "esp_bt_main.h" +#include "btc/btc_manage.h" +#include "btc_hf_client.h" +#include "bta/bta_api.h" +#include "bta/bta_hf_client_api.h" + +#if BTC_HF_CLIENT_INCLUDED +esp_err_t esp_hf_client_register_callback(esp_hf_client_cb_t callback) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + if (callback == NULL) { + return ESP_FAIL; + } + + btc_profile_cb_set(BTC_PID_HF_CLIENT, callback); + return ESP_OK; +} + +esp_err_t esp_hf_client_init(void) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_INIT_EVT; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_deinit(void) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_DEINIT_EVT; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_connect(esp_bd_addr_t remote_bda) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + bt_status_t stat; + btc_hf_client_args_t arg; + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_CONNECT_EVT; + + memset(&arg, 0, sizeof(btc_hf_client_args_t)); + + /* Switch to BTC context */ + memcpy(&(arg.connect), remote_bda, sizeof(bt_bdaddr_t)); + stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_disconnect(esp_bd_addr_t remote_bda) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + bt_status_t stat; + btc_hf_client_args_t arg; + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_DISCONNECT_EVT; + + memset(&arg, 0, sizeof(btc_hf_client_args_t)); + + /* Switch to BTC context */ + memcpy(&(arg.disconnect), remote_bda, sizeof(bt_bdaddr_t)); + stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_connect_audio(esp_bd_addr_t remote_bda) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + bt_status_t stat; + btc_hf_client_args_t arg; + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_CONNECT_AUDIO_EVT; + + memset(&arg, 0, sizeof(btc_hf_client_args_t)); + + /* Switch to BTC context */ + memcpy(&(arg.connect_audio), remote_bda, sizeof(bt_bdaddr_t)); + stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_disconnect_audio(esp_bd_addr_t remote_bda) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + bt_status_t stat; + btc_hf_client_args_t arg; + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_DISCONNECT_AUDIO_EVT; + + memset(&arg, 0, sizeof(btc_hf_client_args_t)); + + /* Switch to BTC context */ + memcpy(&(arg.disconnect_audio), remote_bda, sizeof(bt_bdaddr_t)); + stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + + +esp_err_t esp_hf_client_start_voice_recognition(void) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_START_VOICE_RECOGNITION_EVT; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_stop_voice_recognition(void) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_STOP_VOICE_RECOGNITION_EVT; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_volume_update(esp_hf_volume_control_target_t type, int volume) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + btc_hf_client_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_VOLUME_UPDATE_EVT; + + memset(&arg, 0, sizeof(btc_hf_client_args_t)); + arg.volume_update.type = type; + arg.volume_update.volume = volume; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_dial(const char *number) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + btc_hf_client_args_t arg; + + if (number != NULL && strlen(number) > ESP_BT_HF_CLIENT_NUMBER_LEN) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_DIAL_EVT; + + memset(&arg, 0, sizeof(btc_hf_client_args_t)); + if (number != NULL) { + strcpy(arg.dial.number, number); + } else { + arg.dial.number[0] = '\0'; + } + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_dial_memory(int location) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + btc_hf_client_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_DIAL_MEMORY_EVT; + + memset(&arg, 0, sizeof(btc_hf_client_args_t)); + arg.dial_memory.location = location; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_send_chld_cmd(esp_hf_chld_type_t chld, int idx) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + btc_hf_client_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_SEND_CHLD_CMD_EVT; + + memset(&arg, 0, sizeof(btc_hf_client_args_t)); + arg.chld.type = chld; + arg.chld.idx = idx; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_send_btrh_cmd(esp_hf_btrh_cmd_t btrh) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + btc_hf_client_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_SEND_BTRH_CMD_EVT; + + memset(&arg, 0, sizeof(btc_hf_client_args_t)); + arg.btrh.cmd = btrh; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_answer_call(void) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_ANSWER_CALL_EVT; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_reject_call(void) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_REJECT_CALL_EVT; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_query_current_calls(void) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_QUERY_CURRENT_CALLS_EVT; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_query_current_operator_name(void) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_QUERY_CURRENT_OPERATOR_NAME_EVT; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_retrieve_subscriber_info(void) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_RETRIEVE_SUBSCRIBER_INFO_EVT; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_send_dtmf(char code) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + btc_hf_client_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_SEND_DTMF_EVT; + + memset(&arg, 0, sizeof(btc_hf_client_args_t)); + arg.send_dtmf.code = code; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_request_last_voice_tag_number(void) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_REQUEST_LAST_VOICE_TAG_NUMBER_EVT; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + +esp_err_t esp_hf_client_register_data_callback(esp_hf_client_incoming_data_cb_t recv, + esp_hf_client_outgoing_data_cb_t send) +{ + if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + + btc_msg_t msg; + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = BTC_HF_CLIENT_REGISTER_DATA_CALLBACK_EVT; + + btc_hf_client_args_t arg; + memset(&arg, 0, sizeof(btc_hf_client_args_t)); + arg.reg_data_cb.recv = recv; + arg.reg_data_cb.send = send; + + /* Switch to BTC context */ + bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hf_client_args_t), NULL); + return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL; +} + + +#if (BTM_SCO_HCI_INCLUDED == TRUE ) +void esp_hf_client_outgoing_data_ready(void) +{ + BTA_HfClientCiData(); +} + +void esp_hf_client_pcm_resample_init(uint32_t src_sps, uint32_t bits, uint32_t channels) +{ + BTA_DmPcmInitSamples(src_sps, bits, channels); +} + +int32_t esp_hf_client_pcm_resample(void *src, uint32_t in_bytes, void *dst) +{ + return BTA_DmPcmResample(src, in_bytes, dst); +} + +#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) */ + +#endif /* BTC_HF_CLIENT_INCLUDED */ diff --git a/components/bt/bluedroid/api/include/api/esp_hf_client_api.h b/components/bt/bluedroid/api/include/api/esp_hf_client_api.h new file mode 100644 index 0000000000..65598e0879 --- /dev/null +++ b/components/bt/bluedroid/api/include/api/esp_hf_client_api.h @@ -0,0 +1,635 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __ESP_HF_CLIENT_API_H__ +#define __ESP_HF_CLIENT_API_H__ + +#include "esp_err.h" +#include "esp_bt_defs.h" +#include "esp_hf_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ESP_BT_HF_CLIENT_NUMBER_LEN (32) +#define ESP_BT_HF_CLIENT_OPERATOR_NAME_LEN (16) + +/// Bluetooth HFP RFCOMM connection and service level connection status +typedef enum { + ESP_HF_CLIENT_CONNECTION_STATE_DISCONNECTED = 0, /*!< RFCOMM data link channel released */ + ESP_HF_CLIENT_CONNECTION_STATE_CONNECTING, /*!< connecting remote device on the RFCOMM data link*/ + ESP_HF_CLIENT_CONNECTION_STATE_CONNECTED, /*!< RFCOMM connection established */ + ESP_HF_CLIENT_CONNECTION_STATE_SLC_CONNECTED, /*!< service level connection established */ + ESP_HF_CLIENT_CONNECTION_STATE_DISCONNECTING, /*!< disconnecting with remote device on the RFCOMM dat link*/ +} esp_hf_client_connection_state_t; + +/// Bluetooth HFP audio connection status +typedef enum { + ESP_HF_CLIENT_AUDIO_STATE_DISCONNECTED = 0, /*!< audio connection released */ + ESP_HF_CLIENT_AUDIO_STATE_CONNECTING, /*!< audio connection has been initiated */ + ESP_HF_CLIENT_AUDIO_STATE_CONNECTED, /*!< audio connection is established */ + ESP_HF_CLIENT_AUDIO_STATE_CONNECTED_MSBC, /*!< mSBC audio connection is estalibshed */ +} esp_hf_client_audio_state_t; + +/// in-band ring tone state +typedef enum { + ESP_HF_CLIENT_IN_BAND_RINGTONE_NOT_PROVIDED = 0, + ESP_HF_CLIENT_IN_BAND_RINGTONE_PROVIDED, +} esp_hf_client_in_band_ring_state_t; + +/* features masks of AG */ +#define ESP_HF_CLIENT_PEER_FEAT_3WAY 0x01 /* Three-way calling */ +#define ESP_HF_CLIENT_PEER_FEAT_ECNR 0x02 /* Echo cancellation and/or noise reduction */ +#define ESP_HF_CLIENT_PEER_FEAT_VREC 0x04 /* Voice recognition */ +#define ESP_HF_CLIENT_PEER_FEAT_INBAND 0x08 /* In-band ring tone */ +#define ESP_HF_CLIENT_PEER_FEAT_VTAG 0x10 /* Attach a phone number to a voice tag */ +#define ESP_HF_CLIENT_PEER_FEAT_REJECT 0x20 /* Ability to reject incoming call */ +#define ESP_HF_CLIENT_PEER_FEAT_ECS 0x40 /* Enhanced Call Status */ +#define ESP_HF_CLIENT_PEER_FEAT_ECC 0x80 /* Enhanced Call Control */ +#define ESP_HF_CLIENT_PEER_FEAT_EXTERR 0x100 /* Extended error codes */ +#define ESP_HF_CLIENT_PEER_FEAT_CODEC 0x200 /* Codec Negotiation */ + +/* CHLD feature masks of AG */ +#define ESP_HF_CLIENT_CHLD_FEAT_REL 0x01 /* 0 Release waiting call or held calls */ +#define ESP_HF_CLIENT_CHLD_FEAT_REL_ACC 0x02 /* 1 Release active calls and accept other waiting or held call */ +#define ESP_HF_CLIENT_CHLD_FEAT_REL_X 0x04 /* 1x Release specified active call only */ +#define ESP_HF_CLIENT_CHLD_FEAT_HOLD_ACC 0x08 /* 2 Active calls on hold and accept other waiting or held call */ +#define ESP_HF_CLIENT_CHLD_FEAT_PRIV_X 0x10 /* 2x Request private mode with specified call(put the rest on hold */ +#define ESP_HF_CLIENT_CHLD_FEAT_MERGE 0x20 /* 3 Add held call to multiparty */ +#define ESP_HF_CLIENT_CHLD_FEAT_MERGE_DETACH 0x40 /* 4 Connect two calls and leave(disconnct from multiparty */ + +/// HF CLIENT callback events +typedef enum { + ESP_HF_CLIENT_CONNECTION_STATE_EVT = 0, /*!< connection state changed event */ + ESP_HF_CLIENT_AUDIO_STATE_EVT, /*!< audio connection state change event */ + ESP_HF_CLIENT_BVRA_EVT, /*!< voice recognition state change event */ + ESP_HF_CLIENT_CIND_CALL_EVT, /*!< call indication */ + ESP_HF_CLIENT_CIND_CALL_SETUP_EVT, /*!< call setup indication */ + ESP_HF_CLIENT_CIND_CALL_HELD_EVT, /*!< call held indication */ + ESP_HF_CLIENT_CIND_SERVICE_AVAILABILITY_EVT, /*!< network service availability indication */ + ESP_HF_CLIENT_CIND_SIGNAL_STRENGTH_EVT, /*!< signal strength indication */ + ESP_HF_CLIENT_CIND_ROAMING_STATUS_EVT, /*!< roaming status indication */ + ESP_HF_CLIENT_CIND_BATTERY_LEVEL_EVT, /*!< battery level indication */ + ESP_HF_CLIENT_COPS_CURRENT_OPERATOR_EVT, /*!< current operator information */ + ESP_HF_CLIENT_BTRH_EVT, /*!< call response and hold event */ + ESP_HF_CLIENT_CLIP_EVT, /*!< Calling Line Identification notification */ + ESP_HF_CLIENT_CCWA_EVT, /*!< call waiting notification */ + ESP_HF_CLIENT_CLCC_EVT, /*!< list of current calls notification */ + ESP_HF_CLIENT_VOLUME_CONTROL_EVT, /*!< audio volume control command from AG, provided by +VGM or +VGS message */ + ESP_HF_CLIENT_AT_RESPONSE_EVT, /*!< AT command response event */ + ESP_HF_CLIENT_CNUM_EVT, /*!< subscriber information response from AG */ + ESP_HF_CLIENT_BSIR_EVT, /*!< setting of in-band ring tone */ + ESP_HF_CLIENT_BINP_EVT, /*!< requested number of last voice tag from AG */ + ESP_HF_CLIENT_RING_IND_EVT, /*!< ring indication event */ +} esp_hf_client_cb_event_t; + +/// HFP client callback parameters +typedef union { + /** + * @brief ESP_HF_CLIENT_CONNECTION_STATE_EVT + */ + struct hf_client_conn_stat_param { + esp_hf_client_connection_state_t state; /*!< HF connection state */ + uint32_t peer_feat; /*!< AG supported features */ + uint32_t chld_feat; /*!< AG supported features on call hold and multiparty services */ + esp_bd_addr_t remote_bda; /*!< remote bluetooth device address */ + } conn_stat; /*!< HF callback param of ESP_HF_CLIENT_CONNECTION_STATE_EVT */ + + /** + * @brief ESP_HF_CLIENT_AUDIO_STATE_EVT + */ + struct hf_client_audio_stat_param { + esp_hf_client_audio_state_t state; /*!< audio connection state */ + esp_bd_addr_t remote_bda; /*!< remote bluetooth device address */ + } audio_stat; /*!< HF callback param of ESP_HF_CLIENT_AUDIO_STATE_EVT */ + + /** + * @brief ESP_HF_CLIENT_BVRA_EVT + */ + struct hf_client_bvra_param { + esp_hf_vr_state_t value; /*!< voice recognition state */ + } bvra; /*!< HF callback param of ESP_HF_CLIENT_BVRA_EVT */ + + /** + * @brief ESP_HF_CLIENT_CIND_SERVICE_AVAILABILITY_EVT + */ + struct hf_client_service_availability_param { + esp_hf_service_availability_status_t status; /*!< service availability status */ + } service_availability; /*!< HF callback param of ESP_HF_CLIENT_CIND_SERVICE_AVAILABILITY_EVT */ + + /** + * @brief ESP_HF_CLIENT_CIND_ROAMING_STATUS_EVT + */ + struct hf_client_network_roaming_param { + esp_hf_roaming_status_t status; /*!< roaming status */ + } roaming; /*!< HF callback param of ESP_HF_CLIENT_CIND_ROAMING_STATUS_EVT */ + + /** + * @brief ESP_HF_CLIENT_CIND_SIGNAL_STRENGTH_EVT + */ + struct hf_client_signal_strength_ind_param { + int value; /*!< singal strength value, ranges from 0 to 5 */ + } signal_strength; /*!< HF callback param of ESP_HF_CLIENT_CIND_SIGNAL_STRENGTH_EVT */ + + /** + * @brief ESP_HF_CLIENT_CIND_BATTERY_LEVEL_EVT + */ + struct hf_client_battery_level_ind_param { + int value; /*!< battery charge value, ranges from 0 to 5 */ + } battery_level; /*!< HF callback param of ESP_HF_CLIENT_CIND_BATTERY_LEVEL_EVT */ + + /** + * @brief ESP_HF_CLIENT_COPS_CURRENT_OPERATOR_EVT + */ + struct hf_client_current_operator_param { + const char *name; /*!< name of the network operator */ + } cops; /*!< HF callback param of ESP_HF_CLIENT_COPS_CURRENT_OPERATOR_EVT */ + + /** + * @brief ESP_HF_CLIENT_CIND_CALL_EVT + */ + struct hf_client_call_ind_param { + esp_hf_call_status_t status; /*!< call status indicator */ + } call; /*!< HF callback param of ESP_HF_CLIENT_CIND_CALL_EVT */ + + /** + * @brief ESP_HF_CLIENT_CIND_CALL_SETUP_EVT + */ + struct hf_client_call_setup_ind_param { + esp_hf_call_setup_status_t status; /*!< call setup status indicator */ + } call_setup; /*!< HF callback param of ESP_HF_CLIENT_BVRA_EVT */ + + /** + * @brief ESP_HF_CLIENT_CIND_CALL_HELD_EVT + */ + struct hf_client_call_held_ind_param { + esp_hf_call_held_status_t status; /*!< bluetooth proprietary call hold status indocator */ + } call_held; /*!< HF callback param of ESP_HF_CLIENT_CIND_CALL_HELD_EVT */ + + /** + * @brief ESP_HF_CLIENT_BTRH_EVT + */ + struct hf_client_btrh_param { + esp_hf_btrh_status_t status; /*!< call hold and response status result code */ + } btrh; /*!< HF callback param of ESP_HF_CLIENT_BRTH_EVT */ + + /** + * @brief ESP_HF_CLIENT_CLIP_EVT + */ + struct hf_client_clip_param { + const char *number; /*!< phone number string of call */ + } clip; /*!< HF callback param of ESP_HF_CLIENT_CLIP_EVT */ + + /** + * @brief ESP_HF_CLIENT_CCWA_EVT + */ + struct hf_client_ccwa_param { + const char *number; /*!< phone number string of waiting call */ + } ccwa; /*!< HF callback param of ESP_HF_CLIENT_BVRA_EVT */ + + /** + * @brief ESP_HF_CLIENT_CLCC_EVT + */ + struct hf_client_clcc_param { + int idx; /*!< numbering(starting with 1) of the call */ + esp_hf_current_call_direction_t dir; /*!< direction of the call */ + esp_hf_current_call_status_t status; /*!< status of the call */ + esp_hf_current_call_mpty_type_t mpty; /*!< multi-party flag */ + char *number; /*!< phone number(optional) */ + } clcc; /*!< HF callback param of ESP_HF_CLIENT_CLCC_EVT */ + + /** + * @brief ESP_HF_CLIENT_VOLUME_CONTROL_EVT + */ + struct hf_client_volume_control_param { + esp_hf_volume_control_target_t type; /*!< volume control target, speaker or microphone */ + int volume; /*!< gain, ranges from 0 to 15 */ + } volume_control; /*!< HF callback param of ESP_HF_CLIENT_VOLUME_CONTROL_EVT */ + + /** + * @brief ESP_HF_CLIENT_AT_RESPONSE_EVT + */ + struct hf_client_at_response_param { + esp_hf_at_response_code_t code; /*!< AT response code */ + esp_hf_cme_err_t cme; /*!< Extended Audio Gateway Error Result Code */ + } at_response; /*!< HF callback param of ESP_HF_CLIENT_AT_RESPONSE_EVT */ + + /** + * @brief ESP_HF_CLIENT_CNUM_EVT + */ + struct hf_client_cnum_param { + const char *number; /*!< phone number string */ + esp_hf_subscriber_service_type_t type; /*!< service type that the phone number relates to */ + } cnum; /*!< HF callback param of ESP_HF_CLIENT_CNUM_EVT */ + + /** + * @brief ESP_HF_CLIENT_BSIR_EVT + */ + struct hf_client_bsirparam { + esp_hf_client_in_band_ring_state_t state; /*!< setting state of in-band ring tone */ + } bsir; /*!< HF callback param of ESP_HF_CLIENT_BSIR_EVT */ + + /** + * @brief ESP_HF_CLIENT_BINP_EVT + */ + struct hf_client_binp_param { + const char *number; /*!< phone number corresponding to the last voice tag in the HF */ + } binp; /*!< HF callback param of ESP_HF_CLIENT_BINP_EVT */ + +} esp_hf_client_cb_param_t; + +/** + * @brief HFP client incoming data callback function, the callback is useful in case of + * Voice Over HCI. + * @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the + * buffer is allocated inside bluetooth protocol stack and will be released after + * invoke of the callback is finished. + * @param[in] len : size(in bytes) in buf + */ +typedef void (* esp_hf_client_incoming_data_cb_t)(const uint8_t *buf, uint32_t len); + +/** + * @brief HFP client outgoing data callback function, the callback is useful in case of + * Voice Over HCI. Once audio connection is set up and the application layer has + * prepared data to send, the lower layer will call this function to read data + * and then send. This callback is supposed to be implemented as non-blocking, + * and if data is not enough, return value 0 is supposed. + * + * @param[in] buf : pointer to incoming data(payload of HCI synchronous data packet), the + * buffer is allocated inside bluetooth protocol stack and will be released after + * invoke of the callback is finished. + * @param[in] len : size(in bytes) in buf + * @param[out] length of data successfully read + */ +typedef uint32_t (* esp_hf_client_outgoing_data_cb_t)(uint8_t *buf, uint32_t len); + +/** + * @brief HFP client callback function type + * + * @param event : Event type + * + * @param param : Pointer to callback parameter + */ +typedef void (* esp_hf_client_cb_t)(esp_hf_client_cb_event_t event, esp_hf_client_cb_param_t *param); + +/** + * @brief Register application callback function to HFP client module. This function should be called + * only after esp_bluedroid_enable() completes successfully, used by HFP client + * + * @param[in] callback: HFP client event callback function + * + * @return + * - ESP_OK: success + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: if callback is a NULL function pointer + * + */ +esp_err_t esp_hf_client_register_callback(esp_hf_client_cb_t callback); + +/** + * + * @brief Initialize the bluetooth HFP client module. This function should be called + * after esp_bluedroid_enable() completes successfully + * + * @return + * - ESP_OK: if the initialization request is sent successfully + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_init(void); + +/** + * + * @brief De-initialize for HFP client module. This function + * should be called only after esp_bluedroid_enable() completes successfully + * + * @return + * - ESP_OK: success + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_deinit(void); + +/** + * + * @brief Connect to remote bluetooth HFP audio gateway(AG) device, must after esp_a2d_hf_client_init() + * + * @param[in] remote_bda: remote bluetooth device address + * + * @return + * - ESP_OK: connect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_connect(esp_bd_addr_t remote_bda); + +/** + * + * @brief Disconnect from the remote HFP audio gateway + * + * @param[in] remote_bda: remote bluetooth device address + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_disconnect(esp_bd_addr_t remote_bda); + +/** + * + * @brief Create audio connection with remote HFP AG. As a precondition to use this API, + * Service Level Connection shall exist with AG + * + * @param[in] remote_bda: remote bluetooth device address + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_connect_audio(esp_bd_addr_t remote_bda); + +/** + * + * @brief Release the established audio connection with remote HFP AG. + * + * @param[in] remote_bda: remote bluetooth device address + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_disconnect_audio(esp_bd_addr_t remote_bda); + +/** + * + * @brief Enable voice recognition in the AG. As a precondition to use this API, + * Service Level Connection shall exist with AG + * + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_start_voice_recognition(void); + +/** + * + * @brief Disable voice recognition in the AG. As a precondition to use this API, + * Service Level Connection shall exist with AG + * + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_stop_voice_recognition(void); + +/** + * + * @brief Volume synchronization with AG. As a precondition to use this API, + * Service Level Connection shall exist with AG + * + * @param[in] type: volume control target, speaker or microphone + * @param[in] volume: gain of the speaker of microphone, ranges 0 to 15 + * + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_volume_update(esp_hf_volume_control_target_t type, int volume); + +/** + * + * @brief Place a call with a specified number, if number is NULL, last called number is + * called. As a precondition to use this API, Service Level Connection shall + * exist with AG + * + * @param[in] number: number string of the call. If NULL, the last number is called(aka re-dial) + * + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_dial(const char *number); + +/** + * + * @brief Place a call with number specified by location(speed dial). As a precondition, + * to use this API, Service Level Connection shall exist with AG + * + * @param[in] location: location of the number in the memory + * + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ + +esp_err_t esp_hf_client_dial_memory(int location); + +/** + * + * @brief Send call hold and multiparty commands, or enhanced call control commands(Use AT+CHLD). + * As a precondition to use this API, Service Level Connection shall exist with AG + * + * @param[in] chld: AT+CHLD call hold and multiparty handling AT command. + * @param[in] idx: used in Enhanced Call Control Mechanisms, used if chld is + * ESP_HF_CHLD_TYPE_REL_X or ESP_HF_CHLD_TYPE_PRIV_X + * + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_send_chld_cmd(esp_hf_chld_type_t chld, int idx); + +/** + * + * @brief Send response and hold action command(Send AT+BTRH command) + * As a precondition to use this API, Service Level Connection shall exist with AG + * + * @param[in] btrh: response and hold action to send + * + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_send_btrh_cmd(esp_hf_btrh_cmd_t btrh); + +/** + * + * @brief Answer an incoming call(send ATA command). As a precondition to use this API, + * Service Level Connection shall exist with AG + * + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_answer_call(void); + +/** + * + * @brief Reject an incoming call(send AT+CHUP command), As a precondition to use this API, + * Service Level Connection shall exist with AG + * + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_reject_call(void); + +/** + * + * @brief Query list of current calls in AG(send AT+CLCC command), As a precondition to use this API, + * Service Level Connection shall exist with AG + * + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_query_current_calls(void); + +/** + * + * @brief Query the name of currently selected network operator in AG(use AT+COPS commands) + * As a precondition to use this API, Service Level Connection shall exist with AG + * + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_query_current_operator_name(void); + +/** + * + * @brief Get subscriber information number from AG(send AT+CNUM command) + * As a precondition to use this API, Service Level Connection shall exist with AG + * + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_retrieve_subscriber_info(void); + +/** + * + * @brief Transmit DTMF codes during an ongoing call(use AT+VTS commands) + * As a precondition to use this API, Service Level Connection shall exist with AG + * + * @param[in] code: dtmf code, single ascii character in the set 0-9, #, *, A-D + * + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_send_dtmf(char code); + +/** + * + * @brief Request a phone number from AG corresponding to last voice tag recorded + * (send AT+BINP command). As a precondition to use this API, Service Level + * Connection shall exist with AG + * + * @return + * - ESP_OK: disconnect request is sent to lower layer + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: others + * + */ +esp_err_t esp_hf_client_request_last_voice_tag_number(void); + +/** + * @brief Register HFP client data output function; the callback is only used in + * the case that Voice Over HCI is enabled. + * + * @param[in] recv: HFP client incoming data callback function + * @param[in] send: HFP client outgoing data callback function + * + * @return + * - ESP_OK: success + * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled + * - ESP_FAIL: if callback is a NULL function pointer + * + */ +esp_err_t esp_hf_client_register_data_callback(esp_hf_client_incoming_data_cb_t recv, + esp_hf_client_outgoing_data_cb_t send); + +/** + * @brief Trigger the lower-layer to fetch and send audio data. This function is only + * only used in the case that Voice Over HCI is enabled. Precondition is that + * the HFP audio connection is connected. After this function is called, lower + * layer will invoke esp_hf_client_outgoing_data_cb_t to fetch data + * + */ +void esp_hf_client_outgoing_data_ready(void); + + +/** + * @brief Initialize the down sampling converter. This is a utility function that can + * only be used in the case that Voice Over HCI is enabled. + * + * @param[in] src_sps: original samples per second(source audio data, i.e. 48000, 32000, + * 16000, 44100, 22050, 11025) + * @param[in] bits: number of bits per pcm sample (16) + * @param[in] channels: number of channels (i.e. mono(1), stereo(2)...) + */ +void esp_hf_client_pcm_resample_init(uint32_t src_sps, uint32_t bits, uint32_t channels); + +/** + * @brief Down sampling utility to convert high sampling rate into 8K/16bits 1-channel mode PCM + * samples. This can only be used in the case that Voice Over HCI is enabled. + * + * @param[in] src: pointer to the buffer where the original smapling PCM are stored + * @param[in] in_bytes: length of the input PCM sample buffer in byte + * @param[in] dst: pointer to the buffer which is to be used to store the converted PCM samples + * + * @return number of samples converted + */ +int32_t esp_hf_client_pcm_resample(void *src, uint32_t in_bytes, void *dst); + +#ifdef __cplusplus +} +#endif + + +#endif /* __ESP_HF_CLIENT_API_H__ */ diff --git a/components/bt/bluedroid/api/include/api/esp_hf_defs.h b/components/bt/bluedroid/api/include/api/esp_hf_defs.h new file mode 100644 index 0000000000..b71277932d --- /dev/null +++ b/components/bt/bluedroid/api/include/api/esp_hf_defs.h @@ -0,0 +1,181 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __ESP_HF_DEFS_H__ +#define __ESP_HF_DEFS_H__ + +#include "esp_bt_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/// Bluetooth HFP audio volume control target +typedef enum { + ESP_HF_VOLUME_CONTROL_TARGET_SPK = 0, /*!< speaker */ + ESP_HF_VOLUME_CONTROL_TARGET_MIC, /*!< microphone */ +} esp_hf_volume_control_target_t; + +/// +CIND roaming status indicator values +typedef enum { + ESP_HF_ROAMING_STATUS_INACTIVE = 0, /*!< roaming is not active */ + ESP_HF_ROAMING_STATUS_ACTIVE, /*!< a roaming is active */ +} esp_hf_roaming_status_t; + +/// +CIND call status indicator values +typedef enum { + ESP_HF_CALL_STATUS_NO_CALLS = 0, /*!< no call in progress */ + ESP_HF_CALL_STATUS_CALL_IN_PROGRESS = 1, /*!< call is present(active or held) */ +} esp_hf_call_status_t; + +/// +CIND call setup status indicator values +typedef enum { + ESP_HF_CALL_SETUP_STATUS_NONE = 0, /*!< no call setup in progress */ + ESP_HF_CALL_SETUP_STATUS_INCOMING = 1, /*!< incoming call setup in progress */ + ESP_HF_CALL_SETUP_STATUS_OUTGOING_DIALING = 2, /*!< outgoing call setup in dialing state */ + ESP_HF_CALL_SETUP_STATUS_OUTGOING_ALERTING = 3, /*!< outgoing call setup in alerting state */ +} esp_hf_call_setup_status_t; + +/// +CIND call held indicator values +typedef enum { + ESP_HF_CALL_HELD_STATUS_NONE = 0, /*!< no calls held */ + ESP_HF_CALL_HELD_STATUS_HELD_AND_ACTIVE = 1, /*!< both active and held call */ + ESP_HF_CALL_HELD_STATUS_HELD = 2, /*!< call on hold, no active call*/ +} esp_hf_call_held_status_t; + +/// +CIND network service availability status +typedef enum { + ESP_HF_SERVICE_AVAILABILITY_STATUS_UNAVAILABLE = 0, /*!< service not available */ + ESP_HF_SERVICE_AVAILABILITY_STATUS_AVAILABLE, /*!< service available */ +} esp_hf_service_availability_status_t; + +/// +CLCC status of the call +typedef enum { + ESP_HF_CURRENT_CALL_STATUS_ACTIVE = 0, /*!< active */ + ESP_HF_CURRENT_CALL_STATUS_HELD = 1, /*!< held */ + ESP_HF_CURRENT_CALL_STATUS_DIALING = 2, /*!< dialing (outgoing calls only) */ + ESP_HF_CURRENT_CALL_STATUS_ALERTING = 3, /*!< alerting (outgoing calls only) */ + ESP_HF_CURRENT_CALL_STATUS_INCOMING = 4, /*!< incoming (incoming calls only) */ + ESP_HF_CURRENT_CALL_STATUS_WAITING = 5, /*!< waiting (incoming calls only) */ + ESP_HF_CURRENT_CALL_STATUS_HELD_BY_RESP_HOLD = 6, /*!< call held by response and hold */ +} esp_hf_current_call_status_t; + +/// +CLCC direction of the call +typedef enum { + ESP_HF_CURRENT_CALL_DIRECTION_OUTGOING = 0, /*!< outgoing */ + ESP_HF_CURRENT_CALL_DIRECTION_INCOMING = 1, /*!< incoming */ +} esp_hf_current_call_direction_t; + +/// +CLCC multi-party call flag +typedef enum { + ESP_HF_CURRENT_CALL_MPTY_TYPE_SINGLE = 0, /*!< not a member of a multi-party call */ + ESP_HF_CURRENT_CALL_MPTY_TYPE_MULTI = 1, /*!< member of a multi-party call */ +} esp_hf_current_call_mpty_type_t; + +/// +CLCC call mode +typedef enum { + ESP_HF_CURRENT_CALL_MODE_VOICE = 0, + ESP_HF_CURRENT_CALL_MODE_DATA = 1, + ESP_HF_CURRENT_CALL_MODE_FAX = 2, +} esp_hf_current_call_mode_t; + +/// +CLCC address type +typedef enum { + ESP_HF_CALL_ADDR_TYPE_UNKNOWN = 0x81, /*!< unkown address type */ + ESP_HF_CALL_ADDR_TYPE_INTERNATIONAL = 0x91, /*!< international address */ +} esp_hf_call_addr_type_t; + +/// +CNUM service type of the phone number +typedef enum { + ESP_HF_SUBSCRIBER_SERVICE_TYPE_UNKNOWN = 0, /*!< unknown */ + ESP_HF_SUBSCRIBER_SERVICE_TYPE_VOICE, /*!< voice service */ + ESP_HF_SUBSCRIBER_SERVICE_TYPE_FAX, /*!< fax service */ +} esp_hf_subscriber_service_type_t; + +/// +BTRH response and hold result code +typedef enum { + ESP_HF_BTRH_STATUS_HELD = 0, /*!< incoming call is put on held in AG */ + ESP_HF_BTRH_STATUS_ACCEPTED, /*!< held incoming call is accepted in AG */ + ESP_HF_BTRH_STATUS_REJECTED, /*!< held incoming call is rejected in AG */ +} esp_hf_btrh_status_t; + +/// AT+BTRH response and hold action code +typedef enum { + ESP_HF_BTRH_CMD_HOLD = 0, /*!< put the incoming call on hold */ + ESP_HF_BTRH_CMD_ACCEPT = 1, /*!< accept a held incoming call */ + ESP_HF_BTRH_CMD_REJECT = 2, /*!< reject a held incoming call */ +} esp_hf_btrh_cmd_t; + +/// response indication codes for AT commands +typedef enum { + ESP_HF_AT_RESPONSE_CODE_OK = 0, /*!< acknoweledges execution of a command line */ + ESP_HF_AT_RESPONSE_CODE_ERR, /*!< command not accepted */ + ESP_HF_AT_RESPONSE_CODE_NO_CARRIER, /*!< connection terminated */ + ESP_HF_AT_RESPONSE_CODE_BUSY, /*!< busy signal detected */ + ESP_HF_AT_RESPONSE_CODE_NO_ANSWER, /*!< connection completion timeout */ + ESP_HF_AT_RESPONSE_CODE_DELAYED, /*!< delayed */ + ESP_HF_AT_RESPONSE_CODE_BLACKLISTED, /*!< blacklisted */ + ESP_HF_AT_RESPONSE_CODE_CME, /*!< CME error */ +} esp_hf_at_response_code_t; + +/// voice recognition state +typedef enum { + ESP_HF_VR_STATE_DISABLED = 0, /*!< voice recognition disabled */ + ESP_HF_VR_STATE_ENABLED, /*!< voice recognition enabled */ +} esp_hf_vr_state_t; + +/// AT+CHLD command values +typedef enum { + ESP_HF_CHLD_TYPE_REL = 0, /*!< <0>, Terminate all held or set UDUB("busy") to a waiting call */ + ESP_HF_CHLD_TYPE_REL_ACC, /*!< <1>, Terminate all active calls and accepts a waiting/held call */ + ESP_HF_CHLD_TYPE_HOLD_ACC, /*!< <2>, Hold all active calls and accepts a waiting/held call */ + ESP_HF_CHLD_TYPE_MERGE, /*!< <3>, Add all held calls to a conference */ + ESP_HF_CHLD_TYPE_MERGE_DETACH, /*!< <4>, connect the two calls and disconnects the subscriber from both calls */ + ESP_HF_CHLD_TYPE_REL_X, /*!< <1x>, releases specified calls only */ + ESP_HF_CHLD_TYPE_PRIV_X, /*!< <2x>, request private consultation mode with specified call */ +} esp_hf_chld_type_t; + +/// Extended Audio Gateway Error Result Code Response +typedef enum { + ESP_HF_CME_AG_FAILURE = 0, /*!< ag failure */ + ESP_HF_CME_NO_CONNECTION_TO_PHONE = 1, /*!< no connection to phone */ + ESP_HF_CME_OPERATION_NOT_ALLOWED = 3, /*!< operation not allowed */ + ESP_HF_CME_OPERATION_NOT_SUPPORTED = 4, /*!< operation not supported */ + ESP_HF_CME_PH_SIM_PIN_REQUIRED = 5, /*!< PH-SIM PIN Required */ + ESP_HF_CME_SIM_NOT_INSERTED = 10, /*!< SIM not inserted */ + ESP_HF_CME_SIM_PIN_REQUIRED = 11, /*!< SIM PIN required */ + ESP_HF_CME_SIM_PUK_REQUIRED = 12, /*!< SIM PUK required */ + ESP_HF_CME_SIM_FAILURE = 13, /*!< SIM failure */ + ESP_HF_CME_SIM_BUSY = 14, /*!< SIM busy */ + ESP_HF_CME_INCORRECT_PASSWORD = 16, /*!< incorrect password */ + ESP_HF_CME_SIM_PIN2_REQUIRED = 17, /*!< SIM PIN2 required */ + ESP_HF_CME_SIM_PUK2_REQUIRED = 18, /*!< SIM PUK2 required */ + ESP_HF_CME_MEMEORY_FULL = 20, /*!< memory full */ + ESP_HF_CME_INVALID_INDEX = 21, /*!< invalid index */ + ESP_HF_CME_MEMEORY_FAILURE = 23, /*!< memory failure */ + ESP_HF_CME_TEXT_STRING_TOO_LONG = 24, /*!< test string too long */ + ESP_HF_CME_INVALID_CHARACTERS_IN_TEXT_STRING = 25, /*!< invalid characters in text string */ + ESP_HF_CME_DIAL_STRING_TOO_LONG = 26, /*!< dial string too long*/ + ESP_HF_CME_INVALID_CHARACTERS_IN_DIAL_STRING = 27, /*!< invalid characters in dial string */ + ESP_HF_CME_NO_NETWORK_SERVICE = 30, /*!< no network service */ + ESP_HF_CME_NETWORK_TIMEOUT = 31, /*!< network timeout */ + ESP_HF_CME_NETWORK_NOT_ALLOWED = 32, /*!< network not allowed --emergency calls only */ +} esp_hf_cme_err_t; + +#ifdef __cplusplus +} +#endif + +#endif /* __ESP_HF_DEFS_H__ */ diff --git a/components/bt/bluedroid/bta/dm/bta_dm_act.c b/components/bt/bluedroid/bta/dm/bta_dm_act.c index 3985dc839d..c2eff109a7 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_act.c @@ -396,9 +396,7 @@ static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status ) #endif /* hw is ready, go on with BTA DM initialization */ memset(&bta_dm_search_cb, 0x00, sizeof(bta_dm_search_cb)); -#if (BTM_SSR_INCLUDED == TRUE) memset(&bta_dm_conn_srvcs, 0x00, sizeof(bta_dm_conn_srvcs)); -#endif ///BTM_SSR_INCLUDED == TRUE memset(&bta_dm_di_cb, 0, sizeof(tBTA_DM_DI_CB)); memcpy(dev_class, p_bta_dm_cfg->dev_class, sizeof(dev_class)); @@ -443,10 +441,12 @@ static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status ) BTM_ReadLocalDeviceNameFromController((tBTM_CMPL_CB *)bta_dm_local_name_cback); bta_sys_rm_register((tBTA_SYS_CONN_CBACK *)bta_dm_rm_cback); -#if (BTM_SSR_INCLUDED == TRUE) + +#if (BTA_DM_PM_INCLUDED == TRUE) /* initialize bluetooth low power manager */ bta_dm_init_pm(); -#endif ///BTM_SSR_INCLUDED == TRUE +#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */ + bta_sys_policy_register((tBTA_SYS_CONN_CBACK *)bta_dm_policy_cback); #if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE && SDP_INCLUDED == TRUE) && (GATTC_INCLUDED == TRUE) @@ -483,9 +483,11 @@ void bta_dm_disable (tBTA_DM_MSG *p_data) BTM_SetDiscoverability(BTM_NON_DISCOVERABLE, 0, 0); BTM_SetConnectability(BTM_NON_CONNECTABLE, 0, 0); -#if (BTM_SSR_INCLUDED == TRUE) + +#if (BTA_DM_PM_INCLUDED == TRUE) bta_dm_disable_pm(); -#endif ///BTM_SSR_INCLUDED == TRUE +#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */ + bta_dm_disable_search_and_disc(); bta_dm_cb.disabling = TRUE; @@ -1070,12 +1072,12 @@ static void bta_dm_policy_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app p_dev->link_policy &= (~policy); BTM_SetLinkPolicy(p_dev->peer_bdaddr, &(p_dev->link_policy)); +#if (BTA_DM_PM_INCLUDED == TRUE) if (policy & (HCI_ENABLE_SNIFF_MODE | HCI_ENABLE_PARK_MODE)) { /* if clearing sniff/park, wake the link */ -#if (BTM_SSR_INCLUDED == TRUE) bta_dm_pm_active(p_dev->peer_bdaddr); -#endif ///BTM_SSR_INCLUDED == TRUE } +#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */ break; case BTA_SYS_PLCY_DEF_SET: @@ -3365,10 +3367,12 @@ static void bta_dm_disable_conn_down_timer_cback (TIMER_LIST_ENT *p_tle) { UNUSED(p_tle); tBTA_SYS_HW_MSG *sys_enable_event; -#if (BTM_SSR_INCLUDED == TRUE) + +#if (BTA_DM_PM_INCLUDED == TRUE) /* disable the power managment module */ bta_dm_disable_pm(); -#endif ///BTM_SSR_INCLUDED == TRUE +#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */ + /* register our callback to SYS HW manager */ bta_sys_hw_register( BTA_SYS_HW_BLUETOOTH, bta_dm_sys_hw_cback ); @@ -3431,9 +3435,7 @@ static void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, } /* AV calls bta_sys_conn_open with the A2DP stream count as app_id */ if (BTA_ID_AV == id) { -#if (BTM_SSR_INCLUDED == TRUE) bta_dm_cb.cur_av_count = bta_dm_get_av_count(); -#endif ///BTM_SSR_INCLUDED == TRUE } } else if ( status == BTA_SYS_CONN_IDLE) { if (p_dev) { @@ -3442,9 +3444,7 @@ static void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, /* get cur_av_count from connected services */ if (BTA_ID_AV == id) { -#if (BTM_SSR_INCLUDED == TRUE) bta_dm_cb.cur_av_count = bta_dm_get_av_count(); -#endif ///BTM_SSR_INCLUDED == TRUE } } APPL_TRACE_EVENT("bta_dm_rm_cback:%d, status:%d", bta_dm_cb.cur_av_count, status); diff --git a/components/bt/bluedroid/bta/dm/bta_dm_cfg.c b/components/bt/bluedroid/bta/dm/bta_dm_cfg.c index 2e22aa77c5..c29960ab68 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_cfg.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_cfg.c @@ -116,39 +116,24 @@ tBTA_DM_CFG *p_bta_dm_cfg = (tBTA_DM_CFG *) &bta_dm_cfg; tBTA_DM_RM *p_bta_dm_rm_cfg = (tBTA_DM_RM *) &bta_dm_rm_cfg; #if BLE_INCLUDED == TRUE -# define BTA_DM_NUM_PM_ENTRY 21 /* number of entries in bta_dm_pm_cfg except the first */ -# define BTA_DM_NUM_PM_SPEC 15 /* number of entries in bta_dm_pm_spec */ +# define BTA_DM_NUM_PM_ENTRY 6 /* number of entries in bta_dm_pm_cfg except the first */ +# define BTA_DM_NUM_PM_SPEC 6 /* number of entries in bta_dm_pm_spec */ #else -# define BTA_DM_NUM_PM_ENTRY 19 /* number of entries in bta_dm_pm_cfg except the first */ -# define BTA_DM_NUM_PM_SPEC 13 /* number of entries in bta_dm_pm_spec */ +# define BTA_DM_NUM_PM_ENTRY 4 /* number of entries in bta_dm_pm_cfg except the first */ +# define BTA_DM_NUM_PM_SPEC 4 /* number of entries in bta_dm_pm_spec */ #endif +#if (BTA_DM_PM_INCLUDED == TRUE) + tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_CFG bta_dm_pm_cfg[BTA_DM_NUM_PM_ENTRY + 1] = { {BTA_ID_SYS, BTA_DM_NUM_PM_ENTRY, 0}, /* reserved: specifies length of this table. */ {BTA_ID_AG, BTA_ALL_APP_ID, 0}, /* ag uses first spec table for app id 0 */ - {BTA_ID_CT, 1, 1}, /* ct (BTA_ID_CT,APP ID=1) spec table */ - {BTA_ID_CG, BTA_ALL_APP_ID, 1}, /* cg resue ct spec table */ - {BTA_ID_DG, BTA_ALL_APP_ID, 2}, /* dg spec table */ - {BTA_ID_AV, BTA_ALL_APP_ID, 4}, /* av spec table */ - {BTA_ID_AVK, BTA_ALL_APP_ID, 12}, /* avk spec table */ - {BTA_ID_FTC, BTA_ALL_APP_ID, 6}, /* ftc spec table */ - {BTA_ID_FTS, BTA_ALL_APP_ID, 7}, /* fts spec table */ - {BTA_ID_HD, BTA_ALL_APP_ID, 3}, /* hd spec table */ - {BTA_ID_HH, BTA_ALL_APP_ID, 5}, /* hh spec table */ - {BTA_ID_PBC, BTA_ALL_APP_ID, 2}, /* reuse dg spec table */ - {BTA_ID_PBS, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */ - {BTA_ID_OPC, BTA_ALL_APP_ID, 6}, /* reuse ftc spec table */ - {BTA_ID_OPS, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */ - {BTA_ID_MSE, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */ - // {BTA_ID_JV, BTA_JV_PM_ID_1, 6}, /* app BTA_JV_PM_ID_1, reuse ftc spec table */ - // {BTA_ID_JV, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */ - {BTA_ID_HL, BTA_ALL_APP_ID, 8}, /* reuse fts spec table */ - {BTA_ID_PAN, BTUI_PAN_ID_PANU, 9}, /* PANU spec table */ - {BTA_ID_PAN, BTUI_PAN_ID_NAP, 10}, /* NAP spec table */ - {BTA_ID_HS, BTA_ALL_APP_ID, 11} /* HS spec table */ + {BTA_ID_AV, BTA_ALL_APP_ID, 1}, /* av spec table */ + {BTA_ID_HS, BTA_ALL_APP_ID, 2}, /* HS spec table */ + {BTA_ID_AVK, BTA_ALL_APP_ID, 3} /* avk spec table */ #if BLE_INCLUDED == TRUE - , {BTA_ID_GATTC, BTA_ALL_APP_ID, 13} /* gattc spec table */ - , {BTA_ID_GATTS, BTA_ALL_APP_ID, 14} /* gatts spec table */ + , {BTA_ID_GATTC, BTA_ALL_APP_ID, 4} /* gattc spec table */ + , {BTA_ID_GATTS, BTA_ALL_APP_ID, 5} /* gatts spec table */ #endif }; @@ -173,64 +158,7 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = { } }, - /* CT, CG : 1 */ - { - (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */ -#if (BTM_SSR_INCLUDED == TRUE) - (BTA_DM_PM_SSR2), /* the SSR entry */ -#endif - { - {{BTA_DM_PM_PARK, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open park */ - {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */ - {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open sniff */ - {{BTA_DM_PM_PARK, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close park */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */ - {{BTA_DM_PM_RETRY, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ - } - }, - - /* DG, PBC : 2 */ - { - (BTA_DM_PM_ACTIVE), /* no power saving mode allowed */ -#if (BTM_SSR_INCLUDED == TRUE) - (BTA_DM_PM_SSR2), /* the SSR entry */ -#endif - { - {{BTA_DM_PM_SNIFF, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open active */ - {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */ - {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */ - {{BTA_DM_PM_SNIFF, 1000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ - {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ - } - }, - - /* HD : 3 */ - { - (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */ -#if (BTM_SSR_INCLUDED == TRUE) - (BTA_DM_PM_SSR3), /* the SSR entry */ -#endif - { - {{BTA_DM_PM_SNIFF_HD_ACTIVE_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */ - {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */ - {{BTA_DM_PM_SNIFF_HD_IDLE_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ - {{BTA_DM_PM_SNIFF_HD_ACTIVE_IDX, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ - } - }, - - /* AV : 4 */ + /* AV : 1 */ { (BTA_DM_PM_SNIFF), /* allow sniff */ #if (BTM_SSR_INCLUDED == TRUE) @@ -249,122 +177,7 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = { } }, - /* HH : 5 */ - { - (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */ -#if (BTM_SSR_INCLUDED == TRUE) - (BTA_DM_PM_SSR1), /* the SSR entry */ -#endif - { - {{BTA_DM_PM_SNIFF_HH_OPEN_IDX, BTA_DM_PM_HH_OPEN_DELAY + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */ - {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close, used for HH suspend */ - {{BTA_DM_PM_SNIFF_HH_IDLE_IDX, BTA_DM_PM_HH_IDLE_DELAY + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ - {{BTA_DM_PM_SNIFF_HH_ACTIVE_IDX, BTA_DM_PM_HH_ACTIVE_DELAY + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ - } - }, - - /* FTC, OPC, JV : 6 */ - { - (BTA_DM_PM_SNIFF), /* allow sniff */ -#if (BTM_SSR_INCLUDED == TRUE) - (BTA_DM_PM_SSR2), /* the SSR entry */ -#endif - { - {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open active */ - {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */ - {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */ - {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ - {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ - } - }, - - /* FTS, PBS, OPS, MSE, BTA_JV_PM_ID_1 : 7 */ - { - (BTA_DM_PM_SNIFF), /* allow sniff */ -#if (BTM_SSR_INCLUDED == TRUE) - (BTA_DM_PM_SSR2), /* the SSR entry */ -#endif - { - {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open active */ - {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */ - {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */ - {{BTA_DM_PM_SNIFF_A2DP_IDX, BTA_FTS_OPS_IDLE_TO_SNIFF_DELAY_MS + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ - {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ - } - }, - - /* HL : 8 */ - { - (BTA_DM_PM_SNIFF), /* allow sniff */ -#if (BTM_SSR_INCLUDED == TRUE) - (BTA_DM_PM_SSR2), /* the SSR entry */ -#endif - { - {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */ - {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open, active */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close sniff */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ - {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ - } - }, - - /* PANU : 9 */ - { - (BTA_DM_PM_SNIFF), /* allow sniff */ -#if (BTM_SSR_INCLUDED == TRUE) - (BTA_DM_PM_SSR2), /* the SSR entry */ -#endif - { - {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open active */ - {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */ - {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */ - {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ - {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ - } - }, - - /* NAP : 10 */ - { - (BTA_DM_PM_SNIFF), /* allow sniff */ -#if (BTM_SSR_INCLUDED == TRUE) - (BTA_DM_PM_SSR2), /* the SSR entry */ -#endif - { - {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open active */ - {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */ - {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */ - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */ - {{BTA_DM_PM_SNIFF_A2DP_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */ - {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */ - - {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ - } - }, - - /* HS : 11 */ + /* HS : 2 */ { (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */ #if (BTM_SSR_INCLUDED == TRUE) @@ -383,7 +196,7 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = { } }, - /* AVK : 12 */ + /* AVK : 3 */ { (BTA_DM_PM_SNIFF), /* allow sniff */ #if (BTM_SSR_INCLUDED == TRUE) @@ -403,7 +216,7 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = { } #if BLE_INCLUDED == TRUE - /* GATTC : 13 */ + /* GATTC : 4 */ , { (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */ #if (BTM_SSR_INCLUDED == TRUE) @@ -424,7 +237,7 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = { {{BTA_DM_PM_RETRY, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */ } } - /* GATTS : 14 */ + /* GATTS : 5 */ , { (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */ #if (BTM_SSR_INCLUDED == TRUE) @@ -528,6 +341,8 @@ tBTA_DM_PM_CFG *p_bta_dm_pm_cfg = (tBTA_DM_PM_CFG *) &bta_dm_pm_cfg; tBTA_DM_PM_SPEC *p_bta_dm_pm_spec = (tBTA_DM_PM_SPEC *) &bta_dm_pm_spec; tBTM_PM_PWR_MD *p_bta_dm_pm_md = (tBTM_PM_PWR_MD *) &bta_dm_pm_md; +#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */ + /* The performance impact of EIR packet size ** ** When BTM_EIR_DEFAULT_FEC_REQUIRED is TRUE, diff --git a/components/bt/bluedroid/bta/dm/bta_dm_ci.c b/components/bt/bluedroid/bta/dm/bta_dm_ci.c index e7385013c5..f10787ad03 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_ci.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_ci.c @@ -83,32 +83,3 @@ void bta_dm_ci_rmt_oob(BOOLEAN accept, BD_ADDR bd_addr, BT_OCTET16 c, BT_OCTET16 } } #endif /* BTM_OOB_INCLUDED */ - -#if (BTM_SCO_HCI_INCLUDED == TRUE) -/******************************************************************************* -** -** Function bta_dm_sco_ci_data_ready -** -** Description This function sends an event to indicating that the phone -** has SCO data ready. -** -** Parameters event: is obtained from bta_dm_sco_co_open() function, which -** is the BTA event we want to send back to BTA module -** when there is encoded data ready. -** sco_handle: is the BTA sco handle which indicate a specific -** SCO connection. -** Returns void -** -*******************************************************************************/ -void bta_dm_sco_ci_data_ready(UINT16 event, UINT16 sco_handle) -{ - BT_HDR *p_buf; - - if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { - p_buf->event = event; - p_buf->layer_specific = sco_handle; - - bta_sys_sendmsg(p_buf); - } -} -#endif diff --git a/components/bt/bluedroid/bta/dm/bta_dm_co.c b/components/bt/bluedroid/bta/dm/bta_dm_co.c index 9b0b89b3a4..dbfabc3b7a 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_co.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_co.c @@ -205,149 +205,6 @@ void bta_dm_co_rmt_oob(BD_ADDR bd_addr) // REMOVE FOR BLUEDROID ? -#if (BTM_SCO_HCI_INCLUDED == TRUE ) && (BTM_SCO_INCLUDED == TRUE) -#if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE) -/******************************************************************************* -** -** Function btui_sco_codec_callback -** -** Description Callback for btui codec. -** -** -** Returns void -** -*******************************************************************************/ -static void btui_sco_codec_callback(UINT16 event, UINT16 sco_handle) -{ - bta_dm_sco_ci_data_ready(event, sco_handle); -} -/******************************************************************************* -** -** Function bta_dm_sco_co_init -** -** Description This function can be used by the phone to initialize audio -** codec or for other initialization purposes before SCO connection -** is opened. -** -** -** Returns tBTA_DM_SCO_ROUTE_TYPE: SCO routing configuration type. -** -*******************************************************************************/ -tBTA_DM_SCO_ROUTE_TYPE bta_dm_sco_co_init(UINT32 rx_bw, UINT32 tx_bw, - tBTA_CODEC_INFO *p_codec_type, UINT8 app_id) -{ - tBTM_SCO_ROUTE_TYPE route = BTA_DM_SCO_ROUTE_PCM; - - BTIF_TRACE_DEBUG("bta_dm_sco_co_init"); - - /* set up SCO routing configuration if SCO over HCI app ID is used and run time - configuration is set to SCO over HCI */ - /* HS invoke this call-out */ - if ( -#if (BTA_HS_INCLUDED == TRUE ) && (BTA_HS_INCLUDED == TRUE) - (app_id == BTUI_DM_SCO_4_HS_APP_ID && btui_cfg.hs_sco_over_hci) || -#endif - /* AG invoke this call-out */ - (app_id != BTUI_DM_SCO_4_HS_APP_ID && btui_cfg.ag_sco_over_hci )) { - route = btui_cb.sco_hci = BTA_DM_SCO_ROUTE_HCI; - } - /* no codec is is used for the SCO data */ - if (p_codec_type->codec_type == BTA_SCO_CODEC_PCM && route == BTA_DM_SCO_ROUTE_HCI) { - /* initialize SCO codec */ - if (!btui_sco_codec_init(rx_bw, tx_bw)) { - BTIF_TRACE_ERROR("codec initialization exception!"); - } - } - - return route; -} - - - -/******************************************************************************* -** -** Function bta_dm_sco_co_open -** -** Description This function is executed when a SCO connection is open. -** -** -** Returns void -** -*******************************************************************************/ -void bta_dm_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event) -{ - tBTUI_SCO_CODEC_CFG cfg; - - if (btui_cb.sco_hci) { - BTIF_TRACE_DEBUG("bta_dm_sco_co_open handle:%d pkt_size:%d", handle, pkt_size); - /* use dedicated SCO buffer pool for SCO TX data */ - cfg.pool_id = HCI_SCO_POOL_ID; - cfg.p_cback = btui_sco_codec_callback; - cfg.pkt_size = pkt_size; - cfg.cb_event = event; - /* open and start the codec */ - btui_sco_codec_open(&cfg); - btui_sco_codec_start(handle); - } -} - -/******************************************************************************* -** -** Function bta_dm_sco_co_close -** -** Description This function is called when a SCO connection is closed -** -** -** Returns void -** -*******************************************************************************/ -void bta_dm_sco_co_close(void) -{ - if (btui_cb.sco_hci) { - BTIF_TRACE_DEBUG("bta_dm_sco_co_close close codec"); - /* close sco codec */ - btui_sco_codec_close(); - - btui_cb.sco_hci = FALSE; - } -} - -/******************************************************************************* -** -** Function bta_dm_sco_co_in_data -** -** Description This function is called to send incoming SCO data to application. -** -** Returns void -** -*******************************************************************************/ -void bta_dm_sco_co_in_data(BT_HDR *p_buf) -{ - if (btui_cfg.sco_use_mic) { - btui_sco_codec_inqdata (p_buf); - } else { - osi_free(p_buf); - } -} - -/******************************************************************************* -** -** Function bta_dm_sco_co_out_data -** -** Description This function is called to send SCO data over HCI. -** -** Returns void -** -*******************************************************************************/ -void bta_dm_sco_co_out_data(BT_HDR **p_buf) -{ - btui_sco_codec_readbuf(p_buf); -} - -#endif /* #if (defined(BTIF_INCLUDED) && BTIF_INCLUDED == TRUE) */ -#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) && (BTM_SCO_INCLUDED == TRUE)*/ - - #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE) /******************************************************************************* ** diff --git a/components/bt/bluedroid/bta/dm/bta_dm_main.c b/components/bt/bluedroid/bta/dm/bta_dm_main.c index 75d5ad44c6..25977e7a49 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_main.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_main.c @@ -66,11 +66,11 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { bta_dm_bond_cancel, /* 12 BTA_DM_API_BOND_CANCEL_EVT */ bta_dm_pin_reply, /* 13 BTA_DM_API_PIN_REPLY_EVT */ #endif ///SMP_INCLUDED == TRUE -#if (BTM_SSR_INCLUDED == TRUE) +#if (BTA_DM_PM_INCLUDED == TRUE) /* power manger events */ bta_dm_pm_btm_status, /* 16 BTA_DM_PM_BTM_STATUS_EVT */ bta_dm_pm_timer, /* 17 BTA_DM_PM_TIMER_EVT*/ -#endif ///BTM_SSR_INCLUDED == TRUE +#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */ /* simple pairing events */ #if (SMP_INCLUDED == TRUE) bta_dm_confirm, /* 18 BTA_DM_API_CONFIRM_EVT */ diff --git a/components/bt/bluedroid/bta/dm/bta_dm_pm.c b/components/bt/bluedroid/bta/dm/bta_dm_pm.c index a876ec36a9..e0f967ba50 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_pm.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_pm.c @@ -30,9 +30,11 @@ #include "bta/bta_api.h" #include "bta_dm_int.h" #include "stack/btm_api.h" +#include "osi/allocator.h" -#if (BTM_SSR_INCLUDED == TRUE) +tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs; +#if (BTA_DM_PM_INCLUDED == TRUE) static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr); static void bta_dm_pm_set_mode(BD_ADDR peer_addr, tBTA_DM_PM_ACTION pm_mode, tBTA_DM_PM_REQ pm_req); @@ -45,18 +47,15 @@ static void bta_dm_pm_hid_check(BOOLEAN bScoActive); static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE *p_dev, BOOLEAN bDisable); static void bta_dm_pm_stop_timer_by_index(tBTA_PM_TIMER *p_timer, UINT8 timer_idx); -#endif///BTM_SSR_INCLUDED == TRUE #if (BTM_SSR_INCLUDED == TRUE) #if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE) #include "../hh/bta_hh_int.h" /* BTA_DM_PM_SSR1 will be dedicated for HH SSR setting entry, no other profile can use it */ #define BTA_DM_PM_SSR_HH BTA_DM_PM_SSR1 -#endif +#endif /* (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE) */ static void bta_dm_pm_ssr(BD_ADDR peer_addr); - -tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs; - +#endif /* (BTM_SSR_INCLUDED == TRUE) */ /******************************************************************************* ** @@ -118,27 +117,6 @@ void bta_dm_disable_pm(void) } } -/******************************************************************************* -** -** Function bta_dm_get_av_count -** -** Description Get the number of connected AV -** -** -** Returns number of av connections -** -*******************************************************************************/ -UINT8 bta_dm_get_av_count(void) -{ - UINT8 count = 0; - for (int i = 0; i < bta_dm_conn_srvcs.count; i++) { - if (bta_dm_conn_srvcs.conn_srvc[i].id == BTA_ID_AV) { - ++count; - } - } - return count; -} - /******************************************************************************* ** ** Function bta_dm_pm_stop_timer @@ -337,10 +315,10 @@ static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, { UINT8 i, j; - UINT8 *p = NULL; tBTA_DM_PEER_DEVICE *p_dev; #if (BTM_SSR_INCLUDED == TRUE) + UINT8 *p = NULL; int index = BTA_DM_PM_SSR0; #endif @@ -492,7 +470,6 @@ static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, ** Returns void ** *******************************************************************************/ - static void bta_dm_pm_set_mode(BD_ADDR peer_addr, tBTA_DM_PM_ACTION pm_request, tBTA_DM_PM_REQ pm_req ) { @@ -702,8 +679,6 @@ static BOOLEAN bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE *p_peer_dev, UINT8 index) BTM_ReadPowerMode(p_peer_dev->peer_bdaddr, &mode); #if (BTM_SSR_INCLUDED == TRUE) p_rem_feat = BTM_ReadRemoteFeatures (p_peer_dev->peer_bdaddr); -#endif ///BTM_SSR_INCLUDED == TRUE -#if (BTM_SSR_INCLUDED == TRUE) APPL_TRACE_DEBUG("bta_dm_pm_sniff cur:%d, idx:%d, info:x%x", mode, index, p_peer_dev->info); if (mode != BTM_PM_MD_SNIFF || (HCI_SNIFF_SUB_RATE_SUPPORTED(BTM_ReadLocalFeatures ()) && p_rem_feat && @@ -805,6 +780,7 @@ static void bta_dm_pm_ssr(BD_ADDR peer_addr) } } #endif + /******************************************************************************* ** ** Function bta_dm_pm_active @@ -824,11 +800,8 @@ void bta_dm_pm_active(BD_ADDR peer_addr) /* switch to active mode */ pm.mode = BTM_PM_MD_ACTIVE; BTM_SetPowerMode (bta_dm_cb.pm_id, peer_addr, &pm); - - } - /******************************************************************************* ** ** Function bta_dm_pm_btm_cback @@ -901,6 +874,7 @@ static void bta_dm_pm_timer_cback(void *p_tle) } } + /******************************************************************************* ** ** Function bta_dm_pm_btm_status @@ -995,11 +969,9 @@ void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data) default: break; } - - - } + /******************************************************************************* ** ** Function bta_dm_pm_timer @@ -1015,33 +987,7 @@ void bta_dm_pm_timer(tBTA_DM_MSG *p_data) APPL_TRACE_EVENT("%s", __func__); bta_dm_pm_set_mode(p_data->pm_timer.bd_addr, p_data->pm_timer.pm_request, BTA_DM_PM_EXECUTE); } -#endif ///BTM_SSR_INCLUDED == TRUE - -/******************************************************************************* -** -** Function bta_dm_find_peer_device -** -** Description Given an address, find the associated control block. -** -** Returns tBTA_DM_PEER_DEVICE -** -*******************************************************************************/ -tBTA_DM_PEER_DEVICE *bta_dm_find_peer_device(BD_ADDR peer_addr) -{ - tBTA_DM_PEER_DEVICE *p_dev = NULL; - - for (int i = 0; i < bta_dm_cb.device_list.count; i++) { - if (!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, peer_addr)) { - p_dev = &bta_dm_cb.device_list.peer_device[i]; - break; - } - - } - return p_dev; -} - -#if (BTM_SSR_INCLUDED == TRUE) /******************************************************************************* ** ** Function bta_dm_is_sco_active @@ -1138,7 +1084,52 @@ static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE *p_dev, BOOLEAN bDisa BTM_SetLinkPolicy(p_dev->peer_bdaddr, &policy_setting); } -#endif ///BTM_SSR_INCLUDED == TRUE +#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */ + +/******************************************************************************* +** +** Function bta_dm_get_av_count +** +** Description Get the number of connected AV +** +** +** Returns number of av connections +** +*******************************************************************************/ +UINT8 bta_dm_get_av_count(void) +{ + UINT8 count = 0; + for (int i = 0; i < bta_dm_conn_srvcs.count; i++) { + if (bta_dm_conn_srvcs.conn_srvc[i].id == BTA_ID_AV) { + ++count; + } + } + return count; +} + +/******************************************************************************* +** +** Function bta_dm_find_peer_device +** +** Description Given an address, find the associated control block. +** +** Returns tBTA_DM_PEER_DEVICE +** +*******************************************************************************/ +tBTA_DM_PEER_DEVICE *bta_dm_find_peer_device(BD_ADDR peer_addr) +{ + tBTA_DM_PEER_DEVICE *p_dev = NULL; + + for (int i = 0; i < bta_dm_cb.device_list.count; i++) { + if (!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, peer_addr)) { + p_dev = &bta_dm_cb.device_list.peer_device[i]; + break; + } + + } + return p_dev; +} + #if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE) && SDP_INCLUDED == TRUE) /******************************************************************************* @@ -1161,5 +1152,6 @@ tBTA_DM_CONTRL_STATE bta_dm_pm_obtain_controller_state(void) APPL_TRACE_DEBUG("bta_dm_pm_obtain_controller_state: %d", cur_state); return cur_state; } + #endif diff --git a/components/bt/bluedroid/bta/dm/bta_dm_sco.c b/components/bt/bluedroid/bta/dm/bta_dm_sco.c index 45d098f442..9acfa9544a 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_sco.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_sco.c @@ -650,6 +650,6 @@ INT32 BTA_DmPcmResample (void *p_src, UINT32 in_bytes, void *p_dst) APPL_TRACE_DEBUG("bta_pcm_resample : outsamples %d", out_sample); #endif - return (out_sample * bta_dm_pcm_cb.sample_size); + return (out_sample); } #endif diff --git a/components/bt/bluedroid/bta/dm/include/bta_dm_int.h b/components/bt/bluedroid/bta/dm/include/bta_dm_int.h index 6461bd4986..d07e951f12 100644 --- a/components/bt/bluedroid/bta/dm/include/bta_dm_int.h +++ b/components/bt/bluedroid/bta/dm/include/bta_dm_int.h @@ -63,11 +63,11 @@ enum { BTA_DM_API_BOND_CANCEL_EVT, BTA_DM_API_PIN_REPLY_EVT, #endif ///SMP_INCLUDED == TRUE -#if (BTM_SSR_INCLUDED == TRUE) +#if (BTA_DM_PM_INCLUDED == TRUE) /* power manger events */ BTA_DM_PM_BTM_STATUS_EVT, BTA_DM_PM_TIMER_EVT, -#endif ///BTM_SSR_INCLUDED == TRUE +#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */ #if (SMP_INCLUDED == TRUE) /* simple pairing events */ BTA_DM_API_CONFIRM_EVT, @@ -350,6 +350,7 @@ typedef struct { #endif } tBTA_DM_ACL_CHANGE; +#if (BTA_DM_PM_INCLUDED == TRUE) /* data type for BTA_DM_PM_BTM_STATUS_EVT */ typedef struct { @@ -367,7 +368,7 @@ typedef struct { BD_ADDR bd_addr; tBTA_DM_PM_ACTION pm_request; } tBTA_DM_PM_TIMER; - +#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */ /* data type for BTA_DM_API_ADD_DEVICE_EVT */ typedef struct { @@ -757,9 +758,11 @@ typedef union { tBTA_DM_ACL_CHANGE acl_change; +#if (BTA_DM_PM_INCLUDED == TRUE) tBTA_DM_PM_BTM_STATUS pm_status; tBTA_DM_PM_TIMER pm_timer; +#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */ tBTA_DM_API_DI_DISC di_disc; @@ -889,6 +892,10 @@ typedef struct { } tBTA_DM_CONNECTED_SRVCS; +extern tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs; + +#if (BTA_DM_PM_INCLUDED == TRUE) + typedef struct { #define BTA_DM_PM_SNIFF_TIMER_IDX 0 #define BTA_DM_PM_PARK_TIMER_IDX 1 @@ -908,9 +915,8 @@ typedef struct { BOOLEAN in_use; } tBTA_PM_TIMER; -extern tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs; - #define BTA_DM_NUM_PM_TIMER 7 +#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */ /* DM control block */ typedef struct { @@ -931,10 +937,10 @@ typedef struct { UINT32 wbt_sdp_handle; /* WIDCOMM Extensions SDP record handle */ UINT8 wbt_scn; /* WIDCOMM Extensions SCN */ UINT8 num_master_only; -#if BTM_SSR_INCLUDED == TRUE +#if (BTA_DM_PM_INCLUDED == TRUE) UINT8 pm_id; tBTA_PM_TIMER pm_timer[BTA_DM_NUM_PM_TIMER]; -#endif ///BTM_SSR_INCLUDED == TRUE +#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */ UINT32 role_policy_mask; /* the bits set indicates the modules that wants to remove role switch from the default link policy */ UINT16 cur_policy; /* current default link policy */ UINT16 rs_event; /* the event waiting for role switch */ @@ -1101,12 +1107,14 @@ typedef struct { UINT8 lmp_version; } tBTA_DM_LMP_VER_INFO; +#if (BTA_DM_PM_INCLUDED == TRUE) extern tBTA_DM_PM_CFG *p_bta_dm_pm_cfg; extern tBTA_DM_PM_SPEC *p_bta_dm_pm_spec; extern tBTM_PM_PWR_MD *p_bta_dm_pm_md; #if (BTM_SSR_INCLUDED == TRUE) extern tBTA_DM_SSR_SPEC *p_bta_dm_ssr_spec; #endif +#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */ /* update dynamic BRCM Aware EIR data */ extern const tBTA_DM_EIR_CONF bta_dm_eir_cfg; @@ -1161,9 +1169,6 @@ extern void bta_dm_add_device (tBTA_DM_MSG *p_data); extern void bta_dm_remove_device (tBTA_DM_MSG *p_data); extern void bta_dm_close_acl(tBTA_DM_MSG *p_data); - -extern void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data); -extern void bta_dm_pm_timer(tBTA_DM_MSG *p_data); extern void bta_dm_add_ampkey (tBTA_DM_MSG *p_data); #if BLE_INCLUDED == TRUE @@ -1223,8 +1228,13 @@ extern void bta_dm_ci_io_req_act(tBTA_DM_MSG *p_data); extern void bta_dm_ci_rmt_oob_act(tBTA_DM_MSG *p_data); #endif /* BTM_OOB_INCLUDED */ +#if (BTA_DM_PM_INCLUDED == TRUE) extern void bta_dm_init_pm(void); extern void bta_dm_disable_pm(void); +extern void bta_dm_pm_active(BD_ADDR peer_addr); +extern void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data); +extern void bta_dm_pm_timer(tBTA_DM_MSG *p_data); +#endif /* #if (BTA_DM_PM_INCLUDED == TRUE) */ extern UINT8 bta_dm_get_av_count(void); extern void bta_dm_search_start (tBTA_DM_MSG *p_data); @@ -1251,9 +1261,6 @@ extern void bta_dm_search_cancel_notify (tBTA_DM_MSG *p_data); extern void bta_dm_search_cancel_transac_cmpl(tBTA_DM_MSG *p_data); extern void bta_dm_disc_rmt_name (tBTA_DM_MSG *p_data); extern tBTA_DM_PEER_DEVICE *bta_dm_find_peer_device(BD_ADDR peer_addr); - -extern void bta_dm_pm_active(BD_ADDR peer_addr); - void bta_dm_eir_update_uuid(UINT16 uuid16, BOOLEAN adding); extern void bta_dm_enable_test_mode(tBTA_DM_MSG *p_data); diff --git a/components/bt/bluedroid/bta/hf_client/bta_hf_client_act.c b/components/bt/bluedroid/bta/hf_client/bta_hf_client_act.c new file mode 100644 index 0000000000..c42b5bd14f --- /dev/null +++ b/components/bt/bluedroid/bta/hf_client/bta_hf_client_act.c @@ -0,0 +1,772 @@ +/****************************************************************************** + * + * Copyright (c) 2014 The Android Open Source Project + * Copyright (C) 2003-2012 Broadcom Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +/****************************************************************************** + * + * This file contains action functions for the handsfree client. + * + ******************************************************************************/ + +#include "bta/bta_api.h" +#include "bta/bta_hf_client_api.h" +#include "bta_hf_client_int.h" +#include "bta_dm_int.h" +#include "stack/l2c_api.h" +#include "stack/port_api.h" +#include "bta/bta_sys.h" +#include "bta/utl.h" +#include "common/bt_defs.h" +#include +#include "osi/allocator.h" + +#if (BTA_HF_INCLUDED == TRUE) +/***************************************************************************** +** Constants +*****************************************************************************/ + +/* maximum length of data to read from RFCOMM */ +#define BTA_HF_CLIENT_RFC_READ_MAX 512 + +/******************************************************************************* +** +** Function bta_hf_client_register +** +** Description This function initializes values of the scb and sets up +** the SDP record for the services. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_register(tBTA_HF_CLIENT_DATA *p_data) +{ + tBTA_HF_CLIENT_REGISTER evt; + tBTA_UTL_COD cod; + + memset(&evt, 0, sizeof(evt)); + + /* initialize control block */ + bta_hf_client_scb_init(); + + bta_hf_client_cb.scb.serv_sec_mask = p_data->api_register.sec_mask; + bta_hf_client_cb.scb.features = p_data->api_register.features; + + /* initialize AT control block */ + bta_hf_client_at_init(); + + /* create SDP records */ + bta_hf_client_create_record(p_data); + + /* Set the Audio service class bit */ + cod.service = BTM_COD_SERVICE_AUDIO; + utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS); + + /* start RFCOMM server */ + bta_hf_client_start_server(); + + /* call app callback with register event */ + evt.status = BTA_HF_CLIENT_SUCCESS; + (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_REGISTER_EVT, &evt); +} + +/******************************************************************************* +** +** Function bta_hf_client_deregister +** +** Description This function removes the sdp records, closes the RFCOMM +** servers, and deallocates the service control block. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_deregister(tBTA_HF_CLIENT_DATA *p_data) +{ + bta_hf_client_cb.scb.deregister = TRUE; + + /* remove sdp record */ + bta_hf_client_del_record(p_data); + + /* remove rfcomm server */ + bta_hf_client_close_server(); + + /* disable */ + bta_hf_client_scb_disable(); +} + +/******************************************************************************* +** +** Function bta_hf_client_start_dereg +** +** Description Start a deregister event. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_start_dereg(tBTA_HF_CLIENT_DATA *p_data) +{ + bta_hf_client_cb.scb.deregister = TRUE; + + /* remove sdp record */ + bta_hf_client_del_record(p_data); +} + +/******************************************************************************* +** +** Function bta_hf_client_start_close +** +** Description Start the process of closing SCO and RFCOMM connection. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_start_close(tBTA_HF_CLIENT_DATA *p_data) +{ + /* Take the link out of sniff and set L2C idle time to 0 */ +#if (BTA_DM_PM_INCLUDED == TRUE) + bta_dm_pm_active(bta_hf_client_cb.scb.peer_addr); +#endif /* (BTA_DM_PM_INCLUDED == TRUE) */ + L2CA_SetIdleTimeoutByBdAddr(bta_hf_client_cb.scb.peer_addr, 0, BT_TRANSPORT_BR_EDR); + + /* if SCO is open close SCO and wait on RFCOMM close */ + if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_OPEN_ST) { + bta_hf_client_cb.scb.sco_close_rfc = TRUE; + } else { + bta_hf_client_rfc_do_close(p_data); + } + + /* always do SCO shutdown to handle all SCO corner cases */ + bta_hf_client_sco_shutdown(NULL); +} + +/******************************************************************************* +** +** Function bta_hf_client_start_open +** +** Description This starts an HF Client open. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_start_open(tBTA_HF_CLIENT_DATA *p_data) +{ + BD_ADDR pending_bd_addr; + + /* store parameters */ + if (p_data) { + bdcpy(bta_hf_client_cb.scb.peer_addr, p_data->api_open.bd_addr); + bta_hf_client_cb.scb.cli_sec_mask = p_data->api_open.sec_mask; + } + + /* Check if RFCOMM has any incoming connection to avoid collision. */ + if (PORT_IsOpening (pending_bd_addr)) { + /* Let the incoming connection goes through. */ + /* Issue collision for now. */ + /* We will decide what to do when we find incoming connection later.*/ + bta_hf_client_collision_cback (0, BTA_ID_HS, 0, bta_hf_client_cb.scb.peer_addr); + return; + } + + /* close server */ + bta_hf_client_close_server(); + + /* set role */ + bta_hf_client_cb.scb.role = BTA_HF_CLIENT_INT; + + /* do service search */ + bta_hf_client_do_disc(); +} + +/******************************************************************************* +** +** Function bta_hf_client_cback_open +** +** Description Send open callback event to application. +** +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_cback_open(tBTA_HF_CLIENT_DATA *p_data, tBTA_HF_CLIENT_STATUS status) +{ + tBTA_HF_CLIENT_OPEN evt; + + memset(&evt, 0, sizeof(evt)); + + /* call app callback with open event */ + evt.status = status; + if (p_data) { + /* if p_data is provided then we need to pick the bd address from the open api structure */ + bdcpy(evt.bd_addr, p_data->api_open.bd_addr); + } else { + bdcpy(evt.bd_addr, bta_hf_client_cb.scb.peer_addr); + } + + (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_OPEN_EVT, &evt); +} + +/******************************************************************************* +** +** Function bta_hf_client_rfc_open +** +** Description Handle RFCOMM channel open. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_rfc_open(tBTA_HF_CLIENT_DATA *p_data) +{ + UNUSED(p_data); + + bta_sys_conn_open(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); + + bta_hf_client_cback_open(NULL, BTA_HF_CLIENT_SUCCESS); + + /* start SLC procedure */ + bta_hf_client_slc_seq(FALSE); +} + +/******************************************************************************* +** +** Function bta_hf_client_rfc_acp_open +** +** Description Handle RFCOMM channel open when accepting connection. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_rfc_acp_open(tBTA_HF_CLIENT_DATA *p_data) +{ + UINT16 lcid; + BD_ADDR dev_addr; + int status; + + /* set role */ + bta_hf_client_cb.scb.role = BTA_HF_CLIENT_ACP; + + APPL_TRACE_DEBUG ("bta_hf_client_rfc_acp_open: serv_handle = %d rfc.port_handle = %d", + bta_hf_client_cb.scb.serv_handle, p_data->rfc.port_handle); + + /* get bd addr of peer */ + if (PORT_SUCCESS != (status = PORT_CheckConnection(p_data->rfc.port_handle, dev_addr, &lcid))) { + APPL_TRACE_DEBUG ("bta_hf_client_rfc_acp_open error PORT_CheckConnection returned status %d", status); + } + + /* Collision Handling */ + if (bta_hf_client_cb.scb.colli_tmr_on) { + /* stop collision timer */ + bta_hf_client_cb.scb.colli_tmr_on = FALSE; + bta_sys_free_timer (&bta_hf_client_cb.scb.colli_timer); + + if (bdcmp (dev_addr, bta_hf_client_cb.scb.peer_addr) == 0) { + /* If incoming and outgoing device are same, nothing more to do. */ + /* Outgoing conn will be aborted because we have successful incoming conn. */ + } else { + /* Resume outgoing connection. */ + bta_hf_client_resume_open (); + } + } + + bdcpy (bta_hf_client_cb.scb.peer_addr, dev_addr); + bta_hf_client_cb.scb.conn_handle = p_data->rfc.port_handle; + + /* do service discovery to get features */ + bta_hf_client_do_disc(); + + /* continue with open processing */ + bta_hf_client_rfc_open(p_data); +} + +/******************************************************************************* +** +** Function bta_hf_client_rfc_fail +** +** Description RFCOMM connection failed. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_rfc_fail(tBTA_HF_CLIENT_DATA *p_data) +{ + UNUSED(p_data); + + /* reinitialize stuff */ + bta_hf_client_cb.scb.conn_handle = 0; + bta_hf_client_cb.scb.peer_features = 0; + bta_hf_client_cb.scb.chld_features = 0; + bta_hf_client_cb.scb.role = BTA_HF_CLIENT_ACP; + bta_hf_client_cb.scb.svc_conn = FALSE; + bta_hf_client_cb.scb.send_at_reply = FALSE; + bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD; + + bta_hf_client_at_reset(); + + /* reopen server */ + bta_hf_client_start_server(); + + /* call open cback w. failure */ + bta_hf_client_cback_open(NULL, BTA_HF_CLIENT_FAIL_RFCOMM); +} + +/******************************************************************************* +** +** Function bta_hf_client_disc_fail +** +** Description This function handles a discovery failure. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_disc_fail(tBTA_HF_CLIENT_DATA *p_data) +{ + UNUSED(p_data); + + /* reopen server */ + bta_hf_client_start_server(); + + /* reinitialize stuff */ + + /* call open cback w. failure */ + bta_hf_client_cback_open(NULL, BTA_HF_CLIENT_FAIL_SDP); +} + +/******************************************************************************* +** +** Function bta_hf_client_open_fail +** +** Description open connection failed. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_open_fail(tBTA_HF_CLIENT_DATA *p_data) +{ + /* call open cback w. failure */ + bta_hf_client_cback_open(p_data, BTA_HF_CLIENT_FAIL_RESOURCES); +} + +/******************************************************************************* +** +** Function bta_hf_client_rfc_close +** +** Description RFCOMM connection closed. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_rfc_close(tBTA_HF_CLIENT_DATA *p_data) +{ + UNUSED(p_data); + + /* reinitialize stuff */ + bta_hf_client_cb.scb.peer_features = 0; + bta_hf_client_cb.scb.chld_features = 0; + bta_hf_client_cb.scb.role = BTA_HF_CLIENT_ACP; + bta_hf_client_cb.scb.svc_conn = FALSE; + bta_hf_client_cb.scb.send_at_reply = FALSE; + bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD; + + bta_hf_client_at_reset(); + + bta_sys_conn_close(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); + + /* call close cback */ + (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CLOSE_EVT, NULL); + + /* if not deregistering reopen server */ + if (bta_hf_client_cb.scb.deregister == FALSE) { + /* Clear peer bd_addr so instance can be reused */ + bdcpy(bta_hf_client_cb.scb.peer_addr, bd_addr_null); + + /* start server as it might got closed on open*/ + bta_hf_client_start_server(); + + bta_hf_client_cb.scb.conn_handle = 0; + + /* Make sure SCO is shutdown */ + bta_hf_client_sco_shutdown(NULL); + + bta_sys_sco_unuse(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); + } + /* else close port and deallocate scb */ + else { + bta_hf_client_close_server(); + bta_hf_client_scb_disable(); + } +} + +/******************************************************************************* +** +** Function bta_hf_client_disc_int_res +** +** Description This function handles a discovery result when initiator. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_disc_int_res(tBTA_HF_CLIENT_DATA *p_data) +{ + UINT16 event = BTA_HF_CLIENT_DISC_FAIL_EVT; + + APPL_TRACE_DEBUG ("bta_hf_client_disc_int_res: Status: %d", p_data->disc_result.status); + + /* if found service */ + if (p_data->disc_result.status == SDP_SUCCESS || + p_data->disc_result.status == SDP_DB_FULL) { + /* get attributes */ + if (bta_hf_client_sdp_find_attr()) { + event = BTA_HF_CLIENT_DISC_OK_EVT; + } + } + + /* free discovery db */ + bta_hf_client_free_db(p_data); + + /* send ourselves sdp ok/fail event */ + bta_hf_client_sm_execute(event, p_data); +} + +/******************************************************************************* +** +** Function bta_hf_client_disc_acp_res +** +** Description This function handles a discovery result when acceptor. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_disc_acp_res(tBTA_HF_CLIENT_DATA *p_data) +{ + /* if found service */ + if (p_data->disc_result.status == SDP_SUCCESS || + p_data->disc_result.status == SDP_DB_FULL) { + /* get attributes */ + bta_hf_client_sdp_find_attr(); + } + + /* free discovery db */ + bta_hf_client_free_db(p_data); +} + +/******************************************************************************* +** +** Function bta_hf_client_rfc_data +** +** Description Read and process data from RFCOMM. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_rfc_data(tBTA_HF_CLIENT_DATA *p_data) +{ + UINT16 len; + char *buf = osi_calloc(BTA_HF_CLIENT_RFC_READ_MAX); + if (buf == NULL) { + APPL_TRACE_ERROR("No mem %s", __FUNCTION__); + return; + } + + UNUSED(p_data); + + /* read data from rfcomm; if bad status, we're done */ + while (PORT_ReadData(bta_hf_client_cb.scb.conn_handle, buf, BTA_HF_CLIENT_RFC_READ_MAX, &len) == PORT_SUCCESS) { + /* if no data, we're done */ + if (len == 0) { + break; + } + + bta_hf_client_at_parse(buf, len); + + /* no more data to read, we're done */ + if (len < BTA_HF_CLIENT_RFC_READ_MAX) { + break; + } + } + osi_free(buf); +} + +/******************************************************************************* +** +** Function bta_hf_client_svc_conn_open +** +** Description Service level connection opened +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_svc_conn_open(tBTA_HF_CLIENT_DATA *p_data) +{ + tBTA_HF_CLIENT_CONN evt; + UNUSED(p_data); + + memset(&evt, 0, sizeof(evt)); + + if (!bta_hf_client_cb.scb.svc_conn) { + /* set state variable */ + bta_hf_client_cb.scb.svc_conn = TRUE; + + /* call callback */ + evt.peer_feat = bta_hf_client_cb.scb.peer_features; + evt.chld_feat = bta_hf_client_cb.scb.chld_features; + + (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CONN_EVT, &evt); + } +} + +/******************************************************************************* +** +** Function bta_hf_client_cback_ind +** +** Description Send indicator callback event to application. +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_ind(tBTA_HF_CLIENT_IND_TYPE type, UINT16 value) +{ + tBTA_HF_CLIENT_IND evt; + + memset(&evt, 0, sizeof(evt)); + + evt.type = type; + evt.value = value; + + (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_IND_EVT, &evt); +} + +/******************************************************************************* +** +** Function bta_hf_client_evt_val +** +** Description Send event to application. +** This is a generic helper for events with common data. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_evt_val(tBTA_HF_CLIENT_EVT type, UINT16 value) +{ + tBTA_HF_CLIENT_VAL evt; + + memset(&evt, 0, sizeof(evt)); + + evt.value = value; + + (*bta_hf_client_cb.p_cback)(type, &evt); +} + +/******************************************************************************* +** +** Function bta_hf_client_operator_name +** +** Description Send operator name event to application. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_operator_name(char *name) +{ + tBTA_HF_CLIENT_OPERATOR_NAME *evt; + + if ((evt = osi_calloc(sizeof(tBTA_HF_CLIENT_OPERATOR_NAME))) != NULL) { + strlcpy(evt->name, name, BTA_HF_CLIENT_OPERATOR_NAME_LEN + 1); + evt->name[BTA_HF_CLIENT_OPERATOR_NAME_LEN] = '\0'; + + (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_OPERATOR_NAME_EVT, evt); + osi_free(evt); + } else { + APPL_TRACE_ERROR("No mem: %s", __func__); + } +} + + +/******************************************************************************* +** +** Function bta_hf_client_clip +** +** Description Send CLIP event to application. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_clip(char *number) +{ + tBTA_HF_CLIENT_NUMBER *evt; + + if ((evt = osi_calloc(sizeof(tBTA_HF_CLIENT_NUMBER))) != NULL) { + strlcpy(evt->number, number, BTA_HF_CLIENT_NUMBER_LEN + 1); + evt->number[BTA_HF_CLIENT_NUMBER_LEN] = '\0'; + + (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CLIP_EVT, evt); + osi_free(evt); + } else { + APPL_TRACE_ERROR("No mem: %s", __func__); + } +} + +/******************************************************************************* +** +** Function bta_hf_client_ccwa +** +** Description Send CLIP event to application. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_ccwa(char *number) +{ + tBTA_HF_CLIENT_NUMBER *evt; + + if ((evt = osi_calloc(sizeof(tBTA_HF_CLIENT_NUMBER))) != NULL) { + strlcpy(evt->number, number, BTA_HF_CLIENT_NUMBER_LEN + 1); + evt->number[BTA_HF_CLIENT_NUMBER_LEN] = '\0'; + + + (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CCWA_EVT, evt); + osi_free(evt); + } else { + APPL_TRACE_ERROR("No mem: %s", __func__); + } +} + +/******************************************************************************* +** +** Function bta_hf_client_at_result +** +** Description Send AT result event to application. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_at_result(tBTA_HF_CLIENT_AT_RESULT_TYPE type, UINT16 cme) +{ + tBTA_HF_CLIENT_AT_RESULT evt; + + memset(&evt, 0, sizeof(evt)); + + evt.type = type; + evt.cme = cme; + + (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_AT_RESULT_EVT, &evt); +} + +/******************************************************************************* +** +** Function bta_hf_client_clcc +** +** Description Send clcc event to application. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_clcc(UINT32 idx, BOOLEAN incoming, UINT8 status, BOOLEAN mpty, char *number) +{ + tBTA_HF_CLIENT_CLCC *evt; + + if ((evt = osi_calloc(sizeof(tBTA_HF_CLIENT_CLCC))) != NULL) { + evt->idx = idx; + evt->inc = incoming; + evt->status = status; + evt->mpty = mpty; + + if (number) { + evt->number_present = TRUE; + strlcpy(evt->number, number, BTA_HF_CLIENT_NUMBER_LEN + 1); + evt->number[BTA_HF_CLIENT_NUMBER_LEN] = '\0'; + } + + (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CLCC_EVT, evt); + osi_free(evt); + } else { + APPL_TRACE_ERROR("No mem, %s\n", __func__); + } +} + +/******************************************************************************* +** +** Function bta_hf_client_cnum +** +** Description Send cnum event to application. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_cnum(char *number, UINT16 service) +{ + tBTA_HF_CLIENT_CNUM *evt; + + if ((evt = osi_calloc(sizeof(tBTA_HF_CLIENT_CNUM))) != NULL) { + + evt->service = service; + strlcpy(evt->number, number, BTA_HF_CLIENT_NUMBER_LEN + 1); + evt->number[BTA_HF_CLIENT_NUMBER_LEN] = '\0'; + + (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_CNUM_EVT, evt); + osi_free(evt); + } else { + APPL_TRACE_ERROR("No mem, %s", __func__); + } +} + +/******************************************************************************* +** +** Function bta_hf_client_binp +** +** Description Send BINP event to application. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_binp(char *number) +{ + tBTA_HF_CLIENT_NUMBER *evt; + + if ((evt = osi_calloc(sizeof(tBTA_HF_CLIENT_NUMBER))) != NULL) { + strlcpy(evt->number, number, BTA_HF_CLIENT_NUMBER_LEN + 1); + evt->number[BTA_HF_CLIENT_NUMBER_LEN] = '\0'; + + (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_BINP_EVT, evt); + osi_free(evt); + } else { + APPL_TRACE_ERROR("No mem: %s", __func__); + } +} + +#endif /* #if (BTA_HF_INCLUDED == TRUE) */ diff --git a/components/bt/bluedroid/bta/hf_client/bta_hf_client_api.c b/components/bt/bluedroid/bta/hf_client/bta_hf_client_api.c new file mode 100644 index 0000000000..434b2b520c --- /dev/null +++ b/components/bt/bluedroid/bta/hf_client/bta_hf_client_api.c @@ -0,0 +1,312 @@ +/****************************************************************************** + * + * Copyright (c) 2014 The Android Open Source Project + * Copyright (C) 2003-2012 Broadcom Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +/****************************************************************************** + * + * This is the implementation of the API for the handsfree (HF role) + * subsystem of BTA + * + ******************************************************************************/ + +#include +#include "bta/bta_hf_client_api.h" +#include "bta_hf_client_int.h" +#include "osi/allocator.h" + +#if (BTA_HF_INCLUDED == TRUE) +/***************************************************************************** +** Constants and data types +*****************************************************************************/ +static const tBTA_SYS_REG bta_hf_client_reg = { + bta_hf_client_hdl_event, + BTA_HfClientDisable +}; + +static const uint8_t bta_hf_client_cb_data_size[] = { + 0, // #define BTA_HF_CLIENT_ENABLE_EVT 0 + sizeof(tBTA_HF_CLIENT_REGISTER), // #define BTA_HF_CLIENT_REGISTER_EVT 1 + sizeof(tBTA_HF_CLIENT_OPEN), // #define BTA_HF_CLIENT_OPEN_EVT 2 + 0, // #define BTA_HF_CLIENT_CLOSE_EVT 3 + sizeof(tBTA_HF_CLIENT_CONN), // #define BTA_HF_CLIENT_CONN_EVT 4 + sizeof(tBTA_HF_CLIENT_HDR), // #define BTA_HF_CLIENT_AUDIO_OPEN_EVT 5 + sizeof(tBTA_HF_CLIENT_HDR), //#define BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT 6 + sizeof(tBTA_HF_CLIENT_HDR), // #define BTA_HF_CLIENT_AUDIO_CLOSE_EVT 7 + sizeof(tBTA_HF_CLIENT_VAL), // #define BTA_HF_CLIENT_SPK_EVT 8 + sizeof(tBTA_HF_CLIENT_VAL), // #define BTA_HF_CLIENT_MIC_EVT 9 + sizeof(tBTA_HF_CLIENT_IND), //#define BTA_HF_CLIENT_IND_EVT 10 + sizeof(tBTA_HF_CLIENT_VAL), // #define BTA_HF_CLIENT_VOICE_REC_EVT 11 + sizeof(tBTA_HF_CLIENT_OPERATOR_NAME), // #define BTA_HF_CLIENT_OPERATOR_NAME_EVT 12 + sizeof(tBTA_HF_CLIENT_NUMBER), // #define BTA_HF_CLIENT_CLIP_EVT 13 + sizeof(tBTA_HF_CLIENT_NUMBER), // #define BTA_HF_CLIENT_CCWA_EVT 14 + sizeof(tBTA_HF_CLIENT_AT_RESULT), // #define BTA_HF_CLIENT_AT_RESULT_EVT 15 + sizeof(tBTA_HF_CLIENT_CLCC), // #define BTA_HF_CLIENT_CLCC_EVT 16 + sizeof(tBTA_HF_CLIENT_CNUM), //#define BTA_HF_CLIENT_CNUM_EVT 17 + sizeof(tBTA_HF_CLIENT_VAL), // #define BTA_HF_CLIENT_BTRH_EVT 18 + sizeof(tBTA_HF_CLIENT_VAL), // #define BTA_HF_CLIENT_BSIR_EVT 19 + sizeof(tBTA_HF_CLIENT_NUMBER), // #define BTA_HF_CLIENT_BINP_EVT 20 + sizeof(tBTA_HF_CLIENT_VAL), // #define BTA_HF_CLIENT_RING_INDICATION 21 + 0, // #define BTA_HF_CLIENT_DISABLE_EVT 30 +}; +/***************************************************************************** +** External Function Declarations +*****************************************************************************/ + +/******************************************************************************* +** +** Function BTA_HfClientEnable +** +** Description Enable the HF CLient service. When the enable +** operation is complete the callback function will be +** called with a BTA_HF_CLIENT_ENABLE_EVT. This function must +** be called before other function in the HF CLient API are +** called. +** +** Returns BTA_SUCCESS if OK, BTA_FAILURE otherwise. +** +*******************************************************************************/ +tBTA_STATUS BTA_HfClientEnable(tBTA_HF_CLIENT_CBACK *p_cback) +{ + tBTA_HF_CLIENT_API_ENABLE *p_buf; + + if (bta_sys_is_register (BTA_ID_HS)) { + APPL_TRACE_ERROR("BTA HF Client is already enabled, ignoring ..."); + return BTA_FAILURE; + } + + /* register with BTA system manager */ + bta_sys_register(BTA_ID_HS, &bta_hf_client_reg); + + if ((p_buf = (tBTA_HF_CLIENT_API_ENABLE *) osi_malloc(sizeof(tBTA_HF_CLIENT_API_ENABLE))) != NULL) { + p_buf->hdr.event = BTA_HF_CLIENT_API_ENABLE_EVT; + p_buf->p_cback = p_cback; + bta_sys_sendmsg(p_buf); + } + + return BTA_SUCCESS; +} + +/******************************************************************************* +** +** Function BTA_HfClientDisable +** +** Description Disable the HF Client service +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientDisable(void) +{ + BT_HDR *p_buf; + + if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { + p_buf->event = BTA_HF_CLIENT_API_DISABLE_EVT; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_HfClientRegister +** +** Description Register an HF Client service. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientRegister(tBTA_SEC sec_mask, tBTA_HF_CLIENT_FEAT features, + char *p_service_name) +{ + tBTA_HF_CLIENT_API_REGISTER *p_buf; + + if ((p_buf = (tBTA_HF_CLIENT_API_REGISTER *) osi_malloc(sizeof(tBTA_HF_CLIENT_API_REGISTER))) != NULL) { + p_buf->hdr.event = BTA_HF_CLIENT_API_REGISTER_EVT; + p_buf->features = features; + p_buf->sec_mask = sec_mask; + if (p_service_name) { + BCM_STRNCPY_S(p_buf->name, BTA_SERVICE_NAME_LEN + 1, p_service_name, BTA_SERVICE_NAME_LEN); + p_buf->name[BTA_SERVICE_NAME_LEN] = 0; + } else { + p_buf->name[0] = '\0'; + } + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_HfClientDeregister +** +** Description Deregister an HF Client service. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientDeregister(UINT16 handle) +{ + BT_HDR *p_buf; + + if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { + p_buf->event = BTA_HF_CLIENT_API_DEREGISTER_EVT; + p_buf->layer_specific = handle; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_HfClientOpen +** +** Description Opens a connection to an audio gateway. +** When connection is open callback function is called +** with a BTA_AG_OPEN_EVT. Only the data connection is +** opened. The audio connection is not opened. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientOpen(UINT16 handle, BD_ADDR bd_addr, tBTA_SEC sec_mask) +{ + tBTA_HF_CLIENT_API_OPEN *p_buf; + + if ((p_buf = (tBTA_HF_CLIENT_API_OPEN *) osi_malloc(sizeof(tBTA_HF_CLIENT_API_OPEN))) != NULL) { + p_buf->hdr.event = BTA_HF_CLIENT_API_OPEN_EVT; + p_buf->hdr.layer_specific = handle; + bdcpy(p_buf->bd_addr, bd_addr); + p_buf->sec_mask = sec_mask; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_HfClientClose +** +** Description Close the current connection to an audio gateway. +** Any current audio connection will also be closed +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientClose(UINT16 handle) +{ + BT_HDR *p_buf; + + if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { + p_buf->event = BTA_HF_CLIENT_API_CLOSE_EVT; + p_buf->layer_specific = handle; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_HfCllientAudioOpen +** +** Description Opens an audio connection to the currently connected +** audio gateway +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientAudioOpen(UINT16 handle) +{ + BT_HDR *p_buf; + + if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { + p_buf->event = BTA_HF_CLIENT_API_AUDIO_OPEN_EVT; + p_buf->layer_specific = handle; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_HfClientAudioClose +** +** Description Close the currently active audio connection to an audio +** gateway. The data connection remains open +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientAudioClose(UINT16 handle) +{ + BT_HDR *p_buf; + + if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { + p_buf->event = BTA_HF_CLIENT_API_AUDIO_CLOSE_EVT; + p_buf->layer_specific = handle; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function BTA_HfClientSendAT +** +** Description send AT command +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientSendAT(UINT16 handle, tBTA_HF_CLIENT_AT_CMD_TYPE at, UINT32 val1, UINT32 val2, const char *str) +{ + tBTA_HF_CLIENT_DATA_VAL *p_buf; + + if ((p_buf = (tBTA_HF_CLIENT_DATA_VAL *) osi_malloc(sizeof(tBTA_HF_CLIENT_DATA_VAL))) != NULL) { + p_buf->hdr.event = BTA_HF_CLIENT_SEND_AT_CMD_EVT; + p_buf->uint8_val = at; + p_buf->uint32_val1 = val1; + p_buf->uint32_val2 = val2; + + if (str) { + strlcpy(p_buf->str, str, BTA_HF_CLIENT_NUMBER_LEN + 1); + p_buf->str[BTA_HF_CLIENT_NUMBER_LEN] = '\0'; + } else { + p_buf->str[0] = '\0'; + } + + p_buf->hdr.layer_specific = handle; + bta_sys_sendmsg(p_buf); + } +} +#if (BTM_SCO_HCI_INCLUDED == TRUE ) +void BTA_HfClientCiData(void) +{ + BT_HDR *p_buf; + if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { + p_buf->event = BTA_HF_CLIENT_CI_SCO_DATA_EVT; + bta_sys_sendmsg(p_buf); + } +} +#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) */ + +int BTA_HfClientGetCbDataSize(tBTA_HF_CLIENT_EVT event) +{ + return bta_hf_client_cb_data_size[event]; +} +#endif /* #if (BTA_HF_INCLUDED == TRUE) */ diff --git a/components/bt/bluedroid/bta/hf_client/bta_hf_client_at.c b/components/bt/bluedroid/bta/hf_client/bta_hf_client_at.c new file mode 100644 index 0000000000..51a10d9bf4 --- /dev/null +++ b/components/bt/bluedroid/bta/hf_client/bta_hf_client_at.c @@ -0,0 +1,1795 @@ +/****************************************************************************** + * + * Copyright (c) 2014 The Android Open Source Project + * Copyright (C) 2003-2012 Broadcom Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ +// #include +#include +#include + +#include "bta/bta_hf_client_api.h" +#include "bta_hf_client_int.h" +#include "stack/port_api.h" +#include "osi/allocator.h" + +#if (BTA_HF_INCLUDED == TRUE) +/* Uncomment to enable AT traffic dumping */ +/* #define BTA_HF_CLIENT_AT_DUMP 1 */ + +/* minimum length of AT event */ +#define BTA_HF_CLIENT_AT_EVENT_MIN_LEN 3 + +/* timeout for AT response */ +#define BTA_HF_CLIENT_AT_TIMEOUT 29989 + +/* timeout for AT hold timer */ +#define BTA_HF_CLIENT_AT_HOLD_TIMEOUT 41 + +/****************************************************************************** +** +** DATA TYPES AND CONTAINERS +** +*******************************************************************************/ +/* BRSF: store received values here */ +extern tBTA_HF_CLIENT_CB bta_hf_client_cb; + +/****************************************************************************** +** SUPPORTED EVENT MESSAGES +*******************************************************************************/ + +/* CIND: supported indicator names */ +#define BTA_HF_CLIENT_INDICATOR_BATTERYCHG "battchg" +#define BTA_HF_CLIENT_INDICATOR_SIGNAL "signal" +#define BTA_HF_CLIENT_INDICATOR_SERVICE "service" +#define BTA_HF_CLIENT_INDICATOR_CALL "call" +#define BTA_HF_CLIENT_INDICATOR_ROAM "roam" +#define BTA_HF_CLIENT_INDICATOR_CALLSETUP "callsetup" +#define BTA_HF_CLIENT_INDICATOR_CALLHELD "callheld" + +#define MIN(a, b) \ + ({ __typeof__(a) _a = (a); __typeof__(b) _b = (b); (_a < _b) ? _a : _b; }) + +/* CIND: represents each indicators boundaries */ +typedef struct { + char *name; + UINT8 min; + UINT8 max; + UINT8 namelen; +} tBTA_HF_CLIENT_INDICATOR; + +#define BTA_HF_CLIENT_AT_SUPPORTED_INDICATOR_COUNT 7 + +/* CIND: storage room for indicators value range and their statuses */ +static const tBTA_HF_CLIENT_INDICATOR bta_hf_client_indicators[BTA_HF_CLIENT_AT_SUPPORTED_INDICATOR_COUNT] = { + /* name | min | max | name length - used by parser */ + {BTA_HF_CLIENT_INDICATOR_BATTERYCHG, 0, 5, sizeof(BTA_HF_CLIENT_INDICATOR_BATTERYCHG)}, + {BTA_HF_CLIENT_INDICATOR_SIGNAL, 0, 5, sizeof(BTA_HF_CLIENT_INDICATOR_SIGNAL)}, + {BTA_HF_CLIENT_INDICATOR_SERVICE, 0, 1, sizeof(BTA_HF_CLIENT_INDICATOR_SERVICE)}, + {BTA_HF_CLIENT_INDICATOR_CALL, 0, 1, sizeof(BTA_HF_CLIENT_INDICATOR_CALL)}, + {BTA_HF_CLIENT_INDICATOR_ROAM, 0, 1, sizeof(BTA_HF_CLIENT_INDICATOR_ROAM)}, + {BTA_HF_CLIENT_INDICATOR_CALLSETUP, 0, 3, sizeof(BTA_HF_CLIENT_INDICATOR_CALLSETUP)}, + {BTA_HF_CLIENT_INDICATOR_CALLHELD, 0, 2, sizeof(BTA_HF_CLIENT_INDICATOR_CALLHELD)} +}; + +/* +VGM/+VGS - gain min/max values */ +#define BTA_HF_CLIENT_VGS_MIN 0 +#define BTA_HF_CLIENT_VGS_MAX 15 +#define BTA_HF_CLIENT_VGM_MIN 0 +#define BTA_HF_CLIENT_VGM_MAX 15 + +UINT32 service_index = 0; +BOOLEAN service_availability = TRUE; +/* helper functions for handling AT commands queueing */ + +static void bta_hf_client_handle_ok(); + +static void bta_hf_client_clear_queued_at(void) +{ + tBTA_HF_CLIENT_AT_QCMD *cur = bta_hf_client_cb.scb.at_cb.queued_cmd; + tBTA_HF_CLIENT_AT_QCMD *next; + + while (cur != NULL) { + next = cur->next; + osi_free(cur); + cur = next; + } + + bta_hf_client_cb.scb.at_cb.queued_cmd = NULL; +} + +static void bta_hf_client_queue_at(tBTA_HF_CLIENT_AT_CMD cmd, const char *buf, UINT16 buf_len) +{ + tBTA_HF_CLIENT_AT_QCMD *new_cmd; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if ((new_cmd = (tBTA_HF_CLIENT_AT_QCMD *) osi_malloc(sizeof(tBTA_HF_CLIENT_AT_QCMD))) != NULL) { + new_cmd->cmd = cmd; + new_cmd->buf_len = buf_len; + new_cmd->next = NULL; + memcpy(new_cmd->buf, buf, buf_len); + + if (bta_hf_client_cb.scb.at_cb.queued_cmd != NULL) { + tBTA_HF_CLIENT_AT_QCMD *qcmd = bta_hf_client_cb.scb.at_cb.queued_cmd; + + while (qcmd->next != NULL) { + qcmd = qcmd->next; + } + + qcmd->next = new_cmd; + } else { + bta_hf_client_cb.scb.at_cb.queued_cmd = new_cmd; + } + } +} + +static void bta_hf_client_at_resp_timer_cback (TIMER_LIST_ENT *p_tle) +{ + if (p_tle) { + bta_hf_client_cb.scb.at_cb.resp_timer_on = FALSE; + + APPL_TRACE_ERROR("HFPClient: AT response timeout, disconnecting"); + + bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL); + } +} + +static void bta_hf_client_stop_at_resp_timer(void) +{ + if (bta_hf_client_cb.scb.at_cb.resp_timer_on) { + bta_hf_client_cb.scb.at_cb.resp_timer_on = FALSE; + bta_sys_stop_timer (&bta_hf_client_cb.scb.at_cb.resp_timer); + } +} + +static void bta_hf_client_free_at_resp_timer(void) +{ + bta_hf_client_cb.scb.at_cb.resp_timer_on = FALSE; + bta_sys_free_timer (&bta_hf_client_cb.scb.at_cb.resp_timer); +} + +static void bta_hf_client_start_at_resp_timer(void) +{ + if (bta_hf_client_cb.scb.at_cb.resp_timer_on) { + bta_sys_stop_timer (&bta_hf_client_cb.scb.at_cb.resp_timer); + } + + bta_hf_client_cb.scb.at_cb.resp_timer.p_cback = (TIMER_CBACK *)&bta_hf_client_at_resp_timer_cback; + bta_sys_start_timer(&bta_hf_client_cb.scb.at_cb.resp_timer, 0, BTA_HF_CLIENT_AT_TIMEOUT); + bta_hf_client_cb.scb.at_cb.resp_timer_on = TRUE; +} + +static void bta_hf_client_send_at(tBTA_HF_CLIENT_AT_CMD cmd, char *buf, UINT16 buf_len) +{ + if ((bta_hf_client_cb.scb.at_cb.current_cmd == BTA_HF_CLIENT_AT_NONE || + bta_hf_client_cb.scb.svc_conn == FALSE) && + bta_hf_client_cb.scb.at_cb.hold_timer_on == FALSE) { + UINT16 len; + +#ifdef BTA_HF_CLIENT_AT_DUMP + APPL_TRACE_DEBUG("%s %.*s", __FUNCTION__, buf_len - 1, buf); +#endif + + bta_hf_client_cb.scb.at_cb.current_cmd = cmd; + /* Generate fake responses for these because they won't reliably work */ + if (!service_availability && + (cmd == BTA_HF_CLIENT_AT_CNUM || cmd == BTA_HF_CLIENT_AT_COPS)) { + APPL_TRACE_WARNING("%s: No service, skipping %d command", __FUNCTION__, cmd); + bta_hf_client_handle_ok(); + return; + } + + PORT_WriteData(bta_hf_client_cb.scb.conn_handle, buf, buf_len, &len); + + bta_hf_client_start_at_resp_timer(); + + return; + } + + bta_hf_client_queue_at(cmd, buf, buf_len); +} + +static void bta_hf_client_send_queued_at(void) +{ + tBTA_HF_CLIENT_AT_QCMD *cur = bta_hf_client_cb.scb.at_cb.queued_cmd; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if (cur != NULL) { + bta_hf_client_cb.scb.at_cb.queued_cmd = cur->next; + + bta_hf_client_send_at(cur->cmd, cur->buf, cur->buf_len); + + osi_free(cur); + } +} + +static void bta_hf_client_at_hold_timer_cback(TIMER_LIST_ENT *p_tle) +{ + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if (p_tle) { + bta_hf_client_cb.scb.at_cb.hold_timer_on = FALSE; + bta_hf_client_send_queued_at(); + } +} + +static void bta_hf_client_stop_at_hold_timer(void) +{ + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if (bta_hf_client_cb.scb.at_cb.hold_timer_on) { + bta_hf_client_cb.scb.at_cb.hold_timer_on = FALSE; + bta_sys_stop_timer (&bta_hf_client_cb.scb.at_cb.hold_timer); + } +} + +static void bta_hf_client_free_at_hold_timer(void) +{ + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + bta_hf_client_cb.scb.at_cb.hold_timer_on = FALSE; + bta_sys_free_timer(&bta_hf_client_cb.scb.at_cb.hold_timer); +} + +static void bta_hf_client_start_at_hold_timer(void) +{ + TIMER_LIST_ENT *timer = &bta_hf_client_cb.scb.at_cb.hold_timer; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if (bta_hf_client_cb.scb.at_cb.hold_timer_on) { + bta_sys_stop_timer (timer); + } + + timer->p_cback = (TIMER_CBACK *)&bta_hf_client_at_hold_timer_cback; + bta_sys_start_timer(timer, 0, BTA_HF_CLIENT_AT_HOLD_TIMEOUT); + bta_hf_client_cb.scb.at_cb.hold_timer_on = TRUE; +} + +/****************************************************************************** +** +** COMMON AT EVENT HANDLING FUNCTIONS +** +** Receives data (strings, ints, etc.) from the parser and processes this data. +** No buffer parsing is being done here. +*******************************************************************************/ + +static void bta_hf_client_handle_ok() +{ + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + bta_hf_client_stop_at_resp_timer(); + + if (!bta_hf_client_cb.scb.svc_conn) { + bta_hf_client_slc_seq(FALSE); + return; + } + + switch (bta_hf_client_cb.scb.at_cb.current_cmd) { + case BTA_HF_CLIENT_AT_BIA: + case BTA_HF_CLIENT_AT_BCC: + break; + case BTA_HF_CLIENT_AT_BCS: + bta_hf_client_start_at_hold_timer(); + bta_hf_client_cb.scb.at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE; + return; + case BTA_HF_CLIENT_AT_CLIP: //last cmd is post slc seq + if (bta_hf_client_cb.scb.send_at_reply == FALSE) { + bta_hf_client_cb.scb.send_at_reply = TRUE; + } + break; + case BTA_HF_CLIENT_AT_NONE: + bta_hf_client_stop_at_hold_timer(); + break; + default: + if (bta_hf_client_cb.scb.send_at_reply) { + bta_hf_client_at_result(BTA_HF_CLIENT_AT_RESULT_OK, 0); + } + break; + } + + bta_hf_client_cb.scb.at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE; + + bta_hf_client_send_queued_at(); +} + +static void bta_hf_client_handle_error(tBTA_HF_CLIENT_AT_RESULT_TYPE type, UINT16 cme) +{ + APPL_TRACE_DEBUG("%s %u %u", __FUNCTION__, type, cme); + + bta_hf_client_stop_at_resp_timer(); + + if (!bta_hf_client_cb.scb.svc_conn) { + bta_hf_client_slc_seq(TRUE); + return; + } + + switch (bta_hf_client_cb.scb.at_cb.current_cmd) { + case BTA_HF_CLIENT_AT_BIA: + break; + case BTA_HF_CLIENT_AT_BCC: + case BTA_HF_CLIENT_AT_BCS: + bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT); + break; + case BTA_HF_CLIENT_AT_CLIP: //last cmd is post slc seq + if (bta_hf_client_cb.scb.send_at_reply == FALSE) { + bta_hf_client_cb.scb.send_at_reply = TRUE; + } + break; + default: + if (bta_hf_client_cb.scb.send_at_reply) { + bta_hf_client_at_result(type, cme); + } + break; + } + + bta_hf_client_cb.scb.at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE; + + bta_hf_client_send_queued_at(); +} + +static void bta_hf_client_handle_ring() +{ + APPL_TRACE_DEBUG("%s", __FUNCTION__); + bta_hf_client_evt_val(BTA_HF_CLIENT_RING_INDICATION, 0); +} + +static void bta_hf_client_handle_brsf(UINT32 value) +{ + APPL_TRACE_DEBUG("%s 0x%x", __FUNCTION__, value); + bta_hf_client_cb.scb.peer_features = value; +} + +/* handles a single indicator descriptor - registers it for value changing events */ +static void bta_hf_client_handle_cind_list_item(char *name, UINT32 min, UINT32 max, UINT32 index) +{ + + UINT8 i = 0; + + APPL_TRACE_DEBUG("%s %u.%s <%u:%u>", __FUNCTION__, index, name, min, max); + + /* look for a matching indicator on list of supported ones */ + for (i = 0; i < BTA_HF_CLIENT_AT_SUPPORTED_INDICATOR_COUNT; i++) { + if (strcmp(name, BTA_HF_CLIENT_INDICATOR_SERVICE) == 0) { + service_index = index; + } + /* look for a match - search one sign further than indicators name to check for string end */ + /* It will distinguish 'callheld' which could be matched by strncmp as 'call'. */ + if (strncmp(name, bta_hf_client_indicators[i].name, bta_hf_client_indicators[i].namelen) != 0) { + continue; + } + + /* index - enumerates value position in the incoming sequence */ + /* if name matches one of the known indicators, add its incoming position */ + /* to lookup table for easy value->indicator matching later, when only values come */ + bta_hf_client_cb.scb.at_cb.indicator_lookup[index] = i; + + return; + } +} + +static void bta_hf_client_handle_cind_value(UINT32 index, UINT32 value) +{ + APPL_TRACE_DEBUG("%s index: %u value: %u", __FUNCTION__, index, value); + + if (index >= BTA_HF_CLIENT_AT_INDICATOR_COUNT) { + return; + } + + if (service_index == index) { + if (value == 0) { + service_availability = FALSE; + } else { + service_availability = TRUE; + } + } + if (bta_hf_client_cb.scb.at_cb.indicator_lookup[index] == -1) { + return; + } + + /* get the real array index from lookup table */ + index = bta_hf_client_cb.scb.at_cb.indicator_lookup[index]; + + /* Ignore out of range values */ + if (value > bta_hf_client_indicators[index].max || + value < bta_hf_client_indicators[index].min) { + return; + } + + /* tBTA_HF_CLIENT_IND_TYPE match index in bta_hf_client_indicators */ + bta_hf_client_ind(index, value); +} + +static void bta_hf_client_handle_chld(UINT32 mask) +{ + APPL_TRACE_DEBUG("%s 0x%x", __FUNCTION__, mask); + + bta_hf_client_cb.scb.chld_features |= mask; +} + +static void bta_hf_client_handle_ciev(UINT32 index, UINT32 value) +{ + INT8 realind = -1; + + APPL_TRACE_DEBUG("%s index: %u value: %u", __FUNCTION__, index, value); + + if (index == 0 || index > BTA_HF_CLIENT_AT_INDICATOR_COUNT) { + return; + } + + if (service_index == index - 1) { + service_availability = value == 0 ? FALSE : TRUE; + } + + realind = bta_hf_client_cb.scb.at_cb.indicator_lookup[index - 1]; + + if (realind >= 0 && realind < BTA_HF_CLIENT_AT_SUPPORTED_INDICATOR_COUNT) { + /* get the real in-array index from lookup table by index it comes at */ + /* if there is no bug it should automatically be correctly calculated */ + if (value > bta_hf_client_indicators[realind].max || value < bta_hf_client_indicators[realind].min) { + return; + } + + /* update service availability on +ciev from AG. */ + if (service_index == (index - 1)) { + if (value == 1) { + service_availability = TRUE; + } else { + service_availability = FALSE; + } + } + + /* tBTA_HF_CLIENT_IND_TYPE match index in bta_hf_client_indicators */ + bta_hf_client_ind(realind, value); + } +} + +static void bta_hf_client_handle_bcs(UINT32 codec) +{ + APPL_TRACE_DEBUG("%s %u", __FUNCTION__, codec); + + if (codec == BTM_SCO_CODEC_CVSD || + (codec == BTM_SCO_CODEC_MSBC && bta_hf_client_cb.msbc_enabled == TRUE)) { + bta_hf_client_cb.scb.negotiated_codec = codec; + bta_hf_client_send_at_bcs(codec); + } else { + bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD; + bta_hf_client_send_at_bac(); + } +} + +static void bta_hf_client_handle_bsir(UINT32 provided) +{ + APPL_TRACE_DEBUG("%s %u", __FUNCTION__, provided); + + bta_hf_client_evt_val(BTA_HF_CLIENT_BSIR_EVT, provided); +} + +static void bta_hf_client_handle_cmeerror(UINT32 code) +{ + bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_CME, code); +} + +static void bta_hf_client_handle_vgm(UINT32 value) +{ + APPL_TRACE_DEBUG("%s %u", __FUNCTION__, value); + + if (value <= BTA_HF_CLIENT_VGM_MAX) { + bta_hf_client_evt_val(BTA_HF_CLIENT_MIC_EVT, value); + } +} + +static void bta_hf_client_handle_vgs(UINT32 value) +{ + APPL_TRACE_DEBUG("%s %u", __FUNCTION__, value); + + if (value <= BTA_HF_CLIENT_VGS_MAX) { + bta_hf_client_evt_val(BTA_HF_CLIENT_SPK_EVT, value); + } +} + +static void bta_hf_client_handle_bvra(UINT32 value) +{ + APPL_TRACE_DEBUG("%s %u", __FUNCTION__, value); + + if (value > 1) { + return; + } + + bta_hf_client_evt_val(BTA_HF_CLIENT_VOICE_REC_EVT, value); +} + +static void bta_hf_client_handle_clip(char *numstr, UINT32 type) +{ + APPL_TRACE_DEBUG("%s %u %s", __FUNCTION__, type, numstr); + + bta_hf_client_clip(numstr); +} + +static void bta_hf_client_handle_ccwa(char *numstr, UINT32 type) +{ + APPL_TRACE_DEBUG("%s %u %s", __FUNCTION__, type, numstr); + + bta_hf_client_ccwa(numstr); +} + +static void bta_hf_client_handle_cops(char *opstr, UINT32 mode) +{ + APPL_TRACE_DEBUG("%s %u %s", __FUNCTION__, mode, opstr); + + bta_hf_client_operator_name(opstr); +} + +static void bta_hf_client_handle_binp(char *numstr) +{ + APPL_TRACE_DEBUG("%s %s", __FUNCTION__, numstr); + + bta_hf_client_binp(numstr); +} + +static void bta_hf_client_handle_clcc(UINT16 idx, UINT16 dir, UINT16 status, UINT16 mode, UINT16 mpty, char *numstr, UINT16 type) +{ + APPL_TRACE_DEBUG("%s idx: %u dir: %u status: %u mode: %u mpty: %u", + __FUNCTION__, idx, dir, status, mode, mpty); + + if (numstr) { + APPL_TRACE_DEBUG("%s number: %s type: %u", __FUNCTION__, numstr, type); + } + + bta_hf_client_clcc(idx, dir, status, mpty, numstr); +} + +static void bta_hf_client_handle_cnum( char *numstr, UINT16 type, UINT16 service) +{ + APPL_TRACE_DEBUG("%s number: %s type: %u service: %u", __FUNCTION__, numstr, type, service); + + /* TODO: should number be modified according to type? */ + bta_hf_client_cnum(numstr, service); +} + +static void bta_hf_client_handle_btrh( UINT16 code) +{ + APPL_TRACE_DEBUG("%s %u", __FUNCTION__, code); + + bta_hf_client_evt_val(BTA_HF_CLIENT_BTRH_EVT, code); +} + +/****************************************************************************** +** +** COMMON AT EVENTS PARSING FUNCTIONS +** +*******************************************************************************/ + +/* Check if prefix match and skip spaces if any */ +#define AT_CHECK_EVENT(buf, event) \ + if (strncmp("\r\n"event, buf,sizeof("\r\n"event) - 1) != 0) return buf; \ + buf += sizeof("\r\n"event) - 1; \ + while (*buf == ' ') buf++; + +/* check for and forward buffer if match */ +#define AT_CHECK_RN(buf) \ + if (strncmp("\r\n", buf, sizeof("\r\n") - 1) != 0) { \ + APPL_TRACE_DEBUG("%s missing end ", __FUNCTION__); \ + return NULL;} \ + buf += sizeof("\r\n") - 1; + +/* skip rest of AT string up to */ +#define AT_SKIP_REST(buf) while(*buf != '\r') buf++; + +static char *bta_hf_client_parse_ok(char *buffer) +{ + AT_CHECK_EVENT(buffer, "OK"); + AT_CHECK_RN(buffer); + + bta_hf_client_handle_ok(); + + return buffer; +} + +static char *bta_hf_client_parse_error(char *buffer) +{ + AT_CHECK_EVENT(buffer, "ERROR"); + AT_CHECK_RN(buffer); + + bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_ERROR, 0); + + return buffer; +} + +static char *bta_hf_client_parse_ring(char *buffer) +{ + AT_CHECK_EVENT(buffer, "RING"); + AT_CHECK_RN(buffer); + + bta_hf_client_handle_ring(); + + return buffer; +} + +/* generic uint32 parser */ +static char *bta_hf_client_parse_uint32(char *buffer, void (*handler_callback)(UINT32)) +{ + UINT32 value; + int res; + int offset; + + res = sscanf(buffer, "%u%n", &value, &offset); + if (res < 1) { + return NULL; + } + + buffer += offset; + + AT_CHECK_RN(buffer); + + handler_callback(value); + return buffer; +} + +static char *bta_hf_client_parse_brsf(char *buffer) +{ + AT_CHECK_EVENT(buffer, "+BRSF:"); + + return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_brsf); +} + +static char *bta_hf_client_parse_cind_values(char *buffer) +{ + /* value and its position */ + UINT16 index = 0; + UINT32 value = 0; + + int offset; + int res; + + while ((res = sscanf(buffer, "%u%n", &value, &offset)) > 0) { + /* decides if its valid index and value, if yes stores it */ + bta_hf_client_handle_cind_value(index, value); + + buffer += offset; + + /* check if more values are present */ + if (*buffer != ',') { + break; + } + + index++; + buffer++; + } + + if (res > 0) { + AT_CHECK_RN(buffer); + return buffer; + } + + return NULL; +} + +static char *bta_hf_client_parse_cind_list(char *buffer) +{ + int offset; + char *name = osi_malloc(129); + UINT32 min, max; + UINT32 index = 0; + int res; + + if (name == NULL) { + APPL_TRACE_ERROR("No mem %s", __FUNCTION__); + return NULL; + } + + while ((res = sscanf(buffer, "(\"%128[^\"]\",(%u%*[-,]%u))%n", name, &min, &max, &offset)) > 2) { + bta_hf_client_handle_cind_list_item(name, min, max, index); + buffer += offset; + index++; + + if (*buffer != ',') { + break; + } + + buffer++; + } + + osi_free(name); + + if (res > 2) { + AT_CHECK_RN(buffer); + return buffer; + } + + return NULL; +} + +static char *bta_hf_client_parse_cind(char *buffer) +{ + AT_CHECK_EVENT(buffer, "+CIND:"); + + if (*buffer == '(') { + return bta_hf_client_parse_cind_list(buffer); + } + + return bta_hf_client_parse_cind_values(buffer); +} + +static char *bta_hf_client_parse_chld(char *buffer) +{ + AT_CHECK_EVENT(buffer, "+CHLD:"); + + if (*buffer != '(') { + return NULL; + } + + buffer++; + + while (*buffer != '\0') { + if (strncmp("0", buffer, 1) == 0) { + bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_REL); + buffer++; + } else if (strncmp("1x", buffer, 2) == 0) { + bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_REL_X); + buffer += 2; + } else if (strncmp("1", buffer, 1) == 0) { + bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_REL_ACC); + buffer++; + } else if (strncmp("2x", buffer, 2) == 0) { + bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_PRIV_X); + buffer += 2; + } else if (strncmp("2", buffer, 1) == 0) { + bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_HOLD_ACC); + buffer++; + } else if (strncmp("3", buffer, 1) == 0) { + bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_MERGE); + buffer++; + } else if (strncmp("4", buffer, 1) == 0) { + bta_hf_client_handle_chld(BTA_HF_CLIENT_CHLD_MERGE_DETACH); + buffer++; + } else { + return NULL; + } + + if (*buffer == ',') { + buffer++; + continue; + } + + if (*buffer == ')') { + buffer++; + break; + } + + return NULL; + } + + AT_CHECK_RN(buffer); + + return buffer; +} + +static char *bta_hf_client_parse_ciev(char *buffer) +{ + UINT32 index, value; + int res; + int offset; + + AT_CHECK_EVENT(buffer, "+CIEV:"); + + res = sscanf(buffer, "%u,%u%n", &index, &value, &offset); + if (res < 2) { + return NULL; + } + + buffer += offset; + + AT_CHECK_RN(buffer); + + bta_hf_client_handle_ciev(index, value); + return buffer; +} + +static char *bta_hf_client_parse_bcs(char *buffer) +{ + AT_CHECK_EVENT(buffer, "+BCS:"); + + return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_bcs); +} + +static char *bta_hf_client_parse_bsir(char *buffer) +{ + AT_CHECK_EVENT(buffer, "+BSIR:"); + + return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_bsir); +} + +static char *bta_hf_client_parse_cmeerror(char *buffer) +{ + AT_CHECK_EVENT(buffer, "+CME ERROR:"); + + return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_cmeerror); +} + +static char *bta_hf_client_parse_vgm(char *buffer) +{ + AT_CHECK_EVENT(buffer, "+VGM:"); + + return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_vgm); +} + +static char *bta_hf_client_parse_vgme(char *buffer) +{ + AT_CHECK_EVENT(buffer, "+VGM="); + + return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_vgm); +} + +static char *bta_hf_client_parse_vgs(char *buffer) +{ + AT_CHECK_EVENT(buffer, "+VGS:"); + + return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_vgs); +} + +static char *bta_hf_client_parse_vgse(char *buffer) +{ + AT_CHECK_EVENT(buffer, "+VGS="); + + return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_vgs); +} + +static char *bta_hf_client_parse_bvra(char *buffer) +{ + AT_CHECK_EVENT(buffer, "+BVRA:"); + + return bta_hf_client_parse_uint32(buffer, bta_hf_client_handle_bvra); +} + +static char *bta_hf_client_parse_clip(char *buffer) +{ + /* spec forces 32 chars, plus \0 here */ + char number[33]; + UINT32 type = 0; + int res; + int offset; + + AT_CHECK_EVENT(buffer, "+CLIP:"); + + /* there might be something more after %lu but HFP doesn't care */ + res = sscanf(buffer, "\"%32[^\"]\",%u%n", number, &type, &offset); + if (res < 2) { + return NULL; + } + + buffer += offset; + + AT_SKIP_REST(buffer); + + AT_CHECK_RN(buffer); + + bta_hf_client_handle_clip(number, type); + return buffer; +} + +/* in HFP context there is no difference between ccwa and clip */ +static char *bta_hf_client_parse_ccwa(char *buffer) +{ + /* ac to spec 32 chars max, plus \0 here */ + char number[33]; + UINT32 type = 0; + int res ; + int offset; + + AT_CHECK_EVENT(buffer, "+CCWA:"); + + /* there might be something more after %lu but HFP doesn't care */ + res = sscanf(buffer, "\"%32[^\"]\",%u%n", number, &type, &offset); + if (res < 2) { + return NULL; + } + + buffer += offset; + + AT_SKIP_REST(buffer); + + AT_CHECK_RN(buffer); + + bta_hf_client_handle_ccwa(number, type); + return buffer; +} + +static char *bta_hf_client_parse_cops(char *buffer) +{ + UINT8 mode; + /* spec forces 16 chars max, plus \0 here */ + char opstr[17]; + int res; + int offset; + + AT_CHECK_EVENT(buffer, "+COPS:"); + + /* TODO: Not sure if operator string actually can contain escaped " char inside */ + res = sscanf(buffer, "%hhi,0,\"%16[^\"]\"%n", &mode, opstr, &offset); + if (res < 2) { + return NULL; + } + + buffer += offset; + + AT_SKIP_REST(buffer); + + AT_CHECK_RN(buffer); + + bta_hf_client_handle_cops(opstr, mode); + return buffer; +} + +static char *bta_hf_client_parse_binp(char *buffer) +{ + /* HFP only supports phone number as BINP data */ + /* phone number is 32 chars plus one for \0*/ + char numstr[33]; + int res; + int offset; + + AT_CHECK_EVENT(buffer, "+BINP:"); + + res = sscanf(buffer, "\"%32[^\"]\"\r\n%n", numstr, &offset); + if (res < 1) { + return NULL; + } + + buffer += offset; + + /* some phones might sent type as well, just skip it */ + AT_SKIP_REST(buffer); + + AT_CHECK_RN(buffer); + + bta_hf_client_handle_binp(numstr); + return buffer; +} + +static char *bta_hf_client_parse_clcc(char *buffer) +{ + UINT16 idx, dir, status, mode, mpty; + char numstr[33]; /* spec forces 32 chars, plus one for \0*/ + UINT16 type; + int res; + int offset; + AT_CHECK_EVENT(buffer, "+CLCC:"); + + res = sscanf(buffer, "%hu,%hu,%hu,%hu,%hu%n", + &idx, &dir, &status, &mode, &mpty, &offset); + if (res < 5) { + return NULL; + } + + buffer += offset; + + /* check optional part */ + if (*buffer == ',') { + int res2; + + res2 = sscanf(buffer, ",\"%32[^\"]\",%hu%n", numstr, &type, &offset); + if (res2 < 0) { + return NULL; + } + + if (res2 == 0) { + res2 = sscanf(buffer, ",\"\",%hu%n", &type, &offset); + if (res < 0) { + return NULL; + } + + /* numstr is not matched in second attempt, correct this */ + res2++; + numstr[0] = '\0'; + } + + if (res2 < 2) { + return NULL; + } + + res += res2; + buffer += offset; + } + + AT_CHECK_RN(buffer); + + if (res > 6) { + /* we also have last two optional parameters */ + bta_hf_client_handle_clcc(idx, dir, status, mode, mpty, numstr, type); + } else { + /* we didn't get the last two parameters */ + bta_hf_client_handle_clcc(idx, dir, status, mode, mpty, NULL, 0); + } + + return buffer; +} + +static char *bta_hf_client_parse_cnum(char *buffer) +{ + char numstr[33]; /* spec forces 32 chars, plus one for \0*/ + UINT16 type; + UINT16 service = 0; /* 0 in case this optional parameter is not being sent */ + int res; + int offset; + + AT_CHECK_EVENT(buffer, "+CNUM:"); + + res = sscanf(buffer, ",\"%32[^\"]\",%hu,,%hu%n", numstr, &type, &service, &offset); + if (res < 0) { + return NULL; + } + + if (res == 0) { + res = sscanf(buffer, ",\"\",%hu,,%hu%n", &type, &service, &offset); + if (res < 0) { + return NULL; + } + + /* numstr is not matched in second attempt, correct this */ + res++; + numstr[0] = '\0'; + } + + if (res < 3) { + return NULL; + } + + buffer += offset; + + AT_CHECK_RN(buffer); + + /* service is optional */ + if (res == 2) { + bta_hf_client_handle_cnum(numstr, type, service); + return buffer; + } + + if (service != 4 && service != 5) { + return NULL; + } + + bta_hf_client_handle_cnum(numstr, type, service); + return buffer; +} + +static char *bta_hf_client_parse_btrh(char *buffer) +{ + UINT16 code = 0; + int res; + int offset; + + AT_CHECK_EVENT(buffer, "+BTRH:"); + + res = sscanf(buffer, "%hu%n", &code, &offset); + if (res < 1) { + return NULL; + } + + buffer += offset; + + AT_CHECK_RN(buffer); + + bta_hf_client_handle_btrh(code); + return buffer; +} + +static char *bta_hf_client_parse_busy(char *buffer) +{ + AT_CHECK_EVENT(buffer, "BUSY"); + AT_CHECK_RN(buffer); + + bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_BUSY, 0); + + return buffer; +} + +static char *bta_hf_client_parse_delayed(char *buffer) +{ + AT_CHECK_EVENT(buffer, "DELAYED"); + AT_CHECK_RN(buffer); + + bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_DELAY, 0); + + return buffer; +} + +static char *bta_hf_client_parse_no_carrier(char *buffer) +{ + AT_CHECK_EVENT(buffer, "NO CARRIER"); + AT_CHECK_RN(buffer); + + bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_NO_CARRIER, 0); + + return buffer; +} + +static char *bta_hf_client_parse_no_answer(char *buffer) +{ + AT_CHECK_EVENT(buffer, "NO ANSWER"); + AT_CHECK_RN(buffer); + + bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_NO_ANSWER, 0); + + return buffer; +} + +static char *bta_hf_client_parse_blacklisted(char *buffer) +{ + AT_CHECK_EVENT(buffer, "BLACKLISTED"); + AT_CHECK_RN(buffer); + + bta_hf_client_handle_error(BTA_HF_CLIENT_AT_RESULT_BLACKLISTED, 0); + + return buffer; +} + +static char *bta_hf_client_skip_unknown(char *buffer) +{ + char *start; + char *tmp; + + tmp = strstr(buffer, "\r\n"); + if (tmp == NULL) { + return NULL; + } + + buffer += 2; + start = buffer; + + tmp = strstr(buffer, "\r\n"); + if (tmp == NULL) { + return NULL; + } + + buffer = tmp + 2; + + APPL_TRACE_DEBUG("%s %.*s", __FUNCTION__, buffer - start - 2, start); + + return buffer; +} + + +/****************************************************************************** +** SUPPORTED EVENT MESSAGES +*******************************************************************************/ + +/* returned values are as follow: + * != NULL && != buf : match and parsed ok + * == NULL : match but parse failed + * != NULL && == buf : no match + */ +typedef char *(*tBTA_HF_CLIENT_PARSER_CALLBACK)(char *); + +static const tBTA_HF_CLIENT_PARSER_CALLBACK bta_hf_client_parser_cb[] = { + bta_hf_client_parse_ok, + bta_hf_client_parse_error, + bta_hf_client_parse_ring, + bta_hf_client_parse_brsf, + bta_hf_client_parse_cind, + bta_hf_client_parse_ciev, + bta_hf_client_parse_chld, + bta_hf_client_parse_bcs, + bta_hf_client_parse_bsir, + bta_hf_client_parse_cmeerror, + bta_hf_client_parse_vgm, + bta_hf_client_parse_vgme, + bta_hf_client_parse_vgs, + bta_hf_client_parse_vgse, + bta_hf_client_parse_bvra, + bta_hf_client_parse_clip, + bta_hf_client_parse_ccwa, + bta_hf_client_parse_cops, + bta_hf_client_parse_binp, + bta_hf_client_parse_clcc, + bta_hf_client_parse_cnum, + bta_hf_client_parse_btrh, + bta_hf_client_parse_busy, + bta_hf_client_parse_delayed, + bta_hf_client_parse_no_carrier, + bta_hf_client_parse_no_answer, + bta_hf_client_parse_blacklisted, + bta_hf_client_skip_unknown +}; + +/* calculate supported event list length */ +static const UINT16 bta_hf_client_psraser_cb_count = + sizeof(bta_hf_client_parser_cb) / sizeof(bta_hf_client_parser_cb[0]); + +#ifdef BTA_HF_CLIENT_AT_DUMP +static void bta_hf_client_dump_at(void) +{ + char dump[(4 * BTA_HF_CLIENT_AT_PARSER_MAX_LEN) + 1]; + char *p1, *p2; + + p1 = bta_hf_client_cb.scb.at_cb.buf; + p2 = dump; + + while (*p1 != '\0') { + if (*p1 == '\r') { + strlcpy(p2, "", 4); + p2 += 4; + } else if (*p1 == '\n') { + strlcpy(p2, "", 4); + p2 += 4; + } else { + *p2 = *p1; + p2++; + } + p1++; + } + + *p2 = '\0'; + + APPL_TRACE_DEBUG("%s %s", __FUNCTION__, dump); +} +#endif + +static void bta_hf_client_at_parse_start(void) +{ + char *buf = bta_hf_client_cb.scb.at_cb.buf; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + +#ifdef BTA_HF_CLIENT_AT_DUMP + bta_hf_client_dump_at(); +#endif + + while (*buf != '\0') { + int i; + char *tmp = NULL; + + for (i = 0; i < bta_hf_client_psraser_cb_count; i++) { + tmp = bta_hf_client_parser_cb[i](buf); + if (tmp == NULL) { + APPL_TRACE_ERROR("HFPCient: AT event/reply parsing failed, skipping"); + tmp = bta_hf_client_skip_unknown(buf); + break; + } + + /* matched or unknown skipped, if unknown failed tmp is NULL so + this is also handled */ + if (tmp != buf) { + buf = tmp; + break; + } + } + + /* could not skip unknown (received garbage?)... disconnect */ + if (tmp == NULL) { + APPL_TRACE_ERROR("HFPCient: could not skip unknown AT event, disconnecting"); + bta_hf_client_at_reset(); + bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL); + return; + } + + buf = tmp; + } +} + +static BOOLEAN bta_hf_client_check_at_complete(void) +{ + BOOLEAN ret = FALSE; + tBTA_HF_CLIENT_AT_CB *at_cb = &bta_hf_client_cb.scb.at_cb; + + if (at_cb->offset >= BTA_HF_CLIENT_AT_EVENT_MIN_LEN) { + if (at_cb->buf[at_cb->offset - 2] == '\r' && at_cb->buf[at_cb->offset - 1] == '\n') { + ret = TRUE; + } + } + + APPL_TRACE_DEBUG("%s %d", __FUNCTION__, ret); + + return ret; +} + +static void bta_hf_client_at_clear_buf(void) +{ + memset(bta_hf_client_cb.scb.at_cb.buf, 0, sizeof(bta_hf_client_cb.scb.at_cb.buf)); + bta_hf_client_cb.scb.at_cb.offset = 0; +} + +/****************************************************************************** +** +** MAIN PARSING FUNCTION +** +** +*******************************************************************************/ +void bta_hf_client_at_parse(char *buf, unsigned int len) +{ + APPL_TRACE_DEBUG("%s offset: %u len: %u", __FUNCTION__, bta_hf_client_cb.scb.at_cb.offset, len); + + if (len + bta_hf_client_cb.scb.at_cb.offset > BTA_HF_CLIENT_AT_PARSER_MAX_LEN) { + unsigned int tmp = bta_hf_client_cb.scb.at_cb.offset; + unsigned int space_left = BTA_HF_CLIENT_AT_PARSER_MAX_LEN - bta_hf_client_cb.scb.at_cb.offset; + char *tmp_buff = osi_malloc(BTA_HF_CLIENT_AT_PARSER_MAX_LEN); + if (tmp_buff == NULL) { + APPL_TRACE_ERROR("No mem %s", __FUNCTION__); + return; + } + APPL_TRACE_DEBUG("%s overrun, trying to recover", __FUNCTION__); + + /* fill up parser buffer */ + memcpy(bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, buf, space_left); + len -= space_left; + buf += space_left; + bta_hf_client_cb.scb.at_cb.offset += space_left; + + /* find end of last complete command before proceeding */ + while (bta_hf_client_check_at_complete() == FALSE) { + if (bta_hf_client_cb.scb.at_cb.offset == 0) { + APPL_TRACE_ERROR("HFPClient: AT parser buffer overrun, disconnecting"); + + bta_hf_client_at_reset(); + bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL); + osi_free(tmp_buff); + return; + } + + bta_hf_client_cb.scb.at_cb.offset--; + } + + /* cut buffer to complete AT event and keep cut data */ + tmp += space_left - bta_hf_client_cb.scb.at_cb.offset; + memcpy(tmp_buff, bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, tmp); + bta_hf_client_cb.scb.at_cb.buf[bta_hf_client_cb.scb.at_cb.offset] = '\0'; + + /* parse */ + bta_hf_client_at_parse_start(); + bta_hf_client_at_clear_buf(); + + /* recover cut data */ + memcpy(bta_hf_client_cb.scb.at_cb.buf, tmp_buff, tmp); + bta_hf_client_cb.scb.at_cb.offset += tmp; + + osi_free(tmp_buff); + } + + memcpy(bta_hf_client_cb.scb.at_cb.buf + bta_hf_client_cb.scb.at_cb.offset, buf, len); + bta_hf_client_cb.scb.at_cb.offset += len; + + /* If last event is complete, parsing can be started */ + if (bta_hf_client_check_at_complete() == TRUE) { + bta_hf_client_at_parse_start(); + bta_hf_client_at_clear_buf(); + } +} + +void bta_hf_client_send_at_brsf(void) +{ + char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN); + int at_len; + + if (buf == NULL) { + APPL_TRACE_ERROR("No mem %s", __FUNCTION__); + return; + } + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+BRSF=%u\r", bta_hf_client_cb.scb.features); + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_BRSF , buf, at_len); + osi_free(buf); +} + +void bta_hf_client_send_at_bac(void) +{ + char *buf; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if (bta_hf_client_cb.msbc_enabled) { + buf = "AT+BAC=1,2\r"; + } else { + buf = "AT+BAC=1\r"; + } + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_BAC, buf, strlen(buf)); +} + +void bta_hf_client_send_at_bcs(UINT32 codec) +{ + char * buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN); + int at_len; + + if (buf == NULL) { + APPL_TRACE_ERROR("No mem %s", __FUNCTION__); + return; + } + + at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+BCS=%u\r", codec); + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_BCS, buf, at_len); + osi_free(buf); +} + +void bta_hf_client_send_at_cind(BOOLEAN status) +{ + char *buf; + tBTA_HF_CLIENT_AT_CMD cmd; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if (status) { + buf = "AT+CIND?\r"; + cmd = BTA_HF_CLIENT_AT_CIND_STATUS; + } else { + buf = "AT+CIND=?\r"; + cmd = BTA_HF_CLIENT_AT_CIND; + } + + bta_hf_client_send_at(cmd, buf, strlen(buf)); +} + +void bta_hf_client_send_at_cmer(BOOLEAN activate) +{ + char *buf; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if (activate) { + buf = "AT+CMER=3,0,0,1\r"; + } else { + buf = "AT+CMER=3,0,0,0\r"; + } + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_CMER, buf, strlen(buf)); +} + +void bta_hf_client_send_at_chld(char cmd, UINT32 idx) +{ + char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN); + int at_len; + + if (buf == NULL) { + APPL_TRACE_ERROR("No mem %s", __FUNCTION__); + return; + } + + if (idx > 0) { + at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+CHLD=%c%u\r", cmd, idx); + } else { + at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+CHLD=%c\r", cmd); + } + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_CHLD, buf, at_len); + osi_free(buf); +} + +void bta_hf_client_send_at_clip(BOOLEAN activate) +{ + char *buf; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if (activate) { + buf = "AT+CLIP=1\r"; + } else { + buf = "AT+CLIP=0\r"; + } + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_CLIP, buf, strlen(buf)); +} + +void bta_hf_client_send_at_ccwa(BOOLEAN activate) +{ + char *buf; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if (activate) { + buf = "AT+CCWA=1\r"; + } else { + buf = "AT+CCWA=0\r"; + } + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_CCWA, buf, strlen(buf)); +} + + +void bta_hf_client_send_at_cmee(BOOLEAN activate) +{ + char *buf; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if (activate) { + buf = "AT+CMEE=1\r"; + } else { + buf = "AT+CMEE=0\r"; + } + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_CMEE, buf, strlen(buf)); +} + +void bta_hf_client_send_at_cops(BOOLEAN query) +{ + char *buf; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if (query) { + buf = "AT+COPS?\r"; + } else { + buf = "AT+COPS=3,0\r"; + } + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_COPS, buf, strlen(buf)); +} + +void bta_hf_client_send_at_clcc(void) +{ + char *buf; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + buf = "AT+CLCC\r"; + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_CLCC, buf, strlen(buf)); +} + +void bta_hf_client_send_at_bvra(BOOLEAN enable) +{ + char *buf; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if (enable) { + buf = "AT+BVRA=1\r"; + } else { + buf = "AT+BVRA=0\r"; + } + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_BVRA, buf, strlen(buf)); +} + +void bta_hf_client_send_at_vgs(UINT32 volume) +{ + char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN); + int at_len; + if (buf == NULL) { + APPL_TRACE_ERROR("No mem %s", __FUNCTION__); + return; + } + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+VGS=%u\r", volume); + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_VGS, buf, at_len); + osi_free(buf); +} + +void bta_hf_client_send_at_vgm(UINT32 volume) +{ + char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN); + int at_len; + + if (buf == NULL) { + APPL_TRACE_ERROR("No mem %s", __FUNCTION__); + return; + } + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+VGM=%u\r", volume); + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_VGM, buf, at_len); + osi_free(buf); +} + +void bta_hf_client_send_at_atd(char *number, UINT32 memory) +{ + char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN); + int at_len; + + if (buf == NULL) { + APPL_TRACE_ERROR("No mem %s", __FUNCTION__); + return; + } + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if (number[0] != '\0') { + at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "ATD%s;\r", number); + } else { + at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "ATD>%u;\r", memory); + } + + at_len = MIN(at_len, BTA_HF_CLIENT_AT_MAX_LEN); + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_ATD, buf, at_len); + osi_free(buf); +} + +void bta_hf_client_send_at_bldn(void) +{ + char *buf; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + buf = "AT+BLDN\r"; + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_BLDN, buf, strlen(buf)); +} + +void bta_hf_client_send_at_ata(void) +{ + char *buf; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + buf = "ATA\r"; + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_ATA, buf, strlen(buf)); +} + +void bta_hf_client_send_at_chup(void) +{ + char *buf; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + buf = "AT+CHUP\r"; + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_CHUP, buf, strlen(buf)); +} + +void bta_hf_client_send_at_btrh(BOOLEAN query, UINT32 val) +{ + char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN); + int at_len; + + if (buf == NULL) { + APPL_TRACE_ERROR("No mem %s", __FUNCTION__); + return; + } + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if (query == TRUE) { + at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+BTRH?\r"); + } else { + at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+BTRH=%u\r", val); + } + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_BTRH, buf, at_len); + osi_free(buf); +} + +void bta_hf_client_send_at_vts(char code) +{ + char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN); + int at_len; + if (buf == NULL) { + APPL_TRACE_ERROR("No mem %s", __FUNCTION__); + return; + } + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+VTS=%c\r", code); + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_VTS, buf, at_len); + osi_free(buf); +} + +void bta_hf_client_send_at_bcc(void) +{ + char *buf; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + buf = "AT+BCC\r"; + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_BCC, buf, strlen(buf)); +} + +void bta_hf_client_send_at_cnum(void) +{ + char *buf; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + buf = "AT+CNUM\r"; + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_CNUM, buf, strlen(buf)); +} + +void bta_hf_client_send_at_nrec(void) +{ + char *buf; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if (!(bta_hf_client_cb.scb.peer_features & BTA_HF_CLIENT_PEER_FEAT_ECNR)) { + APPL_TRACE_ERROR("%s: Remote does not support NREC.", __FUNCTION__); + return; + } + + buf = "AT+NREC=0\r"; + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_NREC, buf, strlen(buf)); +} + +void bta_hf_client_send_at_binp(UINT32 action) +{ + char *buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN); + int at_len; + + if (buf == NULL) { + APPL_TRACE_ERROR("No mem %s", __FUNCTION__); + return; + } + + at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+BINP=%u\r", action); + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_BINP, buf, at_len); + osi_free(buf); +} + +void bta_hf_client_send_at_bia(void) +{ + char *buf; + int at_len; + int i; + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + if (bta_hf_client_cb.scb.peer_version < HFP_VERSION_1_6) { + APPL_TRACE_DEBUG("Remote does not Support AT+BIA"); + return; + } + + buf = osi_malloc(BTA_HF_CLIENT_AT_MAX_LEN); + if (buf == NULL) { + APPL_TRACE_ERROR("No mem %s", __FUNCTION__); + return; + } + at_len = snprintf(buf, BTA_HF_CLIENT_AT_MAX_LEN, "AT+BIA="); + + for (i = 0; i < BTA_HF_CLIENT_AT_INDICATOR_COUNT; i++) { + int sup = bta_hf_client_cb.scb.at_cb.indicator_lookup[i] == -1 ? 0 : 1; + + at_len += snprintf(buf + at_len, BTA_HF_CLIENT_AT_MAX_LEN - at_len, "%u,", sup); + } + + buf[at_len - 1] = '\r'; + + bta_hf_client_send_at(BTA_HF_CLIENT_AT_BIA, buf, at_len); + osi_free(buf); +} + +void bta_hf_client_at_init(void) +{ + memset(&bta_hf_client_cb.scb.at_cb, 0, sizeof(tBTA_HF_CLIENT_AT_CB)); + bta_hf_client_at_reset(); +} + +void bta_hf_client_at_reset(void) +{ + int i; + + bta_hf_client_free_at_resp_timer(); + bta_hf_client_free_at_hold_timer(); + + bta_hf_client_clear_queued_at(); + + bta_hf_client_at_clear_buf(); + + for (i = 0; i < BTA_HF_CLIENT_AT_INDICATOR_COUNT; i++) { + bta_hf_client_cb.scb.at_cb.indicator_lookup[i] = -1; + } + + bta_hf_client_cb.scb.at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE; +} +#endif /* #if (BTA_HF_INCLUDED == TRUE) */ diff --git a/components/bt/bluedroid/bta/hf_client/bta_hf_client_cmd.c b/components/bt/bluedroid/bta/hf_client/bta_hf_client_cmd.c new file mode 100644 index 0000000000..df761e4e92 --- /dev/null +++ b/components/bt/bluedroid/bta/hf_client/bta_hf_client_cmd.c @@ -0,0 +1,85 @@ +/****************************************************************************** + * + * Copyright (c) 2014 The Android Open Source Project + * Copyright (C) 2003-2012 Broadcom Corporation + * + * 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 "bta_hf_client_int.h" +#include "stdio.h" +#include "common/bt_target.h" + +#if (BTA_HF_INCLUDED == TRUE) + +void bta_hf_client_send_at_cmd(tBTA_HF_CLIENT_DATA *p_data) +{ + tBTA_HF_CLIENT_DATA_VAL *p_val = (tBTA_HF_CLIENT_DATA_VAL *)p_data; + + switch (p_val->uint8_val) { + case BTA_HF_CLIENT_AT_CMD_VTS: + bta_hf_client_send_at_vts((char)p_val->uint32_val1); + break; + case BTA_HF_CLIENT_AT_CMD_BTRH: + bta_hf_client_send_at_btrh(FALSE, p_val->uint32_val1); + break; + case BTA_HF_CLIENT_AT_CMD_CHUP: + bta_hf_client_send_at_chup(); + break; + case BTA_HF_CLIENT_AT_CMD_CHLD: + /* expects ascii code for command */ + bta_hf_client_send_at_chld('0' + p_val->uint32_val1, p_val->uint32_val2); + break; + case BTA_HF_CLIENT_AT_CMD_BCC: + bta_hf_client_send_at_bcc(); + break; + case BTA_HF_CLIENT_AT_CMD_CNUM: + bta_hf_client_send_at_cnum(); + break; + case BTA_HF_CLIENT_AT_CMD_ATA: + bta_hf_client_send_at_ata(); + break; + case BTA_HF_CLIENT_AT_CMD_COPS: + bta_hf_client_send_at_cops(TRUE); + break; + case BTA_HF_CLIENT_AT_CMD_ATD: + bta_hf_client_send_at_atd(p_val->str, p_val->uint32_val1); + break; + case BTA_HF_CLIENT_AT_CMD_VGM: + bta_hf_client_send_at_vgm(p_val->uint32_val1); + break; + case BTA_HF_CLIENT_AT_CMD_VGS: + bta_hf_client_send_at_vgs(p_val->uint32_val1); + break; + case BTA_HF_CLIENT_AT_CMD_BVRA: + bta_hf_client_send_at_bvra(p_val->uint32_val1 == 0 ? FALSE : TRUE); + break; + case BTA_HF_CLIENT_AT_CMD_CLCC: + bta_hf_client_send_at_clcc(); + break; + case BTA_HF_CLIENT_AT_CMD_BINP: + bta_hf_client_send_at_binp(p_val->uint32_val1); + break; + case BTA_HF_CLIENT_AT_CMD_BLDN: + bta_hf_client_send_at_bldn(); + break; + case BTA_HF_CLIENT_AT_CMD_NREC: + bta_hf_client_send_at_nrec(); + break; + default: + APPL_TRACE_ERROR("Default case, %s", __FUNCTION__); + break; + } +} +#endif /* #if (BTA_HF_INCLUDED == TRUE) */ diff --git a/components/bt/bluedroid/bta/hf_client/bta_hf_client_main.c b/components/bt/bluedroid/bta/hf_client/bta_hf_client_main.c new file mode 100644 index 0000000000..16e67cf731 --- /dev/null +++ b/components/bt/bluedroid/bta/hf_client/bta_hf_client_main.c @@ -0,0 +1,662 @@ +/****************************************************************************** + * + * Copyright (c) 2014 The Android Open Source Project + * Copyright (C) 2003-2012 Broadcom Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +#include +#include +#include "common/bt_defs.h" +#include "bta/bta_api.h" +#include "bta/bta_sys.h" +#include "bta/bta_hf_client_api.h" +#include "bta_hf_client_int.h" + +#if (BTA_HF_INCLUDED == TRUE) +/* uncomment to enable extra debug */ +/* #define BTA_HF_CLIENT_DEBUG TRUE */ + +#ifndef BTA_HF_CLIENT_DEBUG +#define BTA_HF_CLIENT_DEBUG FALSE +#endif + +#if BTA_HF_CLIENT_DEBUG == TRUE +static char *bta_hf_client_evt_str(UINT16 event); +static char *bta_hf_client_state_str(UINT8 state); +#endif + +/* state machine states */ +enum { + BTA_HF_CLIENT_INIT_ST, + BTA_HF_CLIENT_OPENING_ST, + BTA_HF_CLIENT_OPEN_ST, + BTA_HF_CLIENT_CLOSING_ST +}; + +/* state machine action enumeration list */ +enum { + BTA_HF_CLIENT_REGISTER, + BTA_HF_CLIENT_DEREGISTER, + BTA_HF_CLIENT_START_DEREG, + BTA_HF_CLIENT_RFC_DO_CLOSE, + BTA_HF_CLIENT_START_CLOSE, + BTA_HF_CLIENT_START_OPEN, + BTA_HF_CLIENT_RFC_ACP_OPEN, + BTA_HF_CLIENT_SCO_LISTEN, + BTA_HF_CLIENT_SCO_CONN_OPEN, + BTA_HF_CLIENT_SCO_CONN_CLOSE, + BTA_HF_CLIENT_SCO_OPEN, + BTA_HF_CLIENT_SCO_CLOSE, + BTA_HF_CLIENT_SCO_SHUTDOWN, + BTA_HF_CLIENT_FREE_DB, + BTA_HF_CLIENT_OPEN_FAIL, + BTA_HF_CLIENT_RFC_OPEN, + BTA_HF_CLIENT_RFC_FAIL, + BTA_HF_CLIENT_DISC_INT_RES, + BTA_HF_CLIENT_RFC_DO_OPEN, + BTA_HF_CLIENT_DISC_FAIL, + BTA_HF_CLIENT_RFC_CLOSE, + BTA_HF_CLIENT_RFC_DATA, + BTA_HF_CLIENT_DISC_ACP_RES, + BTA_HF_CLIENT_SVC_CONN_OPEN, + BTA_HF_CLIENT_SEND_AT_CMD, +#if (BTM_SCO_HCI_INCLUDED == TRUE) + BTA_HF_CLIENT_CI_SCO_DATA, +#endif + BTA_HF_CLIENT_NUM_ACTIONS, +}; + +#define BTA_HF_CLIENT_IGNORE BTA_HF_CLIENT_NUM_ACTIONS + +/* type for action functions */ +typedef void (*tBTA_HF_CLIENT_ACTION)(tBTA_HF_CLIENT_DATA *p_data); + +/* action functions table, indexed with action enum */ +const tBTA_HF_CLIENT_ACTION bta_hf_client_action[] = { + /* BTA_HF_CLIENT_REGISTER */ bta_hf_client_register, + /* BTA_HF_CLIENT_DEREGISTER */ bta_hf_client_deregister, + /* BTA_HF_CLIENT_START_DEREG */ bta_hf_client_start_dereg, + /* BTA_HF_CLIENT_RFC_DO_CLOSE */ bta_hf_client_rfc_do_close, + /* BTA_HF_CLIENT_START_CLOSE */ bta_hf_client_start_close, + /* BTA_HF_CLIENT_START_OPEN */ bta_hf_client_start_open, + /* BTA_HF_CLIENT_RFC_ACP_OPEN */ bta_hf_client_rfc_acp_open, + /* BTA_HF_CLIENT_SCO_LISTEN */ bta_hf_client_sco_listen, + /* BTA_HF_CLIENT_SCO_CONN_OPEN */ bta_hf_client_sco_conn_open, + /* BTA_HF_CLIENT_SCO_CONN_CLOSE*/ bta_hf_client_sco_conn_close, + /* BTA_HF_CLIENT_SCO_OPEN */ bta_hf_client_sco_open, + /* BTA_HF_CLIENT_SCO_CLOSE */ bta_hf_client_sco_close, + /* BTA_HF_CLIENT_SCO_SHUTDOWN */ bta_hf_client_sco_shutdown, + /* BTA_HF_CLIENT_FREE_DB */ bta_hf_client_free_db, + /* BTA_HF_CLIENT_OPEN_FAIL */ bta_hf_client_open_fail, + /* BTA_HF_CLIENT_RFC_OPEN */ bta_hf_client_rfc_open, + /* BTA_HF_CLIENT_RFC_FAIL */ bta_hf_client_rfc_fail, + /* BTA_HF_CLIENT_DISC_INT_RES */ bta_hf_client_disc_int_res, + /* BTA_HF_CLIENT_RFC_DO_OPEN */ bta_hf_client_rfc_do_open, + /* BTA_HF_CLIENT_DISC_FAIL */ bta_hf_client_disc_fail, + /* BTA_HF_CLIENT_RFC_CLOSE */ bta_hf_client_rfc_close, + /* BTA_HF_CLIENT_RFC_DATA */ bta_hf_client_rfc_data, + /* BTA_HF_CLIENT_DISC_ACP_RES */ bta_hf_client_disc_acp_res, + /* BTA_HF_CLIENT_SVC_CONN_OPEN */ bta_hf_client_svc_conn_open, + /* BTA_HF_CLIENT_SEND_AT_CMD */ bta_hf_client_send_at_cmd, +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + /* BTA_HF_CLIENT_CI_SCO_DATA */ bta_hf_client_ci_sco_data, +#endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */ +}; + +/* state table information */ +#define BTA_HF_CLIENT_ACTIONS 2 /* number of actions */ +#define BTA_HF_CLIENT_NEXT_STATE 2 /* position of next state */ +#define BTA_HF_CLIENT_NUM_COLS 3 /* number of columns in state tables */ + +/* state table for init state */ +const UINT8 bta_hf_client_st_init[][BTA_HF_CLIENT_NUM_COLS] = { + /* Event Action 1 Action 2 Next state */ + /* API_REGISTER_EVT */ {BTA_HF_CLIENT_REGISTER, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* API_DEREGISTER_EVT */ {BTA_HF_CLIENT_DEREGISTER, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* API_OPEN_EVT */ {BTA_HF_CLIENT_START_OPEN, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, + /* API_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* API_AUDIO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* API_AUDIO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* RFC_OPEN_EVT */ {BTA_HF_CLIENT_RFC_ACP_OPEN, BTA_HF_CLIENT_SCO_LISTEN, BTA_HF_CLIENT_OPEN_ST}, + /* RFC_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* RFC_SRV_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* RFC_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* DISC_ACP_RES_EVT */ {BTA_HF_CLIENT_FREE_DB, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* DISC_INT_RES_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* DISC_OK_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* DISC_FAIL_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* SCO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + /* CI_SCO_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, +#endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */ +}; + +/* state table for opening state */ +const UINT8 bta_hf_client_st_opening[][BTA_HF_CLIENT_NUM_COLS] = { + /* Event Action 1 Action 2 Next state */ + /* API_REGISTER_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, + /* API_DEREGISTER_EVT */ {BTA_HF_CLIENT_RFC_DO_CLOSE, BTA_HF_CLIENT_START_DEREG, BTA_HF_CLIENT_CLOSING_ST}, + /* API_OPEN_EVT */ {BTA_HF_CLIENT_OPEN_FAIL, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, + /* API_CLOSE_EVT */ {BTA_HF_CLIENT_RFC_DO_CLOSE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* API_AUDIO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, + /* API_AUDIO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, + /* RFC_OPEN_EVT */ {BTA_HF_CLIENT_RFC_OPEN, BTA_HF_CLIENT_SCO_LISTEN, BTA_HF_CLIENT_OPEN_ST}, + /* RFC_CLOSE_EVT */ {BTA_HF_CLIENT_RFC_FAIL, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* RFC_SRV_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, + /* RFC_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, + /* DISC_ACP_RES_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, + /* DISC_INT_RES_EVT */ {BTA_HF_CLIENT_DISC_INT_RES, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, + /* DISC_OK_EVT */ {BTA_HF_CLIENT_RFC_DO_OPEN, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, + /* DISC_FAIL_EVT */ {BTA_HF_CLIENT_DISC_FAIL, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* SCO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, + /* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, + /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + /* CI_SCO_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPENING_ST}, +#endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */ +}; + +/* state table for open state */ +const UINT8 bta_hf_client_st_open[][BTA_HF_CLIENT_NUM_COLS] = { + /* Event Action 1 Action 2 Next state */ + /* API_REGISTER_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, + /* API_DEREGISTER_EVT */ {BTA_HF_CLIENT_START_CLOSE, BTA_HF_CLIENT_START_DEREG, BTA_HF_CLIENT_CLOSING_ST}, + /* API_OPEN_EVT */ {BTA_HF_CLIENT_OPEN_FAIL, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, + /* API_CLOSE_EVT */ {BTA_HF_CLIENT_START_CLOSE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* API_AUDIO_OPEN_EVT */ {BTA_HF_CLIENT_SCO_OPEN, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, + /* API_AUDIO_CLOSE_EVT */ {BTA_HF_CLIENT_SCO_CLOSE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, + /* RFC_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, + /* RFC_CLOSE_EVT */ {BTA_HF_CLIENT_RFC_CLOSE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* RFC_SRV_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, + /* RFC_DATA_EVT */ {BTA_HF_CLIENT_RFC_DATA, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, + /* DISC_ACP_RES_EVT */ {BTA_HF_CLIENT_DISC_ACP_RES, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, + /* DISC_INT_RES_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, + /* DISC_OK_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, + /* DISC_FAIL_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, + /* SCO_OPEN_EVT */ {BTA_HF_CLIENT_SCO_CONN_OPEN, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, + /* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_SCO_CONN_CLOSE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, + /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_SEND_AT_CMD, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + /* CI_SCO_DATA_EVT */ {BTA_HF_CLIENT_CI_SCO_DATA, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_OPEN_ST}, +#endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */ +}; + +/* state table for closing state */ +const UINT8 bta_hf_client_st_closing[][BTA_HF_CLIENT_NUM_COLS] = { + /* Event Action 1 Action 2 Next state */ + /* API_REGISTER_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* API_DEREGISTER_EVT */ {BTA_HF_CLIENT_START_DEREG, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* API_OPEN_EVT */ {BTA_HF_CLIENT_OPEN_FAIL, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* API_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* API_AUDIO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* API_AUDIO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* RFC_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* RFC_CLOSE_EVT */ {BTA_HF_CLIENT_RFC_CLOSE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* RFC_SRV_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* RFC_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* DISC_ACP_RES_EVT */ {BTA_HF_CLIENT_FREE_DB, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* DISC_INT_RES_EVT */ {BTA_HF_CLIENT_FREE_DB, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_INIT_ST}, + /* DISC_OK_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* DISC_FAIL_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* SCO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, + /* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + /* CI_SCO_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST}, +#endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */ +}; + +/* type for state table */ +typedef const UINT8 (*tBTA_HF_CLIENT_ST_TBL)[BTA_HF_CLIENT_NUM_COLS]; + +/* state table */ +const tBTA_HF_CLIENT_ST_TBL bta_hf_client_st_tbl[] = { + bta_hf_client_st_init, + bta_hf_client_st_opening, + bta_hf_client_st_open, + bta_hf_client_st_closing +}; + +/* HF Client control block */ +#if BTA_DYNAMIC_MEMORY == FALSE +tBTA_HF_CLIENT_CB bta_hf_client_cb; +#else +tBTA_HF_CLIENT_CB *bta_hf_client_cb_ptr; +#endif + + +/******************************************************************************* +** +** Function bta_hf_client_scb_init +** +** Description Initialize an HF_Client service control block. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_scb_init(void) +{ + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + memset(&bta_hf_client_cb.scb, 0, sizeof(tBTA_HF_CLIENT_SCB)); + bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX; + bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD; +} + +/******************************************************************************* +** +** Function bta_hf_client_scb_disable +** +** Description Disable a service control block. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_scb_disable(void) +{ + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + bta_hf_client_scb_init(); + + (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_DISABLE_EVT, NULL); +} + +/******************************************************************************* +** +** Function bta_hf_client_resume_open +** +** Description Resume opening process. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_resume_open (void) +{ + APPL_TRACE_DEBUG ("%s", __FUNCTION__); + + /* resume opening process. */ + if (bta_hf_client_cb.scb.state == BTA_HF_CLIENT_INIT_ST) { + bta_hf_client_cb.scb.state = BTA_HF_CLIENT_OPENING_ST; + bta_hf_client_start_open (NULL); + } +} + +/******************************************************************************* +** +** Function bta_hf_client_colli_timer_cback +** +** Description HF Client connection collision timer callback +** +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_colli_timer_cback (TIMER_LIST_ENT *p_tle) +{ + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if (p_tle) { + bta_hf_client_cb.scb.colli_tmr_on = FALSE; + + /* If the peer haven't opened connection, restart opening process */ + bta_hf_client_resume_open (); + } +} + +/******************************************************************************* +** +** Function bta_hf_client_collision_cback +** +** Description Get notified about collision. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_collision_cback (tBTA_SYS_CONN_STATUS status, UINT8 id, + UINT8 app_id, BD_ADDR peer_addr) +{ + UNUSED(status); + UNUSED(app_id); + UNUSED(peer_addr); + + if (bta_hf_client_cb.scb.state == BTA_HF_CLIENT_OPENING_ST) { + if (id == BTA_ID_SYS) { /* ACL collision */ + APPL_TRACE_WARNING ("HF Client found collision (ACL) ..."); + } else if (id == BTA_ID_HS) { /* RFCOMM collision */ + APPL_TRACE_WARNING ("HF Client found collision (RFCOMM) ..."); + } else { + APPL_TRACE_WARNING ("HF Client found collision (\?\?\?) ..."); + } + + bta_hf_client_cb.scb.state = BTA_HF_CLIENT_INIT_ST; + + /* Cancel SDP if it had been started. */ + if (bta_hf_client_cb.scb.p_disc_db) { + (void)SDP_CancelServiceSearch (bta_hf_client_cb.scb.p_disc_db); + bta_hf_client_free_db(NULL); + } + + /* reopen registered server */ + /* Collision may be detected before or after we close servers. */ + bta_hf_client_start_server(); + + /* Start timer to handle connection opening restart */ + bta_hf_client_cb.scb.colli_timer.p_cback = (TIMER_CBACK *)&bta_hf_client_colli_timer_cback; + bta_sys_start_timer(&bta_hf_client_cb.scb.colli_timer, 0, BTA_HF_CLIENT_COLLISION_TIMER); + bta_hf_client_cb.scb.colli_tmr_on = TRUE; + } +} + +/******************************************************************************* +** +** Function bta_hf_client_api_enable +** +** Description Handle an API enable event. +** +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_api_enable(tBTA_HF_CLIENT_DATA *p_data) +{ + /* initialize control block */ + memset(&bta_hf_client_cb, 0, sizeof(tBTA_HF_CLIENT_CB)); + + /* store callback function */ + bta_hf_client_cb.p_cback = p_data->api_enable.p_cback; + + /* check if mSBC support enabled */ +#if 0 // todo + char value[PROPERTY_VALUE_MAX]; + property_get("ro.bluetooth.hfp.ver", value, "0"); + if (strcmp(value, "1.6") == 0) { + bta_hf_client_cb.msbc_enabled = TRUE; + } +#else + bta_hf_client_cb.msbc_enabled = FALSE; +#endif + + bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD; + + /* set same setting as AG does */ + BTM_WriteVoiceSettings(AG_VOICE_SETTINGS); + + bta_sys_collision_register (BTA_ID_HS, bta_hf_client_collision_cback); + + /* call callback with enable event */ + (*bta_hf_client_cb.p_cback)(BTA_HF_CLIENT_ENABLE_EVT, NULL); +} + +/******************************************************************************* +** +** Function bta_hf_client_api_disable +** +** Description Handle an API disable event. +** +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_api_disable(tBTA_HF_CLIENT_DATA *p_data) +{ + if (!bta_sys_is_register (BTA_ID_HS)) { + APPL_TRACE_ERROR("BTA HF Client is already disabled, ignoring ..."); + return; + } + + /* De-register with BTA system manager */ + bta_sys_deregister(BTA_ID_HS); + + bta_hf_client_sm_execute(BTA_HF_CLIENT_API_DEREGISTER_EVT, p_data); + + bta_sys_collision_register (BTA_ID_HS, NULL); +} + +/******************************************************************************* +** +** Function bta_hf_client_hdl_event +** +** Description Data HF Client main event handling function. +** +** +** Returns BOOLEAN +** +*******************************************************************************/ +BOOLEAN bta_hf_client_hdl_event(BT_HDR *p_msg) +{ +#if BTA_HF_CLIENT_DEBUG == TRUE + APPL_TRACE_DEBUG("bta_hf_client_hdl_event %s (0x%x)", bta_hf_client_evt_str(p_msg->event), p_msg->event); +#endif + + switch (p_msg->event) { + /* handle enable event */ + case BTA_HF_CLIENT_API_ENABLE_EVT: + bta_hf_client_api_enable((tBTA_HF_CLIENT_DATA *) p_msg); + break; + + /* handle disable event */ + case BTA_HF_CLIENT_API_DISABLE_EVT: + bta_hf_client_api_disable((tBTA_HF_CLIENT_DATA *) p_msg); + break; + + default: + bta_hf_client_sm_execute(p_msg->event, (tBTA_HF_CLIENT_DATA *) p_msg); + break; + } + return TRUE; +} + +/******************************************************************************* +** +** Function bta_hf_client_sm_execute +** +** Description State machine event handling function for HF Client +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_sm_execute(UINT16 event, tBTA_HF_CLIENT_DATA *p_data) +{ + tBTA_HF_CLIENT_ST_TBL state_table; + UINT8 action; + int i; + +#if BTA_HF_CLIENT_DEBUG == TRUE + UINT16 in_event = event; + UINT8 in_state = bta_hf_client_cb.scb.state; + + /* Ignore displaying of AT results when not connected (Ignored in state machine) */ + if (bta_hf_client_cb.scb.state == BTA_HF_CLIENT_OPEN_ST) { + APPL_TRACE_EVENT("HF Client evt : State %d (%s), Event 0x%04x (%s)", + bta_hf_client_cb.scb.state, + bta_hf_client_state_str(bta_hf_client_cb.scb.state), + event, bta_hf_client_evt_str(event)); + } +#endif + + event &= 0x00FF; + if (event >= (BTA_HF_CLIENT_MAX_EVT & 0x00FF)) { + APPL_TRACE_ERROR("HF Client evt out of range, ignoring..."); + return; + } + + /* look up the state table for the current state */ + state_table = bta_hf_client_st_tbl[bta_hf_client_cb.scb.state]; + + /* set next state */ + bta_hf_client_cb.scb.state = state_table[event][BTA_HF_CLIENT_NEXT_STATE]; + + /* execute action functions */ + for (i = 0; i < BTA_HF_CLIENT_ACTIONS; i++) { + if ((action = state_table[event][i]) != BTA_HF_CLIENT_IGNORE) { + (*bta_hf_client_action[action])(p_data); + } else { + break; + } + } + +#if BTA_HF_CLIENT_DEBUG == TRUE + if (bta_hf_client_cb.scb.state != in_state) { + APPL_TRACE_EVENT("BTA HF Client State Change: [%s] -> [%s] after Event [%s]", + bta_hf_client_state_str(in_state), + bta_hf_client_state_str(bta_hf_client_cb.scb.state), + bta_hf_client_evt_str(in_event)); + } +#endif +} + +static void send_post_slc_cmd(void) +{ + bta_hf_client_cb.scb.at_cb.current_cmd = BTA_HF_CLIENT_AT_NONE; + + bta_hf_client_send_at_bia(); + bta_hf_client_send_at_ccwa(TRUE); + bta_hf_client_send_at_cmee(TRUE); + bta_hf_client_send_at_cops(FALSE); + bta_hf_client_send_at_btrh(TRUE, 0); + bta_hf_client_send_at_clip(TRUE); +} + +/******************************************************************************* +** +** Function bta_hf_client_slc_seq +** +** Description Handles AT commands sequence required for SLC creation +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_slc_seq(BOOLEAN error) +{ + APPL_TRACE_DEBUG("bta_hf_client_slc_seq cmd: %u", bta_hf_client_cb.scb.at_cb.current_cmd); + + if (error) { + /* SLC establishment error, sent close rfcomm event */ + APPL_TRACE_ERROR("HFPClient: Failed to create SLC due to AT error, disconnecting (%u)", + bta_hf_client_cb.scb.at_cb.current_cmd); + + bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL); + return; + } + + if (bta_hf_client_cb.scb.svc_conn) { + return; + } + + switch (bta_hf_client_cb.scb.at_cb.current_cmd) { + case BTA_HF_CLIENT_AT_NONE: + bta_hf_client_send_at_brsf(); + break; + + case BTA_HF_CLIENT_AT_BRSF: + if (bta_hf_client_cb.scb.peer_features & BTA_HF_CLIENT_PEER_CODEC) { + bta_hf_client_send_at_bac(); + break; + } + + bta_hf_client_send_at_cind(FALSE); + break; + + case BTA_HF_CLIENT_AT_BAC: + bta_hf_client_send_at_cind(FALSE); + break; + + case BTA_HF_CLIENT_AT_CIND: + bta_hf_client_send_at_cind(TRUE); + break; + + case BTA_HF_CLIENT_AT_CIND_STATUS: + bta_hf_client_send_at_cmer(TRUE); + break; + + case BTA_HF_CLIENT_AT_CMER: + if (bta_hf_client_cb.scb.peer_features & BTA_HF_CLIENT_PEER_FEAT_3WAY) { + bta_hf_client_send_at_chld('?', 0); + } else { + bta_hf_client_svc_conn_open(NULL); + send_post_slc_cmd(); + } + break; + + case BTA_HF_CLIENT_AT_CHLD: + bta_hf_client_svc_conn_open(NULL); + send_post_slc_cmd(); + break; + + default: + /* If happen there is a bug in SLC creation procedure... */ + APPL_TRACE_ERROR("HFPClient: Failed to create SLCdue to unexpected AT command, disconnecting (%u)", + bta_hf_client_cb.scb.at_cb.current_cmd); + + bta_hf_client_sm_execute(BTA_HF_CLIENT_API_CLOSE_EVT, NULL); + break; + } +} + +#if BTA_HF_CLIENT_DEBUG == TRUE + +#ifndef CASE_RETURN_STR +#define CASE_RETURN_STR(const) case const: return #const; +#endif + +static char *bta_hf_client_evt_str(UINT16 event) +{ + switch (event) { + CASE_RETURN_STR(BTA_HF_CLIENT_API_REGISTER_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_API_DEREGISTER_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_API_OPEN_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_API_CLOSE_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_API_AUDIO_OPEN_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_API_AUDIO_CLOSE_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_RFC_OPEN_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_RFC_CLOSE_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_RFC_SRV_CLOSE_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_RFC_DATA_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_DISC_ACP_RES_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_DISC_INT_RES_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_DISC_OK_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_DISC_FAIL_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_API_ENABLE_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_API_DISABLE_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_SCO_OPEN_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_SCO_CLOSE_EVT) + CASE_RETURN_STR(BTA_HF_CLIENT_SEND_AT_CMD_EVT) + default: + return "Unknown HF Client Event"; + } +} + +static char *bta_hf_client_state_str(UINT8 state) +{ + switch (state) { + CASE_RETURN_STR(BTA_HF_CLIENT_INIT_ST) + CASE_RETURN_STR(BTA_HF_CLIENT_OPENING_ST) + CASE_RETURN_STR(BTA_HF_CLIENT_OPEN_ST) + CASE_RETURN_STR(BTA_HF_CLIENT_CLOSING_ST) + default: + return "Unknown HF Client State"; + } +} +#endif +#endif /* #if (BTA_HF_INCLUDED == TRUE) */ diff --git a/components/bt/bluedroid/bta/hf_client/bta_hf_client_rfc.c b/components/bt/bluedroid/bta/hf_client/bta_hf_client_rfc.c new file mode 100644 index 0000000000..1b140dbd96 --- /dev/null +++ b/components/bt/bluedroid/bta/hf_client/bta_hf_client_rfc.c @@ -0,0 +1,246 @@ +/****************************************************************************** + * + * Copyright (c) 2014 The Android Open Source Project + * Copyright (C) 2004-2012 Broadcom Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +/****************************************************************************** + * + * This file contains the audio gateway functions controlling the RFCOMM + * connections. + * + ******************************************************************************/ + +#include +#include "common/bt_defs.h" +#include "bta/bta_api.h" +#include "bta_hf_client_int.h" +#include "stack/port_api.h" +#include "osi/allocator.h" + +#if (BTA_HF_INCLUDED == TRUE) +/******************************************************************************* +** +** Function bta_hf_client_port_cback +** +** Description RFCOMM Port callback +** +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_port_cback(UINT32 code, UINT16 port_handle) +{ + BT_HDR *p_buf; + UNUSED(code); + + /* ignore port events for port handles other than connected handle */ + if (port_handle != bta_hf_client_cb.scb.conn_handle) { + APPL_TRACE_DEBUG("bta_hf_client_port_cback ignoring handle:%d conn_handle = %d", + port_handle, bta_hf_client_cb.scb.conn_handle); + return; + } + + if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { + p_buf->event = BTA_HF_CLIENT_RFC_DATA_EVT; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function bta_hf_client_mgmt_cback +** +** Description RFCOMM management callback +** +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_mgmt_cback(UINT32 code, UINT16 port_handle) +{ + tBTA_HF_CLIENT_RFC *p_buf; + UINT16 event; + + APPL_TRACE_DEBUG("bta_hf_client_mgmt_cback : code = %d, port_handle = %d, conn_handle = %d, serv_handle = %d", + code, port_handle, bta_hf_client_cb.scb.conn_handle, bta_hf_client_cb.scb.serv_handle); + + /* ignore close event for port handles other than connected handle */ + if ((code != PORT_SUCCESS) && (port_handle != bta_hf_client_cb.scb.conn_handle)) { + APPL_TRACE_DEBUG("bta_hf_client_mgmt_cback ignoring handle:%d", port_handle); + return; + } + + if (code == PORT_SUCCESS) { + if ((bta_hf_client_cb.scb.conn_handle && (port_handle == bta_hf_client_cb.scb.conn_handle)) || /* outgoing connection */ + (port_handle == bta_hf_client_cb.scb.serv_handle)) { /* incoming connection */ + event = BTA_HF_CLIENT_RFC_OPEN_EVT; + } else { + APPL_TRACE_ERROR ("bta_hf_client_mgmt_cback: PORT_SUCCESS, ignoring handle = %d", port_handle); + return; + } + } + /* distinguish server close events */ + else if (port_handle == bta_hf_client_cb.scb.conn_handle) { + event = BTA_HF_CLIENT_RFC_CLOSE_EVT; + } else { + event = BTA_HF_CLIENT_RFC_SRV_CLOSE_EVT; + } + + if ((p_buf = (tBTA_HF_CLIENT_RFC *) osi_malloc(sizeof(tBTA_HF_CLIENT_RFC))) != NULL) { + p_buf->hdr.event = event; + p_buf->port_handle = port_handle; + bta_sys_sendmsg(p_buf); + } +} + +/******************************************************************************* +** +** Function bta_hf_client_setup_port +** +** Description Setup RFCOMM port for use by HF Client. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_setup_port(UINT16 handle) +{ + PORT_SetEventMask(handle, PORT_EV_RXCHAR); + PORT_SetEventCallback(handle, bta_hf_client_port_cback); +} + +/******************************************************************************* +** +** Function bta_hf_client_start_server +** +** Description Setup RFCOMM server for use by HF Client. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_start_server(void) +{ + int port_status; + + if (bta_hf_client_cb.scb.serv_handle > 0) { + APPL_TRACE_DEBUG("%s already started, handle: %d", __FUNCTION__, bta_hf_client_cb.scb.serv_handle); + return; + } + + BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HF_HANDSFREE, bta_hf_client_cb.scb.serv_sec_mask, + BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, bta_hf_client_cb.scn); + + port_status = RFCOMM_CreateConnection(UUID_SERVCLASS_HF_HANDSFREE, bta_hf_client_cb.scn, + TRUE, BTA_HF_CLIENT_MTU, (UINT8 *) bd_addr_any, &(bta_hf_client_cb.scb.serv_handle), + bta_hf_client_mgmt_cback); + + if (port_status == PORT_SUCCESS) { + bta_hf_client_setup_port(bta_hf_client_cb.scb.serv_handle); + } else { + /* TODO: can we handle this better? */ + APPL_TRACE_DEBUG("bta_hf_client_start_server: RFCOMM_CreateConnection returned error:%d", port_status); + } + + APPL_TRACE_DEBUG("bta_hf_client_start_server handle: %d", bta_hf_client_cb.scb.serv_handle); +} + +/******************************************************************************* +** +** Function bta_hf_client_close_server +** +** Description Close RFCOMM server port for use by HF Client. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_close_server(void) +{ + APPL_TRACE_DEBUG("%s %d", __FUNCTION__, bta_hf_client_cb.scb.serv_handle); + + if (bta_hf_client_cb.scb.serv_handle == 0) { + APPL_TRACE_DEBUG("%s already stopped", __FUNCTION__); + return; + } + + RFCOMM_RemoveServer(bta_hf_client_cb.scb.serv_handle); + bta_hf_client_cb.scb.serv_handle = 0; +} + +/******************************************************************************* +** +** Function bta_hf_client_rfc_do_open +** +** Description Open an RFCOMM connection to the peer device. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_rfc_do_open(tBTA_HF_CLIENT_DATA *p_data) +{ + BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HF_HANDSFREE, + bta_hf_client_cb.scb.cli_sec_mask, BT_PSM_RFCOMM, + BTM_SEC_PROTO_RFCOMM, bta_hf_client_cb.scb.peer_scn); + + if (RFCOMM_CreateConnection(UUID_SERVCLASS_HF_HANDSFREE, bta_hf_client_cb.scb.peer_scn, + FALSE, BTA_HF_CLIENT_MTU, bta_hf_client_cb.scb.peer_addr, &(bta_hf_client_cb.scb.conn_handle), + bta_hf_client_mgmt_cback) == PORT_SUCCESS) { + bta_hf_client_setup_port(bta_hf_client_cb.scb.conn_handle); + APPL_TRACE_DEBUG("bta_hf_client_rfc_do_open : conn_handle = %d", bta_hf_client_cb.scb.conn_handle); + } + /* RFCOMM create connection failed; send ourselves RFCOMM close event */ + else { + bta_hf_client_sm_execute(BTA_HF_CLIENT_RFC_CLOSE_EVT, p_data); + } +} + +/******************************************************************************* +** +** Function bta_hf_client_rfc_do_close +** +** Description Close RFCOMM connection. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_rfc_do_close(tBTA_HF_CLIENT_DATA *p_data) +{ + tBTA_HF_CLIENT_RFC *p_buf; + UNUSED(p_data); + + if (bta_hf_client_cb.scb.conn_handle) { + RFCOMM_RemoveConnection(bta_hf_client_cb.scb.conn_handle); + } else { + /* Close API was called while HF Client is in Opening state. */ + /* Need to trigger the state machine to send callback to the app */ + /* and move back to INIT state. */ + if ((p_buf = (tBTA_HF_CLIENT_RFC *) osi_malloc(sizeof(tBTA_HF_CLIENT_RFC))) != NULL) { + p_buf->hdr.event = BTA_HF_CLIENT_RFC_CLOSE_EVT; + bta_sys_sendmsg(p_buf); + } + + /* Cancel SDP if it had been started. */ + if (bta_hf_client_cb.scb.p_disc_db) { + (void)SDP_CancelServiceSearch (bta_hf_client_cb.scb.p_disc_db); + bta_hf_client_free_db(NULL); + } + } +} +#endif /* #if (BTA_HF_INCLUDED == TRUE) */ diff --git a/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c b/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c new file mode 100644 index 0000000000..744edc9179 --- /dev/null +++ b/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c @@ -0,0 +1,825 @@ +/****************************************************************************** + * + * Copyright (c) 2014 The Android Open Source Project + * Copyright (C) 2004-2012 Broadcom Corporation + * + * 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 "bta_hf_client_int.h" +#include "common/bt_trace.h" +#include +#include "common/bt_defs.h" +#include "common/bt_target.h" +#include "osi/allocator.h" +#if (BTM_SCO_HCI_INCLUDED == TRUE ) +#include "bta/bta_hf_client_co.h" +#include "hci/hci_audio.h" +#endif + +#if (BTA_HF_INCLUDED == TRUE) +#define BTA_HF_CLIENT_NO_EDR_ESCO (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | \ + BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \ + BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \ + BTM_SCO_PKT_TYPES_MASK_NO_3_EV5) + +static const tBTM_ESCO_PARAMS bta_hf_client_esco_params[] = { + /* SCO CVSD */ + { + .rx_bw = BTM_64KBITS_RATE, + .tx_bw = BTM_64KBITS_RATE, + .max_latency = 10, + .voice_contfmt = BTM_VOICE_SETTING_CVSD, + .packet_types = (BTM_SCO_LINK_ONLY_MASK | + BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | + BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | + BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | + BTM_SCO_PKT_TYPES_MASK_NO_3_EV5), + .retrans_effort = BTM_ESCO_RETRANS_POWER, + }, + /* ESCO CVSD */ + { + .rx_bw = BTM_64KBITS_RATE, + .tx_bw = BTM_64KBITS_RATE, + .max_latency = 10, + .voice_contfmt = BTM_VOICE_SETTING_CVSD, + /* Allow controller to use all types available except 5-slot EDR */ + .packet_types = (BTM_SCO_LINK_ALL_PKT_MASK | + BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | + BTM_SCO_PKT_TYPES_MASK_NO_3_EV5), + .retrans_effort = BTM_ESCO_RETRANS_POWER, + }, + /* ESCO mSBC */ + { + .rx_bw = BTM_64KBITS_RATE, + .tx_bw = BTM_64KBITS_RATE, + .max_latency = 13, + .voice_contfmt = BTM_VOICE_SETTING_TRANS, + /* Packet Types : EV3 + 2-EV3 */ + .packet_types = (BTM_SCO_PKT_TYPES_MASK_EV3 | + BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | + BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | + BTM_SCO_PKT_TYPES_MASK_NO_3_EV5), + .retrans_effort = BTM_ESCO_RETRANS_QUALITY, + } +}; + +enum { + BTA_HF_CLIENT_SCO_LISTEN_E, + BTA_HF_CLIENT_SCO_OPEN_E, /* open request */ + BTA_HF_CLIENT_SCO_CLOSE_E, /* close request */ + BTA_HF_CLIENT_SCO_SHUTDOWN_E, /* shutdown request */ + BTA_HF_CLIENT_SCO_CONN_OPEN_E, /* sco opened */ + BTA_HF_CLIENT_SCO_CONN_CLOSE_E, /* sco closed */ +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + BTA_HF_CLIENT_SCO_CI_DATA_E, /* sco data ready */ +#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) */ +}; + +static void bta_hf_client_sco_event(UINT8 event); +/******************************************************************************* +** +** Function bta_hf_client_remove_sco +** +** Description Removes the specified SCO from the system. +** If only_active is TRUE, then SCO is only removed if connected +** +** Returns BOOLEAN - TRUE if Sco removal was started +** +*******************************************************************************/ +static BOOLEAN bta_hf_client_sco_remove(BOOLEAN only_active) +{ + BOOLEAN removed_started = FALSE; + tBTM_STATUS status; + + APPL_TRACE_DEBUG("%s %d", __FUNCTION__, only_active); + + if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) { + status = BTM_RemoveSco(bta_hf_client_cb.scb.sco_idx); + + APPL_TRACE_DEBUG("%s idx 0x%04x, status:0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx, status); + + if (status == BTM_CMD_STARTED) { + removed_started = TRUE; + } + /* If no connection reset the sco handle */ + else if ( (status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR) ) { + bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX; + } + } + return removed_started; +} + +/******************************************************************************* +** +** Function bta_hf_client_cback_sco +** +** Description Call application callback function with SCO event. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_cback_sco(UINT8 event) +{ + tBTA_HF_CLIENT_HDR evt; + + memset(&evt, 0, sizeof(evt)); + + /* call app cback */ + (*bta_hf_client_cb.p_cback)(event, (tBTA_HF_CLIENT_HDR *) &evt); +} + +#if (BTM_SCO_HCI_INCLUDED == TRUE ) +/******************************************************************************* +** +** Function bta_hf_client_sco_read_cback +** +** Description Callback function is the callback function for incoming +** SCO data over HCI. +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_sco_read_cback (UINT16 sco_idx, BT_HDR *p_data, tBTM_SCO_DATA_FLAG status) +{ + if (status != BTM_SCO_DATA_CORRECT) + { + APPL_TRACE_DEBUG("%s: status(%d)", __FUNCTION__, status); + } + + bta_hf_client_sco_co_in_data (p_data, status); + osi_free(p_data); +} +#endif /* BTM_SCO_HCI_INCLUDED */ + +/******************************************************************************* +** +** Function bta_hf_client_sco_conn_rsp +** +** Description Process the SCO connection request +** +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_sco_conn_rsp(tBTM_ESCO_CONN_REQ_EVT_DATA *p_data) +{ + tBTM_ESCO_PARAMS resp; + UINT8 hci_status = HCI_SUCCESS; +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + tBTA_HFP_CODEC_INFO codec_info = {BTA_HFP_SCO_CODEC_PCM}; + UINT32 pcm_sample_rate; +#endif + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_LISTEN_ST) { + if (p_data->link_type == BTM_LINK_TYPE_SCO) { + resp = bta_hf_client_esco_params[0]; + } else { + resp = bta_hf_client_esco_params[bta_hf_client_cb.scb.negotiated_codec]; + } + + /* tell sys to stop av if any */ + bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); + +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + bta_hf_client_co_audio_state(bta_hf_client_cb.scb.sco_idx, SCO_STATE_SETUP, 0); + pcm_sample_rate = BTA_HFP_SCO_SAMP_RATE_8K; + + /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */ + BTM_ConfigScoPath(bta_hf_client_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, 0), + bta_hf_client_sco_read_cback, NULL, TRUE); +#endif + } else { + hci_status = HCI_ERR_HOST_REJECT_DEVICE; + } + + BTM_EScoConnRsp(p_data->sco_inx, hci_status, &resp); +} + +#if (BTM_SCO_HCI_INCLUDED == TRUE ) +/******************************************************************************* +** +** Function bta_ag_ci_sco_data +** +** Description Process the SCO data ready callin event +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_ci_sco_data(tBTA_HF_CLIENT_DATA *p_data) +{ + UNUSED(p_data); + bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CI_DATA_E); +} +#endif +/******************************************************************************* +** +** Function bta_hf_client_sco_connreq_cback +** +** Description BTM eSCO connection requests and eSCO change requests +** Only the connection requests are processed by BTA. +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_esco_connreq_cback(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data) +{ + APPL_TRACE_DEBUG("%s %d", __FUNCTION__, event); + + if (event != BTM_ESCO_CONN_REQ_EVT) { + return; + } + + /* TODO check remote bdaddr, should allow connect only from device with + * active SLC */ + + bta_hf_client_cb.scb.sco_idx = p_data->conn_evt.sco_inx; + + bta_hf_client_sco_conn_rsp(&p_data->conn_evt); + + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST; +} + +/******************************************************************************* +** +** Function bta_hf_client_sco_conn_cback +** +** Description BTM SCO connection callback. +** +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_sco_conn_cback(UINT16 sco_idx) +{ + BT_HDR *p_buf; + UINT8 *rem_bd; + + APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx); + + rem_bd = BTM_ReadScoBdAddr(sco_idx); + + if (rem_bd && bdcmp(bta_hf_client_cb.scb.peer_addr, rem_bd) == 0 && + bta_hf_client_cb.scb.svc_conn && bta_hf_client_cb.scb.sco_idx == sco_idx) { + if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { + p_buf->event = BTA_HF_CLIENT_SCO_OPEN_EVT; + p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle; + bta_sys_sendmsg(p_buf); + } + } + /* no match found; disconnect sco, init sco variables */ + else { + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; + BTM_RemoveSco(sco_idx); + } +} + +/******************************************************************************* +** +** Function bta_hf_client_sco_disc_cback +** +** Description BTM SCO disconnection callback. +** +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_sco_disc_cback(UINT16 sco_idx) +{ + BT_HDR *p_buf; + + APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx); + + if (bta_hf_client_cb.scb.sco_idx == sco_idx) { +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + tBTM_STATUS status = BTM_ConfigScoPath(BTM_SCO_ROUTE_PCM, NULL, NULL, TRUE); + APPL_TRACE_DEBUG("%s close config status = %d", __FUNCTION__, status); + /* SCO clean up here */ + bta_hf_client_sco_co_close(); +#endif + if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { + p_buf->event = BTA_HF_CLIENT_SCO_CLOSE_EVT; + p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle;; + bta_sys_sendmsg(p_buf); + } + } +} + +/******************************************************************************* +** +** Function bta_hf_client_create_sco +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_sco_create(BOOLEAN is_orig) +{ + tBTM_STATUS status; + UINT8 *p_bd_addr = NULL; + tBTM_ESCO_PARAMS params; +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + tBTM_SCO_ROUTE_TYPE sco_route; + tBTA_HFP_CODEC_INFO codec_info = {BTA_HFP_SCO_CODEC_PCM}; + UINT32 pcm_sample_rate; +#endif + APPL_TRACE_DEBUG("%s %d", __FUNCTION__, is_orig); + + /* Make sure this sco handle is not already in use */ + if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) { + APPL_TRACE_WARNING("%s: Index 0x%04x already in use", __FUNCTION__, + bta_hf_client_cb.scb.sco_idx); + return; + } + + params = bta_hf_client_esco_params[1]; + + /* if initiating set current scb and peer bd addr */ + if (is_orig) { + /* Attempt to use eSCO if remote host supports HFP >= 1.5 */ + if (bta_hf_client_cb.scb.peer_version >= HFP_VERSION_1_5 && !bta_hf_client_cb.scb.retry_with_sco_only) { + BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, ¶ms); + /* If ESCO or EDR ESCO, retry with SCO only in case of failure */ + if ((params.packet_types & BTM_ESCO_LINK_ONLY_MASK) + || !((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_HF_CLIENT_NO_EDR_ESCO)) { + bta_hf_client_cb.scb.retry_with_sco_only = TRUE; + APPL_TRACE_API("Setting retry_with_sco_only to TRUE"); + } + } else { + if (bta_hf_client_cb.scb.retry_with_sco_only) { + APPL_TRACE_API("retrying with SCO only"); + } + bta_hf_client_cb.scb.retry_with_sco_only = FALSE; + + BTM_SetEScoMode(BTM_LINK_TYPE_SCO, ¶ms); + } + + /* tell sys to stop av if any */ + bta_sys_sco_use(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); + +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + /* Allow any platform specific pre-SCO set up to take place */ + bta_hf_client_co_audio_state(bta_hf_client_cb.scb.sco_idx, SCO_STATE_SETUP, 0); + + pcm_sample_rate = BTA_HFP_SCO_SAMP_RATE_8K; + sco_route = bta_hf_client_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, 0); + + /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */ + BTM_ConfigScoPath(sco_route, bta_hf_client_sco_read_cback, NULL, TRUE); +#endif + + } else { + bta_hf_client_cb.scb.retry_with_sco_only = FALSE; + } + + p_bd_addr = bta_hf_client_cb.scb.peer_addr; + + status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types, + &bta_hf_client_cb.scb.sco_idx, bta_hf_client_sco_conn_cback, + bta_hf_client_sco_disc_cback); + if (status == BTM_CMD_STARTED && !is_orig) { + if (!BTM_RegForEScoEvts(bta_hf_client_cb.scb.sco_idx, bta_hf_client_esco_connreq_cback)) { + APPL_TRACE_DEBUG("%s SCO registration success", __FUNCTION__); + } + } + + APPL_TRACE_API("%s: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x", + __FUNCTION__, is_orig, bta_hf_client_cb.scb.sco_idx, + status, params.packet_types); +} + + +/******************************************************************************* +** +** Function bta_hf_client_sco_event +** +** Description Handle SCO events +** +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_sco_event(UINT8 event) +{ + APPL_TRACE_DEBUG("%s state: %d event: %d", __FUNCTION__, + bta_hf_client_cb.scb.sco_state, event); + +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + tBTA_HF_CLIENT_SCB *p_scb = &bta_hf_client_cb.scb; + BT_HDR *p_buf; +#endif + +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + if (event == BTA_HF_CLIENT_SCO_CI_DATA_E) { + uint16_t pkt_offset = 1 + HCI_SCO_PREAMBLE_SIZE; + uint16_t len_to_send = 0; + uint8_t *p; + while (true) + { + p_buf = osi_malloc(sizeof(BT_HDR) + pkt_offset + BTM_SCO_DATA_SIZE_MAX); + if (!p_buf) { + APPL_TRACE_WARNING("%s, no mem", __FUNCTION__); + break; + } + + p_buf->offset = pkt_offset; + len_to_send = bta_hf_client_sco_co_out_data(p_buf->data + pkt_offset, BTM_SCO_DATA_SIZE_MAX); + if (len_to_send) { + if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_OPEN_ST) { + p = (UINT8 *)(p_buf->data + pkt_offset -1); + *p = len_to_send; // set SCO packet length; + tBTM_STATUS write_stat = BTM_WriteScoData(p_scb->sco_idx, p_buf); + if (write_stat != BTM_SUCCESS && write_stat != BTM_SCO_BAD_LENGTH) { + break; + } + } else { + osi_free(p_buf); + } + } else { + osi_free(p_buf); + break; + } + } + + return; + } +#endif + + switch (bta_hf_client_cb.scb.sco_state) { + case BTA_HF_CLIENT_SCO_SHUTDOWN_ST: + switch (event) { + case BTA_HF_CLIENT_SCO_LISTEN_E: + /* create sco listen connection */ + bta_hf_client_sco_create(FALSE); + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; + break; + + default: + APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event %d", event); + break; + } + break; + + case BTA_HF_CLIENT_SCO_LISTEN_ST: + switch (event) { + case BTA_HF_CLIENT_SCO_LISTEN_E: + /* create sco listen connection (Additional channel) */ + bta_hf_client_sco_create(FALSE); + break; + + case BTA_HF_CLIENT_SCO_OPEN_E: + /* remove listening connection */ + bta_hf_client_sco_remove(FALSE); + + /* create sco connection to peer */ + bta_hf_client_sco_create(TRUE); + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST; + break; + + case BTA_HF_CLIENT_SCO_SHUTDOWN_E: + /* remove listening connection */ + bta_hf_client_sco_remove(FALSE); + + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; + break; + + case BTA_HF_CLIENT_SCO_CLOSE_E: + /* remove listening connection */ + /* Ignore the event. We need to keep listening SCO for the active SLC */ + APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event); + break; + + case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: + /* sco failed; create sco listen connection */ + bta_hf_client_sco_create(FALSE); + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; + break; + + default: + APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_LISTEN_ST: Ignoring event %d", event); + break; + } + break; + + case BTA_HF_CLIENT_SCO_OPENING_ST: + switch (event) { + case BTA_HF_CLIENT_SCO_CLOSE_E: + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_CL_ST; + break; + + case BTA_HF_CLIENT_SCO_SHUTDOWN_E: + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; + break; + + case BTA_HF_CLIENT_SCO_CONN_OPEN_E: + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPEN_ST; + break; + + case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: + /* sco failed; create sco listen connection */ + bta_hf_client_sco_create(FALSE); + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; + break; + + default: + APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPENING_ST: Ignoring event %d", event); + break; + } + break; + + case BTA_HF_CLIENT_SCO_OPEN_CL_ST: + switch (event) { + case BTA_HF_CLIENT_SCO_OPEN_E: + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST; + break; + + case BTA_HF_CLIENT_SCO_SHUTDOWN_E: + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; + break; + + case BTA_HF_CLIENT_SCO_CONN_OPEN_E: + /* close sco connection */ + bta_hf_client_sco_remove(TRUE); + + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST; + break; + + case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: + /* sco failed; create sco listen connection */ + + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; + break; + + default: + APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_CL_ST: Ignoring event %d", event); + break; + } + break; + + case BTA_HF_CLIENT_SCO_OPEN_ST: + switch (event) { + case BTA_HF_CLIENT_SCO_CLOSE_E: + /* close sco connection if active */ + if (bta_hf_client_sco_remove(TRUE)) { + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST; + } + break; + + case BTA_HF_CLIENT_SCO_SHUTDOWN_E: + /* remove all listening connections */ + bta_hf_client_sco_remove(FALSE); + + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; + break; + + case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: + /* peer closed sco; create sco listen connection */ + bta_hf_client_sco_create(FALSE); + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; + break; + + default: + APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_OPEN_ST: Ignoring event %d", event); + break; + } + break; + + case BTA_HF_CLIENT_SCO_CLOSING_ST: + switch (event) { + case BTA_HF_CLIENT_SCO_OPEN_E: + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSE_OP_ST; + break; + + case BTA_HF_CLIENT_SCO_SHUTDOWN_E: + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; + break; + + case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: + /* peer closed sco; create sco listen connection */ + bta_hf_client_sco_create(FALSE); + + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_LISTEN_ST; + break; + + default: + APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSING_ST: Ignoring event %d", event); + break; + } + break; + + case BTA_HF_CLIENT_SCO_CLOSE_OP_ST: + switch (event) { + case BTA_HF_CLIENT_SCO_CLOSE_E: + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_CLOSING_ST; + break; + + case BTA_HF_CLIENT_SCO_SHUTDOWN_E: + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTTING_ST; + break; + + case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: + /* open sco connection */ + bta_hf_client_sco_create(TRUE); + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_OPENING_ST; + break; + + default: + APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_CLOSE_OP_ST: Ignoring event %d", event); + break; + } + break; + + case BTA_HF_CLIENT_SCO_SHUTTING_ST: + switch (event) { + case BTA_HF_CLIENT_SCO_CONN_OPEN_E: + /* close sco connection; wait for conn close event */ + bta_hf_client_sco_remove(TRUE); + break; + + case BTA_HF_CLIENT_SCO_CONN_CLOSE_E: + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; + break; + + case BTA_HF_CLIENT_SCO_SHUTDOWN_E: + bta_hf_client_cb.scb.sco_state = BTA_HF_CLIENT_SCO_SHUTDOWN_ST; + break; + + default: + APPL_TRACE_WARNING("BTA_HF_CLIENT_SCO_SHUTTING_ST: Ignoring event %d", event); + break; + } + break; + + default: + break; + } +} + +/******************************************************************************* +** +** Function bta_hf_client_sco_listen +** +** Description Initialize SCO listener +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA *p_data) +{ + UNUSED(p_data); + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_LISTEN_E); +} + +/******************************************************************************* +** +** Function bta_hf_client_sco_shutdown +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA *p_data) +{ + UNUSED(p_data); + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_SHUTDOWN_E); +} + +/******************************************************************************* +** +** Function bta_hf_client_sco_conn_open +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA *p_data) +{ + UNUSED(p_data); + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_OPEN_E); + + bta_sys_sco_open(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); +#if (BTM_SCO_HCI_INCLUDED == TRUE) + bta_hf_client_co_audio_state(bta_hf_client_cb.scb.sco_idx, SCO_STATE_ON, 0); + /* open SCO codec if SCO is routed through transport */ + bta_hf_client_sco_co_open(bta_hf_client_cb.scb.sco_idx, BTA_HFP_SCO_OUT_PKT_SIZE, BTA_HF_CLIENT_CI_SCO_DATA_EVT); +#endif + + if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC) { + bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT); + } else { + bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_OPEN_EVT); + } + + bta_hf_client_cb.scb.retry_with_sco_only = FALSE; +} + +/******************************************************************************* +** +** Function bta_hf_client_sco_conn_close +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA *p_data) +{ + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + /* clear current scb */ + bta_hf_client_cb.scb.sco_idx = BTM_INVALID_SCO_INDEX; + + /* retry_with_sco_only, will be set only when initiator + ** and HFClient is first trying to establish an eSCO connection */ + if (bta_hf_client_cb.scb.retry_with_sco_only && bta_hf_client_cb.scb.svc_conn) { + bta_hf_client_sco_create(TRUE); + } else { + bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CONN_CLOSE_E); + + bta_sys_sco_close(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); + + bta_sys_sco_unuse(BTA_ID_HS, 1, bta_hf_client_cb.scb.peer_addr); + + /* call app callback */ + bta_hf_client_cback_sco(BTA_HF_CLIENT_AUDIO_CLOSE_EVT); + + if (bta_hf_client_cb.scb.sco_close_rfc == TRUE) { + bta_hf_client_cb.scb.sco_close_rfc = FALSE; + bta_hf_client_rfc_do_close(p_data); + } + } + bta_hf_client_cb.scb.retry_with_sco_only = FALSE; +} + +/******************************************************************************* +** +** Function bta_hf_client_sco_open +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA *p_data) +{ + UNUSED(p_data); + + APPL_TRACE_DEBUG("%s", __FUNCTION__); + + bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_OPEN_E); +} + +/******************************************************************************* +** +** Function bta_hf_client_sco_close +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA *p_data) +{ + UNUSED(p_data); + + APPL_TRACE_DEBUG("%s 0x%x", __FUNCTION__, bta_hf_client_cb.scb.sco_idx); + + if (bta_hf_client_cb.scb.sco_idx != BTM_INVALID_SCO_INDEX) { + bta_hf_client_sco_event(BTA_HF_CLIENT_SCO_CLOSE_E); + } +} + +#endif /* #if (BTA_HF_INCLUDED == TRUE) */ diff --git a/components/bt/bluedroid/bta/hf_client/bta_hf_client_sdp.c b/components/bt/bluedroid/bta/hf_client/bta_hf_client_sdp.c new file mode 100644 index 0000000000..920fcc9526 --- /dev/null +++ b/components/bt/bluedroid/bta/hf_client/bta_hf_client_sdp.c @@ -0,0 +1,367 @@ +/****************************************************************************** + * + * Copyright (c) 2014 The Android Open Source Project + * Copyright (C) 2003-2012 Broadcom Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +/****************************************************************************** + * + * This file contains the audio gateway functions performing SDP + * operations. + * + ******************************************************************************/ + +#include +#include "bta/bta_api.h" +#include "bta/bta_sys.h" +#include "common/bt_defs.h" +#include "bta/bta_hf_client_api.h" +#include "bta_hf_client_int.h" +#include "osi/allocator.h" + +#if (BTA_HF_INCLUDED == TRUE) +/* Number of protocol elements in protocol element list. */ +#define BTA_HF_CLIENT_NUM_PROTO_ELEMS 2 + +/* Number of elements in service class id list. */ +#define BTA_HF_CLIENT_NUM_SVC_ELEMS 2 + +/******************************************************************************* +** +** Function bta_hf_client_sdp_cback +** +** Description SDP callback function. +** +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_sdp_cback(UINT16 status) +{ + tBTA_HF_CLIENT_DISC_RESULT *p_buf; + UINT16 event; + + APPL_TRACE_DEBUG("bta_hf_client_sdp_cback status:0x%x", status); + + /* set event according to int/acp */ + if (bta_hf_client_cb.scb.role == BTA_HF_CLIENT_ACP) { + event = BTA_HF_CLIENT_DISC_ACP_RES_EVT; + } else { + event = BTA_HF_CLIENT_DISC_INT_RES_EVT; + } + + if ((p_buf = (tBTA_HF_CLIENT_DISC_RESULT *) osi_malloc(sizeof(tBTA_HF_CLIENT_DISC_RESULT))) != NULL) { + p_buf->hdr.event = event; + p_buf->status = status; + bta_sys_sendmsg(p_buf); + } +} + +/****************************************************************************** +** +** Function bta_hf_client_add_record +** +** Description This function is called by a server application to add +** HFP Client information to an SDP record. Prior to +** calling this function the application must call +** SDP_CreateRecord() to create an SDP record. +** +** Returns TRUE if function execution succeeded, +** FALSE if function execution failed. +** +******************************************************************************/ +BOOLEAN bta_hf_client_add_record(char *p_service_name, UINT8 scn, + tBTA_HF_CLIENT_FEAT features, UINT32 sdp_handle) +{ + tSDP_PROTOCOL_ELEM proto_elem_list[BTA_HF_CLIENT_NUM_PROTO_ELEMS]; + UINT16 svc_class_id_list[BTA_HF_CLIENT_NUM_SVC_ELEMS]; + UINT16 browse_list[] = {UUID_SERVCLASS_PUBLIC_BROWSE_GROUP}; + UINT16 version; + UINT16 profile_uuid; + BOOLEAN result = TRUE; + UINT8 buf[2]; + UINT16 sdp_features = 0; + + APPL_TRACE_DEBUG("bta_hf_client_add_record"); + + memset( proto_elem_list, 0 , BTA_HF_CLIENT_NUM_PROTO_ELEMS * sizeof(tSDP_PROTOCOL_ELEM)); + + /* add the protocol element sequence */ + proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP; + proto_elem_list[0].num_params = 0; + proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM; + proto_elem_list[1].num_params = 1; + proto_elem_list[1].params[0] = scn; + result &= SDP_AddProtocolList(sdp_handle, BTA_HF_CLIENT_NUM_PROTO_ELEMS, proto_elem_list); + + /* add service class id list */ + svc_class_id_list[0] = UUID_SERVCLASS_HF_HANDSFREE; + svc_class_id_list[1] = UUID_SERVCLASS_GENERIC_AUDIO; + result &= SDP_AddServiceClassIdList(sdp_handle, BTA_HF_CLIENT_NUM_SVC_ELEMS, svc_class_id_list); + + /* add profile descriptor list */ + profile_uuid = UUID_SERVCLASS_HF_HANDSFREE; + version = HFP_VERSION_1_6; + + result &= SDP_AddProfileDescriptorList(sdp_handle, profile_uuid, version); + + /* add service name */ + if (p_service_name != NULL && p_service_name[0] != 0) { + result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE, + (UINT32)(strlen(p_service_name) + 1), (UINT8 *) p_service_name); + } + + /* add features */ + if (features & BTA_HF_CLIENT_FEAT_ECNR) { + sdp_features |= BTA_HF_CLIENT_FEAT_ECNR; + } + + if (features & BTA_HF_CLIENT_FEAT_3WAY) { + sdp_features |= BTA_HF_CLIENT_FEAT_3WAY; + } + + if (features & BTA_HF_CLIENT_FEAT_CLI) { + sdp_features |= BTA_HF_CLIENT_FEAT_CLI; + } + + if (features & BTA_HF_CLIENT_FEAT_VREC) { + sdp_features |= BTA_HF_CLIENT_FEAT_VREC; + } + + if (features & BTA_HF_CLIENT_FEAT_VOL) { + sdp_features |= BTA_HF_CLIENT_FEAT_VOL; + } + + /* Codec bit position is different in SDP (bit 5) and in BRSF (bit 7) */ + if (features & BTA_HF_CLIENT_FEAT_CODEC) { + sdp_features |= 0x0020; + } + + UINT16_TO_BE_FIELD(buf, sdp_features); + result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE, 2, buf); + + /* add browse group list */ + result &= SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, browse_list); + + return result; +} + +/******************************************************************************* +** +** Function bta_hf_client_create_record +** +** Description Create SDP record for registered service. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_create_record(tBTA_HF_CLIENT_DATA *p_data) +{ + /* add sdp record if not already registered */ + if (bta_hf_client_cb.sdp_handle == 0) { + bta_hf_client_cb.sdp_handle = SDP_CreateRecord(); + bta_hf_client_cb.scn = BTM_AllocateSCN(); + bta_hf_client_add_record(p_data->api_register.name, + bta_hf_client_cb.scn, + p_data->api_register.features, + bta_hf_client_cb.sdp_handle); + + bta_sys_add_uuid(UUID_SERVCLASS_HF_HANDSFREE); + } + +} + +/******************************************************************************* +** +** Function bta_hf_client_del_record +** +** Description Delete SDP record for registered service. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_del_record(tBTA_HF_CLIENT_DATA *p_data) +{ + UNUSED(p_data); + + APPL_TRACE_DEBUG("bta_hf_client_del_record"); + + if (bta_hf_client_cb.sdp_handle != 0) { + SDP_DeleteRecord(bta_hf_client_cb.sdp_handle); + bta_hf_client_cb.sdp_handle = 0; + BTM_FreeSCN(bta_hf_client_cb.scn); + BTM_SecClrService(BTM_SEC_SERVICE_HF_HANDSFREE); + bta_sys_remove_uuid(UUID_SERVCLASS_HF_HANDSFREE); + } +} + +/******************************************************************************* +** +** Function bta_hf_client_sdp_find_attr +** +** Description Process SDP discovery results to find requested attribute +** +** +** Returns TRUE if results found, FALSE otherwise. +** +*******************************************************************************/ +BOOLEAN bta_hf_client_sdp_find_attr(void) +{ + tSDP_DISC_REC *p_rec = NULL; + tSDP_DISC_ATTR *p_attr; + tSDP_PROTOCOL_ELEM pe; + BOOLEAN result = FALSE; + + bta_hf_client_cb.scb.peer_version = HFP_VERSION_1_1; /* Default version */ + + /* loop through all records we found */ + while (TRUE) { + /* get next record; if none found, we're done */ + if ((p_rec = SDP_FindServiceInDb(bta_hf_client_cb.scb.p_disc_db, UUID_SERVCLASS_AG_HANDSFREE, p_rec)) == NULL) { + break; + } + + /* get scn from proto desc list if initiator */ + if (bta_hf_client_cb.scb.role == BTA_HF_CLIENT_INT) { + if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe)) { + bta_hf_client_cb.scb.peer_scn = (UINT8) pe.params[0]; + } else { + continue; + } + } + + /* get profile version (if failure, version parameter is not updated) */ + SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_HF_HANDSFREE, &bta_hf_client_cb.scb.peer_version); + + /* get features */ + if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_FEATURES)) != NULL) { + /* Found attribute. Get value. */ + /* There might be race condition between SDP and BRSF. */ + /* Do not update if we already received BRSF. */ + if (bta_hf_client_cb.scb.peer_features == 0) { + bta_hf_client_cb.scb.peer_features = p_attr->attr_value.v.u16; + + /* SDP and BRSF WBS bit are different, correct it if set */ + if (bta_hf_client_cb.scb.peer_features & 0x0020) { + bta_hf_client_cb.scb.peer_features &= ~0x0020; + bta_hf_client_cb.scb.peer_features |= BTA_HF_CLIENT_PEER_CODEC; + } + + /* get network for ability to reject calls */ + if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_NETWORK)) != NULL) { + if (p_attr->attr_value.v.u16 == 0x01) { + bta_hf_client_cb.scb.peer_features |= BTA_HF_CLIENT_PEER_REJECT; + } + } + } + } + + /* found what we needed */ + result = TRUE; + break; + } + + APPL_TRACE_DEBUG("%s peer_version=0x%x peer_features=0x%x", + __FUNCTION__, bta_hf_client_cb.scb.peer_version, + bta_hf_client_cb.scb.peer_features); + + return result; +} + +/******************************************************************************* +** +** Function bta_hf_client_do_disc +** +** Description Do service discovery. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_do_disc(void) +{ + tSDP_UUID uuid_list[2]; + UINT16 num_uuid = 1; + UINT16 attr_list[4]; + UINT8 num_attr; + BOOLEAN db_inited = FALSE; + + /* initiator; get proto list and features */ + if (bta_hf_client_cb.scb.role == BTA_HF_CLIENT_INT) { + attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST; + attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST; + attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST; + attr_list[3] = ATTR_ID_SUPPORTED_FEATURES; + num_attr = 4; + uuid_list[0].uu.uuid16 = UUID_SERVCLASS_AG_HANDSFREE; + } + /* acceptor; get features */ + else { + attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST; + attr_list[1] = ATTR_ID_BT_PROFILE_DESC_LIST; + attr_list[2] = ATTR_ID_SUPPORTED_FEATURES; + num_attr = 3; + uuid_list[0].uu.uuid16 = UUID_SERVCLASS_AG_HANDSFREE; + } + + /* allocate buffer for sdp database */ + bta_hf_client_cb.scb.p_disc_db = (tSDP_DISCOVERY_DB *) osi_malloc(BT_DEFAULT_BUFFER_SIZE); + + if (bta_hf_client_cb.scb.p_disc_db) { + /* set up service discovery database; attr happens to be attr_list len */ + uuid_list[0].len = LEN_UUID_16; + uuid_list[1].len = LEN_UUID_16; + db_inited = SDP_InitDiscoveryDb(bta_hf_client_cb.scb.p_disc_db, BT_DEFAULT_BUFFER_SIZE, num_uuid, + uuid_list, num_attr, attr_list); + } + + if (db_inited) { + /*Service discovery not initiated */ + db_inited = SDP_ServiceSearchAttributeRequest(bta_hf_client_cb.scb.peer_addr, + bta_hf_client_cb.scb.p_disc_db, bta_hf_client_sdp_cback); + } + + if (!db_inited) { + /*free discover db */ + bta_hf_client_free_db(NULL); + /* sent failed event */ + bta_hf_client_sm_execute(BTA_HF_CLIENT_DISC_FAIL_EVT, NULL); + } + +} + +/******************************************************************************* +** +** Function bta_hf_client_free_db +** +** Description Free discovery database. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_free_db(tBTA_HF_CLIENT_DATA *p_data) +{ + UNUSED(p_data); + + if (bta_hf_client_cb.scb.p_disc_db != NULL) { + osi_free(bta_hf_client_cb.scb.p_disc_db); + bta_hf_client_cb.scb.p_disc_db = NULL; + } +} +#endif /* #if (BTA_HF_INCLUDED == TRUE) */ diff --git a/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_at.h b/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_at.h new file mode 100644 index 0000000000..922e5e4548 --- /dev/null +++ b/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_at.h @@ -0,0 +1,117 @@ +/****************************************************************************** + * + * Copyright (c) 2014 The Android Open Source Project + * Copyright (C) 2003-2012 Broadcom Corporation + * + * 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. + * + ******************************************************************************/ + +/***************************************************************************** +** Data types +*****************************************************************************/ +#include "common/bt_target.h" +#if (BTA_HF_INCLUDED == TRUE) + +/* ASCII character string of arguments to the AT command */ +#define BTA_HF_CLIENT_AT_MAX_LEN 512 + +/* AT command table element */ +typedef struct { + const char *p_cmd; /* AT command string */ + UINT8 arg_type; /* allowable argument type syntax */ + UINT8 fmt; /* whether arg is int or string */ + UINT8 min; /* minimum value for int arg */ + INT16 max; /* maximum value for int arg */ +} tBTA_AG_AT_CMD; + +/* callback function executed when command is parsed */ +typedef void (tBTA_AG_AT_CMD_CBACK)(void *p_user, UINT16 cmd, UINT8 arg_type, + char *p_arg, INT16 int_arg); + +/* callback function executed to send "ERROR" result code */ +typedef void (tBTA_AG_AT_ERR_CBACK)(void *p_user, BOOLEAN unknown, char *p_arg); + +enum { + BTA_HF_CLIENT_AT_NONE, + BTA_HF_CLIENT_AT_BRSF, + BTA_HF_CLIENT_AT_BAC, + BTA_HF_CLIENT_AT_CIND, + BTA_HF_CLIENT_AT_CIND_STATUS, + BTA_HF_CLIENT_AT_CMER, + BTA_HF_CLIENT_AT_CHLD, + BTA_HF_CLIENT_AT_CMEE, + BTA_HF_CLIENT_AT_BIA, + BTA_HF_CLIENT_AT_CLIP, + BTA_HF_CLIENT_AT_CCWA, + BTA_HF_CLIENT_AT_COPS, + BTA_HF_CLIENT_AT_CLCC, + BTA_HF_CLIENT_AT_BVRA, + BTA_HF_CLIENT_AT_VGS, + BTA_HF_CLIENT_AT_VGM, + BTA_HF_CLIENT_AT_ATD, + BTA_HF_CLIENT_AT_BLDN, + BTA_HF_CLIENT_AT_ATA, + BTA_HF_CLIENT_AT_CHUP, + BTA_HF_CLIENT_AT_BTRH, + BTA_HF_CLIENT_AT_VTS, + BTA_HF_CLIENT_AT_BCC, + BTA_HF_CLIENT_AT_BCS, + BTA_HF_CLIENT_AT_CNUM, + BTA_HF_CLIENT_AT_NREC, + BTA_HF_CLIENT_AT_BINP, +}; + +typedef UINT8 tBTA_HF_CLIENT_AT_CMD; + +/* Maximum combined buffer for received AT events string */ +#define BTA_HF_CLIENT_AT_PARSER_MAX_LEN 4096 + +/* This structure holds prepared AT command queued for sending */ +struct queued_at_cmd { + tBTA_HF_CLIENT_AT_CMD cmd; + char buf[BTA_HF_CLIENT_AT_MAX_LEN]; + UINT16 buf_len; + struct queued_at_cmd *next; +}; +typedef struct queued_at_cmd tBTA_HF_CLIENT_AT_QCMD; + +/* Maximum number of indicators */ +#define BTA_HF_CLIENT_AT_INDICATOR_COUNT 20 + +/* AT command parsing control block */ +typedef struct { + char buf[BTA_HF_CLIENT_AT_PARSER_MAX_LEN + 1]; /* extra byte to always have \0 at the end */ + unsigned int offset; + tBTA_HF_CLIENT_AT_CMD current_cmd; + tBTA_HF_CLIENT_AT_QCMD *queued_cmd; + + TIMER_LIST_ENT resp_timer; /* AT response timer */ + BOOLEAN resp_timer_on; /* TRUE if AT response timer is active */ + + TIMER_LIST_ENT hold_timer; /* AT hold timer */ + BOOLEAN hold_timer_on; /* TRUE if AT hold timer is active */ + + /* CIND: lookup table to store the sequence of incoming indicators and their values + so when their values come later, we know which value in sequence match certain indicator */ + int indicator_lookup[BTA_HF_CLIENT_AT_INDICATOR_COUNT]; + +} tBTA_HF_CLIENT_AT_CB; + +/***************************************************************************** +** Functions +*****************************************************************************/ + +void bta_hf_client_at_init(void); +void bta_hf_client_at_reset(void); +#endif /* #if (BTA_HF_INCLUDED == TRUE) */ diff --git a/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_int.h b/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_int.h new file mode 100644 index 0000000000..2e3fab9c1b --- /dev/null +++ b/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_int.h @@ -0,0 +1,296 @@ +/****************************************************************************** + * + * Copyright (c) 2014 The Android Open Source Project + * Copyright (C) 2003-2012 Broadcom Corporation + * + * 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 "bta/bta_sys.h" +#include "bta/bta_api.h" +#include "bta/bta_hf_client_api.h" +#include "bta_hf_client_at.h" + +#if (BTA_HF_INCLUDED == TRUE) +/***************************************************************************** +** Constants +*****************************************************************************/ +#define HFP_VERSION_1_1 0x0101 +#define HFP_VERSION_1_5 0x0105 +#define HFP_VERSION_1_6 0x0106 + +/* RFCOMM MTU SIZE */ +#define BTA_HF_CLIENT_MTU 256 + +/* profile role for connection */ +#define BTA_HF_CLIENT_ACP 0 /* accepted connection */ +#define BTA_HF_CLIENT_INT 1 /* initiating connection */ + +/* Timer to wait for retry in case of collision */ +#ifndef BTA_HF_CLIENT_COLLISION_TIMER +#define BTA_HF_CLIENT_COLLISION_TIMER 2411 +#endif + +enum { + /* these events are handled by the state machine */ + BTA_HF_CLIENT_API_REGISTER_EVT = BTA_SYS_EVT_START(BTA_ID_HS), + BTA_HF_CLIENT_API_DEREGISTER_EVT, + BTA_HF_CLIENT_API_OPEN_EVT, + BTA_HF_CLIENT_API_CLOSE_EVT, + BTA_HF_CLIENT_API_AUDIO_OPEN_EVT, + BTA_HF_CLIENT_API_AUDIO_CLOSE_EVT, + BTA_HF_CLIENT_RFC_OPEN_EVT, + BTA_HF_CLIENT_RFC_CLOSE_EVT, + BTA_HF_CLIENT_RFC_SRV_CLOSE_EVT, + BTA_HF_CLIENT_RFC_DATA_EVT, + BTA_HF_CLIENT_DISC_ACP_RES_EVT, + BTA_HF_CLIENT_DISC_INT_RES_EVT, + BTA_HF_CLIENT_DISC_OK_EVT, + BTA_HF_CLIENT_DISC_FAIL_EVT, + BTA_HF_CLIENT_SCO_OPEN_EVT, + BTA_HF_CLIENT_SCO_CLOSE_EVT, + BTA_HF_CLIENT_SEND_AT_CMD_EVT, +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + BTA_HF_CLIENT_CI_SCO_DATA_EVT, +#endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */ + BTA_HF_CLIENT_MAX_EVT, + + /* these events are handled outside of the state machine */ + BTA_HF_CLIENT_API_ENABLE_EVT, + BTA_HF_CLIENT_API_DISABLE_EVT +}; + +/***************************************************************************** +** Data types +*****************************************************************************/ + +/* data type for BTA_HF_CLIENT_API_ENABLE_EVT */ +typedef struct { + BT_HDR hdr; + tBTA_HF_CLIENT_CBACK *p_cback; +} tBTA_HF_CLIENT_API_ENABLE; + +/* data type for BTA_HF_CLIENT_API_REGISTER_EVT */ +typedef struct { + BT_HDR hdr; + tBTA_HF_CLIENT_CBACK *p_cback; + tBTA_SEC sec_mask; + tBTA_HF_CLIENT_FEAT features; + char name[BTA_SERVICE_NAME_LEN + 1]; +} tBTA_HF_CLIENT_API_REGISTER; + +/* data type for BTA_HF_CLIENT_API_OPEN_EVT */ +typedef struct { + BT_HDR hdr; + BD_ADDR bd_addr; + tBTA_SEC sec_mask; +} tBTA_HF_CLIENT_API_OPEN; + +/* data type for BTA_HF_CLIENT_DISC_RESULT_EVT */ +typedef struct { + BT_HDR hdr; + UINT16 status; +} tBTA_HF_CLIENT_DISC_RESULT; + +/* data type for RFCOMM events */ +typedef struct { + BT_HDR hdr; + UINT16 port_handle; +} tBTA_HF_CLIENT_RFC; + +/* generic purpose data type for other events */ +typedef struct { + BT_HDR hdr; + BOOLEAN bool_val; + UINT8 uint8_val; + UINT32 uint32_val1; + UINT32 uint32_val2; + char str[BTA_HF_CLIENT_NUMBER_LEN + 1]; +} tBTA_HF_CLIENT_DATA_VAL; + +/* union of all event datatypes */ +typedef union { + BT_HDR hdr; + tBTA_HF_CLIENT_API_ENABLE api_enable; + tBTA_HF_CLIENT_API_REGISTER api_register; + tBTA_HF_CLIENT_API_OPEN api_open; + tBTA_HF_CLIENT_DISC_RESULT disc_result; + tBTA_HF_CLIENT_RFC rfc; + tBTA_HF_CLIENT_DATA_VAL val; + +} tBTA_HF_CLIENT_DATA; + +/* type for each service control block */ +typedef struct { + UINT16 serv_handle; /* RFCOMM server handle */ + BD_ADDR peer_addr; /* peer bd address */ + tSDP_DISCOVERY_DB *p_disc_db; /* pointer to discovery database */ + UINT16 conn_handle; /* RFCOMM handle of connected service */ + tBTA_SEC serv_sec_mask; /* server security mask */ + tBTA_SEC cli_sec_mask; /* client security mask */ + tBTA_HF_CLIENT_FEAT features; /* features registered by application */ + tBTA_HF_CLIENT_PEER_FEAT peer_features; /* peer device features */ + tBTA_HF_CLIENT_CHLD_FEAT chld_features; /* call handling features */ + UINT16 peer_version; /* profile version of peer device */ + UINT8 peer_scn; /* peer scn */ + UINT8 role; /* initiator/acceptor role */ + UINT16 sco_idx; /* SCO handle */ + UINT8 sco_state; /* SCO state variable */ + BOOLEAN sco_close_rfc; /* TRUE if also close RFCOMM after SCO */ + BOOLEAN retry_with_sco_only; + BOOLEAN deregister; /* TRUE if service shutting down */ + BOOLEAN svc_conn; /* set to TRUE when service level connection is up */ + BOOLEAN send_at_reply; /* set to TRUE to notify framework about AT results */ + tBTA_HF_CLIENT_AT_CB at_cb; /* AT Parser control block */ + UINT8 state; /* state machine state */ + tBTM_SCO_CODEC_TYPE negotiated_codec; /* negotiated codec */ + TIMER_LIST_ENT colli_timer; /* Collision timer */ + BOOLEAN colli_tmr_on; /* TRUE if collision timer is active */ +} tBTA_HF_CLIENT_SCB; + +/* sco states */ +enum { + BTA_HF_CLIENT_SCO_SHUTDOWN_ST, /* no listening, no connection */ + BTA_HF_CLIENT_SCO_LISTEN_ST, /* listening */ + BTA_HF_CLIENT_SCO_OPENING_ST, /* connection opening */ + BTA_HF_CLIENT_SCO_OPEN_CL_ST, /* opening connection being closed */ + BTA_HF_CLIENT_SCO_OPEN_ST, /* open */ + BTA_HF_CLIENT_SCO_CLOSING_ST, /* closing */ + BTA_HF_CLIENT_SCO_CLOSE_OP_ST, /* closing sco being opened */ + BTA_HF_CLIENT_SCO_SHUTTING_ST /* sco shutting down */ +}; + +/* type for AG control block */ +typedef struct { + tBTA_HF_CLIENT_SCB scb; /* service control block */ + UINT32 sdp_handle; + UINT8 scn; + tBTA_HF_CLIENT_CBACK *p_cback; /* application callback */ + BOOLEAN msbc_enabled; +} tBTA_HF_CLIENT_CB; + +/***************************************************************************** +** Global data +*****************************************************************************/ + +/* control block declaration */ +#if BTA_DYNAMIC_MEMORY == FALSE +extern tBTA_HF_CLIENT_CB bta_hf_client_cb; +#else +extern tBTA_HF_CLIENT_CB *bta_hf_client_cb_ptr; +#define bta_hf_client_cb (*bta_hf_client_cb_ptr) +#endif + +/***************************************************************************** +** Function prototypes +*****************************************************************************/ + +/* main functions */ +extern void bta_hf_client_scb_init(void); +extern void bta_hf_client_scb_disable(void); +extern BOOLEAN bta_hf_client_hdl_event(BT_HDR *p_msg); +extern void bta_hf_client_sm_execute(UINT16 event, + tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_slc_seq(BOOLEAN error); +extern void bta_hf_client_collision_cback (tBTA_SYS_CONN_STATUS status, UINT8 id, + UINT8 app_id, BD_ADDR peer_addr); +extern void bta_hf_client_resume_open (); + +/* SDP functions */ +extern BOOLEAN bta_hf_client_add_record(char *p_service_name, + UINT8 scn, tBTA_HF_CLIENT_FEAT features, + UINT32 sdp_handle); +extern void bta_hf_client_create_record(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_del_record(tBTA_HF_CLIENT_DATA *p_data); +extern BOOLEAN bta_hf_client_sdp_find_attr(void); +extern void bta_hf_client_do_disc(void); +extern void bta_hf_client_free_db(tBTA_HF_CLIENT_DATA *p_data); + +/* RFCOMM functions */ +extern void bta_hf_client_setup_port(UINT16 handle); +extern void bta_hf_client_start_server(void); +extern void bta_hf_client_close_server(void); +extern void bta_hf_client_rfc_do_open(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_rfc_do_close(tBTA_HF_CLIENT_DATA *p_data); + +/* SCO functions */ +extern void bta_hf_client_sco_listen(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_sco_shutdown(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_sco_conn_close(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_sco_open(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_sco_close(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_cback_sco(UINT8 event); + +/* AT command functions */ +extern void bta_hf_client_at_parse(char *buf, unsigned int len); +extern void bta_hf_client_send_at_brsf(void); +extern void bta_hf_client_send_at_bac(void); +extern void bta_hf_client_send_at_cind(BOOLEAN status); +extern void bta_hf_client_send_at_cmer(BOOLEAN activate); +extern void bta_hf_client_send_at_chld(char cmd, UINT32 idx); +extern void bta_hf_client_send_at_clip(BOOLEAN activate); +extern void bta_hf_client_send_at_ccwa(BOOLEAN activate); +extern void bta_hf_client_send_at_cmee(BOOLEAN activate); +extern void bta_hf_client_send_at_cops(BOOLEAN query); +extern void bta_hf_client_send_at_clcc(void); +extern void bta_hf_client_send_at_bvra(BOOLEAN enable); +extern void bta_hf_client_send_at_vgs(UINT32 volume); +extern void bta_hf_client_send_at_vgm(UINT32 volume); +extern void bta_hf_client_send_at_atd(char *number, UINT32 memory); +extern void bta_hf_client_send_at_bldn(void); +extern void bta_hf_client_send_at_ata(void); +extern void bta_hf_client_send_at_chup(void); +extern void bta_hf_client_send_at_btrh(BOOLEAN query, UINT32 val); +extern void bta_hf_client_send_at_vts(char code); +extern void bta_hf_client_send_at_bcc(void); +extern void bta_hf_client_send_at_bcs(UINT32 codec); +extern void bta_hf_client_send_at_cnum(void); +extern void bta_hf_client_send_at_nrec(void); +extern void bta_hf_client_send_at_binp(UINT32 action); +extern void bta_hf_client_send_at_bia(void); + +/* Action functions */ +extern void bta_hf_client_register(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_deregister(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_start_dereg(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_start_close(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_start_open(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_rfc_acp_open(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_rfc_open(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_rfc_fail(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_disc_fail(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_open_fail(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_rfc_close(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_disc_acp_res(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_rfc_data(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_disc_int_res(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_svc_conn_open(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_ind(tBTA_HF_CLIENT_IND_TYPE type, UINT16 value); +extern void bta_hf_client_evt_val(tBTA_HF_CLIENT_EVT type, UINT16 value); +extern void bta_hf_client_operator_name(char *name); +extern void bta_hf_client_clip(char *number); +extern void bta_hf_client_ccwa(char *number); +extern void bta_hf_client_at_result(tBTA_HF_CLIENT_AT_RESULT_TYPE type, UINT16 cme); +extern void bta_hf_client_clcc(UINT32 idx, BOOLEAN incoming, UINT8 status, BOOLEAN mpty, char *number); +extern void bta_hf_client_cnum(char *number, UINT16 service); +extern void bta_hf_client_binp(char *number); + +/* Commands handling functions */ +extern void bta_hf_client_dial(tBTA_HF_CLIENT_DATA *p_data); +extern void bta_hf_client_send_at_cmd(tBTA_HF_CLIENT_DATA *p_data); +#if (BTM_SCO_HCI_INCLUDED == TRUE ) +extern void bta_hf_client_ci_sco_data(tBTA_HF_CLIENT_DATA *p_data); +#endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */ +#endif /* #if (BTA_HF_INCLUDED == TRUE) */ diff --git a/components/bt/bluedroid/bta/include/bta/bta_dm_ci.h b/components/bt/bluedroid/bta/include/bta/bta_dm_ci.h index 90565aac85..cd15c86c31 100644 --- a/components/bt/bluedroid/bta/include/bta/bta_dm_ci.h +++ b/components/bt/bluedroid/bta/include/bta/bta_dm_ci.h @@ -61,18 +61,6 @@ extern void bta_dm_ci_io_req(BD_ADDR bd_addr, tBTA_IO_CAP io_cap, *******************************************************************************/ extern void bta_dm_ci_rmt_oob(BOOLEAN accept, BD_ADDR bd_addr, BT_OCTET16 c, BT_OCTET16 r); -/******************************************************************************* -** -** Function bta_dm_sco_ci_data_ready -** -** Description This function sends an event to indicating that the phone -** has SCO data ready.. -** -** Returns void -** -*******************************************************************************/ -extern void bta_dm_sco_ci_data_ready(UINT16 event, UINT16 sco_handle); - #ifdef __cplusplus } #endif diff --git a/components/bt/bluedroid/bta/include/bta/bta_dm_co.h b/components/bt/bluedroid/bta/include/bta/bta_dm_co.h index 7d62857191..1f1f648a9f 100644 --- a/components/bt/bluedroid/bta/include/bta/bta_dm_co.h +++ b/components/bt/bluedroid/bta/include/bta/bta_dm_co.h @@ -26,29 +26,6 @@ #include "bta/bta_sys.h" - -#ifndef BTA_SCO_OUT_PKT_SIZE -#define BTA_SCO_OUT_PKT_SIZE BTM_SCO_DATA_SIZE_MAX -#endif - -#define BTA_SCO_CODEC_PCM 0 /* used for regular SCO */ -#define BTA_SCO_CODEC_SBC 1 /* used for WBS */ -typedef UINT8 tBTA_SCO_CODEC_TYPE; - -#define BTA_DM_SCO_SAMP_RATE_8K 8000 -#define BTA_DM_SCO_SAMP_RATE_16K 16000 - -/* SCO codec information */ -typedef struct { - tBTA_SCO_CODEC_TYPE codec_type; -} tBTA_CODEC_INFO; - -#define BTA_DM_SCO_ROUTE_PCM BTM_SCO_ROUTE_PCM -#define BTA_DM_SCO_ROUTE_HCI BTM_SCO_ROUTE_HCI - -typedef tBTM_SCO_ROUTE_TYPE tBTA_DM_SCO_ROUTE_TYPE; - - /***************************************************************************** ** Function Declarations *****************************************************************************/ @@ -135,72 +112,6 @@ extern void bta_dm_co_loc_oob(BOOLEAN valid, BT_OCTET16 c, BT_OCTET16 r); *******************************************************************************/ extern void bta_dm_co_rmt_oob(BD_ADDR bd_addr); -/***************************************************************************** -** SCO over HCI Function Declarations -*****************************************************************************/ -/******************************************************************************* -** -** Function bta_dm_sco_co_init -** -** Description This function can be used by the phone to initialize audio -** codec or for other initialization purposes before SCO connection -** is opened. -** -** -** Returns Void. -** -*******************************************************************************/ -extern tBTA_DM_SCO_ROUTE_TYPE bta_dm_sco_co_init(UINT32 rx_bw, UINT32 tx_bw, - tBTA_CODEC_INFO *p_codec_info, UINT8 app_id); - - -/******************************************************************************* -** -** Function bta_dm_sco_co_open -** -** Description This function is executed when a SCO connection is open. -** -** -** Returns void -** -*******************************************************************************/ -extern void bta_dm_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event); - -/******************************************************************************* -** -** Function bta_dm_sco_co_close -** -** Description This function is called when a SCO connection is closed -** -** -** Returns void -** -*******************************************************************************/ -extern void bta_dm_sco_co_close(void); - -/******************************************************************************* -** -** Function bta_dm_sco_co_out_data -** -** Description This function is called to send SCO data over HCI. -** -** Returns void -** -*******************************************************************************/ -extern void bta_dm_sco_co_out_data(BT_HDR **p_buf); - -/******************************************************************************* -** -** Function bta_dm_sco_co_in_data -** -** Description This function is called to send incoming SCO data to application. -** -** Returns void -** -*******************************************************************************/ -extern void bta_dm_sco_co_in_data(BT_HDR *p_buf, tBTM_SCO_DATA_FLAG status); - - /******************************************************************************* ** diff --git a/components/bt/bluedroid/bta/include/bta/bta_hf_client_api.h b/components/bt/bluedroid/bta/include/bta/bta_hf_client_api.h new file mode 100644 index 0000000000..ade9f63f28 --- /dev/null +++ b/components/bt/bluedroid/bta/include/bta/bta_hf_client_api.h @@ -0,0 +1,378 @@ +/****************************************************************************** + * + * Copyright (c) 2014 The Android Open Source Project + * Copyright (C) 2003-2012 Broadcom Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +/****************************************************************************** + * + * This is the public interface file for the handsfree (HF role) subsystem + * + ******************************************************************************/ +#ifndef BTA_HF_CLIENT_API_H +#define BTA_HF_CLIENT_API_H + +#include "bta_api.h" +#include "bta_hfp_defs.h" + +#if (BTA_HF_INCLUDED == TRUE) +/***************************************************************************** +** Constants and data types +*****************************************************************************/ + +/* HFP peer (AG) features*/ +#define BTA_HF_CLIENT_PEER_FEAT_3WAY 0x00000001 /* Three-way calling */ +#define BTA_HF_CLIENT_PEER_FEAT_ECNR 0x00000002 /* Echo cancellation and/or noise reduction */ +#define BTA_HF_CLIENT_PEER_FEAT_VREC 0x00000004 /* Voice recognition */ +#define BTA_HF_CLIENT_PEER_INBAND 0x00000008 /* In-band ring tone */ +#define BTA_HF_CLIENT_PEER_VTAG 0x00000010 /* Attach a phone number to a voice tag */ +#define BTA_HF_CLIENT_PEER_REJECT 0x00000020 /* Ability to reject incoming call */ +#define BTA_HF_CLIENT_PEER_ECS 0x00000040 /* Enhanced Call Status */ +#define BTA_HF_CLIENT_PEER_ECC 0x00000080 /* Enhanced Call Control */ +#define BTA_HF_CLIENT_PEER_EXTERR 0x00000100 /* Extended error codes */ +#define BTA_HF_CLIENT_PEER_CODEC 0x00000200 /* Codec Negotiation */ + +typedef UINT16 tBTA_HF_CLIENT_PEER_FEAT; + +/* HFP HF features */ +#define BTA_HF_CLIENT_FEAT_ECNR 0x00000001 /* Echo cancellation and/or noise reduction */ +#define BTA_HF_CLIENT_FEAT_3WAY 0x00000002 /* Call waiting and three-way calling */ +#define BTA_HF_CLIENT_FEAT_CLI 0x00000004 /* Caller ID presentation capability */ +#define BTA_HF_CLIENT_FEAT_VREC 0x00000008 /* Voice recognition activation */ +#define BTA_HF_CLIENT_FEAT_VOL 0x00000010 /* Remote volume control */ +#define BTA_HF_CLIENT_FEAT_ECS 0x00000020 /* Enhanced Call Status */ +#define BTA_HF_CLIENT_FEAT_ECC 0x00000040 /* Enhanced Call Control */ +#define BTA_HF_CLIENT_FEAT_CODEC 0x00000080 /* Codec Negotiation */ + +/* HFP HF extended call handling - masks not related to any spec */ +#define BTA_HF_CLIENT_CHLD_REL 0x00000001 /* 0 Release waiting call or held calls */ +#define BTA_HF_CLIENT_CHLD_REL_ACC 0x00000002 /* 1 Release active calls and accept other (waiting or held) cal */ +#define BTA_HF_CLIENT_CHLD_REL_X 0x00000004 /* 1x Release x call*/ +#define BTA_HF_CLIENT_CHLD_HOLD_ACC 0x00000008 /* 2 Active calls on hold and accept other call */ +#define BTA_HF_CLIENT_CHLD_PRIV_X 0x00000010 /* 2x Active multiparty call on hold except call x */ +#define BTA_HF_CLIENT_CHLD_MERGE 0x00000020 /* 3 Add held call to multiparty */ +#define BTA_HF_CLIENT_CHLD_MERGE_DETACH 0x00000040 /* 4 Add held call to multiparty */ + +typedef UINT16 tBTA_HF_CLIENT_CHLD_FEAT; + +/* HFP AG errors ot OK sent to HF Unit */ +#define BTA_HF_CLIENT_AT_RESULT_OK 0 +#define BTA_HF_CLIENT_AT_RESULT_ERROR 1 +#define BTA_HF_CLIENT_AT_RESULT_NO_CARRIER 2 +#define BTA_HF_CLIENT_AT_RESULT_BUSY 3 +#define BTA_HF_CLIENT_AT_RESULT_NO_ANSWER 4 +#define BTA_HF_CLIENT_AT_RESULT_DELAY 5 +#define BTA_HF_CLIENT_AT_RESULT_BLACKLISTED 6 +#define BTA_HF_CLIENT_AT_RESULT_CME 7 + +typedef UINT8 tBTA_HF_CLIENT_AT_RESULT_TYPE; + +/* HF Client callback events */ +#define BTA_HF_CLIENT_ENABLE_EVT 0 /* HF Client enabled */ +#define BTA_HF_CLIENT_REGISTER_EVT 1 /* HF Client registered */ +#define BTA_HF_CLIENT_OPEN_EVT 2 /* HF Client connection open */ +#define BTA_HF_CLIENT_CLOSE_EVT 3 /* HF Client connection closed */ +#define BTA_HF_CLIENT_CONN_EVT 4 /* Service level connection opened */ +#define BTA_HF_CLIENT_AUDIO_OPEN_EVT 5 /* Audio connection open */ +#define BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT 6 /* Audio connection with mSBC codec open */ +#define BTA_HF_CLIENT_AUDIO_CLOSE_EVT 7 /* Audio connection closed */ +#define BTA_HF_CLIENT_SPK_EVT 8 /* Speaker volume changed */ +#define BTA_HF_CLIENT_MIC_EVT 9 /* Microphone volume changed */ +#define BTA_HF_CLIENT_IND_EVT 10 /* Indicator */ +#define BTA_HF_CLIENT_VOICE_REC_EVT 11 /* AG changed voice recognition setting */ +#define BTA_HF_CLIENT_OPERATOR_NAME_EVT 12 /* Operator name acquired */ +#define BTA_HF_CLIENT_CLIP_EVT 13 /* Calling line identification event */ +#define BTA_HF_CLIENT_CCWA_EVT 14 /* Call waiting notification */ +#define BTA_HF_CLIENT_AT_RESULT_EVT 15 /* Call waiting notification */ +#define BTA_HF_CLIENT_CLCC_EVT 16 /* current call event */ +#define BTA_HF_CLIENT_CNUM_EVT 17 /* subscriber information event */ +#define BTA_HF_CLIENT_BTRH_EVT 18 /* bluetooth response and hold event */ +#define BTA_HF_CLIENT_BSIR_EVT 19 /* in-band ring tone setting changed event */ +#define BTA_HF_CLIENT_BINP_EVT 20 /* binp number event */ +#define BTA_HF_CLIENT_RING_INDICATION 21 /* HF Client ring indication */ +#define BTA_HF_CLIENT_DISABLE_EVT 30 /* HF Client disabled */ + +typedef UINT8 tBTA_HF_CLIENT_EVT; + +/* HF Client open status */ +#define BTA_HF_CLIENT_SUCCESS 0 /* Connection successfully opened */ +#define BTA_HF_CLIENT_FAIL_SDP 1 /* Open failed due to SDP */ +#define BTA_HF_CLIENT_FAIL_RFCOMM 2 /* Open failed due to RFCOMM */ +#define BTA_HF_CLIENT_FAIL_RESOURCES 3 /* out of resources failure */ + +typedef UINT8 tBTA_HF_CLIENT_STATUS; + +/* indicator type */ +#define BTA_HF_CLIENT_IND_BATTCH 0 /* Battery charge indicator */ +#define BTA_HF_CLIENT_IND_SIGNAL 1 /* Signal Strength indicator */ +#define BTA_HF_CLIENT_IND_SERVICE 2 /* Service availability indicator */ +#define BTA_HF_CLIENT_IND_CALL 3 /* Standard call status indicator*/ +#define BTA_HF_CLIENT_IND_ROAM 4 /* Roaming status indicator */ +#define BTA_HF_CLIENT_IND_CALLSETUP 5 /* Call setup status indicator */ +#define BTA_HF_CLIENT_IND_CALLHELD 6 /* Call hold status indicator */ + +typedef UINT8 tBTA_HF_CLIENT_IND_TYPE; + +/* AT commands */ +#define BTA_HF_CLIENT_AT_CMD_VTS 0 +#define BTA_HF_CLIENT_AT_CMD_BTRH 1 +#define BTA_HF_CLIENT_AT_CMD_CHUP 2 +#define BTA_HF_CLIENT_AT_CMD_CHLD 3 +#define BTA_HF_CLIENT_AT_CMD_BCC 4 +#define BTA_HF_CLIENT_AT_CMD_CNUM 5 +#define BTA_HF_CLIENT_AT_CMD_ATA 6 +#define BTA_HF_CLIENT_AT_CMD_COPS 7 +#define BTA_HF_CLIENT_AT_CMD_ATD 8 +#define BTA_HF_CLIENT_AT_CMD_VGM 9 +#define BTA_HF_CLIENT_AT_CMD_VGS 10 +#define BTA_HF_CLIENT_AT_CMD_BVRA 11 +#define BTA_HF_CLIENT_AT_CMD_CLCC 12 +#define BTA_HF_CLIENT_AT_CMD_BINP 13 +#define BTA_HF_CLIENT_AT_CMD_BLDN 14 +#define BTA_HF_CLIENT_AT_CMD_NREC 15 + +typedef UINT8 tBTA_HF_CLIENT_AT_CMD_TYPE; + +/* data associated with most non-AT events */ +/* placeholder, if not needed should be removed*/ +typedef struct { +} tBTA_HF_CLIENT_HDR; + +/* data associated with BTA_HF_CLIENT_REGISTER_EVT */ +typedef struct { + tBTA_HF_CLIENT_HDR hdr; + UINT16 handle; + tBTA_HF_CLIENT_STATUS status; +} tBTA_HF_CLIENT_REGISTER; + +/* data associated with BTA_HF_CLIENT_OPEN_EVT */ +typedef struct { + tBTA_HF_CLIENT_HDR hdr; + BD_ADDR bd_addr; + tBTA_HF_CLIENT_STATUS status; +} tBTA_HF_CLIENT_OPEN; + +/* data associated with BTA_HF_CLIENT_CONN_EVT */ +typedef struct { + tBTA_HF_CLIENT_HDR hdr; + tBTA_HF_CLIENT_PEER_FEAT peer_feat; + tBTA_HF_CLIENT_CHLD_FEAT chld_feat; +} tBTA_HF_CLIENT_CONN; + +/* data associated with BTA_HF_CLIENT_IND_EVT event */ +typedef struct { + tBTA_HF_CLIENT_HDR hdr; + tBTA_HF_CLIENT_IND_TYPE type; + UINT16 value; +} tBTA_HF_CLIENT_IND; + +/* data associated with BTA_HF_CLIENT_OPERATOR_NAME_EVT */ +#define BTA_HF_CLIENT_OPERATOR_NAME_LEN 16 +typedef struct { + char name[BTA_HF_CLIENT_OPERATOR_NAME_LEN + 1]; +} tBTA_HF_CLIENT_OPERATOR_NAME; + +/* data associated with BTA_HF_CLIENT_CLIP_EVT and BTA_HF_CLIENT_CCWA_EVT*/ +#define BTA_HF_CLIENT_NUMBER_LEN 32 +typedef struct { + char number[BTA_HF_CLIENT_NUMBER_LEN + 1]; +} tBTA_HF_CLIENT_NUMBER; + +/* data associated with BTA_HF_CLIENT_AT_RESULT_EVT event */ +typedef struct { + tBTA_HF_CLIENT_AT_RESULT_TYPE type; + UINT16 cme; +} tBTA_HF_CLIENT_AT_RESULT; + +/* data associated with BTA_HF_CLIENT_CLCC_EVT event */ +typedef struct { + UINT32 idx; + BOOLEAN inc; + UINT8 status; + BOOLEAN mpty; + BOOLEAN number_present; + char number[BTA_HF_CLIENT_NUMBER_LEN + 1]; +} tBTA_HF_CLIENT_CLCC; + +/* data associated with BTA_HF_CLIENT_CNUM_EVT event */ +typedef struct { + UINT16 service; + char number[BTA_HF_CLIENT_NUMBER_LEN + 1]; +} tBTA_HF_CLIENT_CNUM; + +/* data associated with other events */ +typedef struct { + UINT16 value; +} tBTA_HF_CLIENT_VAL; + +/* union of data associated with AG callback */ +typedef union { + tBTA_HF_CLIENT_HDR hdr; + tBTA_HF_CLIENT_REGISTER reg; + tBTA_HF_CLIENT_OPEN open; + tBTA_HF_CLIENT_CONN conn; + tBTA_HF_CLIENT_IND ind; + tBTA_HF_CLIENT_VAL val; + tBTA_HF_CLIENT_OPERATOR_NAME operator; + tBTA_HF_CLIENT_NUMBER number; + tBTA_HF_CLIENT_AT_RESULT result; + tBTA_HF_CLIENT_CLCC clcc; + tBTA_HF_CLIENT_CNUM cnum; +} tBTA_HF_CLIENT; + +typedef UINT32 tBTA_HF_CLIENT_FEAT; + +/* HF Client callback */ +typedef void (tBTA_HF_CLIENT_CBACK)(tBTA_HF_CLIENT_EVT event, void *p_data); + +#ifdef __cplusplus +extern "C" +{ +#endif + +/***************************************************************************** +** External Function Declarations +*****************************************************************************/ + +/******************************************************************************* +** +** Function BTA_HfClientEnable +** +** Description Enable the HF CLient service. When the enable +** operation is complete the callback function will be +** called with a BTA_HF_CLIENT_ENABLE_EVT. This function must +** be called before other function in the HF CLient API are +** called. +** +** Returns BTA_SUCCESS if OK, BTA_FAILURE otherwise. +** +*******************************************************************************/ +tBTA_STATUS BTA_HfClientEnable(tBTA_HF_CLIENT_CBACK *p_cback); + +/******************************************************************************* +** +** Function BTA_HfClientDisable +** +** Description Disable the HF Client service +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientDisable(void); + +/******************************************************************************* +** +** Function BTA_HfClientRegister +** +** Description Register an HF Client service. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientRegister(tBTA_SEC sec_mask, tBTA_HF_CLIENT_FEAT features, + char *p_service_name); + +/******************************************************************************* +** +** Function BTA_HfClientDeregister +** +** Description Deregister an HF Client service. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientDeregister(UINT16 handle); + +/******************************************************************************* +** +** Function BTA_HfClientOpen +** +** Description Opens a connection to an audio gateway. +** When connection is open callback function is called +** with a BTA_HF_CLIENT_OPEN_EVT. Only the data connection is +** opened. The audio connection is not opened. +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientOpen(UINT16 handle, BD_ADDR bd_addr, tBTA_SEC sec_mask); + +/******************************************************************************* +** +** Function BTA_HfClientClose +** +** Description Close the current connection to an audio gateway. +** Any current audio connection will also be closed +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientClose(UINT16 handle); + +/******************************************************************************* +** +** Function BTA_HfCllientAudioOpen +** +** Description Opens an audio connection to the currently connected +** audio gateway +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientAudioOpen(UINT16 handle); + +/******************************************************************************* +** +** Function BTA_HfClientAudioClose +** +** Description Close the currently active audio connection to an audio +** gateway. The data connection remains open +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientAudioClose(UINT16 handle); + +/******************************************************************************* +** +** Function BTA_HfClientSendAT +** +** Description send AT command +** +** +** Returns void +** +*******************************************************************************/ +void BTA_HfClientSendAT(UINT16 handle, tBTA_HF_CLIENT_AT_CMD_TYPE at, UINT32 val1, UINT32 val2, const char *str); + +#if (BTM_SCO_HCI_INCLUDED == TRUE ) +void BTA_HfClientCiData(void); +#endif /*#if (BTM_SCO_HCI_INCLUDED == TRUE ) */ + +int BTA_HfClientGetCbDataSize(tBTA_HF_CLIENT_EVT event); + +#ifdef __cplusplus +} +#endif +#endif /* #if (BTA_HF_INCLUDED == TRUE) */ +#endif /* BTA_HF_CLIENT_API_H */ diff --git a/components/bt/bluedroid/bta/include/bta/bta_hf_client_co.h b/components/bt/bluedroid/bta/include/bta/bta_hf_client_co.h new file mode 100644 index 0000000000..af53e6e318 --- /dev/null +++ b/components/bt/bluedroid/bta/include/bta/bta_hf_client_co.h @@ -0,0 +1,115 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/****************************************************************************** + * + * This is the interface file for hf client call-out functions. + * + ******************************************************************************/ +#ifndef BTA_HF_CLIENT_CO_H +#define BTA_HF_CLIENT_CO_H + +#include "common/bt_target.h" +#include "bta/bta_hf_client_api.h" + +#if (BTA_HF_INCLUDED == TRUE) + +#if (BTM_SCO_HCI_INCLUDED == TRUE) +/******************************************************************************* +** +** Function bta_hf_client_co_audio_state +** +** Description This function is called by the HF CLIENT before the audio connection +** is brought up, after it comes up, and after it goes down. +** +** Parameters handle - handle of the AG instance +** state - Audio state +** codec - if WBS support is compiled in, codec to going to be used is provided +** and when in SCO_STATE_SETUP, BTM_I2SPCMConfig() must be called with +** the correct platform parameters. +** in the other states codec type should not be ignored +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_co_audio_state(UINT16 handle, UINT8 state, tBTA_HFP_PEER_CODEC codec); + + +/******************************************************************************* +** +** Function bta_hf_client_sco_co_init +** +** Description This function can be used by the phone to initialize audio +** codec or for other initialization purposes before SCO connection +** is opened. +** +** +** Returns Void. +** +*******************************************************************************/ +tBTA_HFP_SCO_ROUTE_TYPE bta_hf_client_sco_co_init(UINT32 rx_bw, UINT32 tx_bw, + tBTA_HFP_CODEC_INFO *p_codec_info, UINT8 app_id); + + +/******************************************************************************* +** +** Function bta_hf_client_sco_co_open +** +** Description This function is executed when a SCO connection is open. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event); + +/******************************************************************************* +** +** Function bta_hf_client_sco_co_close +** +** Description This function is called when a SCO connection is closed +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_sco_co_close(void); + +/******************************************************************************* +** +** Function bta_hf_client_sco_co_out_data +** +** Description This function is called to send SCO data over HCI. +** +** Returns number of bytes got from application +** +*******************************************************************************/ +uint32_t bta_hf_client_sco_co_out_data(uint8_t *p_buf, uint32_t sz); + +/******************************************************************************* +** +** Function bta_hf_client_sco_co_in_data +** +** Description This function is called to send incoming SCO data to application. +** +** Returns void +** +*******************************************************************************/ +extern void bta_hf_client_sco_co_in_data(BT_HDR *p_buf, tBTM_SCO_DATA_FLAG status); + +#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE) */ + +#endif /* #if (BTA_HF_INCLUDED == TRUE) */ +#endif /* BTA_HF_CLIENT_CO_H */ diff --git a/components/bt/bluedroid/bta/include/bta/bta_hfp_defs.h b/components/bt/bluedroid/bta/include/bta/bta_hfp_defs.h new file mode 100644 index 0000000000..464481979f --- /dev/null +++ b/components/bt/bluedroid/bta/include/bta/bta_hfp_defs.h @@ -0,0 +1,47 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __BTA_HFP_DEFS_H__ +#define __BTA_HFP_DEFS_H__ + +#include "stack/btm_api.h" + +#define BTA_HFP_CODEC_NONE BTM_SCO_CODEC_NONE +#define BTA_HFP_CODEC_CVSD BTM_SCO_CODEC_CVSD /* CVSD */ +#define BTA_HFP_CODEC_MSBC BTM_SCO_CODEC_MSBC /* mSBC */ + +typedef UINT16 tBTA_HFP_PEER_CODEC; + +#ifndef BTA_HFP_SCO_OUT_PKT_SIZE +#define BTA_HFP_SCO_OUT_PKT_SIZE BTM_SCO_DATA_SIZE_MAX +#endif + +#define BTA_HFP_SCO_CODEC_PCM 0 /* used for regular SCO */ +#define BTA_HFP_SCO_CODEC_SBC 1 /* used for WBS */ +typedef UINT8 tBTA_HFP_SCO_CODEC_TYPE; + +#define BTA_HFP_SCO_SAMP_RATE_8K 8000 +#define BTA_HFP_SCO_SAMP_RATE_16K 16000 + +/* SCO codec information */ +typedef struct { + tBTA_HFP_SCO_CODEC_TYPE codec_type; +} tBTA_HFP_CODEC_INFO; + +#define BTA_HFP_SCO_ROUTE_PCM BTM_SCO_ROUTE_PCM +#define BTA_HFP_SCO_ROUTE_HCI BTM_SCO_ROUTE_HCI + +typedef tBTM_SCO_ROUTE_TYPE tBTA_HFP_SCO_ROUTE_TYPE; + +#endif /* __BTA_HFP_DEFS_H__ */ diff --git a/components/bt/bluedroid/btc/core/btc_dm.c b/components/bt/bluedroid/btc/core/btc_dm.c index 1ed93a725e..9f6c911058 100644 --- a/components/bt/bluedroid/btc/core/btc_dm.c +++ b/components/bt/bluedroid/btc/core/btc_dm.c @@ -57,6 +57,9 @@ static btc_dm_local_key_cb_t ble_local_key_cb; extern bt_status_t btc_av_execute_service(BOOLEAN b_enable); extern bt_status_t btc_av_sink_execute_service(BOOLEAN b_enable); #endif +#if BTC_HF_CLIENT_INCLUDED +extern bt_status_t btc_hf_client_execute_service(BOOLEAN b_enable); +#endif /****************************************************************************** ** Functions ******************************************************************************/ @@ -396,6 +399,11 @@ static bt_status_t btc_in_execute_service_request(tBTA_SERVICE_ID service_id, btc_av_sink_execute_service(b_enable); break; #endif +#if BTC_HF_CLIENT_INCLUDED + case BTA_HFP_HS_SERVICE_ID: + btc_hf_client_execute_service(b_enable); + break; +#endif /* #if BTC_HF_CLIENT_INCLUDED */ default: BTC_TRACE_ERROR("%s: Unknown service being enabled\n", __FUNCTION__); return BT_STATUS_FAIL; diff --git a/components/bt/bluedroid/btc/core/btc_task.c b/components/bt/bluedroid/btc/core/btc_task.c index 1d14d7ecf0..b8afbb5814 100644 --- a/components/bt/bluedroid/btc/core/btc_task.c +++ b/components/bt/bluedroid/btc/core/btc_task.c @@ -42,6 +42,9 @@ #if CONFIG_BT_SPP_ENABLED #include "btc_spp.h" #endif /* #if CONFIG_BT_SPP_ENABLED */ +#if BTC_HF_CLIENT_INCLUDED +#include "btc_hf_client.h" +#endif /* #if BTC_HF_CLIENT_INCLUDED */ #endif /* #if CONFIG_CLASSIC_BT_ENABLED */ @@ -80,6 +83,9 @@ static btc_func_t profile_tab[BTC_PID_NUM] = { #if CONFIG_BT_SPP_ENABLED [BTC_PID_SPP] = {btc_spp_call_handler, btc_spp_cb_handler }, #endif /* #if CONFIG_BT_SPP_ENABLED */ +#if BTC_HF_CLIENT_INCLUDED + [BTC_PID_HF_CLIENT] = {btc_hf_client_call_handler, btc_hf_client_cb_handler}, +#endif /* #if BTC_HF_CLIENT_INCLUDED */ #endif /* #if CONFIG_CLASSIC_BT_ENABLED */ }; diff --git a/components/bt/bluedroid/btc/include/btc/btc_task.h b/components/bt/bluedroid/btc/include/btc/btc_task.h index 401f8ee7bb..f644e865a6 100644 --- a/components/bt/bluedroid/btc/include/btc/btc_task.h +++ b/components/bt/bluedroid/btc/include/btc/btc_task.h @@ -54,6 +54,9 @@ typedef enum { BTC_PID_A2DP, BTC_PID_AVRC, BTC_PID_SPP, +#if BTC_HF_CLIENT_INCLUDED + BTC_PID_HF_CLIENT, +#endif /* BTC_HF_CLIENT_INCLUDED */ #endif /* CONFIG_CLASSIC_BT_ENABLED */ BTC_PID_NUM, } btc_pid_t; //btc profile id diff --git a/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c b/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c new file mode 100644 index 0000000000..27eda746d3 --- /dev/null +++ b/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c @@ -0,0 +1,137 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "bta/bta_hf_client_co.h" +#include "hci/hci_audio.h" +#include "btc_hf_client.h" +#if (BTA_HF_INCLUDED == TRUE) + +#if (BTM_SCO_HCI_INCLUDED == TRUE) +/******************************************************************************* +** +** Function bta_hf_client_co_audio_state +** +** Description This function is called by the HF CLIENT before the audio connection +** is brought up, after it comes up, and after it goes down. +** +** Parameters handle - handle of the AG instance +** state - Audio state +** codec - if WBS support is compiled in, codec to going to be used is provided +** and when in SCO_STATE_SETUP, BTM_I2SPCMConfig() must be called with +** the correct platform parameters. +** in the other states codec type should not be ignored +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_co_audio_state(UINT16 handle, UINT8 state, tBTA_HFP_PEER_CODEC codec) +{ + switch (state) + { + case SCO_STATE_ON: + case SCO_STATE_OFF: + case SCO_STATE_OFF_TRANSFER: + case SCO_STATE_SETUP: + default: + break; + } +} + +/******************************************************************************* +** +** Function bta_hf_client_sco_co_init +** +** Description This function can be used by the phone to initialize audio +** codec or for other initialization purposes before SCO connection +** is opened. +** +** +** Returns Void. +** +*******************************************************************************/ +tBTA_HFP_SCO_ROUTE_TYPE bta_hf_client_sco_co_init(UINT32 rx_bw, UINT32 tx_bw, + tBTA_HFP_CODEC_INFO *p_codec_info, UINT8 app_id) +{ + APPL_TRACE_EVENT("%s rx_bw %d, tx_bw %d, codec %d", __FUNCTION__, rx_bw, tx_bw, + p_codec_info->codec_type); + return BTA_HFP_SCO_ROUTE_HCI; +} + +/******************************************************************************* +** +** Function bta_hf_client_sco_co_open +** +** Description This function is executed when a SCO connection is open. +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event) +{ + APPL_TRACE_EVENT("%s hdl %x, pkt_sz %u, event %u", __FUNCTION__, handle, + pkt_size, event); +} + +/******************************************************************************* +** +** Function bta_hf_client_sco_co_close +** +** Description This function is called when a SCO connection is closed +** +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_sco_co_close(void) +{ + APPL_TRACE_EVENT("%s", __FUNCTION__); +} + +/******************************************************************************* +** +** Function bta_hf_client_sco_co_out_data +** +** Description This function is called to send SCO data over HCI. +** +** Returns number of bytes got from application +** +*******************************************************************************/ +uint32_t bta_hf_client_sco_co_out_data(uint8_t *p_buf, uint32_t sz) +{ + return btc_hf_client_outgoing_data_cb_to_app(p_buf, sz); +} + +/******************************************************************************* +** +** Function bta_hf_client_sco_co_in_data +** +** Description This function is called to send incoming SCO data to application. +** +** Returns void +** +*******************************************************************************/ +void bta_hf_client_sco_co_in_data(BT_HDR *p_buf, tBTM_SCO_DATA_FLAG status) +{ + UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset; + UINT8 pkt_size = 0; + + STREAM_SKIP_UINT16(p); + STREAM_TO_UINT8 (pkt_size, p); + btc_hf_client_incoming_data_cb_to_app(p, pkt_size); +} + +#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE) */ + +#endif /* #if (BTA_HF_INCLUDED == TRUE) */ diff --git a/components/bt/bluedroid/btc/profile/std/hf_client/btc_hf_client.c b/components/bt/bluedroid/btc/profile/std/hf_client/btc_hf_client.c new file mode 100644 index 0000000000..1d927fe1d9 --- /dev/null +++ b/components/bt/bluedroid/btc/profile/std/hf_client/btc_hf_client.c @@ -0,0 +1,1089 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/****************************************************************************** + ** + ** Name: btc_hf_client.c + ** + ******************************************************************************/ +#include "common/bt_target.h" +#include "common/bt_trace.h" +#include +#include +#include +#include +#include "common/bt_defs.h" +#include "device/bdaddr.h" +#include "btc/btc_dm.h" +#include "btc_hf_client.h" +#include "btc/btc_profile_queue.h" +#include "osi/allocator.h" +#include "btc/btc_manage.h" +#include "btc/btc_util.h" +#include "esp_hf_client_api.h" +#include "bta/bta_hf_client_api.h" +#include "esp_bt.h" +#include + +#if (BTC_HF_CLIENT_INCLUDED == TRUE) + +/************************************************************************************ +** Constants & Macros +************************************************************************************/ + +#ifndef BTC_HF_CLIENT_SERVICE_NAME +#define BTC_HF_CLIENT_SERVICE_NAME ("Handsfree") +#endif + +#ifndef BTC_HF_CLIENT_SECURITY +#define BTC_HF_CLIENT_SECURITY (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT) +#endif + +#ifndef BTC_HF_CLIENT_FEATURES +#define BTC_HF_CLIENT_FEATURES ( BTA_HF_CLIENT_FEAT_ECNR | \ + BTA_HF_CLIENT_FEAT_3WAY | \ + BTA_HF_CLIENT_FEAT_CLI | \ + BTA_HF_CLIENT_FEAT_VREC | \ + BTA_HF_CLIENT_FEAT_VOL | \ + BTA_HF_CLIENT_FEAT_ECS | \ + BTA_HF_CLIENT_FEAT_ECC | \ + BTA_HF_CLIENT_FEAT_CODEC) +#endif + +/************************************************************************************ +** Local type definitions +************************************************************************************/ +/* BTC-HF control block to map bdaddr to BTA handle */ +typedef struct +{ + bool initialized; + UINT16 handle; + bt_bdaddr_t connected_bda; + esp_hf_client_connection_state_t state; + esp_hf_vr_state_t vr_state; + tBTA_HF_CLIENT_PEER_FEAT peer_feat; + tBTA_HF_CLIENT_CHLD_FEAT chld_feat; +} btc_hf_client_cb_t; + +/************************************************************************************ +** Static variables +************************************************************************************/ +const char *btc_hf_client_version = "1.6"; +static UINT32 btc_hf_client_features = 0; +static btc_hf_client_cb_t btc_hf_client_cb; +static esp_hf_client_incoming_data_cb_t btc_hf_client_incoming_data_cb = NULL; +static esp_hf_client_outgoing_data_cb_t btc_hf_client_outgoing_data_cb = NULL; + +/************************************************************************************ +** Static functions +************************************************************************************/ +#define CHECK_HF_CLIENT_INIT() do { \ +if (! btc_hf_client_cb.initialized) { \ + return BT_STATUS_NOT_READY; \ +} \ +} while (0) + +#define CHECK_HF_CLIENT_SLC_CONNECTED() do { \ +if (! btc_hf_client_cb.initialized || \ + btc_hf_client_cb.state != ESP_HF_CLIENT_CONNECTION_STATE_SLC_CONNECTED) { \ + return BT_STATUS_NOT_READY; \ +} \ +} while (0) + +static inline void btc_hf_client_cb_to_app(esp_hf_client_cb_event_t event, esp_hf_client_cb_param_t *param) +{ + esp_hf_client_cb_t btc_hf_client_callback = (esp_hf_client_cb_t)btc_profile_cb_get(BTC_PID_HF_CLIENT); + if (btc_hf_client_callback) { + btc_hf_client_callback(event, param); + } +} + +static void clear_state(void) +{ + memset(&btc_hf_client_cb, 0, sizeof(btc_hf_client_cb_t)); +} + +static BOOLEAN is_connected(bt_bdaddr_t *bd_addr) +{ + if (((btc_hf_client_cb.state == ESP_HF_CLIENT_CONNECTION_STATE_CONNECTED) || + (btc_hf_client_cb.state == ESP_HF_CLIENT_CONNECTION_STATE_SLC_CONNECTED))&& + ((bd_addr == NULL) || (bdcmp(bd_addr->address, btc_hf_client_cb.connected_bda.address) == 0))) + return TRUE; + return FALSE; +} + +void btc_hf_client_reg_data_cb(esp_hf_client_incoming_data_cb_t recv, + esp_hf_client_outgoing_data_cb_t send) +{ + btc_hf_client_incoming_data_cb = recv; + btc_hf_client_outgoing_data_cb = send; +} + +void btc_hf_client_incoming_data_cb_to_app(const uint8_t *data, uint32_t len) +{ + // todo: critical section protection + if (btc_hf_client_incoming_data_cb) { + btc_hf_client_incoming_data_cb(data, len); + } +} + +uint32_t btc_hf_client_outgoing_data_cb_to_app(uint8_t *data, uint32_t len) +{ + // todo: critical section protection + if (btc_hf_client_outgoing_data_cb) { + return btc_hf_client_outgoing_data_cb(data, len); + } else { + return 0; + } +} + +/***************************************************************************** +** +** btc hf api functions +** +*****************************************************************************/ + +/******************************************************************************* +** +** Function btc_hf_client_init +** +** Description initializes the hf interface +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btc_hf_client_init(void) +{ + BTC_TRACE_EVENT("%s", __FUNCTION__); + + uint8_t data_path; + btc_dm_enable_service(BTA_HFP_HS_SERVICE_ID); + + clear_state(); + + btc_hf_client_cb.initialized = true; + +#if CONFIG_HFP_AUDIO_DATA_PATH_HCI + data_path = ESP_SCO_DATA_PATH_HCI; +#else + data_path = ESP_SCO_DATA_PATH_PCM; +#endif + esp_bredr_sco_datapath_set(data_path); + return BT_STATUS_SUCCESS; +} + + +/******************************************************************************* +** +** Function btc_hf_client_connect +** +** Description connect to audio gateway +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t connect_int( bt_bdaddr_t *bd_addr, uint16_t uuid ) +{ + if (is_connected(bd_addr)) + return BT_STATUS_BUSY; + + btc_hf_client_cb.state = ESP_HF_CLIENT_CONNECTION_STATE_CONNECTING; + bdcpy(btc_hf_client_cb.connected_bda.address, bd_addr->address); + + BTA_HfClientOpen(btc_hf_client_cb.handle, btc_hf_client_cb.connected_bda.address, + BTC_HF_CLIENT_SECURITY); + + return BT_STATUS_SUCCESS; +} + + +bt_status_t btc_hf_client_connect( bt_bdaddr_t *bd_addr ) +{ + BTC_TRACE_EVENT("HFP Client version is %s", btc_hf_client_version); + CHECK_HF_CLIENT_INIT(); + return btc_queue_connect(UUID_SERVCLASS_HF_HANDSFREE, bd_addr, connect_int); + +} + +/******************************************************************************* +** +** Function btc_hf_client_deinit +** +** Description Closes the HF interface +** +** Returns bt_status_t +** +*******************************************************************************/ +void btc_hf_client_deinit( void ) +{ + BTC_TRACE_EVENT("%s", __FUNCTION__); + + btc_dm_disable_service(BTA_HFP_HS_SERVICE_ID); + + btc_hf_client_cb.initialized = false; +} + +/******************************************************************************* +** +** Function btc_hf_client_disconnect +** +** Description disconnect from audio gateway +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btc_hf_client_disconnect( bt_bdaddr_t *bd_addr ) +{ + CHECK_HF_CLIENT_INIT(); + + if (is_connected(bd_addr)) + { + BTA_HfClientClose(btc_hf_client_cb.handle); + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_FAIL; +} + +/******************************************************************************* +** +** Function btc_hf_client_connect_audio +** +** Description create an audio connection +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btc_hf_client_connect_audio( bt_bdaddr_t *bd_addr ) +{ + CHECK_HF_CLIENT_SLC_CONNECTED(); + + if (is_connected(bd_addr)) + { + if (btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_CODEC) + { + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_BCC, 0, 0, NULL); + } + else + { + BTA_HfClientAudioOpen(btc_hf_client_cb.handle); + } + + /* Inform the application that the audio connection has been initiated successfully */ + do { + esp_hf_client_cb_param_t param; + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_CONNECTING; + memcpy(param.audio_stat.remote_bda, &btc_hf_client_cb.connected_bda, sizeof(esp_bd_addr_t)); + btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, ¶m); + } while (0); + + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_FAIL; +} + +/******************************************************************************* +** +** Function btc_hf_client_disconnect_audio +** +** Description close the audio connection +** +** Returns bt_status_t +** +*******************************************************************************/ +bt_status_t btc_hf_client_disconnect_audio( bt_bdaddr_t *bd_addr ) +{ + CHECK_HF_CLIENT_SLC_CONNECTED(); + + if (is_connected(bd_addr)) + { + BTA_HfClientAudioClose(btc_hf_client_cb.handle); + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_FAIL; +} + +/******************************************************************************* +** +** Function btc_hf_client_start_voice_recognition +** +** Description start voice recognition +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t btc_hf_client_start_voice_recognition(void) +{ + CHECK_HF_CLIENT_SLC_CONNECTED(); + + if (btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_FEAT_VREC) + { + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_BVRA, 1, 0, NULL); + + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_UNSUPPORTED; +} + + +/******************************************************************************* +** +** Function btc_hf_client_stop_voice_recognition +** +** Description stop voice recognition +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t btc_hf_client_stop_voice_recognition(void) +{ + CHECK_HF_CLIENT_SLC_CONNECTED(); + + if (btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_FEAT_VREC) + { + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_BVRA, 0, 0, NULL); + + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_UNSUPPORTED; +} + +/******************************************************************************* +** +** Function btc_hf_client_volume_update +** +** Description volume update +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t btc_hf_client_volume_update(esp_hf_volume_control_target_t type, int volume) +{ + CHECK_HF_CLIENT_SLC_CONNECTED(); + + switch (type) + { + case ESP_HF_VOLUME_CONTROL_TARGET_SPK: + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_VGS, volume, 0, NULL); + break; + case ESP_HF_VOLUME_CONTROL_TARGET_MIC: + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_VGM, volume, 0, NULL); + break; + default: + return BT_STATUS_UNSUPPORTED; + } + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btc_hf_client_dial +** +** Description place a call +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t btc_hf_client_dial(const char *number) +{ + CHECK_HF_CLIENT_SLC_CONNECTED(); + + if (strlen(number) != 0) + { + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_ATD, 0, 0, number); + } + else + { + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_BLDN, 0, 0, NULL); + } + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function dial_memory +** +** Description place a call with number specified by location (speed dial) +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t btc_hf_client_dial_memory(int location) +{ + CHECK_HF_CLIENT_SLC_CONNECTED(); + + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_ATD, location, 0, NULL); + + return BT_STATUS_SUCCESS; +} + +static bt_status_t btc_hf_client_send_chld_cmd(esp_hf_chld_type_t type, int idx) +{ + CHECK_HF_CLIENT_SLC_CONNECTED(); + + switch (type) + { + case ESP_HF_CHLD_TYPE_REL: + if (btc_hf_client_cb.chld_feat & BTA_HF_CLIENT_CHLD_REL) + { + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CHLD, 0, 0, NULL); + break; + } + return BT_STATUS_UNSUPPORTED; + case ESP_HF_CHLD_TYPE_REL_ACC: + // CHLD 1 is mandatory for 3 way calling + if (btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_FEAT_3WAY) + { + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CHLD, 1, 0, NULL); + break; + } + return BT_STATUS_UNSUPPORTED; + case ESP_HF_CHLD_TYPE_HOLD_ACC: + // CHLD 2 is mandatory for 3 way calling + if (btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_FEAT_3WAY) + { + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CHLD, 2, 0, NULL); + break; + } + return BT_STATUS_UNSUPPORTED; + case ESP_HF_CHLD_TYPE_MERGE: + if (btc_hf_client_cb.chld_feat & BTA_HF_CLIENT_CHLD_MERGE) + { + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CHLD, 3, 0, NULL); + break; + } + return BT_STATUS_UNSUPPORTED; + case ESP_HF_CHLD_TYPE_MERGE_DETACH: + if (btc_hf_client_cb.chld_feat & BTA_HF_CLIENT_CHLD_MERGE_DETACH) + { + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CHLD, 4, 0, NULL); + break; + } + return BT_STATUS_UNSUPPORTED; + case ESP_HF_CHLD_TYPE_REL_X: + if (btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_ECC) + { + if (idx < 1) + { + return BT_STATUS_FAIL; + } + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CHLD, 1, idx, NULL); + break; + } + return BT_STATUS_UNSUPPORTED; + case ESP_HF_CHLD_TYPE_PRIV_X: + if (btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_ECC) + { + if (idx < 1) + { + return BT_STATUS_FAIL; + } + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CHLD, 2, idx, NULL); + break; + } + return BT_STATUS_UNSUPPORTED; + + } + return BT_STATUS_SUCCESS; +} + +static bt_status_t btc_hf_client_send_btrh_cmd(esp_hf_btrh_cmd_t btrh) +{ + CHECK_HF_CLIENT_SLC_CONNECTED(); + + switch (btrh) { + case ESP_HF_BTRH_CMD_HOLD: + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_BTRH, 0, 0, NULL); + break; + case ESP_HF_BTRH_CMD_ACCEPT: + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_BTRH, 1, 0, NULL); + break; + case ESP_HF_BTRH_CMD_REJECT: + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_BTRH, 2, 0, NULL); + break; + default: + return BT_STATUS_FAIL; + } + + return BT_STATUS_SUCCESS; +} + +static bt_status_t btc_hf_client_answer_call(void) +{ + CHECK_HF_CLIENT_SLC_CONNECTED(); + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_ATA, 0, 0, NULL); + return BT_STATUS_SUCCESS; +} + +static bt_status_t btc_hf_client_reject_call(void) +{ + CHECK_HF_CLIENT_SLC_CONNECTED(); + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CHUP, 0, 0, NULL); + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btc_hf_client_query_current_calls +** +** Description query list of current calls +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t btc_hf_client_query_current_calls(void) +{ + CHECK_HF_CLIENT_SLC_CONNECTED(); + + if (btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_ECS) + { + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CLCC, 0, 0, NULL); + + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_UNSUPPORTED; +} + +/******************************************************************************* +** +** Function btc_hf_client_query_current_operator_name +** +** Description query current selected operator name +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t btc_hf_client_query_current_operator_name(void) +{ + CHECK_HF_CLIENT_SLC_CONNECTED(); + + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_COPS, 0, 0, NULL); + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btc_hf_client_retieve_subscriber_info +** +** Description retrieve subscriber number information +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t btc_hf_client_retrieve_subscriber_info(void) +{ + CHECK_HF_CLIENT_SLC_CONNECTED(); + + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_CNUM, 0, 0, NULL); + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btc_hf_client_send_dtmf +** +** Description send dtmf +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t btc_hf_client_send_dtmf(char code) +{ + CHECK_HF_CLIENT_SLC_CONNECTED(); + + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_VTS, code, 0, NULL); + + return BT_STATUS_SUCCESS; +} + +/******************************************************************************* +** +** Function btc_hf_client_request_last_voice_tag_number +** +** Description Request number from AG for VR purposes +** +** Returns bt_status_t +** +*******************************************************************************/ +static bt_status_t btc_hf_client_request_last_voice_tag_number(void) +{ + CHECK_HF_CLIENT_SLC_CONNECTED(); + + if (btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_VTAG) + { + BTA_HfClientSendAT(btc_hf_client_cb.handle, BTA_HF_CLIENT_AT_CMD_BINP, 1, 0, NULL); + + return BT_STATUS_SUCCESS; + } + + return BT_STATUS_UNSUPPORTED; +} + +/******************************************************************************* +** +** Function bte_hf_client_evt +** +** Description Switches context from BTE to BTIF for all HF Client events +** +** Returns void +** +*******************************************************************************/ +static void bte_hf_client_evt(tBTA_HF_CLIENT_EVT event, void *p_data) +{ + bt_status_t stat; + btc_msg_t msg; + int arg_len = BTA_HfClientGetCbDataSize(event); + void *arg = (p_data != NULL && arg_len > 0) ? p_data : NULL; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_HF_CLIENT; + msg.act = (uint8_t) event; + + stat = btc_transfer_context(&msg, arg, arg_len, NULL); + + if (stat) { + BTC_TRACE_ERROR("%s transfer failed\n", __func__); + } +} + +/******************************************************************************* +** +** Function btc_hf_client_execute_service +** +** Description Initializes/Shuts down the service +** +** Returns BT_STATUS_SUCCESS on success, BT_STATUS_FAIL otherwise +** +*******************************************************************************/ +bt_status_t btc_hf_client_execute_service(BOOLEAN b_enable) +{ + BTC_TRACE_EVENT("%s enable:%d", __FUNCTION__, b_enable); + + if (b_enable) + { + /* Enable and register with BTA-HFClient */ + BTA_HfClientEnable(bte_hf_client_evt); + if (strcmp(btc_hf_client_version, "1.6") == 0) + { + BTC_TRACE_EVENT("Support Codec Nego. %d ", BTC_HF_CLIENT_FEATURES); + BTA_HfClientRegister(BTC_HF_CLIENT_SECURITY, BTC_HF_CLIENT_FEATURES, + BTC_HF_CLIENT_SERVICE_NAME); + } + else + { + BTC_TRACE_EVENT("No Codec Nego Supported"); + btc_hf_client_features = BTC_HF_CLIENT_FEATURES; + btc_hf_client_features = btc_hf_client_features & (~BTA_HF_CLIENT_FEAT_CODEC); + BTC_TRACE_EVENT("btc_hf_client_features is %d", btc_hf_client_features); + BTA_HfClientRegister(BTC_HF_CLIENT_SECURITY, btc_hf_client_features, + BTC_HF_CLIENT_SERVICE_NAME); + } + + } + else + { + BTA_HfClientDeregister(btc_hf_client_cb.handle); + BTA_HfClientDisable(); + } + return BT_STATUS_SUCCESS; +} + +static void process_ind_evt(tBTA_HF_CLIENT_IND *ind) +{ + esp_hf_client_cb_param_t param; + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + + switch (ind->type) + { + case BTA_HF_CLIENT_IND_CALL: + param.call.status = ind->value; + btc_hf_client_cb_to_app(ESP_HF_CLIENT_CIND_CALL_EVT, ¶m); + break; + + case BTA_HF_CLIENT_IND_CALLSETUP: + param.call_setup.status = ind->value; + btc_hf_client_cb_to_app(ESP_HF_CLIENT_CIND_CALL_SETUP_EVT, ¶m); + break; + case BTA_HF_CLIENT_IND_CALLHELD: + param.call_held.status = ind->value; + btc_hf_client_cb_to_app(ESP_HF_CLIENT_CIND_CALL_HELD_EVT, ¶m); + break; + + case BTA_HF_CLIENT_IND_SERVICE: + param.service_availability.status = ind->value; + btc_hf_client_cb_to_app(ESP_HF_CLIENT_CIND_SERVICE_AVAILABILITY_EVT, ¶m); + break; + + case BTA_HF_CLIENT_IND_SIGNAL: + param.signal_strength.value = ind->value; + btc_hf_client_cb_to_app(ESP_HF_CLIENT_CIND_SIGNAL_STRENGTH_EVT, ¶m); + break; + + case BTA_HF_CLIENT_IND_ROAM: + param.roaming.status = ind->value; + btc_hf_client_cb_to_app(ESP_HF_CLIENT_CIND_ROAMING_STATUS_EVT, ¶m); + break; + + case BTA_HF_CLIENT_IND_BATTCH: + param.battery_level.value = ind->value; + btc_hf_client_cb_to_app(ESP_HF_CLIENT_CIND_BATTERY_LEVEL_EVT, ¶m); + break; + + default: + break; + } +} + +void btc_hf_client_cb_handler(btc_msg_t *msg) +{ + uint16_t event = msg->act; + tBTA_HF_CLIENT *p_data = (tBTA_HF_CLIENT *)msg->arg; + esp_hf_client_cb_param_t param; + bdstr_t bdstr; + + switch (event) + { + case BTA_HF_CLIENT_ENABLE_EVT: + case BTA_HF_CLIENT_DISABLE_EVT: + break; + case BTA_HF_CLIENT_REGISTER_EVT: + btc_hf_client_cb.handle = p_data->reg.handle; + break; + case BTA_HF_CLIENT_OPEN_EVT: + if (p_data->open.status == BTA_HF_CLIENT_SUCCESS) + { + bdcpy(btc_hf_client_cb.connected_bda.address, p_data->open.bd_addr); + btc_hf_client_cb.state = ESP_HF_CLIENT_CONNECTION_STATE_CONNECTED; + btc_hf_client_cb.peer_feat = 0; + btc_hf_client_cb.chld_feat = 0; + //clear_phone_state(); + } + else if (btc_hf_client_cb.state == ESP_HF_CLIENT_CONNECTION_STATE_CONNECTING) + { + btc_hf_client_cb.state = ESP_HF_CLIENT_CONNECTION_STATE_DISCONNECTED; + } + else + { + BTC_TRACE_WARNING("%s: HF CLient open failed, but another device connected. status=%d state=%d connected device=%s", + __FUNCTION__, p_data->open.status, btc_hf_client_cb.state, bdaddr_to_string(&btc_hf_client_cb.connected_bda, bdstr, sizeof(bdstr))); + break; + } + + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.conn_stat.state = btc_hf_client_cb.state; + param.conn_stat.peer_feat = 0; + param.conn_stat.chld_feat = 0; + + memcpy(param.conn_stat.remote_bda, &btc_hf_client_cb.connected_bda, + sizeof(esp_bd_addr_t)); + + btc_hf_client_cb_to_app(ESP_HF_CLIENT_CONNECTION_STATE_EVT, ¶m); + } while (0); + + if (btc_hf_client_cb.state == ESP_HF_CLIENT_CONNECTION_STATE_DISCONNECTED) + bdsetany(btc_hf_client_cb.connected_bda.address); + + if (p_data->open.status != BTA_HF_CLIENT_SUCCESS) + btc_queue_advance(); + + break; + + case BTA_HF_CLIENT_CONN_EVT: + btc_hf_client_cb.peer_feat = p_data->conn.peer_feat; + btc_hf_client_cb.chld_feat = p_data->conn.chld_feat; + btc_hf_client_cb.state = ESP_HF_CLIENT_CONNECTION_STATE_SLC_CONNECTED; + + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.conn_stat.state = btc_hf_client_cb.state; + param.conn_stat.peer_feat = btc_hf_client_cb.peer_feat; + param.conn_stat.chld_feat = btc_hf_client_cb.chld_feat; + + memcpy(param.conn_stat.remote_bda, &btc_hf_client_cb.connected_bda, + sizeof(esp_bd_addr_t)); + + btc_hf_client_cb_to_app(ESP_HF_CLIENT_CONNECTION_STATE_EVT, ¶m); + } while (0); + + /* Inform the application about in-band ringtone */ + if (btc_hf_client_cb.peer_feat & BTA_HF_CLIENT_PEER_INBAND) + { + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.bsir.state = ESP_HF_CLIENT_IN_BAND_RINGTONE_PROVIDED; + btc_hf_client_cb_to_app(ESP_HF_CLIENT_BSIR_EVT, ¶m); + } while (0); + } + + btc_queue_advance(); + break; + + case BTA_HF_CLIENT_CLOSE_EVT: + btc_hf_client_cb.state = ESP_HF_CLIENT_CONNECTION_STATE_DISCONNECTED; + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.conn_stat.state = ESP_HF_CLIENT_CONNECTION_STATE_DISCONNECTED; + param.conn_stat.peer_feat = 0; + param.conn_stat.chld_feat = 0; + + memcpy(param.conn_stat.remote_bda, &btc_hf_client_cb.connected_bda, + sizeof(esp_bd_addr_t)); + + btc_hf_client_cb_to_app(ESP_HF_CLIENT_CONNECTION_STATE_EVT, ¶m); + } while (0); + + bdsetany(btc_hf_client_cb.connected_bda.address); + btc_hf_client_cb.peer_feat = 0; + btc_hf_client_cb.chld_feat = 0; + btc_queue_advance(); + break; + case BTA_HF_CLIENT_IND_EVT: + process_ind_evt(&p_data->ind); + break; + case BTA_HF_CLIENT_MIC_EVT: + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.volume_control.type = ESP_HF_VOLUME_CONTROL_TARGET_MIC; + param.volume_control.volume = p_data->val.value; + + btc_hf_client_cb_to_app(ESP_HF_CLIENT_VOLUME_CONTROL_EVT, ¶m); + } while (0); + break; + case BTA_HF_CLIENT_SPK_EVT: + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.volume_control.type = ESP_HF_VOLUME_CONTROL_TARGET_SPK; + param.volume_control.volume = p_data->val.value; + + btc_hf_client_cb_to_app(ESP_HF_CLIENT_VOLUME_CONTROL_EVT, ¶m); + } while (0); + break; + case BTA_HF_CLIENT_VOICE_REC_EVT: + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.bvra.value = p_data->val.value; + + btc_hf_client_cb_to_app(ESP_HF_CLIENT_BVRA_EVT, ¶m); + } while (0); + break; + case BTA_HF_CLIENT_OPERATOR_NAME_EVT: + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.cops.name = p_data->operator.name; + btc_hf_client_cb_to_app(ESP_HF_CLIENT_COPS_CURRENT_OPERATOR_EVT, ¶m); + } while (0); + break; + case BTA_HF_CLIENT_CLIP_EVT: + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.clip.number = p_data->number.number; + btc_hf_client_cb_to_app(ESP_HF_CLIENT_CLIP_EVT, ¶m); + } while (0); + break; + case BTA_HF_CLIENT_BINP_EVT: + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.binp.number = p_data->number.number; + btc_hf_client_cb_to_app(ESP_HF_CLIENT_BINP_EVT, ¶m); + } while (0); + break; + case BTA_HF_CLIENT_CCWA_EVT: + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.ccwa.number = p_data->number.number; + btc_hf_client_cb_to_app(ESP_HF_CLIENT_CCWA_EVT, ¶m); + } while (0); + break; + case BTA_HF_CLIENT_AT_RESULT_EVT: + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.at_response.code = p_data->result.type; + param.at_response.cme = p_data->result.cme; + + btc_hf_client_cb_to_app(ESP_HF_CLIENT_AT_RESPONSE_EVT, ¶m); + } while (0); + break; + case BTA_HF_CLIENT_CLCC_EVT: + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.clcc.idx = p_data->clcc.idx; + param.clcc.dir = p_data->clcc.inc ? ESP_HF_CURRENT_CALL_DIRECTION_INCOMING : + ESP_HF_CURRENT_CALL_DIRECTION_OUTGOING; + param.clcc.status = p_data->clcc.status; + param.clcc.mpty = p_data->clcc.mpty ? ESP_HF_CURRENT_CALL_MPTY_TYPE_MULTI : + ESP_HF_CURRENT_CALL_MPTY_TYPE_SINGLE; + param.clcc.number = p_data->clcc.number_present ? p_data->clcc.number : NULL; + btc_hf_client_cb_to_app(ESP_HF_CLIENT_CLCC_EVT, ¶m); + } while (0); + break; + case BTA_HF_CLIENT_CNUM_EVT: + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.cnum.number = p_data->cnum.number; + if (p_data->cnum.service == 4) { + param.cnum.type = ESP_HF_SUBSCRIBER_SERVICE_TYPE_VOICE; + } else if (p_data->cnum.service == 5) { + param.cnum.type = ESP_HF_SUBSCRIBER_SERVICE_TYPE_FAX; + } else { + param.cnum.type = ESP_HF_SUBSCRIBER_SERVICE_TYPE_UNKNOWN; + } + btc_hf_client_cb_to_app(ESP_HF_CLIENT_CNUM_EVT, ¶m); + break; + } while (0); + break; + case BTA_HF_CLIENT_BTRH_EVT: + if (p_data->val.value <= ESP_HF_BTRH_STATUS_REJECTED) { + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.btrh.status = p_data->val.value; + + btc_hf_client_cb_to_app(ESP_HF_CLIENT_BTRH_EVT, ¶m); + } while (0); + } + break; + case BTA_HF_CLIENT_BSIR_EVT: + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + if (p_data->val.value != 0) + { + param.bsir.state = ESP_HF_CLIENT_IN_BAND_RINGTONE_PROVIDED; + } + else + { + param.bsir.state = ESP_HF_CLIENT_IN_BAND_RINGTONE_NOT_PROVIDED; + } + btc_hf_client_cb_to_app(ESP_HF_CLIENT_BSIR_EVT, ¶m); + break; + case BTA_HF_CLIENT_AUDIO_OPEN_EVT: + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_CONNECTED; + memcpy(param.audio_stat.remote_bda, &btc_hf_client_cb.connected_bda, + sizeof(esp_bd_addr_t)); + btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, ¶m); + } while (0); + break; + case BTA_HF_CLIENT_AUDIO_MSBC_OPEN_EVT: + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_CONNECTED_MSBC; + memcpy(param.audio_stat.remote_bda, &btc_hf_client_cb.connected_bda, + sizeof(esp_bd_addr_t)); + btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, ¶m); + } while (0); + break; + case BTA_HF_CLIENT_AUDIO_CLOSE_EVT: + do { + memset(¶m, 0, sizeof(esp_hf_client_cb_param_t)); + param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_DISCONNECTED; + memcpy(param.audio_stat.remote_bda, &btc_hf_client_cb.connected_bda, + sizeof(esp_bd_addr_t)); + btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, ¶m); + } while (0); + break; + case BTA_HF_CLIENT_RING_INDICATION: + do { + btc_hf_client_cb_to_app(ESP_HF_CLIENT_RING_IND_EVT, NULL); + } while (0); + break; + default: + BTC_TRACE_WARNING("%s: Unhandled event: %d", __FUNCTION__, event); + break; + } +} + +void btc_hf_client_call_handler(btc_msg_t *msg) +{ + btc_hf_client_args_t *arg = (btc_hf_client_args_t *)(msg->arg); + switch (msg->act) { + + case BTC_HF_CLIENT_INIT_EVT: + btc_hf_client_init(); + break; + case BTC_HF_CLIENT_DEINIT_EVT: + btc_hf_client_deinit(); + break; + case BTC_HF_CLIENT_CONNECT_EVT: + btc_hf_client_connect(&arg->connect); + break; + case BTC_HF_CLIENT_DISCONNECT_EVT: + btc_hf_client_disconnect(&arg->disconnect); + break; + case BTC_HF_CLIENT_CONNECT_AUDIO_EVT: + btc_hf_client_connect_audio(&arg->connect_audio); + break; + case BTC_HF_CLIENT_DISCONNECT_AUDIO_EVT: + btc_hf_client_disconnect_audio(&arg->disconnect_audio); + break; + case BTC_HF_CLIENT_START_VOICE_RECOGNITION_EVT: + btc_hf_client_start_voice_recognition(); + break; + case BTC_HF_CLIENT_STOP_VOICE_RECOGNITION_EVT: + btc_hf_client_stop_voice_recognition(); + break; + case BTC_HF_CLIENT_VOLUME_UPDATE_EVT: + btc_hf_client_volume_update(arg->volume_update.type, arg->volume_update.volume); + break; + case BTC_HF_CLIENT_DIAL_EVT: + btc_hf_client_dial(arg->dial.number); + break; + case BTC_HF_CLIENT_DIAL_MEMORY_EVT: + btc_hf_client_dial_memory(arg->dial_memory.location); + break; + case BTC_HF_CLIENT_SEND_CHLD_CMD_EVT: + btc_hf_client_send_chld_cmd(arg->chld.type, arg->chld.idx); + break; + case BTC_HF_CLIENT_SEND_BTRH_CMD_EVT: + btc_hf_client_send_btrh_cmd(arg->btrh.cmd); + break; + case BTC_HF_CLIENT_ANSWER_CALL_EVT: + btc_hf_client_answer_call(); + break; + case BTC_HF_CLIENT_REJECT_CALL_EVT: + btc_hf_client_reject_call(); + break; + case BTC_HF_CLIENT_QUERY_CURRENT_CALLS_EVT: + btc_hf_client_query_current_calls(); + break; + case BTC_HF_CLIENT_QUERY_CURRENT_OPERATOR_NAME_EVT: + btc_hf_client_query_current_operator_name(); + break; + case BTC_HF_CLIENT_RETRIEVE_SUBSCRIBER_INFO_EVT: + btc_hf_client_retrieve_subscriber_info(); + break; + case BTC_HF_CLIENT_SEND_DTMF_EVT: + btc_hf_client_send_dtmf(arg->send_dtmf.code); + break; + case BTC_HF_CLIENT_REQUEST_LAST_VOICE_TAG_NUMBER_EVT: + btc_hf_client_request_last_voice_tag_number(); + break; + case BTC_HF_CLIENT_REGISTER_DATA_CALLBACK_EVT: + btc_hf_client_reg_data_cb(arg->reg_data_cb.recv, arg->reg_data_cb.send); + break; + default: + BTC_TRACE_WARNING("%s : unhandled event: %d\n", __FUNCTION__, msg->act); + } +} + +#endif /* #if (BTC_HF_CLIENT_INCLUDED == TRUE) */ diff --git a/components/bt/bluedroid/btc/profile/std/include/btc_hf_client.h b/components/bt/bluedroid/btc/profile/std/include/btc_hf_client.h new file mode 100644 index 0000000000..6500b9d878 --- /dev/null +++ b/components/bt/bluedroid/btc/profile/std/include/btc_hf_client.h @@ -0,0 +1,128 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/******************************************************************************* + * + * Filename: btc_hf_client.h + * + * Description: Main API header file for all BTC HF client functions accessed + * from internal stack. + * + *******************************************************************************/ + +#ifndef __BTC_HF_CLIENT_H__ +#define __BTC_HF_CLIENT_H__ + +#include "common/bt_target.h" +#include "esp_hf_client_api.h" +#include "btc/btc_task.h" +#include "btc/btc_common.h" +#include "bta/bta_hf_client_api.h" + +#if (BTC_HF_CLIENT_INCLUDED == TRUE) +/******************************************************************************* +** Type definitions for callback functions +********************************************************************************/ +typedef enum { + BTC_HF_CLIENT_INIT_EVT, + BTC_HF_CLIENT_DEINIT_EVT, + BTC_HF_CLIENT_CONNECT_EVT, + BTC_HF_CLIENT_DISCONNECT_EVT, + BTC_HF_CLIENT_CONNECT_AUDIO_EVT, + BTC_HF_CLIENT_DISCONNECT_AUDIO_EVT, + BTC_HF_CLIENT_START_VOICE_RECOGNITION_EVT, + BTC_HF_CLIENT_STOP_VOICE_RECOGNITION_EVT, + BTC_HF_CLIENT_VOLUME_UPDATE_EVT, + BTC_HF_CLIENT_DIAL_EVT, + BTC_HF_CLIENT_DIAL_MEMORY_EVT, + BTC_HF_CLIENT_SEND_CHLD_CMD_EVT, + BTC_HF_CLIENT_SEND_BTRH_CMD_EVT, + BTC_HF_CLIENT_ANSWER_CALL_EVT, + BTC_HF_CLIENT_REJECT_CALL_EVT, + BTC_HF_CLIENT_QUERY_CURRENT_CALLS_EVT, + BTC_HF_CLIENT_QUERY_CURRENT_OPERATOR_NAME_EVT, + BTC_HF_CLIENT_RETRIEVE_SUBSCRIBER_INFO_EVT, + BTC_HF_CLIENT_SEND_DTMF_EVT, + BTC_HF_CLIENT_REQUEST_LAST_VOICE_TAG_NUMBER_EVT, + BTC_HF_CLIENT_REGISTER_DATA_CALLBACK_EVT, +} btc_hf_client_act_t; + +/* btc_hf_client_args_t */ +typedef union { + // BTC_HF_CLIENT_CONNECT_EVT + bt_bdaddr_t connect; + + // BTC_HF_CLIENT_DISCONNECT_EVT + bt_bdaddr_t disconnect; + + // BTC_HF_CLIENT_CONNECT_AUDIO_EVT + bt_bdaddr_t connect_audio; + + // BTC_HF_CLIENT_DISCONNECT_AUDIO_EVT + bt_bdaddr_t disconnect_audio; + + // BTC_HF_CLIENT_VOLUME_UPDATE_EVT, + struct volume_update_args { + esp_hf_volume_control_target_t type; + int volume; + } volume_update; + + // BTC_HF_CLIENT_DIAL_EVT + struct dial_args { + char number[ESP_BT_HF_CLIENT_NUMBER_LEN + 1]; + } dial; + + // BTC_HF_CLIENT_DIAL_MEMORY_EVT + struct dial_memory_args { + int location; + } dial_memory; + + // BTC_HF_CLIENT_SEND_CHLD_CMD_EVT + struct send_chld_cmd_args { + esp_hf_chld_type_t type; + int idx; + } chld; + + // BTC_HF_CLIENT_SEND_BTRH_CMD_EVT + struct send_btrh_cmd_args { + esp_hf_btrh_cmd_t cmd; + } btrh; + + // BTC_HF_CLIENT_SEND_DTMF_EVT + struct send_dtmf { + char code; + } send_dtmf; + + // BTC_HF_CLIENT_REGISTER_DATA_CALLBACK_EVT + struct reg_data_callback { + esp_hf_client_incoming_data_cb_t recv; + esp_hf_client_outgoing_data_cb_t send; + } reg_data_cb; +} btc_hf_client_args_t; + +/******************************************************************************* +** BTC HF AG API +********************************************************************************/ + +void btc_hf_client_call_handler(btc_msg_t *msg); + +void btc_hf_client_cb_handler(btc_msg_t *msg); + +void btc_hf_client_incoming_data_cb_to_app(const uint8_t *data, uint32_t len); + +uint32_t btc_hf_client_outgoing_data_cb_to_app(uint8_t *data, uint32_t len); +#endif ///BTC_HF_CLIENT_INCLUDED == TRUE + +#endif /* __BTC_HF_CLIENT_H__ */ diff --git a/components/bt/bluedroid/common/include/common/bt_target.h b/components/bt/bluedroid/common/include/common/bt_target.h index 55b84b808f..8f3205f9be 100644 --- a/components/bt/bluedroid/common/include/common/bt_target.h +++ b/components/bt/bluedroid/common/include/common/bt_target.h @@ -50,6 +50,7 @@ #define BTC_PRF_QUEUE_INCLUDED TRUE #define BTC_GAP_BT_INCLUDED TRUE #define BTA_SDP_INCLUDED TRUE +#define BTA_DM_PM_INCLUDED TRUE #define SDP_INCLUDED TRUE #if CONFIG_A2DP_ENABLE @@ -79,6 +80,20 @@ #define BTC_SPP_INCLUDED TRUE #endif /* CONFIG_BT_SPP_ENABLED */ +#if CONFIG_HFP_CLIENT_ENABLE +#define BTC_HF_CLIENT_INCLUDED TRUE +#define BTA_HF_INCLUDED TRUE +#ifndef RFCOMM_INCLUDED +#define RFCOMM_INCLUDED TRUE +#endif +#ifndef BTM_SCO_INCLUDED +#define BTM_SCO_INCLUDED TRUE +#endif +#ifndef BTM_MAX_SCO_LINKS +#define BTM_MAX_SCO_LINKS (1) +#endif +#endif /* CONFIG_HFP_HF_ENABLE */ + #endif /* #if CONFIG_CLASSIC_BT_ENABLED */ #ifndef CLASSIC_BT_INCLUDED @@ -190,6 +205,10 @@ #define BTA_INCLUDED TRUE #endif +#ifndef BTA_DM_PM_INCLUDED +#define BTA_DM_PM_INCLUDED FALSE +#endif + #ifndef BTA_PAN_INCLUDED #define BTA_PAN_INCLUDED FALSE #endif @@ -491,12 +510,16 @@ /* Includes SCO if TRUE */ #ifndef BTM_SCO_INCLUDED -#define BTM_SCO_INCLUDED FALSE //TRUE /* TRUE includes SCO code */ +#define BTM_SCO_INCLUDED FALSE /* TRUE includes SCO code */ #endif /* Includes SCO if TRUE */ #ifndef BTM_SCO_HCI_INCLUDED -#define BTM_SCO_HCI_INCLUDED FALSE /* TRUE includes SCO over HCI code */ +#if CONFIG_HFP_AUDIO_DATA_PATH_HCI +#define BTM_SCO_HCI_INCLUDED TRUE /* TRUE includes SCO over HCI code */ +#else +#define BTM_SCO_HCI_INCLUDED FALSE +#endif /* CONFIG_HFP_AUDIO_DATA_PATH_HCI */ #endif /* Includes WBS if TRUE */ @@ -516,7 +539,7 @@ *************************/ /* max TX SCO data packet size */ #ifndef BTM_SCO_DATA_SIZE_MAX -#define BTM_SCO_DATA_SIZE_MAX 240 +#define BTM_SCO_DATA_SIZE_MAX 120 //240 #endif /* The size in bytes of the BTM inquiry database. 5 As Default */ @@ -580,11 +603,7 @@ /* The number of SCO links. */ #ifndef BTM_MAX_SCO_LINKS -#if (CLASSIC_BT_INCLUDED == TRUE) -#define BTM_MAX_SCO_LINKS 1 //3 -#else ///CLASSIC_BT_INCLUDED == TRUE -#define BTM_MAX_SCO_LINKS 0 -#endif ///CLASSIC_BT_INCLUDED == TRUE +#define BTM_MAX_SCO_LINKS 0 //3 #endif /* The preferred type of SCO links (2-eSCO, 0-SCO). */ @@ -656,7 +675,7 @@ /* This is set to TRUE if link is to be unparked due to BTM_CreateSCO API. */ #ifndef BTM_SCO_WAKE_PARKED_LINK -#define BTM_SCO_WAKE_PARKED_LINK TRUE +#define BTM_SCO_WAKE_PARKED_LINK FALSE #endif /* If the user does not respond to security process requests within this many seconds, @@ -710,9 +729,11 @@ #endif /* TRUE to include Sniff Subrating */ +#if (BTA_DM_PM_INCLUDED == TRUE) #ifndef BTM_SSR_INCLUDED #define BTM_SSR_INCLUDED FALSE #endif +#endif /* BTA_DM_PM_INCLUDED */ /************************* ** End of Lisbon Features diff --git a/components/bt/bluedroid/device/controller.c b/components/bt/bluedroid/device/controller.c index 93ef5384e8..06b8a52c7c 100644 --- a/components/bt/bluedroid/device/controller.c +++ b/components/bt/bluedroid/device/controller.c @@ -16,6 +16,7 @@ * ******************************************************************************/ #include +#include "common/bt_target.h" #include "common/bt_trace.h" #include "device/bdaddr.h" #include "stack/bt_types.h" @@ -61,6 +62,9 @@ static uint16_t acl_data_size_ble; static uint16_t acl_buffer_count_classic; static uint8_t acl_buffer_count_ble; +static uint8_t sco_data_size; +static uint16_t sco_buffer_count; + static uint8_t ble_white_list_size; static uint8_t ble_resolving_list_max_size; static uint8_t ble_supported_states[BLE_SUPPORTED_STATES_SIZE]; @@ -88,7 +92,8 @@ static void start_up(void) // Request the classic buffer size next response = AWAIT_COMMAND(packet_factory->make_read_buffer_size()); packet_parser->parse_read_buffer_size_response( - response, &acl_data_size_classic, &acl_buffer_count_classic); + response, &acl_data_size_classic, &acl_buffer_count_classic, + &sco_data_size, &sco_buffer_count); // Tell the controller about our buffer sizes and buffer counts next // TODO(zachoverflow): factor this out. eww l2cap contamination. And why just a hardcoded 10? @@ -244,6 +249,10 @@ static void start_up(void) packet_parser->parse_generic_command_complete(response); } +#if (BTM_SCO_HCI_INCLUDED == TRUE) + response = AWAIT_COMMAND(packet_factory->make_write_sync_flow_control_enable(1)); + packet_parser->parse_generic_command_complete(response); +#endif readable = true; // return future_new_immediate(FUTURE_SUCCESS); return; @@ -447,6 +456,20 @@ static void set_ble_resolving_list_max_size(int resolving_list_max_size) ble_resolving_list_max_size = resolving_list_max_size; } +#if (BTM_SCO_HCI_INCLUDED == TRUE) +static uint8_t get_sco_data_size(void) +{ + assert(readable); + return sco_data_size; +} + +static uint8_t get_sco_buffer_count(void) +{ + assert(readable); + return sco_buffer_count; +} +#endif /* (BTM_SCO_HCI_INCLUDED == TRUE) */ + static const controller_t interface = { start_up, shut_down, @@ -489,7 +512,11 @@ static const controller_t interface = { get_ble_white_list_size, get_ble_resolving_list_max_size, - set_ble_resolving_list_max_size + set_ble_resolving_list_max_size, +#if (BTM_SCO_HCI_INCLUDED == TRUE) + get_sco_data_size, + get_sco_buffer_count, +#endif /* (BTM_SCO_HCI_INCLUDED == TRUE) */ }; const controller_t *controller_get_interface() diff --git a/components/bt/bluedroid/device/include/device/controller.h b/components/bt/bluedroid/device/include/device/controller.h index b2806d69b8..704b456d7f 100644 --- a/components/bt/bluedroid/device/include/device/controller.h +++ b/components/bt/bluedroid/device/include/device/controller.h @@ -79,6 +79,11 @@ typedef struct controller_t { uint8_t (*get_ble_resolving_list_max_size)(void); void (*set_ble_resolving_list_max_size)(int resolving_list_max_size); +#if (BTM_SCO_HCI_INCLUDED == TRUE) + // Get the number of sco packets the controller can buffer + uint8_t (*get_sco_data_size)(void); + uint8_t (*get_sco_buffer_count)(void); +#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE) */ } controller_t; const controller_t *controller_get_interface(); diff --git a/components/bt/bluedroid/hci/hci_audio.c b/components/bt/bluedroid/hci/hci_audio.c new file mode 100644 index 0000000000..1983e7afde --- /dev/null +++ b/components/bt/bluedroid/hci/hci_audio.c @@ -0,0 +1,7 @@ +#include "hci/hci_audio.h" + +void set_audio_state(uint16_t handle, sco_codec_t codec, sco_state_t state) +{ + //todo + return; +} diff --git a/components/bt/bluedroid/hci/hci_packet_factory.c b/components/bt/bluedroid/hci/hci_packet_factory.c index 549323be61..2c88570e3d 100644 --- a/components/bt/bluedroid/hci/hci_packet_factory.c +++ b/components/bt/bluedroid/hci/hci_packet_factory.c @@ -175,6 +175,15 @@ static BT_HDR *make_ble_set_event_mask(const bt_event_mask_t *event_mask) return packet; } +static BT_HDR *make_write_sync_flow_control_enable(uint8_t enable) +{ + uint8_t *stream; + const uint8_t parameter_size = 1; + BT_HDR *packet = make_command(HCI_WRITE_SCO_FLOW_CTRL_ENABLE, parameter_size, &stream); + + UINT8_TO_STREAM(stream, enable); + return packet; +} // Internal functions static BT_HDR *make_command_no_params(uint16_t opcode) @@ -227,7 +236,8 @@ static const hci_packet_factory_t interface = { make_ble_read_resolving_list_size, make_ble_read_suggested_default_data_length, make_ble_write_suggested_default_data_length, - make_ble_set_event_mask + make_ble_set_event_mask, + make_write_sync_flow_control_enable }; const hci_packet_factory_t *hci_packet_factory_get_interface() diff --git a/components/bt/bluedroid/hci/hci_packet_parser.c b/components/bt/bluedroid/hci/hci_packet_parser.c index 627d1ccb82..c2adee5e66 100644 --- a/components/bt/bluedroid/hci/hci_packet_parser.c +++ b/components/bt/bluedroid/hci/hci_packet_parser.c @@ -42,16 +42,18 @@ static void parse_generic_command_complete(BT_HDR *response) static void parse_read_buffer_size_response( BT_HDR *response, - uint16_t *data_size_ptr, - uint16_t *acl_buffer_count_ptr) + uint16_t *acl_data_size_ptr, + uint16_t *acl_buffer_count_ptr, + uint8_t *sco_data_size_ptr, + uint16_t *sco_buffer_count_ptr) { - uint8_t *stream = read_command_complete_header(response, HCI_READ_BUFFER_SIZE, 5 /* bytes after */); + uint8_t *stream = read_command_complete_header(response, HCI_READ_BUFFER_SIZE, 7 /* bytes after */); assert(stream != NULL); - STREAM_TO_UINT16(*data_size_ptr, stream); - STREAM_SKIP_UINT8(stream); // skip the sco packet length + STREAM_TO_UINT16(*acl_data_size_ptr, stream); + STREAM_TO_UINT8(*sco_data_size_ptr, stream); STREAM_TO_UINT16(*acl_buffer_count_ptr, stream); - + STREAM_TO_UINT16(*sco_buffer_count_ptr, stream); buffer_allocator->free(response); } diff --git a/components/bt/bluedroid/hci/include/hci/hci_audio.h b/components/bt/bluedroid/hci/include/hci/hci_audio.h new file mode 100644 index 0000000000..a9234c3a06 --- /dev/null +++ b/components/bt/bluedroid/hci/include/hci/hci_audio.h @@ -0,0 +1,42 @@ +/****************************************************************************** + * + * Copyright (C) 2015 Google, Inc. + * + * 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 _HCI_AUDIO_H_ +#define _HCI_AUDIO_H_ +#include + +// Audio state definitions. +typedef enum { + SCO_STATE_OFF = 0, // Audio is off. + SCO_STATE_OFF_TRANSFER, // Closed pending final transfer of audio. + SCO_STATE_ON, // Audio is on. + SCO_STATE_SETUP, // Open pending completion of audio setup. +} sco_state_t; + +// Codec type definitions. +typedef enum { + SCO_CODEC_NONE = 0x0000, + SCO_CODEC_CVSD = 0x0001, + SCO_CODEC_MSBC = 0x0002, +} sco_codec_t; + +// Set the audio state on the controller for SCO (PCM, WBS, ...) using the +// vendor library. +void set_audio_state(uint16_t handle, sco_codec_t codec, sco_state_t state); + +#endif /* _HCI_AUDIO_H_ */ diff --git a/components/bt/bluedroid/hci/include/hci/hci_packet_factory.h b/components/bt/bluedroid/hci/include/hci/hci_packet_factory.h index b98b80d5d7..0cc4dc6849 100644 --- a/components/bt/bluedroid/hci/include/hci/hci_packet_factory.h +++ b/components/bt/bluedroid/hci/include/hci/hci_packet_factory.h @@ -42,6 +42,7 @@ typedef struct { BT_HDR *(*make_ble_read_suggested_default_data_length)(void); BT_HDR *(*make_ble_write_suggested_default_data_length)(uint16_t SuggestedMaxTxOctets, uint16_t SuggestedMaxTxTime); BT_HDR *(*make_ble_set_event_mask)(const bt_event_mask_t *event_mask); + BT_HDR *(*make_write_sync_flow_control_enable)(uint8_t enable); } hci_packet_factory_t; const hci_packet_factory_t *hci_packet_factory_get_interface(); diff --git a/components/bt/bluedroid/hci/include/hci/hci_packet_parser.h b/components/bt/bluedroid/hci/include/hci/hci_packet_parser.h index 2e5b5ef986..b0cc4b3b49 100644 --- a/components/bt/bluedroid/hci/include/hci/hci_packet_parser.h +++ b/components/bt/bluedroid/hci/include/hci/hci_packet_parser.h @@ -33,8 +33,10 @@ typedef struct { void (*parse_read_buffer_size_response)( BT_HDR *response, - uint16_t *data_size_ptr, - uint16_t *acl_buffer_count_ptr + uint16_t *acl_data_size_ptr, + uint16_t *acl_buffer_count_ptr, + uint8_t *sco_data_size_ptr, + uint16_t *sco_buffer_count_ptr ); void (*parse_read_local_version_info_response)( diff --git a/components/bt/bluedroid/main/bte_init.c b/components/bt/bluedroid/main/bte_init.c index 1b1395f4b4..38cfc812fb 100644 --- a/components/bt/bluedroid/main/bte_init.c +++ b/components/bt/bluedroid/main/bte_init.c @@ -89,7 +89,9 @@ #include "bta/bta_sys.h" #include "osi/allocator.h" -//#include "bta_ag_int.h" +#if BTA_HF_INCLUDED == TRUE +#include "bta_hf_client_int.h" +#endif #if BTA_SDP_INCLUDED == TRUE #include "bta_sdp_int.h" @@ -227,7 +229,13 @@ void BTE_InitStack(void) memset((void *)bta_dm_search_cb_ptr, 0, sizeof(tBTA_DM_SEARCH_CB)); memset((void *)bta_dm_di_cb_ptr, 0, sizeof(tBTA_DM_DI_CB)); //memset((void *)bta_prm_cb_ptr, 0, sizeof(tBTA_PRM_CB)); - //memset((void *)bta_ag_cb_ptr, 0, sizeof(tBTA_AG_CB)); + +#if (defined BTA_HF_INCLUDED && BTA_HF_INCLUDED == TRUE) + if ((bta_hf_client_cb_ptr = (tBTA_HF_CLIENT_CB *)osi_malloc(sizeof(tBTA_HF_CLIENT_CB))) == NULL) { + return; + } + memset((void *)bta_hf_client_cb_ptr, 0, sizeof(tBTA_HF_CLIENT_CB)); +#endif #if (defined BTA_JV_INCLUDED && BTA_JV_INCLUDED == TRUE) if ((bta_jv_cb_ptr = (tBTA_JV_CB *)osi_malloc(sizeof(tBTA_JV_CB))) == NULL) { return; @@ -327,6 +335,10 @@ void BTE_DeinitStack(void) osi_free(bta_jv_cb_ptr); bta_jv_cb_ptr = NULL; #endif //JV +#if (defined BTA_HF_INCLUDED && BTA_HF_INCLUDED == TRUE) + osi_free(bta_hf_client_cb_ptr); + bta_hf_client_cb_ptr = NULL; +#endif osi_free(bta_dm_di_cb_ptr); bta_dm_di_cb_ptr = NULL; osi_free(bta_dm_search_cb_ptr); @@ -354,4 +366,4 @@ void BTE_DeinitStack(void) #if (defined(A2D_INCLUDED) && A2D_INCLUDED == TRUE) A2D_Deinit(); #endif -} \ No newline at end of file +} diff --git a/components/bt/bluedroid/stack/btm/btm_devctl.c b/components/bt/bluedroid/stack/btm/btm_devctl.c index 085cda9254..41bfb92f08 100644 --- a/components/bt/bluedroid/stack/btm/btm_devctl.c +++ b/components/bt/bluedroid/stack/btm/btm_devctl.c @@ -170,6 +170,9 @@ static void reset_complete(void) btm_pm_reset(); l2c_link_processs_num_bufs(controller->get_acl_buffer_count_classic()); +#if BTM_SCO_HCI_INCLUDED == TRUE + btm_sco_process_num_bufs(controller->get_sco_buffer_count()); +#endif #if (BLE_INCLUDED == TRUE) #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) diff --git a/components/bt/bluedroid/stack/btm/btm_sco.c b/components/bt/bluedroid/stack/btm/btm_sco.c index d9b257d171..e04209aab5 100644 --- a/components/bt/bluedroid/stack/btm/btm_sco.c +++ b/components/bt/bluedroid/stack/btm/btm_sco.c @@ -30,6 +30,7 @@ #include "stack/hcimsgs.h" #include "stack/btu.h" #include "stack/btm_api.h" +#include "osi/allocator.h" #include "btm_int.h" #include "stack/hcidefs.h" //#include "bt_utils.h" @@ -109,6 +110,11 @@ void btm_sco_init (void) { #if 0 /* cleared in btm_init; put back in if called from anywhere else! */ memset (&btm_cb.sco_cb, 0, sizeof(tSCO_CB)); +#endif +#if (BTM_SCO_HCI_INCLUDED == TRUE) + for (int i = 0; i < BTM_MAX_SCO_LINKS; i++) { + btm_cb.sco_cb.sco_db[i].xmit_data_q = fixed_queue_new(SIZE_MAX); + } #endif /* Initialize nonzero defaults */ btm_cb.sco_cb.sco_disc_reason = BTM_INVALID_SCO_DISC_REASON; @@ -207,6 +213,66 @@ static void btm_esco_conn_rsp (UINT16 sco_inx, UINT8 hci_status, BD_ADDR bda, #if BTM_SCO_HCI_INCLUDED == TRUE +void btm_sco_process_num_bufs (UINT16 num_lm_sco_bufs) +{ + BTM_TRACE_ERROR("%s, %d", __FUNCTION__, num_lm_sco_bufs); + btm_cb.sco_cb.num_lm_sco_bufs = btm_cb.sco_cb.xmit_window_size = num_lm_sco_bufs; +} + +/******************************************************************************* +** +** Function BTM_ConfigScoPath +** +** Description This function enable/disable SCO over HCI and registers SCO +** data callback if SCO over HCI is enabled. +** +** Parameter path: SCO or HCI +** p_sco_data_cb: callback function or SCO data if path is set +** to transport. +** p_pcm_param: pointer to the PCM interface parameter. If a NULL +** pointer is used, PCM parameter maintained in +** the control block will be used; otherwise update +** control block value. +** err_data_rpt: Lisbon feature to enable the erronous data report +** or not. +** +** Returns BTM_SUCCESS if the successful. +** BTM_NO_RESOURCES: no rsource to start the command. +** BTM_ILLEGAL_VALUE: invalid callback function pointer. +** BTM_CMD_STARTED :Command sent. Waiting for command cmpl event. +** +** +*******************************************************************************/ +//extern +tBTM_STATUS BTM_ConfigScoPath (tBTM_SCO_ROUTE_TYPE path, + tBTM_SCO_DATA_CB *p_sco_data_cb, + tBTM_SCO_PCM_PARAM *p_pcm_param, + BOOLEAN err_data_rpt) +{ + UNUSED(err_data_rpt); + UNUSED(p_pcm_param); + btm_cb.sco_cb.sco_path = path; + if (path == BTM_SCO_ROUTE_PCM) { + return BTM_SUCCESS; + } else if (path == BTM_SCO_ROUTE_HCI) { + if (p_sco_data_cb) { + btm_cb.sco_cb.p_data_cb = p_sco_data_cb; + } + } + + return BTM_SUCCESS; +} + +static void hci_sco_data_to_lower(BT_HDR *p_buf) +{ + p_buf->event = BT_EVT_TO_LM_HCI_SCO; + if (p_buf->offset == 0) { + BTM_TRACE_ERROR("offset cannot be 0"); + osi_free(p_buf); + } + + bte_main_hci_send(p_buf, (UINT16)(BT_EVT_TO_LM_HCI_SCO | LOCAL_BLE_CONTROLLER_ID)); +} /******************************************************************************* ** ** Function btm_sco_check_send_pkts @@ -224,16 +290,58 @@ void btm_sco_check_send_pkts (UINT16 sco_inx) /* If there is data to send, send it now */ BT_HDR *p_buf; - while ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->xmit_data_q)) != NULL) + while (p_cb->xmit_window_size != 0) { + if ((p_buf = (BT_HDR *)fixed_queue_try_dequeue(p_ccb->xmit_data_q)) == NULL) { + break; + } #if BTM_SCO_HCI_DEBUG BTM_TRACE_DEBUG("btm: [%d] buf in xmit_data_q", fixed_queue_length(p_ccb->xmit_data_q) + 1); #endif + /* Don't go negative */ + p_cb->xmit_window_size -= 1; + p_ccb->sent_not_acked += 1; - HCI_SCO_DATA_TO_LOWER(p_buf); + // HCI_SCO_DATA_TO_LOWER(p_buf); + hci_sco_data_to_lower(p_buf); } } + +void btm_sco_process_num_completed_pkts (UINT8 *p) +{ + UINT8 num_handles, xx; + UINT16 handle; + UINT16 num_sent; + UINT16 sco_inx; + tSCO_CB *p_cb = &btm_cb.sco_cb; + tSCO_CONN * p_ccb; + STREAM_TO_UINT8 (num_handles, p); + for (xx = 0; xx < num_handles; xx++) { + STREAM_TO_UINT16 (handle, p); + handle &= 0x7ff; // walk around for bad handle bit mask from controller + STREAM_TO_UINT16 (num_sent, p); + if ((sco_inx = btm_find_scb_by_handle(handle & 0x7ff)) == BTM_MAX_SCO_LINKS) { + continue; + } + BTM_TRACE_DEBUG("%s, %d, %u", __FUNCTION__, handle, p_cb->xmit_window_size); //debug + p_ccb = &p_cb->sco_db[sco_inx]; + p_ccb->sent_not_acked -= num_sent; + // don't go negative + if (p_ccb->sent_not_acked < 0) { + BTM_TRACE_WARNING("SCO: un-acked underf: %u", p_ccb->sent_not_acked); + p_ccb->sent_not_acked = 0; + } + p_cb->xmit_window_size += num_sent; + if (p_cb->xmit_window_size > p_cb->num_lm_sco_bufs) { + BTM_TRACE_WARNING("SCO xwind: %d, max %d", p_cb->xmit_window_size, p_cb->num_lm_sco_bufs); + p_cb->xmit_window_size = p_cb->num_lm_sco_bufs; + } + btm_sco_check_send_pkts (sco_inx); + } + + return; +} #endif /* BTM_SCO_HCI_INCLUDED == TRUE */ /******************************************************************************* @@ -259,7 +367,7 @@ void btm_route_sco_data(BT_HDR *p_msg) handle = HCID_GET_HANDLE (handle); STREAM_TO_UINT8 (pkt_size, p); - + UNUSED(pkt_size); if ((sco_inx = btm_find_scb_by_handle(handle)) != BTM_MAX_SCO_LINKS ) { /* send data callback */ if (!btm_cb.sco_cb.p_data_cb ) @@ -272,6 +380,7 @@ void btm_route_sco_data(BT_HDR *p_msg) } else { /* no mapping handle SCO connection is active, free the buffer */ osi_free (p_msg); } + BTM_TRACE_DEBUG ("SCO: hdl %x, len %d, pkt_sz %d\n", handle, p_msg->len, pkt_size); #else osi_free(p_msg); #endif @@ -295,11 +404,13 @@ void btm_route_sco_data(BT_HDR *p_msg) ** BTM_NO_RESOURCES: no resources. ** BTM_UNKNOWN_ADDR: unknown SCO connection handle, or SCO is not ** routed via HCI. +** BTM_ERR_PROCESSING: transmit queue overflow ** ** *******************************************************************************/ tBTM_STATUS BTM_WriteScoData (UINT16 sco_inx, BT_HDR *p_buf) { + APPL_TRACE_DEBUG("%s", __FUNCTION__); #if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTM_MAX_SCO_LINKS>0) tSCO_CONN *p_ccb = &btm_cb.sco_cb.sco_db[sco_inx]; UINT8 *p; @@ -310,7 +421,6 @@ tBTM_STATUS BTM_WriteScoData (UINT16 sco_inx, BT_HDR *p_buf) /* Ensure we have enough space in the buffer for the SCO and HCI headers */ if (p_buf->offset < HCI_SCO_PREAMBLE_SIZE) { BTM_TRACE_ERROR ("BTM SCO - cannot send buffer, offset: %d", p_buf->offset); - osi_free (p_buf); status = BTM_ILLEGAL_VALUE; } else { /* write HCI header */ /* Step back 3 bytes to add the headers */ @@ -327,20 +437,27 @@ tBTM_STATUS BTM_WriteScoData (UINT16 sco_inx, BT_HDR *p_buf) } UINT8_TO_STREAM (p, (UINT8)p_buf->len); + BTM_TRACE_DEBUG ("BTM SCO hdl %x, len %u", p_ccb->hci_handle, p_buf->len); p_buf->len += HCI_SCO_PREAMBLE_SIZE; - fixed_queue_enqueue(p_ccb->xmit_data_q, p_buf); - - btm_sco_check_send_pkts (sco_inx); + if (fixed_queue_length(p_ccb->xmit_data_q) < BTM_SCO_XMIT_QUEUE_THRS) { + fixed_queue_enqueue(p_ccb->xmit_data_q, p_buf); + btm_sco_check_send_pkts (sco_inx); + } else { + BTM_TRACE_WARNING ("SCO xmit Q overflow, pkt dropped"); + status = BTM_ERR_PROCESSING; + } } } else { - osi_free(p_buf); - BTM_TRACE_WARNING ("BTM_WriteScoData, invalid sco index: %d at state [%d]", sco_inx, btm_cb.sco_cb.sco_db[sco_inx].state); status = BTM_UNKNOWN_ADDR; } + if (status != BTM_SUCCESS && status != BTM_SCO_BAD_LENGTH) { + BTM_TRACE_WARNING ("stat %d", status); + osi_free(p_buf); + } return (status); #else @@ -839,7 +956,7 @@ void btm_sco_connected (UINT8 hci_status, BD_ADDR bda, UINT16 hci_handle, #endif btm_cb.sco_cb.sco_disc_reason = hci_status; - + BTM_TRACE_ERROR("%s, handle %x", __FUNCTION__, hci_handle); #if (BTM_MAX_SCO_LINKS>0) for (xx = 0; xx < BTM_MAX_SCO_LINKS; xx++, p++) { if (((p->state == SCO_ST_CONNECTING) || @@ -876,7 +993,9 @@ void btm_sco_connected (UINT8 hci_status, BD_ADDR bda, UINT16 hci_handle, if (p->state == SCO_ST_LISTENING) { spt = TRUE; } - +#if BTM_SCO_HCI_INCLUDED == TRUE + p->sent_not_acked = 0; +#endif p->state = SCO_ST_CONNECTED; p->hci_handle = hci_handle; @@ -1022,6 +1141,14 @@ void btm_sco_removed (UINT16 hci_handle, UINT8 reason) btm_sco_flush_sco_data(xx); p->state = SCO_ST_UNUSED; +#if BTM_SCO_HCI_INCLUDED == TRUE + btm_cb.sco_cb.xmit_window_size += p->sent_not_acked; + /* avoid overflow */ + if (btm_cb.sco_cb.xmit_window_size > btm_cb.sco_cb.num_lm_sco_bufs) { + btm_cb.sco_cb.xmit_window_size = btm_cb.sco_cb.num_lm_sco_bufs; + } + p->sent_not_acked = 0; +#endif p->hci_handle = BTM_INVALID_HCI_HANDLE; p->rem_bd_known = FALSE; p->esco.p_esco_cback = NULL; /* Deregister eSCO callback */ diff --git a/components/bt/bluedroid/stack/btm/include/btm_int.h b/components/bt/bluedroid/stack/btm/include/btm_int.h index 5922a58145..bde7af9a2e 100644 --- a/components/bt/bluedroid/stack/btm/include/btm_int.h +++ b/components/bt/bluedroid/stack/btm/include/btm_int.h @@ -365,7 +365,9 @@ typedef struct { typedef struct { tBTM_ESCO_INFO esco; /* Current settings */ #if BTM_SCO_HCI_INCLUDED == TRUE +#define BTM_SCO_XMIT_QUEUE_THRS 20 fixed_queue_t *xmit_data_q; /* SCO data transmitting queue */ + INT16 sent_not_acked; #endif tBTM_SCO_CB *p_conn_cb; /* Callback for when connected */ tBTM_SCO_CB *p_disc_cb; /* Callback for when disconnect */ @@ -382,6 +384,7 @@ typedef struct { #if BTM_SCO_HCI_INCLUDED == TRUE tBTM_SCO_DATA_CB *p_data_cb; /* Callback for SCO data over HCI */ UINT32 xmit_window_size; /* Total SCO window in bytes */ + UINT16 num_lm_sco_bufs; #endif tSCO_CONN sco_db[BTM_MAX_SCO_LINKS]; tBTM_ESCO_PARAMS def_esco_parms; @@ -996,6 +999,10 @@ void btm_pm_proc_mode_change (UINT8 hci_status, UINT16 hci_handle, UINT8 mode, void btm_pm_proc_ssr_evt (UINT8 *p, UINT16 evt_len); #if BTM_SCO_INCLUDED == TRUE void btm_sco_chk_pend_unpark (UINT8 hci_status, UINT16 hci_handle); +#if (BTM_SCO_HCI_INCLUDED == TRUE ) +void btm_sco_process_num_bufs (UINT16 num_lm_sco_bufs); +void btm_sco_process_num_completed_pkts (UINT8 *p); +#endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */ #else #define btm_sco_chk_pend_unpark(hci_status, hci_handle) #endif /* BTM_SCO_INCLUDED */ diff --git a/components/bt/bluedroid/stack/btu/btu_hcif.c b/components/bt/bluedroid/stack/btu/btu_hcif.c index f0d50ed42b..09f5af4914 100644 --- a/components/bt/bluedroid/stack/btu/btu_hcif.c +++ b/components/bt/bluedroid/stack/btu/btu_hcif.c @@ -1292,7 +1292,9 @@ static void btu_hcif_num_compl_data_pkts_evt (UINT8 *p) l2c_link_process_num_completed_pkts (p); /* Send on to SCO */ - /*?? No SCO for now */ +#if (BTM_SCO_HCI_INCLUDED == TRUE) && (BTM_SCO_INCLUDED == TRUE) + btm_sco_process_num_completed_pkts (p); +#endif } /******************************************************************************* diff --git a/components/bt/bluedroid/stack/include/stack/btm_api.h b/components/bt/bluedroid/stack/include/stack/btm_api.h index 294cf84cee..79ecba8c8f 100644 --- a/components/bt/bluedroid/stack/include/stack/btm_api.h +++ b/components/bt/bluedroid/stack/include/stack/btm_api.h @@ -955,8 +955,8 @@ typedef UINT8 tBTM_SCO_TYPE; /******************* ** SCO Routing Path ********************/ -#define BTM_SCO_ROUTE_PCM HCI_BRCM_SCO_ROUTE_PCM -#define BTM_SCO_ROUTE_HCI HCI_BRCM_SCO_ROUTE_HCI +#define BTM_SCO_ROUTE_PCM (0) // HCI_BRCM_SCO_ROUTE_PCM +#define BTM_SCO_ROUTE_HCI (1) // HCI_BRCM_SCO_ROUTE_HCI typedef UINT8 tBTM_SCO_ROUTE_TYPE; diff --git a/components/bt/bluedroid/stack/rfcomm/port_rfc.c b/components/bt/bluedroid/stack/rfcomm/port_rfc.c index b227ea5cf9..46b3e07116 100644 --- a/components/bt/bluedroid/stack/rfcomm/port_rfc.c +++ b/components/bt/bluedroid/stack/rfcomm/port_rfc.c @@ -833,7 +833,7 @@ void PORT_DataInd (tRFC_MCB *p_mcb, UINT8 dlci, BT_HDR *p_buf) //osi_free (p_buf); return; } else { - RFCOMM_TRACE_ERROR("PORT_DataInd, p_port:%p, p_data_co_callback is null", p_port); + RFCOMM_TRACE_DEBUG("PORT_DataInd, p_port:%p, p_data_co_callback is null", p_port); } /* If client registered callback we can just deliver receive data */ if (p_port->p_data_callback) { @@ -1094,4 +1094,4 @@ void port_get_credits (tPORT *p_port, UINT8 k) } -#endif ///(defined RFCOMM_INCLUDED && RFCOMM_INCLUDED == TRUE) \ No newline at end of file +#endif ///(defined RFCOMM_INCLUDED && RFCOMM_INCLUDED == TRUE) diff --git a/components/bt/bt.c b/components/bt/bt.c index 68f5dee7fd..eeb374f1f2 100644 --- a/components/bt/bt.c +++ b/components/bt/bt.c @@ -97,6 +97,7 @@ extern int ble_txpwr_set(int power_type, int power_level); extern int ble_txpwr_get(int power_type); extern int bredr_txpwr_set(int min_power_level, int max_power_level); extern int bredr_txpwr_get(int *min_power_level, int *max_power_level); +extern void bredr_sco_datapath_set(uint8_t data_path); extern char _bss_start_btdm; extern char _bss_end_btdm; @@ -1103,4 +1104,13 @@ void esp_bt_controller_wakeup_request(void) btdm_wakeup_request(); } +esp_err_t esp_bredr_sco_datapath_set(esp_sco_data_path_t data_path) +{ + if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return ESP_ERR_INVALID_STATE; + } + bredr_sco_datapath_set(data_path); + return ESP_OK; +} + #endif /* CONFIG_BT_ENABLED */ diff --git a/components/bt/component.mk b/components/bt/component.mk index 8de4d6889c..f0c1f12027 100644 --- a/components/bt/component.mk +++ b/components/bt/component.mk @@ -25,6 +25,7 @@ ifdef CONFIG_BLUEDROID_ENABLED COMPONENT_PRIV_INCLUDEDIRS += bluedroid/bta/include \ bluedroid/bta/ar/include \ bluedroid/bta/av/include \ + bluedroid/bta/hf_client/include \ bluedroid/bta/dm/include \ bluedroid/bta/gatt/include \ bluedroid/bta/hh/include \ @@ -75,6 +76,7 @@ COMPONENT_SRCDIRS += bluedroid/bta/dm \ bluedroid/bta/ar \ bluedroid/bta/sys \ bluedroid/bta/jv \ + bluedroid/bta/hf_client \ bluedroid/bta \ bluedroid/btcore \ bluedroid/btif \ @@ -92,6 +94,7 @@ COMPONENT_SRCDIRS += bluedroid/bta/dm \ bluedroid/btc/profile/std/a2dp \ bluedroid/btc/profile/std/avrc \ bluedroid/btc/profile/std/spp \ + bluedroid/btc/profile/std/hf_client \ bluedroid/btc/profile \ bluedroid/stack/btm \ bluedroid/stack/btu \ @@ -111,5 +114,4 @@ COMPONENT_SRCDIRS += bluedroid/bta/dm \ bluedroid/utils \ bluedroid/api \ bluedroid - endif diff --git a/components/bt/include/esp_bt.h b/components/bt/include/esp_bt.h index 9924420f6f..2b06c09d11 100644 --- a/components/bt/include/esp_bt.h +++ b/components/bt/include/esp_bt.h @@ -122,6 +122,14 @@ typedef enum { ESP_PWR_LVL_P7 = 7, /*!< Corresponding to 7dbm */ } esp_power_level_t; +/** + * @brief Bluetooth audio data transport path + */ +typedef enum { + ESP_SCO_DATA_PATH_HCI = 0, /*!< data over HCI transport */ + ESP_SCO_DATA_PATH_PCM = 1, /*!< data over PCM interface */ +} esp_sco_data_path_t; + /** * @brief Set BLE TX power * Connection Tx power should only be set after connection created. @@ -164,6 +172,13 @@ esp_err_t esp_bredr_tx_power_set(esp_power_level_t min_power_level, esp_power_le */ esp_err_t esp_bredr_tx_power_get(esp_power_level_t *min_power_level, esp_power_level_t *max_power_level); +/** + * @brief set default SCO data path + * Should be called after controller is enabled, and before (e)SCO link is established + * @param data_path: SCO data path + * @return ESP_OK - success, other - failed + */ +esp_err_t esp_bredr_sco_datapath_set(esp_sco_data_path_t data_path); /** * @brief Initialize BT controller to allocate task and other resource. diff --git a/components/bt/lib b/components/bt/lib index 700d2bc914..16516d7009 160000 --- a/components/bt/lib +++ b/components/bt/lib @@ -1 +1 @@ -Subproject commit 700d2bc914b755b840a0adeaa9d1ff45b398b6fa +Subproject commit 16516d7009f1c31c21939047447a95238194de40 diff --git a/components/esp32/ld/esp32.rom.ld b/components/esp32/ld/esp32.rom.ld index 6529aacb97..8c458ff146 100644 --- a/components/esp32/ld/esp32.rom.ld +++ b/components/esp32/ld/esp32.rom.ld @@ -1704,6 +1704,7 @@ PROVIDE ( ets_update_cpu_frequency_rom = 0x40008550 ); /* Updates g_ticks_per_u PROVIDE ( hci_tl_env = 0x3ffb8154 ); PROVIDE ( ld_acl_env = 0x3ffb8258 ); PROVIDE ( ea_env = 0x3ffb80ec ); +PROVIDE ( lc_sco_data_path_config = 0x3ffb81f8 ); PROVIDE ( ld_active_ch_map = 0x3ffb8334 ); PROVIDE ( ld_bcst_acl_env = 0x3ffb8274 ); PROVIDE ( ld_csb_rx_env = 0x3ffb8278 ); diff --git a/docs/Doxyfile b/docs/Doxyfile index 7c1ac334d3..481eaa3fe5 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -51,6 +51,8 @@ INPUT = \ ../../components/bt/bluedroid/api/include/api/esp_a2dp_api.h \ ../../components/bt/bluedroid/api/include/api/esp_avrc_api.h \ ../../components/bt/bluedroid/api/include/api/esp_spp_api.h \ + ../../components/bt/bluedroid/api/include/api/esp_hf_defs.h \ + ../../components/bt/bluedroid/api/include/api/esp_hf_client_api.h \ ## ## Ethernet - API Reference ## diff --git a/docs/en/api-reference/bluetooth/classic_bt.rst b/docs/en/api-reference/bluetooth/classic_bt.rst index 2fd161e711..3a9a30430b 100644 --- a/docs/en/api-reference/bluetooth/classic_bt.rst +++ b/docs/en/api-reference/bluetooth/classic_bt.rst @@ -8,3 +8,5 @@ CLASSIC BT BT A2DP BT AVRC BT SPP + BT HFP Define + BT HFP Client diff --git a/docs/en/api-reference/bluetooth/esp_hf_client.rst b/docs/en/api-reference/bluetooth/esp_hf_client.rst new file mode 100644 index 0000000000..7c8a2d88c9 --- /dev/null +++ b/docs/en/api-reference/bluetooth/esp_hf_client.rst @@ -0,0 +1,14 @@ +HFP CLIENT API +============== + +Overview +-------- + +`Instructions`_ + +.. _Instructions: ../template.html + +API Reference +------------- + +.. include:: /_build/inc/esp_hf_client_api.inc diff --git a/docs/en/api-reference/bluetooth/esp_hf_defs.rst b/docs/en/api-reference/bluetooth/esp_hf_defs.rst new file mode 100644 index 0000000000..615b623862 --- /dev/null +++ b/docs/en/api-reference/bluetooth/esp_hf_defs.rst @@ -0,0 +1,16 @@ +HFP DEFINES +=========== + +Overview +-------- + +`Instructions`_ + +.. _Instructions: ../template.html + +API Reference +------------- + +.. include:: /_build/inc/esp_hf_defs.inc + + diff --git a/docs/zh_CN/api-reference/bluetooth/esp_hf_client.rst b/docs/zh_CN/api-reference/bluetooth/esp_hf_client.rst new file mode 100644 index 0000000000..160f0b2df3 --- /dev/null +++ b/docs/zh_CN/api-reference/bluetooth/esp_hf_client.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/bluetooth/esp_hf_client.rst diff --git a/docs/zh_CN/api-reference/bluetooth/esp_hf_defs.rst b/docs/zh_CN/api-reference/bluetooth/esp_hf_defs.rst new file mode 100644 index 0000000000..f863457f28 --- /dev/null +++ b/docs/zh_CN/api-reference/bluetooth/esp_hf_defs.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/bluetooth/esp_hf_defs.rst From 09181b7d940e14a388bdeb4dd2360b01931d5732 Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Fri, 18 May 2018 15:56:45 +0800 Subject: [PATCH 140/187] driver(touchpad): improve touchpad filter mode and update examples. --- components/driver/include/driver/touch_pad.h | 60 ++++++++-- components/driver/rtc_module.c | 107 ++++++++++++++---- .../peripherals/touch_pad_interrupt/README.md | 18 ++- .../main/tp_interrupt_main.c | 33 +++--- examples/peripherals/touch_pad_read/README.md | 47 ++++---- .../touch_pad_read/main/tp_read_main.c | 87 +++++--------- 6 files changed, 221 insertions(+), 131 deletions(-) diff --git a/components/driver/include/driver/touch_pad.h b/components/driver/include/driver/touch_pad.h index 9d14fe4e71..f18069ab3c 100644 --- a/components/driver/include/driver/touch_pad.h +++ b/components/driver/include/driver/touch_pad.h @@ -103,14 +103,17 @@ typedef enum { typedef intr_handle_t touch_isr_handle_t; #define TOUCH_PAD_SLEEP_CYCLE_DEFAULT (0x1000) /*!> n) & 0x1) == ((data >> m) & 0x1) ? (data) : ((data) ^ ((0x1 <filtered_val[i] = s_touch_pad_filter->filtered_val[i] == 0 ? (val << TOUCH_PAD_SHIFT_DEFAULT) : s_touch_pad_filter->filtered_val[i]; - s_touch_pad_filter->filtered_val[i] = _touch_filter_iir((val << TOUCH_PAD_SHIFT_DEFAULT), - s_touch_pad_filter->filtered_val[i], TOUCH_PAD_FILTER_FACTOR_DEFAULT); + if ((s_touch_pad_init_bit >> i) & 0x1) { + _touch_pad_read(i, &val, mode); + s_touch_pad_filter->raw_val[i] = val; + s_filtered_temp[i] = s_filtered_temp[i] == 0 ? ((uint32_t)val << TOUCH_PAD_SHIFT_DEFAULT) : s_filtered_temp[i]; + s_filtered_temp[i] = _touch_filter_iir((val << TOUCH_PAD_SHIFT_DEFAULT), + s_filtered_temp[i], TOUCH_PAD_FILTER_FACTOR_DEFAULT); + s_touch_pad_filter->filtered_val[i] = (s_filtered_temp[i] + TOUCH_PAD_SHIFT_ROUND_DEFAULT) >> TOUCH_PAD_SHIFT_DEFAULT; + } + } + xTimerReset(s_touch_pad_filter->timer, portMAX_DELAY); + xSemaphoreGive(rtc_touch_mux); + if(s_filter_cb != NULL) { + //return the raw data and filtered data. + s_filter_cb(s_touch_pad_filter->raw_val, s_touch_pad_filter->filtered_val); } } @@ -526,6 +552,8 @@ esp_err_t touch_pad_set_meas_time(uint16_t sleep_cycle, uint16_t meas_cycle) SENS.sar_touch_ctrl2.touch_sleep_cycles = sleep_cycle; //touch sensor measure time= meas_cycle / 8Mhz SENS.sar_touch_ctrl1.touch_meas_delay = meas_cycle; + //the waiting cycles (in 8MHz) between TOUCH_START and TOUCH_XPD + SENS.sar_touch_ctrl1.touch_xpd_wait = TOUCH_PAD_MEASURE_WAIT_DEFAULT; portEXIT_CRITICAL(&rtc_spinlock); xSemaphoreGive(rtc_touch_mux); return ESP_OK; @@ -792,10 +820,19 @@ esp_err_t touch_pad_config(touch_pad_t touch_num, uint16_t threshold) { RTC_MODULE_CHECK(rtc_touch_mux != NULL, "Touch pad not initialized", ESP_FAIL); RTC_MODULE_CHECK(touch_num < TOUCH_PAD_MAX, "Touch_Pad Num Err", ESP_ERR_INVALID_ARG); + s_touch_pad_init_bit |= (1 << touch_num); touch_pad_set_thresh(touch_num, threshold); touch_pad_io_init(touch_num); - touch_pad_set_cnt_mode(touch_num, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_HIGH); - touch_pad_set_group_mask((1 << touch_num), (1 << touch_num), (1 << touch_num)); + touch_pad_set_cnt_mode(touch_num, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_LOW); + touch_fsm_mode_t mode; + touch_pad_get_fsm_mode(&mode); + if (TOUCH_FSM_MODE_SW == mode) { + touch_pad_clear_group_mask((1 << touch_num), (1 << touch_num), (1 << touch_num)); + } else if (TOUCH_FSM_MODE_TIMER == mode){ + touch_pad_set_group_mask((1 << touch_num), (1 << touch_num), (1 << touch_num)); + } else { + return ESP_FAIL; + } return ESP_OK; } @@ -822,6 +859,7 @@ esp_err_t touch_pad_deinit() if (rtc_touch_mux == NULL) { return ESP_FAIL; } + s_touch_pad_init_bit = 0x0000; touch_pad_filter_delete(); touch_pad_set_fsm_mode(TOUCH_FSM_MODE_SW); touch_pad_clear_status(); @@ -831,19 +869,52 @@ esp_err_t touch_pad_deinit() return ESP_OK; } +static esp_err_t _touch_pad_read(touch_pad_t touch_num, uint16_t *touch_value, touch_fsm_mode_t mode) +{ + esp_err_t res = ESP_OK; + touch_pad_t tp_wrap = touch_pad_num_wrap(touch_num); + if (TOUCH_FSM_MODE_SW == mode) { + touch_pad_set_group_mask((1 << touch_num), (1 << touch_num), (1 << touch_num)); + touch_pad_sw_start(); + while (SENS.sar_touch_ctrl2.touch_meas_done == 0) {}; + *touch_value = (tp_wrap & 0x1) ? \ + SENS.touch_meas[tp_wrap / 2].l_val: \ + SENS.touch_meas[tp_wrap / 2].h_val; + + touch_pad_clear_group_mask((1 << touch_num), (1 << touch_num), (1 << touch_num)); + } else if (TOUCH_FSM_MODE_TIMER == mode) { + while (SENS.sar_touch_ctrl2.touch_meas_done == 0) {}; + *touch_value = (tp_wrap & 0x1) ? \ + SENS.touch_meas[tp_wrap / 2].l_val: \ + SENS.touch_meas[tp_wrap / 2].h_val; + } else { + res = ESP_FAIL; + } + return res; +} + esp_err_t touch_pad_read(touch_pad_t touch_num, uint16_t *touch_value) { RTC_MODULE_CHECK(touch_num < TOUCH_PAD_MAX, "Touch_Pad Num Err", ESP_ERR_INVALID_ARG); RTC_MODULE_CHECK(touch_value != NULL, "touch_value", ESP_ERR_INVALID_ARG); RTC_MODULE_CHECK(rtc_touch_mux != NULL, "Touch pad not initialized", ESP_FAIL); - touch_pad_t tp_wrap = touch_pad_num_wrap(touch_num); + esp_err_t res = ESP_OK; + touch_fsm_mode_t mode; + touch_pad_get_fsm_mode(&mode); xSemaphoreTake(rtc_touch_mux, portMAX_DELAY); - while (SENS.sar_touch_ctrl2.touch_meas_done == 0) {}; - *touch_value = (tp_wrap & 0x1) ? \ - SENS.touch_meas[tp_wrap / 2].l_val: \ - SENS.touch_meas[tp_wrap / 2].h_val; + res = _touch_pad_read(touch_num, touch_value, mode); xSemaphoreGive(rtc_touch_mux); + return res; +} + +IRAM_ATTR esp_err_t touch_pad_read_raw_data(touch_pad_t touch_num, uint16_t *touch_value) +{ + RTC_MODULE_CHECK(rtc_touch_mux != NULL, "Touch pad not initialized", ESP_FAIL); + RTC_MODULE_CHECK(touch_num < TOUCH_PAD_MAX, "Touch_Pad Num Err", ESP_ERR_INVALID_ARG); + RTC_MODULE_CHECK(touch_value != NULL, "touch_value", ESP_ERR_INVALID_ARG); + RTC_MODULE_CHECK(s_touch_pad_filter != NULL, "Touch pad filter not initialized", ESP_ERR_INVALID_STATE); + *touch_value = s_touch_pad_filter->raw_val[touch_num]; return ESP_OK; } @@ -853,7 +924,7 @@ IRAM_ATTR esp_err_t touch_pad_read_filtered(touch_pad_t touch_num, uint16_t *tou RTC_MODULE_CHECK(touch_num < TOUCH_PAD_MAX, "Touch_Pad Num Err", ESP_ERR_INVALID_ARG); RTC_MODULE_CHECK(touch_value != NULL, "touch_value", ESP_ERR_INVALID_ARG); RTC_MODULE_CHECK(s_touch_pad_filter != NULL, "Touch pad filter not initialized", ESP_ERR_INVALID_STATE); - *touch_value = (s_touch_pad_filter->filtered_val[touch_num] >> TOUCH_PAD_SHIFT_DEFAULT); + *touch_value = (s_touch_pad_filter->filtered_val[touch_num]); return ESP_OK; } @@ -908,13 +979,12 @@ esp_err_t touch_pad_filter_start(uint32_t filter_period_ms) } } if (s_touch_pad_filter->timer == NULL) { - s_touch_pad_filter->timer = xTimerCreate("filter_tmr", filter_period_ms / portTICK_PERIOD_MS, pdTRUE, + s_touch_pad_filter->timer = xTimerCreate("filter_tmr", filter_period_ms / portTICK_PERIOD_MS, pdFALSE, NULL, touch_pad_filter_cb); if (s_touch_pad_filter->timer == NULL) { ret = ESP_ERR_NO_MEM; } xTimerStart(s_touch_pad_filter->timer, portMAX_DELAY); - s_touch_pad_filter->enable = true; } else { xTimerChangePeriod(s_touch_pad_filter->timer, filter_period_ms / portTICK_PERIOD_MS, portMAX_DELAY); s_touch_pad_filter->period = filter_period_ms; @@ -932,7 +1002,6 @@ esp_err_t touch_pad_filter_stop() xSemaphoreTake(rtc_touch_mux, portMAX_DELAY); if (s_touch_pad_filter != NULL) { xTimerStop(s_touch_pad_filter->timer, portMAX_DELAY); - s_touch_pad_filter->enable = false; } else { ESP_LOGE(RTC_MODULE_TAG, "Touch pad filter deleted"); ret = ESP_ERR_INVALID_STATE; diff --git a/examples/peripherals/touch_pad_interrupt/README.md b/examples/peripherals/touch_pad_interrupt/README.md index fd4c2aa4b1..44a5efb511 100644 --- a/examples/peripherals/touch_pad_interrupt/README.md +++ b/examples/peripherals/touch_pad_interrupt/README.md @@ -1,12 +1,16 @@ # Touch Pad Interrupt Example +Demonstrates how to set up ESP32's capacitive touch pad peripheral to trigger interrupt when a pad is touched. It also shows how to detect the touch event by the software for sensor designs when greater touch detection sensitivity is required. -Demonstrates how to set up ESP32's capacitive touch pad peripheral to trigger interrupt when a pad is touched. +ESP32 supports touch detection by configuring hardware registers. The hardware periodically detects the pulse counts. If the number of pulse counts exceeds the set threshold, a hardware interrupt will be generated to notify the application layer that a certain touch sensor channel may be triggered. -Application has been developed and tested using [ESP32 Demo Board V2](https://dl.espressif.com/dl/schematics/ESP32-Demo-Board-V2_sch.pdf) that has ten capacitive sensor pads T0 to T9 exposed. +For the sensor designs when the pad is covered a glass or plastic, the difference caused by a 'touch' action could be very small. In such a case we are using software pooling and algorithms to reduce noise to still be able to detect small changes of the pulse counts. In certain cases we may need to use additional routines to adjust the threshold level dynamically as it may change depending on environment conditions. -![alt text](https://dl.espressif.com/dl/schematics/pictures/esp32-demo-board-v2.jpg "ESP32 Demo Board V2") +Comparison of the two modes: -The following output is shown when a pad is touched: +- The hardware interrupt mode occupies less CPU resources, but only a single threshold can be set and cannot support various software algorithms. +- The continuous pooling is flexible and supports various software algorithms. However, it also costs CPU overhead + +The application is cycling between the interrupt mode and the pooling mode with a filter, to compare performance of the touch sensor system in both scenarios: ``` I (6303) Touch pad: Waiting for any pad being touched... @@ -23,8 +27,10 @@ I (17903) Touch pad: Waiting for any pad being touched... I (22903) Touch pad: Waiting for any pad being touched... ``` -Note: Sensing threshold is set up automatically at start up by performing simple calibration. Application is reading current value for each pad and assuming half of this value as the sensing threshold. Do not touch pads on application start up, otherwise sensing may not work correctly. +Note: Sensing threshold is set up automatically at start up by performing simple calibration. Application is reading current value for each pad and assuming two thirds of this value as the sensing threshold. Do not touch pads on application start up, otherwise sensing may not work correctly. -For a simpler example how to configure and read capacitive touch pads, please refer to [touch_pad_read](../touch_pad_read). +For a simpler example how to configure and read capacitive touch pads, please refer to [touch_pad_read](../touch_pad_read). + +Design and implementation of the touch sensor system is a complex process. The [Touch Sensor Application Note](https://github.com/espressif/esp-iot-solution/blob/master/documents/touch_pad_solution/touch_sensor_design_en.md) contains several ESP32 specific notes and comments to optimize the design and get the best out of the application with sensors controlled with the ESP32. See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/peripherals/touch_pad_interrupt/main/tp_interrupt_main.c b/examples/peripherals/touch_pad_interrupt/main/tp_interrupt_main.c index a1c58762a7..dd0f8c26d4 100644 --- a/examples/peripherals/touch_pad_interrupt/main/tp_interrupt_main.c +++ b/examples/peripherals/touch_pad_interrupt/main/tp_interrupt_main.c @@ -17,12 +17,12 @@ static const char* TAG = "Touch pad"; #define TOUCH_THRESH_NO_USE (0) -#define TOUCH_THRESH_PERCENT (99) +#define TOUCH_THRESH_PERCENT (80) +#define TOUCHPAD_FILTER_TOUCH_PERIOD (10) static bool s_pad_activated[TOUCH_PAD_MAX]; static uint32_t s_pad_init_val[TOUCH_PAD_MAX]; - /* Read values sensed at all available touch pads. Use 2 / 3 of read value as the threshold @@ -42,7 +42,7 @@ static void tp_example_set_thresholds(void) //read filtered value touch_pad_read_filtered(i, &touch_value); s_pad_init_val[i] = touch_value; - ESP_LOGI(TAG, "test init touch val: %d\n", touch_value); + ESP_LOGI(TAG, "test init touch val: %d", touch_value); //set interrupt threshold. ESP_ERROR_CHECK(touch_pad_set_thresh(i, touch_value * 2 / 3)); @@ -58,7 +58,7 @@ static void tp_example_set_thresholds(void) In interrupt mode, the table is updated in touch ISR. In filter mode, we will compare the current filtered value with the initial one. - If the current filtered value is less than 99% of the initial value, we can + If the current filtered value is less than 80% of the initial value, we can regard it as a 'touched' event. When calling touch_pad_init, a timer will be started to run the filter. This mode is designed for the situation that the pad is covered @@ -90,12 +90,13 @@ static void tp_example_read_task(void *pvParameter) } else { //filter mode, disable touch interrupt touch_pad_intr_disable(); + touch_pad_clear_status(); for (int i = 0; i < TOUCH_PAD_MAX; i++) { uint16_t value = 0; touch_pad_read_filtered(i, &value); if (value < s_pad_init_val[i] * TOUCH_THRESH_PERCENT / 100) { ESP_LOGI(TAG, "T%d activated!", i); - ESP_LOGI(TAG, "value: %d; init val: %d\n", value, s_pad_init_val[i]); + ESP_LOGI(TAG, "value: %d; init val: %d", value, s_pad_init_val[i]); vTaskDelay(200 / portTICK_PERIOD_MS); // Reset the counter to stop changing mode. change_mode = 1; @@ -115,7 +116,7 @@ static void tp_example_read_task(void *pvParameter) // We can compare the two different mode. if (change_mode++ % 2000 == 0) { filter_mode = !filter_mode; - ESP_LOGI(TAG, "Change mode...%s\n", filter_mode == 0? "interrupt mode": "filter mode"); + ESP_LOGW(TAG, "Change mode...%s", filter_mode == 0? "interrupt mode": "filter mode"); } } } @@ -152,26 +153,20 @@ void app_main() // Initialize touch pad peripheral, it will start a timer to run a filter ESP_LOGI(TAG, "Initializing touch pad"); touch_pad_init(); - + // If use interrupt trigger mode, should set touch sensor FSM mode at 'TOUCH_FSM_MODE_TIMER'. + touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER); + // Set reference voltage for charging/discharging + // For most usage scenarios, we recommend using the following combination: + // the high reference valtage will be 2.7V - 1V = 1.7V, The low reference voltage will be 0.5V. + touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V); // Initialize and start a software filter to detect slight change of capacitance. - touch_pad_filter_start(10); - // Set measuring time and sleep time - // In this case, measurement will sustain 0xffff / 8Mhz = 8.19ms - // Meanwhile, sleep time between two measurement will be 0x1000 / 150Khz = 27.3 ms - touch_pad_set_meas_time(0x1000, 0xffff); - - //set reference voltage for charging/discharging - // In this case, the high reference valtage will be 2.4V - 1.5V = 0.9V - // The low reference voltage will be 0.8V, so that the procedure of charging - // and discharging would be very fast. - touch_pad_set_voltage(TOUCH_HVOLT_2V4, TOUCH_LVOLT_0V8, TOUCH_HVOLT_ATTEN_1V5); + touch_pad_filter_start(TOUCHPAD_FILTER_TOUCH_PERIOD); // Init touch pad IO tp_example_touch_pad_init(); // Set thresh hold tp_example_set_thresholds(); // Register touch interrupt ISR touch_pad_isr_register(tp_example_rtc_intr, NULL); - // Start a task to show what pads have been touched xTaskCreate(&tp_example_read_task, "touch_pad_read_task", 2048, NULL, 5, NULL); } diff --git a/examples/peripherals/touch_pad_read/README.md b/examples/peripherals/touch_pad_read/README.md index a6525f3b6c..13c5b39f2c 100644 --- a/examples/peripherals/touch_pad_read/README.md +++ b/examples/peripherals/touch_pad_read/README.md @@ -1,24 +1,23 @@ -# Touch Pad Read Example - -Read and display raw values from capacitive touch pad sensors. - -Once configured, ESP32 is continuously measuring capacitance of touch pad sensors. Measurement is reflected as numeric value inversely related to sensor's capacitance. The capacitance is bigger when sensor is touched with a finger and the measured value smaller. In opposite situation, when finger is released, capacitance is smaller and the measured value bigger. - -To detect when a sensor is touched and when not, each particular design should be calibrated by obtaining both measurements for each individual sensor. Then a threshold between both values should be established. Using specific threshold, API is then able to distinguish whether specific sensor is touched or released. - -ESP32 supports reading up to ten capacitive touch pad sensors T0 - T9, connected to specific GPIO pins. For information on available pins please refer to [Technical Reference Manual](https://espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf). Application initializes all ten sensor pads. Then in a loop reads sensors T0 - T9 and displays obtained values (after a colon) on a serial terminal: - -``` -T0: 486 T1: 1 T2: 559 T3: 567 T4: 871 T5: 522 T6:1174 T7:1531 T8:1508 T9:1640 -T0: 485 T1: 1 T2: 559 T3: 568 T4: 871 T5: 521 T6:1176 T7:1536 T8:1509 T9:1635 -T0: 485 T1: 1 T2: 559 T3: 568 T4: 871 T5: 521 T6:1172 T7:1536 T8:1507 T9:1640 -T0: 11 T1: 1 T2: 558 T3: 568 T4: 871 T5: 522 T6:1172 T7:1535 T8:1507 T9:1638 -``` - -Above log is prepared using [ESP32 Demo Board V2](https://dl.espressif.com/dl/schematics/ESP32-Demo-Board-V2_sch.pdf) that has all ten pad sensors exposed. Values will be different depending on layout of pads on particular board. - -![alt text](https://dl.espressif.com/dl/schematics/pictures/esp32-demo-board-v2.jpg "ESP32 Demo Board V2") - -There is another similar example that demonstrates how to perform simple calibration and trigger an interrupt when a pat is touched - see [touch_pad_interrupt](../touch_pad_interrupt). - -See the README.md file in the upper level 'examples' directory for more information about examples. +# Touch Pad Read Example + +Read and display raw values or IIR filtered values from capacitive touch pad sensors. + +Once configured, ESP32 is continuously measuring capacitance of touch pad sensors. Measurement is reflected as numeric value inversely related to sensor's capacitance. The capacitance is bigger when sensor is touched with a finger and the measured value smaller. In opposite situation, when finger is released, capacitance is smaller and the measured value bigger. + +To detect when a sensor is touched and when not, each particular design should be calibrated by obtaining both measurements for each individual sensor. Then a threshold between both values should be established. Using specific threshold, API is then able to distinguish whether specific sensor is touched or released. + +ESP32 supports reading up to ten capacitive touch pad sensors T0 - T9, connected to specific GPIO pins. For information on available pins please refer to [Technical Reference Manual](https://espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf). Application initializes all ten sensor pads. Then in a loop reads sensors T0 - T9 and displays obtained values (after a colon) on a serial terminal: + +``` +Touch Sensor filter mode read, the output format is: +Touchpad num:[raw data, filtered data] + +T0:[1072,1071] T1:[ 475, 475] T2:[1004,1003] T3:[1232,1231] T4:[1675,1676] T5:[1146,1146] T6:[1607,1607] T7:[1118,1118] T8:[1695,1695] T9:[1223,1222] +T0:[1072,1071] T1:[ 475, 475] T2:[1003,1003] T3:[1231,1231] T4:[1676,1676] T5:[1146,1146] T6:[1607,1607] T7:[1118,1118] T8:[1694,1694] T9:[1222,1221] +T0:[1071,1071] T1:[ 475, 475] T2:[1004,1004] T3:[1231,1231] T4:[1678,1677] T5:[1147,1146] T6:[1607,1607] T7:[1118,1118] T8:[1694,1694] T9:[1222,1221] +``` +For hardware and firmware design guidelines on ESP32 touch sensor system, please refer to [Touch Sensor Application Note](https://github.com/espressif/esp-iot-solution/blob/master/documents/touch_pad_solution/touch_sensor_design_en.md), where you may find comprehensive information on how to design and implement touch sensing applications, such as linear slider, wheel slider, matrix buttons and spring buttons. + +There is another similar example that demonstrates how to perform simple calibration and trigger an interrupt when a pat is touched - see [touch_pad_interrupt](../touch_pad_interrupt). + +See the README.md file in the upper level 'examples' directory for more information about examples. diff --git a/examples/peripherals/touch_pad_read/main/tp_read_main.c b/examples/peripherals/touch_pad_read/main/tp_read_main.c index def1dacf07..b7f9e0ea77 100644 --- a/examples/peripherals/touch_pad_read/main/tp_read_main.c +++ b/examples/peripherals/touch_pad_read/main/tp_read_main.c @@ -11,69 +11,37 @@ #include "freertos/task.h" #include "driver/touch_pad.h" -#define TOUCH_TEST_LOOP_NUM (10) #define TOUCH_PAD_NO_CHANGE (-1) #define TOUCH_THRESH_NO_USE (0) +#define TOUCH_FILTER_MODE_EN (1) +#define TOUCHPAD_FILTER_TOUCH_PERIOD (10) /* Read values sensed at all available touch pads. Print out values in a loop on a serial monitor. */ static void tp_example_read_task(void *pvParameter) { + uint16_t touch_value; + uint16_t touch_filter_value; +#if TOUCH_FILTER_MODE_EN + printf("Touch Sensor filter mode read, the output format is: \nTouchpad num:[raw data, filtered data]\n\n"); +#else + printf("Touch Sensor normal mode read, the output format is: \nTouchpad num:[raw data]\n\n"); +#endif while (1) { - uint16_t touch_value; - //set reference voltage for charging/discharging - // In this case, the high reference valtage will be 2.7V - 0V = 2.7V - // The low reference voltage will be 0.5 - // So the charing/discharging time would be longer, so the counter value would be smaller. - touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_0V); - - vTaskDelay(100 / portTICK_PERIOD_MS); - printf("Case[1], set default measure time\n"); - for (int j = 0; j < TOUCH_TEST_LOOP_NUM; j++) { - for (int i = 0; i < TOUCH_PAD_MAX; i++) { - ESP_ERROR_CHECK(touch_pad_read(i, &touch_value)); - printf("T%d:%5d ", i, touch_value); - } - printf("\n"); - vTaskDelay(500 / portTICK_PERIOD_MS); - } - - printf("Case[2], set max measure time\n"); - //set reference voltage for charging/discharging - // In this case, the high reference valtage will be 2.4V - 1.5V = 0.9V - // The low reference voltage will be 0.8 - // So the charing/discharging time would be shorter, so the counter value would be larger. - touch_pad_set_voltage(TOUCH_HVOLT_2V4, TOUCH_LVOLT_0V8, TOUCH_HVOLT_ATTEN_1V5); - vTaskDelay(100 / portTICK_PERIOD_MS); - for (int j = 0; j < TOUCH_TEST_LOOP_NUM; j++) { - for (int i = 0; i < TOUCH_PAD_MAX; i++) { - ESP_ERROR_CHECK(touch_pad_read(i, &touch_value)); - printf("T%d:%5d ", i, touch_value); - } - printf("\n"); - vTaskDelay(500 / portTICK_PERIOD_MS); - } - - - touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_0V); - vTaskDelay(100/portTICK_PERIOD_MS); - - printf("Case[3], set differen slope for each channel\n"); - for (int i = 0;i Date: Thu, 3 May 2018 20:22:08 +0800 Subject: [PATCH 141/187] Component/bt: fix scan duplicate --- components/bt/Kconfig | 32 ++++++++++++++ .../api/include/api/esp_gap_ble_api.h | 10 +++++ components/bt/bluedroid/bta/dm/bta_dm_act.c | 1 + components/bt/bluedroid/bta/dm/bta_dm_api.c | 4 +- .../bt/bluedroid/bta/dm/include/bta_dm_int.h | 1 + .../bt/bluedroid/bta/include/bta/bta_api.h | 3 +- .../btc/profile/std/gap/btc_gap_ble.c | 2 + .../bt/bluedroid/stack/btm/btm_ble_gap.c | 11 ++--- .../bluedroid/stack/btm/include/btm_ble_int.h | 3 +- components/bt/bluedroid/stack/btu/btu_hcif.c | 33 ++++++++++++++- .../stack/include/stack/btm_ble_api.h | 3 +- components/bt/bt.c | 6 +++ components/bt/include/esp_bt.h | 42 +++++++++++++++++++ components/bt/lib | 2 +- .../integration_test/TC_IT_BTSTK_GAP.yml | 4 +- .../ble_eddystone/main/esp_eddystone_demo.c | 3 +- .../bluetooth/ble_ibeacon/main/ibeacon_demo.c | 3 +- .../ble_spp_client/main/spp_client_demo.c | 3 +- .../main/example_ble_client_throughput.c | 3 +- .../bluetooth/gatt_client/main/gattc_demo.c | 3 +- .../main/example_ble_sec_gattc_demo.c | 3 +- .../main/gattc_multi_connect.c | 3 +- 22 files changed, 157 insertions(+), 21 deletions(-) diff --git a/components/bt/Kconfig b/components/bt/Kconfig index aca5029e73..fb5e72f18a 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -1007,6 +1007,38 @@ config BT_BLE_DYNAMIC_ENV_MEMORY help This select can make the allocation of memory will become more flexible +config BLE_SCAN_DUPLICATE + bool "BLE Scan Duplicate Options " + depends on BLUEDROID_ENABLED + default y + help + This select enables parameters setting of BLE scan duplicate. + +config DUPLICATE_SCAN_CACHE_SIZE + int "Maximum number of devices in scan duplicate filter" + depends on BLE_SCAN_DUPLICATE + range 10 200 + default 20 + help + Maximum number of devices which can be recorded in scan duplicate filter. + When the maximum amount of device in the filter is reached, the cache will be refreshed. + +config BLE_MESH_SCAN_DUPLICATE_EN + bool "Special duplicate scan mechanism for BLE Mesh scan" + depends on BLE_SCAN_DUPLICATE + default n + help + This enables the BLE scan duplicate for special BLE Mesh scan. + +config MESH_DUPLICATE_SCAN_CACHE_SIZE + int "Maximum number of Mesh adv packets in scan duplicate filter" + depends on BLE_MESH_SCAN_DUPLICATE_EN + range 10 200 + default 50 + help + Maximum number of adv packets which can be recorded in duplicate scan cache for BLE Mesh. + When the maximum amount of device in the filter is reached, the cache will be refreshed. + config SMP_ENABLE bool depends on BLUEDROID_ENABLED diff --git a/components/bt/bluedroid/api/include/api/esp_gap_ble_api.h b/components/bt/bluedroid/api/include/api/esp_gap_ble_api.h index 08feb13caf..faa8ed4f06 100644 --- a/components/bt/bluedroid/api/include/api/esp_gap_ble_api.h +++ b/components/bt/bluedroid/api/include/api/esp_gap_ble_api.h @@ -324,6 +324,13 @@ typedef enum { 3. directed advertising packets addressed to this device.*/ } esp_ble_scan_filter_t; +/// Ble scan duplicate type +typedef enum { + BLE_SCAN_DUPLICATE_DISABLE = 0x0, /*!< the Link Layer should generate advertising reports to the host for each packet received */ + BLE_SCAN_DUPLICATE_ENABLE = 0x1, /*!< the Link Layer should filter out duplicate advertising reports to the Host */ + BLE_SCAN_DUPLICATE_MAX = 0x2, /*!< 0x02 – 0xFF, Reserved for future use */ +} esp_ble_scan_duplicate_t; + /// Ble scan parameters typedef struct { esp_ble_scan_type_t scan_type; /*!< Scan type */ @@ -339,6 +346,9 @@ typedef struct { Range: 0x0004 to 0x4000 Default: 0x0010 (10 ms) Time = N * 0.625 msec Time Range: 2.5 msec to 10240 msec */ + esp_ble_scan_duplicate_t scan_duplicate; /*!< The Scan_Duplicates parameter controls whether the Link Layer should filter out + duplicate advertising reports (BLE_SCAN_DUPLICATE_ENABLE) to the Host, or if the Link Layer should generate + advertising reports for each packet received */ } esp_ble_scan_params_t; /// Connection update parameters diff --git a/components/bt/bluedroid/bta/dm/bta_dm_act.c b/components/bt/bluedroid/bta/dm/bta_dm_act.c index c2eff109a7..caa4943145 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_act.c @@ -4567,6 +4567,7 @@ void bta_dm_ble_set_scan_fil_params(tBTA_DM_MSG *p_data) p_data->ble_set_scan_fil_params.scan_window, p_data->ble_set_scan_fil_params.scan_mode, p_data->ble_set_scan_fil_params.addr_type_own, + p_data->ble_set_scan_fil_params.scan_duplicate_filter, p_data->ble_set_scan_fil_params.scan_filter_policy, p_data->ble_set_scan_fil_params.scan_param_setup_cback); } diff --git a/components/bt/bluedroid/bta/dm/bta_dm_api.c b/components/bt/bluedroid/bta/dm/bta_dm_api.c index 6564adc824..1f2262ae90 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_api.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_api.c @@ -968,6 +968,7 @@ void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval, ** scan_interval - scan interval ** scan_window - scan window ** scan_mode - scan mode +** scan_duplicate_filter - scan duplicate filter ** scan_param_setup_status_cback - Set scan param status callback ** ** Returns void @@ -975,7 +976,7 @@ void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval, *******************************************************************************/ void BTA_DmSetBleScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 scan_window, tBLE_SCAN_MODE scan_mode, UINT8 scan_fil_poilcy, - UINT8 addr_type_own, tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback) + UINT8 addr_type_own, UINT8 scan_duplicate_filter, tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback) { tBTA_DM_API_BLE_SCAN_FILTER_PARAMS *p_msg; @@ -987,6 +988,7 @@ void BTA_DmSetBleScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, p_msg->scan_window = scan_window; p_msg->scan_mode = scan_mode; p_msg->addr_type_own = addr_type_own; + p_msg->scan_duplicate_filter = scan_duplicate_filter; p_msg->scan_filter_policy = scan_fil_poilcy; p_msg->scan_param_setup_cback = scan_param_setup_cback; diff --git a/components/bt/bluedroid/bta/dm/include/bta_dm_int.h b/components/bt/bluedroid/bta/dm/include/bta_dm_int.h index d07e951f12..8ee1dda61b 100644 --- a/components/bt/bluedroid/bta/dm/include/bta_dm_int.h +++ b/components/bt/bluedroid/bta/dm/include/bta_dm_int.h @@ -492,6 +492,7 @@ typedef struct { UINT32 scan_window; tBLE_SCAN_MODE scan_mode; UINT8 addr_type_own; + UINT8 scan_duplicate_filter; UINT8 scan_filter_policy; tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback; } tBTA_DM_API_BLE_SCAN_FILTER_PARAMS; diff --git a/components/bt/bluedroid/bta/include/bta/bta_api.h b/components/bt/bluedroid/bta/include/bta/bta_api.h index 74ed278778..702701bd2e 100644 --- a/components/bt/bluedroid/bta/include/bta/bta_api.h +++ b/components/bt/bluedroid/bta/include/bta/bta_api.h @@ -1908,6 +1908,7 @@ extern void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval, ** scan_interval - scan interval ** scan_window - scan window ** scan_mode - scan mode +** scan_duplicate_filter - scan duplicate filter ** scan_param_setup_status_cback - Set scan param status callback ** ** Returns void @@ -1915,7 +1916,7 @@ extern void BTA_DmSetBleScanParams(tGATT_IF client_if, UINT32 scan_interval, *******************************************************************************/ extern void BTA_DmSetBleScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 scan_window, tBLE_SCAN_MODE scan_mode, UINT8 scan_fil_poilcy, - UINT8 addr_type_own, tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback); + UINT8 addr_type_own, UINT8 scan_duplicate_filter, tBLE_SCAN_PARAM_SETUP_CBACK scan_param_setup_cback); /******************************************************************************* diff --git a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c index fd88148155..f5b21f00c0 100644 --- a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c +++ b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c @@ -483,6 +483,7 @@ static void btc_ble_set_scan_params(esp_ble_scan_params_t *scan_params, tBLE_SCA BLE_ISVALID_PARAM(scan_params->scan_window, BTM_BLE_SCAN_WIN_MIN, BTM_BLE_SCAN_WIN_MAX) && BLE_ISVALID_PARAM(scan_params->own_addr_type, BLE_ADDR_TYPE_PUBLIC, BLE_ADDR_TYPE_RPA_RANDOM) && BLE_ISVALID_PARAM(scan_params->scan_filter_policy, BLE_SCAN_FILTER_ALLOW_ALL, BLE_SCAN_FILTER_ALLOW_WLIST_PRA_DIR) && + BLE_ISVALID_PARAM(scan_params->scan_duplicate, BLE_SCAN_DUPLICATE_DISABLE, BLE_SCAN_DUPLICATE_MAX -1) && (scan_params->scan_type == BTM_BLE_SCAN_MODE_ACTI || scan_params->scan_type == BTM_BLE_SCAN_MODE_PASS)) { BTA_DmSetBleScanFilterParams(ESP_DEFAULT_GATT_IF, /*client_if*/ scan_params->scan_interval, @@ -490,6 +491,7 @@ static void btc_ble_set_scan_params(esp_ble_scan_params_t *scan_params, tBLE_SCA scan_params->scan_type, scan_params->scan_filter_policy, scan_params->own_addr_type, + scan_params->scan_duplicate, scan_param_setup_cback); } else { btc_scan_params_callback(ESP_DEFAULT_GATT_IF, BTM_ILLEGAL_VALUE); diff --git a/components/bt/bluedroid/stack/btm/btm_ble_gap.c b/components/bt/bluedroid/stack/btm/btm_ble_gap.c index 35ae79dfc3..4444a11d94 100644 --- a/components/bt/bluedroid/stack/btm/btm_ble_gap.c +++ b/components/bt/bluedroid/stack/btm/btm_ble_gap.c @@ -403,7 +403,6 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT32 duration, BTM_BLE_DEFAULT_SFP); } - p_inq->scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE; status = btm_ble_start_scan(); } @@ -442,7 +441,6 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT32 duration, tBTM_STATUS BTM_BleScan(BOOLEAN start, UINT32 duration, tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb) { - tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var; tBTM_STATUS status = BTM_WRONG_MODE; if (!controller_get_interface()->supports_ble()) { @@ -467,7 +465,6 @@ tBTM_STATUS BTM_BleScan(BOOLEAN start, UINT32 duration, /* enable resolving list */ btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN); #endif - p_inq->scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE; status = btm_ble_start_scan(); } @@ -1390,7 +1387,7 @@ void BTM_BleSetScanParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 scan_ } void BTM_BleSetScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 scan_window, - tBLE_SCAN_MODE scan_mode, UINT8 addr_type_own, tBTM_BLE_SFP scan_filter_policy, + tBLE_SCAN_MODE scan_mode, UINT8 addr_type_own, UINT8 scan_duplicate_filter, tBTM_BLE_SFP scan_filter_policy, tBLE_SCAN_PARAM_SETUP_CBACK scan_setup_status_cback) { tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var; @@ -1433,6 +1430,8 @@ void BTM_BleSetScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 p_cb->scan_window = scan_window; p_cb->sfp = scan_filter_policy; p_cb->scan_params_set = TRUE; + p_cb->scan_duplicate_filter = scan_duplicate_filter; + btsnd_hcic_ble_set_scan_params(p_cb->scan_type, (UINT16)scan_interval, (UINT16)scan_window, @@ -2333,7 +2332,6 @@ tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration) /* enable IRK list */ btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN); #endif - p_ble_cb->inq_var.scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE; status = btm_ble_start_scan(); } else if ((p_ble_cb->inq_var.scan_interval != BTM_BLE_LOW_LATENCY_SCAN_INT) || (p_ble_cb->inq_var.scan_window != BTM_BLE_LOW_LATENCY_SCAN_WIN)) { @@ -3247,6 +3245,9 @@ tBTM_STATUS btm_ble_start_scan(void) tBTM_STATUS status = BTM_CMD_STARTED; // recoverly the scan parameters to the controller before start scan btm_ble_recover_scan_params(); + if(p_inq->scan_duplicate_filter > BTM_BLE_DUPLICATE_MAX) { + p_inq->scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE; + } /* start scan, disable duplicate filtering */ if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, p_inq->scan_duplicate_filter)) { status = BTM_NO_RESOURCES; diff --git a/components/bt/bluedroid/stack/btm/include/btm_ble_int.h b/components/bt/bluedroid/stack/btm/include/btm_ble_int.h index 88e56e070b..a9f0d8ff68 100644 --- a/components/bt/bluedroid/stack/btm/include/btm_ble_int.h +++ b/components/bt/bluedroid/stack/btm/include/btm_ble_int.h @@ -55,8 +55,9 @@ #define BTM_BLE_ENC_MASK 0x03 -#define BTM_BLE_DUPLICATE_ENABLE 1 #define BTM_BLE_DUPLICATE_DISABLE 0 +#define BTM_BLE_DUPLICATE_ENABLE 1 +#define BTM_BLE_DUPLICATE_MAX BTM_BLE_DUPLICATE_ENABLE #define BTM_BLE_GAP_DISC_SCAN_INT 18 /* Interval(scan_int) = 11.25 ms= 0x0010 * 0.625 ms */ #define BTM_BLE_GAP_DISC_SCAN_WIN 18 /* scan_window = 11.25 ms= 0x0010 * 0.625 ms */ diff --git a/components/bt/bluedroid/stack/btu/btu_hcif.c b/components/bt/bluedroid/stack/btu/btu_hcif.c index 09f5af4914..6374d0b0ae 100644 --- a/components/bt/bluedroid/stack/btu/btu_hcif.c +++ b/components/bt/bluedroid/stack/btu/btu_hcif.c @@ -906,7 +906,30 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l case HCI_BLE_CLEAR_WHITE_LIST: btm_ble_clear_white_list_complete(p, evt_len); break; - + case HCI_BLE_WRITE_ADV_PARAMS: { + uint8_t status; + STREAM_TO_UINT8 (status, p); + if(status != HCI_SUCCESS) { + HCI_TRACE_ERROR("hci write adv params error 0x%x", status); + } + break; + } + case HCI_BLE_RC_PARAM_REQ_REPLY: { + uint8_t status; + STREAM_TO_UINT8 (status, p); + if(status != HCI_SUCCESS) { + HCI_TRACE_ERROR("hci connection params reply command error 0x%x", status); + } + break; + } + case HCI_BLE_RC_PARAM_REQ_NEG_REPLY: { + uint8_t status; + STREAM_TO_UINT8 (status, p); + if(status != HCI_SUCCESS) { + HCI_TRACE_ERROR("hci connection params neg reply command error %x", status); + } + break; + } case HCI_BLE_REMOVE_WHITE_LIST: btm_ble_remove_from_white_list_complete(p, evt_len); break; @@ -960,12 +983,18 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l #endif #endif /* (BLE_INCLUDED == TRUE) */ - default: + default: { if ((opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC) { btm_vsc_complete (p, opcode, evt_len, (tBTM_CMPL_CB *)p_cplt_cback); } + uint8_t status; + STREAM_TO_UINT8 (status, p); + if(status != HCI_SUCCESS) { + HCI_TRACE_ERROR("%s opcode 0x%x status 0x%x", __func__, opcode, status); + } break; } + } } /******************************************************************************* diff --git a/components/bt/bluedroid/stack/include/stack/btm_ble_api.h b/components/bt/bluedroid/stack/include/stack/btm_ble_api.h index 0e93959afc..b3d254df03 100644 --- a/components/bt/bluedroid/stack/include/stack/btm_ble_api.h +++ b/components/bt/bluedroid/stack/include/stack/btm_ble_api.h @@ -1059,6 +1059,7 @@ void BTM_BleSetScanParams(tGATT_IF client_if, UINT32 scan_interval, ** scan_window - Scan window ** scan_type - Scan type ** addr_type_own - owner address type +** scan_duplicate_filter - scan duplicate filter ** scan_filter_policy - scan filter policy ** scan_setup_status_cback - Scan setup status callback ** @@ -1066,7 +1067,7 @@ void BTM_BleSetScanParams(tGATT_IF client_if, UINT32 scan_interval, ** *******************************************************************************/ void BTM_BleSetScanFilterParams(tGATT_IF client_if, UINT32 scan_interval, UINT32 scan_window, - tBLE_SCAN_MODE scan_mode, UINT8 addr_type_own, tBTM_BLE_SFP scan_filter_policy, + tBLE_SCAN_MODE scan_mode, UINT8 addr_type_own, UINT8 scan_duplicate_filter, tBTM_BLE_SFP scan_filter_policy, tBLE_SCAN_PARAM_SETUP_CBACK scan_setup_status_cback); diff --git a/components/bt/bt.c b/components/bt/bt.c index eeb374f1f2..f0640917c0 100644 --- a/components/bt/bt.c +++ b/components/bt/bt.c @@ -54,6 +54,8 @@ #define BTDM_CFG_BT_DATA_RELEASE (1<<0) #define BTDM_CFG_HCI_UART (1<<1) #define BTDM_CFG_CONTROLLER_RUN_APP_CPU (1<<2) +#define BTDM_CFG_SCAN_DUPLICATE_OPTIONS (1<<3) +#define BTDM_CFG_SEND_ADV_RESERVED_SIZE (1<<4) /* Other reserved for future */ /* not for user call, so don't put to include file */ @@ -706,6 +708,10 @@ static uint32_t btdm_config_mask_load(void) #if CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE == 1 mask |= BTDM_CFG_CONTROLLER_RUN_APP_CPU; #endif + mask |= BTDM_CFG_SCAN_DUPLICATE_OPTIONS; + + mask |= BTDM_CFG_SEND_ADV_RESERVED_SIZE; + return mask; } diff --git a/components/bt/include/esp_bt.h b/components/bt/include/esp_bt.h index 2b06c09d11..1fda81dad0 100644 --- a/components/bt/include/esp_bt.h +++ b/components/bt/include/esp_bt.h @@ -35,9 +35,19 @@ typedef struct { uint8_t controller_task_prio; /*!< Bluetooth controller task priority */ uint8_t hci_uart_no; /*!< If use UART1/2 as HCI IO interface, indicate UART number */ uint32_t hci_uart_baudrate; /*!< If use UART1/2 as HCI IO interface, indicate UART baudrate */ + uint8_t scan_duplicate_mode; /*!< If use UART1/2 as HCI IO interface, indicate UART baudrate */ + uint16_t normal_adv_size; /*!< Normal adv size for scan duplicate */ + uint16_t mesh_adv_size; /*!< Mesh adv size for scan duplicate */ + uint16_t send_adv_reserved_size; /*!< Controller minimum memory value */ + uint32_t controller_debug_flag; /*!< Controller debug log flag */ } esp_bt_controller_config_t; #ifdef CONFIG_BT_ENABLED +/* While scanning, if the free memory value in controller is less than SCAN_SEND_ADV_RESERVED_SIZE, +the adv packet will be discarded until the memory is restored. */ +#define SCAN_SEND_ADV_RESERVED_SIZE 1000 +/* open controller log debug when adv lost */ +#define CONTROLLER_ADV_LOST_DEBUG_BIT (0<<0) #ifdef CONFIG_BT_HCI_UART_NO #define BT_HCI_UART_NO_DEFAULT CONFIG_BT_HCI_UART_NO @@ -51,12 +61,44 @@ typedef struct { #define BT_HCI_UART_BAUDRATE_DEFAULT 921600 #endif /* BT_HCI_UART_BAUDRATE_DEFAULT */ +/* normal adv cache size */ +#ifdef CONFIG_DUPLICATE_SCAN_CACHE_SIZE +#define NORMAL_SCAN_DUPLICATE_CACHE_SIZE CONFIG_DUPLICATE_SCAN_CACHE_SIZE +#else +#define NORMAL_SCAN_DUPLICATE_CACHE_SIZE 20 +#endif + +#ifndef CONFIG_BLE_MESH_SCAN_DUPLICATE_EN +#define CONFIG_BLE_MESH_SCAN_DUPLICATE_EN FALSE +#endif + +#define SCAN_DUPLICATE_MODE_NORMAL_ADV_ONLY 0 +#define SCAN_DUPLICATE_MODE_NORMAL_ADV_MESH_ADV 1 + +#if CONFIG_BLE_MESH_SCAN_DUPLICATE_EN + #define SCAN_DUPLICATE_MODE SCAN_DUPLICATE_MODE_NORMAL_ADV_MESH_ADV + #ifdef CONFIG_MESH_DUPLICATE_SCAN_CACHE_SIZE + #define MESH_DUPLICATE_SCAN_CACHE_SIZE CONFIG_MESH_DUPLICATE_SCAN_CACHE_SIZE + #else + #define MESH_DUPLICATE_SCAN_CACHE_SIZE 50 + #endif +#else + #define SCAN_DUPLICATE_MODE SCAN_DUPLICATE_MODE_NORMAL_ADV_ONLY + #define MESH_DUPLICATE_SCAN_CACHE_SIZE 0 +#endif + #define BT_CONTROLLER_INIT_CONFIG_DEFAULT() { \ .controller_task_stack_size = ESP_TASK_BT_CONTROLLER_STACK, \ .controller_task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \ .hci_uart_no = BT_HCI_UART_NO_DEFAULT, \ .hci_uart_baudrate = BT_HCI_UART_BAUDRATE_DEFAULT, \ + .scan_duplicate_mode = SCAN_DUPLICATE_MODE, \ + .normal_adv_size = NORMAL_SCAN_DUPLICATE_CACHE_SIZE, \ + .mesh_adv_size = MESH_DUPLICATE_SCAN_CACHE_SIZE, \ + .send_adv_reserved_size = SCAN_SEND_ADV_RESERVED_SIZE, \ + .controller_debug_flag = CONTROLLER_ADV_LOST_DEBUG_BIT, \ }; + #else #define BT_CONTROLLER_INIT_CONFIG_DEFAULT() {0}; _Static_assert(0, "please enable bluetooth in menuconfig to use bt.h"); #endif diff --git a/components/bt/lib b/components/bt/lib index 16516d7009..7c55331605 160000 --- a/components/bt/lib +++ b/components/bt/lib @@ -1 +1 @@ -Subproject commit 16516d7009f1c31c21939047447a95238194de40 +Subproject commit 7c55331605beefea4882efc4343c23b28eb38d83 diff --git a/components/idf_test/integration_test/TC_IT_BTSTK_GAP.yml b/components/idf_test/integration_test/TC_IT_BTSTK_GAP.yml index ad55be7e63..02a4ae7c57 100644 --- a/components/idf_test/integration_test/TC_IT_BTSTK_GAP.yml +++ b/components/idf_test/integration_test/TC_IT_BTSTK_GAP.yml @@ -607,7 +607,7 @@ test cases: - ["R SSC1 C +BLEADV:SetAdv,OK"] - *open_capture_nic - *dut1_stop_adv - - - LOOP 2 2 "['0x20-0x40','0xA0-0xB0']" "['NPDU','PDU']" + - - LOOP 2 2 "['0x20-0x40','0xA0-0xB0']" "['PDU','PDU']" - [""] - - "SSC SSC1 bleadv -D -z start -t 2 -i {%s}" - ["R SSC1 C +BLEADV:OK"] @@ -637,7 +637,7 @@ test cases: - ["R SSC1 C +BLEADV:SetAdv,OK"] - *open_capture_nic - *dut1_stop_adv - - - LOOP 2 2 "['0x20-0x40','0xA0-0xB0']" "['NPDU','PDU']" + - - LOOP 2 2 "['0x20-0x40','0xA0-0xB0']" "['PDU','PDU']" - [""] - - "SSC SSC1 bleadv -D -z start -t 3 -i {%s}" - ["R SSC1 C +BLEADV:OK"] diff --git a/examples/bluetooth/ble_eddystone/main/esp_eddystone_demo.c b/examples/bluetooth/ble_eddystone/main/esp_eddystone_demo.c index d7ff377086..7f6e67b862 100644 --- a/examples/bluetooth/ble_eddystone/main/esp_eddystone_demo.c +++ b/examples/bluetooth/ble_eddystone/main/esp_eddystone_demo.c @@ -41,7 +41,8 @@ static esp_ble_scan_params_t ble_scan_params = { .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, .scan_interval = 0x50, - .scan_window = 0x30 + .scan_window = 0x30, + .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE }; static void esp_eddystone_show_inform(const esp_eddystone_result_t* res) diff --git a/examples/bluetooth/ble_ibeacon/main/ibeacon_demo.c b/examples/bluetooth/ble_ibeacon/main/ibeacon_demo.c index 5db17265a7..dcad4dd4a2 100644 --- a/examples/bluetooth/ble_ibeacon/main/ibeacon_demo.c +++ b/examples/bluetooth/ble_ibeacon/main/ibeacon_demo.c @@ -46,7 +46,8 @@ static esp_ble_scan_params_t ble_scan_params = { .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, .scan_interval = 0x50, - .scan_window = 0x30 + .scan_window = 0x30, + .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE }; #elif (IBEACON_MODE == IBEACON_SENDER) diff --git a/examples/bluetooth/ble_spp_client/main/spp_client_demo.c b/examples/bluetooth/ble_spp_client/main/spp_client_demo.c index 28711a2b42..03561acb8e 100644 --- a/examples/bluetooth/ble_spp_client/main/spp_client_demo.c +++ b/examples/bluetooth/ble_spp_client/main/spp_client_demo.c @@ -88,7 +88,8 @@ static esp_ble_scan_params_t ble_scan_params = { .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, .scan_interval = 0x50, - .scan_window = 0x30 + .scan_window = 0x30, + .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE }; static const char device_name[] = "ESP_SPP_SERVER"; diff --git a/examples/bluetooth/ble_throughput/throughput_client/main/example_ble_client_throughput.c b/examples/bluetooth/ble_throughput/throughput_client/main/example_ble_client_throughput.c index a124e96e7a..48b61d0d82 100644 --- a/examples/bluetooth/ble_throughput/throughput_client/main/example_ble_client_throughput.c +++ b/examples/bluetooth/ble_throughput/throughput_client/main/example_ble_client_throughput.c @@ -91,7 +91,8 @@ static esp_ble_scan_params_t ble_scan_params = { .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, .scan_interval = 0x50, - .scan_window = 0x30 + .scan_window = 0x30, + .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE }; struct gattc_profile_inst { diff --git a/examples/bluetooth/gatt_client/main/gattc_demo.c b/examples/bluetooth/gatt_client/main/gattc_demo.c index 8817a93546..1f2cc20e41 100644 --- a/examples/bluetooth/gatt_client/main/gattc_demo.c +++ b/examples/bluetooth/gatt_client/main/gattc_demo.c @@ -72,7 +72,8 @@ static esp_ble_scan_params_t ble_scan_params = { .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, .scan_interval = 0x50, - .scan_window = 0x30 + .scan_window = 0x30, + .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE }; struct gattc_profile_inst { diff --git a/examples/bluetooth/gatt_security_client/main/example_ble_sec_gattc_demo.c b/examples/bluetooth/gatt_security_client/main/example_ble_sec_gattc_demo.c index aa068ff6f1..16a23fdd6a 100644 --- a/examples/bluetooth/gatt_security_client/main/example_ble_sec_gattc_demo.c +++ b/examples/bluetooth/gatt_security_client/main/example_ble_sec_gattc_demo.c @@ -59,7 +59,8 @@ static esp_ble_scan_params_t ble_scan_params = { .own_addr_type = BLE_ADDR_TYPE_RANDOM, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, .scan_interval = 0x50, - .scan_window = 0x30 + .scan_window = 0x30, + .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE }; diff --git a/examples/bluetooth/gattc_multi_connect/main/gattc_multi_connect.c b/examples/bluetooth/gattc_multi_connect/main/gattc_multi_connect.c index 84f48a5d0a..71f70d4701 100644 --- a/examples/bluetooth/gattc_multi_connect/main/gattc_multi_connect.c +++ b/examples/bluetooth/gattc_multi_connect/main/gattc_multi_connect.c @@ -95,7 +95,8 @@ static esp_ble_scan_params_t ble_scan_params = { .own_addr_type = BLE_ADDR_TYPE_PUBLIC, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, .scan_interval = 0x50, - .scan_window = 0x30 + .scan_window = 0x30, + .scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE }; struct gattc_profile_inst { From b14bbd4205f7c300bd8a5aea0a104d2d40a1ddce Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 21 May 2018 17:33:10 +1000 Subject: [PATCH 142/187] gen_esp_err_to_name.py: Use normal file I/O instead of mmap() mmap is different on Python for Windows --- tools/gen_esp_err_to_name.py | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/tools/gen_esp_err_to_name.py b/tools/gen_esp_err_to_name.py index 1dfe15bab5..7281ed5511 100755 --- a/tools/gen_esp_err_to_name.py +++ b/tools/gen_esp_err_to_name.py @@ -16,7 +16,6 @@ import os import argparse -import mmap import re import fnmatch import string @@ -277,19 +276,14 @@ def main(): idf_path = os.path.relpath(full_path, os.environ['IDF_PATH']) if idf_path in ignore_files: continue - with open(full_path, "r+b") as f: - try: - map = mmap.mmap(f.fileno(), 0, prot=mmap.ACCESS_READ) - except ValueError: - pass # An empty file cannot be mmaped - else: - for line in iter(map.readline, ""): - # match also ESP_OK and ESP_FAIL because some of ESP_ERRs are referencing them - if re.match(r"\s*#define\s+(ESP_ERR_|ESP_OK|ESP_FAIL)", line): - try: - process(str.strip(line), idf_path) - except InputError as e: - print (e) + with open(full_path, "r+") as f: + for line in f: + # match also ESP_OK and ESP_FAIL because some of ESP_ERRs are referencing them + if re.match(r"\s*#define\s+(ESP_ERR_|ESP_OK|ESP_FAIL)", line): + try: + process(str.strip(line), idf_path) + except InputError as e: + print (e) process_remaining_errors() From ae8ed8dad8134d41e39d8d8173c83a83a0c51419 Mon Sep 17 00:00:00 2001 From: Amey Inamdar Date: Thu, 12 Apr 2018 10:47:21 +0530 Subject: [PATCH 143/187] bt-a2dp: BT A2DP sink and source selection is now runtime Earlier they have to be selected at the compile time through sdkconfig. A2DP sink and source application tested with this change. Signed-off-by: Amey Inamdar --- components/bt/Kconfig | 14 ++------------ .../bluedroid/btc/profile/std/a2dp/btc_a2dp.c | 11 ++++++----- .../btc/profile/std/a2dp/btc_a2dp_control.c | 9 +++++---- .../btc/profile/std/a2dp/btc_a2dp_sink.c | 1 + .../bt/bluedroid/btc/profile/std/a2dp/btc_av.c | 17 +++++++++++++++++ .../bluedroid/btc/profile/std/include/btc_av.h | 12 ++++++++++++ .../bluedroid/common/include/common/bt_target.h | 8 +------- examples/bluetooth/a2dp_sink/sdkconfig.defaults | 2 -- .../bluetooth/a2dp_source/sdkconfig.defaults | 2 -- 9 files changed, 44 insertions(+), 32 deletions(-) diff --git a/components/bt/Kconfig b/components/bt/Kconfig index 37d660cf98..cc301947b4 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -120,24 +120,14 @@ config A2DP_ENABLE help Advanced Audio Distrubution Profile -choice A2DP_ROLE - prompt "A2DP ROLE config" - depends on A2DP_ENABLE - -config A2DP_SINK_ENABLE - bool "SINK" -config A2DP_SRC_ENABLE - bool "SOURCE" -endchoice - config A2DP_SINK_TASK_STACK_SIZE int "A2DP sink (audio stream decoding) task stack size" - depends on A2DP_ENABLE && A2DP_SINK_ENABLE + depends on A2DP_ENABLE default 2048 config A2DP_SOURCE_TASK_STACK_SIZE int "A2DP source (audio stream encoding) task stack size" - depends on A2DP_ENABLE && A2DP_SRC_ENABLE + depends on A2DP_ENABLE default 2048 config BT_SPP_ENABLED diff --git a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp.c b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp.c index 3987d05c87..43d8f93290 100644 --- a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp.c +++ b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp.c @@ -49,9 +49,10 @@ void btc_a2dp_on_init(void) void btc_a2dp_on_idle(void) { - APPL_TRACE_EVENT("## ON A2DP IDLE ## peer_sep = %d", btc_av_get_peer_sep()); + APPL_TRACE_EVENT("## ON A2DP IDLE ## peer_sep = %d, service id = %d", btc_av_get_peer_sep(), + btc_av_get_service_id()); #if BTC_AV_SRC_INCLUDED - if (btc_av_get_peer_sep() == AVDT_TSEP_SNK) { + if (btc_av_get_peer_sep() == AVDT_TSEP_SNK && btc_av_get_service_id() == BTA_A2DP_SOURCE_SERVICE_ID) { btc_a2dp_source_on_idle(); } #endif // BTC_AV_SRC_INCLUDED @@ -59,7 +60,7 @@ void btc_a2dp_on_idle(void) bta_av_co_init(); #if BTC_AV_SINK_INCLUDED - if (btc_av_get_peer_sep() == AVDT_TSEP_SRC) { + if (btc_av_get_peer_sep() == AVDT_TSEP_SRC && btc_av_get_service_id() == BTA_A2DP_SINK_SERVICE_ID) { btc_a2dp_sink_on_idle(); } #endif // BTC_AV_SINK_INCLUDED @@ -120,7 +121,7 @@ void btc_a2dp_on_stopped(tBTA_AV_SUSPEND *p_av) { APPL_TRACE_EVENT("## ON A2DP STOPPED ##"); #if BTC_AV_SINK_INCLUDED - if (btc_av_get_peer_sep() == AVDT_TSEP_SRC) { + if (btc_av_get_peer_sep() == AVDT_TSEP_SRC && btc_av_get_service_id() == BTA_A2DP_SINK_SERVICE_ID) { btc_a2dp_sink_on_stopped(p_av); return; } @@ -140,7 +141,7 @@ void btc_a2dp_on_suspended(tBTA_AV_SUSPEND *p_av) { APPL_TRACE_EVENT("## ON A2DP SUSPENDED ##"); #if BTC_AV_SINK_INCLUDED - if (btc_av_get_peer_sep() == AVDT_TSEP_SRC) { + if (btc_av_get_peer_sep() == AVDT_TSEP_SRC && btc_av_get_service_id() == BTA_A2DP_SINK_SERVICE_ID) { btc_a2dp_sink_on_suspended(p_av); return; } diff --git a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c index 6c6f30f1a9..aca3f5d860 100644 --- a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c +++ b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c @@ -75,7 +75,7 @@ void btc_a2dp_control_command_ack(int status) static void btc_a2dp_datapath_open(void) { #if BTC_AV_SRC_INCLUDED - if (btc_av_get_peer_sep() == AVDT_TSEP_SNK) { + if (btc_av_get_peer_sep() == AVDT_TSEP_SNK && btc_av_get_service_id() == BTA_A2DP_SOURCE_SERVICE_ID) { /* Start the media task to encode SBC */ btc_a2dp_source_start_audio_req(); @@ -147,7 +147,7 @@ void btc_a2dp_control_media_ctrl(esp_a2d_media_ctrl_t ctrl) btc_a2dp_dispatch_datapath_evt(BTC_AV_DATAPATH_OPEN_EVT); #if (BTC_AV_SINK_INCLUDED == TRUE) - if (btc_av_get_peer_sep() == AVDT_TSEP_SRC) { + if (btc_av_get_peer_sep() == AVDT_TSEP_SRC && btc_av_get_service_id() == BTA_A2DP_SINK_SERVICE_ID) { btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_SUCCESS); } #endif @@ -160,7 +160,8 @@ void btc_a2dp_control_media_ctrl(esp_a2d_media_ctrl_t ctrl) break; case ESP_A2D_MEDIA_CTRL_STOP: #if BTC_AV_SRC_INCLUDED - if (btc_av_get_peer_sep() == AVDT_TSEP_SNK && !btc_a2dp_source_is_streaming()) { + if (btc_av_get_peer_sep() == AVDT_TSEP_SNK && !btc_a2dp_source_is_streaming() && + btc_av_get_service_id() == BTA_A2DP_SOURCE_SERVICE_ID) { /* we are already stopped, just ack back*/ btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_SUCCESS); break; @@ -168,7 +169,7 @@ void btc_a2dp_control_media_ctrl(esp_a2d_media_ctrl_t ctrl) #endif /* BTC_AV_SRC_INCLUDED */ btc_dispatch_sm_event(BTC_AV_STOP_STREAM_REQ_EVT, NULL, 0); #if (BTC_AV_SINK_INCLUDED == TRUE) - if (btc_av_get_peer_sep() == AVDT_TSEP_SRC) { + if (btc_av_get_peer_sep() == AVDT_TSEP_SRC && btc_av_get_service_id() == BTA_A2DP_SINK_SERVICE_ID) { btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_SUCCESS); } #endif diff --git a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c index e5747e62be..2722b3e9bd 100644 --- a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c +++ b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c @@ -588,6 +588,7 @@ static void btc_a2dp_sink_handle_inc_media(tBT_SBC_HDR *p_msg) UINT32 sbc_frame_len = p_msg->len - 1; availPcmBytes = 2 * sizeof(pcmData); + /* XXX: Check if the below check is correct, we are checking for peer to be sink when we are sink */ if (btc_av_get_peer_sep() == AVDT_TSEP_SNK || (btc_aa_snk_cb.rx_flush)) { APPL_TRACE_DEBUG(" State Changed happened in this tick "); return; diff --git a/components/bt/bluedroid/btc/profile/std/a2dp/btc_av.c b/components/bt/bluedroid/btc/profile/std/a2dp/btc_av.c index 0541111886..2911a0d7ce 100644 --- a/components/bt/bluedroid/btc/profile/std/a2dp/btc_av.c +++ b/components/bt/bluedroid/btc/profile/std/a2dp/btc_av.c @@ -72,6 +72,7 @@ typedef enum { ******************************************************************************/ typedef struct { + int service_id; tBTA_AV_HNDL bta_handle; bt_bdaddr_t peer_bda; btc_sm_handle_t sm_handle; @@ -957,6 +958,7 @@ static void btc_av_event_free_data(btc_sm_event_t event, void *p_data) static bt_status_t btc_av_init(int service_id) { if (btc_av_cb.sm_handle == NULL) { + btc_av_cb.service_id = service_id; bool stat = false; if (service_id == BTA_A2DP_SOURCE_SERVICE_ID) { #if BTC_AV_SRC_INCLUDED @@ -1265,6 +1267,21 @@ BOOLEAN btc_av_is_connected(void) return ((state == BTC_AV_STATE_OPENED) || (state == BTC_AV_STATE_STARTED)); } +/******************************************************************************* + * + * Function btc_av_get_service_id + * + * Description Get the current AV service ID. + * + * Returns The stream endpoint type: either BTA_A2DP_SOURCE_SERVICE_ID or + * BTA_A2DP_SINK_SERVICE_ID. + * + ******************************************************************************/ +uint8_t btc_av_get_service_id(void) +{ + return btc_av_cb.service_id; +} + /******************************************************************************* * * Function btc_av_get_peer_sep diff --git a/components/bt/bluedroid/btc/profile/std/include/btc_av.h b/components/bt/bluedroid/btc/profile/std/include/btc_av.h index 78cf7cf0d9..4f3554bb39 100644 --- a/components/bt/bluedroid/btc/profile/std/include/btc_av.h +++ b/components/bt/bluedroid/btc/profile/std/include/btc_av.h @@ -203,6 +203,18 @@ BOOLEAN btc_av_is_peer_edr(void); ********************************************************************************/ void btc_av_clear_remote_suspend_flag(void); +/******************************************************************************* + * + * Function btc_av_get_service_id + * + * Description Get the current AV service ID. + * + * Returns The stream endpoint type: either BTA_A2DP_SOURCE_SERVICE_ID or + * BTA_A2DP_SINK_SERVICE_ID. + * + ******************************************************************************/ +uint8_t btc_av_get_service_id(void); + #endif ///BTC_AV_INCLUDED == TRUE #endif /* __BTC_AV_H__ */ diff --git a/components/bt/bluedroid/common/include/common/bt_target.h b/components/bt/bluedroid/common/include/common/bt_target.h index 55b84b808f..9edb93dfd0 100644 --- a/components/bt/bluedroid/common/include/common/bt_target.h +++ b/components/bt/bluedroid/common/include/common/bt_target.h @@ -60,18 +60,12 @@ #define AVCT_INCLUDED TRUE #define AVRC_INCLUDED TRUE #define BTC_AV_INCLUDED TRUE -#endif /* CONFIG_A2DP_ENABLE */ - -#if CONFIG_A2DP_SINK_ENABLE #define BTA_AV_SINK_INCLUDED TRUE #define BTC_AV_SINK_INCLUDED TRUE #define SBC_DEC_INCLUDED TRUE -#endif /* CONFIG_A2DP_SINK_ENABLE */ - -#if CONFIG_A2DP_SRC_ENABLE #define BTC_AV_SRC_INCLUDED TRUE #define SBC_ENC_INCLUDED TRUE -#endif /* CONFIG_A2DP_SRC_ENABLE */ +#endif /* CONFIG_A2DP_ENABLE */ #if CONFIG_BT_SPP_ENABLED #define RFCOMM_INCLUDED TRUE diff --git a/examples/bluetooth/a2dp_sink/sdkconfig.defaults b/examples/bluetooth/a2dp_sink/sdkconfig.defaults index d99fa240cb..82779f66ef 100644 --- a/examples/bluetooth/a2dp_sink/sdkconfig.defaults +++ b/examples/bluetooth/a2dp_sink/sdkconfig.defaults @@ -4,8 +4,6 @@ CONFIG_BT_ENABLED=y CONFIG_BLUEDROID_ENABLED=y CONFIG_CLASSIC_BT_ENABLED=y CONFIG_A2DP_ENABLE=y -CONFIG_A2DP_SINK_ENABLE=y -CONFIG_A2DP_SRC_ENABLE= CONFIG_BT_SPP_ENABLED= CONFIG_GATTS_ENABLE= CONFIG_GATTC_ENABLE= diff --git a/examples/bluetooth/a2dp_source/sdkconfig.defaults b/examples/bluetooth/a2dp_source/sdkconfig.defaults index 1ec00447a9..6625f76f4d 100644 --- a/examples/bluetooth/a2dp_source/sdkconfig.defaults +++ b/examples/bluetooth/a2dp_source/sdkconfig.defaults @@ -4,8 +4,6 @@ CONFIG_BT_ENABLED=y CONFIG_BLUEDROID_ENABLED=y CONFIG_CLASSIC_BT_ENABLED=y CONFIG_A2DP_ENABLE=y -CONFIG_A2DP_SINK_ENABLE= -CONFIG_A2DP_SRC_ENABLE=y CONFIG_BT_SPP_ENABLED= CONFIG_GATTS_ENABLE= CONFIG_GATTC_ENABLE= From e8525396ddfc8a61bf8951ad44b778c9dbe0a15f Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 21 May 2018 14:50:27 +1000 Subject: [PATCH 144/187] test: Allow per-unit-test timeouts Work around for "(WL) write/read speed test" taking >30s in some configs --- components/fatfs/test/test_fatfs_sdmmc.c | 2 +- components/fatfs/test/test_fatfs_spiflash.c | 2 +- tools/tiny-test-fw/CIAssignUnitTest.py | 5 +++++ tools/unit-test-app/tools/TagDefinition.yml | 3 +++ tools/unit-test-app/tools/UnitTestParser.py | 6 +++--- tools/unit-test-app/unit_test.py | 15 ++++++++------- 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/components/fatfs/test/test_fatfs_sdmmc.c b/components/fatfs/test/test_fatfs_sdmmc.c index 6dc1ec3fc0..c813022071 100644 --- a/components/fatfs/test/test_fatfs_sdmmc.c +++ b/components/fatfs/test/test_fatfs_sdmmc.c @@ -154,7 +154,7 @@ TEST_CASE("(SD) multiple tasks can use same volume", "[fatfs][test_env=UT_T1_SDM static void speed_test(void* buf, size_t buf_size, size_t file_size, bool write); -TEST_CASE("(SD) write/read speed test", "[fatfs][sd][test_env=UT_T1_SDMODE]") +TEST_CASE("(SD) write/read speed test", "[fatfs][sd][test_env=UT_T1_SDMODE][timeout=60]") { size_t heap_size; HEAP_SIZE_CAPTURE(heap_size); diff --git a/components/fatfs/test/test_fatfs_spiflash.c b/components/fatfs/test/test_fatfs_spiflash.c index 55b3b68788..70f73f0e53 100644 --- a/components/fatfs/test/test_fatfs_spiflash.c +++ b/components/fatfs/test/test_fatfs_spiflash.c @@ -145,7 +145,7 @@ TEST_CASE("(WL) multiple tasks can use same volume", "[fatfs][wear_levelling]") test_teardown(); } -TEST_CASE("(WL) write/read speed test", "[fatfs][wear_levelling]") +TEST_CASE("(WL) write/read speed test", "[fatfs][wear_levelling][timeout=60]") { /* Erase partition before running the test to get consistent results */ const esp_partition_t* part = get_test_data_partition(); diff --git a/tools/tiny-test-fw/CIAssignUnitTest.py b/tools/tiny-test-fw/CIAssignUnitTest.py index 03768dbf86..3c31514589 100644 --- a/tools/tiny-test-fw/CIAssignUnitTest.py +++ b/tools/tiny-test-fw/CIAssignUnitTest.py @@ -38,12 +38,17 @@ class Group(CIAssignTest.Group): return test_app[3:] def _create_extra_data(self, test_function): + """ + For unit test case, we need to copy some attributes of test cases into config file. + So unit test function knows how to run the case. + """ case_data = [] for case in self.case_list: one_case_data = { "config": self._get_ut_config(self._get_case_attr(case, "Test App")), "name": self._get_case_attr(case, "summary"), "reset": self._get_case_attr(case, "reset"), + "timeout": self._get_case_attr(case, "timeout"), } if test_function in ["run_multiple_devices_cases", "run_multiple_stage_cases"]: diff --git a/tools/unit-test-app/tools/TagDefinition.yml b/tools/unit-test-app/tools/TagDefinition.yml index 293208d7b2..f84d9a7024 100644 --- a/tools/unit-test-app/tools/TagDefinition.yml +++ b/tools/unit-test-app/tools/TagDefinition.yml @@ -15,3 +15,6 @@ multi_device: multi_stage: default: "Yes" omitted: "No" +timeout: + default: 30 + omitted: 30 diff --git a/tools/unit-test-app/tools/UnitTestParser.py b/tools/unit-test-app/tools/UnitTestParser.py index db9a94119a..688e4ce37d 100644 --- a/tools/unit-test-app/tools/UnitTestParser.py +++ b/tools/unit-test-app/tools/UnitTestParser.py @@ -8,7 +8,6 @@ import hashlib from copy import deepcopy import CreateSectionTable - TEST_CASE_PATTERN = { "initial condition": "UTINIT1", "SDK": "ESP32_IDF", @@ -21,7 +20,7 @@ TEST_CASE_PATTERN = { "test environment": "UT_T1_1", "reset": "", "expected result": "1. set succeed", - "cmd set": "test_unit_test_case", + "cmd set": "test_unit_test_case" } CONFIG_FILE_PATTERN = { @@ -191,7 +190,8 @@ class Parser(object): "sub module": self.module_map[prop["module"]]['sub module'], "summary": name, "multi_device": prop["multi_device"], - "multi_stage": prop["multi_stage"]}) + "multi_stage": prop["multi_stage"], + "timeout": int(prop["timeout"])}) return test_case def dump_test_cases(self, test_cases): diff --git a/tools/unit-test-app/unit_test.py b/tools/unit-test-app/unit_test.py index 594a71becf..e049e7505e 100644 --- a/tools/unit-test-app/unit_test.py +++ b/tools/unit-test-app/unit_test.py @@ -27,7 +27,8 @@ RESET_PATTERN = re.compile(r"(ets [\w]{3}\s+[\d]{1,2} [\d]{4} [\d]{2}:[\d]{2}:[\ EXCEPTION_PATTERN = re.compile(r"(Guru Meditation Error: Core\s+\d panic'ed \([\w].*?\))") ABORT_PATTERN = re.compile(r"(abort\(\) was called at PC 0x[a-eA-E\d]{8} on core \d)") FINISH_PATTERN = re.compile(r"1 Tests (\d) Failures (\d) Ignored") -UT_TIMEOUT = 30 + +STARTUP_TIMEOUT=10 def format_test_case_config(test_case_data): @@ -142,7 +143,7 @@ def run_unit_test_cases(env, extra_data): # to determine if DUT is ready to test. dut.write("-", flush=False) dut.expect_any(UT_APP_BOOT_UP_DONE, - "0 Tests 0 Failures 0 Ignored", timeout=UT_TIMEOUT) + "0 Tests 0 Failures 0 Ignored", timeout=STARTUP_TIMEOUT) # run test case dut.write("\"{}\"".format(one_case["name"])) @@ -203,7 +204,7 @@ def run_unit_test_cases(env, extra_data): (ABORT_PATTERN, handle_exception_reset), (FINISH_PATTERN, handle_test_finish), (UT_APP_BOOT_UP_DONE, handle_reset_finish), - timeout=UT_TIMEOUT) + timeout=one_case["timeout"]) except ExpectTimeout: Utility.console_log("Timeout in expect", color="orange") one_case_finish(False) @@ -223,7 +224,7 @@ class Handler(threading.Thread): SEND_SIGNAL_PATTERN = re.compile(r'Send signal: \[(.+)\]!') FINISH_PATTERN = re.compile(r"1 Tests (\d) Failures (\d) Ignored") - def __init__(self, dut, sent_signal_list, lock, parent_case_name, child_case_index, timeout=30): + def __init__(self, dut, sent_signal_list, lock, parent_case_name, child_case_index, timeout): self.dut = dut self.sent_signal_list = sent_signal_list self.lock = lock @@ -288,7 +289,7 @@ class Handler(threading.Thread): (self.WAIT_SIGNAL_PATTERN, device_wait_action), # wait signal pattern (self.SEND_SIGNAL_PATTERN, device_send_action), # send signal pattern (self.FINISH_PATTERN, handle_device_test_finish), # test finish pattern - timeout=UT_TIMEOUT) + timeout=self.timeout) except ExpectTimeout: Utility.console_log("Timeout in expect", color="orange") one_device_case_finish(False) @@ -321,7 +322,7 @@ def case_run(duts, ut_config, env, one_case, failed_cases): for i in range(case_num): dut = get_dut(duts, env, "dut%d" % i, ut_config) threads.append(Handler(dut, send_signal_list, lock, - parent_case, i)) + parent_case, i, one_case["timeout"])) for thread in threads: thread.setDaemon(True) thread.start() @@ -487,7 +488,7 @@ def run_multiple_stage_cases(env, extra_data): (ABORT_PATTERN, handle_exception_reset), (FINISH_PATTERN, handle_test_finish), (UT_APP_BOOT_UP_DONE, handle_next_stage), - timeout=UT_TIMEOUT) + timeout=one_case["timeout"]) except ExpectTimeout: Utility.console_log("Timeout in expect", color="orange") one_case_finish(False) From 156dd4841d5b0a6f4b03305f768a26b3a89217e0 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Mon, 21 May 2018 14:59:55 +1000 Subject: [PATCH 145/187] Temporarily disable SD CD/WP mode tests Tracked in TW22648 --- components/sdmmc/test/test_sd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/sdmmc/test/test_sd.c b/components/sdmmc/test/test_sd.c index 1808a0cdd0..d16dcd0e34 100644 --- a/components/sdmmc/test/test_sd.c +++ b/components/sdmmc/test/test_sd.c @@ -266,7 +266,7 @@ static void test_cd_input(int gpio_cd_num, const sdmmc_host_t* config) free(card); } -TEST_CASE("CD input works in SD mode", "[sd][test_env=UT_T1_SDMODE]") +TEST_CASE("CD input works in SD mode", "[sd][test_env=UT_T1_SDMODE][ignore]") { sdmmc_host_t config = SDMMC_HOST_DEFAULT(); sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); @@ -327,7 +327,7 @@ static void test_wp_input(int gpio_wp_num, const sdmmc_host_t* config) free(card); } -TEST_CASE("WP input works in SD mode", "[sd][test_env=UT_T1_SDMODE]") +TEST_CASE("WP input works in SD mode", "[sd][test_env=UT_T1_SDMODE][ignore]") { sdmmc_host_t config = SDMMC_HOST_DEFAULT(); sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); From c73575de4f175d3ae738b62d79cc70b6ac746c0e Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Wed, 25 Oct 2017 08:45:17 +0800 Subject: [PATCH 146/187] feat(sdio_slave): add headers for sdio slave components: slc, host, hinf --- components/esp32/ld/esp32.peripherals.ld | 3 + components/soc/esp32/include/soc/hinf_reg.h | 248 ++ .../soc/esp32/include/soc/hinf_struct.h | 134 + components/soc/esp32/include/soc/host_reg.h | 3144 ++++++++++++++++ .../soc/esp32/include/soc/host_struct.h | 891 +++++ components/soc/esp32/include/soc/slc_reg.h | 3244 +++++++++++++++++ components/soc/esp32/include/soc/slc_struct.h | 858 +++++ 7 files changed, 8522 insertions(+) create mode 100644 components/soc/esp32/include/soc/hinf_reg.h create mode 100644 components/soc/esp32/include/soc/hinf_struct.h create mode 100644 components/soc/esp32/include/soc/host_reg.h create mode 100644 components/soc/esp32/include/soc/host_struct.h create mode 100644 components/soc/esp32/include/soc/slc_reg.h create mode 100644 components/soc/esp32/include/soc/slc_struct.h diff --git a/components/esp32/ld/esp32.peripherals.ld b/components/esp32/ld/esp32.peripherals.ld index 621fedea13..3403ee8a8e 100644 --- a/components/esp32/ld/esp32.peripherals.ld +++ b/components/esp32/ld/esp32.peripherals.ld @@ -6,14 +6,17 @@ PROVIDE ( SIGMADELTA = 0x3ff44f00 ); PROVIDE ( RTCCNTL = 0x3ff48000 ); PROVIDE ( RTCIO = 0x3ff48400 ); PROVIDE ( SENS = 0x3ff48800 ); +PROVIDE ( HINF = 0x3ff4B000 ); PROVIDE ( UHCI1 = 0x3ff4C000 ); PROVIDE ( I2S0 = 0x3ff4F000 ); PROVIDE ( UART1 = 0x3ff50000 ); PROVIDE ( I2C0 = 0x3ff53000 ); PROVIDE ( UHCI0 = 0x3ff54000 ); +PROVIDE ( HOST = 0x3ff55000 ); PROVIDE ( RMT = 0x3ff56000 ); PROVIDE ( RMTMEM = 0x3ff56800 ); PROVIDE ( PCNT = 0x3ff57000 ); +PROVIDE ( SLC = 0x3ff58000 ); PROVIDE ( LEDC = 0x3ff59000 ); PROVIDE ( MCPWM0 = 0x3ff5E000 ); PROVIDE ( TIMERG0 = 0x3ff5F000 ); diff --git a/components/soc/esp32/include/soc/hinf_reg.h b/components/soc/esp32/include/soc/hinf_reg.h new file mode 100644 index 0000000000..aad357864e --- /dev/null +++ b/components/soc/esp32/include/soc/hinf_reg.h @@ -0,0 +1,248 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_HINF_REG_H_ +#define _SOC_HINF_REG_H_ + + +#include "soc.h" +#define HINF_CFG_DATA0_REG (DR_REG_HINF_BASE + 0x0) +/* HINF_DEVICE_ID_FN1 : R/W ;bitpos:[31:16] ;default: 16'h2222 ; */ +/*description: */ +#define HINF_DEVICE_ID_FN1 0x0000FFFF +#define HINF_DEVICE_ID_FN1_M ((HINF_DEVICE_ID_FN1_V)<<(HINF_DEVICE_ID_FN1_S)) +#define HINF_DEVICE_ID_FN1_V 0xFFFF +#define HINF_DEVICE_ID_FN1_S 16 +/* HINF_USER_ID_FN1 : R/W ;bitpos:[15:0] ;default: 16'h6666 ; */ +/*description: */ +#define HINF_USER_ID_FN1 0x0000FFFF +#define HINF_USER_ID_FN1_M ((HINF_USER_ID_FN1_V)<<(HINF_USER_ID_FN1_S)) +#define HINF_USER_ID_FN1_V 0xFFFF +#define HINF_USER_ID_FN1_S 0 + +#define HINF_CFG_DATA1_REG (DR_REG_HINF_BASE + 0x4) +/* HINF_SDIO20_CONF1 : R/W ;bitpos:[31:29] ;default: 3'h0 ; */ +/*description: */ +#define HINF_SDIO20_CONF1 0x00000007 +#define HINF_SDIO20_CONF1_M ((HINF_SDIO20_CONF1_V)<<(HINF_SDIO20_CONF1_S)) +#define HINF_SDIO20_CONF1_V 0x7 +#define HINF_SDIO20_CONF1_S 29 +/* HINF_FUNC2_EPS : RO ;bitpos:[28] ;default: 1'b0 ; */ +/*description: */ +#define HINF_FUNC2_EPS (BIT(28)) +#define HINF_FUNC2_EPS_M (BIT(28)) +#define HINF_FUNC2_EPS_V 0x1 +#define HINF_FUNC2_EPS_S 28 +/* HINF_SDIO_VER : R/W ;bitpos:[27:16] ;default: 12'h111 ; */ +/*description: */ +#define HINF_SDIO_VER 0x00000FFF +#define HINF_SDIO_VER_M ((HINF_SDIO_VER_V)<<(HINF_SDIO_VER_S)) +#define HINF_SDIO_VER_V 0xFFF +#define HINF_SDIO_VER_S 16 +/* HINF_SDIO20_CONF0 : R/W ;bitpos:[15:12] ;default: 4'b0 ; */ +/*description: */ +#define HINF_SDIO20_CONF0 0x0000000F +#define HINF_SDIO20_CONF0_M ((HINF_SDIO20_CONF0_V)<<(HINF_SDIO20_CONF0_S)) +#define HINF_SDIO20_CONF0_V 0xF +#define HINF_SDIO20_CONF0_S 12 +/* HINF_IOENABLE1 : RO ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define HINF_IOENABLE1 (BIT(11)) +#define HINF_IOENABLE1_M (BIT(11)) +#define HINF_IOENABLE1_V 0x1 +#define HINF_IOENABLE1_S 11 +/* HINF_EMP : RO ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define HINF_EMP (BIT(10)) +#define HINF_EMP_M (BIT(10)) +#define HINF_EMP_V 0x1 +#define HINF_EMP_S 10 +/* HINF_FUNC1_EPS : RO ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define HINF_FUNC1_EPS (BIT(9)) +#define HINF_FUNC1_EPS_M (BIT(9)) +#define HINF_FUNC1_EPS_V 0x1 +#define HINF_FUNC1_EPS_S 9 +/* HINF_CD_DISABLE : RO ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define HINF_CD_DISABLE (BIT(8)) +#define HINF_CD_DISABLE_M (BIT(8)) +#define HINF_CD_DISABLE_V 0x1 +#define HINF_CD_DISABLE_S 8 +/* HINF_IOENABLE2 : RO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define HINF_IOENABLE2 (BIT(7)) +#define HINF_IOENABLE2_M (BIT(7)) +#define HINF_IOENABLE2_V 0x1 +#define HINF_IOENABLE2_S 7 +/* HINF_SDIO_INT_MASK : R/W ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define HINF_SDIO_INT_MASK (BIT(6)) +#define HINF_SDIO_INT_MASK_M (BIT(6)) +#define HINF_SDIO_INT_MASK_V 0x1 +#define HINF_SDIO_INT_MASK_S 6 +/* HINF_SDIO_IOREADY2 : R/W ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define HINF_SDIO_IOREADY2 (BIT(5)) +#define HINF_SDIO_IOREADY2_M (BIT(5)) +#define HINF_SDIO_IOREADY2_V 0x1 +#define HINF_SDIO_IOREADY2_S 5 +/* HINF_SDIO_CD_ENABLE : R/W ;bitpos:[4] ;default: 1'b1 ; */ +/*description: */ +#define HINF_SDIO_CD_ENABLE (BIT(4)) +#define HINF_SDIO_CD_ENABLE_M (BIT(4)) +#define HINF_SDIO_CD_ENABLE_V 0x1 +#define HINF_SDIO_CD_ENABLE_S 4 +/* HINF_HIGHSPEED_MODE : RO ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define HINF_HIGHSPEED_MODE (BIT(3)) +#define HINF_HIGHSPEED_MODE_M (BIT(3)) +#define HINF_HIGHSPEED_MODE_V 0x1 +#define HINF_HIGHSPEED_MODE_S 3 +/* HINF_HIGHSPEED_ENABLE : R/W ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define HINF_HIGHSPEED_ENABLE (BIT(2)) +#define HINF_HIGHSPEED_ENABLE_M (BIT(2)) +#define HINF_HIGHSPEED_ENABLE_V 0x1 +#define HINF_HIGHSPEED_ENABLE_S 2 +/* HINF_SDIO_IOREADY1 : R/W ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define HINF_SDIO_IOREADY1 (BIT(1)) +#define HINF_SDIO_IOREADY1_M (BIT(1)) +#define HINF_SDIO_IOREADY1_V 0x1 +#define HINF_SDIO_IOREADY1_S 1 +/* HINF_SDIO_ENABLE : R/W ;bitpos:[0] ;default: 1'b1 ; */ +/*description: */ +#define HINF_SDIO_ENABLE (BIT(0)) +#define HINF_SDIO_ENABLE_M (BIT(0)) +#define HINF_SDIO_ENABLE_V 0x1 +#define HINF_SDIO_ENABLE_S 0 + +#define HINF_CFG_DATA7_REG (DR_REG_HINF_BASE + 0x1C) +/* HINF_SDIO_IOREADY0 : R/W ;bitpos:[17] ;default: 1'b1 ; */ +/*description: */ +#define HINF_SDIO_IOREADY0 (BIT(17)) +#define HINF_SDIO_IOREADY0_M (BIT(17)) +#define HINF_SDIO_IOREADY0_V 0x1 +#define HINF_SDIO_IOREADY0_S 17 +/* HINF_SDIO_RST : R/W ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define HINF_SDIO_RST (BIT(16)) +#define HINF_SDIO_RST_M (BIT(16)) +#define HINF_SDIO_RST_V 0x1 +#define HINF_SDIO_RST_S 16 +/* HINF_CHIP_STATE : R/W ;bitpos:[15:8] ;default: 8'b0 ; */ +/*description: */ +#define HINF_CHIP_STATE 0x000000FF +#define HINF_CHIP_STATE_M ((HINF_CHIP_STATE_V)<<(HINF_CHIP_STATE_S)) +#define HINF_CHIP_STATE_V 0xFF +#define HINF_CHIP_STATE_S 8 +/* HINF_PIN_STATE : R/W ;bitpos:[7:0] ;default: 8'b0 ; */ +/*description: */ +#define HINF_PIN_STATE 0x000000FF +#define HINF_PIN_STATE_M ((HINF_PIN_STATE_V)<<(HINF_PIN_STATE_S)) +#define HINF_PIN_STATE_V 0xFF +#define HINF_PIN_STATE_S 0 + +#define HINF_CIS_CONF0_REG (DR_REG_HINF_BASE + 0x20) +/* HINF_CIS_CONF_W0 : R/W ;bitpos:[31:0] ;default: 32'hffffffff ; */ +/*description: */ +#define HINF_CIS_CONF_W0 0xFFFFFFFF +#define HINF_CIS_CONF_W0_M ((HINF_CIS_CONF_W0_V)<<(HINF_CIS_CONF_W0_S)) +#define HINF_CIS_CONF_W0_V 0xFFFFFFFF +#define HINF_CIS_CONF_W0_S 0 + +#define HINF_CIS_CONF1_REG (DR_REG_HINF_BASE + 0x24) +/* HINF_CIS_CONF_W1 : R/W ;bitpos:[31:0] ;default: 32'hffffffff ; */ +/*description: */ +#define HINF_CIS_CONF_W1 0xFFFFFFFF +#define HINF_CIS_CONF_W1_M ((HINF_CIS_CONF_W1_V)<<(HINF_CIS_CONF_W1_S)) +#define HINF_CIS_CONF_W1_V 0xFFFFFFFF +#define HINF_CIS_CONF_W1_S 0 + +#define HINF_CIS_CONF2_REG (DR_REG_HINF_BASE + 0x28) +/* HINF_CIS_CONF_W2 : R/W ;bitpos:[31:0] ;default: 32'hffffffff ; */ +/*description: */ +#define HINF_CIS_CONF_W2 0xFFFFFFFF +#define HINF_CIS_CONF_W2_M ((HINF_CIS_CONF_W2_V)<<(HINF_CIS_CONF_W2_S)) +#define HINF_CIS_CONF_W2_V 0xFFFFFFFF +#define HINF_CIS_CONF_W2_S 0 + +#define HINF_CIS_CONF3_REG (DR_REG_HINF_BASE + 0x2C) +/* HINF_CIS_CONF_W3 : R/W ;bitpos:[31:0] ;default: 32'hffffffff ; */ +/*description: */ +#define HINF_CIS_CONF_W3 0xFFFFFFFF +#define HINF_CIS_CONF_W3_M ((HINF_CIS_CONF_W3_V)<<(HINF_CIS_CONF_W3_S)) +#define HINF_CIS_CONF_W3_V 0xFFFFFFFF +#define HINF_CIS_CONF_W3_S 0 + +#define HINF_CIS_CONF4_REG (DR_REG_HINF_BASE + 0x30) +/* HINF_CIS_CONF_W4 : R/W ;bitpos:[31:0] ;default: 32'hffffffff ; */ +/*description: */ +#define HINF_CIS_CONF_W4 0xFFFFFFFF +#define HINF_CIS_CONF_W4_M ((HINF_CIS_CONF_W4_V)<<(HINF_CIS_CONF_W4_S)) +#define HINF_CIS_CONF_W4_V 0xFFFFFFFF +#define HINF_CIS_CONF_W4_S 0 + +#define HINF_CIS_CONF5_REG (DR_REG_HINF_BASE + 0x34) +/* HINF_CIS_CONF_W5 : R/W ;bitpos:[31:0] ;default: 32'hffffffff ; */ +/*description: */ +#define HINF_CIS_CONF_W5 0xFFFFFFFF +#define HINF_CIS_CONF_W5_M ((HINF_CIS_CONF_W5_V)<<(HINF_CIS_CONF_W5_S)) +#define HINF_CIS_CONF_W5_V 0xFFFFFFFF +#define HINF_CIS_CONF_W5_S 0 + +#define HINF_CIS_CONF6_REG (DR_REG_HINF_BASE + 0x38) +/* HINF_CIS_CONF_W6 : R/W ;bitpos:[31:0] ;default: 32'hffffffff ; */ +/*description: */ +#define HINF_CIS_CONF_W6 0xFFFFFFFF +#define HINF_CIS_CONF_W6_M ((HINF_CIS_CONF_W6_V)<<(HINF_CIS_CONF_W6_S)) +#define HINF_CIS_CONF_W6_V 0xFFFFFFFF +#define HINF_CIS_CONF_W6_S 0 + +#define HINF_CIS_CONF7_REG (DR_REG_HINF_BASE + 0x3C) +/* HINF_CIS_CONF_W7 : R/W ;bitpos:[31:0] ;default: 32'hffffffff ; */ +/*description: */ +#define HINF_CIS_CONF_W7 0xFFFFFFFF +#define HINF_CIS_CONF_W7_M ((HINF_CIS_CONF_W7_V)<<(HINF_CIS_CONF_W7_S)) +#define HINF_CIS_CONF_W7_V 0xFFFFFFFF +#define HINF_CIS_CONF_W7_S 0 + +#define HINF_CFG_DATA16_REG (DR_REG_HINF_BASE + 0x40) +/* HINF_DEVICE_ID_FN2 : R/W ;bitpos:[31:16] ;default: 16'h3333 ; */ +/*description: */ +#define HINF_DEVICE_ID_FN2 0x0000FFFF +#define HINF_DEVICE_ID_FN2_M ((HINF_DEVICE_ID_FN2_V)<<(HINF_DEVICE_ID_FN2_S)) +#define HINF_DEVICE_ID_FN2_V 0xFFFF +#define HINF_DEVICE_ID_FN2_S 16 +/* HINF_USER_ID_FN2 : R/W ;bitpos:[15:0] ;default: 16'h6666 ; */ +/*description: */ +#define HINF_USER_ID_FN2 0x0000FFFF +#define HINF_USER_ID_FN2_M ((HINF_USER_ID_FN2_V)<<(HINF_USER_ID_FN2_S)) +#define HINF_USER_ID_FN2_V 0xFFFF +#define HINF_USER_ID_FN2_S 0 + +#define HINF_DATE_REG (DR_REG_HINF_BASE + 0xFC) +/* HINF_SDIO_DATE : R/W ;bitpos:[31:0] ;default: 32'h15030200 ; */ +/*description: */ +#define HINF_SDIO_DATE 0xFFFFFFFF +#define HINF_SDIO_DATE_M ((HINF_SDIO_DATE_V)<<(HINF_SDIO_DATE_S)) +#define HINF_SDIO_DATE_V 0xFFFFFFFF +#define HINF_SDIO_DATE_S 0 + + + + +#endif /*_SOC_HINF_REG_H_ */ + + diff --git a/components/soc/esp32/include/soc/hinf_struct.h b/components/soc/esp32/include/soc/hinf_struct.h new file mode 100644 index 0000000000..1c2d9e3b78 --- /dev/null +++ b/components/soc/esp32/include/soc/hinf_struct.h @@ -0,0 +1,134 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_HINF_STRUCT_H_ +#define _SOC_HINF_STRUCT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef volatile struct { + union { + struct { + uint32_t user_id_fn1: 16; + uint32_t device_id_fn1:16; + }; + uint32_t val; + } cfg_data0; + union { + struct { + uint32_t sdio_enable: 1; + uint32_t sdio_ioready1: 1; + uint32_t highspeed_enable: 1; + uint32_t highspeed_mode: 1; + uint32_t sdio_cd_enable: 1; + uint32_t sdio_ioready2: 1; + uint32_t sdio_int_mask: 1; + uint32_t ioenable2: 1; + uint32_t cd_disable: 1; + uint32_t func1_eps: 1; + uint32_t emp: 1; + uint32_t ioenable1: 1; + uint32_t sdio20_conf0: 4; + uint32_t sdio_ver: 12; + uint32_t func2_eps: 1; + uint32_t sdio20_conf1: 3; + }; + uint32_t val; + } cfg_data1; + uint32_t reserved_8; + uint32_t reserved_c; + uint32_t reserved_10; + uint32_t reserved_14; + uint32_t reserved_18; + union { + struct { + uint32_t pin_state: 8; + uint32_t chip_state: 8; + uint32_t sdio_rst: 1; + uint32_t sdio_ioready0: 1; + uint32_t reserved18: 14; + }; + uint32_t val; + } cfg_data7; + uint32_t cis_conf0; /**/ + uint32_t cis_conf1; /**/ + uint32_t cis_conf2; /**/ + uint32_t cis_conf3; /**/ + uint32_t cis_conf4; /**/ + uint32_t cis_conf5; /**/ + uint32_t cis_conf6; /**/ + uint32_t cis_conf7; /**/ + union { + struct { + uint32_t user_id_fn2: 16; + uint32_t device_id_fn2:16; + }; + uint32_t val; + } cfg_data16; + uint32_t reserved_44; + uint32_t reserved_48; + uint32_t reserved_4c; + uint32_t reserved_50; + uint32_t reserved_54; + uint32_t reserved_58; + uint32_t reserved_5c; + uint32_t reserved_60; + uint32_t reserved_64; + uint32_t reserved_68; + uint32_t reserved_6c; + uint32_t reserved_70; + uint32_t reserved_74; + uint32_t reserved_78; + uint32_t reserved_7c; + uint32_t reserved_80; + uint32_t reserved_84; + uint32_t reserved_88; + uint32_t reserved_8c; + uint32_t reserved_90; + uint32_t reserved_94; + uint32_t reserved_98; + uint32_t reserved_9c; + uint32_t reserved_a0; + uint32_t reserved_a4; + uint32_t reserved_a8; + uint32_t reserved_ac; + uint32_t reserved_b0; + uint32_t reserved_b4; + uint32_t reserved_b8; + uint32_t reserved_bc; + uint32_t reserved_c0; + uint32_t reserved_c4; + uint32_t reserved_c8; + uint32_t reserved_cc; + uint32_t reserved_d0; + uint32_t reserved_d4; + uint32_t reserved_d8; + uint32_t reserved_dc; + uint32_t reserved_e0; + uint32_t reserved_e4; + uint32_t reserved_e8; + uint32_t reserved_ec; + uint32_t reserved_f0; + uint32_t reserved_f4; + uint32_t reserved_f8; + uint32_t date; /**/ +} hinf_dev_t; +extern hinf_dev_t HINF; + +#ifdef __cplusplus +} +#endif + +#endif /* _SOC_HINF_STRUCT_H_ */ diff --git a/components/soc/esp32/include/soc/host_reg.h b/components/soc/esp32/include/soc/host_reg.h new file mode 100644 index 0000000000..ef556e21cd --- /dev/null +++ b/components/soc/esp32/include/soc/host_reg.h @@ -0,0 +1,3144 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_HOST_REG_H_ +#define _SOC_HOST_REG_H_ + + +#include "soc.h" +#define HOST_SLCHOST_FUNC2_0_REG (DR_REG_SLCHOST_BASE + 0x10) +/* HOST_SLC_FUNC2_INT : R/W ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC_FUNC2_INT (BIT(24)) +#define HOST_SLC_FUNC2_INT_M (BIT(24)) +#define HOST_SLC_FUNC2_INT_V 0x1 +#define HOST_SLC_FUNC2_INT_S 24 + +#define HOST_SLCHOST_FUNC2_1_REG (DR_REG_SLCHOST_BASE + 0x14) +/* HOST_SLC_FUNC2_INT_EN : R/W ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC_FUNC2_INT_EN (BIT(0)) +#define HOST_SLC_FUNC2_INT_EN_M (BIT(0)) +#define HOST_SLC_FUNC2_INT_EN_V 0x1 +#define HOST_SLC_FUNC2_INT_EN_S 0 + +#define HOST_SLCHOST_FUNC2_2_REG (DR_REG_SLCHOST_BASE + 0x20) +/* HOST_SLC_FUNC1_MDSTAT : R/W ;bitpos:[0] ;default: 1'b1 ; */ +/*description: */ +#define HOST_SLC_FUNC1_MDSTAT (BIT(0)) +#define HOST_SLC_FUNC1_MDSTAT_M (BIT(0)) +#define HOST_SLC_FUNC1_MDSTAT_V 0x1 +#define HOST_SLC_FUNC1_MDSTAT_S 0 + +#define HOST_SLCHOST_GPIO_STATUS0_REG (DR_REG_SLCHOST_BASE + 0x34) +/* HOST_GPIO_SDIO_INT0 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define HOST_GPIO_SDIO_INT0 0xFFFFFFFF +#define HOST_GPIO_SDIO_INT0_M ((HOST_GPIO_SDIO_INT0_V)<<(HOST_GPIO_SDIO_INT0_S)) +#define HOST_GPIO_SDIO_INT0_V 0xFFFFFFFF +#define HOST_GPIO_SDIO_INT0_S 0 + +#define HOST_SLCHOST_GPIO_STATUS1_REG (DR_REG_SLCHOST_BASE + 0x38) +/* HOST_GPIO_SDIO_INT1 : RO ;bitpos:[7:0] ;default: 8'b0 ; */ +/*description: */ +#define HOST_GPIO_SDIO_INT1 0x000000FF +#define HOST_GPIO_SDIO_INT1_M ((HOST_GPIO_SDIO_INT1_V)<<(HOST_GPIO_SDIO_INT1_S)) +#define HOST_GPIO_SDIO_INT1_V 0xFF +#define HOST_GPIO_SDIO_INT1_S 0 + +#define HOST_SLCHOST_GPIO_IN0_REG (DR_REG_SLCHOST_BASE + 0x3C) +/* HOST_GPIO_SDIO_IN0 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define HOST_GPIO_SDIO_IN0 0xFFFFFFFF +#define HOST_GPIO_SDIO_IN0_M ((HOST_GPIO_SDIO_IN0_V)<<(HOST_GPIO_SDIO_IN0_S)) +#define HOST_GPIO_SDIO_IN0_V 0xFFFFFFFF +#define HOST_GPIO_SDIO_IN0_S 0 + +#define HOST_SLCHOST_GPIO_IN1_REG (DR_REG_SLCHOST_BASE + 0x40) +/* HOST_GPIO_SDIO_IN1 : RO ;bitpos:[7:0] ;default: 8'b0 ; */ +/*description: */ +#define HOST_GPIO_SDIO_IN1 0x000000FF +#define HOST_GPIO_SDIO_IN1_M ((HOST_GPIO_SDIO_IN1_V)<<(HOST_GPIO_SDIO_IN1_S)) +#define HOST_GPIO_SDIO_IN1_V 0xFF +#define HOST_GPIO_SDIO_IN1_S 0 + +#define HOST_SLC0HOST_TOKEN_RDATA_REG (DR_REG_SLCHOST_BASE + 0x44) +/* HOST_SLC0_RX_PF_EOF : RO ;bitpos:[31:28] ;default: 4'h0 ; */ +/*description: */ +#define HOST_SLC0_RX_PF_EOF 0x0000000F +#define HOST_SLC0_RX_PF_EOF_M ((HOST_SLC0_RX_PF_EOF_V)<<(HOST_SLC0_RX_PF_EOF_S)) +#define HOST_SLC0_RX_PF_EOF_V 0xF +#define HOST_SLC0_RX_PF_EOF_S 28 +/* HOST_HOSTSLC0_TOKEN1 : RO ;bitpos:[27:16] ;default: 12'h0 ; */ +/*description: */ +#define HOST_HOSTSLC0_TOKEN1 0x00000FFF +#define HOST_HOSTSLC0_TOKEN1_M ((HOST_HOSTSLC0_TOKEN1_V)<<(HOST_HOSTSLC0_TOKEN1_S)) +#define HOST_HOSTSLC0_TOKEN1_V 0xFFF +#define HOST_HOSTSLC0_TOKEN1_S 16 +/* HOST_SLC0_RX_PF_VALID : RO ;bitpos:[12] ;default: 4'h0 ; */ +/*description: */ +#define HOST_SLC0_RX_PF_VALID (BIT(12)) +#define HOST_SLC0_RX_PF_VALID_M (BIT(12)) +#define HOST_SLC0_RX_PF_VALID_V 0x1 +#define HOST_SLC0_RX_PF_VALID_S 12 +/* HOST_SLC0_TOKEN0 : RO ;bitpos:[11:0] ;default: 12'h0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN0 0x00000FFF +#define HOST_SLC0_TOKEN0_M ((HOST_SLC0_TOKEN0_V)<<(HOST_SLC0_TOKEN0_S)) +#define HOST_SLC0_TOKEN0_V 0xFFF +#define HOST_SLC0_TOKEN0_S 0 + +#define HOST_SLC0_HOST_PF_REG (DR_REG_SLCHOST_BASE + 0x48) +/* HOST_SLC0_PF_DATA : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define HOST_SLC0_PF_DATA 0xFFFFFFFF +#define HOST_SLC0_PF_DATA_M ((HOST_SLC0_PF_DATA_V)<<(HOST_SLC0_PF_DATA_S)) +#define HOST_SLC0_PF_DATA_V 0xFFFFFFFF +#define HOST_SLC0_PF_DATA_S 0 + +#define HOST_SLC1_HOST_PF_REG (DR_REG_SLCHOST_BASE + 0x4C) +/* HOST_SLC1_PF_DATA : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define HOST_SLC1_PF_DATA 0xFFFFFFFF +#define HOST_SLC1_PF_DATA_M ((HOST_SLC1_PF_DATA_V)<<(HOST_SLC1_PF_DATA_S)) +#define HOST_SLC1_PF_DATA_V 0xFFFFFFFF +#define HOST_SLC1_PF_DATA_S 0 + +#define HOST_SLC0HOST_INT_RAW_REG (DR_REG_SLCHOST_BASE + 0x50) +/* HOST_GPIO_SDIO_INT_RAW : RO ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define HOST_GPIO_SDIO_INT_RAW (BIT(25)) +#define HOST_GPIO_SDIO_INT_RAW_M (BIT(25)) +#define HOST_GPIO_SDIO_INT_RAW_V 0x1 +#define HOST_GPIO_SDIO_INT_RAW_S 25 +/* HOST_SLC0_HOST_RD_RETRY_INT_RAW : RO ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_HOST_RD_RETRY_INT_RAW (BIT(24)) +#define HOST_SLC0_HOST_RD_RETRY_INT_RAW_M (BIT(24)) +#define HOST_SLC0_HOST_RD_RETRY_INT_RAW_V 0x1 +#define HOST_SLC0_HOST_RD_RETRY_INT_RAW_S 24 +/* HOST_SLC0_RX_NEW_PACKET_INT_RAW : RO ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_RX_NEW_PACKET_INT_RAW (BIT(23)) +#define HOST_SLC0_RX_NEW_PACKET_INT_RAW_M (BIT(23)) +#define HOST_SLC0_RX_NEW_PACKET_INT_RAW_V 0x1 +#define HOST_SLC0_RX_NEW_PACKET_INT_RAW_S 23 +/* HOST_SLC0_EXT_BIT3_INT_RAW : RO ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT3_INT_RAW (BIT(22)) +#define HOST_SLC0_EXT_BIT3_INT_RAW_M (BIT(22)) +#define HOST_SLC0_EXT_BIT3_INT_RAW_V 0x1 +#define HOST_SLC0_EXT_BIT3_INT_RAW_S 22 +/* HOST_SLC0_EXT_BIT2_INT_RAW : RO ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT2_INT_RAW (BIT(21)) +#define HOST_SLC0_EXT_BIT2_INT_RAW_M (BIT(21)) +#define HOST_SLC0_EXT_BIT2_INT_RAW_V 0x1 +#define HOST_SLC0_EXT_BIT2_INT_RAW_S 21 +/* HOST_SLC0_EXT_BIT1_INT_RAW : RO ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT1_INT_RAW (BIT(20)) +#define HOST_SLC0_EXT_BIT1_INT_RAW_M (BIT(20)) +#define HOST_SLC0_EXT_BIT1_INT_RAW_V 0x1 +#define HOST_SLC0_EXT_BIT1_INT_RAW_S 20 +/* HOST_SLC0_EXT_BIT0_INT_RAW : RO ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT0_INT_RAW (BIT(19)) +#define HOST_SLC0_EXT_BIT0_INT_RAW_M (BIT(19)) +#define HOST_SLC0_EXT_BIT0_INT_RAW_V 0x1 +#define HOST_SLC0_EXT_BIT0_INT_RAW_S 19 +/* HOST_SLC0_RX_PF_VALID_INT_RAW : RO ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_RX_PF_VALID_INT_RAW (BIT(18)) +#define HOST_SLC0_RX_PF_VALID_INT_RAW_M (BIT(18)) +#define HOST_SLC0_RX_PF_VALID_INT_RAW_V 0x1 +#define HOST_SLC0_RX_PF_VALID_INT_RAW_S 18 +/* HOST_SLC0_TX_OVF_INT_RAW : RO ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TX_OVF_INT_RAW (BIT(17)) +#define HOST_SLC0_TX_OVF_INT_RAW_M (BIT(17)) +#define HOST_SLC0_TX_OVF_INT_RAW_V 0x1 +#define HOST_SLC0_TX_OVF_INT_RAW_S 17 +/* HOST_SLC0_RX_UDF_INT_RAW : RO ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_RX_UDF_INT_RAW (BIT(16)) +#define HOST_SLC0_RX_UDF_INT_RAW_M (BIT(16)) +#define HOST_SLC0_RX_UDF_INT_RAW_V 0x1 +#define HOST_SLC0_RX_UDF_INT_RAW_S 16 +/* HOST_SLC0HOST_TX_START_INT_RAW : RO ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_TX_START_INT_RAW (BIT(15)) +#define HOST_SLC0HOST_TX_START_INT_RAW_M (BIT(15)) +#define HOST_SLC0HOST_TX_START_INT_RAW_V 0x1 +#define HOST_SLC0HOST_TX_START_INT_RAW_S 15 +/* HOST_SLC0HOST_RX_START_INT_RAW : RO ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_RX_START_INT_RAW (BIT(14)) +#define HOST_SLC0HOST_RX_START_INT_RAW_M (BIT(14)) +#define HOST_SLC0HOST_RX_START_INT_RAW_V 0x1 +#define HOST_SLC0HOST_RX_START_INT_RAW_S 14 +/* HOST_SLC0HOST_RX_EOF_INT_RAW : RO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_RX_EOF_INT_RAW (BIT(13)) +#define HOST_SLC0HOST_RX_EOF_INT_RAW_M (BIT(13)) +#define HOST_SLC0HOST_RX_EOF_INT_RAW_V 0x1 +#define HOST_SLC0HOST_RX_EOF_INT_RAW_S 13 +/* HOST_SLC0HOST_RX_SOF_INT_RAW : RO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_RX_SOF_INT_RAW (BIT(12)) +#define HOST_SLC0HOST_RX_SOF_INT_RAW_M (BIT(12)) +#define HOST_SLC0HOST_RX_SOF_INT_RAW_V 0x1 +#define HOST_SLC0HOST_RX_SOF_INT_RAW_S 12 +/* HOST_SLC0_TOKEN1_0TO1_INT_RAW : RO ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN1_0TO1_INT_RAW (BIT(11)) +#define HOST_SLC0_TOKEN1_0TO1_INT_RAW_M (BIT(11)) +#define HOST_SLC0_TOKEN1_0TO1_INT_RAW_V 0x1 +#define HOST_SLC0_TOKEN1_0TO1_INT_RAW_S 11 +/* HOST_SLC0_TOKEN0_0TO1_INT_RAW : RO ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN0_0TO1_INT_RAW (BIT(10)) +#define HOST_SLC0_TOKEN0_0TO1_INT_RAW_M (BIT(10)) +#define HOST_SLC0_TOKEN0_0TO1_INT_RAW_V 0x1 +#define HOST_SLC0_TOKEN0_0TO1_INT_RAW_S 10 +/* HOST_SLC0_TOKEN1_1TO0_INT_RAW : RO ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN1_1TO0_INT_RAW (BIT(9)) +#define HOST_SLC0_TOKEN1_1TO0_INT_RAW_M (BIT(9)) +#define HOST_SLC0_TOKEN1_1TO0_INT_RAW_V 0x1 +#define HOST_SLC0_TOKEN1_1TO0_INT_RAW_S 9 +/* HOST_SLC0_TOKEN0_1TO0_INT_RAW : RO ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN0_1TO0_INT_RAW (BIT(8)) +#define HOST_SLC0_TOKEN0_1TO0_INT_RAW_M (BIT(8)) +#define HOST_SLC0_TOKEN0_1TO0_INT_RAW_V 0x1 +#define HOST_SLC0_TOKEN0_1TO0_INT_RAW_S 8 +/* HOST_SLC0_TOHOST_BIT7_INT_RAW : RO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT7_INT_RAW (BIT(7)) +#define HOST_SLC0_TOHOST_BIT7_INT_RAW_M (BIT(7)) +#define HOST_SLC0_TOHOST_BIT7_INT_RAW_V 0x1 +#define HOST_SLC0_TOHOST_BIT7_INT_RAW_S 7 +/* HOST_SLC0_TOHOST_BIT6_INT_RAW : RO ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT6_INT_RAW (BIT(6)) +#define HOST_SLC0_TOHOST_BIT6_INT_RAW_M (BIT(6)) +#define HOST_SLC0_TOHOST_BIT6_INT_RAW_V 0x1 +#define HOST_SLC0_TOHOST_BIT6_INT_RAW_S 6 +/* HOST_SLC0_TOHOST_BIT5_INT_RAW : RO ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT5_INT_RAW (BIT(5)) +#define HOST_SLC0_TOHOST_BIT5_INT_RAW_M (BIT(5)) +#define HOST_SLC0_TOHOST_BIT5_INT_RAW_V 0x1 +#define HOST_SLC0_TOHOST_BIT5_INT_RAW_S 5 +/* HOST_SLC0_TOHOST_BIT4_INT_RAW : RO ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT4_INT_RAW (BIT(4)) +#define HOST_SLC0_TOHOST_BIT4_INT_RAW_M (BIT(4)) +#define HOST_SLC0_TOHOST_BIT4_INT_RAW_V 0x1 +#define HOST_SLC0_TOHOST_BIT4_INT_RAW_S 4 +/* HOST_SLC0_TOHOST_BIT3_INT_RAW : RO ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT3_INT_RAW (BIT(3)) +#define HOST_SLC0_TOHOST_BIT3_INT_RAW_M (BIT(3)) +#define HOST_SLC0_TOHOST_BIT3_INT_RAW_V 0x1 +#define HOST_SLC0_TOHOST_BIT3_INT_RAW_S 3 +/* HOST_SLC0_TOHOST_BIT2_INT_RAW : RO ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT2_INT_RAW (BIT(2)) +#define HOST_SLC0_TOHOST_BIT2_INT_RAW_M (BIT(2)) +#define HOST_SLC0_TOHOST_BIT2_INT_RAW_V 0x1 +#define HOST_SLC0_TOHOST_BIT2_INT_RAW_S 2 +/* HOST_SLC0_TOHOST_BIT1_INT_RAW : RO ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT1_INT_RAW (BIT(1)) +#define HOST_SLC0_TOHOST_BIT1_INT_RAW_M (BIT(1)) +#define HOST_SLC0_TOHOST_BIT1_INT_RAW_V 0x1 +#define HOST_SLC0_TOHOST_BIT1_INT_RAW_S 1 +/* HOST_SLC0_TOHOST_BIT0_INT_RAW : RO ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT0_INT_RAW (BIT(0)) +#define HOST_SLC0_TOHOST_BIT0_INT_RAW_M (BIT(0)) +#define HOST_SLC0_TOHOST_BIT0_INT_RAW_V 0x1 +#define HOST_SLC0_TOHOST_BIT0_INT_RAW_S 0 + +#define HOST_SLC1HOST_INT_RAW_REG (DR_REG_SLCHOST_BASE + 0x54) +/* HOST_SLC1_BT_RX_NEW_PACKET_INT_RAW : RO ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_RAW (BIT(25)) +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_RAW_M (BIT(25)) +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_RAW_V 0x1 +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_RAW_S 25 +/* HOST_SLC1_HOST_RD_RETRY_INT_RAW : RO ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_HOST_RD_RETRY_INT_RAW (BIT(24)) +#define HOST_SLC1_HOST_RD_RETRY_INT_RAW_M (BIT(24)) +#define HOST_SLC1_HOST_RD_RETRY_INT_RAW_V 0x1 +#define HOST_SLC1_HOST_RD_RETRY_INT_RAW_S 24 +/* HOST_SLC1_WIFI_RX_NEW_PACKET_INT_RAW : RO ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_RAW (BIT(23)) +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_RAW_M (BIT(23)) +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_RAW_V 0x1 +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_RAW_S 23 +/* HOST_SLC1_EXT_BIT3_INT_RAW : RO ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT3_INT_RAW (BIT(22)) +#define HOST_SLC1_EXT_BIT3_INT_RAW_M (BIT(22)) +#define HOST_SLC1_EXT_BIT3_INT_RAW_V 0x1 +#define HOST_SLC1_EXT_BIT3_INT_RAW_S 22 +/* HOST_SLC1_EXT_BIT2_INT_RAW : RO ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT2_INT_RAW (BIT(21)) +#define HOST_SLC1_EXT_BIT2_INT_RAW_M (BIT(21)) +#define HOST_SLC1_EXT_BIT2_INT_RAW_V 0x1 +#define HOST_SLC1_EXT_BIT2_INT_RAW_S 21 +/* HOST_SLC1_EXT_BIT1_INT_RAW : RO ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT1_INT_RAW (BIT(20)) +#define HOST_SLC1_EXT_BIT1_INT_RAW_M (BIT(20)) +#define HOST_SLC1_EXT_BIT1_INT_RAW_V 0x1 +#define HOST_SLC1_EXT_BIT1_INT_RAW_S 20 +/* HOST_SLC1_EXT_BIT0_INT_RAW : RO ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT0_INT_RAW (BIT(19)) +#define HOST_SLC1_EXT_BIT0_INT_RAW_M (BIT(19)) +#define HOST_SLC1_EXT_BIT0_INT_RAW_V 0x1 +#define HOST_SLC1_EXT_BIT0_INT_RAW_S 19 +/* HOST_SLC1_RX_PF_VALID_INT_RAW : RO ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_RX_PF_VALID_INT_RAW (BIT(18)) +#define HOST_SLC1_RX_PF_VALID_INT_RAW_M (BIT(18)) +#define HOST_SLC1_RX_PF_VALID_INT_RAW_V 0x1 +#define HOST_SLC1_RX_PF_VALID_INT_RAW_S 18 +/* HOST_SLC1_TX_OVF_INT_RAW : RO ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TX_OVF_INT_RAW (BIT(17)) +#define HOST_SLC1_TX_OVF_INT_RAW_M (BIT(17)) +#define HOST_SLC1_TX_OVF_INT_RAW_V 0x1 +#define HOST_SLC1_TX_OVF_INT_RAW_S 17 +/* HOST_SLC1_RX_UDF_INT_RAW : RO ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_RX_UDF_INT_RAW (BIT(16)) +#define HOST_SLC1_RX_UDF_INT_RAW_M (BIT(16)) +#define HOST_SLC1_RX_UDF_INT_RAW_V 0x1 +#define HOST_SLC1_RX_UDF_INT_RAW_S 16 +/* HOST_SLC1HOST_TX_START_INT_RAW : RO ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_TX_START_INT_RAW (BIT(15)) +#define HOST_SLC1HOST_TX_START_INT_RAW_M (BIT(15)) +#define HOST_SLC1HOST_TX_START_INT_RAW_V 0x1 +#define HOST_SLC1HOST_TX_START_INT_RAW_S 15 +/* HOST_SLC1HOST_RX_START_INT_RAW : RO ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_RX_START_INT_RAW (BIT(14)) +#define HOST_SLC1HOST_RX_START_INT_RAW_M (BIT(14)) +#define HOST_SLC1HOST_RX_START_INT_RAW_V 0x1 +#define HOST_SLC1HOST_RX_START_INT_RAW_S 14 +/* HOST_SLC1HOST_RX_EOF_INT_RAW : RO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_RX_EOF_INT_RAW (BIT(13)) +#define HOST_SLC1HOST_RX_EOF_INT_RAW_M (BIT(13)) +#define HOST_SLC1HOST_RX_EOF_INT_RAW_V 0x1 +#define HOST_SLC1HOST_RX_EOF_INT_RAW_S 13 +/* HOST_SLC1HOST_RX_SOF_INT_RAW : RO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_RX_SOF_INT_RAW (BIT(12)) +#define HOST_SLC1HOST_RX_SOF_INT_RAW_M (BIT(12)) +#define HOST_SLC1HOST_RX_SOF_INT_RAW_V 0x1 +#define HOST_SLC1HOST_RX_SOF_INT_RAW_S 12 +/* HOST_SLC1_TOKEN1_0TO1_INT_RAW : RO ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN1_0TO1_INT_RAW (BIT(11)) +#define HOST_SLC1_TOKEN1_0TO1_INT_RAW_M (BIT(11)) +#define HOST_SLC1_TOKEN1_0TO1_INT_RAW_V 0x1 +#define HOST_SLC1_TOKEN1_0TO1_INT_RAW_S 11 +/* HOST_SLC1_TOKEN0_0TO1_INT_RAW : RO ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN0_0TO1_INT_RAW (BIT(10)) +#define HOST_SLC1_TOKEN0_0TO1_INT_RAW_M (BIT(10)) +#define HOST_SLC1_TOKEN0_0TO1_INT_RAW_V 0x1 +#define HOST_SLC1_TOKEN0_0TO1_INT_RAW_S 10 +/* HOST_SLC1_TOKEN1_1TO0_INT_RAW : RO ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN1_1TO0_INT_RAW (BIT(9)) +#define HOST_SLC1_TOKEN1_1TO0_INT_RAW_M (BIT(9)) +#define HOST_SLC1_TOKEN1_1TO0_INT_RAW_V 0x1 +#define HOST_SLC1_TOKEN1_1TO0_INT_RAW_S 9 +/* HOST_SLC1_TOKEN0_1TO0_INT_RAW : RO ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN0_1TO0_INT_RAW (BIT(8)) +#define HOST_SLC1_TOKEN0_1TO0_INT_RAW_M (BIT(8)) +#define HOST_SLC1_TOKEN0_1TO0_INT_RAW_V 0x1 +#define HOST_SLC1_TOKEN0_1TO0_INT_RAW_S 8 +/* HOST_SLC1_TOHOST_BIT7_INT_RAW : RO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT7_INT_RAW (BIT(7)) +#define HOST_SLC1_TOHOST_BIT7_INT_RAW_M (BIT(7)) +#define HOST_SLC1_TOHOST_BIT7_INT_RAW_V 0x1 +#define HOST_SLC1_TOHOST_BIT7_INT_RAW_S 7 +/* HOST_SLC1_TOHOST_BIT6_INT_RAW : RO ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT6_INT_RAW (BIT(6)) +#define HOST_SLC1_TOHOST_BIT6_INT_RAW_M (BIT(6)) +#define HOST_SLC1_TOHOST_BIT6_INT_RAW_V 0x1 +#define HOST_SLC1_TOHOST_BIT6_INT_RAW_S 6 +/* HOST_SLC1_TOHOST_BIT5_INT_RAW : RO ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT5_INT_RAW (BIT(5)) +#define HOST_SLC1_TOHOST_BIT5_INT_RAW_M (BIT(5)) +#define HOST_SLC1_TOHOST_BIT5_INT_RAW_V 0x1 +#define HOST_SLC1_TOHOST_BIT5_INT_RAW_S 5 +/* HOST_SLC1_TOHOST_BIT4_INT_RAW : RO ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT4_INT_RAW (BIT(4)) +#define HOST_SLC1_TOHOST_BIT4_INT_RAW_M (BIT(4)) +#define HOST_SLC1_TOHOST_BIT4_INT_RAW_V 0x1 +#define HOST_SLC1_TOHOST_BIT4_INT_RAW_S 4 +/* HOST_SLC1_TOHOST_BIT3_INT_RAW : RO ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT3_INT_RAW (BIT(3)) +#define HOST_SLC1_TOHOST_BIT3_INT_RAW_M (BIT(3)) +#define HOST_SLC1_TOHOST_BIT3_INT_RAW_V 0x1 +#define HOST_SLC1_TOHOST_BIT3_INT_RAW_S 3 +/* HOST_SLC1_TOHOST_BIT2_INT_RAW : RO ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT2_INT_RAW (BIT(2)) +#define HOST_SLC1_TOHOST_BIT2_INT_RAW_M (BIT(2)) +#define HOST_SLC1_TOHOST_BIT2_INT_RAW_V 0x1 +#define HOST_SLC1_TOHOST_BIT2_INT_RAW_S 2 +/* HOST_SLC1_TOHOST_BIT1_INT_RAW : RO ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT1_INT_RAW (BIT(1)) +#define HOST_SLC1_TOHOST_BIT1_INT_RAW_M (BIT(1)) +#define HOST_SLC1_TOHOST_BIT1_INT_RAW_V 0x1 +#define HOST_SLC1_TOHOST_BIT1_INT_RAW_S 1 +/* HOST_SLC1_TOHOST_BIT0_INT_RAW : RO ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT0_INT_RAW (BIT(0)) +#define HOST_SLC1_TOHOST_BIT0_INT_RAW_M (BIT(0)) +#define HOST_SLC1_TOHOST_BIT0_INT_RAW_V 0x1 +#define HOST_SLC1_TOHOST_BIT0_INT_RAW_S 0 + +#define HOST_SLC0HOST_INT_ST_REG (DR_REG_SLCHOST_BASE + 0x58) +/* HOST_GPIO_SDIO_INT_ST : RO ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define HOST_GPIO_SDIO_INT_ST (BIT(25)) +#define HOST_GPIO_SDIO_INT_ST_M (BIT(25)) +#define HOST_GPIO_SDIO_INT_ST_V 0x1 +#define HOST_GPIO_SDIO_INT_ST_S 25 +/* HOST_SLC0_HOST_RD_RETRY_INT_ST : RO ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_HOST_RD_RETRY_INT_ST (BIT(24)) +#define HOST_SLC0_HOST_RD_RETRY_INT_ST_M (BIT(24)) +#define HOST_SLC0_HOST_RD_RETRY_INT_ST_V 0x1 +#define HOST_SLC0_HOST_RD_RETRY_INT_ST_S 24 +/* HOST_SLC0_RX_NEW_PACKET_INT_ST : RO ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_RX_NEW_PACKET_INT_ST (BIT(23)) +#define HOST_SLC0_RX_NEW_PACKET_INT_ST_M (BIT(23)) +#define HOST_SLC0_RX_NEW_PACKET_INT_ST_V 0x1 +#define HOST_SLC0_RX_NEW_PACKET_INT_ST_S 23 +/* HOST_SLC0_EXT_BIT3_INT_ST : RO ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT3_INT_ST (BIT(22)) +#define HOST_SLC0_EXT_BIT3_INT_ST_M (BIT(22)) +#define HOST_SLC0_EXT_BIT3_INT_ST_V 0x1 +#define HOST_SLC0_EXT_BIT3_INT_ST_S 22 +/* HOST_SLC0_EXT_BIT2_INT_ST : RO ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT2_INT_ST (BIT(21)) +#define HOST_SLC0_EXT_BIT2_INT_ST_M (BIT(21)) +#define HOST_SLC0_EXT_BIT2_INT_ST_V 0x1 +#define HOST_SLC0_EXT_BIT2_INT_ST_S 21 +/* HOST_SLC0_EXT_BIT1_INT_ST : RO ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT1_INT_ST (BIT(20)) +#define HOST_SLC0_EXT_BIT1_INT_ST_M (BIT(20)) +#define HOST_SLC0_EXT_BIT1_INT_ST_V 0x1 +#define HOST_SLC0_EXT_BIT1_INT_ST_S 20 +/* HOST_SLC0_EXT_BIT0_INT_ST : RO ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT0_INT_ST (BIT(19)) +#define HOST_SLC0_EXT_BIT0_INT_ST_M (BIT(19)) +#define HOST_SLC0_EXT_BIT0_INT_ST_V 0x1 +#define HOST_SLC0_EXT_BIT0_INT_ST_S 19 +/* HOST_SLC0_RX_PF_VALID_INT_ST : RO ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_RX_PF_VALID_INT_ST (BIT(18)) +#define HOST_SLC0_RX_PF_VALID_INT_ST_M (BIT(18)) +#define HOST_SLC0_RX_PF_VALID_INT_ST_V 0x1 +#define HOST_SLC0_RX_PF_VALID_INT_ST_S 18 +/* HOST_SLC0_TX_OVF_INT_ST : RO ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TX_OVF_INT_ST (BIT(17)) +#define HOST_SLC0_TX_OVF_INT_ST_M (BIT(17)) +#define HOST_SLC0_TX_OVF_INT_ST_V 0x1 +#define HOST_SLC0_TX_OVF_INT_ST_S 17 +/* HOST_SLC0_RX_UDF_INT_ST : RO ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_RX_UDF_INT_ST (BIT(16)) +#define HOST_SLC0_RX_UDF_INT_ST_M (BIT(16)) +#define HOST_SLC0_RX_UDF_INT_ST_V 0x1 +#define HOST_SLC0_RX_UDF_INT_ST_S 16 +/* HOST_SLC0HOST_TX_START_INT_ST : RO ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_TX_START_INT_ST (BIT(15)) +#define HOST_SLC0HOST_TX_START_INT_ST_M (BIT(15)) +#define HOST_SLC0HOST_TX_START_INT_ST_V 0x1 +#define HOST_SLC0HOST_TX_START_INT_ST_S 15 +/* HOST_SLC0HOST_RX_START_INT_ST : RO ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_RX_START_INT_ST (BIT(14)) +#define HOST_SLC0HOST_RX_START_INT_ST_M (BIT(14)) +#define HOST_SLC0HOST_RX_START_INT_ST_V 0x1 +#define HOST_SLC0HOST_RX_START_INT_ST_S 14 +/* HOST_SLC0HOST_RX_EOF_INT_ST : RO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_RX_EOF_INT_ST (BIT(13)) +#define HOST_SLC0HOST_RX_EOF_INT_ST_M (BIT(13)) +#define HOST_SLC0HOST_RX_EOF_INT_ST_V 0x1 +#define HOST_SLC0HOST_RX_EOF_INT_ST_S 13 +/* HOST_SLC0HOST_RX_SOF_INT_ST : RO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_RX_SOF_INT_ST (BIT(12)) +#define HOST_SLC0HOST_RX_SOF_INT_ST_M (BIT(12)) +#define HOST_SLC0HOST_RX_SOF_INT_ST_V 0x1 +#define HOST_SLC0HOST_RX_SOF_INT_ST_S 12 +/* HOST_SLC0_TOKEN1_0TO1_INT_ST : RO ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN1_0TO1_INT_ST (BIT(11)) +#define HOST_SLC0_TOKEN1_0TO1_INT_ST_M (BIT(11)) +#define HOST_SLC0_TOKEN1_0TO1_INT_ST_V 0x1 +#define HOST_SLC0_TOKEN1_0TO1_INT_ST_S 11 +/* HOST_SLC0_TOKEN0_0TO1_INT_ST : RO ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN0_0TO1_INT_ST (BIT(10)) +#define HOST_SLC0_TOKEN0_0TO1_INT_ST_M (BIT(10)) +#define HOST_SLC0_TOKEN0_0TO1_INT_ST_V 0x1 +#define HOST_SLC0_TOKEN0_0TO1_INT_ST_S 10 +/* HOST_SLC0_TOKEN1_1TO0_INT_ST : RO ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN1_1TO0_INT_ST (BIT(9)) +#define HOST_SLC0_TOKEN1_1TO0_INT_ST_M (BIT(9)) +#define HOST_SLC0_TOKEN1_1TO0_INT_ST_V 0x1 +#define HOST_SLC0_TOKEN1_1TO0_INT_ST_S 9 +/* HOST_SLC0_TOKEN0_1TO0_INT_ST : RO ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN0_1TO0_INT_ST (BIT(8)) +#define HOST_SLC0_TOKEN0_1TO0_INT_ST_M (BIT(8)) +#define HOST_SLC0_TOKEN0_1TO0_INT_ST_V 0x1 +#define HOST_SLC0_TOKEN0_1TO0_INT_ST_S 8 +/* HOST_SLC0_TOHOST_BIT7_INT_ST : RO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT7_INT_ST (BIT(7)) +#define HOST_SLC0_TOHOST_BIT7_INT_ST_M (BIT(7)) +#define HOST_SLC0_TOHOST_BIT7_INT_ST_V 0x1 +#define HOST_SLC0_TOHOST_BIT7_INT_ST_S 7 +/* HOST_SLC0_TOHOST_BIT6_INT_ST : RO ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT6_INT_ST (BIT(6)) +#define HOST_SLC0_TOHOST_BIT6_INT_ST_M (BIT(6)) +#define HOST_SLC0_TOHOST_BIT6_INT_ST_V 0x1 +#define HOST_SLC0_TOHOST_BIT6_INT_ST_S 6 +/* HOST_SLC0_TOHOST_BIT5_INT_ST : RO ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT5_INT_ST (BIT(5)) +#define HOST_SLC0_TOHOST_BIT5_INT_ST_M (BIT(5)) +#define HOST_SLC0_TOHOST_BIT5_INT_ST_V 0x1 +#define HOST_SLC0_TOHOST_BIT5_INT_ST_S 5 +/* HOST_SLC0_TOHOST_BIT4_INT_ST : RO ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT4_INT_ST (BIT(4)) +#define HOST_SLC0_TOHOST_BIT4_INT_ST_M (BIT(4)) +#define HOST_SLC0_TOHOST_BIT4_INT_ST_V 0x1 +#define HOST_SLC0_TOHOST_BIT4_INT_ST_S 4 +/* HOST_SLC0_TOHOST_BIT3_INT_ST : RO ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT3_INT_ST (BIT(3)) +#define HOST_SLC0_TOHOST_BIT3_INT_ST_M (BIT(3)) +#define HOST_SLC0_TOHOST_BIT3_INT_ST_V 0x1 +#define HOST_SLC0_TOHOST_BIT3_INT_ST_S 3 +/* HOST_SLC0_TOHOST_BIT2_INT_ST : RO ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT2_INT_ST (BIT(2)) +#define HOST_SLC0_TOHOST_BIT2_INT_ST_M (BIT(2)) +#define HOST_SLC0_TOHOST_BIT2_INT_ST_V 0x1 +#define HOST_SLC0_TOHOST_BIT2_INT_ST_S 2 +/* HOST_SLC0_TOHOST_BIT1_INT_ST : RO ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT1_INT_ST (BIT(1)) +#define HOST_SLC0_TOHOST_BIT1_INT_ST_M (BIT(1)) +#define HOST_SLC0_TOHOST_BIT1_INT_ST_V 0x1 +#define HOST_SLC0_TOHOST_BIT1_INT_ST_S 1 +/* HOST_SLC0_TOHOST_BIT0_INT_ST : RO ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT0_INT_ST (BIT(0)) +#define HOST_SLC0_TOHOST_BIT0_INT_ST_M (BIT(0)) +#define HOST_SLC0_TOHOST_BIT0_INT_ST_V 0x1 +#define HOST_SLC0_TOHOST_BIT0_INT_ST_S 0 + +#define HOST_SLC1HOST_INT_ST_REG (DR_REG_SLCHOST_BASE + 0x5C) +/* HOST_SLC1_BT_RX_NEW_PACKET_INT_ST : RO ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_ST (BIT(25)) +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_ST_M (BIT(25)) +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_ST_V 0x1 +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_ST_S 25 +/* HOST_SLC1_HOST_RD_RETRY_INT_ST : RO ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_HOST_RD_RETRY_INT_ST (BIT(24)) +#define HOST_SLC1_HOST_RD_RETRY_INT_ST_M (BIT(24)) +#define HOST_SLC1_HOST_RD_RETRY_INT_ST_V 0x1 +#define HOST_SLC1_HOST_RD_RETRY_INT_ST_S 24 +/* HOST_SLC1_WIFI_RX_NEW_PACKET_INT_ST : RO ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_ST (BIT(23)) +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_ST_M (BIT(23)) +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_ST_V 0x1 +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_ST_S 23 +/* HOST_SLC1_EXT_BIT3_INT_ST : RO ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT3_INT_ST (BIT(22)) +#define HOST_SLC1_EXT_BIT3_INT_ST_M (BIT(22)) +#define HOST_SLC1_EXT_BIT3_INT_ST_V 0x1 +#define HOST_SLC1_EXT_BIT3_INT_ST_S 22 +/* HOST_SLC1_EXT_BIT2_INT_ST : RO ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT2_INT_ST (BIT(21)) +#define HOST_SLC1_EXT_BIT2_INT_ST_M (BIT(21)) +#define HOST_SLC1_EXT_BIT2_INT_ST_V 0x1 +#define HOST_SLC1_EXT_BIT2_INT_ST_S 21 +/* HOST_SLC1_EXT_BIT1_INT_ST : RO ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT1_INT_ST (BIT(20)) +#define HOST_SLC1_EXT_BIT1_INT_ST_M (BIT(20)) +#define HOST_SLC1_EXT_BIT1_INT_ST_V 0x1 +#define HOST_SLC1_EXT_BIT1_INT_ST_S 20 +/* HOST_SLC1_EXT_BIT0_INT_ST : RO ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT0_INT_ST (BIT(19)) +#define HOST_SLC1_EXT_BIT0_INT_ST_M (BIT(19)) +#define HOST_SLC1_EXT_BIT0_INT_ST_V 0x1 +#define HOST_SLC1_EXT_BIT0_INT_ST_S 19 +/* HOST_SLC1_RX_PF_VALID_INT_ST : RO ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_RX_PF_VALID_INT_ST (BIT(18)) +#define HOST_SLC1_RX_PF_VALID_INT_ST_M (BIT(18)) +#define HOST_SLC1_RX_PF_VALID_INT_ST_V 0x1 +#define HOST_SLC1_RX_PF_VALID_INT_ST_S 18 +/* HOST_SLC1_TX_OVF_INT_ST : RO ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TX_OVF_INT_ST (BIT(17)) +#define HOST_SLC1_TX_OVF_INT_ST_M (BIT(17)) +#define HOST_SLC1_TX_OVF_INT_ST_V 0x1 +#define HOST_SLC1_TX_OVF_INT_ST_S 17 +/* HOST_SLC1_RX_UDF_INT_ST : RO ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_RX_UDF_INT_ST (BIT(16)) +#define HOST_SLC1_RX_UDF_INT_ST_M (BIT(16)) +#define HOST_SLC1_RX_UDF_INT_ST_V 0x1 +#define HOST_SLC1_RX_UDF_INT_ST_S 16 +/* HOST_SLC1HOST_TX_START_INT_ST : RO ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_TX_START_INT_ST (BIT(15)) +#define HOST_SLC1HOST_TX_START_INT_ST_M (BIT(15)) +#define HOST_SLC1HOST_TX_START_INT_ST_V 0x1 +#define HOST_SLC1HOST_TX_START_INT_ST_S 15 +/* HOST_SLC1HOST_RX_START_INT_ST : RO ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_RX_START_INT_ST (BIT(14)) +#define HOST_SLC1HOST_RX_START_INT_ST_M (BIT(14)) +#define HOST_SLC1HOST_RX_START_INT_ST_V 0x1 +#define HOST_SLC1HOST_RX_START_INT_ST_S 14 +/* HOST_SLC1HOST_RX_EOF_INT_ST : RO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_RX_EOF_INT_ST (BIT(13)) +#define HOST_SLC1HOST_RX_EOF_INT_ST_M (BIT(13)) +#define HOST_SLC1HOST_RX_EOF_INT_ST_V 0x1 +#define HOST_SLC1HOST_RX_EOF_INT_ST_S 13 +/* HOST_SLC1HOST_RX_SOF_INT_ST : RO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_RX_SOF_INT_ST (BIT(12)) +#define HOST_SLC1HOST_RX_SOF_INT_ST_M (BIT(12)) +#define HOST_SLC1HOST_RX_SOF_INT_ST_V 0x1 +#define HOST_SLC1HOST_RX_SOF_INT_ST_S 12 +/* HOST_SLC1_TOKEN1_0TO1_INT_ST : RO ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN1_0TO1_INT_ST (BIT(11)) +#define HOST_SLC1_TOKEN1_0TO1_INT_ST_M (BIT(11)) +#define HOST_SLC1_TOKEN1_0TO1_INT_ST_V 0x1 +#define HOST_SLC1_TOKEN1_0TO1_INT_ST_S 11 +/* HOST_SLC1_TOKEN0_0TO1_INT_ST : RO ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN0_0TO1_INT_ST (BIT(10)) +#define HOST_SLC1_TOKEN0_0TO1_INT_ST_M (BIT(10)) +#define HOST_SLC1_TOKEN0_0TO1_INT_ST_V 0x1 +#define HOST_SLC1_TOKEN0_0TO1_INT_ST_S 10 +/* HOST_SLC1_TOKEN1_1TO0_INT_ST : RO ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN1_1TO0_INT_ST (BIT(9)) +#define HOST_SLC1_TOKEN1_1TO0_INT_ST_M (BIT(9)) +#define HOST_SLC1_TOKEN1_1TO0_INT_ST_V 0x1 +#define HOST_SLC1_TOKEN1_1TO0_INT_ST_S 9 +/* HOST_SLC1_TOKEN0_1TO0_INT_ST : RO ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN0_1TO0_INT_ST (BIT(8)) +#define HOST_SLC1_TOKEN0_1TO0_INT_ST_M (BIT(8)) +#define HOST_SLC1_TOKEN0_1TO0_INT_ST_V 0x1 +#define HOST_SLC1_TOKEN0_1TO0_INT_ST_S 8 +/* HOST_SLC1_TOHOST_BIT7_INT_ST : RO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT7_INT_ST (BIT(7)) +#define HOST_SLC1_TOHOST_BIT7_INT_ST_M (BIT(7)) +#define HOST_SLC1_TOHOST_BIT7_INT_ST_V 0x1 +#define HOST_SLC1_TOHOST_BIT7_INT_ST_S 7 +/* HOST_SLC1_TOHOST_BIT6_INT_ST : RO ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT6_INT_ST (BIT(6)) +#define HOST_SLC1_TOHOST_BIT6_INT_ST_M (BIT(6)) +#define HOST_SLC1_TOHOST_BIT6_INT_ST_V 0x1 +#define HOST_SLC1_TOHOST_BIT6_INT_ST_S 6 +/* HOST_SLC1_TOHOST_BIT5_INT_ST : RO ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT5_INT_ST (BIT(5)) +#define HOST_SLC1_TOHOST_BIT5_INT_ST_M (BIT(5)) +#define HOST_SLC1_TOHOST_BIT5_INT_ST_V 0x1 +#define HOST_SLC1_TOHOST_BIT5_INT_ST_S 5 +/* HOST_SLC1_TOHOST_BIT4_INT_ST : RO ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT4_INT_ST (BIT(4)) +#define HOST_SLC1_TOHOST_BIT4_INT_ST_M (BIT(4)) +#define HOST_SLC1_TOHOST_BIT4_INT_ST_V 0x1 +#define HOST_SLC1_TOHOST_BIT4_INT_ST_S 4 +/* HOST_SLC1_TOHOST_BIT3_INT_ST : RO ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT3_INT_ST (BIT(3)) +#define HOST_SLC1_TOHOST_BIT3_INT_ST_M (BIT(3)) +#define HOST_SLC1_TOHOST_BIT3_INT_ST_V 0x1 +#define HOST_SLC1_TOHOST_BIT3_INT_ST_S 3 +/* HOST_SLC1_TOHOST_BIT2_INT_ST : RO ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT2_INT_ST (BIT(2)) +#define HOST_SLC1_TOHOST_BIT2_INT_ST_M (BIT(2)) +#define HOST_SLC1_TOHOST_BIT2_INT_ST_V 0x1 +#define HOST_SLC1_TOHOST_BIT2_INT_ST_S 2 +/* HOST_SLC1_TOHOST_BIT1_INT_ST : RO ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT1_INT_ST (BIT(1)) +#define HOST_SLC1_TOHOST_BIT1_INT_ST_M (BIT(1)) +#define HOST_SLC1_TOHOST_BIT1_INT_ST_V 0x1 +#define HOST_SLC1_TOHOST_BIT1_INT_ST_S 1 +/* HOST_SLC1_TOHOST_BIT0_INT_ST : RO ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT0_INT_ST (BIT(0)) +#define HOST_SLC1_TOHOST_BIT0_INT_ST_M (BIT(0)) +#define HOST_SLC1_TOHOST_BIT0_INT_ST_V 0x1 +#define HOST_SLC1_TOHOST_BIT0_INT_ST_S 0 + +#define HOST_SLCHOST_PKT_LEN_REG (DR_REG_SLCHOST_BASE + 0x60) +/* HOST_HOSTSLC0_LEN_CHECK : RO ;bitpos:[31:20] ;default: 10'h0 ; */ +/*description: */ +#define HOST_HOSTSLC0_LEN_CHECK 0x00000FFF +#define HOST_HOSTSLC0_LEN_CHECK_M ((HOST_HOSTSLC0_LEN_CHECK_V)<<(HOST_HOSTSLC0_LEN_CHECK_S)) +#define HOST_HOSTSLC0_LEN_CHECK_V 0xFFF +#define HOST_HOSTSLC0_LEN_CHECK_S 20 +/* HOST_HOSTSLC0_LEN : RO ;bitpos:[19:0] ;default: 20'h0 ; */ +/*description: */ +#define HOST_HOSTSLC0_LEN 0x000FFFFF +#define HOST_HOSTSLC0_LEN_M ((HOST_HOSTSLC0_LEN_V)<<(HOST_HOSTSLC0_LEN_S)) +#define HOST_HOSTSLC0_LEN_V 0xFFFFF +#define HOST_HOSTSLC0_LEN_S 0 + +#define HOST_SLCHOST_STATE_W0_REG (DR_REG_SLCHOST_BASE + 0x64) +/* HOST_SLCHOST_STATE3 : RO ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_STATE3 0x000000FF +#define HOST_SLCHOST_STATE3_M ((HOST_SLCHOST_STATE3_V)<<(HOST_SLCHOST_STATE3_S)) +#define HOST_SLCHOST_STATE3_V 0xFF +#define HOST_SLCHOST_STATE3_S 24 +/* HOST_SLCHOST_STATE2 : RO ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_STATE2 0x000000FF +#define HOST_SLCHOST_STATE2_M ((HOST_SLCHOST_STATE2_V)<<(HOST_SLCHOST_STATE2_S)) +#define HOST_SLCHOST_STATE2_V 0xFF +#define HOST_SLCHOST_STATE2_S 16 +/* HOST_SLCHOST_STATE1 : RO ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_STATE1 0x000000FF +#define HOST_SLCHOST_STATE1_M ((HOST_SLCHOST_STATE1_V)<<(HOST_SLCHOST_STATE1_S)) +#define HOST_SLCHOST_STATE1_V 0xFF +#define HOST_SLCHOST_STATE1_S 8 +/* HOST_SLCHOST_STATE0 : RO ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_STATE0 0x000000FF +#define HOST_SLCHOST_STATE0_M ((HOST_SLCHOST_STATE0_V)<<(HOST_SLCHOST_STATE0_S)) +#define HOST_SLCHOST_STATE0_V 0xFF +#define HOST_SLCHOST_STATE0_S 0 + +#define HOST_SLCHOST_STATE_W1_REG (DR_REG_SLCHOST_BASE + 0x68) +/* HOST_SLCHOST_STATE7 : RO ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_STATE7 0x000000FF +#define HOST_SLCHOST_STATE7_M ((HOST_SLCHOST_STATE7_V)<<(HOST_SLCHOST_STATE7_S)) +#define HOST_SLCHOST_STATE7_V 0xFF +#define HOST_SLCHOST_STATE7_S 24 +/* HOST_SLCHOST_STATE6 : RO ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_STATE6 0x000000FF +#define HOST_SLCHOST_STATE6_M ((HOST_SLCHOST_STATE6_V)<<(HOST_SLCHOST_STATE6_S)) +#define HOST_SLCHOST_STATE6_V 0xFF +#define HOST_SLCHOST_STATE6_S 16 +/* HOST_SLCHOST_STATE5 : RO ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_STATE5 0x000000FF +#define HOST_SLCHOST_STATE5_M ((HOST_SLCHOST_STATE5_V)<<(HOST_SLCHOST_STATE5_S)) +#define HOST_SLCHOST_STATE5_V 0xFF +#define HOST_SLCHOST_STATE5_S 8 +/* HOST_SLCHOST_STATE4 : RO ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_STATE4 0x000000FF +#define HOST_SLCHOST_STATE4_M ((HOST_SLCHOST_STATE4_V)<<(HOST_SLCHOST_STATE4_S)) +#define HOST_SLCHOST_STATE4_V 0xFF +#define HOST_SLCHOST_STATE4_S 0 + +#define HOST_SLCHOST_CONF_W_REG(pos) (HOST_SLCHOST_CONF_W0_REG+pos+(pos>23?4:0)+(pos>31?12:0)) + +#define HOST_SLCHOST_CONF_W0_REG (DR_REG_SLCHOST_BASE + 0x6C) +/* HOST_SLCHOST_CONF3 : R/W ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF3 0x000000FF +#define HOST_SLCHOST_CONF3_M ((HOST_SLCHOST_CONF3_V)<<(HOST_SLCHOST_CONF3_S)) +#define HOST_SLCHOST_CONF3_V 0xFF +#define HOST_SLCHOST_CONF3_S 24 +/* HOST_SLCHOST_CONF2 : R/W ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF2 0x000000FF +#define HOST_SLCHOST_CONF2_M ((HOST_SLCHOST_CONF2_V)<<(HOST_SLCHOST_CONF2_S)) +#define HOST_SLCHOST_CONF2_V 0xFF +#define HOST_SLCHOST_CONF2_S 16 +/* HOST_SLCHOST_CONF1 : R/W ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF1 0x000000FF +#define HOST_SLCHOST_CONF1_M ((HOST_SLCHOST_CONF1_V)<<(HOST_SLCHOST_CONF1_S)) +#define HOST_SLCHOST_CONF1_V 0xFF +#define HOST_SLCHOST_CONF1_S 8 +/* HOST_SLCHOST_CONF0 : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF0 0x000000FF +#define HOST_SLCHOST_CONF0_M ((HOST_SLCHOST_CONF0_V)<<(HOST_SLCHOST_CONF0_S)) +#define HOST_SLCHOST_CONF0_V 0xFF +#define HOST_SLCHOST_CONF0_S 0 + +#define HOST_SLCHOST_CONF_W1_REG (DR_REG_SLCHOST_BASE + 0x70) +/* HOST_SLCHOST_CONF7 : R/W ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF7 0x000000FF +#define HOST_SLCHOST_CONF7_M ((HOST_SLCHOST_CONF7_V)<<(HOST_SLCHOST_CONF7_S)) +#define HOST_SLCHOST_CONF7_V 0xFF +#define HOST_SLCHOST_CONF7_S 24 +/* HOST_SLCHOST_CONF6 : R/W ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF6 0x000000FF +#define HOST_SLCHOST_CONF6_M ((HOST_SLCHOST_CONF6_V)<<(HOST_SLCHOST_CONF6_S)) +#define HOST_SLCHOST_CONF6_V 0xFF +#define HOST_SLCHOST_CONF6_S 16 +/* HOST_SLCHOST_CONF5 : R/W ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF5 0x000000FF +#define HOST_SLCHOST_CONF5_M ((HOST_SLCHOST_CONF5_V)<<(HOST_SLCHOST_CONF5_S)) +#define HOST_SLCHOST_CONF5_V 0xFF +#define HOST_SLCHOST_CONF5_S 8 +/* HOST_SLCHOST_CONF4 : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF4 0x000000FF +#define HOST_SLCHOST_CONF4_M ((HOST_SLCHOST_CONF4_V)<<(HOST_SLCHOST_CONF4_S)) +#define HOST_SLCHOST_CONF4_V 0xFF +#define HOST_SLCHOST_CONF4_S 0 + +#define HOST_SLCHOST_CONF_W2_REG (DR_REG_SLCHOST_BASE + 0x74) +/* HOST_SLCHOST_CONF11 : R/W ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF11 0x000000FF +#define HOST_SLCHOST_CONF11_M ((HOST_SLCHOST_CONF11_V)<<(HOST_SLCHOST_CONF11_S)) +#define HOST_SLCHOST_CONF11_V 0xFF +#define HOST_SLCHOST_CONF11_S 24 +/* HOST_SLCHOST_CONF10 : R/W ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF10 0x000000FF +#define HOST_SLCHOST_CONF10_M ((HOST_SLCHOST_CONF10_V)<<(HOST_SLCHOST_CONF10_S)) +#define HOST_SLCHOST_CONF10_V 0xFF +#define HOST_SLCHOST_CONF10_S 16 +/* HOST_SLCHOST_CONF9 : R/W ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF9 0x000000FF +#define HOST_SLCHOST_CONF9_M ((HOST_SLCHOST_CONF9_V)<<(HOST_SLCHOST_CONF9_S)) +#define HOST_SLCHOST_CONF9_V 0xFF +#define HOST_SLCHOST_CONF9_S 8 +/* HOST_SLCHOST_CONF8 : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF8 0x000000FF +#define HOST_SLCHOST_CONF8_M ((HOST_SLCHOST_CONF8_V)<<(HOST_SLCHOST_CONF8_S)) +#define HOST_SLCHOST_CONF8_V 0xFF +#define HOST_SLCHOST_CONF8_S 0 + +#define HOST_SLCHOST_CONF_W3_REG (DR_REG_SLCHOST_BASE + 0x78) +/* HOST_SLCHOST_CONF15 : R/W ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF15 0x000000FF +#define HOST_SLCHOST_CONF15_M ((HOST_SLCHOST_CONF15_V)<<(HOST_SLCHOST_CONF15_S)) +#define HOST_SLCHOST_CONF15_V 0xFF +#define HOST_SLCHOST_CONF15_S 24 +/* HOST_SLCHOST_CONF14 : R/W ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF14 0x000000FF +#define HOST_SLCHOST_CONF14_M ((HOST_SLCHOST_CONF14_V)<<(HOST_SLCHOST_CONF14_S)) +#define HOST_SLCHOST_CONF14_V 0xFF +#define HOST_SLCHOST_CONF14_S 16 +/* HOST_SLCHOST_CONF13 : R/W ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF13 0x000000FF +#define HOST_SLCHOST_CONF13_M ((HOST_SLCHOST_CONF13_V)<<(HOST_SLCHOST_CONF13_S)) +#define HOST_SLCHOST_CONF13_V 0xFF +#define HOST_SLCHOST_CONF13_S 8 +/* HOST_SLCHOST_CONF12 : R/W ;bitpos:[7:0] ;default: 8'hc0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF12 0x000000FF +#define HOST_SLCHOST_CONF12_M ((HOST_SLCHOST_CONF12_V)<<(HOST_SLCHOST_CONF12_S)) +#define HOST_SLCHOST_CONF12_V 0xFF +#define HOST_SLCHOST_CONF12_S 0 + +#define HOST_SLCHOST_CONF_W4_REG (DR_REG_SLCHOST_BASE + 0x7C) +/* HOST_SLCHOST_CONF19 : R/W ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: Interrupt to target CPU*/ +#define HOST_SLCHOST_CONF19 0x000000FF +#define HOST_SLCHOST_CONF19_M ((HOST_SLCHOST_CONF19_V)<<(HOST_SLCHOST_CONF19_S)) +#define HOST_SLCHOST_CONF19_V 0xFF +#define HOST_SLCHOST_CONF19_S 24 +/* HOST_SLCHOST_CONF18 : R/W ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF18 0x000000FF +#define HOST_SLCHOST_CONF18_M ((HOST_SLCHOST_CONF18_V)<<(HOST_SLCHOST_CONF18_S)) +#define HOST_SLCHOST_CONF18_V 0xFF +#define HOST_SLCHOST_CONF18_S 16 +/* HOST_SLCHOST_CONF17 : R/W ;bitpos:[15:8] ;default: 8'h1 ; */ +/*description: SLC timeout enable*/ +#define HOST_SLCHOST_CONF17 0x000000FF +#define HOST_SLCHOST_CONF17_M ((HOST_SLCHOST_CONF17_V)<<(HOST_SLCHOST_CONF17_S)) +#define HOST_SLCHOST_CONF17_V 0xFF +#define HOST_SLCHOST_CONF17_S 8 +/* HOST_SLCHOST_CONF16 : R/W ;bitpos:[7:0] ;default: 8'hFF ; */ +/*description: SLC timeout value*/ +#define HOST_SLCHOST_CONF16 0x000000FF +#define HOST_SLCHOST_CONF16_M ((HOST_SLCHOST_CONF16_V)<<(HOST_SLCHOST_CONF16_S)) +#define HOST_SLCHOST_CONF16_V 0xFF +#define HOST_SLCHOST_CONF16_S 0 + +#define HOST_SLCHOST_CONF_W5_REG (DR_REG_SLCHOST_BASE + 0x80) +/* HOST_SLCHOST_CONF23 : R/W ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF23 0x000000FF +#define HOST_SLCHOST_CONF23_M ((HOST_SLCHOST_CONF23_V)<<(HOST_SLCHOST_CONF23_S)) +#define HOST_SLCHOST_CONF23_V 0xFF +#define HOST_SLCHOST_CONF23_S 24 +/* HOST_SLCHOST_CONF22 : R/W ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF22 0x000000FF +#define HOST_SLCHOST_CONF22_M ((HOST_SLCHOST_CONF22_V)<<(HOST_SLCHOST_CONF22_S)) +#define HOST_SLCHOST_CONF22_V 0xFF +#define HOST_SLCHOST_CONF22_S 16 +/* HOST_SLCHOST_CONF21 : R/W ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF21 0x000000FF +#define HOST_SLCHOST_CONF21_M ((HOST_SLCHOST_CONF21_V)<<(HOST_SLCHOST_CONF21_S)) +#define HOST_SLCHOST_CONF21_V 0xFF +#define HOST_SLCHOST_CONF21_S 8 +/* HOST_SLCHOST_CONF20 : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF20 0x000000FF +#define HOST_SLCHOST_CONF20_M ((HOST_SLCHOST_CONF20_V)<<(HOST_SLCHOST_CONF20_S)) +#define HOST_SLCHOST_CONF20_V 0xFF +#define HOST_SLCHOST_CONF20_S 0 + +#define HOST_SLCHOST_WIN_CMD_REG (DR_REG_SLCHOST_BASE + 0x84) + +#define HOST_SLCHOST_CONF_W6_REG (DR_REG_SLCHOST_BASE + 0x88) +/* HOST_SLCHOST_CONF27 : R/W ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF27 0x000000FF +#define HOST_SLCHOST_CONF27_M ((HOST_SLCHOST_CONF27_V)<<(HOST_SLCHOST_CONF27_S)) +#define HOST_SLCHOST_CONF27_V 0xFF +#define HOST_SLCHOST_CONF27_S 24 +/* HOST_SLCHOST_CONF26 : R/W ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF26 0x000000FF +#define HOST_SLCHOST_CONF26_M ((HOST_SLCHOST_CONF26_V)<<(HOST_SLCHOST_CONF26_S)) +#define HOST_SLCHOST_CONF26_V 0xFF +#define HOST_SLCHOST_CONF26_S 16 +/* HOST_SLCHOST_CONF25 : R/W ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF25 0x000000FF +#define HOST_SLCHOST_CONF25_M ((HOST_SLCHOST_CONF25_V)<<(HOST_SLCHOST_CONF25_S)) +#define HOST_SLCHOST_CONF25_V 0xFF +#define HOST_SLCHOST_CONF25_S 8 +/* HOST_SLCHOST_CONF24 : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF24 0x000000FF +#define HOST_SLCHOST_CONF24_M ((HOST_SLCHOST_CONF24_V)<<(HOST_SLCHOST_CONF24_S)) +#define HOST_SLCHOST_CONF24_V 0xFF +#define HOST_SLCHOST_CONF24_S 0 + +#define HOST_SLCHOST_CONF_W7_REG (DR_REG_SLCHOST_BASE + 0x8C) +/* HOST_SLCHOST_CONF31 : R/W ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF31 0x000000FF +#define HOST_SLCHOST_CONF31_M ((HOST_SLCHOST_CONF31_V)<<(HOST_SLCHOST_CONF31_S)) +#define HOST_SLCHOST_CONF31_V 0xFF +#define HOST_SLCHOST_CONF31_S 24 +/* HOST_SLCHOST_CONF30 : R/W ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF30 0x000000FF +#define HOST_SLCHOST_CONF30_M ((HOST_SLCHOST_CONF30_V)<<(HOST_SLCHOST_CONF30_S)) +#define HOST_SLCHOST_CONF30_V 0xFF +#define HOST_SLCHOST_CONF30_S 16 +/* HOST_SLCHOST_CONF29 : R/W ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF29 0x000000FF +#define HOST_SLCHOST_CONF29_M ((HOST_SLCHOST_CONF29_V)<<(HOST_SLCHOST_CONF29_S)) +#define HOST_SLCHOST_CONF29_V 0xFF +#define HOST_SLCHOST_CONF29_S 8 +/* HOST_SLCHOST_CONF28 : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF28 0x000000FF +#define HOST_SLCHOST_CONF28_M ((HOST_SLCHOST_CONF28_V)<<(HOST_SLCHOST_CONF28_S)) +#define HOST_SLCHOST_CONF28_V 0xFF +#define HOST_SLCHOST_CONF28_S 0 + +#define HOST_SLCHOST_PKT_LEN0_REG (DR_REG_SLCHOST_BASE + 0x90) +/* HOST_HOSTSLC0_LEN0 : RO ;bitpos:[19:0] ;default: 20'h0 ; */ +/*description: */ +#define HOST_HOSTSLC0_LEN0 0x000FFFFF +#define HOST_HOSTSLC0_LEN0_M ((HOST_HOSTSLC0_LEN0_V)<<(HOST_HOSTSLC0_LEN0_S)) +#define HOST_HOSTSLC0_LEN0_V 0xFFFFF +#define HOST_HOSTSLC0_LEN0_S 0 + +#define HOST_SLCHOST_PKT_LEN1_REG (DR_REG_SLCHOST_BASE + 0x94) +/* HOST_HOSTSLC0_LEN1 : RO ;bitpos:[19:0] ;default: 20'h0 ; */ +/*description: */ +#define HOST_HOSTSLC0_LEN1 0x000FFFFF +#define HOST_HOSTSLC0_LEN1_M ((HOST_HOSTSLC0_LEN1_V)<<(HOST_HOSTSLC0_LEN1_S)) +#define HOST_HOSTSLC0_LEN1_V 0xFFFFF +#define HOST_HOSTSLC0_LEN1_S 0 + +#define HOST_SLCHOST_PKT_LEN2_REG (DR_REG_SLCHOST_BASE + 0x98) +/* HOST_HOSTSLC0_LEN2 : RO ;bitpos:[19:0] ;default: 20'h0 ; */ +/*description: */ +#define HOST_HOSTSLC0_LEN2 0x000FFFFF +#define HOST_HOSTSLC0_LEN2_M ((HOST_HOSTSLC0_LEN2_V)<<(HOST_HOSTSLC0_LEN2_S)) +#define HOST_HOSTSLC0_LEN2_V 0xFFFFF +#define HOST_HOSTSLC0_LEN2_S 0 + +#define HOST_SLCHOST_CONF_W8_REG (DR_REG_SLCHOST_BASE + 0x9C) +/* HOST_SLCHOST_CONF35 : R/W ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF35 0x000000FF +#define HOST_SLCHOST_CONF35_M ((HOST_SLCHOST_CONF35_V)<<(HOST_SLCHOST_CONF35_S)) +#define HOST_SLCHOST_CONF35_V 0xFF +#define HOST_SLCHOST_CONF35_S 24 +/* HOST_SLCHOST_CONF34 : R/W ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF34 0x000000FF +#define HOST_SLCHOST_CONF34_M ((HOST_SLCHOST_CONF34_V)<<(HOST_SLCHOST_CONF34_S)) +#define HOST_SLCHOST_CONF34_V 0xFF +#define HOST_SLCHOST_CONF34_S 16 +/* HOST_SLCHOST_CONF33 : R/W ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF33 0x000000FF +#define HOST_SLCHOST_CONF33_M ((HOST_SLCHOST_CONF33_V)<<(HOST_SLCHOST_CONF33_S)) +#define HOST_SLCHOST_CONF33_V 0xFF +#define HOST_SLCHOST_CONF33_S 8 +/* HOST_SLCHOST_CONF32 : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF32 0x000000FF +#define HOST_SLCHOST_CONF32_M ((HOST_SLCHOST_CONF32_V)<<(HOST_SLCHOST_CONF32_S)) +#define HOST_SLCHOST_CONF32_V 0xFF +#define HOST_SLCHOST_CONF32_S 0 + +#define HOST_SLCHOST_CONF_W9_REG (DR_REG_SLCHOST_BASE + 0xA0) +/* HOST_SLCHOST_CONF39 : R/W ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF39 0x000000FF +#define HOST_SLCHOST_CONF39_M ((HOST_SLCHOST_CONF39_V)<<(HOST_SLCHOST_CONF39_S)) +#define HOST_SLCHOST_CONF39_V 0xFF +#define HOST_SLCHOST_CONF39_S 24 +/* HOST_SLCHOST_CONF38 : R/W ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF38 0x000000FF +#define HOST_SLCHOST_CONF38_M ((HOST_SLCHOST_CONF38_V)<<(HOST_SLCHOST_CONF38_S)) +#define HOST_SLCHOST_CONF38_V 0xFF +#define HOST_SLCHOST_CONF38_S 16 +/* HOST_SLCHOST_CONF37 : R/W ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF37 0x000000FF +#define HOST_SLCHOST_CONF37_M ((HOST_SLCHOST_CONF37_V)<<(HOST_SLCHOST_CONF37_S)) +#define HOST_SLCHOST_CONF37_V 0xFF +#define HOST_SLCHOST_CONF37_S 8 +/* HOST_SLCHOST_CONF36 : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF36 0x000000FF +#define HOST_SLCHOST_CONF36_M ((HOST_SLCHOST_CONF36_V)<<(HOST_SLCHOST_CONF36_S)) +#define HOST_SLCHOST_CONF36_V 0xFF +#define HOST_SLCHOST_CONF36_S 0 + +#define HOST_SLCHOST_CONF_W10_REG (DR_REG_SLCHOST_BASE + 0xA4) +/* HOST_SLCHOST_CONF43 : R/W ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF43 0x000000FF +#define HOST_SLCHOST_CONF43_M ((HOST_SLCHOST_CONF43_V)<<(HOST_SLCHOST_CONF43_S)) +#define HOST_SLCHOST_CONF43_V 0xFF +#define HOST_SLCHOST_CONF43_S 24 +/* HOST_SLCHOST_CONF42 : R/W ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF42 0x000000FF +#define HOST_SLCHOST_CONF42_M ((HOST_SLCHOST_CONF42_V)<<(HOST_SLCHOST_CONF42_S)) +#define HOST_SLCHOST_CONF42_V 0xFF +#define HOST_SLCHOST_CONF42_S 16 +/* HOST_SLCHOST_CONF41 : R/W ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF41 0x000000FF +#define HOST_SLCHOST_CONF41_M ((HOST_SLCHOST_CONF41_V)<<(HOST_SLCHOST_CONF41_S)) +#define HOST_SLCHOST_CONF41_V 0xFF +#define HOST_SLCHOST_CONF41_S 8 +/* HOST_SLCHOST_CONF40 : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF40 0x000000FF +#define HOST_SLCHOST_CONF40_M ((HOST_SLCHOST_CONF40_V)<<(HOST_SLCHOST_CONF40_S)) +#define HOST_SLCHOST_CONF40_V 0xFF +#define HOST_SLCHOST_CONF40_S 0 + +#define HOST_SLCHOST_CONF_W11_REG (DR_REG_SLCHOST_BASE + 0xA8) +/* HOST_SLCHOST_CONF47 : R/W ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF47 0x000000FF +#define HOST_SLCHOST_CONF47_M ((HOST_SLCHOST_CONF47_V)<<(HOST_SLCHOST_CONF47_S)) +#define HOST_SLCHOST_CONF47_V 0xFF +#define HOST_SLCHOST_CONF47_S 24 +/* HOST_SLCHOST_CONF46 : R/W ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF46 0x000000FF +#define HOST_SLCHOST_CONF46_M ((HOST_SLCHOST_CONF46_V)<<(HOST_SLCHOST_CONF46_S)) +#define HOST_SLCHOST_CONF46_V 0xFF +#define HOST_SLCHOST_CONF46_S 16 +/* HOST_SLCHOST_CONF45 : R/W ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF45 0x000000FF +#define HOST_SLCHOST_CONF45_M ((HOST_SLCHOST_CONF45_V)<<(HOST_SLCHOST_CONF45_S)) +#define HOST_SLCHOST_CONF45_V 0xFF +#define HOST_SLCHOST_CONF45_S 8 +/* HOST_SLCHOST_CONF44 : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF44 0x000000FF +#define HOST_SLCHOST_CONF44_M ((HOST_SLCHOST_CONF44_V)<<(HOST_SLCHOST_CONF44_S)) +#define HOST_SLCHOST_CONF44_V 0xFF +#define HOST_SLCHOST_CONF44_S 0 + +#define HOST_SLCHOST_CONF_W12_REG (DR_REG_SLCHOST_BASE + 0xAC) +/* HOST_SLCHOST_CONF51 : R/W ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF51 0x000000FF +#define HOST_SLCHOST_CONF51_M ((HOST_SLCHOST_CONF51_V)<<(HOST_SLCHOST_CONF51_S)) +#define HOST_SLCHOST_CONF51_V 0xFF +#define HOST_SLCHOST_CONF51_S 24 +/* HOST_SLCHOST_CONF50 : R/W ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF50 0x000000FF +#define HOST_SLCHOST_CONF50_M ((HOST_SLCHOST_CONF50_V)<<(HOST_SLCHOST_CONF50_S)) +#define HOST_SLCHOST_CONF50_V 0xFF +#define HOST_SLCHOST_CONF50_S 16 +/* HOST_SLCHOST_CONF49 : R/W ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF49 0x000000FF +#define HOST_SLCHOST_CONF49_M ((HOST_SLCHOST_CONF49_V)<<(HOST_SLCHOST_CONF49_S)) +#define HOST_SLCHOST_CONF49_V 0xFF +#define HOST_SLCHOST_CONF49_S 8 +/* HOST_SLCHOST_CONF48 : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF48 0x000000FF +#define HOST_SLCHOST_CONF48_M ((HOST_SLCHOST_CONF48_V)<<(HOST_SLCHOST_CONF48_S)) +#define HOST_SLCHOST_CONF48_V 0xFF +#define HOST_SLCHOST_CONF48_S 0 + +#define HOST_SLCHOST_CONF_W13_REG (DR_REG_SLCHOST_BASE + 0xB0) +/* HOST_SLCHOST_CONF55 : R/W ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF55 0x000000FF +#define HOST_SLCHOST_CONF55_M ((HOST_SLCHOST_CONF55_V)<<(HOST_SLCHOST_CONF55_S)) +#define HOST_SLCHOST_CONF55_V 0xFF +#define HOST_SLCHOST_CONF55_S 24 +/* HOST_SLCHOST_CONF54 : R/W ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF54 0x000000FF +#define HOST_SLCHOST_CONF54_M ((HOST_SLCHOST_CONF54_V)<<(HOST_SLCHOST_CONF54_S)) +#define HOST_SLCHOST_CONF54_V 0xFF +#define HOST_SLCHOST_CONF54_S 16 +/* HOST_SLCHOST_CONF53 : R/W ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF53 0x000000FF +#define HOST_SLCHOST_CONF53_M ((HOST_SLCHOST_CONF53_V)<<(HOST_SLCHOST_CONF53_S)) +#define HOST_SLCHOST_CONF53_V 0xFF +#define HOST_SLCHOST_CONF53_S 8 +/* HOST_SLCHOST_CONF52 : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF52 0x000000FF +#define HOST_SLCHOST_CONF52_M ((HOST_SLCHOST_CONF52_V)<<(HOST_SLCHOST_CONF52_S)) +#define HOST_SLCHOST_CONF52_V 0xFF +#define HOST_SLCHOST_CONF52_S 0 + +#define HOST_SLCHOST_CONF_W14_REG (DR_REG_SLCHOST_BASE + 0xB4) +/* HOST_SLCHOST_CONF59 : R/W ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF59 0x000000FF +#define HOST_SLCHOST_CONF59_M ((HOST_SLCHOST_CONF59_V)<<(HOST_SLCHOST_CONF59_S)) +#define HOST_SLCHOST_CONF59_V 0xFF +#define HOST_SLCHOST_CONF59_S 24 +/* HOST_SLCHOST_CONF58 : R/W ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF58 0x000000FF +#define HOST_SLCHOST_CONF58_M ((HOST_SLCHOST_CONF58_V)<<(HOST_SLCHOST_CONF58_S)) +#define HOST_SLCHOST_CONF58_V 0xFF +#define HOST_SLCHOST_CONF58_S 16 +/* HOST_SLCHOST_CONF57 : R/W ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF57 0x000000FF +#define HOST_SLCHOST_CONF57_M ((HOST_SLCHOST_CONF57_V)<<(HOST_SLCHOST_CONF57_S)) +#define HOST_SLCHOST_CONF57_V 0xFF +#define HOST_SLCHOST_CONF57_S 8 +/* HOST_SLCHOST_CONF56 : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF56 0x000000FF +#define HOST_SLCHOST_CONF56_M ((HOST_SLCHOST_CONF56_V)<<(HOST_SLCHOST_CONF56_S)) +#define HOST_SLCHOST_CONF56_V 0xFF +#define HOST_SLCHOST_CONF56_S 0 + +#define HOST_SLCHOST_CONF_W15_REG (DR_REG_SLCHOST_BASE + 0xB8) +/* HOST_SLCHOST_CONF63 : R/W ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF63 0x000000FF +#define HOST_SLCHOST_CONF63_M ((HOST_SLCHOST_CONF63_V)<<(HOST_SLCHOST_CONF63_S)) +#define HOST_SLCHOST_CONF63_V 0xFF +#define HOST_SLCHOST_CONF63_S 24 +/* HOST_SLCHOST_CONF62 : R/W ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF62 0x000000FF +#define HOST_SLCHOST_CONF62_M ((HOST_SLCHOST_CONF62_V)<<(HOST_SLCHOST_CONF62_S)) +#define HOST_SLCHOST_CONF62_V 0xFF +#define HOST_SLCHOST_CONF62_S 16 +/* HOST_SLCHOST_CONF61 : R/W ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF61 0x000000FF +#define HOST_SLCHOST_CONF61_M ((HOST_SLCHOST_CONF61_V)<<(HOST_SLCHOST_CONF61_S)) +#define HOST_SLCHOST_CONF61_V 0xFF +#define HOST_SLCHOST_CONF61_S 8 +/* HOST_SLCHOST_CONF60 : R/W ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define HOST_SLCHOST_CONF60 0x000000FF +#define HOST_SLCHOST_CONF60_M ((HOST_SLCHOST_CONF60_V)<<(HOST_SLCHOST_CONF60_S)) +#define HOST_SLCHOST_CONF60_V 0xFF +#define HOST_SLCHOST_CONF60_S 0 + +#define HOST_SLCHOST_CHECK_SUM0_REG (DR_REG_SLCHOST_BASE + 0xBC) +/* HOST_SLCHOST_CHECK_SUM0 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define HOST_SLCHOST_CHECK_SUM0 0xFFFFFFFF +#define HOST_SLCHOST_CHECK_SUM0_M ((HOST_SLCHOST_CHECK_SUM0_V)<<(HOST_SLCHOST_CHECK_SUM0_S)) +#define HOST_SLCHOST_CHECK_SUM0_V 0xFFFFFFFF +#define HOST_SLCHOST_CHECK_SUM0_S 0 + +#define HOST_SLCHOST_CHECK_SUM1_REG (DR_REG_SLCHOST_BASE + 0xC0) +/* HOST_SLCHOST_CHECK_SUM1 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define HOST_SLCHOST_CHECK_SUM1 0xFFFFFFFF +#define HOST_SLCHOST_CHECK_SUM1_M ((HOST_SLCHOST_CHECK_SUM1_V)<<(HOST_SLCHOST_CHECK_SUM1_S)) +#define HOST_SLCHOST_CHECK_SUM1_V 0xFFFFFFFF +#define HOST_SLCHOST_CHECK_SUM1_S 0 + +#define HOST_SLC1HOST_TOKEN_RDATA_REG (DR_REG_SLCHOST_BASE + 0xC4) +/* HOST_SLC1_RX_PF_EOF : RO ;bitpos:[31:28] ;default: 4'h0 ; */ +/*description: */ +#define HOST_SLC1_RX_PF_EOF 0x0000000F +#define HOST_SLC1_RX_PF_EOF_M ((HOST_SLC1_RX_PF_EOF_V)<<(HOST_SLC1_RX_PF_EOF_S)) +#define HOST_SLC1_RX_PF_EOF_V 0xF +#define HOST_SLC1_RX_PF_EOF_S 28 +/* HOST_HOSTSLC1_TOKEN1 : RO ;bitpos:[27:16] ;default: 12'h0 ; */ +/*description: */ +#define HOST_HOSTSLC1_TOKEN1 0x00000FFF +#define HOST_HOSTSLC1_TOKEN1_M ((HOST_HOSTSLC1_TOKEN1_V)<<(HOST_HOSTSLC1_TOKEN1_S)) +#define HOST_HOSTSLC1_TOKEN1_V 0xFFF +#define HOST_HOSTSLC1_TOKEN1_S 16 +/* HOST_SLC1_RX_PF_VALID : RO ;bitpos:[12] ;default: 1'h0 ; */ +/*description: */ +#define HOST_SLC1_RX_PF_VALID (BIT(12)) +#define HOST_SLC1_RX_PF_VALID_M (BIT(12)) +#define HOST_SLC1_RX_PF_VALID_V 0x1 +#define HOST_SLC1_RX_PF_VALID_S 12 +/* HOST_SLC1_TOKEN0 : RO ;bitpos:[11:0] ;default: 12'h0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN0 0x00000FFF +#define HOST_SLC1_TOKEN0_M ((HOST_SLC1_TOKEN0_V)<<(HOST_SLC1_TOKEN0_S)) +#define HOST_SLC1_TOKEN0_V 0xFFF +#define HOST_SLC1_TOKEN0_S 0 + +#define HOST_SLC0HOST_TOKEN_WDATA_REG (DR_REG_SLCHOST_BASE + 0xC8) +/* HOST_SLC0HOST_TOKEN1_WD : R/W ;bitpos:[27:16] ;default: 12'h0 ; */ +/*description: */ +#define HOST_SLC0HOST_TOKEN1_WD 0x00000FFF +#define HOST_SLC0HOST_TOKEN1_WD_M ((HOST_SLC0HOST_TOKEN1_WD_V)<<(HOST_SLC0HOST_TOKEN1_WD_S)) +#define HOST_SLC0HOST_TOKEN1_WD_V 0xFFF +#define HOST_SLC0HOST_TOKEN1_WD_S 16 +/* HOST_SLC0HOST_TOKEN0_WD : R/W ;bitpos:[11:0] ;default: 12'h0 ; */ +/*description: */ +#define HOST_SLC0HOST_TOKEN0_WD 0x00000FFF +#define HOST_SLC0HOST_TOKEN0_WD_M ((HOST_SLC0HOST_TOKEN0_WD_V)<<(HOST_SLC0HOST_TOKEN0_WD_S)) +#define HOST_SLC0HOST_TOKEN0_WD_V 0xFFF +#define HOST_SLC0HOST_TOKEN0_WD_S 0 + +#define HOST_SLC1HOST_TOKEN_WDATA_REG (DR_REG_SLCHOST_BASE + 0xCC) +/* HOST_SLC1HOST_TOKEN1_WD : R/W ;bitpos:[27:16] ;default: 12'h0 ; */ +/*description: */ +#define HOST_SLC1HOST_TOKEN1_WD 0x00000FFF +#define HOST_SLC1HOST_TOKEN1_WD_M ((HOST_SLC1HOST_TOKEN1_WD_V)<<(HOST_SLC1HOST_TOKEN1_WD_S)) +#define HOST_SLC1HOST_TOKEN1_WD_V 0xFFF +#define HOST_SLC1HOST_TOKEN1_WD_S 16 +/* HOST_SLC1HOST_TOKEN0_WD : R/W ;bitpos:[11:0] ;default: 12'h0 ; */ +/*description: */ +#define HOST_SLC1HOST_TOKEN0_WD 0x00000FFF +#define HOST_SLC1HOST_TOKEN0_WD_M ((HOST_SLC1HOST_TOKEN0_WD_V)<<(HOST_SLC1HOST_TOKEN0_WD_S)) +#define HOST_SLC1HOST_TOKEN0_WD_V 0xFFF +#define HOST_SLC1HOST_TOKEN0_WD_S 0 + +#define HOST_SLCHOST_TOKEN_CON_REG (DR_REG_SLCHOST_BASE + 0xD0) +/* HOST_SLC0HOST_LEN_WR : WO ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_LEN_WR (BIT(8)) +#define HOST_SLC0HOST_LEN_WR_M (BIT(8)) +#define HOST_SLC0HOST_LEN_WR_V 0x1 +#define HOST_SLC0HOST_LEN_WR_S 8 +/* HOST_SLC1HOST_TOKEN1_WR : WO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_TOKEN1_WR (BIT(7)) +#define HOST_SLC1HOST_TOKEN1_WR_M (BIT(7)) +#define HOST_SLC1HOST_TOKEN1_WR_V 0x1 +#define HOST_SLC1HOST_TOKEN1_WR_S 7 +/* HOST_SLC1HOST_TOKEN0_WR : WO ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_TOKEN0_WR (BIT(6)) +#define HOST_SLC1HOST_TOKEN0_WR_M (BIT(6)) +#define HOST_SLC1HOST_TOKEN0_WR_V 0x1 +#define HOST_SLC1HOST_TOKEN0_WR_S 6 +/* HOST_SLC1HOST_TOKEN1_DEC : WO ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_TOKEN1_DEC (BIT(5)) +#define HOST_SLC1HOST_TOKEN1_DEC_M (BIT(5)) +#define HOST_SLC1HOST_TOKEN1_DEC_V 0x1 +#define HOST_SLC1HOST_TOKEN1_DEC_S 5 +/* HOST_SLC1HOST_TOKEN0_DEC : WO ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_TOKEN0_DEC (BIT(4)) +#define HOST_SLC1HOST_TOKEN0_DEC_M (BIT(4)) +#define HOST_SLC1HOST_TOKEN0_DEC_V 0x1 +#define HOST_SLC1HOST_TOKEN0_DEC_S 4 +/* HOST_SLC0HOST_TOKEN1_WR : WO ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_TOKEN1_WR (BIT(3)) +#define HOST_SLC0HOST_TOKEN1_WR_M (BIT(3)) +#define HOST_SLC0HOST_TOKEN1_WR_V 0x1 +#define HOST_SLC0HOST_TOKEN1_WR_S 3 +/* HOST_SLC0HOST_TOKEN0_WR : WO ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_TOKEN0_WR (BIT(2)) +#define HOST_SLC0HOST_TOKEN0_WR_M (BIT(2)) +#define HOST_SLC0HOST_TOKEN0_WR_V 0x1 +#define HOST_SLC0HOST_TOKEN0_WR_S 2 +/* HOST_SLC0HOST_TOKEN1_DEC : WO ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_TOKEN1_DEC (BIT(1)) +#define HOST_SLC0HOST_TOKEN1_DEC_M (BIT(1)) +#define HOST_SLC0HOST_TOKEN1_DEC_V 0x1 +#define HOST_SLC0HOST_TOKEN1_DEC_S 1 +/* HOST_SLC0HOST_TOKEN0_DEC : WO ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_TOKEN0_DEC (BIT(0)) +#define HOST_SLC0HOST_TOKEN0_DEC_M (BIT(0)) +#define HOST_SLC0HOST_TOKEN0_DEC_V 0x1 +#define HOST_SLC0HOST_TOKEN0_DEC_S 0 + +#define HOST_SLC0HOST_INT_CLR_REG (DR_REG_SLCHOST_BASE + 0xD4) +/* HOST_GPIO_SDIO_INT_CLR : WO ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define HOST_GPIO_SDIO_INT_CLR (BIT(25)) +#define HOST_GPIO_SDIO_INT_CLR_M (BIT(25)) +#define HOST_GPIO_SDIO_INT_CLR_V 0x1 +#define HOST_GPIO_SDIO_INT_CLR_S 25 +/* HOST_SLC0_HOST_RD_RETRY_INT_CLR : WO ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_HOST_RD_RETRY_INT_CLR (BIT(24)) +#define HOST_SLC0_HOST_RD_RETRY_INT_CLR_M (BIT(24)) +#define HOST_SLC0_HOST_RD_RETRY_INT_CLR_V 0x1 +#define HOST_SLC0_HOST_RD_RETRY_INT_CLR_S 24 +/* HOST_SLC0_RX_NEW_PACKET_INT_CLR : WO ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_RX_NEW_PACKET_INT_CLR (BIT(23)) +#define HOST_SLC0_RX_NEW_PACKET_INT_CLR_M (BIT(23)) +#define HOST_SLC0_RX_NEW_PACKET_INT_CLR_V 0x1 +#define HOST_SLC0_RX_NEW_PACKET_INT_CLR_S 23 +/* HOST_SLC0_EXT_BIT3_INT_CLR : WO ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT3_INT_CLR (BIT(22)) +#define HOST_SLC0_EXT_BIT3_INT_CLR_M (BIT(22)) +#define HOST_SLC0_EXT_BIT3_INT_CLR_V 0x1 +#define HOST_SLC0_EXT_BIT3_INT_CLR_S 22 +/* HOST_SLC0_EXT_BIT2_INT_CLR : WO ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT2_INT_CLR (BIT(21)) +#define HOST_SLC0_EXT_BIT2_INT_CLR_M (BIT(21)) +#define HOST_SLC0_EXT_BIT2_INT_CLR_V 0x1 +#define HOST_SLC0_EXT_BIT2_INT_CLR_S 21 +/* HOST_SLC0_EXT_BIT1_INT_CLR : WO ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT1_INT_CLR (BIT(20)) +#define HOST_SLC0_EXT_BIT1_INT_CLR_M (BIT(20)) +#define HOST_SLC0_EXT_BIT1_INT_CLR_V 0x1 +#define HOST_SLC0_EXT_BIT1_INT_CLR_S 20 +/* HOST_SLC0_EXT_BIT0_INT_CLR : WO ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT0_INT_CLR (BIT(19)) +#define HOST_SLC0_EXT_BIT0_INT_CLR_M (BIT(19)) +#define HOST_SLC0_EXT_BIT0_INT_CLR_V 0x1 +#define HOST_SLC0_EXT_BIT0_INT_CLR_S 19 +/* HOST_SLC0_RX_PF_VALID_INT_CLR : WO ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_RX_PF_VALID_INT_CLR (BIT(18)) +#define HOST_SLC0_RX_PF_VALID_INT_CLR_M (BIT(18)) +#define HOST_SLC0_RX_PF_VALID_INT_CLR_V 0x1 +#define HOST_SLC0_RX_PF_VALID_INT_CLR_S 18 +/* HOST_SLC0_TX_OVF_INT_CLR : WO ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TX_OVF_INT_CLR (BIT(17)) +#define HOST_SLC0_TX_OVF_INT_CLR_M (BIT(17)) +#define HOST_SLC0_TX_OVF_INT_CLR_V 0x1 +#define HOST_SLC0_TX_OVF_INT_CLR_S 17 +/* HOST_SLC0_RX_UDF_INT_CLR : WO ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_RX_UDF_INT_CLR (BIT(16)) +#define HOST_SLC0_RX_UDF_INT_CLR_M (BIT(16)) +#define HOST_SLC0_RX_UDF_INT_CLR_V 0x1 +#define HOST_SLC0_RX_UDF_INT_CLR_S 16 +/* HOST_SLC0HOST_TX_START_INT_CLR : WO ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_TX_START_INT_CLR (BIT(15)) +#define HOST_SLC0HOST_TX_START_INT_CLR_M (BIT(15)) +#define HOST_SLC0HOST_TX_START_INT_CLR_V 0x1 +#define HOST_SLC0HOST_TX_START_INT_CLR_S 15 +/* HOST_SLC0HOST_RX_START_INT_CLR : WO ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_RX_START_INT_CLR (BIT(14)) +#define HOST_SLC0HOST_RX_START_INT_CLR_M (BIT(14)) +#define HOST_SLC0HOST_RX_START_INT_CLR_V 0x1 +#define HOST_SLC0HOST_RX_START_INT_CLR_S 14 +/* HOST_SLC0HOST_RX_EOF_INT_CLR : WO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_RX_EOF_INT_CLR (BIT(13)) +#define HOST_SLC0HOST_RX_EOF_INT_CLR_M (BIT(13)) +#define HOST_SLC0HOST_RX_EOF_INT_CLR_V 0x1 +#define HOST_SLC0HOST_RX_EOF_INT_CLR_S 13 +/* HOST_SLC0HOST_RX_SOF_INT_CLR : WO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_RX_SOF_INT_CLR (BIT(12)) +#define HOST_SLC0HOST_RX_SOF_INT_CLR_M (BIT(12)) +#define HOST_SLC0HOST_RX_SOF_INT_CLR_V 0x1 +#define HOST_SLC0HOST_RX_SOF_INT_CLR_S 12 +/* HOST_SLC0_TOKEN1_0TO1_INT_CLR : WO ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN1_0TO1_INT_CLR (BIT(11)) +#define HOST_SLC0_TOKEN1_0TO1_INT_CLR_M (BIT(11)) +#define HOST_SLC0_TOKEN1_0TO1_INT_CLR_V 0x1 +#define HOST_SLC0_TOKEN1_0TO1_INT_CLR_S 11 +/* HOST_SLC0_TOKEN0_0TO1_INT_CLR : WO ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN0_0TO1_INT_CLR (BIT(10)) +#define HOST_SLC0_TOKEN0_0TO1_INT_CLR_M (BIT(10)) +#define HOST_SLC0_TOKEN0_0TO1_INT_CLR_V 0x1 +#define HOST_SLC0_TOKEN0_0TO1_INT_CLR_S 10 +/* HOST_SLC0_TOKEN1_1TO0_INT_CLR : WO ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN1_1TO0_INT_CLR (BIT(9)) +#define HOST_SLC0_TOKEN1_1TO0_INT_CLR_M (BIT(9)) +#define HOST_SLC0_TOKEN1_1TO0_INT_CLR_V 0x1 +#define HOST_SLC0_TOKEN1_1TO0_INT_CLR_S 9 +/* HOST_SLC0_TOKEN0_1TO0_INT_CLR : WO ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN0_1TO0_INT_CLR (BIT(8)) +#define HOST_SLC0_TOKEN0_1TO0_INT_CLR_M (BIT(8)) +#define HOST_SLC0_TOKEN0_1TO0_INT_CLR_V 0x1 +#define HOST_SLC0_TOKEN0_1TO0_INT_CLR_S 8 +/* HOST_SLC0_TOHOST_BIT7_INT_CLR : WO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT7_INT_CLR (BIT(7)) +#define HOST_SLC0_TOHOST_BIT7_INT_CLR_M (BIT(7)) +#define HOST_SLC0_TOHOST_BIT7_INT_CLR_V 0x1 +#define HOST_SLC0_TOHOST_BIT7_INT_CLR_S 7 +/* HOST_SLC0_TOHOST_BIT6_INT_CLR : WO ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT6_INT_CLR (BIT(6)) +#define HOST_SLC0_TOHOST_BIT6_INT_CLR_M (BIT(6)) +#define HOST_SLC0_TOHOST_BIT6_INT_CLR_V 0x1 +#define HOST_SLC0_TOHOST_BIT6_INT_CLR_S 6 +/* HOST_SLC0_TOHOST_BIT5_INT_CLR : WO ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT5_INT_CLR (BIT(5)) +#define HOST_SLC0_TOHOST_BIT5_INT_CLR_M (BIT(5)) +#define HOST_SLC0_TOHOST_BIT5_INT_CLR_V 0x1 +#define HOST_SLC0_TOHOST_BIT5_INT_CLR_S 5 +/* HOST_SLC0_TOHOST_BIT4_INT_CLR : WO ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT4_INT_CLR (BIT(4)) +#define HOST_SLC0_TOHOST_BIT4_INT_CLR_M (BIT(4)) +#define HOST_SLC0_TOHOST_BIT4_INT_CLR_V 0x1 +#define HOST_SLC0_TOHOST_BIT4_INT_CLR_S 4 +/* HOST_SLC0_TOHOST_BIT3_INT_CLR : WO ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT3_INT_CLR (BIT(3)) +#define HOST_SLC0_TOHOST_BIT3_INT_CLR_M (BIT(3)) +#define HOST_SLC0_TOHOST_BIT3_INT_CLR_V 0x1 +#define HOST_SLC0_TOHOST_BIT3_INT_CLR_S 3 +/* HOST_SLC0_TOHOST_BIT2_INT_CLR : WO ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT2_INT_CLR (BIT(2)) +#define HOST_SLC0_TOHOST_BIT2_INT_CLR_M (BIT(2)) +#define HOST_SLC0_TOHOST_BIT2_INT_CLR_V 0x1 +#define HOST_SLC0_TOHOST_BIT2_INT_CLR_S 2 +/* HOST_SLC0_TOHOST_BIT1_INT_CLR : WO ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT1_INT_CLR (BIT(1)) +#define HOST_SLC0_TOHOST_BIT1_INT_CLR_M (BIT(1)) +#define HOST_SLC0_TOHOST_BIT1_INT_CLR_V 0x1 +#define HOST_SLC0_TOHOST_BIT1_INT_CLR_S 1 +/* HOST_SLC0_TOHOST_BIT0_INT_CLR : WO ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT0_INT_CLR (BIT(0)) +#define HOST_SLC0_TOHOST_BIT0_INT_CLR_M (BIT(0)) +#define HOST_SLC0_TOHOST_BIT0_INT_CLR_V 0x1 +#define HOST_SLC0_TOHOST_BIT0_INT_CLR_S 0 + +#define HOST_SLC1HOST_INT_CLR_REG (DR_REG_SLCHOST_BASE + 0xD8) +/* HOST_SLC1_BT_RX_NEW_PACKET_INT_CLR : WO ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_CLR (BIT(25)) +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_CLR_M (BIT(25)) +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_CLR_V 0x1 +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_CLR_S 25 +/* HOST_SLC1_HOST_RD_RETRY_INT_CLR : WO ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_HOST_RD_RETRY_INT_CLR (BIT(24)) +#define HOST_SLC1_HOST_RD_RETRY_INT_CLR_M (BIT(24)) +#define HOST_SLC1_HOST_RD_RETRY_INT_CLR_V 0x1 +#define HOST_SLC1_HOST_RD_RETRY_INT_CLR_S 24 +/* HOST_SLC1_WIFI_RX_NEW_PACKET_INT_CLR : WO ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_CLR (BIT(23)) +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_CLR_M (BIT(23)) +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_CLR_V 0x1 +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_CLR_S 23 +/* HOST_SLC1_EXT_BIT3_INT_CLR : WO ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT3_INT_CLR (BIT(22)) +#define HOST_SLC1_EXT_BIT3_INT_CLR_M (BIT(22)) +#define HOST_SLC1_EXT_BIT3_INT_CLR_V 0x1 +#define HOST_SLC1_EXT_BIT3_INT_CLR_S 22 +/* HOST_SLC1_EXT_BIT2_INT_CLR : WO ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT2_INT_CLR (BIT(21)) +#define HOST_SLC1_EXT_BIT2_INT_CLR_M (BIT(21)) +#define HOST_SLC1_EXT_BIT2_INT_CLR_V 0x1 +#define HOST_SLC1_EXT_BIT2_INT_CLR_S 21 +/* HOST_SLC1_EXT_BIT1_INT_CLR : WO ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT1_INT_CLR (BIT(20)) +#define HOST_SLC1_EXT_BIT1_INT_CLR_M (BIT(20)) +#define HOST_SLC1_EXT_BIT1_INT_CLR_V 0x1 +#define HOST_SLC1_EXT_BIT1_INT_CLR_S 20 +/* HOST_SLC1_EXT_BIT0_INT_CLR : WO ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT0_INT_CLR (BIT(19)) +#define HOST_SLC1_EXT_BIT0_INT_CLR_M (BIT(19)) +#define HOST_SLC1_EXT_BIT0_INT_CLR_V 0x1 +#define HOST_SLC1_EXT_BIT0_INT_CLR_S 19 +/* HOST_SLC1_RX_PF_VALID_INT_CLR : WO ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_RX_PF_VALID_INT_CLR (BIT(18)) +#define HOST_SLC1_RX_PF_VALID_INT_CLR_M (BIT(18)) +#define HOST_SLC1_RX_PF_VALID_INT_CLR_V 0x1 +#define HOST_SLC1_RX_PF_VALID_INT_CLR_S 18 +/* HOST_SLC1_TX_OVF_INT_CLR : WO ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TX_OVF_INT_CLR (BIT(17)) +#define HOST_SLC1_TX_OVF_INT_CLR_M (BIT(17)) +#define HOST_SLC1_TX_OVF_INT_CLR_V 0x1 +#define HOST_SLC1_TX_OVF_INT_CLR_S 17 +/* HOST_SLC1_RX_UDF_INT_CLR : WO ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_RX_UDF_INT_CLR (BIT(16)) +#define HOST_SLC1_RX_UDF_INT_CLR_M (BIT(16)) +#define HOST_SLC1_RX_UDF_INT_CLR_V 0x1 +#define HOST_SLC1_RX_UDF_INT_CLR_S 16 +/* HOST_SLC1HOST_TX_START_INT_CLR : WO ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_TX_START_INT_CLR (BIT(15)) +#define HOST_SLC1HOST_TX_START_INT_CLR_M (BIT(15)) +#define HOST_SLC1HOST_TX_START_INT_CLR_V 0x1 +#define HOST_SLC1HOST_TX_START_INT_CLR_S 15 +/* HOST_SLC1HOST_RX_START_INT_CLR : WO ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_RX_START_INT_CLR (BIT(14)) +#define HOST_SLC1HOST_RX_START_INT_CLR_M (BIT(14)) +#define HOST_SLC1HOST_RX_START_INT_CLR_V 0x1 +#define HOST_SLC1HOST_RX_START_INT_CLR_S 14 +/* HOST_SLC1HOST_RX_EOF_INT_CLR : WO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_RX_EOF_INT_CLR (BIT(13)) +#define HOST_SLC1HOST_RX_EOF_INT_CLR_M (BIT(13)) +#define HOST_SLC1HOST_RX_EOF_INT_CLR_V 0x1 +#define HOST_SLC1HOST_RX_EOF_INT_CLR_S 13 +/* HOST_SLC1HOST_RX_SOF_INT_CLR : WO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_RX_SOF_INT_CLR (BIT(12)) +#define HOST_SLC1HOST_RX_SOF_INT_CLR_M (BIT(12)) +#define HOST_SLC1HOST_RX_SOF_INT_CLR_V 0x1 +#define HOST_SLC1HOST_RX_SOF_INT_CLR_S 12 +/* HOST_SLC1_TOKEN1_0TO1_INT_CLR : WO ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN1_0TO1_INT_CLR (BIT(11)) +#define HOST_SLC1_TOKEN1_0TO1_INT_CLR_M (BIT(11)) +#define HOST_SLC1_TOKEN1_0TO1_INT_CLR_V 0x1 +#define HOST_SLC1_TOKEN1_0TO1_INT_CLR_S 11 +/* HOST_SLC1_TOKEN0_0TO1_INT_CLR : WO ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN0_0TO1_INT_CLR (BIT(10)) +#define HOST_SLC1_TOKEN0_0TO1_INT_CLR_M (BIT(10)) +#define HOST_SLC1_TOKEN0_0TO1_INT_CLR_V 0x1 +#define HOST_SLC1_TOKEN0_0TO1_INT_CLR_S 10 +/* HOST_SLC1_TOKEN1_1TO0_INT_CLR : WO ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN1_1TO0_INT_CLR (BIT(9)) +#define HOST_SLC1_TOKEN1_1TO0_INT_CLR_M (BIT(9)) +#define HOST_SLC1_TOKEN1_1TO0_INT_CLR_V 0x1 +#define HOST_SLC1_TOKEN1_1TO0_INT_CLR_S 9 +/* HOST_SLC1_TOKEN0_1TO0_INT_CLR : WO ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN0_1TO0_INT_CLR (BIT(8)) +#define HOST_SLC1_TOKEN0_1TO0_INT_CLR_M (BIT(8)) +#define HOST_SLC1_TOKEN0_1TO0_INT_CLR_V 0x1 +#define HOST_SLC1_TOKEN0_1TO0_INT_CLR_S 8 +/* HOST_SLC1_TOHOST_BIT7_INT_CLR : WO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT7_INT_CLR (BIT(7)) +#define HOST_SLC1_TOHOST_BIT7_INT_CLR_M (BIT(7)) +#define HOST_SLC1_TOHOST_BIT7_INT_CLR_V 0x1 +#define HOST_SLC1_TOHOST_BIT7_INT_CLR_S 7 +/* HOST_SLC1_TOHOST_BIT6_INT_CLR : WO ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT6_INT_CLR (BIT(6)) +#define HOST_SLC1_TOHOST_BIT6_INT_CLR_M (BIT(6)) +#define HOST_SLC1_TOHOST_BIT6_INT_CLR_V 0x1 +#define HOST_SLC1_TOHOST_BIT6_INT_CLR_S 6 +/* HOST_SLC1_TOHOST_BIT5_INT_CLR : WO ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT5_INT_CLR (BIT(5)) +#define HOST_SLC1_TOHOST_BIT5_INT_CLR_M (BIT(5)) +#define HOST_SLC1_TOHOST_BIT5_INT_CLR_V 0x1 +#define HOST_SLC1_TOHOST_BIT5_INT_CLR_S 5 +/* HOST_SLC1_TOHOST_BIT4_INT_CLR : WO ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT4_INT_CLR (BIT(4)) +#define HOST_SLC1_TOHOST_BIT4_INT_CLR_M (BIT(4)) +#define HOST_SLC1_TOHOST_BIT4_INT_CLR_V 0x1 +#define HOST_SLC1_TOHOST_BIT4_INT_CLR_S 4 +/* HOST_SLC1_TOHOST_BIT3_INT_CLR : WO ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT3_INT_CLR (BIT(3)) +#define HOST_SLC1_TOHOST_BIT3_INT_CLR_M (BIT(3)) +#define HOST_SLC1_TOHOST_BIT3_INT_CLR_V 0x1 +#define HOST_SLC1_TOHOST_BIT3_INT_CLR_S 3 +/* HOST_SLC1_TOHOST_BIT2_INT_CLR : WO ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT2_INT_CLR (BIT(2)) +#define HOST_SLC1_TOHOST_BIT2_INT_CLR_M (BIT(2)) +#define HOST_SLC1_TOHOST_BIT2_INT_CLR_V 0x1 +#define HOST_SLC1_TOHOST_BIT2_INT_CLR_S 2 +/* HOST_SLC1_TOHOST_BIT1_INT_CLR : WO ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT1_INT_CLR (BIT(1)) +#define HOST_SLC1_TOHOST_BIT1_INT_CLR_M (BIT(1)) +#define HOST_SLC1_TOHOST_BIT1_INT_CLR_V 0x1 +#define HOST_SLC1_TOHOST_BIT1_INT_CLR_S 1 +/* HOST_SLC1_TOHOST_BIT0_INT_CLR : WO ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT0_INT_CLR (BIT(0)) +#define HOST_SLC1_TOHOST_BIT0_INT_CLR_M (BIT(0)) +#define HOST_SLC1_TOHOST_BIT0_INT_CLR_V 0x1 +#define HOST_SLC1_TOHOST_BIT0_INT_CLR_S 0 + +#define HOST_SLC0HOST_FUNC1_INT_ENA_REG (DR_REG_SLCHOST_BASE + 0xDC) +/* HOST_FN1_GPIO_SDIO_INT_ENA : R/W ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_GPIO_SDIO_INT_ENA (BIT(25)) +#define HOST_FN1_GPIO_SDIO_INT_ENA_M (BIT(25)) +#define HOST_FN1_GPIO_SDIO_INT_ENA_V 0x1 +#define HOST_FN1_GPIO_SDIO_INT_ENA_S 25 +/* HOST_FN1_SLC0_HOST_RD_RETRY_INT_ENA : R/W ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_HOST_RD_RETRY_INT_ENA (BIT(24)) +#define HOST_FN1_SLC0_HOST_RD_RETRY_INT_ENA_M (BIT(24)) +#define HOST_FN1_SLC0_HOST_RD_RETRY_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_HOST_RD_RETRY_INT_ENA_S 24 +/* HOST_FN1_SLC0_RX_NEW_PACKET_INT_ENA : R/W ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_RX_NEW_PACKET_INT_ENA (BIT(23)) +#define HOST_FN1_SLC0_RX_NEW_PACKET_INT_ENA_M (BIT(23)) +#define HOST_FN1_SLC0_RX_NEW_PACKET_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_RX_NEW_PACKET_INT_ENA_S 23 +/* HOST_FN1_SLC0_EXT_BIT3_INT_ENA : R/W ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_EXT_BIT3_INT_ENA (BIT(22)) +#define HOST_FN1_SLC0_EXT_BIT3_INT_ENA_M (BIT(22)) +#define HOST_FN1_SLC0_EXT_BIT3_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_EXT_BIT3_INT_ENA_S 22 +/* HOST_FN1_SLC0_EXT_BIT2_INT_ENA : R/W ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_EXT_BIT2_INT_ENA (BIT(21)) +#define HOST_FN1_SLC0_EXT_BIT2_INT_ENA_M (BIT(21)) +#define HOST_FN1_SLC0_EXT_BIT2_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_EXT_BIT2_INT_ENA_S 21 +/* HOST_FN1_SLC0_EXT_BIT1_INT_ENA : R/W ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_EXT_BIT1_INT_ENA (BIT(20)) +#define HOST_FN1_SLC0_EXT_BIT1_INT_ENA_M (BIT(20)) +#define HOST_FN1_SLC0_EXT_BIT1_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_EXT_BIT1_INT_ENA_S 20 +/* HOST_FN1_SLC0_EXT_BIT0_INT_ENA : R/W ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_EXT_BIT0_INT_ENA (BIT(19)) +#define HOST_FN1_SLC0_EXT_BIT0_INT_ENA_M (BIT(19)) +#define HOST_FN1_SLC0_EXT_BIT0_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_EXT_BIT0_INT_ENA_S 19 +/* HOST_FN1_SLC0_RX_PF_VALID_INT_ENA : R/W ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_RX_PF_VALID_INT_ENA (BIT(18)) +#define HOST_FN1_SLC0_RX_PF_VALID_INT_ENA_M (BIT(18)) +#define HOST_FN1_SLC0_RX_PF_VALID_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_RX_PF_VALID_INT_ENA_S 18 +/* HOST_FN1_SLC0_TX_OVF_INT_ENA : R/W ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_TX_OVF_INT_ENA (BIT(17)) +#define HOST_FN1_SLC0_TX_OVF_INT_ENA_M (BIT(17)) +#define HOST_FN1_SLC0_TX_OVF_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_TX_OVF_INT_ENA_S 17 +/* HOST_FN1_SLC0_RX_UDF_INT_ENA : R/W ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_RX_UDF_INT_ENA (BIT(16)) +#define HOST_FN1_SLC0_RX_UDF_INT_ENA_M (BIT(16)) +#define HOST_FN1_SLC0_RX_UDF_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_RX_UDF_INT_ENA_S 16 +/* HOST_FN1_SLC0HOST_TX_START_INT_ENA : R/W ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0HOST_TX_START_INT_ENA (BIT(15)) +#define HOST_FN1_SLC0HOST_TX_START_INT_ENA_M (BIT(15)) +#define HOST_FN1_SLC0HOST_TX_START_INT_ENA_V 0x1 +#define HOST_FN1_SLC0HOST_TX_START_INT_ENA_S 15 +/* HOST_FN1_SLC0HOST_RX_START_INT_ENA : R/W ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0HOST_RX_START_INT_ENA (BIT(14)) +#define HOST_FN1_SLC0HOST_RX_START_INT_ENA_M (BIT(14)) +#define HOST_FN1_SLC0HOST_RX_START_INT_ENA_V 0x1 +#define HOST_FN1_SLC0HOST_RX_START_INT_ENA_S 14 +/* HOST_FN1_SLC0HOST_RX_EOF_INT_ENA : R/W ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0HOST_RX_EOF_INT_ENA (BIT(13)) +#define HOST_FN1_SLC0HOST_RX_EOF_INT_ENA_M (BIT(13)) +#define HOST_FN1_SLC0HOST_RX_EOF_INT_ENA_V 0x1 +#define HOST_FN1_SLC0HOST_RX_EOF_INT_ENA_S 13 +/* HOST_FN1_SLC0HOST_RX_SOF_INT_ENA : R/W ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0HOST_RX_SOF_INT_ENA (BIT(12)) +#define HOST_FN1_SLC0HOST_RX_SOF_INT_ENA_M (BIT(12)) +#define HOST_FN1_SLC0HOST_RX_SOF_INT_ENA_V 0x1 +#define HOST_FN1_SLC0HOST_RX_SOF_INT_ENA_S 12 +/* HOST_FN1_SLC0_TOKEN1_0TO1_INT_ENA : R/W ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_TOKEN1_0TO1_INT_ENA (BIT(11)) +#define HOST_FN1_SLC0_TOKEN1_0TO1_INT_ENA_M (BIT(11)) +#define HOST_FN1_SLC0_TOKEN1_0TO1_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_TOKEN1_0TO1_INT_ENA_S 11 +/* HOST_FN1_SLC0_TOKEN0_0TO1_INT_ENA : R/W ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_TOKEN0_0TO1_INT_ENA (BIT(10)) +#define HOST_FN1_SLC0_TOKEN0_0TO1_INT_ENA_M (BIT(10)) +#define HOST_FN1_SLC0_TOKEN0_0TO1_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_TOKEN0_0TO1_INT_ENA_S 10 +/* HOST_FN1_SLC0_TOKEN1_1TO0_INT_ENA : R/W ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_TOKEN1_1TO0_INT_ENA (BIT(9)) +#define HOST_FN1_SLC0_TOKEN1_1TO0_INT_ENA_M (BIT(9)) +#define HOST_FN1_SLC0_TOKEN1_1TO0_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_TOKEN1_1TO0_INT_ENA_S 9 +/* HOST_FN1_SLC0_TOKEN0_1TO0_INT_ENA : R/W ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_TOKEN0_1TO0_INT_ENA (BIT(8)) +#define HOST_FN1_SLC0_TOKEN0_1TO0_INT_ENA_M (BIT(8)) +#define HOST_FN1_SLC0_TOKEN0_1TO0_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_TOKEN0_1TO0_INT_ENA_S 8 +/* HOST_FN1_SLC0_TOHOST_BIT7_INT_ENA : R/W ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_TOHOST_BIT7_INT_ENA (BIT(7)) +#define HOST_FN1_SLC0_TOHOST_BIT7_INT_ENA_M (BIT(7)) +#define HOST_FN1_SLC0_TOHOST_BIT7_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_TOHOST_BIT7_INT_ENA_S 7 +/* HOST_FN1_SLC0_TOHOST_BIT6_INT_ENA : R/W ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_TOHOST_BIT6_INT_ENA (BIT(6)) +#define HOST_FN1_SLC0_TOHOST_BIT6_INT_ENA_M (BIT(6)) +#define HOST_FN1_SLC0_TOHOST_BIT6_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_TOHOST_BIT6_INT_ENA_S 6 +/* HOST_FN1_SLC0_TOHOST_BIT5_INT_ENA : R/W ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_TOHOST_BIT5_INT_ENA (BIT(5)) +#define HOST_FN1_SLC0_TOHOST_BIT5_INT_ENA_M (BIT(5)) +#define HOST_FN1_SLC0_TOHOST_BIT5_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_TOHOST_BIT5_INT_ENA_S 5 +/* HOST_FN1_SLC0_TOHOST_BIT4_INT_ENA : R/W ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_TOHOST_BIT4_INT_ENA (BIT(4)) +#define HOST_FN1_SLC0_TOHOST_BIT4_INT_ENA_M (BIT(4)) +#define HOST_FN1_SLC0_TOHOST_BIT4_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_TOHOST_BIT4_INT_ENA_S 4 +/* HOST_FN1_SLC0_TOHOST_BIT3_INT_ENA : R/W ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_TOHOST_BIT3_INT_ENA (BIT(3)) +#define HOST_FN1_SLC0_TOHOST_BIT3_INT_ENA_M (BIT(3)) +#define HOST_FN1_SLC0_TOHOST_BIT3_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_TOHOST_BIT3_INT_ENA_S 3 +/* HOST_FN1_SLC0_TOHOST_BIT2_INT_ENA : R/W ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_TOHOST_BIT2_INT_ENA (BIT(2)) +#define HOST_FN1_SLC0_TOHOST_BIT2_INT_ENA_M (BIT(2)) +#define HOST_FN1_SLC0_TOHOST_BIT2_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_TOHOST_BIT2_INT_ENA_S 2 +/* HOST_FN1_SLC0_TOHOST_BIT1_INT_ENA : R/W ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_TOHOST_BIT1_INT_ENA (BIT(1)) +#define HOST_FN1_SLC0_TOHOST_BIT1_INT_ENA_M (BIT(1)) +#define HOST_FN1_SLC0_TOHOST_BIT1_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_TOHOST_BIT1_INT_ENA_S 1 +/* HOST_FN1_SLC0_TOHOST_BIT0_INT_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC0_TOHOST_BIT0_INT_ENA (BIT(0)) +#define HOST_FN1_SLC0_TOHOST_BIT0_INT_ENA_M (BIT(0)) +#define HOST_FN1_SLC0_TOHOST_BIT0_INT_ENA_V 0x1 +#define HOST_FN1_SLC0_TOHOST_BIT0_INT_ENA_S 0 + +#define HOST_SLC1HOST_FUNC1_INT_ENA_REG (DR_REG_SLCHOST_BASE + 0xE0) +/* HOST_FN1_SLC1_BT_RX_NEW_PACKET_INT_ENA : R/W ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_BT_RX_NEW_PACKET_INT_ENA (BIT(25)) +#define HOST_FN1_SLC1_BT_RX_NEW_PACKET_INT_ENA_M (BIT(25)) +#define HOST_FN1_SLC1_BT_RX_NEW_PACKET_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_BT_RX_NEW_PACKET_INT_ENA_S 25 +/* HOST_FN1_SLC1_HOST_RD_RETRY_INT_ENA : R/W ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_HOST_RD_RETRY_INT_ENA (BIT(24)) +#define HOST_FN1_SLC1_HOST_RD_RETRY_INT_ENA_M (BIT(24)) +#define HOST_FN1_SLC1_HOST_RD_RETRY_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_HOST_RD_RETRY_INT_ENA_S 24 +/* HOST_FN1_SLC1_WIFI_RX_NEW_PACKET_INT_ENA : R/W ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_WIFI_RX_NEW_PACKET_INT_ENA (BIT(23)) +#define HOST_FN1_SLC1_WIFI_RX_NEW_PACKET_INT_ENA_M (BIT(23)) +#define HOST_FN1_SLC1_WIFI_RX_NEW_PACKET_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_WIFI_RX_NEW_PACKET_INT_ENA_S 23 +/* HOST_FN1_SLC1_EXT_BIT3_INT_ENA : R/W ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_EXT_BIT3_INT_ENA (BIT(22)) +#define HOST_FN1_SLC1_EXT_BIT3_INT_ENA_M (BIT(22)) +#define HOST_FN1_SLC1_EXT_BIT3_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_EXT_BIT3_INT_ENA_S 22 +/* HOST_FN1_SLC1_EXT_BIT2_INT_ENA : R/W ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_EXT_BIT2_INT_ENA (BIT(21)) +#define HOST_FN1_SLC1_EXT_BIT2_INT_ENA_M (BIT(21)) +#define HOST_FN1_SLC1_EXT_BIT2_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_EXT_BIT2_INT_ENA_S 21 +/* HOST_FN1_SLC1_EXT_BIT1_INT_ENA : R/W ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_EXT_BIT1_INT_ENA (BIT(20)) +#define HOST_FN1_SLC1_EXT_BIT1_INT_ENA_M (BIT(20)) +#define HOST_FN1_SLC1_EXT_BIT1_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_EXT_BIT1_INT_ENA_S 20 +/* HOST_FN1_SLC1_EXT_BIT0_INT_ENA : R/W ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_EXT_BIT0_INT_ENA (BIT(19)) +#define HOST_FN1_SLC1_EXT_BIT0_INT_ENA_M (BIT(19)) +#define HOST_FN1_SLC1_EXT_BIT0_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_EXT_BIT0_INT_ENA_S 19 +/* HOST_FN1_SLC1_RX_PF_VALID_INT_ENA : R/W ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_RX_PF_VALID_INT_ENA (BIT(18)) +#define HOST_FN1_SLC1_RX_PF_VALID_INT_ENA_M (BIT(18)) +#define HOST_FN1_SLC1_RX_PF_VALID_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_RX_PF_VALID_INT_ENA_S 18 +/* HOST_FN1_SLC1_TX_OVF_INT_ENA : R/W ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_TX_OVF_INT_ENA (BIT(17)) +#define HOST_FN1_SLC1_TX_OVF_INT_ENA_M (BIT(17)) +#define HOST_FN1_SLC1_TX_OVF_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_TX_OVF_INT_ENA_S 17 +/* HOST_FN1_SLC1_RX_UDF_INT_ENA : R/W ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_RX_UDF_INT_ENA (BIT(16)) +#define HOST_FN1_SLC1_RX_UDF_INT_ENA_M (BIT(16)) +#define HOST_FN1_SLC1_RX_UDF_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_RX_UDF_INT_ENA_S 16 +/* HOST_FN1_SLC1HOST_TX_START_INT_ENA : R/W ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1HOST_TX_START_INT_ENA (BIT(15)) +#define HOST_FN1_SLC1HOST_TX_START_INT_ENA_M (BIT(15)) +#define HOST_FN1_SLC1HOST_TX_START_INT_ENA_V 0x1 +#define HOST_FN1_SLC1HOST_TX_START_INT_ENA_S 15 +/* HOST_FN1_SLC1HOST_RX_START_INT_ENA : R/W ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1HOST_RX_START_INT_ENA (BIT(14)) +#define HOST_FN1_SLC1HOST_RX_START_INT_ENA_M (BIT(14)) +#define HOST_FN1_SLC1HOST_RX_START_INT_ENA_V 0x1 +#define HOST_FN1_SLC1HOST_RX_START_INT_ENA_S 14 +/* HOST_FN1_SLC1HOST_RX_EOF_INT_ENA : R/W ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1HOST_RX_EOF_INT_ENA (BIT(13)) +#define HOST_FN1_SLC1HOST_RX_EOF_INT_ENA_M (BIT(13)) +#define HOST_FN1_SLC1HOST_RX_EOF_INT_ENA_V 0x1 +#define HOST_FN1_SLC1HOST_RX_EOF_INT_ENA_S 13 +/* HOST_FN1_SLC1HOST_RX_SOF_INT_ENA : R/W ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1HOST_RX_SOF_INT_ENA (BIT(12)) +#define HOST_FN1_SLC1HOST_RX_SOF_INT_ENA_M (BIT(12)) +#define HOST_FN1_SLC1HOST_RX_SOF_INT_ENA_V 0x1 +#define HOST_FN1_SLC1HOST_RX_SOF_INT_ENA_S 12 +/* HOST_FN1_SLC1_TOKEN1_0TO1_INT_ENA : R/W ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_TOKEN1_0TO1_INT_ENA (BIT(11)) +#define HOST_FN1_SLC1_TOKEN1_0TO1_INT_ENA_M (BIT(11)) +#define HOST_FN1_SLC1_TOKEN1_0TO1_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_TOKEN1_0TO1_INT_ENA_S 11 +/* HOST_FN1_SLC1_TOKEN0_0TO1_INT_ENA : R/W ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_TOKEN0_0TO1_INT_ENA (BIT(10)) +#define HOST_FN1_SLC1_TOKEN0_0TO1_INT_ENA_M (BIT(10)) +#define HOST_FN1_SLC1_TOKEN0_0TO1_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_TOKEN0_0TO1_INT_ENA_S 10 +/* HOST_FN1_SLC1_TOKEN1_1TO0_INT_ENA : R/W ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_TOKEN1_1TO0_INT_ENA (BIT(9)) +#define HOST_FN1_SLC1_TOKEN1_1TO0_INT_ENA_M (BIT(9)) +#define HOST_FN1_SLC1_TOKEN1_1TO0_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_TOKEN1_1TO0_INT_ENA_S 9 +/* HOST_FN1_SLC1_TOKEN0_1TO0_INT_ENA : R/W ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_TOKEN0_1TO0_INT_ENA (BIT(8)) +#define HOST_FN1_SLC1_TOKEN0_1TO0_INT_ENA_M (BIT(8)) +#define HOST_FN1_SLC1_TOKEN0_1TO0_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_TOKEN0_1TO0_INT_ENA_S 8 +/* HOST_FN1_SLC1_TOHOST_BIT7_INT_ENA : R/W ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_TOHOST_BIT7_INT_ENA (BIT(7)) +#define HOST_FN1_SLC1_TOHOST_BIT7_INT_ENA_M (BIT(7)) +#define HOST_FN1_SLC1_TOHOST_BIT7_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_TOHOST_BIT7_INT_ENA_S 7 +/* HOST_FN1_SLC1_TOHOST_BIT6_INT_ENA : R/W ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_TOHOST_BIT6_INT_ENA (BIT(6)) +#define HOST_FN1_SLC1_TOHOST_BIT6_INT_ENA_M (BIT(6)) +#define HOST_FN1_SLC1_TOHOST_BIT6_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_TOHOST_BIT6_INT_ENA_S 6 +/* HOST_FN1_SLC1_TOHOST_BIT5_INT_ENA : R/W ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_TOHOST_BIT5_INT_ENA (BIT(5)) +#define HOST_FN1_SLC1_TOHOST_BIT5_INT_ENA_M (BIT(5)) +#define HOST_FN1_SLC1_TOHOST_BIT5_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_TOHOST_BIT5_INT_ENA_S 5 +/* HOST_FN1_SLC1_TOHOST_BIT4_INT_ENA : R/W ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_TOHOST_BIT4_INT_ENA (BIT(4)) +#define HOST_FN1_SLC1_TOHOST_BIT4_INT_ENA_M (BIT(4)) +#define HOST_FN1_SLC1_TOHOST_BIT4_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_TOHOST_BIT4_INT_ENA_S 4 +/* HOST_FN1_SLC1_TOHOST_BIT3_INT_ENA : R/W ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_TOHOST_BIT3_INT_ENA (BIT(3)) +#define HOST_FN1_SLC1_TOHOST_BIT3_INT_ENA_M (BIT(3)) +#define HOST_FN1_SLC1_TOHOST_BIT3_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_TOHOST_BIT3_INT_ENA_S 3 +/* HOST_FN1_SLC1_TOHOST_BIT2_INT_ENA : R/W ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_TOHOST_BIT2_INT_ENA (BIT(2)) +#define HOST_FN1_SLC1_TOHOST_BIT2_INT_ENA_M (BIT(2)) +#define HOST_FN1_SLC1_TOHOST_BIT2_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_TOHOST_BIT2_INT_ENA_S 2 +/* HOST_FN1_SLC1_TOHOST_BIT1_INT_ENA : R/W ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_TOHOST_BIT1_INT_ENA (BIT(1)) +#define HOST_FN1_SLC1_TOHOST_BIT1_INT_ENA_M (BIT(1)) +#define HOST_FN1_SLC1_TOHOST_BIT1_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_TOHOST_BIT1_INT_ENA_S 1 +/* HOST_FN1_SLC1_TOHOST_BIT0_INT_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN1_SLC1_TOHOST_BIT0_INT_ENA (BIT(0)) +#define HOST_FN1_SLC1_TOHOST_BIT0_INT_ENA_M (BIT(0)) +#define HOST_FN1_SLC1_TOHOST_BIT0_INT_ENA_V 0x1 +#define HOST_FN1_SLC1_TOHOST_BIT0_INT_ENA_S 0 + +#define HOST_SLC0HOST_FUNC2_INT_ENA_REG (DR_REG_SLCHOST_BASE + 0xE4) +/* HOST_FN2_GPIO_SDIO_INT_ENA : R/W ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_GPIO_SDIO_INT_ENA (BIT(25)) +#define HOST_FN2_GPIO_SDIO_INT_ENA_M (BIT(25)) +#define HOST_FN2_GPIO_SDIO_INT_ENA_V 0x1 +#define HOST_FN2_GPIO_SDIO_INT_ENA_S 25 +/* HOST_FN2_SLC0_HOST_RD_RETRY_INT_ENA : R/W ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_HOST_RD_RETRY_INT_ENA (BIT(24)) +#define HOST_FN2_SLC0_HOST_RD_RETRY_INT_ENA_M (BIT(24)) +#define HOST_FN2_SLC0_HOST_RD_RETRY_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_HOST_RD_RETRY_INT_ENA_S 24 +/* HOST_FN2_SLC0_RX_NEW_PACKET_INT_ENA : R/W ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_RX_NEW_PACKET_INT_ENA (BIT(23)) +#define HOST_FN2_SLC0_RX_NEW_PACKET_INT_ENA_M (BIT(23)) +#define HOST_FN2_SLC0_RX_NEW_PACKET_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_RX_NEW_PACKET_INT_ENA_S 23 +/* HOST_FN2_SLC0_EXT_BIT3_INT_ENA : R/W ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_EXT_BIT3_INT_ENA (BIT(22)) +#define HOST_FN2_SLC0_EXT_BIT3_INT_ENA_M (BIT(22)) +#define HOST_FN2_SLC0_EXT_BIT3_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_EXT_BIT3_INT_ENA_S 22 +/* HOST_FN2_SLC0_EXT_BIT2_INT_ENA : R/W ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_EXT_BIT2_INT_ENA (BIT(21)) +#define HOST_FN2_SLC0_EXT_BIT2_INT_ENA_M (BIT(21)) +#define HOST_FN2_SLC0_EXT_BIT2_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_EXT_BIT2_INT_ENA_S 21 +/* HOST_FN2_SLC0_EXT_BIT1_INT_ENA : R/W ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_EXT_BIT1_INT_ENA (BIT(20)) +#define HOST_FN2_SLC0_EXT_BIT1_INT_ENA_M (BIT(20)) +#define HOST_FN2_SLC0_EXT_BIT1_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_EXT_BIT1_INT_ENA_S 20 +/* HOST_FN2_SLC0_EXT_BIT0_INT_ENA : R/W ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_EXT_BIT0_INT_ENA (BIT(19)) +#define HOST_FN2_SLC0_EXT_BIT0_INT_ENA_M (BIT(19)) +#define HOST_FN2_SLC0_EXT_BIT0_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_EXT_BIT0_INT_ENA_S 19 +/* HOST_FN2_SLC0_RX_PF_VALID_INT_ENA : R/W ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_RX_PF_VALID_INT_ENA (BIT(18)) +#define HOST_FN2_SLC0_RX_PF_VALID_INT_ENA_M (BIT(18)) +#define HOST_FN2_SLC0_RX_PF_VALID_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_RX_PF_VALID_INT_ENA_S 18 +/* HOST_FN2_SLC0_TX_OVF_INT_ENA : R/W ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_TX_OVF_INT_ENA (BIT(17)) +#define HOST_FN2_SLC0_TX_OVF_INT_ENA_M (BIT(17)) +#define HOST_FN2_SLC0_TX_OVF_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_TX_OVF_INT_ENA_S 17 +/* HOST_FN2_SLC0_RX_UDF_INT_ENA : R/W ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_RX_UDF_INT_ENA (BIT(16)) +#define HOST_FN2_SLC0_RX_UDF_INT_ENA_M (BIT(16)) +#define HOST_FN2_SLC0_RX_UDF_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_RX_UDF_INT_ENA_S 16 +/* HOST_FN2_SLC0HOST_TX_START_INT_ENA : R/W ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0HOST_TX_START_INT_ENA (BIT(15)) +#define HOST_FN2_SLC0HOST_TX_START_INT_ENA_M (BIT(15)) +#define HOST_FN2_SLC0HOST_TX_START_INT_ENA_V 0x1 +#define HOST_FN2_SLC0HOST_TX_START_INT_ENA_S 15 +/* HOST_FN2_SLC0HOST_RX_START_INT_ENA : R/W ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0HOST_RX_START_INT_ENA (BIT(14)) +#define HOST_FN2_SLC0HOST_RX_START_INT_ENA_M (BIT(14)) +#define HOST_FN2_SLC0HOST_RX_START_INT_ENA_V 0x1 +#define HOST_FN2_SLC0HOST_RX_START_INT_ENA_S 14 +/* HOST_FN2_SLC0HOST_RX_EOF_INT_ENA : R/W ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0HOST_RX_EOF_INT_ENA (BIT(13)) +#define HOST_FN2_SLC0HOST_RX_EOF_INT_ENA_M (BIT(13)) +#define HOST_FN2_SLC0HOST_RX_EOF_INT_ENA_V 0x1 +#define HOST_FN2_SLC0HOST_RX_EOF_INT_ENA_S 13 +/* HOST_FN2_SLC0HOST_RX_SOF_INT_ENA : R/W ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0HOST_RX_SOF_INT_ENA (BIT(12)) +#define HOST_FN2_SLC0HOST_RX_SOF_INT_ENA_M (BIT(12)) +#define HOST_FN2_SLC0HOST_RX_SOF_INT_ENA_V 0x1 +#define HOST_FN2_SLC0HOST_RX_SOF_INT_ENA_S 12 +/* HOST_FN2_SLC0_TOKEN1_0TO1_INT_ENA : R/W ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_TOKEN1_0TO1_INT_ENA (BIT(11)) +#define HOST_FN2_SLC0_TOKEN1_0TO1_INT_ENA_M (BIT(11)) +#define HOST_FN2_SLC0_TOKEN1_0TO1_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_TOKEN1_0TO1_INT_ENA_S 11 +/* HOST_FN2_SLC0_TOKEN0_0TO1_INT_ENA : R/W ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_TOKEN0_0TO1_INT_ENA (BIT(10)) +#define HOST_FN2_SLC0_TOKEN0_0TO1_INT_ENA_M (BIT(10)) +#define HOST_FN2_SLC0_TOKEN0_0TO1_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_TOKEN0_0TO1_INT_ENA_S 10 +/* HOST_FN2_SLC0_TOKEN1_1TO0_INT_ENA : R/W ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_TOKEN1_1TO0_INT_ENA (BIT(9)) +#define HOST_FN2_SLC0_TOKEN1_1TO0_INT_ENA_M (BIT(9)) +#define HOST_FN2_SLC0_TOKEN1_1TO0_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_TOKEN1_1TO0_INT_ENA_S 9 +/* HOST_FN2_SLC0_TOKEN0_1TO0_INT_ENA : R/W ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_TOKEN0_1TO0_INT_ENA (BIT(8)) +#define HOST_FN2_SLC0_TOKEN0_1TO0_INT_ENA_M (BIT(8)) +#define HOST_FN2_SLC0_TOKEN0_1TO0_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_TOKEN0_1TO0_INT_ENA_S 8 +/* HOST_FN2_SLC0_TOHOST_BIT7_INT_ENA : R/W ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_TOHOST_BIT7_INT_ENA (BIT(7)) +#define HOST_FN2_SLC0_TOHOST_BIT7_INT_ENA_M (BIT(7)) +#define HOST_FN2_SLC0_TOHOST_BIT7_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_TOHOST_BIT7_INT_ENA_S 7 +/* HOST_FN2_SLC0_TOHOST_BIT6_INT_ENA : R/W ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_TOHOST_BIT6_INT_ENA (BIT(6)) +#define HOST_FN2_SLC0_TOHOST_BIT6_INT_ENA_M (BIT(6)) +#define HOST_FN2_SLC0_TOHOST_BIT6_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_TOHOST_BIT6_INT_ENA_S 6 +/* HOST_FN2_SLC0_TOHOST_BIT5_INT_ENA : R/W ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_TOHOST_BIT5_INT_ENA (BIT(5)) +#define HOST_FN2_SLC0_TOHOST_BIT5_INT_ENA_M (BIT(5)) +#define HOST_FN2_SLC0_TOHOST_BIT5_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_TOHOST_BIT5_INT_ENA_S 5 +/* HOST_FN2_SLC0_TOHOST_BIT4_INT_ENA : R/W ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_TOHOST_BIT4_INT_ENA (BIT(4)) +#define HOST_FN2_SLC0_TOHOST_BIT4_INT_ENA_M (BIT(4)) +#define HOST_FN2_SLC0_TOHOST_BIT4_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_TOHOST_BIT4_INT_ENA_S 4 +/* HOST_FN2_SLC0_TOHOST_BIT3_INT_ENA : R/W ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_TOHOST_BIT3_INT_ENA (BIT(3)) +#define HOST_FN2_SLC0_TOHOST_BIT3_INT_ENA_M (BIT(3)) +#define HOST_FN2_SLC0_TOHOST_BIT3_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_TOHOST_BIT3_INT_ENA_S 3 +/* HOST_FN2_SLC0_TOHOST_BIT2_INT_ENA : R/W ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_TOHOST_BIT2_INT_ENA (BIT(2)) +#define HOST_FN2_SLC0_TOHOST_BIT2_INT_ENA_M (BIT(2)) +#define HOST_FN2_SLC0_TOHOST_BIT2_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_TOHOST_BIT2_INT_ENA_S 2 +/* HOST_FN2_SLC0_TOHOST_BIT1_INT_ENA : R/W ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_TOHOST_BIT1_INT_ENA (BIT(1)) +#define HOST_FN2_SLC0_TOHOST_BIT1_INT_ENA_M (BIT(1)) +#define HOST_FN2_SLC0_TOHOST_BIT1_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_TOHOST_BIT1_INT_ENA_S 1 +/* HOST_FN2_SLC0_TOHOST_BIT0_INT_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC0_TOHOST_BIT0_INT_ENA (BIT(0)) +#define HOST_FN2_SLC0_TOHOST_BIT0_INT_ENA_M (BIT(0)) +#define HOST_FN2_SLC0_TOHOST_BIT0_INT_ENA_V 0x1 +#define HOST_FN2_SLC0_TOHOST_BIT0_INT_ENA_S 0 + +#define HOST_SLC1HOST_FUNC2_INT_ENA_REG (DR_REG_SLCHOST_BASE + 0xE8) +/* HOST_FN2_SLC1_BT_RX_NEW_PACKET_INT_ENA : R/W ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_BT_RX_NEW_PACKET_INT_ENA (BIT(25)) +#define HOST_FN2_SLC1_BT_RX_NEW_PACKET_INT_ENA_M (BIT(25)) +#define HOST_FN2_SLC1_BT_RX_NEW_PACKET_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_BT_RX_NEW_PACKET_INT_ENA_S 25 +/* HOST_FN2_SLC1_HOST_RD_RETRY_INT_ENA : R/W ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_HOST_RD_RETRY_INT_ENA (BIT(24)) +#define HOST_FN2_SLC1_HOST_RD_RETRY_INT_ENA_M (BIT(24)) +#define HOST_FN2_SLC1_HOST_RD_RETRY_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_HOST_RD_RETRY_INT_ENA_S 24 +/* HOST_FN2_SLC1_WIFI_RX_NEW_PACKET_INT_ENA : R/W ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_WIFI_RX_NEW_PACKET_INT_ENA (BIT(23)) +#define HOST_FN2_SLC1_WIFI_RX_NEW_PACKET_INT_ENA_M (BIT(23)) +#define HOST_FN2_SLC1_WIFI_RX_NEW_PACKET_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_WIFI_RX_NEW_PACKET_INT_ENA_S 23 +/* HOST_FN2_SLC1_EXT_BIT3_INT_ENA : R/W ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_EXT_BIT3_INT_ENA (BIT(22)) +#define HOST_FN2_SLC1_EXT_BIT3_INT_ENA_M (BIT(22)) +#define HOST_FN2_SLC1_EXT_BIT3_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_EXT_BIT3_INT_ENA_S 22 +/* HOST_FN2_SLC1_EXT_BIT2_INT_ENA : R/W ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_EXT_BIT2_INT_ENA (BIT(21)) +#define HOST_FN2_SLC1_EXT_BIT2_INT_ENA_M (BIT(21)) +#define HOST_FN2_SLC1_EXT_BIT2_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_EXT_BIT2_INT_ENA_S 21 +/* HOST_FN2_SLC1_EXT_BIT1_INT_ENA : R/W ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_EXT_BIT1_INT_ENA (BIT(20)) +#define HOST_FN2_SLC1_EXT_BIT1_INT_ENA_M (BIT(20)) +#define HOST_FN2_SLC1_EXT_BIT1_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_EXT_BIT1_INT_ENA_S 20 +/* HOST_FN2_SLC1_EXT_BIT0_INT_ENA : R/W ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_EXT_BIT0_INT_ENA (BIT(19)) +#define HOST_FN2_SLC1_EXT_BIT0_INT_ENA_M (BIT(19)) +#define HOST_FN2_SLC1_EXT_BIT0_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_EXT_BIT0_INT_ENA_S 19 +/* HOST_FN2_SLC1_RX_PF_VALID_INT_ENA : R/W ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_RX_PF_VALID_INT_ENA (BIT(18)) +#define HOST_FN2_SLC1_RX_PF_VALID_INT_ENA_M (BIT(18)) +#define HOST_FN2_SLC1_RX_PF_VALID_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_RX_PF_VALID_INT_ENA_S 18 +/* HOST_FN2_SLC1_TX_OVF_INT_ENA : R/W ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_TX_OVF_INT_ENA (BIT(17)) +#define HOST_FN2_SLC1_TX_OVF_INT_ENA_M (BIT(17)) +#define HOST_FN2_SLC1_TX_OVF_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_TX_OVF_INT_ENA_S 17 +/* HOST_FN2_SLC1_RX_UDF_INT_ENA : R/W ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_RX_UDF_INT_ENA (BIT(16)) +#define HOST_FN2_SLC1_RX_UDF_INT_ENA_M (BIT(16)) +#define HOST_FN2_SLC1_RX_UDF_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_RX_UDF_INT_ENA_S 16 +/* HOST_FN2_SLC1HOST_TX_START_INT_ENA : R/W ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1HOST_TX_START_INT_ENA (BIT(15)) +#define HOST_FN2_SLC1HOST_TX_START_INT_ENA_M (BIT(15)) +#define HOST_FN2_SLC1HOST_TX_START_INT_ENA_V 0x1 +#define HOST_FN2_SLC1HOST_TX_START_INT_ENA_S 15 +/* HOST_FN2_SLC1HOST_RX_START_INT_ENA : R/W ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1HOST_RX_START_INT_ENA (BIT(14)) +#define HOST_FN2_SLC1HOST_RX_START_INT_ENA_M (BIT(14)) +#define HOST_FN2_SLC1HOST_RX_START_INT_ENA_V 0x1 +#define HOST_FN2_SLC1HOST_RX_START_INT_ENA_S 14 +/* HOST_FN2_SLC1HOST_RX_EOF_INT_ENA : R/W ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1HOST_RX_EOF_INT_ENA (BIT(13)) +#define HOST_FN2_SLC1HOST_RX_EOF_INT_ENA_M (BIT(13)) +#define HOST_FN2_SLC1HOST_RX_EOF_INT_ENA_V 0x1 +#define HOST_FN2_SLC1HOST_RX_EOF_INT_ENA_S 13 +/* HOST_FN2_SLC1HOST_RX_SOF_INT_ENA : R/W ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1HOST_RX_SOF_INT_ENA (BIT(12)) +#define HOST_FN2_SLC1HOST_RX_SOF_INT_ENA_M (BIT(12)) +#define HOST_FN2_SLC1HOST_RX_SOF_INT_ENA_V 0x1 +#define HOST_FN2_SLC1HOST_RX_SOF_INT_ENA_S 12 +/* HOST_FN2_SLC1_TOKEN1_0TO1_INT_ENA : R/W ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_TOKEN1_0TO1_INT_ENA (BIT(11)) +#define HOST_FN2_SLC1_TOKEN1_0TO1_INT_ENA_M (BIT(11)) +#define HOST_FN2_SLC1_TOKEN1_0TO1_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_TOKEN1_0TO1_INT_ENA_S 11 +/* HOST_FN2_SLC1_TOKEN0_0TO1_INT_ENA : R/W ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_TOKEN0_0TO1_INT_ENA (BIT(10)) +#define HOST_FN2_SLC1_TOKEN0_0TO1_INT_ENA_M (BIT(10)) +#define HOST_FN2_SLC1_TOKEN0_0TO1_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_TOKEN0_0TO1_INT_ENA_S 10 +/* HOST_FN2_SLC1_TOKEN1_1TO0_INT_ENA : R/W ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_TOKEN1_1TO0_INT_ENA (BIT(9)) +#define HOST_FN2_SLC1_TOKEN1_1TO0_INT_ENA_M (BIT(9)) +#define HOST_FN2_SLC1_TOKEN1_1TO0_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_TOKEN1_1TO0_INT_ENA_S 9 +/* HOST_FN2_SLC1_TOKEN0_1TO0_INT_ENA : R/W ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_TOKEN0_1TO0_INT_ENA (BIT(8)) +#define HOST_FN2_SLC1_TOKEN0_1TO0_INT_ENA_M (BIT(8)) +#define HOST_FN2_SLC1_TOKEN0_1TO0_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_TOKEN0_1TO0_INT_ENA_S 8 +/* HOST_FN2_SLC1_TOHOST_BIT7_INT_ENA : R/W ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_TOHOST_BIT7_INT_ENA (BIT(7)) +#define HOST_FN2_SLC1_TOHOST_BIT7_INT_ENA_M (BIT(7)) +#define HOST_FN2_SLC1_TOHOST_BIT7_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_TOHOST_BIT7_INT_ENA_S 7 +/* HOST_FN2_SLC1_TOHOST_BIT6_INT_ENA : R/W ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_TOHOST_BIT6_INT_ENA (BIT(6)) +#define HOST_FN2_SLC1_TOHOST_BIT6_INT_ENA_M (BIT(6)) +#define HOST_FN2_SLC1_TOHOST_BIT6_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_TOHOST_BIT6_INT_ENA_S 6 +/* HOST_FN2_SLC1_TOHOST_BIT5_INT_ENA : R/W ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_TOHOST_BIT5_INT_ENA (BIT(5)) +#define HOST_FN2_SLC1_TOHOST_BIT5_INT_ENA_M (BIT(5)) +#define HOST_FN2_SLC1_TOHOST_BIT5_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_TOHOST_BIT5_INT_ENA_S 5 +/* HOST_FN2_SLC1_TOHOST_BIT4_INT_ENA : R/W ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_TOHOST_BIT4_INT_ENA (BIT(4)) +#define HOST_FN2_SLC1_TOHOST_BIT4_INT_ENA_M (BIT(4)) +#define HOST_FN2_SLC1_TOHOST_BIT4_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_TOHOST_BIT4_INT_ENA_S 4 +/* HOST_FN2_SLC1_TOHOST_BIT3_INT_ENA : R/W ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_TOHOST_BIT3_INT_ENA (BIT(3)) +#define HOST_FN2_SLC1_TOHOST_BIT3_INT_ENA_M (BIT(3)) +#define HOST_FN2_SLC1_TOHOST_BIT3_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_TOHOST_BIT3_INT_ENA_S 3 +/* HOST_FN2_SLC1_TOHOST_BIT2_INT_ENA : R/W ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_TOHOST_BIT2_INT_ENA (BIT(2)) +#define HOST_FN2_SLC1_TOHOST_BIT2_INT_ENA_M (BIT(2)) +#define HOST_FN2_SLC1_TOHOST_BIT2_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_TOHOST_BIT2_INT_ENA_S 2 +/* HOST_FN2_SLC1_TOHOST_BIT1_INT_ENA : R/W ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_TOHOST_BIT1_INT_ENA (BIT(1)) +#define HOST_FN2_SLC1_TOHOST_BIT1_INT_ENA_M (BIT(1)) +#define HOST_FN2_SLC1_TOHOST_BIT1_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_TOHOST_BIT1_INT_ENA_S 1 +/* HOST_FN2_SLC1_TOHOST_BIT0_INT_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define HOST_FN2_SLC1_TOHOST_BIT0_INT_ENA (BIT(0)) +#define HOST_FN2_SLC1_TOHOST_BIT0_INT_ENA_M (BIT(0)) +#define HOST_FN2_SLC1_TOHOST_BIT0_INT_ENA_V 0x1 +#define HOST_FN2_SLC1_TOHOST_BIT0_INT_ENA_S 0 + +#define HOST_SLC0HOST_INT_ENA_REG (DR_REG_SLCHOST_BASE + 0xEC) +/* HOST_GPIO_SDIO_INT_ENA : R/W ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define HOST_GPIO_SDIO_INT_ENA (BIT(25)) +#define HOST_GPIO_SDIO_INT_ENA_M (BIT(25)) +#define HOST_GPIO_SDIO_INT_ENA_V 0x1 +#define HOST_GPIO_SDIO_INT_ENA_S 25 +/* HOST_SLC0_HOST_RD_RETRY_INT_ENA : R/W ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_HOST_RD_RETRY_INT_ENA (BIT(24)) +#define HOST_SLC0_HOST_RD_RETRY_INT_ENA_M (BIT(24)) +#define HOST_SLC0_HOST_RD_RETRY_INT_ENA_V 0x1 +#define HOST_SLC0_HOST_RD_RETRY_INT_ENA_S 24 +/* HOST_SLC0_RX_NEW_PACKET_INT_ENA : R/W ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_RX_NEW_PACKET_INT_ENA (BIT(23)) +#define HOST_SLC0_RX_NEW_PACKET_INT_ENA_M (BIT(23)) +#define HOST_SLC0_RX_NEW_PACKET_INT_ENA_V 0x1 +#define HOST_SLC0_RX_NEW_PACKET_INT_ENA_S 23 +/* HOST_SLC0_EXT_BIT3_INT_ENA : R/W ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT3_INT_ENA (BIT(22)) +#define HOST_SLC0_EXT_BIT3_INT_ENA_M (BIT(22)) +#define HOST_SLC0_EXT_BIT3_INT_ENA_V 0x1 +#define HOST_SLC0_EXT_BIT3_INT_ENA_S 22 +/* HOST_SLC0_EXT_BIT2_INT_ENA : R/W ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT2_INT_ENA (BIT(21)) +#define HOST_SLC0_EXT_BIT2_INT_ENA_M (BIT(21)) +#define HOST_SLC0_EXT_BIT2_INT_ENA_V 0x1 +#define HOST_SLC0_EXT_BIT2_INT_ENA_S 21 +/* HOST_SLC0_EXT_BIT1_INT_ENA : R/W ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT1_INT_ENA (BIT(20)) +#define HOST_SLC0_EXT_BIT1_INT_ENA_M (BIT(20)) +#define HOST_SLC0_EXT_BIT1_INT_ENA_V 0x1 +#define HOST_SLC0_EXT_BIT1_INT_ENA_S 20 +/* HOST_SLC0_EXT_BIT0_INT_ENA : R/W ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT0_INT_ENA (BIT(19)) +#define HOST_SLC0_EXT_BIT0_INT_ENA_M (BIT(19)) +#define HOST_SLC0_EXT_BIT0_INT_ENA_V 0x1 +#define HOST_SLC0_EXT_BIT0_INT_ENA_S 19 +/* HOST_SLC0_RX_PF_VALID_INT_ENA : R/W ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_RX_PF_VALID_INT_ENA (BIT(18)) +#define HOST_SLC0_RX_PF_VALID_INT_ENA_M (BIT(18)) +#define HOST_SLC0_RX_PF_VALID_INT_ENA_V 0x1 +#define HOST_SLC0_RX_PF_VALID_INT_ENA_S 18 +/* HOST_SLC0_TX_OVF_INT_ENA : R/W ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TX_OVF_INT_ENA (BIT(17)) +#define HOST_SLC0_TX_OVF_INT_ENA_M (BIT(17)) +#define HOST_SLC0_TX_OVF_INT_ENA_V 0x1 +#define HOST_SLC0_TX_OVF_INT_ENA_S 17 +/* HOST_SLC0_RX_UDF_INT_ENA : R/W ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_RX_UDF_INT_ENA (BIT(16)) +#define HOST_SLC0_RX_UDF_INT_ENA_M (BIT(16)) +#define HOST_SLC0_RX_UDF_INT_ENA_V 0x1 +#define HOST_SLC0_RX_UDF_INT_ENA_S 16 +/* HOST_SLC0HOST_TX_START_INT_ENA : R/W ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_TX_START_INT_ENA (BIT(15)) +#define HOST_SLC0HOST_TX_START_INT_ENA_M (BIT(15)) +#define HOST_SLC0HOST_TX_START_INT_ENA_V 0x1 +#define HOST_SLC0HOST_TX_START_INT_ENA_S 15 +/* HOST_SLC0HOST_RX_START_INT_ENA : R/W ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_RX_START_INT_ENA (BIT(14)) +#define HOST_SLC0HOST_RX_START_INT_ENA_M (BIT(14)) +#define HOST_SLC0HOST_RX_START_INT_ENA_V 0x1 +#define HOST_SLC0HOST_RX_START_INT_ENA_S 14 +/* HOST_SLC0HOST_RX_EOF_INT_ENA : R/W ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_RX_EOF_INT_ENA (BIT(13)) +#define HOST_SLC0HOST_RX_EOF_INT_ENA_M (BIT(13)) +#define HOST_SLC0HOST_RX_EOF_INT_ENA_V 0x1 +#define HOST_SLC0HOST_RX_EOF_INT_ENA_S 13 +/* HOST_SLC0HOST_RX_SOF_INT_ENA : R/W ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_RX_SOF_INT_ENA (BIT(12)) +#define HOST_SLC0HOST_RX_SOF_INT_ENA_M (BIT(12)) +#define HOST_SLC0HOST_RX_SOF_INT_ENA_V 0x1 +#define HOST_SLC0HOST_RX_SOF_INT_ENA_S 12 +/* HOST_SLC0_TOKEN1_0TO1_INT_ENA : R/W ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN1_0TO1_INT_ENA (BIT(11)) +#define HOST_SLC0_TOKEN1_0TO1_INT_ENA_M (BIT(11)) +#define HOST_SLC0_TOKEN1_0TO1_INT_ENA_V 0x1 +#define HOST_SLC0_TOKEN1_0TO1_INT_ENA_S 11 +/* HOST_SLC0_TOKEN0_0TO1_INT_ENA : R/W ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN0_0TO1_INT_ENA (BIT(10)) +#define HOST_SLC0_TOKEN0_0TO1_INT_ENA_M (BIT(10)) +#define HOST_SLC0_TOKEN0_0TO1_INT_ENA_V 0x1 +#define HOST_SLC0_TOKEN0_0TO1_INT_ENA_S 10 +/* HOST_SLC0_TOKEN1_1TO0_INT_ENA : R/W ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN1_1TO0_INT_ENA (BIT(9)) +#define HOST_SLC0_TOKEN1_1TO0_INT_ENA_M (BIT(9)) +#define HOST_SLC0_TOKEN1_1TO0_INT_ENA_V 0x1 +#define HOST_SLC0_TOKEN1_1TO0_INT_ENA_S 9 +/* HOST_SLC0_TOKEN0_1TO0_INT_ENA : R/W ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN0_1TO0_INT_ENA (BIT(8)) +#define HOST_SLC0_TOKEN0_1TO0_INT_ENA_M (BIT(8)) +#define HOST_SLC0_TOKEN0_1TO0_INT_ENA_V 0x1 +#define HOST_SLC0_TOKEN0_1TO0_INT_ENA_S 8 +/* HOST_SLC0_TOHOST_BIT7_INT_ENA : R/W ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT7_INT_ENA (BIT(7)) +#define HOST_SLC0_TOHOST_BIT7_INT_ENA_M (BIT(7)) +#define HOST_SLC0_TOHOST_BIT7_INT_ENA_V 0x1 +#define HOST_SLC0_TOHOST_BIT7_INT_ENA_S 7 +/* HOST_SLC0_TOHOST_BIT6_INT_ENA : R/W ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT6_INT_ENA (BIT(6)) +#define HOST_SLC0_TOHOST_BIT6_INT_ENA_M (BIT(6)) +#define HOST_SLC0_TOHOST_BIT6_INT_ENA_V 0x1 +#define HOST_SLC0_TOHOST_BIT6_INT_ENA_S 6 +/* HOST_SLC0_TOHOST_BIT5_INT_ENA : R/W ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT5_INT_ENA (BIT(5)) +#define HOST_SLC0_TOHOST_BIT5_INT_ENA_M (BIT(5)) +#define HOST_SLC0_TOHOST_BIT5_INT_ENA_V 0x1 +#define HOST_SLC0_TOHOST_BIT5_INT_ENA_S 5 +/* HOST_SLC0_TOHOST_BIT4_INT_ENA : R/W ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT4_INT_ENA (BIT(4)) +#define HOST_SLC0_TOHOST_BIT4_INT_ENA_M (BIT(4)) +#define HOST_SLC0_TOHOST_BIT4_INT_ENA_V 0x1 +#define HOST_SLC0_TOHOST_BIT4_INT_ENA_S 4 +/* HOST_SLC0_TOHOST_BIT3_INT_ENA : R/W ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT3_INT_ENA (BIT(3)) +#define HOST_SLC0_TOHOST_BIT3_INT_ENA_M (BIT(3)) +#define HOST_SLC0_TOHOST_BIT3_INT_ENA_V 0x1 +#define HOST_SLC0_TOHOST_BIT3_INT_ENA_S 3 +/* HOST_SLC0_TOHOST_BIT2_INT_ENA : R/W ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT2_INT_ENA (BIT(2)) +#define HOST_SLC0_TOHOST_BIT2_INT_ENA_M (BIT(2)) +#define HOST_SLC0_TOHOST_BIT2_INT_ENA_V 0x1 +#define HOST_SLC0_TOHOST_BIT2_INT_ENA_S 2 +/* HOST_SLC0_TOHOST_BIT1_INT_ENA : R/W ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT1_INT_ENA (BIT(1)) +#define HOST_SLC0_TOHOST_BIT1_INT_ENA_M (BIT(1)) +#define HOST_SLC0_TOHOST_BIT1_INT_ENA_V 0x1 +#define HOST_SLC0_TOHOST_BIT1_INT_ENA_S 1 +/* HOST_SLC0_TOHOST_BIT0_INT_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT0_INT_ENA (BIT(0)) +#define HOST_SLC0_TOHOST_BIT0_INT_ENA_M (BIT(0)) +#define HOST_SLC0_TOHOST_BIT0_INT_ENA_V 0x1 +#define HOST_SLC0_TOHOST_BIT0_INT_ENA_S 0 + +#define HOST_SLC1HOST_INT_ENA_REG (DR_REG_SLCHOST_BASE + 0xF0) +/* HOST_SLC1_BT_RX_NEW_PACKET_INT_ENA : R/W ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_ENA (BIT(25)) +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_ENA_M (BIT(25)) +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_ENA_V 0x1 +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_ENA_S 25 +/* HOST_SLC1_HOST_RD_RETRY_INT_ENA : R/W ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_HOST_RD_RETRY_INT_ENA (BIT(24)) +#define HOST_SLC1_HOST_RD_RETRY_INT_ENA_M (BIT(24)) +#define HOST_SLC1_HOST_RD_RETRY_INT_ENA_V 0x1 +#define HOST_SLC1_HOST_RD_RETRY_INT_ENA_S 24 +/* HOST_SLC1_WIFI_RX_NEW_PACKET_INT_ENA : R/W ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_ENA (BIT(23)) +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_ENA_M (BIT(23)) +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_ENA_V 0x1 +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_ENA_S 23 +/* HOST_SLC1_EXT_BIT3_INT_ENA : R/W ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT3_INT_ENA (BIT(22)) +#define HOST_SLC1_EXT_BIT3_INT_ENA_M (BIT(22)) +#define HOST_SLC1_EXT_BIT3_INT_ENA_V 0x1 +#define HOST_SLC1_EXT_BIT3_INT_ENA_S 22 +/* HOST_SLC1_EXT_BIT2_INT_ENA : R/W ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT2_INT_ENA (BIT(21)) +#define HOST_SLC1_EXT_BIT2_INT_ENA_M (BIT(21)) +#define HOST_SLC1_EXT_BIT2_INT_ENA_V 0x1 +#define HOST_SLC1_EXT_BIT2_INT_ENA_S 21 +/* HOST_SLC1_EXT_BIT1_INT_ENA : R/W ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT1_INT_ENA (BIT(20)) +#define HOST_SLC1_EXT_BIT1_INT_ENA_M (BIT(20)) +#define HOST_SLC1_EXT_BIT1_INT_ENA_V 0x1 +#define HOST_SLC1_EXT_BIT1_INT_ENA_S 20 +/* HOST_SLC1_EXT_BIT0_INT_ENA : R/W ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT0_INT_ENA (BIT(19)) +#define HOST_SLC1_EXT_BIT0_INT_ENA_M (BIT(19)) +#define HOST_SLC1_EXT_BIT0_INT_ENA_V 0x1 +#define HOST_SLC1_EXT_BIT0_INT_ENA_S 19 +/* HOST_SLC1_RX_PF_VALID_INT_ENA : R/W ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_RX_PF_VALID_INT_ENA (BIT(18)) +#define HOST_SLC1_RX_PF_VALID_INT_ENA_M (BIT(18)) +#define HOST_SLC1_RX_PF_VALID_INT_ENA_V 0x1 +#define HOST_SLC1_RX_PF_VALID_INT_ENA_S 18 +/* HOST_SLC1_TX_OVF_INT_ENA : R/W ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TX_OVF_INT_ENA (BIT(17)) +#define HOST_SLC1_TX_OVF_INT_ENA_M (BIT(17)) +#define HOST_SLC1_TX_OVF_INT_ENA_V 0x1 +#define HOST_SLC1_TX_OVF_INT_ENA_S 17 +/* HOST_SLC1_RX_UDF_INT_ENA : R/W ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_RX_UDF_INT_ENA (BIT(16)) +#define HOST_SLC1_RX_UDF_INT_ENA_M (BIT(16)) +#define HOST_SLC1_RX_UDF_INT_ENA_V 0x1 +#define HOST_SLC1_RX_UDF_INT_ENA_S 16 +/* HOST_SLC1HOST_TX_START_INT_ENA : R/W ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_TX_START_INT_ENA (BIT(15)) +#define HOST_SLC1HOST_TX_START_INT_ENA_M (BIT(15)) +#define HOST_SLC1HOST_TX_START_INT_ENA_V 0x1 +#define HOST_SLC1HOST_TX_START_INT_ENA_S 15 +/* HOST_SLC1HOST_RX_START_INT_ENA : R/W ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_RX_START_INT_ENA (BIT(14)) +#define HOST_SLC1HOST_RX_START_INT_ENA_M (BIT(14)) +#define HOST_SLC1HOST_RX_START_INT_ENA_V 0x1 +#define HOST_SLC1HOST_RX_START_INT_ENA_S 14 +/* HOST_SLC1HOST_RX_EOF_INT_ENA : R/W ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_RX_EOF_INT_ENA (BIT(13)) +#define HOST_SLC1HOST_RX_EOF_INT_ENA_M (BIT(13)) +#define HOST_SLC1HOST_RX_EOF_INT_ENA_V 0x1 +#define HOST_SLC1HOST_RX_EOF_INT_ENA_S 13 +/* HOST_SLC1HOST_RX_SOF_INT_ENA : R/W ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_RX_SOF_INT_ENA (BIT(12)) +#define HOST_SLC1HOST_RX_SOF_INT_ENA_M (BIT(12)) +#define HOST_SLC1HOST_RX_SOF_INT_ENA_V 0x1 +#define HOST_SLC1HOST_RX_SOF_INT_ENA_S 12 +/* HOST_SLC1_TOKEN1_0TO1_INT_ENA : R/W ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN1_0TO1_INT_ENA (BIT(11)) +#define HOST_SLC1_TOKEN1_0TO1_INT_ENA_M (BIT(11)) +#define HOST_SLC1_TOKEN1_0TO1_INT_ENA_V 0x1 +#define HOST_SLC1_TOKEN1_0TO1_INT_ENA_S 11 +/* HOST_SLC1_TOKEN0_0TO1_INT_ENA : R/W ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN0_0TO1_INT_ENA (BIT(10)) +#define HOST_SLC1_TOKEN0_0TO1_INT_ENA_M (BIT(10)) +#define HOST_SLC1_TOKEN0_0TO1_INT_ENA_V 0x1 +#define HOST_SLC1_TOKEN0_0TO1_INT_ENA_S 10 +/* HOST_SLC1_TOKEN1_1TO0_INT_ENA : R/W ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN1_1TO0_INT_ENA (BIT(9)) +#define HOST_SLC1_TOKEN1_1TO0_INT_ENA_M (BIT(9)) +#define HOST_SLC1_TOKEN1_1TO0_INT_ENA_V 0x1 +#define HOST_SLC1_TOKEN1_1TO0_INT_ENA_S 9 +/* HOST_SLC1_TOKEN0_1TO0_INT_ENA : R/W ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN0_1TO0_INT_ENA (BIT(8)) +#define HOST_SLC1_TOKEN0_1TO0_INT_ENA_M (BIT(8)) +#define HOST_SLC1_TOKEN0_1TO0_INT_ENA_V 0x1 +#define HOST_SLC1_TOKEN0_1TO0_INT_ENA_S 8 +/* HOST_SLC1_TOHOST_BIT7_INT_ENA : R/W ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT7_INT_ENA (BIT(7)) +#define HOST_SLC1_TOHOST_BIT7_INT_ENA_M (BIT(7)) +#define HOST_SLC1_TOHOST_BIT7_INT_ENA_V 0x1 +#define HOST_SLC1_TOHOST_BIT7_INT_ENA_S 7 +/* HOST_SLC1_TOHOST_BIT6_INT_ENA : R/W ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT6_INT_ENA (BIT(6)) +#define HOST_SLC1_TOHOST_BIT6_INT_ENA_M (BIT(6)) +#define HOST_SLC1_TOHOST_BIT6_INT_ENA_V 0x1 +#define HOST_SLC1_TOHOST_BIT6_INT_ENA_S 6 +/* HOST_SLC1_TOHOST_BIT5_INT_ENA : R/W ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT5_INT_ENA (BIT(5)) +#define HOST_SLC1_TOHOST_BIT5_INT_ENA_M (BIT(5)) +#define HOST_SLC1_TOHOST_BIT5_INT_ENA_V 0x1 +#define HOST_SLC1_TOHOST_BIT5_INT_ENA_S 5 +/* HOST_SLC1_TOHOST_BIT4_INT_ENA : R/W ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT4_INT_ENA (BIT(4)) +#define HOST_SLC1_TOHOST_BIT4_INT_ENA_M (BIT(4)) +#define HOST_SLC1_TOHOST_BIT4_INT_ENA_V 0x1 +#define HOST_SLC1_TOHOST_BIT4_INT_ENA_S 4 +/* HOST_SLC1_TOHOST_BIT3_INT_ENA : R/W ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT3_INT_ENA (BIT(3)) +#define HOST_SLC1_TOHOST_BIT3_INT_ENA_M (BIT(3)) +#define HOST_SLC1_TOHOST_BIT3_INT_ENA_V 0x1 +#define HOST_SLC1_TOHOST_BIT3_INT_ENA_S 3 +/* HOST_SLC1_TOHOST_BIT2_INT_ENA : R/W ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT2_INT_ENA (BIT(2)) +#define HOST_SLC1_TOHOST_BIT2_INT_ENA_M (BIT(2)) +#define HOST_SLC1_TOHOST_BIT2_INT_ENA_V 0x1 +#define HOST_SLC1_TOHOST_BIT2_INT_ENA_S 2 +/* HOST_SLC1_TOHOST_BIT1_INT_ENA : R/W ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT1_INT_ENA (BIT(1)) +#define HOST_SLC1_TOHOST_BIT1_INT_ENA_M (BIT(1)) +#define HOST_SLC1_TOHOST_BIT1_INT_ENA_V 0x1 +#define HOST_SLC1_TOHOST_BIT1_INT_ENA_S 1 +/* HOST_SLC1_TOHOST_BIT0_INT_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT0_INT_ENA (BIT(0)) +#define HOST_SLC1_TOHOST_BIT0_INT_ENA_M (BIT(0)) +#define HOST_SLC1_TOHOST_BIT0_INT_ENA_V 0x1 +#define HOST_SLC1_TOHOST_BIT0_INT_ENA_S 0 + +#define HOST_SLC0HOST_RX_INFOR_REG (DR_REG_SLCHOST_BASE + 0xF4) +/* HOST_SLC0HOST_RX_INFOR : R/W ;bitpos:[19:0] ;default: 20'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_RX_INFOR 0x000FFFFF +#define HOST_SLC0HOST_RX_INFOR_M ((HOST_SLC0HOST_RX_INFOR_V)<<(HOST_SLC0HOST_RX_INFOR_S)) +#define HOST_SLC0HOST_RX_INFOR_V 0xFFFFF +#define HOST_SLC0HOST_RX_INFOR_S 0 + +#define HOST_SLC1HOST_RX_INFOR_REG (DR_REG_SLCHOST_BASE + 0xF8) +/* HOST_SLC1HOST_RX_INFOR : R/W ;bitpos:[19:0] ;default: 20'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_RX_INFOR 0x000FFFFF +#define HOST_SLC1HOST_RX_INFOR_M ((HOST_SLC1HOST_RX_INFOR_V)<<(HOST_SLC1HOST_RX_INFOR_S)) +#define HOST_SLC1HOST_RX_INFOR_V 0xFFFFF +#define HOST_SLC1HOST_RX_INFOR_S 0 + +#define HOST_SLC0HOST_LEN_WD_REG (DR_REG_SLCHOST_BASE + 0xFC) +/* HOST_SLC0HOST_LEN_WD : R/W ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_LEN_WD 0xFFFFFFFF +#define HOST_SLC0HOST_LEN_WD_M ((HOST_SLC0HOST_LEN_WD_V)<<(HOST_SLC0HOST_LEN_WD_S)) +#define HOST_SLC0HOST_LEN_WD_V 0xFFFFFFFF +#define HOST_SLC0HOST_LEN_WD_S 0 + +#define HOST_SLC_APBWIN_WDATA_REG (DR_REG_SLCHOST_BASE + 0x100) +/* HOST_SLC_APBWIN_WDATA : R/W ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define HOST_SLC_APBWIN_WDATA 0xFFFFFFFF +#define HOST_SLC_APBWIN_WDATA_M ((HOST_SLC_APBWIN_WDATA_V)<<(HOST_SLC_APBWIN_WDATA_S)) +#define HOST_SLC_APBWIN_WDATA_V 0xFFFFFFFF +#define HOST_SLC_APBWIN_WDATA_S 0 + +#define HOST_SLC_APBWIN_CONF_REG (DR_REG_SLCHOST_BASE + 0x104) +/* HOST_SLC_APBWIN_START : R/W ;bitpos:[29] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC_APBWIN_START (BIT(29)) +#define HOST_SLC_APBWIN_START_M (BIT(29)) +#define HOST_SLC_APBWIN_START_V 0x1 +#define HOST_SLC_APBWIN_START_S 29 +/* HOST_SLC_APBWIN_WR : R/W ;bitpos:[28] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC_APBWIN_WR (BIT(28)) +#define HOST_SLC_APBWIN_WR_M (BIT(28)) +#define HOST_SLC_APBWIN_WR_V 0x1 +#define HOST_SLC_APBWIN_WR_S 28 +/* HOST_SLC_APBWIN_ADDR : R/W ;bitpos:[27:0] ;default: 28'b0 ; */ +/*description: */ +#define HOST_SLC_APBWIN_ADDR 0x0FFFFFFF +#define HOST_SLC_APBWIN_ADDR_M ((HOST_SLC_APBWIN_ADDR_V)<<(HOST_SLC_APBWIN_ADDR_S)) +#define HOST_SLC_APBWIN_ADDR_V 0xFFFFFFF +#define HOST_SLC_APBWIN_ADDR_S 0 + +#define HOST_SLC_APBWIN_RDATA_REG (DR_REG_SLCHOST_BASE + 0x108) +/* HOST_SLC_APBWIN_RDATA : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define HOST_SLC_APBWIN_RDATA 0xFFFFFFFF +#define HOST_SLC_APBWIN_RDATA_M ((HOST_SLC_APBWIN_RDATA_V)<<(HOST_SLC_APBWIN_RDATA_S)) +#define HOST_SLC_APBWIN_RDATA_V 0xFFFFFFFF +#define HOST_SLC_APBWIN_RDATA_S 0 + +#define HOST_SLCHOST_RDCLR0_REG (DR_REG_SLCHOST_BASE + 0x10C) +/* HOST_SLCHOST_SLC0_BIT6_CLRADDR : R/W ;bitpos:[17:9] ;default: 9'h1e0 ; */ +/*description: */ +#define HOST_SLCHOST_SLC0_BIT6_CLRADDR 0x000001FF +#define HOST_SLCHOST_SLC0_BIT6_CLRADDR_M ((HOST_SLCHOST_SLC0_BIT6_CLRADDR_V)<<(HOST_SLCHOST_SLC0_BIT6_CLRADDR_S)) +#define HOST_SLCHOST_SLC0_BIT6_CLRADDR_V 0x1FF +#define HOST_SLCHOST_SLC0_BIT6_CLRADDR_S 9 +/* HOST_SLCHOST_SLC0_BIT7_CLRADDR : R/W ;bitpos:[8:0] ;default: 9'h44 ; */ +/*description: */ +#define HOST_SLCHOST_SLC0_BIT7_CLRADDR 0x000001FF +#define HOST_SLCHOST_SLC0_BIT7_CLRADDR_M ((HOST_SLCHOST_SLC0_BIT7_CLRADDR_V)<<(HOST_SLCHOST_SLC0_BIT7_CLRADDR_S)) +#define HOST_SLCHOST_SLC0_BIT7_CLRADDR_V 0x1FF +#define HOST_SLCHOST_SLC0_BIT7_CLRADDR_S 0 + +#define HOST_SLCHOST_RDCLR1_REG (DR_REG_SLCHOST_BASE + 0x110) +/* HOST_SLCHOST_SLC1_BIT6_CLRADDR : R/W ;bitpos:[17:9] ;default: 9'h1e0 ; */ +/*description: */ +#define HOST_SLCHOST_SLC1_BIT6_CLRADDR 0x000001FF +#define HOST_SLCHOST_SLC1_BIT6_CLRADDR_M ((HOST_SLCHOST_SLC1_BIT6_CLRADDR_V)<<(HOST_SLCHOST_SLC1_BIT6_CLRADDR_S)) +#define HOST_SLCHOST_SLC1_BIT6_CLRADDR_V 0x1FF +#define HOST_SLCHOST_SLC1_BIT6_CLRADDR_S 9 +/* HOST_SLCHOST_SLC1_BIT7_CLRADDR : R/W ;bitpos:[8:0] ;default: 9'h1e0 ; */ +/*description: */ +#define HOST_SLCHOST_SLC1_BIT7_CLRADDR 0x000001FF +#define HOST_SLCHOST_SLC1_BIT7_CLRADDR_M ((HOST_SLCHOST_SLC1_BIT7_CLRADDR_V)<<(HOST_SLCHOST_SLC1_BIT7_CLRADDR_S)) +#define HOST_SLCHOST_SLC1_BIT7_CLRADDR_V 0x1FF +#define HOST_SLCHOST_SLC1_BIT7_CLRADDR_S 0 + +#define HOST_SLC0HOST_INT_ENA1_REG (DR_REG_SLCHOST_BASE + 0x114) +/* HOST_GPIO_SDIO_INT_ENA1 : R/W ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define HOST_GPIO_SDIO_INT_ENA1 (BIT(25)) +#define HOST_GPIO_SDIO_INT_ENA1_M (BIT(25)) +#define HOST_GPIO_SDIO_INT_ENA1_V 0x1 +#define HOST_GPIO_SDIO_INT_ENA1_S 25 +/* HOST_SLC0_HOST_RD_RETRY_INT_ENA1 : R/W ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_HOST_RD_RETRY_INT_ENA1 (BIT(24)) +#define HOST_SLC0_HOST_RD_RETRY_INT_ENA1_M (BIT(24)) +#define HOST_SLC0_HOST_RD_RETRY_INT_ENA1_V 0x1 +#define HOST_SLC0_HOST_RD_RETRY_INT_ENA1_S 24 +/* HOST_SLC0_RX_NEW_PACKET_INT_ENA1 : R/W ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_RX_NEW_PACKET_INT_ENA1 (BIT(23)) +#define HOST_SLC0_RX_NEW_PACKET_INT_ENA1_M (BIT(23)) +#define HOST_SLC0_RX_NEW_PACKET_INT_ENA1_V 0x1 +#define HOST_SLC0_RX_NEW_PACKET_INT_ENA1_S 23 +/* HOST_SLC0_EXT_BIT3_INT_ENA1 : R/W ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT3_INT_ENA1 (BIT(22)) +#define HOST_SLC0_EXT_BIT3_INT_ENA1_M (BIT(22)) +#define HOST_SLC0_EXT_BIT3_INT_ENA1_V 0x1 +#define HOST_SLC0_EXT_BIT3_INT_ENA1_S 22 +/* HOST_SLC0_EXT_BIT2_INT_ENA1 : R/W ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT2_INT_ENA1 (BIT(21)) +#define HOST_SLC0_EXT_BIT2_INT_ENA1_M (BIT(21)) +#define HOST_SLC0_EXT_BIT2_INT_ENA1_V 0x1 +#define HOST_SLC0_EXT_BIT2_INT_ENA1_S 21 +/* HOST_SLC0_EXT_BIT1_INT_ENA1 : R/W ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT1_INT_ENA1 (BIT(20)) +#define HOST_SLC0_EXT_BIT1_INT_ENA1_M (BIT(20)) +#define HOST_SLC0_EXT_BIT1_INT_ENA1_V 0x1 +#define HOST_SLC0_EXT_BIT1_INT_ENA1_S 20 +/* HOST_SLC0_EXT_BIT0_INT_ENA1 : R/W ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_EXT_BIT0_INT_ENA1 (BIT(19)) +#define HOST_SLC0_EXT_BIT0_INT_ENA1_M (BIT(19)) +#define HOST_SLC0_EXT_BIT0_INT_ENA1_V 0x1 +#define HOST_SLC0_EXT_BIT0_INT_ENA1_S 19 +/* HOST_SLC0_RX_PF_VALID_INT_ENA1 : R/W ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_RX_PF_VALID_INT_ENA1 (BIT(18)) +#define HOST_SLC0_RX_PF_VALID_INT_ENA1_M (BIT(18)) +#define HOST_SLC0_RX_PF_VALID_INT_ENA1_V 0x1 +#define HOST_SLC0_RX_PF_VALID_INT_ENA1_S 18 +/* HOST_SLC0_TX_OVF_INT_ENA1 : R/W ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TX_OVF_INT_ENA1 (BIT(17)) +#define HOST_SLC0_TX_OVF_INT_ENA1_M (BIT(17)) +#define HOST_SLC0_TX_OVF_INT_ENA1_V 0x1 +#define HOST_SLC0_TX_OVF_INT_ENA1_S 17 +/* HOST_SLC0_RX_UDF_INT_ENA1 : R/W ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_RX_UDF_INT_ENA1 (BIT(16)) +#define HOST_SLC0_RX_UDF_INT_ENA1_M (BIT(16)) +#define HOST_SLC0_RX_UDF_INT_ENA1_V 0x1 +#define HOST_SLC0_RX_UDF_INT_ENA1_S 16 +/* HOST_SLC0HOST_TX_START_INT_ENA1 : R/W ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_TX_START_INT_ENA1 (BIT(15)) +#define HOST_SLC0HOST_TX_START_INT_ENA1_M (BIT(15)) +#define HOST_SLC0HOST_TX_START_INT_ENA1_V 0x1 +#define HOST_SLC0HOST_TX_START_INT_ENA1_S 15 +/* HOST_SLC0HOST_RX_START_INT_ENA1 : R/W ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_RX_START_INT_ENA1 (BIT(14)) +#define HOST_SLC0HOST_RX_START_INT_ENA1_M (BIT(14)) +#define HOST_SLC0HOST_RX_START_INT_ENA1_V 0x1 +#define HOST_SLC0HOST_RX_START_INT_ENA1_S 14 +/* HOST_SLC0HOST_RX_EOF_INT_ENA1 : R/W ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_RX_EOF_INT_ENA1 (BIT(13)) +#define HOST_SLC0HOST_RX_EOF_INT_ENA1_M (BIT(13)) +#define HOST_SLC0HOST_RX_EOF_INT_ENA1_V 0x1 +#define HOST_SLC0HOST_RX_EOF_INT_ENA1_S 13 +/* HOST_SLC0HOST_RX_SOF_INT_ENA1 : R/W ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0HOST_RX_SOF_INT_ENA1 (BIT(12)) +#define HOST_SLC0HOST_RX_SOF_INT_ENA1_M (BIT(12)) +#define HOST_SLC0HOST_RX_SOF_INT_ENA1_V 0x1 +#define HOST_SLC0HOST_RX_SOF_INT_ENA1_S 12 +/* HOST_SLC0_TOKEN1_0TO1_INT_ENA1 : R/W ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN1_0TO1_INT_ENA1 (BIT(11)) +#define HOST_SLC0_TOKEN1_0TO1_INT_ENA1_M (BIT(11)) +#define HOST_SLC0_TOKEN1_0TO1_INT_ENA1_V 0x1 +#define HOST_SLC0_TOKEN1_0TO1_INT_ENA1_S 11 +/* HOST_SLC0_TOKEN0_0TO1_INT_ENA1 : R/W ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN0_0TO1_INT_ENA1 (BIT(10)) +#define HOST_SLC0_TOKEN0_0TO1_INT_ENA1_M (BIT(10)) +#define HOST_SLC0_TOKEN0_0TO1_INT_ENA1_V 0x1 +#define HOST_SLC0_TOKEN0_0TO1_INT_ENA1_S 10 +/* HOST_SLC0_TOKEN1_1TO0_INT_ENA1 : R/W ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN1_1TO0_INT_ENA1 (BIT(9)) +#define HOST_SLC0_TOKEN1_1TO0_INT_ENA1_M (BIT(9)) +#define HOST_SLC0_TOKEN1_1TO0_INT_ENA1_V 0x1 +#define HOST_SLC0_TOKEN1_1TO0_INT_ENA1_S 9 +/* HOST_SLC0_TOKEN0_1TO0_INT_ENA1 : R/W ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOKEN0_1TO0_INT_ENA1 (BIT(8)) +#define HOST_SLC0_TOKEN0_1TO0_INT_ENA1_M (BIT(8)) +#define HOST_SLC0_TOKEN0_1TO0_INT_ENA1_V 0x1 +#define HOST_SLC0_TOKEN0_1TO0_INT_ENA1_S 8 +/* HOST_SLC0_TOHOST_BIT7_INT_ENA1 : R/W ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT7_INT_ENA1 (BIT(7)) +#define HOST_SLC0_TOHOST_BIT7_INT_ENA1_M (BIT(7)) +#define HOST_SLC0_TOHOST_BIT7_INT_ENA1_V 0x1 +#define HOST_SLC0_TOHOST_BIT7_INT_ENA1_S 7 +/* HOST_SLC0_TOHOST_BIT6_INT_ENA1 : R/W ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT6_INT_ENA1 (BIT(6)) +#define HOST_SLC0_TOHOST_BIT6_INT_ENA1_M (BIT(6)) +#define HOST_SLC0_TOHOST_BIT6_INT_ENA1_V 0x1 +#define HOST_SLC0_TOHOST_BIT6_INT_ENA1_S 6 +/* HOST_SLC0_TOHOST_BIT5_INT_ENA1 : R/W ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT5_INT_ENA1 (BIT(5)) +#define HOST_SLC0_TOHOST_BIT5_INT_ENA1_M (BIT(5)) +#define HOST_SLC0_TOHOST_BIT5_INT_ENA1_V 0x1 +#define HOST_SLC0_TOHOST_BIT5_INT_ENA1_S 5 +/* HOST_SLC0_TOHOST_BIT4_INT_ENA1 : R/W ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT4_INT_ENA1 (BIT(4)) +#define HOST_SLC0_TOHOST_BIT4_INT_ENA1_M (BIT(4)) +#define HOST_SLC0_TOHOST_BIT4_INT_ENA1_V 0x1 +#define HOST_SLC0_TOHOST_BIT4_INT_ENA1_S 4 +/* HOST_SLC0_TOHOST_BIT3_INT_ENA1 : R/W ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT3_INT_ENA1 (BIT(3)) +#define HOST_SLC0_TOHOST_BIT3_INT_ENA1_M (BIT(3)) +#define HOST_SLC0_TOHOST_BIT3_INT_ENA1_V 0x1 +#define HOST_SLC0_TOHOST_BIT3_INT_ENA1_S 3 +/* HOST_SLC0_TOHOST_BIT2_INT_ENA1 : R/W ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT2_INT_ENA1 (BIT(2)) +#define HOST_SLC0_TOHOST_BIT2_INT_ENA1_M (BIT(2)) +#define HOST_SLC0_TOHOST_BIT2_INT_ENA1_V 0x1 +#define HOST_SLC0_TOHOST_BIT2_INT_ENA1_S 2 +/* HOST_SLC0_TOHOST_BIT1_INT_ENA1 : R/W ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT1_INT_ENA1 (BIT(1)) +#define HOST_SLC0_TOHOST_BIT1_INT_ENA1_M (BIT(1)) +#define HOST_SLC0_TOHOST_BIT1_INT_ENA1_V 0x1 +#define HOST_SLC0_TOHOST_BIT1_INT_ENA1_S 1 +/* HOST_SLC0_TOHOST_BIT0_INT_ENA1 : R/W ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC0_TOHOST_BIT0_INT_ENA1 (BIT(0)) +#define HOST_SLC0_TOHOST_BIT0_INT_ENA1_M (BIT(0)) +#define HOST_SLC0_TOHOST_BIT0_INT_ENA1_V 0x1 +#define HOST_SLC0_TOHOST_BIT0_INT_ENA1_S 0 + +#define HOST_SLC1HOST_INT_ENA1_REG (DR_REG_SLCHOST_BASE + 0x118) +/* HOST_SLC1_BT_RX_NEW_PACKET_INT_ENA1 : R/W ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_ENA1 (BIT(25)) +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_ENA1_M (BIT(25)) +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_ENA1_V 0x1 +#define HOST_SLC1_BT_RX_NEW_PACKET_INT_ENA1_S 25 +/* HOST_SLC1_HOST_RD_RETRY_INT_ENA1 : R/W ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_HOST_RD_RETRY_INT_ENA1 (BIT(24)) +#define HOST_SLC1_HOST_RD_RETRY_INT_ENA1_M (BIT(24)) +#define HOST_SLC1_HOST_RD_RETRY_INT_ENA1_V 0x1 +#define HOST_SLC1_HOST_RD_RETRY_INT_ENA1_S 24 +/* HOST_SLC1_WIFI_RX_NEW_PACKET_INT_ENA1 : R/W ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_ENA1 (BIT(23)) +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_ENA1_M (BIT(23)) +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_ENA1_V 0x1 +#define HOST_SLC1_WIFI_RX_NEW_PACKET_INT_ENA1_S 23 +/* HOST_SLC1_EXT_BIT3_INT_ENA1 : R/W ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT3_INT_ENA1 (BIT(22)) +#define HOST_SLC1_EXT_BIT3_INT_ENA1_M (BIT(22)) +#define HOST_SLC1_EXT_BIT3_INT_ENA1_V 0x1 +#define HOST_SLC1_EXT_BIT3_INT_ENA1_S 22 +/* HOST_SLC1_EXT_BIT2_INT_ENA1 : R/W ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT2_INT_ENA1 (BIT(21)) +#define HOST_SLC1_EXT_BIT2_INT_ENA1_M (BIT(21)) +#define HOST_SLC1_EXT_BIT2_INT_ENA1_V 0x1 +#define HOST_SLC1_EXT_BIT2_INT_ENA1_S 21 +/* HOST_SLC1_EXT_BIT1_INT_ENA1 : R/W ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT1_INT_ENA1 (BIT(20)) +#define HOST_SLC1_EXT_BIT1_INT_ENA1_M (BIT(20)) +#define HOST_SLC1_EXT_BIT1_INT_ENA1_V 0x1 +#define HOST_SLC1_EXT_BIT1_INT_ENA1_S 20 +/* HOST_SLC1_EXT_BIT0_INT_ENA1 : R/W ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_EXT_BIT0_INT_ENA1 (BIT(19)) +#define HOST_SLC1_EXT_BIT0_INT_ENA1_M (BIT(19)) +#define HOST_SLC1_EXT_BIT0_INT_ENA1_V 0x1 +#define HOST_SLC1_EXT_BIT0_INT_ENA1_S 19 +/* HOST_SLC1_RX_PF_VALID_INT_ENA1 : R/W ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_RX_PF_VALID_INT_ENA1 (BIT(18)) +#define HOST_SLC1_RX_PF_VALID_INT_ENA1_M (BIT(18)) +#define HOST_SLC1_RX_PF_VALID_INT_ENA1_V 0x1 +#define HOST_SLC1_RX_PF_VALID_INT_ENA1_S 18 +/* HOST_SLC1_TX_OVF_INT_ENA1 : R/W ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TX_OVF_INT_ENA1 (BIT(17)) +#define HOST_SLC1_TX_OVF_INT_ENA1_M (BIT(17)) +#define HOST_SLC1_TX_OVF_INT_ENA1_V 0x1 +#define HOST_SLC1_TX_OVF_INT_ENA1_S 17 +/* HOST_SLC1_RX_UDF_INT_ENA1 : R/W ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_RX_UDF_INT_ENA1 (BIT(16)) +#define HOST_SLC1_RX_UDF_INT_ENA1_M (BIT(16)) +#define HOST_SLC1_RX_UDF_INT_ENA1_V 0x1 +#define HOST_SLC1_RX_UDF_INT_ENA1_S 16 +/* HOST_SLC1HOST_TX_START_INT_ENA1 : R/W ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_TX_START_INT_ENA1 (BIT(15)) +#define HOST_SLC1HOST_TX_START_INT_ENA1_M (BIT(15)) +#define HOST_SLC1HOST_TX_START_INT_ENA1_V 0x1 +#define HOST_SLC1HOST_TX_START_INT_ENA1_S 15 +/* HOST_SLC1HOST_RX_START_INT_ENA1 : R/W ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_RX_START_INT_ENA1 (BIT(14)) +#define HOST_SLC1HOST_RX_START_INT_ENA1_M (BIT(14)) +#define HOST_SLC1HOST_RX_START_INT_ENA1_V 0x1 +#define HOST_SLC1HOST_RX_START_INT_ENA1_S 14 +/* HOST_SLC1HOST_RX_EOF_INT_ENA1 : R/W ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_RX_EOF_INT_ENA1 (BIT(13)) +#define HOST_SLC1HOST_RX_EOF_INT_ENA1_M (BIT(13)) +#define HOST_SLC1HOST_RX_EOF_INT_ENA1_V 0x1 +#define HOST_SLC1HOST_RX_EOF_INT_ENA1_S 13 +/* HOST_SLC1HOST_RX_SOF_INT_ENA1 : R/W ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1HOST_RX_SOF_INT_ENA1 (BIT(12)) +#define HOST_SLC1HOST_RX_SOF_INT_ENA1_M (BIT(12)) +#define HOST_SLC1HOST_RX_SOF_INT_ENA1_V 0x1 +#define HOST_SLC1HOST_RX_SOF_INT_ENA1_S 12 +/* HOST_SLC1_TOKEN1_0TO1_INT_ENA1 : R/W ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN1_0TO1_INT_ENA1 (BIT(11)) +#define HOST_SLC1_TOKEN1_0TO1_INT_ENA1_M (BIT(11)) +#define HOST_SLC1_TOKEN1_0TO1_INT_ENA1_V 0x1 +#define HOST_SLC1_TOKEN1_0TO1_INT_ENA1_S 11 +/* HOST_SLC1_TOKEN0_0TO1_INT_ENA1 : R/W ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN0_0TO1_INT_ENA1 (BIT(10)) +#define HOST_SLC1_TOKEN0_0TO1_INT_ENA1_M (BIT(10)) +#define HOST_SLC1_TOKEN0_0TO1_INT_ENA1_V 0x1 +#define HOST_SLC1_TOKEN0_0TO1_INT_ENA1_S 10 +/* HOST_SLC1_TOKEN1_1TO0_INT_ENA1 : R/W ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN1_1TO0_INT_ENA1 (BIT(9)) +#define HOST_SLC1_TOKEN1_1TO0_INT_ENA1_M (BIT(9)) +#define HOST_SLC1_TOKEN1_1TO0_INT_ENA1_V 0x1 +#define HOST_SLC1_TOKEN1_1TO0_INT_ENA1_S 9 +/* HOST_SLC1_TOKEN0_1TO0_INT_ENA1 : R/W ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOKEN0_1TO0_INT_ENA1 (BIT(8)) +#define HOST_SLC1_TOKEN0_1TO0_INT_ENA1_M (BIT(8)) +#define HOST_SLC1_TOKEN0_1TO0_INT_ENA1_V 0x1 +#define HOST_SLC1_TOKEN0_1TO0_INT_ENA1_S 8 +/* HOST_SLC1_TOHOST_BIT7_INT_ENA1 : R/W ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT7_INT_ENA1 (BIT(7)) +#define HOST_SLC1_TOHOST_BIT7_INT_ENA1_M (BIT(7)) +#define HOST_SLC1_TOHOST_BIT7_INT_ENA1_V 0x1 +#define HOST_SLC1_TOHOST_BIT7_INT_ENA1_S 7 +/* HOST_SLC1_TOHOST_BIT6_INT_ENA1 : R/W ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT6_INT_ENA1 (BIT(6)) +#define HOST_SLC1_TOHOST_BIT6_INT_ENA1_M (BIT(6)) +#define HOST_SLC1_TOHOST_BIT6_INT_ENA1_V 0x1 +#define HOST_SLC1_TOHOST_BIT6_INT_ENA1_S 6 +/* HOST_SLC1_TOHOST_BIT5_INT_ENA1 : R/W ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT5_INT_ENA1 (BIT(5)) +#define HOST_SLC1_TOHOST_BIT5_INT_ENA1_M (BIT(5)) +#define HOST_SLC1_TOHOST_BIT5_INT_ENA1_V 0x1 +#define HOST_SLC1_TOHOST_BIT5_INT_ENA1_S 5 +/* HOST_SLC1_TOHOST_BIT4_INT_ENA1 : R/W ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT4_INT_ENA1 (BIT(4)) +#define HOST_SLC1_TOHOST_BIT4_INT_ENA1_M (BIT(4)) +#define HOST_SLC1_TOHOST_BIT4_INT_ENA1_V 0x1 +#define HOST_SLC1_TOHOST_BIT4_INT_ENA1_S 4 +/* HOST_SLC1_TOHOST_BIT3_INT_ENA1 : R/W ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT3_INT_ENA1 (BIT(3)) +#define HOST_SLC1_TOHOST_BIT3_INT_ENA1_M (BIT(3)) +#define HOST_SLC1_TOHOST_BIT3_INT_ENA1_V 0x1 +#define HOST_SLC1_TOHOST_BIT3_INT_ENA1_S 3 +/* HOST_SLC1_TOHOST_BIT2_INT_ENA1 : R/W ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT2_INT_ENA1 (BIT(2)) +#define HOST_SLC1_TOHOST_BIT2_INT_ENA1_M (BIT(2)) +#define HOST_SLC1_TOHOST_BIT2_INT_ENA1_V 0x1 +#define HOST_SLC1_TOHOST_BIT2_INT_ENA1_S 2 +/* HOST_SLC1_TOHOST_BIT1_INT_ENA1 : R/W ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT1_INT_ENA1 (BIT(1)) +#define HOST_SLC1_TOHOST_BIT1_INT_ENA1_M (BIT(1)) +#define HOST_SLC1_TOHOST_BIT1_INT_ENA1_V 0x1 +#define HOST_SLC1_TOHOST_BIT1_INT_ENA1_S 1 +/* HOST_SLC1_TOHOST_BIT0_INT_ENA1 : R/W ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SLC1_TOHOST_BIT0_INT_ENA1 (BIT(0)) +#define HOST_SLC1_TOHOST_BIT0_INT_ENA1_M (BIT(0)) +#define HOST_SLC1_TOHOST_BIT0_INT_ENA1_V 0x1 +#define HOST_SLC1_TOHOST_BIT0_INT_ENA1_S 0 + +#define HOST_SLCHOSTDATE_REG (DR_REG_SLCHOST_BASE + 0x178) +/* HOST_SLCHOST_DATE : R/W ;bitpos:[31:0] ;default: 32'h16022500 ; */ +/*description: */ +#define HOST_SLCHOST_DATE 0xFFFFFFFF +#define HOST_SLCHOST_DATE_M ((HOST_SLCHOST_DATE_V)<<(HOST_SLCHOST_DATE_S)) +#define HOST_SLCHOST_DATE_V 0xFFFFFFFF +#define HOST_SLCHOST_DATE_S 0 + +#define HOST_SLCHOSTID_REG (DR_REG_SLCHOST_BASE + 0x17C) +/* HOST_SLCHOST_ID : R/W ;bitpos:[31:0] ;default: 32'h0600 ; */ +/*description: */ +#define HOST_SLCHOST_ID 0xFFFFFFFF +#define HOST_SLCHOST_ID_M ((HOST_SLCHOST_ID_V)<<(HOST_SLCHOST_ID_S)) +#define HOST_SLCHOST_ID_V 0xFFFFFFFF +#define HOST_SLCHOST_ID_S 0 + +#define HOST_SLCHOST_CONF_REG (DR_REG_SLCHOST_BASE + 0x1F0) +/* HOST_HSPEED_CON_EN : R/W ;bitpos:[27] ;default: 1'b0 ; */ +/*description: */ +#define HOST_HSPEED_CON_EN (BIT(27)) +#define HOST_HSPEED_CON_EN_M (BIT(27)) +#define HOST_HSPEED_CON_EN_V 0x1 +#define HOST_HSPEED_CON_EN_S 27 +/* HOST_SDIO_PAD_PULLUP : R/W ;bitpos:[26] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SDIO_PAD_PULLUP (BIT(26)) +#define HOST_SDIO_PAD_PULLUP_M (BIT(26)) +#define HOST_SDIO_PAD_PULLUP_V 0x1 +#define HOST_SDIO_PAD_PULLUP_S 26 +/* HOST_SDIO20_INT_DELAY : R/W ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define HOST_SDIO20_INT_DELAY (BIT(25)) +#define HOST_SDIO20_INT_DELAY_M (BIT(25)) +#define HOST_SDIO20_INT_DELAY_V 0x1 +#define HOST_SDIO20_INT_DELAY_S 25 +/* HOST_FRC_QUICK_IN : R/W ;bitpos:[24:20] ;default: 5'b0 ; */ +/*description: */ +#define HOST_FRC_QUICK_IN 0x0000001F +#define HOST_FRC_QUICK_IN_M ((HOST_FRC_QUICK_IN_V)<<(HOST_FRC_QUICK_IN_S)) +#define HOST_FRC_QUICK_IN_V 0x1F +#define HOST_FRC_QUICK_IN_S 20 +/* HOST_FRC_POS_SAMP : R/W ;bitpos:[19:15] ;default: 5'b0 ; */ +/*description: */ +#define HOST_FRC_POS_SAMP 0x0000001F +#define HOST_FRC_POS_SAMP_M ((HOST_FRC_POS_SAMP_V)<<(HOST_FRC_POS_SAMP_S)) +#define HOST_FRC_POS_SAMP_V 0x1F +#define HOST_FRC_POS_SAMP_S 15 +/* HOST_FRC_NEG_SAMP : R/W ;bitpos:[14:10] ;default: 5'b0 ; */ +/*description: */ +#define HOST_FRC_NEG_SAMP 0x0000001F +#define HOST_FRC_NEG_SAMP_M ((HOST_FRC_NEG_SAMP_V)<<(HOST_FRC_NEG_SAMP_S)) +#define HOST_FRC_NEG_SAMP_V 0x1F +#define HOST_FRC_NEG_SAMP_S 10 +/* HOST_FRC_SDIO20 : R/W ;bitpos:[9:5] ;default: 5'b0 ; */ +/*description: */ +#define HOST_FRC_SDIO20 0x0000001F +#define HOST_FRC_SDIO20_M ((HOST_FRC_SDIO20_V)<<(HOST_FRC_SDIO20_S)) +#define HOST_FRC_SDIO20_V 0x1F +#define HOST_FRC_SDIO20_S 5 +/* HOST_FRC_SDIO11 : R/W ;bitpos:[4:0] ;default: 5'b0 ; */ +/*description: */ +#define HOST_FRC_SDIO11 0x0000001F +#define HOST_FRC_SDIO11_M ((HOST_FRC_SDIO11_V)<<(HOST_FRC_SDIO11_S)) +#define HOST_FRC_SDIO11_V 0x1F +#define HOST_FRC_SDIO11_S 0 + +#define HOST_SLCHOST_INF_ST_REG (DR_REG_SLCHOST_BASE + 0x1F4) +/* HOST_SDIO_QUICK_IN : RO ;bitpos:[14:10] ;default: 5'b0 ; */ +/*description: */ +#define HOST_SDIO_QUICK_IN 0x0000001F +#define HOST_SDIO_QUICK_IN_M ((HOST_SDIO_QUICK_IN_V)<<(HOST_SDIO_QUICK_IN_S)) +#define HOST_SDIO_QUICK_IN_V 0x1F +#define HOST_SDIO_QUICK_IN_S 10 +/* HOST_SDIO_NEG_SAMP : RO ;bitpos:[9:5] ;default: 5'b0 ; */ +/*description: */ +#define HOST_SDIO_NEG_SAMP 0x0000001F +#define HOST_SDIO_NEG_SAMP_M ((HOST_SDIO_NEG_SAMP_V)<<(HOST_SDIO_NEG_SAMP_S)) +#define HOST_SDIO_NEG_SAMP_V 0x1F +#define HOST_SDIO_NEG_SAMP_S 5 +/* HOST_SDIO20_MODE : RO ;bitpos:[4:0] ;default: 5'b0 ; */ +/*description: */ +#define HOST_SDIO20_MODE 0x0000001F +#define HOST_SDIO20_MODE_M ((HOST_SDIO20_MODE_V)<<(HOST_SDIO20_MODE_S)) +#define HOST_SDIO20_MODE_V 0x1F +#define HOST_SDIO20_MODE_S 0 + + + + +#endif /*_SOC_HOST_REG_H_ */ + + diff --git a/components/soc/esp32/include/soc/host_struct.h b/components/soc/esp32/include/soc/host_struct.h new file mode 100644 index 0000000000..a86c2982db --- /dev/null +++ b/components/soc/esp32/include/soc/host_struct.h @@ -0,0 +1,891 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_HOST_STRUCT_H_ +#define _SOC_HOST_STRUCT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef volatile struct { + uint32_t reserved_0; + uint32_t reserved_4; + uint32_t reserved_8; + uint32_t reserved_c; + union { + struct { + uint32_t reserved0: 24; + uint32_t func2_int: 1; + uint32_t reserved25: 7; + }; + uint32_t val; + } func2_0; + union { + struct { + uint32_t func2_int_en: 1; + uint32_t reserved1: 31; + }; + uint32_t val; + } func2_1; + uint32_t reserved_18; + uint32_t reserved_1c; + union { + struct { + uint32_t func1_mdstat: 1; + uint32_t reserved1: 31; + }; + uint32_t val; + } func2_2; + uint32_t reserved_24; + uint32_t reserved_28; + uint32_t reserved_2c; + uint32_t reserved_30; + uint32_t gpio_status0; /**/ + union { + struct { + uint32_t sdio_int1: 8; + uint32_t reserved8: 24; + }; + uint32_t val; + } gpio_status1; + uint32_t gpio_in0; /**/ + union { + struct { + uint32_t sdio_in1: 8; + uint32_t reserved8: 24; + }; + uint32_t val; + } gpio_in1; + union { + struct { + uint32_t token0: 12; + uint32_t rx_pf_valid: 1; + uint32_t reserved13: 3; + uint32_t reg_token1: 12; + uint32_t rx_pf_eof: 4; + }; + uint32_t val; + } slc0_token_rdata; + uint32_t slc0_pf; /**/ + uint32_t slc1_pf; /**/ + union { + struct { + uint32_t tohost_bit0: 1; + uint32_t tohost_bit1: 1; + uint32_t tohost_bit2: 1; + uint32_t tohost_bit3: 1; + uint32_t tohost_bit4: 1; + uint32_t tohost_bit5: 1; + uint32_t tohost_bit6: 1; + uint32_t tohost_bit7: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t token0_0to1: 1; + uint32_t token1_0to1: 1; + uint32_t rx_sof: 1; + uint32_t rx_eof: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t rx_pf_valid: 1; + uint32_t ext_bit0: 1; + uint32_t ext_bit1: 1; + uint32_t ext_bit2: 1; + uint32_t ext_bit3: 1; + uint32_t rx_new_packet: 1; + uint32_t rd_retry: 1; + uint32_t gpio_sdio: 1; + uint32_t reserved26: 6; + }; + uint32_t val; + } slc0_int_raw; + union { + struct { + uint32_t tohost_bit0: 1; + uint32_t tohost_bit1: 1; + uint32_t tohost_bit2: 1; + uint32_t tohost_bit3: 1; + uint32_t tohost_bit4: 1; + uint32_t tohost_bit5: 1; + uint32_t tohost_bit6: 1; + uint32_t tohost_bit7: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t token0_0to1: 1; + uint32_t token1_0to1: 1; + uint32_t rx_sof: 1; + uint32_t rx_eof: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t rx_pf_valid: 1; + uint32_t ext_bit0: 1; + uint32_t ext_bit1: 1; + uint32_t ext_bit2: 1; + uint32_t ext_bit3: 1; + uint32_t wifi_rx_new_packet: 1; + uint32_t rd_retry: 1; + uint32_t bt_rx_new_packet: 1; + uint32_t reserved26: 6; + }; + uint32_t val; + } slc1_int_raw; + union { + struct { + uint32_t tohost_bit0: 1; + uint32_t tohost_bit1: 1; + uint32_t tohost_bit2: 1; + uint32_t tohost_bit3: 1; + uint32_t tohost_bit4: 1; + uint32_t tohost_bit5: 1; + uint32_t tohost_bit6: 1; + uint32_t tohost_bit7: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t token0_0to1: 1; + uint32_t token1_0to1: 1; + uint32_t rx_sof: 1; + uint32_t rx_eof: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t rx_pf_valid: 1; + uint32_t ext_bit0: 1; + uint32_t ext_bit1: 1; + uint32_t ext_bit2: 1; + uint32_t ext_bit3: 1; + uint32_t rx_new_packet: 1; + uint32_t rd_retry: 1; + uint32_t gpio_sdio: 1; + uint32_t reserved26: 6; + }; + uint32_t val; + } slc0_int_st; + union { + struct { + uint32_t tohost_bit0: 1; + uint32_t tohost_bit1: 1; + uint32_t tohost_bit2: 1; + uint32_t tohost_bit3: 1; + uint32_t tohost_bit4: 1; + uint32_t tohost_bit5: 1; + uint32_t tohost_bit6: 1; + uint32_t tohost_bit7: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t token0_0to1: 1; + uint32_t token1_0to1: 1; + uint32_t rx_sof: 1; + uint32_t rx_eof: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t rx_pf_valid: 1; + uint32_t ext_bit0: 1; + uint32_t ext_bit1: 1; + uint32_t ext_bit2: 1; + uint32_t ext_bit3: 1; + uint32_t wifi_rx_new_packet: 1; + uint32_t rd_retry: 1; + uint32_t bt_rx_new_packet: 1; + uint32_t reserved26: 6; + }; + uint32_t val; + } slc1_int_st; + union { + struct { + uint32_t reg_slc0_len: 20; + uint32_t reg_slc0_len_check:12; + }; + uint32_t val; + } pkt_len; + union { + struct { + uint32_t state0: 8; + uint32_t state1: 8; + uint32_t state2: 8; + uint32_t state3: 8; + }; + uint32_t val; + } state_w0; + union { + struct { + uint32_t state4: 8; + uint32_t state5: 8; + uint32_t state6: 8; + uint32_t state7: 8; + }; + uint32_t val; + } state_w1; + union { + struct { + uint32_t conf0: 8; + uint32_t conf1: 8; + uint32_t conf2: 8; + uint32_t conf3: 8; + }; + uint32_t val; + } conf_w0; + union { + struct { + uint32_t conf4: 8; + uint32_t conf5: 8; + uint32_t conf6: 8; + uint32_t conf7: 8; + }; + uint32_t val; + } conf_w1; + union { + struct { + uint32_t conf8: 8; + uint32_t conf9: 8; + uint32_t conf10: 8; + uint32_t conf11: 8; + }; + uint32_t val; + } conf_w2; + union { + struct { + uint32_t conf12: 8; + uint32_t conf13: 8; + uint32_t conf14: 8; + uint32_t conf15: 8; + }; + uint32_t val; + } conf_w3; + union { + struct { + uint32_t conf16: 8; /*SLC timeout value*/ + uint32_t conf17: 8; /*SLC timeout enable*/ + uint32_t conf18: 8; + uint32_t conf19: 8; /*Interrupt to target CPU*/ + }; + uint32_t val; + } conf_w4; + union { + struct { + uint32_t conf20: 8; + uint32_t conf21: 8; + uint32_t conf22: 8; + uint32_t conf23: 8; + }; + uint32_t val; + } conf_w5; + uint32_t win_cmd; /**/ + union { + struct { + uint32_t conf24: 8; + uint32_t conf25: 8; + uint32_t conf26: 8; + uint32_t conf27: 8; + }; + uint32_t val; + } conf_w6; + union { + struct { + uint32_t conf28: 8; + uint32_t conf29: 8; + uint32_t conf30: 8; + uint32_t conf31: 8; + }; + uint32_t val; + } conf_w7; + union { + struct { + uint32_t reg_slc0_len0:20; + uint32_t reserved20: 12; + }; + uint32_t val; + } pkt_len0; + union { + struct { + uint32_t reg_slc0_len1:20; + uint32_t reserved20: 12; + }; + uint32_t val; + } pkt_len1; + union { + struct { + uint32_t reg_slc0_len2:20; + uint32_t reserved20: 12; + }; + uint32_t val; + } pkt_len2; + union { + struct { + uint32_t conf32: 8; + uint32_t conf33: 8; + uint32_t conf34: 8; + uint32_t conf35: 8; + }; + uint32_t val; + } conf_w8; + union { + struct { + uint32_t conf36: 8; + uint32_t conf37: 8; + uint32_t conf38: 8; + uint32_t conf39: 8; + }; + uint32_t val; + } conf_w9; + union { + struct { + uint32_t conf40: 8; + uint32_t conf41: 8; + uint32_t conf42: 8; + uint32_t conf43: 8; + }; + uint32_t val; + } conf_w10; + union { + struct { + uint32_t conf44: 8; + uint32_t conf45: 8; + uint32_t conf46: 8; + uint32_t conf47: 8; + }; + uint32_t val; + } conf_w11; + union { + struct { + uint32_t conf48: 8; + uint32_t conf49: 8; + uint32_t conf50: 8; + uint32_t conf51: 8; + }; + uint32_t val; + } conf_w12; + union { + struct { + uint32_t conf52: 8; + uint32_t conf53: 8; + uint32_t conf54: 8; + uint32_t conf55: 8; + }; + uint32_t val; + } conf_w13; + union { + struct { + uint32_t conf56: 8; + uint32_t conf57: 8; + uint32_t conf58: 8; + uint32_t conf59: 8; + }; + uint32_t val; + } conf_w14; + union { + struct { + uint32_t conf60: 8; + uint32_t conf61: 8; + uint32_t conf62: 8; + uint32_t conf63: 8; + }; + uint32_t val; + } conf_w15; + uint32_t check_sum0; /**/ + uint32_t check_sum1; /**/ + union { + struct { + uint32_t token0: 12; + uint32_t rx_pf_valid: 1; + uint32_t reserved13: 3; + uint32_t reg_token1: 12; + uint32_t rx_pf_eof: 4; + }; + uint32_t val; + } slc1_token_rdata; + union { + struct { + uint32_t token0_wd: 12; + uint32_t reserved12: 4; + uint32_t token1_wd: 12; + uint32_t reserved28: 4; + }; + uint32_t val; + } slc0_token_wdata; + union { + struct { + uint32_t token0_wd: 12; + uint32_t reserved12: 4; + uint32_t token1_wd: 12; + uint32_t reserved28: 4; + }; + uint32_t val; + } slc1_token_wdata; + union { + struct { + uint32_t slc0_token0_dec: 1; + uint32_t slc0_token1_dec: 1; + uint32_t slc0_token0_wr: 1; + uint32_t slc0_token1_wr: 1; + uint32_t slc1_token0_dec: 1; + uint32_t slc1_token1_dec: 1; + uint32_t slc1_token0_wr: 1; + uint32_t slc1_token1_wr: 1; + uint32_t slc0_len_wr: 1; + uint32_t reserved9: 23; + }; + uint32_t val; + } token_con; + union { + struct { + uint32_t tohost_bit0: 1; + uint32_t tohost_bit1: 1; + uint32_t tohost_bit2: 1; + uint32_t tohost_bit3: 1; + uint32_t tohost_bit4: 1; + uint32_t tohost_bit5: 1; + uint32_t tohost_bit6: 1; + uint32_t tohost_bit7: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t token0_0to1: 1; + uint32_t token1_0to1: 1; + uint32_t rx_sof: 1; + uint32_t rx_eof: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t rx_pf_valid: 1; + uint32_t ext_bit0: 1; + uint32_t ext_bit1: 1; + uint32_t ext_bit2: 1; + uint32_t ext_bit3: 1; + uint32_t rx_new_packet: 1; + uint32_t rd_retry: 1; + uint32_t gpio_sdio: 1; + uint32_t reserved26: 6; + }; + uint32_t val; + } slc0_int_clr; + union { + struct { + uint32_t tohost_bit0: 1; + uint32_t tohost_bit1: 1; + uint32_t tohost_bit2: 1; + uint32_t tohost_bit3: 1; + uint32_t tohost_bit4: 1; + uint32_t tohost_bit5: 1; + uint32_t tohost_bit6: 1; + uint32_t tohost_bit7: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t token0_0to1: 1; + uint32_t token1_0to1: 1; + uint32_t rx_sof: 1; + uint32_t rx_eof: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t rx_pf_valid: 1; + uint32_t ext_bit0: 1; + uint32_t ext_bit1: 1; + uint32_t ext_bit2: 1; + uint32_t ext_bit3: 1; + uint32_t wifi_rx_new_packet: 1; + uint32_t rd_retry: 1; + uint32_t bt_rx_new_packet: 1; + uint32_t reserved26: 6; + }; + uint32_t val; + } slc1_int_clr; + union { + struct { + uint32_t tohost_bit0: 1; + uint32_t tohost_bit1: 1; + uint32_t tohost_bit2: 1; + uint32_t tohost_bit3: 1; + uint32_t tohost_bit4: 1; + uint32_t tohost_bit5: 1; + uint32_t tohost_bit6: 1; + uint32_t tohost_bit7: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t token0_0to1: 1; + uint32_t token1_0to1: 1; + uint32_t rx_sof: 1; + uint32_t rx_eof: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t rx_pf_valid: 1; + uint32_t ext_bit0: 1; + uint32_t ext_bit1: 1; + uint32_t ext_bit2: 1; + uint32_t ext_bit3: 1; + uint32_t rx_new_packet: 1; + uint32_t rd_retry: 1; + uint32_t gpio_sdio: 1; + uint32_t reserved26: 6; + }; + uint32_t val; + } slc0_func1_int_ena; + union { + struct { + uint32_t tohost_bit0: 1; + uint32_t tohost_bit1: 1; + uint32_t tohost_bit2: 1; + uint32_t tohost_bit3: 1; + uint32_t tohost_bit4: 1; + uint32_t tohost_bit5: 1; + uint32_t tohost_bit6: 1; + uint32_t tohost_bit7: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t token0_0to1: 1; + uint32_t token1_0to1: 1; + uint32_t rx_sof: 1; + uint32_t rx_eof: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t rx_pf_valid: 1; + uint32_t ext_bit0: 1; + uint32_t ext_bit1: 1; + uint32_t ext_bit2: 1; + uint32_t ext_bit3: 1; + uint32_t wifi_rx_new_packet: 1; + uint32_t rd_retry: 1; + uint32_t bt_rx_new_packet: 1; + uint32_t reserved26: 6; + }; + uint32_t val; + } slc1_func1_int_ena; + union { + struct { + uint32_t tohost_bit0: 1; + uint32_t tohost_bit1: 1; + uint32_t tohost_bit2: 1; + uint32_t tohost_bit3: 1; + uint32_t tohost_bit4: 1; + uint32_t tohost_bit5: 1; + uint32_t tohost_bit6: 1; + uint32_t tohost_bit7: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t token0_0to1: 1; + uint32_t token1_0to1: 1; + uint32_t rx_sof: 1; + uint32_t rx_eof: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t rx_pf_valid: 1; + uint32_t ext_bit0: 1; + uint32_t ext_bit1: 1; + uint32_t ext_bit2: 1; + uint32_t ext_bit3: 1; + uint32_t rx_new_packet: 1; + uint32_t rd_retry: 1; + uint32_t gpio_sdio: 1; + uint32_t reserved26: 6; + }; + uint32_t val; + } slc0_func2_int_ena; + union { + struct { + uint32_t tohost_bit0: 1; + uint32_t tohost_bit1: 1; + uint32_t tohost_bit2: 1; + uint32_t tohost_bit3: 1; + uint32_t tohost_bit4: 1; + uint32_t tohost_bit5: 1; + uint32_t tohost_bit6: 1; + uint32_t tohost_bit7: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t token0_0to1: 1; + uint32_t token1_0to1: 1; + uint32_t rx_sof: 1; + uint32_t rx_eof: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t rx_pf_valid: 1; + uint32_t ext_bit0: 1; + uint32_t ext_bit1: 1; + uint32_t ext_bit2: 1; + uint32_t ext_bit3: 1; + uint32_t wifi_rx_new_packet: 1; + uint32_t rd_retry: 1; + uint32_t bt_rx_new_packet: 1; + uint32_t reserved26: 6; + }; + uint32_t val; + } slc1_func2_int_ena; + union { + struct { + uint32_t tohost_bit0: 1; + uint32_t tohost_bit1: 1; + uint32_t tohost_bit2: 1; + uint32_t tohost_bit3: 1; + uint32_t tohost_bit4: 1; + uint32_t tohost_bit5: 1; + uint32_t tohost_bit6: 1; + uint32_t tohost_bit7: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t token0_0to1: 1; + uint32_t token1_0to1: 1; + uint32_t rx_sof: 1; + uint32_t rx_eof: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t rx_pf_valid: 1; + uint32_t ext_bit0: 1; + uint32_t ext_bit1: 1; + uint32_t ext_bit2: 1; + uint32_t ext_bit3: 1; + uint32_t rx_new_packet: 1; + uint32_t rd_retry: 1; + uint32_t gpio_sdio: 1; + uint32_t reserved26: 6; + }; + uint32_t val; + } slc0_int_ena; + union { + struct { + uint32_t tohost_bit0: 1; + uint32_t tohost_bit1: 1; + uint32_t tohost_bit2: 1; + uint32_t tohost_bit3: 1; + uint32_t tohost_bit4: 1; + uint32_t tohost_bit5: 1; + uint32_t tohost_bit6: 1; + uint32_t tohost_bit7: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t token0_0to1: 1; + uint32_t token1_0to1: 1; + uint32_t rx_sof: 1; + uint32_t rx_eof: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t rx_pf_valid: 1; + uint32_t ext_bit0: 1; + uint32_t ext_bit1: 1; + uint32_t ext_bit2: 1; + uint32_t ext_bit3: 1; + uint32_t wifi_rx_new_packet: 1; + uint32_t rd_retry: 1; + uint32_t bt_rx_new_packet: 1; + uint32_t reserved26: 6; + }; + uint32_t val; + } slc1_int_ena; + union { + struct { + uint32_t infor: 20; + uint32_t reserved20: 12; + }; + uint32_t val; + } slc0_rx_infor; + union { + struct { + uint32_t infor: 20; + uint32_t reserved20: 12; + }; + uint32_t val; + } slc1_rx_infor; + uint32_t slc0_len_wd; /**/ + uint32_t apbwin_wdata; /**/ + union { + struct { + uint32_t addr: 28; + uint32_t wr: 1; + uint32_t start: 1; + uint32_t reserved30: 2; + }; + uint32_t val; + } apbwin_conf; + uint32_t apbwin_rdata; /**/ + union { + struct { + uint32_t bit7_clraddr: 9; + uint32_t bit6_clraddr: 9; + uint32_t reserved18: 14; + }; + uint32_t val; + } slc0_rdclr; + union { + struct { + uint32_t bit7_clraddr: 9; + uint32_t bit6_clraddr: 9; + uint32_t reserved18: 14; + }; + uint32_t val; + } slc1_rdclr; + union { + struct { + uint32_t tohost_bit01: 1; + uint32_t tohost_bit11: 1; + uint32_t tohost_bit21: 1; + uint32_t tohost_bit31: 1; + uint32_t tohost_bit41: 1; + uint32_t tohost_bit51: 1; + uint32_t tohost_bit61: 1; + uint32_t tohost_bit71: 1; + uint32_t token0_1to01: 1; + uint32_t token1_1to01: 1; + uint32_t token0_0to11: 1; + uint32_t token1_0to11: 1; + uint32_t rx_sof1: 1; + uint32_t rx_eof1: 1; + uint32_t rx_start1: 1; + uint32_t tx_start1: 1; + uint32_t rx_udf1: 1; + uint32_t tx_ovf1: 1; + uint32_t rx_pf_valid1: 1; + uint32_t ext_bit01: 1; + uint32_t ext_bit11: 1; + uint32_t ext_bit21: 1; + uint32_t ext_bit31: 1; + uint32_t rx_new_packet1: 1; + uint32_t rd_retry1: 1; + uint32_t gpio_sdio1: 1; + uint32_t reserved26: 6; + }; + uint32_t val; + } slc0_int_ena1; + union { + struct { + uint32_t tohost_bit01: 1; + uint32_t tohost_bit11: 1; + uint32_t tohost_bit21: 1; + uint32_t tohost_bit31: 1; + uint32_t tohost_bit41: 1; + uint32_t tohost_bit51: 1; + uint32_t tohost_bit61: 1; + uint32_t tohost_bit71: 1; + uint32_t token0_1to01: 1; + uint32_t token1_1to01: 1; + uint32_t token0_0to11: 1; + uint32_t token1_0to11: 1; + uint32_t rx_sof1: 1; + uint32_t rx_eof1: 1; + uint32_t rx_start1: 1; + uint32_t tx_start1: 1; + uint32_t rx_udf1: 1; + uint32_t tx_ovf1: 1; + uint32_t rx_pf_valid1: 1; + uint32_t ext_bit01: 1; + uint32_t ext_bit11: 1; + uint32_t ext_bit21: 1; + uint32_t ext_bit31: 1; + uint32_t wifi_rx_new_packet1: 1; + uint32_t rd_retry1: 1; + uint32_t bt_rx_new_packet1: 1; + uint32_t reserved26: 6; + }; + uint32_t val; + } slc1_int_ena1; + uint32_t reserved_11c; + uint32_t reserved_120; + uint32_t reserved_124; + uint32_t reserved_128; + uint32_t reserved_12c; + uint32_t reserved_130; + uint32_t reserved_134; + uint32_t reserved_138; + uint32_t reserved_13c; + uint32_t reserved_140; + uint32_t reserved_144; + uint32_t reserved_148; + uint32_t reserved_14c; + uint32_t reserved_150; + uint32_t reserved_154; + uint32_t reserved_158; + uint32_t reserved_15c; + uint32_t reserved_160; + uint32_t reserved_164; + uint32_t reserved_168; + uint32_t reserved_16c; + uint32_t reserved_170; + uint32_t reserved_174; + uint32_t date; /**/ + uint32_t id; /**/ + uint32_t reserved_180; + uint32_t reserved_184; + uint32_t reserved_188; + uint32_t reserved_18c; + uint32_t reserved_190; + uint32_t reserved_194; + uint32_t reserved_198; + uint32_t reserved_19c; + uint32_t reserved_1a0; + uint32_t reserved_1a4; + uint32_t reserved_1a8; + uint32_t reserved_1ac; + uint32_t reserved_1b0; + uint32_t reserved_1b4; + uint32_t reserved_1b8; + uint32_t reserved_1bc; + uint32_t reserved_1c0; + uint32_t reserved_1c4; + uint32_t reserved_1c8; + uint32_t reserved_1cc; + uint32_t reserved_1d0; + uint32_t reserved_1d4; + uint32_t reserved_1d8; + uint32_t reserved_1dc; + uint32_t reserved_1e0; + uint32_t reserved_1e4; + uint32_t reserved_1e8; + uint32_t reserved_1ec; + union { + struct { + uint32_t frc_sdio11: 5; + uint32_t frc_sdio20: 5; + uint32_t frc_neg_samp: 5; + uint32_t frc_pos_samp: 5; + uint32_t frc_quick_in: 5; + uint32_t sdio20_int_delay: 1; + uint32_t sdio_pad_pullup: 1; + uint32_t hspeed_con_en: 1; + uint32_t reserved28: 4; + }; + uint32_t val; + } conf; + union { + struct { + uint32_t sdio20_mode: 5; + uint32_t sdio_neg_samp: 5; + uint32_t sdio_quick_in: 5; + uint32_t reserved15: 17; + }; + uint32_t val; + } inf_st; +} host_dev_t; +extern host_dev_t HOST; + +#ifdef __cplusplus +} +#endif + +#endif /* _SOC_HOST_STRUCT_H_ */ diff --git a/components/soc/esp32/include/soc/slc_reg.h b/components/soc/esp32/include/soc/slc_reg.h new file mode 100644 index 0000000000..3d4541cccb --- /dev/null +++ b/components/soc/esp32/include/soc/slc_reg.h @@ -0,0 +1,3244 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_SLC_REG_H_ +#define _SOC_SLC_REG_H_ + + +#include "soc.h" +#define SLC_CONF0_REG (DR_REG_SLC_BASE + 0x0) +/* SLC_SLC1_TOKEN_SEL : R/W ;bitpos:[31] ;default: 1'h1 ; */ +/*description: */ +#define SLC_SLC1_TOKEN_SEL (BIT(31)) +#define SLC_SLC1_TOKEN_SEL_M (BIT(31)) +#define SLC_SLC1_TOKEN_SEL_V 0x1 +#define SLC_SLC1_TOKEN_SEL_S 31 +/* SLC_SLC1_TOKEN_AUTO_CLR : R/W ;bitpos:[30] ;default: 1'h1 ; */ +/*description: */ +#define SLC_SLC1_TOKEN_AUTO_CLR (BIT(30)) +#define SLC_SLC1_TOKEN_AUTO_CLR_M (BIT(30)) +#define SLC_SLC1_TOKEN_AUTO_CLR_V 0x1 +#define SLC_SLC1_TOKEN_AUTO_CLR_S 30 +/* SLC_SLC1_TXDATA_BURST_EN : R/W ;bitpos:[29] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_TXDATA_BURST_EN (BIT(29)) +#define SLC_SLC1_TXDATA_BURST_EN_M (BIT(29)) +#define SLC_SLC1_TXDATA_BURST_EN_V 0x1 +#define SLC_SLC1_TXDATA_BURST_EN_S 29 +/* SLC_SLC1_TXDSCR_BURST_EN : R/W ;bitpos:[28] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_TXDSCR_BURST_EN (BIT(28)) +#define SLC_SLC1_TXDSCR_BURST_EN_M (BIT(28)) +#define SLC_SLC1_TXDSCR_BURST_EN_V 0x1 +#define SLC_SLC1_TXDSCR_BURST_EN_S 28 +/* SLC_SLC1_TXLINK_AUTO_RET : R/W ;bitpos:[27] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_TXLINK_AUTO_RET (BIT(27)) +#define SLC_SLC1_TXLINK_AUTO_RET_M (BIT(27)) +#define SLC_SLC1_TXLINK_AUTO_RET_V 0x1 +#define SLC_SLC1_TXLINK_AUTO_RET_S 27 +/* SLC_SLC1_RXLINK_AUTO_RET : R/W ;bitpos:[26] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_RXLINK_AUTO_RET (BIT(26)) +#define SLC_SLC1_RXLINK_AUTO_RET_M (BIT(26)) +#define SLC_SLC1_RXLINK_AUTO_RET_V 0x1 +#define SLC_SLC1_RXLINK_AUTO_RET_S 26 +/* SLC_SLC1_RXDATA_BURST_EN : R/W ;bitpos:[25] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_RXDATA_BURST_EN (BIT(25)) +#define SLC_SLC1_RXDATA_BURST_EN_M (BIT(25)) +#define SLC_SLC1_RXDATA_BURST_EN_V 0x1 +#define SLC_SLC1_RXDATA_BURST_EN_S 25 +/* SLC_SLC1_RXDSCR_BURST_EN : R/W ;bitpos:[24] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_RXDSCR_BURST_EN (BIT(24)) +#define SLC_SLC1_RXDSCR_BURST_EN_M (BIT(24)) +#define SLC_SLC1_RXDSCR_BURST_EN_V 0x1 +#define SLC_SLC1_RXDSCR_BURST_EN_S 24 +/* SLC_SLC1_RX_NO_RESTART_CLR : R/W ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_NO_RESTART_CLR (BIT(23)) +#define SLC_SLC1_RX_NO_RESTART_CLR_M (BIT(23)) +#define SLC_SLC1_RX_NO_RESTART_CLR_V 0x1 +#define SLC_SLC1_RX_NO_RESTART_CLR_S 23 +/* SLC_SLC1_RX_AUTO_WRBACK : R/W ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_AUTO_WRBACK (BIT(22)) +#define SLC_SLC1_RX_AUTO_WRBACK_M (BIT(22)) +#define SLC_SLC1_RX_AUTO_WRBACK_V 0x1 +#define SLC_SLC1_RX_AUTO_WRBACK_S 22 +/* SLC_SLC1_RX_LOOP_TEST : R/W ;bitpos:[21] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_RX_LOOP_TEST (BIT(21)) +#define SLC_SLC1_RX_LOOP_TEST_M (BIT(21)) +#define SLC_SLC1_RX_LOOP_TEST_V 0x1 +#define SLC_SLC1_RX_LOOP_TEST_S 21 +/* SLC_SLC1_TX_LOOP_TEST : R/W ;bitpos:[20] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_TX_LOOP_TEST (BIT(20)) +#define SLC_SLC1_TX_LOOP_TEST_M (BIT(20)) +#define SLC_SLC1_TX_LOOP_TEST_V 0x1 +#define SLC_SLC1_TX_LOOP_TEST_S 20 +/* SLC_SLC1_WR_RETRY_MASK_EN : R/W ;bitpos:[19] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_WR_RETRY_MASK_EN (BIT(19)) +#define SLC_SLC1_WR_RETRY_MASK_EN_M (BIT(19)) +#define SLC_SLC1_WR_RETRY_MASK_EN_V 0x1 +#define SLC_SLC1_WR_RETRY_MASK_EN_S 19 +/* SLC_SLC0_WR_RETRY_MASK_EN : R/W ;bitpos:[18] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC0_WR_RETRY_MASK_EN (BIT(18)) +#define SLC_SLC0_WR_RETRY_MASK_EN_M (BIT(18)) +#define SLC_SLC0_WR_RETRY_MASK_EN_V 0x1 +#define SLC_SLC0_WR_RETRY_MASK_EN_S 18 +/* SLC_SLC1_RX_RST : R/W ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_RST (BIT(17)) +#define SLC_SLC1_RX_RST_M (BIT(17)) +#define SLC_SLC1_RX_RST_V 0x1 +#define SLC_SLC1_RX_RST_S 17 +/* SLC_SLC1_TX_RST : R/W ;bitpos:[16] ;default: 1'h0 ; */ +/*description: */ +#define SLC_SLC1_TX_RST (BIT(16)) +#define SLC_SLC1_TX_RST_M (BIT(16)) +#define SLC_SLC1_TX_RST_V 0x1 +#define SLC_SLC1_TX_RST_S 16 +/* SLC_SLC0_TOKEN_SEL : R/W ;bitpos:[15] ;default: 1'h1 ; */ +/*description: */ +#define SLC_SLC0_TOKEN_SEL (BIT(15)) +#define SLC_SLC0_TOKEN_SEL_M (BIT(15)) +#define SLC_SLC0_TOKEN_SEL_V 0x1 +#define SLC_SLC0_TOKEN_SEL_S 15 +/* SLC_SLC0_TOKEN_AUTO_CLR : R/W ;bitpos:[14] ;default: 1'h1 ; */ +/*description: */ +#define SLC_SLC0_TOKEN_AUTO_CLR (BIT(14)) +#define SLC_SLC0_TOKEN_AUTO_CLR_M (BIT(14)) +#define SLC_SLC0_TOKEN_AUTO_CLR_V 0x1 +#define SLC_SLC0_TOKEN_AUTO_CLR_S 14 +/* SLC_SLC0_TXDATA_BURST_EN : R/W ;bitpos:[13] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC0_TXDATA_BURST_EN (BIT(13)) +#define SLC_SLC0_TXDATA_BURST_EN_M (BIT(13)) +#define SLC_SLC0_TXDATA_BURST_EN_V 0x1 +#define SLC_SLC0_TXDATA_BURST_EN_S 13 +/* SLC_SLC0_TXDSCR_BURST_EN : R/W ;bitpos:[12] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC0_TXDSCR_BURST_EN (BIT(12)) +#define SLC_SLC0_TXDSCR_BURST_EN_M (BIT(12)) +#define SLC_SLC0_TXDSCR_BURST_EN_V 0x1 +#define SLC_SLC0_TXDSCR_BURST_EN_S 12 +/* SLC_SLC0_TXLINK_AUTO_RET : R/W ;bitpos:[11] ;default: 1'h1 ; */ +/*description: */ +#define SLC_SLC0_TXLINK_AUTO_RET (BIT(11)) +#define SLC_SLC0_TXLINK_AUTO_RET_M (BIT(11)) +#define SLC_SLC0_TXLINK_AUTO_RET_V 0x1 +#define SLC_SLC0_TXLINK_AUTO_RET_S 11 +/* SLC_SLC0_RXLINK_AUTO_RET : R/W ;bitpos:[10] ;default: 1'h1 ; */ +/*description: */ +#define SLC_SLC0_RXLINK_AUTO_RET (BIT(10)) +#define SLC_SLC0_RXLINK_AUTO_RET_M (BIT(10)) +#define SLC_SLC0_RXLINK_AUTO_RET_V 0x1 +#define SLC_SLC0_RXLINK_AUTO_RET_S 10 +/* SLC_SLC0_RXDATA_BURST_EN : R/W ;bitpos:[9] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC0_RXDATA_BURST_EN (BIT(9)) +#define SLC_SLC0_RXDATA_BURST_EN_M (BIT(9)) +#define SLC_SLC0_RXDATA_BURST_EN_V 0x1 +#define SLC_SLC0_RXDATA_BURST_EN_S 9 +/* SLC_SLC0_RXDSCR_BURST_EN : R/W ;bitpos:[8] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC0_RXDSCR_BURST_EN (BIT(8)) +#define SLC_SLC0_RXDSCR_BURST_EN_M (BIT(8)) +#define SLC_SLC0_RXDSCR_BURST_EN_V 0x1 +#define SLC_SLC0_RXDSCR_BURST_EN_S 8 +/* SLC_SLC0_RX_NO_RESTART_CLR : R/W ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_NO_RESTART_CLR (BIT(7)) +#define SLC_SLC0_RX_NO_RESTART_CLR_M (BIT(7)) +#define SLC_SLC0_RX_NO_RESTART_CLR_V 0x1 +#define SLC_SLC0_RX_NO_RESTART_CLR_S 7 +/* SLC_SLC0_RX_AUTO_WRBACK : R/W ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_AUTO_WRBACK (BIT(6)) +#define SLC_SLC0_RX_AUTO_WRBACK_M (BIT(6)) +#define SLC_SLC0_RX_AUTO_WRBACK_V 0x1 +#define SLC_SLC0_RX_AUTO_WRBACK_S 6 +/* SLC_SLC0_RX_LOOP_TEST : R/W ;bitpos:[5] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC0_RX_LOOP_TEST (BIT(5)) +#define SLC_SLC0_RX_LOOP_TEST_M (BIT(5)) +#define SLC_SLC0_RX_LOOP_TEST_V 0x1 +#define SLC_SLC0_RX_LOOP_TEST_S 5 +/* SLC_SLC0_TX_LOOP_TEST : R/W ;bitpos:[4] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC0_TX_LOOP_TEST (BIT(4)) +#define SLC_SLC0_TX_LOOP_TEST_M (BIT(4)) +#define SLC_SLC0_TX_LOOP_TEST_V 0x1 +#define SLC_SLC0_TX_LOOP_TEST_S 4 +/* SLC_AHBM_RST : R/W ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define SLC_AHBM_RST (BIT(3)) +#define SLC_AHBM_RST_M (BIT(3)) +#define SLC_AHBM_RST_V 0x1 +#define SLC_AHBM_RST_S 3 +/* SLC_AHBM_FIFO_RST : R/W ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define SLC_AHBM_FIFO_RST (BIT(2)) +#define SLC_AHBM_FIFO_RST_M (BIT(2)) +#define SLC_AHBM_FIFO_RST_V 0x1 +#define SLC_AHBM_FIFO_RST_S 2 +/* SLC_SLC0_RX_RST : R/W ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_RST (BIT(1)) +#define SLC_SLC0_RX_RST_M (BIT(1)) +#define SLC_SLC0_RX_RST_V 0x1 +#define SLC_SLC0_RX_RST_S 1 +/* SLC_SLC0_TX_RST : R/W ;bitpos:[0] ;default: 1'h0 ; */ +/*description: */ +#define SLC_SLC0_TX_RST (BIT(0)) +#define SLC_SLC0_TX_RST_M (BIT(0)) +#define SLC_SLC0_TX_RST_V 0x1 +#define SLC_SLC0_TX_RST_S 0 + +#define SLC_0INT_RAW_REG (DR_REG_SLC_BASE + 0x4) +/* SLC_SLC0_RX_QUICK_EOF_INT_RAW : RO ;bitpos:[26] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_QUICK_EOF_INT_RAW (BIT(26)) +#define SLC_SLC0_RX_QUICK_EOF_INT_RAW_M (BIT(26)) +#define SLC_SLC0_RX_QUICK_EOF_INT_RAW_V 0x1 +#define SLC_SLC0_RX_QUICK_EOF_INT_RAW_S 26 +/* SLC_CMD_DTC_INT_RAW : RO ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define SLC_CMD_DTC_INT_RAW (BIT(25)) +#define SLC_CMD_DTC_INT_RAW_M (BIT(25)) +#define SLC_CMD_DTC_INT_RAW_V 0x1 +#define SLC_CMD_DTC_INT_RAW_S 25 +/* SLC_SLC0_TX_ERR_EOF_INT_RAW : RO ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_ERR_EOF_INT_RAW (BIT(24)) +#define SLC_SLC0_TX_ERR_EOF_INT_RAW_M (BIT(24)) +#define SLC_SLC0_TX_ERR_EOF_INT_RAW_V 0x1 +#define SLC_SLC0_TX_ERR_EOF_INT_RAW_S 24 +/* SLC_SLC0_WR_RETRY_DONE_INT_RAW : RO ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_WR_RETRY_DONE_INT_RAW (BIT(23)) +#define SLC_SLC0_WR_RETRY_DONE_INT_RAW_M (BIT(23)) +#define SLC_SLC0_WR_RETRY_DONE_INT_RAW_V 0x1 +#define SLC_SLC0_WR_RETRY_DONE_INT_RAW_S 23 +/* SLC_SLC0_HOST_RD_ACK_INT_RAW : RO ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_HOST_RD_ACK_INT_RAW (BIT(22)) +#define SLC_SLC0_HOST_RD_ACK_INT_RAW_M (BIT(22)) +#define SLC_SLC0_HOST_RD_ACK_INT_RAW_V 0x1 +#define SLC_SLC0_HOST_RD_ACK_INT_RAW_S 22 +/* SLC_SLC0_TX_DSCR_EMPTY_INT_RAW : RO ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DSCR_EMPTY_INT_RAW (BIT(21)) +#define SLC_SLC0_TX_DSCR_EMPTY_INT_RAW_M (BIT(21)) +#define SLC_SLC0_TX_DSCR_EMPTY_INT_RAW_V 0x1 +#define SLC_SLC0_TX_DSCR_EMPTY_INT_RAW_S 21 +/* SLC_SLC0_RX_DSCR_ERR_INT_RAW : RO ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_DSCR_ERR_INT_RAW (BIT(20)) +#define SLC_SLC0_RX_DSCR_ERR_INT_RAW_M (BIT(20)) +#define SLC_SLC0_RX_DSCR_ERR_INT_RAW_V 0x1 +#define SLC_SLC0_RX_DSCR_ERR_INT_RAW_S 20 +/* SLC_SLC0_TX_DSCR_ERR_INT_RAW : RO ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DSCR_ERR_INT_RAW (BIT(19)) +#define SLC_SLC0_TX_DSCR_ERR_INT_RAW_M (BIT(19)) +#define SLC_SLC0_TX_DSCR_ERR_INT_RAW_V 0x1 +#define SLC_SLC0_TX_DSCR_ERR_INT_RAW_S 19 +/* SLC_SLC0_TOHOST_INT_RAW : RO ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOHOST_INT_RAW (BIT(18)) +#define SLC_SLC0_TOHOST_INT_RAW_M (BIT(18)) +#define SLC_SLC0_TOHOST_INT_RAW_V 0x1 +#define SLC_SLC0_TOHOST_INT_RAW_S 18 +/* SLC_SLC0_RX_EOF_INT_RAW : RO ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_EOF_INT_RAW (BIT(17)) +#define SLC_SLC0_RX_EOF_INT_RAW_M (BIT(17)) +#define SLC_SLC0_RX_EOF_INT_RAW_V 0x1 +#define SLC_SLC0_RX_EOF_INT_RAW_S 17 +/* SLC_SLC0_RX_DONE_INT_RAW : RO ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_DONE_INT_RAW (BIT(16)) +#define SLC_SLC0_RX_DONE_INT_RAW_M (BIT(16)) +#define SLC_SLC0_RX_DONE_INT_RAW_V 0x1 +#define SLC_SLC0_RX_DONE_INT_RAW_S 16 +/* SLC_SLC0_TX_SUC_EOF_INT_RAW : RO ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_SUC_EOF_INT_RAW (BIT(15)) +#define SLC_SLC0_TX_SUC_EOF_INT_RAW_M (BIT(15)) +#define SLC_SLC0_TX_SUC_EOF_INT_RAW_V 0x1 +#define SLC_SLC0_TX_SUC_EOF_INT_RAW_S 15 +/* SLC_SLC0_TX_DONE_INT_RAW : RO ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DONE_INT_RAW (BIT(14)) +#define SLC_SLC0_TX_DONE_INT_RAW_M (BIT(14)) +#define SLC_SLC0_TX_DONE_INT_RAW_V 0x1 +#define SLC_SLC0_TX_DONE_INT_RAW_S 14 +/* SLC_SLC0_TOKEN1_1TO0_INT_RAW : RO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN1_1TO0_INT_RAW (BIT(13)) +#define SLC_SLC0_TOKEN1_1TO0_INT_RAW_M (BIT(13)) +#define SLC_SLC0_TOKEN1_1TO0_INT_RAW_V 0x1 +#define SLC_SLC0_TOKEN1_1TO0_INT_RAW_S 13 +/* SLC_SLC0_TOKEN0_1TO0_INT_RAW : RO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN0_1TO0_INT_RAW (BIT(12)) +#define SLC_SLC0_TOKEN0_1TO0_INT_RAW_M (BIT(12)) +#define SLC_SLC0_TOKEN0_1TO0_INT_RAW_V 0x1 +#define SLC_SLC0_TOKEN0_1TO0_INT_RAW_S 12 +/* SLC_SLC0_TX_OVF_INT_RAW : RO ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_OVF_INT_RAW (BIT(11)) +#define SLC_SLC0_TX_OVF_INT_RAW_M (BIT(11)) +#define SLC_SLC0_TX_OVF_INT_RAW_V 0x1 +#define SLC_SLC0_TX_OVF_INT_RAW_S 11 +/* SLC_SLC0_RX_UDF_INT_RAW : RO ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_UDF_INT_RAW (BIT(10)) +#define SLC_SLC0_RX_UDF_INT_RAW_M (BIT(10)) +#define SLC_SLC0_RX_UDF_INT_RAW_V 0x1 +#define SLC_SLC0_RX_UDF_INT_RAW_S 10 +/* SLC_SLC0_TX_START_INT_RAW : RO ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_START_INT_RAW (BIT(9)) +#define SLC_SLC0_TX_START_INT_RAW_M (BIT(9)) +#define SLC_SLC0_TX_START_INT_RAW_V 0x1 +#define SLC_SLC0_TX_START_INT_RAW_S 9 +/* SLC_SLC0_RX_START_INT_RAW : RO ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_START_INT_RAW (BIT(8)) +#define SLC_SLC0_RX_START_INT_RAW_M (BIT(8)) +#define SLC_SLC0_RX_START_INT_RAW_V 0x1 +#define SLC_SLC0_RX_START_INT_RAW_S 8 +/* SLC_FRHOST_BIT7_INT_RAW : RO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT7_INT_RAW (BIT(7)) +#define SLC_FRHOST_BIT7_INT_RAW_M (BIT(7)) +#define SLC_FRHOST_BIT7_INT_RAW_V 0x1 +#define SLC_FRHOST_BIT7_INT_RAW_S 7 +/* SLC_FRHOST_BIT6_INT_RAW : RO ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT6_INT_RAW (BIT(6)) +#define SLC_FRHOST_BIT6_INT_RAW_M (BIT(6)) +#define SLC_FRHOST_BIT6_INT_RAW_V 0x1 +#define SLC_FRHOST_BIT6_INT_RAW_S 6 +/* SLC_FRHOST_BIT5_INT_RAW : RO ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT5_INT_RAW (BIT(5)) +#define SLC_FRHOST_BIT5_INT_RAW_M (BIT(5)) +#define SLC_FRHOST_BIT5_INT_RAW_V 0x1 +#define SLC_FRHOST_BIT5_INT_RAW_S 5 +/* SLC_FRHOST_BIT4_INT_RAW : RO ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT4_INT_RAW (BIT(4)) +#define SLC_FRHOST_BIT4_INT_RAW_M (BIT(4)) +#define SLC_FRHOST_BIT4_INT_RAW_V 0x1 +#define SLC_FRHOST_BIT4_INT_RAW_S 4 +/* SLC_FRHOST_BIT3_INT_RAW : RO ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT3_INT_RAW (BIT(3)) +#define SLC_FRHOST_BIT3_INT_RAW_M (BIT(3)) +#define SLC_FRHOST_BIT3_INT_RAW_V 0x1 +#define SLC_FRHOST_BIT3_INT_RAW_S 3 +/* SLC_FRHOST_BIT2_INT_RAW : RO ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT2_INT_RAW (BIT(2)) +#define SLC_FRHOST_BIT2_INT_RAW_M (BIT(2)) +#define SLC_FRHOST_BIT2_INT_RAW_V 0x1 +#define SLC_FRHOST_BIT2_INT_RAW_S 2 +/* SLC_FRHOST_BIT1_INT_RAW : RO ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT1_INT_RAW (BIT(1)) +#define SLC_FRHOST_BIT1_INT_RAW_M (BIT(1)) +#define SLC_FRHOST_BIT1_INT_RAW_V 0x1 +#define SLC_FRHOST_BIT1_INT_RAW_S 1 +/* SLC_FRHOST_BIT0_INT_RAW : RO ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT0_INT_RAW (BIT(0)) +#define SLC_FRHOST_BIT0_INT_RAW_M (BIT(0)) +#define SLC_FRHOST_BIT0_INT_RAW_V 0x1 +#define SLC_FRHOST_BIT0_INT_RAW_S 0 + +#define SLC_0INT_ST_REG (DR_REG_SLC_BASE + 0x8) +/* SLC_SLC0_RX_QUICK_EOF_INT_ST : RO ;bitpos:[26] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_QUICK_EOF_INT_ST (BIT(26)) +#define SLC_SLC0_RX_QUICK_EOF_INT_ST_M (BIT(26)) +#define SLC_SLC0_RX_QUICK_EOF_INT_ST_V 0x1 +#define SLC_SLC0_RX_QUICK_EOF_INT_ST_S 26 +/* SLC_CMD_DTC_INT_ST : RO ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define SLC_CMD_DTC_INT_ST (BIT(25)) +#define SLC_CMD_DTC_INT_ST_M (BIT(25)) +#define SLC_CMD_DTC_INT_ST_V 0x1 +#define SLC_CMD_DTC_INT_ST_S 25 +/* SLC_SLC0_TX_ERR_EOF_INT_ST : RO ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_ERR_EOF_INT_ST (BIT(24)) +#define SLC_SLC0_TX_ERR_EOF_INT_ST_M (BIT(24)) +#define SLC_SLC0_TX_ERR_EOF_INT_ST_V 0x1 +#define SLC_SLC0_TX_ERR_EOF_INT_ST_S 24 +/* SLC_SLC0_WR_RETRY_DONE_INT_ST : RO ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_WR_RETRY_DONE_INT_ST (BIT(23)) +#define SLC_SLC0_WR_RETRY_DONE_INT_ST_M (BIT(23)) +#define SLC_SLC0_WR_RETRY_DONE_INT_ST_V 0x1 +#define SLC_SLC0_WR_RETRY_DONE_INT_ST_S 23 +/* SLC_SLC0_HOST_RD_ACK_INT_ST : RO ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_HOST_RD_ACK_INT_ST (BIT(22)) +#define SLC_SLC0_HOST_RD_ACK_INT_ST_M (BIT(22)) +#define SLC_SLC0_HOST_RD_ACK_INT_ST_V 0x1 +#define SLC_SLC0_HOST_RD_ACK_INT_ST_S 22 +/* SLC_SLC0_TX_DSCR_EMPTY_INT_ST : RO ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST (BIT(21)) +#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST_M (BIT(21)) +#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST_V 0x1 +#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST_S 21 +/* SLC_SLC0_RX_DSCR_ERR_INT_ST : RO ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_DSCR_ERR_INT_ST (BIT(20)) +#define SLC_SLC0_RX_DSCR_ERR_INT_ST_M (BIT(20)) +#define SLC_SLC0_RX_DSCR_ERR_INT_ST_V 0x1 +#define SLC_SLC0_RX_DSCR_ERR_INT_ST_S 20 +/* SLC_SLC0_TX_DSCR_ERR_INT_ST : RO ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DSCR_ERR_INT_ST (BIT(19)) +#define SLC_SLC0_TX_DSCR_ERR_INT_ST_M (BIT(19)) +#define SLC_SLC0_TX_DSCR_ERR_INT_ST_V 0x1 +#define SLC_SLC0_TX_DSCR_ERR_INT_ST_S 19 +/* SLC_SLC0_TOHOST_INT_ST : RO ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOHOST_INT_ST (BIT(18)) +#define SLC_SLC0_TOHOST_INT_ST_M (BIT(18)) +#define SLC_SLC0_TOHOST_INT_ST_V 0x1 +#define SLC_SLC0_TOHOST_INT_ST_S 18 +/* SLC_SLC0_RX_EOF_INT_ST : RO ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_EOF_INT_ST (BIT(17)) +#define SLC_SLC0_RX_EOF_INT_ST_M (BIT(17)) +#define SLC_SLC0_RX_EOF_INT_ST_V 0x1 +#define SLC_SLC0_RX_EOF_INT_ST_S 17 +/* SLC_SLC0_RX_DONE_INT_ST : RO ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_DONE_INT_ST (BIT(16)) +#define SLC_SLC0_RX_DONE_INT_ST_M (BIT(16)) +#define SLC_SLC0_RX_DONE_INT_ST_V 0x1 +#define SLC_SLC0_RX_DONE_INT_ST_S 16 +/* SLC_SLC0_TX_SUC_EOF_INT_ST : RO ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_SUC_EOF_INT_ST (BIT(15)) +#define SLC_SLC0_TX_SUC_EOF_INT_ST_M (BIT(15)) +#define SLC_SLC0_TX_SUC_EOF_INT_ST_V 0x1 +#define SLC_SLC0_TX_SUC_EOF_INT_ST_S 15 +/* SLC_SLC0_TX_DONE_INT_ST : RO ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DONE_INT_ST (BIT(14)) +#define SLC_SLC0_TX_DONE_INT_ST_M (BIT(14)) +#define SLC_SLC0_TX_DONE_INT_ST_V 0x1 +#define SLC_SLC0_TX_DONE_INT_ST_S 14 +/* SLC_SLC0_TOKEN1_1TO0_INT_ST : RO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN1_1TO0_INT_ST (BIT(13)) +#define SLC_SLC0_TOKEN1_1TO0_INT_ST_M (BIT(13)) +#define SLC_SLC0_TOKEN1_1TO0_INT_ST_V 0x1 +#define SLC_SLC0_TOKEN1_1TO0_INT_ST_S 13 +/* SLC_SLC0_TOKEN0_1TO0_INT_ST : RO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN0_1TO0_INT_ST (BIT(12)) +#define SLC_SLC0_TOKEN0_1TO0_INT_ST_M (BIT(12)) +#define SLC_SLC0_TOKEN0_1TO0_INT_ST_V 0x1 +#define SLC_SLC0_TOKEN0_1TO0_INT_ST_S 12 +/* SLC_SLC0_TX_OVF_INT_ST : RO ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_OVF_INT_ST (BIT(11)) +#define SLC_SLC0_TX_OVF_INT_ST_M (BIT(11)) +#define SLC_SLC0_TX_OVF_INT_ST_V 0x1 +#define SLC_SLC0_TX_OVF_INT_ST_S 11 +/* SLC_SLC0_RX_UDF_INT_ST : RO ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_UDF_INT_ST (BIT(10)) +#define SLC_SLC0_RX_UDF_INT_ST_M (BIT(10)) +#define SLC_SLC0_RX_UDF_INT_ST_V 0x1 +#define SLC_SLC0_RX_UDF_INT_ST_S 10 +/* SLC_SLC0_TX_START_INT_ST : RO ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_START_INT_ST (BIT(9)) +#define SLC_SLC0_TX_START_INT_ST_M (BIT(9)) +#define SLC_SLC0_TX_START_INT_ST_V 0x1 +#define SLC_SLC0_TX_START_INT_ST_S 9 +/* SLC_SLC0_RX_START_INT_ST : RO ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_START_INT_ST (BIT(8)) +#define SLC_SLC0_RX_START_INT_ST_M (BIT(8)) +#define SLC_SLC0_RX_START_INT_ST_V 0x1 +#define SLC_SLC0_RX_START_INT_ST_S 8 +/* SLC_FRHOST_BIT7_INT_ST : RO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT7_INT_ST (BIT(7)) +#define SLC_FRHOST_BIT7_INT_ST_M (BIT(7)) +#define SLC_FRHOST_BIT7_INT_ST_V 0x1 +#define SLC_FRHOST_BIT7_INT_ST_S 7 +/* SLC_FRHOST_BIT6_INT_ST : RO ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT6_INT_ST (BIT(6)) +#define SLC_FRHOST_BIT6_INT_ST_M (BIT(6)) +#define SLC_FRHOST_BIT6_INT_ST_V 0x1 +#define SLC_FRHOST_BIT6_INT_ST_S 6 +/* SLC_FRHOST_BIT5_INT_ST : RO ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT5_INT_ST (BIT(5)) +#define SLC_FRHOST_BIT5_INT_ST_M (BIT(5)) +#define SLC_FRHOST_BIT5_INT_ST_V 0x1 +#define SLC_FRHOST_BIT5_INT_ST_S 5 +/* SLC_FRHOST_BIT4_INT_ST : RO ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT4_INT_ST (BIT(4)) +#define SLC_FRHOST_BIT4_INT_ST_M (BIT(4)) +#define SLC_FRHOST_BIT4_INT_ST_V 0x1 +#define SLC_FRHOST_BIT4_INT_ST_S 4 +/* SLC_FRHOST_BIT3_INT_ST : RO ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT3_INT_ST (BIT(3)) +#define SLC_FRHOST_BIT3_INT_ST_M (BIT(3)) +#define SLC_FRHOST_BIT3_INT_ST_V 0x1 +#define SLC_FRHOST_BIT3_INT_ST_S 3 +/* SLC_FRHOST_BIT2_INT_ST : RO ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT2_INT_ST (BIT(2)) +#define SLC_FRHOST_BIT2_INT_ST_M (BIT(2)) +#define SLC_FRHOST_BIT2_INT_ST_V 0x1 +#define SLC_FRHOST_BIT2_INT_ST_S 2 +/* SLC_FRHOST_BIT1_INT_ST : RO ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT1_INT_ST (BIT(1)) +#define SLC_FRHOST_BIT1_INT_ST_M (BIT(1)) +#define SLC_FRHOST_BIT1_INT_ST_V 0x1 +#define SLC_FRHOST_BIT1_INT_ST_S 1 +/* SLC_FRHOST_BIT0_INT_ST : RO ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT0_INT_ST (BIT(0)) +#define SLC_FRHOST_BIT0_INT_ST_M (BIT(0)) +#define SLC_FRHOST_BIT0_INT_ST_V 0x1 +#define SLC_FRHOST_BIT0_INT_ST_S 0 + +#define SLC_0INT_ENA_REG (DR_REG_SLC_BASE + 0xC) +/* SLC_SLC0_RX_QUICK_EOF_INT_ENA : R/W ;bitpos:[26] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_QUICK_EOF_INT_ENA (BIT(26)) +#define SLC_SLC0_RX_QUICK_EOF_INT_ENA_M (BIT(26)) +#define SLC_SLC0_RX_QUICK_EOF_INT_ENA_V 0x1 +#define SLC_SLC0_RX_QUICK_EOF_INT_ENA_S 26 +/* SLC_CMD_DTC_INT_ENA : R/W ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define SLC_CMD_DTC_INT_ENA (BIT(25)) +#define SLC_CMD_DTC_INT_ENA_M (BIT(25)) +#define SLC_CMD_DTC_INT_ENA_V 0x1 +#define SLC_CMD_DTC_INT_ENA_S 25 +/* SLC_SLC0_TX_ERR_EOF_INT_ENA : R/W ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_ERR_EOF_INT_ENA (BIT(24)) +#define SLC_SLC0_TX_ERR_EOF_INT_ENA_M (BIT(24)) +#define SLC_SLC0_TX_ERR_EOF_INT_ENA_V 0x1 +#define SLC_SLC0_TX_ERR_EOF_INT_ENA_S 24 +/* SLC_SLC0_WR_RETRY_DONE_INT_ENA : R/W ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_WR_RETRY_DONE_INT_ENA (BIT(23)) +#define SLC_SLC0_WR_RETRY_DONE_INT_ENA_M (BIT(23)) +#define SLC_SLC0_WR_RETRY_DONE_INT_ENA_V 0x1 +#define SLC_SLC0_WR_RETRY_DONE_INT_ENA_S 23 +/* SLC_SLC0_HOST_RD_ACK_INT_ENA : R/W ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_HOST_RD_ACK_INT_ENA (BIT(22)) +#define SLC_SLC0_HOST_RD_ACK_INT_ENA_M (BIT(22)) +#define SLC_SLC0_HOST_RD_ACK_INT_ENA_V 0x1 +#define SLC_SLC0_HOST_RD_ACK_INT_ENA_S 22 +/* SLC_SLC0_TX_DSCR_EMPTY_INT_ENA : R/W ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA (BIT(21)) +#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA_M (BIT(21)) +#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA_V 0x1 +#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA_S 21 +/* SLC_SLC0_RX_DSCR_ERR_INT_ENA : R/W ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_DSCR_ERR_INT_ENA (BIT(20)) +#define SLC_SLC0_RX_DSCR_ERR_INT_ENA_M (BIT(20)) +#define SLC_SLC0_RX_DSCR_ERR_INT_ENA_V 0x1 +#define SLC_SLC0_RX_DSCR_ERR_INT_ENA_S 20 +/* SLC_SLC0_TX_DSCR_ERR_INT_ENA : R/W ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DSCR_ERR_INT_ENA (BIT(19)) +#define SLC_SLC0_TX_DSCR_ERR_INT_ENA_M (BIT(19)) +#define SLC_SLC0_TX_DSCR_ERR_INT_ENA_V 0x1 +#define SLC_SLC0_TX_DSCR_ERR_INT_ENA_S 19 +/* SLC_SLC0_TOHOST_INT_ENA : R/W ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOHOST_INT_ENA (BIT(18)) +#define SLC_SLC0_TOHOST_INT_ENA_M (BIT(18)) +#define SLC_SLC0_TOHOST_INT_ENA_V 0x1 +#define SLC_SLC0_TOHOST_INT_ENA_S 18 +/* SLC_SLC0_RX_EOF_INT_ENA : R/W ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_EOF_INT_ENA (BIT(17)) +#define SLC_SLC0_RX_EOF_INT_ENA_M (BIT(17)) +#define SLC_SLC0_RX_EOF_INT_ENA_V 0x1 +#define SLC_SLC0_RX_EOF_INT_ENA_S 17 +/* SLC_SLC0_RX_DONE_INT_ENA : R/W ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_DONE_INT_ENA (BIT(16)) +#define SLC_SLC0_RX_DONE_INT_ENA_M (BIT(16)) +#define SLC_SLC0_RX_DONE_INT_ENA_V 0x1 +#define SLC_SLC0_RX_DONE_INT_ENA_S 16 +/* SLC_SLC0_TX_SUC_EOF_INT_ENA : R/W ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_SUC_EOF_INT_ENA (BIT(15)) +#define SLC_SLC0_TX_SUC_EOF_INT_ENA_M (BIT(15)) +#define SLC_SLC0_TX_SUC_EOF_INT_ENA_V 0x1 +#define SLC_SLC0_TX_SUC_EOF_INT_ENA_S 15 +/* SLC_SLC0_TX_DONE_INT_ENA : R/W ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DONE_INT_ENA (BIT(14)) +#define SLC_SLC0_TX_DONE_INT_ENA_M (BIT(14)) +#define SLC_SLC0_TX_DONE_INT_ENA_V 0x1 +#define SLC_SLC0_TX_DONE_INT_ENA_S 14 +/* SLC_SLC0_TOKEN1_1TO0_INT_ENA : R/W ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN1_1TO0_INT_ENA (BIT(13)) +#define SLC_SLC0_TOKEN1_1TO0_INT_ENA_M (BIT(13)) +#define SLC_SLC0_TOKEN1_1TO0_INT_ENA_V 0x1 +#define SLC_SLC0_TOKEN1_1TO0_INT_ENA_S 13 +/* SLC_SLC0_TOKEN0_1TO0_INT_ENA : R/W ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN0_1TO0_INT_ENA (BIT(12)) +#define SLC_SLC0_TOKEN0_1TO0_INT_ENA_M (BIT(12)) +#define SLC_SLC0_TOKEN0_1TO0_INT_ENA_V 0x1 +#define SLC_SLC0_TOKEN0_1TO0_INT_ENA_S 12 +/* SLC_SLC0_TX_OVF_INT_ENA : R/W ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_OVF_INT_ENA (BIT(11)) +#define SLC_SLC0_TX_OVF_INT_ENA_M (BIT(11)) +#define SLC_SLC0_TX_OVF_INT_ENA_V 0x1 +#define SLC_SLC0_TX_OVF_INT_ENA_S 11 +/* SLC_SLC0_RX_UDF_INT_ENA : R/W ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_UDF_INT_ENA (BIT(10)) +#define SLC_SLC0_RX_UDF_INT_ENA_M (BIT(10)) +#define SLC_SLC0_RX_UDF_INT_ENA_V 0x1 +#define SLC_SLC0_RX_UDF_INT_ENA_S 10 +/* SLC_SLC0_TX_START_INT_ENA : R/W ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_START_INT_ENA (BIT(9)) +#define SLC_SLC0_TX_START_INT_ENA_M (BIT(9)) +#define SLC_SLC0_TX_START_INT_ENA_V 0x1 +#define SLC_SLC0_TX_START_INT_ENA_S 9 +/* SLC_SLC0_RX_START_INT_ENA : R/W ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_START_INT_ENA (BIT(8)) +#define SLC_SLC0_RX_START_INT_ENA_M (BIT(8)) +#define SLC_SLC0_RX_START_INT_ENA_V 0x1 +#define SLC_SLC0_RX_START_INT_ENA_S 8 +/* SLC_FRHOST_BIT7_INT_ENA : R/W ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT7_INT_ENA (BIT(7)) +#define SLC_FRHOST_BIT7_INT_ENA_M (BIT(7)) +#define SLC_FRHOST_BIT7_INT_ENA_V 0x1 +#define SLC_FRHOST_BIT7_INT_ENA_S 7 +/* SLC_FRHOST_BIT6_INT_ENA : R/W ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT6_INT_ENA (BIT(6)) +#define SLC_FRHOST_BIT6_INT_ENA_M (BIT(6)) +#define SLC_FRHOST_BIT6_INT_ENA_V 0x1 +#define SLC_FRHOST_BIT6_INT_ENA_S 6 +/* SLC_FRHOST_BIT5_INT_ENA : R/W ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT5_INT_ENA (BIT(5)) +#define SLC_FRHOST_BIT5_INT_ENA_M (BIT(5)) +#define SLC_FRHOST_BIT5_INT_ENA_V 0x1 +#define SLC_FRHOST_BIT5_INT_ENA_S 5 +/* SLC_FRHOST_BIT4_INT_ENA : R/W ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT4_INT_ENA (BIT(4)) +#define SLC_FRHOST_BIT4_INT_ENA_M (BIT(4)) +#define SLC_FRHOST_BIT4_INT_ENA_V 0x1 +#define SLC_FRHOST_BIT4_INT_ENA_S 4 +/* SLC_FRHOST_BIT3_INT_ENA : R/W ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT3_INT_ENA (BIT(3)) +#define SLC_FRHOST_BIT3_INT_ENA_M (BIT(3)) +#define SLC_FRHOST_BIT3_INT_ENA_V 0x1 +#define SLC_FRHOST_BIT3_INT_ENA_S 3 +/* SLC_FRHOST_BIT2_INT_ENA : R/W ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT2_INT_ENA (BIT(2)) +#define SLC_FRHOST_BIT2_INT_ENA_M (BIT(2)) +#define SLC_FRHOST_BIT2_INT_ENA_V 0x1 +#define SLC_FRHOST_BIT2_INT_ENA_S 2 +/* SLC_FRHOST_BIT1_INT_ENA : R/W ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT1_INT_ENA (BIT(1)) +#define SLC_FRHOST_BIT1_INT_ENA_M (BIT(1)) +#define SLC_FRHOST_BIT1_INT_ENA_V 0x1 +#define SLC_FRHOST_BIT1_INT_ENA_S 1 +/* SLC_FRHOST_BIT0_INT_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT0_INT_ENA (BIT(0)) +#define SLC_FRHOST_BIT0_INT_ENA_M (BIT(0)) +#define SLC_FRHOST_BIT0_INT_ENA_V 0x1 +#define SLC_FRHOST_BIT0_INT_ENA_S 0 + +#define SLC_0INT_CLR_REG (DR_REG_SLC_BASE + 0x10) +/* SLC_SLC0_RX_QUICK_EOF_INT_CLR : WO ;bitpos:[26] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_QUICK_EOF_INT_CLR (BIT(26)) +#define SLC_SLC0_RX_QUICK_EOF_INT_CLR_M (BIT(26)) +#define SLC_SLC0_RX_QUICK_EOF_INT_CLR_V 0x1 +#define SLC_SLC0_RX_QUICK_EOF_INT_CLR_S 26 +/* SLC_CMD_DTC_INT_CLR : WO ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define SLC_CMD_DTC_INT_CLR (BIT(25)) +#define SLC_CMD_DTC_INT_CLR_M (BIT(25)) +#define SLC_CMD_DTC_INT_CLR_V 0x1 +#define SLC_CMD_DTC_INT_CLR_S 25 +/* SLC_SLC0_TX_ERR_EOF_INT_CLR : WO ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_ERR_EOF_INT_CLR (BIT(24)) +#define SLC_SLC0_TX_ERR_EOF_INT_CLR_M (BIT(24)) +#define SLC_SLC0_TX_ERR_EOF_INT_CLR_V 0x1 +#define SLC_SLC0_TX_ERR_EOF_INT_CLR_S 24 +/* SLC_SLC0_WR_RETRY_DONE_INT_CLR : WO ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_WR_RETRY_DONE_INT_CLR (BIT(23)) +#define SLC_SLC0_WR_RETRY_DONE_INT_CLR_M (BIT(23)) +#define SLC_SLC0_WR_RETRY_DONE_INT_CLR_V 0x1 +#define SLC_SLC0_WR_RETRY_DONE_INT_CLR_S 23 +/* SLC_SLC0_HOST_RD_ACK_INT_CLR : WO ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_HOST_RD_ACK_INT_CLR (BIT(22)) +#define SLC_SLC0_HOST_RD_ACK_INT_CLR_M (BIT(22)) +#define SLC_SLC0_HOST_RD_ACK_INT_CLR_V 0x1 +#define SLC_SLC0_HOST_RD_ACK_INT_CLR_S 22 +/* SLC_SLC0_TX_DSCR_EMPTY_INT_CLR : WO ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DSCR_EMPTY_INT_CLR (BIT(21)) +#define SLC_SLC0_TX_DSCR_EMPTY_INT_CLR_M (BIT(21)) +#define SLC_SLC0_TX_DSCR_EMPTY_INT_CLR_V 0x1 +#define SLC_SLC0_TX_DSCR_EMPTY_INT_CLR_S 21 +/* SLC_SLC0_RX_DSCR_ERR_INT_CLR : WO ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_DSCR_ERR_INT_CLR (BIT(20)) +#define SLC_SLC0_RX_DSCR_ERR_INT_CLR_M (BIT(20)) +#define SLC_SLC0_RX_DSCR_ERR_INT_CLR_V 0x1 +#define SLC_SLC0_RX_DSCR_ERR_INT_CLR_S 20 +/* SLC_SLC0_TX_DSCR_ERR_INT_CLR : WO ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DSCR_ERR_INT_CLR (BIT(19)) +#define SLC_SLC0_TX_DSCR_ERR_INT_CLR_M (BIT(19)) +#define SLC_SLC0_TX_DSCR_ERR_INT_CLR_V 0x1 +#define SLC_SLC0_TX_DSCR_ERR_INT_CLR_S 19 +/* SLC_SLC0_TOHOST_INT_CLR : WO ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOHOST_INT_CLR (BIT(18)) +#define SLC_SLC0_TOHOST_INT_CLR_M (BIT(18)) +#define SLC_SLC0_TOHOST_INT_CLR_V 0x1 +#define SLC_SLC0_TOHOST_INT_CLR_S 18 +/* SLC_SLC0_RX_EOF_INT_CLR : WO ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_EOF_INT_CLR (BIT(17)) +#define SLC_SLC0_RX_EOF_INT_CLR_M (BIT(17)) +#define SLC_SLC0_RX_EOF_INT_CLR_V 0x1 +#define SLC_SLC0_RX_EOF_INT_CLR_S 17 +/* SLC_SLC0_RX_DONE_INT_CLR : WO ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_DONE_INT_CLR (BIT(16)) +#define SLC_SLC0_RX_DONE_INT_CLR_M (BIT(16)) +#define SLC_SLC0_RX_DONE_INT_CLR_V 0x1 +#define SLC_SLC0_RX_DONE_INT_CLR_S 16 +/* SLC_SLC0_TX_SUC_EOF_INT_CLR : WO ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_SUC_EOF_INT_CLR (BIT(15)) +#define SLC_SLC0_TX_SUC_EOF_INT_CLR_M (BIT(15)) +#define SLC_SLC0_TX_SUC_EOF_INT_CLR_V 0x1 +#define SLC_SLC0_TX_SUC_EOF_INT_CLR_S 15 +/* SLC_SLC0_TX_DONE_INT_CLR : WO ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DONE_INT_CLR (BIT(14)) +#define SLC_SLC0_TX_DONE_INT_CLR_M (BIT(14)) +#define SLC_SLC0_TX_DONE_INT_CLR_V 0x1 +#define SLC_SLC0_TX_DONE_INT_CLR_S 14 +/* SLC_SLC0_TOKEN1_1TO0_INT_CLR : WO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN1_1TO0_INT_CLR (BIT(13)) +#define SLC_SLC0_TOKEN1_1TO0_INT_CLR_M (BIT(13)) +#define SLC_SLC0_TOKEN1_1TO0_INT_CLR_V 0x1 +#define SLC_SLC0_TOKEN1_1TO0_INT_CLR_S 13 +/* SLC_SLC0_TOKEN0_1TO0_INT_CLR : WO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN0_1TO0_INT_CLR (BIT(12)) +#define SLC_SLC0_TOKEN0_1TO0_INT_CLR_M (BIT(12)) +#define SLC_SLC0_TOKEN0_1TO0_INT_CLR_V 0x1 +#define SLC_SLC0_TOKEN0_1TO0_INT_CLR_S 12 +/* SLC_SLC0_TX_OVF_INT_CLR : WO ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_OVF_INT_CLR (BIT(11)) +#define SLC_SLC0_TX_OVF_INT_CLR_M (BIT(11)) +#define SLC_SLC0_TX_OVF_INT_CLR_V 0x1 +#define SLC_SLC0_TX_OVF_INT_CLR_S 11 +/* SLC_SLC0_RX_UDF_INT_CLR : WO ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_UDF_INT_CLR (BIT(10)) +#define SLC_SLC0_RX_UDF_INT_CLR_M (BIT(10)) +#define SLC_SLC0_RX_UDF_INT_CLR_V 0x1 +#define SLC_SLC0_RX_UDF_INT_CLR_S 10 +/* SLC_SLC0_TX_START_INT_CLR : WO ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_START_INT_CLR (BIT(9)) +#define SLC_SLC0_TX_START_INT_CLR_M (BIT(9)) +#define SLC_SLC0_TX_START_INT_CLR_V 0x1 +#define SLC_SLC0_TX_START_INT_CLR_S 9 +/* SLC_SLC0_RX_START_INT_CLR : WO ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_START_INT_CLR (BIT(8)) +#define SLC_SLC0_RX_START_INT_CLR_M (BIT(8)) +#define SLC_SLC0_RX_START_INT_CLR_V 0x1 +#define SLC_SLC0_RX_START_INT_CLR_S 8 +/* SLC_FRHOST_BIT7_INT_CLR : WO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT7_INT_CLR (BIT(7)) +#define SLC_FRHOST_BIT7_INT_CLR_M (BIT(7)) +#define SLC_FRHOST_BIT7_INT_CLR_V 0x1 +#define SLC_FRHOST_BIT7_INT_CLR_S 7 +/* SLC_FRHOST_BIT6_INT_CLR : WO ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT6_INT_CLR (BIT(6)) +#define SLC_FRHOST_BIT6_INT_CLR_M (BIT(6)) +#define SLC_FRHOST_BIT6_INT_CLR_V 0x1 +#define SLC_FRHOST_BIT6_INT_CLR_S 6 +/* SLC_FRHOST_BIT5_INT_CLR : WO ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT5_INT_CLR (BIT(5)) +#define SLC_FRHOST_BIT5_INT_CLR_M (BIT(5)) +#define SLC_FRHOST_BIT5_INT_CLR_V 0x1 +#define SLC_FRHOST_BIT5_INT_CLR_S 5 +/* SLC_FRHOST_BIT4_INT_CLR : WO ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT4_INT_CLR (BIT(4)) +#define SLC_FRHOST_BIT4_INT_CLR_M (BIT(4)) +#define SLC_FRHOST_BIT4_INT_CLR_V 0x1 +#define SLC_FRHOST_BIT4_INT_CLR_S 4 +/* SLC_FRHOST_BIT3_INT_CLR : WO ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT3_INT_CLR (BIT(3)) +#define SLC_FRHOST_BIT3_INT_CLR_M (BIT(3)) +#define SLC_FRHOST_BIT3_INT_CLR_V 0x1 +#define SLC_FRHOST_BIT3_INT_CLR_S 3 +/* SLC_FRHOST_BIT2_INT_CLR : WO ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT2_INT_CLR (BIT(2)) +#define SLC_FRHOST_BIT2_INT_CLR_M (BIT(2)) +#define SLC_FRHOST_BIT2_INT_CLR_V 0x1 +#define SLC_FRHOST_BIT2_INT_CLR_S 2 +/* SLC_FRHOST_BIT1_INT_CLR : WO ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT1_INT_CLR (BIT(1)) +#define SLC_FRHOST_BIT1_INT_CLR_M (BIT(1)) +#define SLC_FRHOST_BIT1_INT_CLR_V 0x1 +#define SLC_FRHOST_BIT1_INT_CLR_S 1 +/* SLC_FRHOST_BIT0_INT_CLR : WO ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT0_INT_CLR (BIT(0)) +#define SLC_FRHOST_BIT0_INT_CLR_M (BIT(0)) +#define SLC_FRHOST_BIT0_INT_CLR_V 0x1 +#define SLC_FRHOST_BIT0_INT_CLR_S 0 + +#define SLC_1INT_RAW_REG (DR_REG_SLC_BASE + 0x14) +/* SLC_SLC1_TX_ERR_EOF_INT_RAW : RO ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_ERR_EOF_INT_RAW (BIT(24)) +#define SLC_SLC1_TX_ERR_EOF_INT_RAW_M (BIT(24)) +#define SLC_SLC1_TX_ERR_EOF_INT_RAW_V 0x1 +#define SLC_SLC1_TX_ERR_EOF_INT_RAW_S 24 +/* SLC_SLC1_WR_RETRY_DONE_INT_RAW : RO ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_WR_RETRY_DONE_INT_RAW (BIT(23)) +#define SLC_SLC1_WR_RETRY_DONE_INT_RAW_M (BIT(23)) +#define SLC_SLC1_WR_RETRY_DONE_INT_RAW_V 0x1 +#define SLC_SLC1_WR_RETRY_DONE_INT_RAW_S 23 +/* SLC_SLC1_HOST_RD_ACK_INT_RAW : RO ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_HOST_RD_ACK_INT_RAW (BIT(22)) +#define SLC_SLC1_HOST_RD_ACK_INT_RAW_M (BIT(22)) +#define SLC_SLC1_HOST_RD_ACK_INT_RAW_V 0x1 +#define SLC_SLC1_HOST_RD_ACK_INT_RAW_S 22 +/* SLC_SLC1_TX_DSCR_EMPTY_INT_RAW : RO ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DSCR_EMPTY_INT_RAW (BIT(21)) +#define SLC_SLC1_TX_DSCR_EMPTY_INT_RAW_M (BIT(21)) +#define SLC_SLC1_TX_DSCR_EMPTY_INT_RAW_V 0x1 +#define SLC_SLC1_TX_DSCR_EMPTY_INT_RAW_S 21 +/* SLC_SLC1_RX_DSCR_ERR_INT_RAW : RO ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_DSCR_ERR_INT_RAW (BIT(20)) +#define SLC_SLC1_RX_DSCR_ERR_INT_RAW_M (BIT(20)) +#define SLC_SLC1_RX_DSCR_ERR_INT_RAW_V 0x1 +#define SLC_SLC1_RX_DSCR_ERR_INT_RAW_S 20 +/* SLC_SLC1_TX_DSCR_ERR_INT_RAW : RO ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DSCR_ERR_INT_RAW (BIT(19)) +#define SLC_SLC1_TX_DSCR_ERR_INT_RAW_M (BIT(19)) +#define SLC_SLC1_TX_DSCR_ERR_INT_RAW_V 0x1 +#define SLC_SLC1_TX_DSCR_ERR_INT_RAW_S 19 +/* SLC_SLC1_TOHOST_INT_RAW : RO ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOHOST_INT_RAW (BIT(18)) +#define SLC_SLC1_TOHOST_INT_RAW_M (BIT(18)) +#define SLC_SLC1_TOHOST_INT_RAW_V 0x1 +#define SLC_SLC1_TOHOST_INT_RAW_S 18 +/* SLC_SLC1_RX_EOF_INT_RAW : RO ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_EOF_INT_RAW (BIT(17)) +#define SLC_SLC1_RX_EOF_INT_RAW_M (BIT(17)) +#define SLC_SLC1_RX_EOF_INT_RAW_V 0x1 +#define SLC_SLC1_RX_EOF_INT_RAW_S 17 +/* SLC_SLC1_RX_DONE_INT_RAW : RO ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_DONE_INT_RAW (BIT(16)) +#define SLC_SLC1_RX_DONE_INT_RAW_M (BIT(16)) +#define SLC_SLC1_RX_DONE_INT_RAW_V 0x1 +#define SLC_SLC1_RX_DONE_INT_RAW_S 16 +/* SLC_SLC1_TX_SUC_EOF_INT_RAW : RO ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_SUC_EOF_INT_RAW (BIT(15)) +#define SLC_SLC1_TX_SUC_EOF_INT_RAW_M (BIT(15)) +#define SLC_SLC1_TX_SUC_EOF_INT_RAW_V 0x1 +#define SLC_SLC1_TX_SUC_EOF_INT_RAW_S 15 +/* SLC_SLC1_TX_DONE_INT_RAW : RO ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DONE_INT_RAW (BIT(14)) +#define SLC_SLC1_TX_DONE_INT_RAW_M (BIT(14)) +#define SLC_SLC1_TX_DONE_INT_RAW_V 0x1 +#define SLC_SLC1_TX_DONE_INT_RAW_S 14 +/* SLC_SLC1_TOKEN1_1TO0_INT_RAW : RO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN1_1TO0_INT_RAW (BIT(13)) +#define SLC_SLC1_TOKEN1_1TO0_INT_RAW_M (BIT(13)) +#define SLC_SLC1_TOKEN1_1TO0_INT_RAW_V 0x1 +#define SLC_SLC1_TOKEN1_1TO0_INT_RAW_S 13 +/* SLC_SLC1_TOKEN0_1TO0_INT_RAW : RO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN0_1TO0_INT_RAW (BIT(12)) +#define SLC_SLC1_TOKEN0_1TO0_INT_RAW_M (BIT(12)) +#define SLC_SLC1_TOKEN0_1TO0_INT_RAW_V 0x1 +#define SLC_SLC1_TOKEN0_1TO0_INT_RAW_S 12 +/* SLC_SLC1_TX_OVF_INT_RAW : RO ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_OVF_INT_RAW (BIT(11)) +#define SLC_SLC1_TX_OVF_INT_RAW_M (BIT(11)) +#define SLC_SLC1_TX_OVF_INT_RAW_V 0x1 +#define SLC_SLC1_TX_OVF_INT_RAW_S 11 +/* SLC_SLC1_RX_UDF_INT_RAW : RO ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_UDF_INT_RAW (BIT(10)) +#define SLC_SLC1_RX_UDF_INT_RAW_M (BIT(10)) +#define SLC_SLC1_RX_UDF_INT_RAW_V 0x1 +#define SLC_SLC1_RX_UDF_INT_RAW_S 10 +/* SLC_SLC1_TX_START_INT_RAW : RO ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_START_INT_RAW (BIT(9)) +#define SLC_SLC1_TX_START_INT_RAW_M (BIT(9)) +#define SLC_SLC1_TX_START_INT_RAW_V 0x1 +#define SLC_SLC1_TX_START_INT_RAW_S 9 +/* SLC_SLC1_RX_START_INT_RAW : RO ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_START_INT_RAW (BIT(8)) +#define SLC_SLC1_RX_START_INT_RAW_M (BIT(8)) +#define SLC_SLC1_RX_START_INT_RAW_V 0x1 +#define SLC_SLC1_RX_START_INT_RAW_S 8 +/* SLC_FRHOST_BIT15_INT_RAW : RO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT15_INT_RAW (BIT(7)) +#define SLC_FRHOST_BIT15_INT_RAW_M (BIT(7)) +#define SLC_FRHOST_BIT15_INT_RAW_V 0x1 +#define SLC_FRHOST_BIT15_INT_RAW_S 7 +/* SLC_FRHOST_BIT14_INT_RAW : RO ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT14_INT_RAW (BIT(6)) +#define SLC_FRHOST_BIT14_INT_RAW_M (BIT(6)) +#define SLC_FRHOST_BIT14_INT_RAW_V 0x1 +#define SLC_FRHOST_BIT14_INT_RAW_S 6 +/* SLC_FRHOST_BIT13_INT_RAW : RO ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT13_INT_RAW (BIT(5)) +#define SLC_FRHOST_BIT13_INT_RAW_M (BIT(5)) +#define SLC_FRHOST_BIT13_INT_RAW_V 0x1 +#define SLC_FRHOST_BIT13_INT_RAW_S 5 +/* SLC_FRHOST_BIT12_INT_RAW : RO ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT12_INT_RAW (BIT(4)) +#define SLC_FRHOST_BIT12_INT_RAW_M (BIT(4)) +#define SLC_FRHOST_BIT12_INT_RAW_V 0x1 +#define SLC_FRHOST_BIT12_INT_RAW_S 4 +/* SLC_FRHOST_BIT11_INT_RAW : RO ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT11_INT_RAW (BIT(3)) +#define SLC_FRHOST_BIT11_INT_RAW_M (BIT(3)) +#define SLC_FRHOST_BIT11_INT_RAW_V 0x1 +#define SLC_FRHOST_BIT11_INT_RAW_S 3 +/* SLC_FRHOST_BIT10_INT_RAW : RO ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT10_INT_RAW (BIT(2)) +#define SLC_FRHOST_BIT10_INT_RAW_M (BIT(2)) +#define SLC_FRHOST_BIT10_INT_RAW_V 0x1 +#define SLC_FRHOST_BIT10_INT_RAW_S 2 +/* SLC_FRHOST_BIT9_INT_RAW : RO ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT9_INT_RAW (BIT(1)) +#define SLC_FRHOST_BIT9_INT_RAW_M (BIT(1)) +#define SLC_FRHOST_BIT9_INT_RAW_V 0x1 +#define SLC_FRHOST_BIT9_INT_RAW_S 1 +/* SLC_FRHOST_BIT8_INT_RAW : RO ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT8_INT_RAW (BIT(0)) +#define SLC_FRHOST_BIT8_INT_RAW_M (BIT(0)) +#define SLC_FRHOST_BIT8_INT_RAW_V 0x1 +#define SLC_FRHOST_BIT8_INT_RAW_S 0 + +#define SLC_1INT_ST_REG (DR_REG_SLC_BASE + 0x18) +/* SLC_SLC1_TX_ERR_EOF_INT_ST : RO ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_ERR_EOF_INT_ST (BIT(24)) +#define SLC_SLC1_TX_ERR_EOF_INT_ST_M (BIT(24)) +#define SLC_SLC1_TX_ERR_EOF_INT_ST_V 0x1 +#define SLC_SLC1_TX_ERR_EOF_INT_ST_S 24 +/* SLC_SLC1_WR_RETRY_DONE_INT_ST : RO ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_WR_RETRY_DONE_INT_ST (BIT(23)) +#define SLC_SLC1_WR_RETRY_DONE_INT_ST_M (BIT(23)) +#define SLC_SLC1_WR_RETRY_DONE_INT_ST_V 0x1 +#define SLC_SLC1_WR_RETRY_DONE_INT_ST_S 23 +/* SLC_SLC1_HOST_RD_ACK_INT_ST : RO ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_HOST_RD_ACK_INT_ST (BIT(22)) +#define SLC_SLC1_HOST_RD_ACK_INT_ST_M (BIT(22)) +#define SLC_SLC1_HOST_RD_ACK_INT_ST_V 0x1 +#define SLC_SLC1_HOST_RD_ACK_INT_ST_S 22 +/* SLC_SLC1_TX_DSCR_EMPTY_INT_ST : RO ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DSCR_EMPTY_INT_ST (BIT(21)) +#define SLC_SLC1_TX_DSCR_EMPTY_INT_ST_M (BIT(21)) +#define SLC_SLC1_TX_DSCR_EMPTY_INT_ST_V 0x1 +#define SLC_SLC1_TX_DSCR_EMPTY_INT_ST_S 21 +/* SLC_SLC1_RX_DSCR_ERR_INT_ST : RO ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_DSCR_ERR_INT_ST (BIT(20)) +#define SLC_SLC1_RX_DSCR_ERR_INT_ST_M (BIT(20)) +#define SLC_SLC1_RX_DSCR_ERR_INT_ST_V 0x1 +#define SLC_SLC1_RX_DSCR_ERR_INT_ST_S 20 +/* SLC_SLC1_TX_DSCR_ERR_INT_ST : RO ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DSCR_ERR_INT_ST (BIT(19)) +#define SLC_SLC1_TX_DSCR_ERR_INT_ST_M (BIT(19)) +#define SLC_SLC1_TX_DSCR_ERR_INT_ST_V 0x1 +#define SLC_SLC1_TX_DSCR_ERR_INT_ST_S 19 +/* SLC_SLC1_TOHOST_INT_ST : RO ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOHOST_INT_ST (BIT(18)) +#define SLC_SLC1_TOHOST_INT_ST_M (BIT(18)) +#define SLC_SLC1_TOHOST_INT_ST_V 0x1 +#define SLC_SLC1_TOHOST_INT_ST_S 18 +/* SLC_SLC1_RX_EOF_INT_ST : RO ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_EOF_INT_ST (BIT(17)) +#define SLC_SLC1_RX_EOF_INT_ST_M (BIT(17)) +#define SLC_SLC1_RX_EOF_INT_ST_V 0x1 +#define SLC_SLC1_RX_EOF_INT_ST_S 17 +/* SLC_SLC1_RX_DONE_INT_ST : RO ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_DONE_INT_ST (BIT(16)) +#define SLC_SLC1_RX_DONE_INT_ST_M (BIT(16)) +#define SLC_SLC1_RX_DONE_INT_ST_V 0x1 +#define SLC_SLC1_RX_DONE_INT_ST_S 16 +/* SLC_SLC1_TX_SUC_EOF_INT_ST : RO ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_SUC_EOF_INT_ST (BIT(15)) +#define SLC_SLC1_TX_SUC_EOF_INT_ST_M (BIT(15)) +#define SLC_SLC1_TX_SUC_EOF_INT_ST_V 0x1 +#define SLC_SLC1_TX_SUC_EOF_INT_ST_S 15 +/* SLC_SLC1_TX_DONE_INT_ST : RO ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DONE_INT_ST (BIT(14)) +#define SLC_SLC1_TX_DONE_INT_ST_M (BIT(14)) +#define SLC_SLC1_TX_DONE_INT_ST_V 0x1 +#define SLC_SLC1_TX_DONE_INT_ST_S 14 +/* SLC_SLC1_TOKEN1_1TO0_INT_ST : RO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN1_1TO0_INT_ST (BIT(13)) +#define SLC_SLC1_TOKEN1_1TO0_INT_ST_M (BIT(13)) +#define SLC_SLC1_TOKEN1_1TO0_INT_ST_V 0x1 +#define SLC_SLC1_TOKEN1_1TO0_INT_ST_S 13 +/* SLC_SLC1_TOKEN0_1TO0_INT_ST : RO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN0_1TO0_INT_ST (BIT(12)) +#define SLC_SLC1_TOKEN0_1TO0_INT_ST_M (BIT(12)) +#define SLC_SLC1_TOKEN0_1TO0_INT_ST_V 0x1 +#define SLC_SLC1_TOKEN0_1TO0_INT_ST_S 12 +/* SLC_SLC1_TX_OVF_INT_ST : RO ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_OVF_INT_ST (BIT(11)) +#define SLC_SLC1_TX_OVF_INT_ST_M (BIT(11)) +#define SLC_SLC1_TX_OVF_INT_ST_V 0x1 +#define SLC_SLC1_TX_OVF_INT_ST_S 11 +/* SLC_SLC1_RX_UDF_INT_ST : RO ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_UDF_INT_ST (BIT(10)) +#define SLC_SLC1_RX_UDF_INT_ST_M (BIT(10)) +#define SLC_SLC1_RX_UDF_INT_ST_V 0x1 +#define SLC_SLC1_RX_UDF_INT_ST_S 10 +/* SLC_SLC1_TX_START_INT_ST : RO ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_START_INT_ST (BIT(9)) +#define SLC_SLC1_TX_START_INT_ST_M (BIT(9)) +#define SLC_SLC1_TX_START_INT_ST_V 0x1 +#define SLC_SLC1_TX_START_INT_ST_S 9 +/* SLC_SLC1_RX_START_INT_ST : RO ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_START_INT_ST (BIT(8)) +#define SLC_SLC1_RX_START_INT_ST_M (BIT(8)) +#define SLC_SLC1_RX_START_INT_ST_V 0x1 +#define SLC_SLC1_RX_START_INT_ST_S 8 +/* SLC_FRHOST_BIT15_INT_ST : RO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT15_INT_ST (BIT(7)) +#define SLC_FRHOST_BIT15_INT_ST_M (BIT(7)) +#define SLC_FRHOST_BIT15_INT_ST_V 0x1 +#define SLC_FRHOST_BIT15_INT_ST_S 7 +/* SLC_FRHOST_BIT14_INT_ST : RO ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT14_INT_ST (BIT(6)) +#define SLC_FRHOST_BIT14_INT_ST_M (BIT(6)) +#define SLC_FRHOST_BIT14_INT_ST_V 0x1 +#define SLC_FRHOST_BIT14_INT_ST_S 6 +/* SLC_FRHOST_BIT13_INT_ST : RO ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT13_INT_ST (BIT(5)) +#define SLC_FRHOST_BIT13_INT_ST_M (BIT(5)) +#define SLC_FRHOST_BIT13_INT_ST_V 0x1 +#define SLC_FRHOST_BIT13_INT_ST_S 5 +/* SLC_FRHOST_BIT12_INT_ST : RO ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT12_INT_ST (BIT(4)) +#define SLC_FRHOST_BIT12_INT_ST_M (BIT(4)) +#define SLC_FRHOST_BIT12_INT_ST_V 0x1 +#define SLC_FRHOST_BIT12_INT_ST_S 4 +/* SLC_FRHOST_BIT11_INT_ST : RO ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT11_INT_ST (BIT(3)) +#define SLC_FRHOST_BIT11_INT_ST_M (BIT(3)) +#define SLC_FRHOST_BIT11_INT_ST_V 0x1 +#define SLC_FRHOST_BIT11_INT_ST_S 3 +/* SLC_FRHOST_BIT10_INT_ST : RO ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT10_INT_ST (BIT(2)) +#define SLC_FRHOST_BIT10_INT_ST_M (BIT(2)) +#define SLC_FRHOST_BIT10_INT_ST_V 0x1 +#define SLC_FRHOST_BIT10_INT_ST_S 2 +/* SLC_FRHOST_BIT9_INT_ST : RO ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT9_INT_ST (BIT(1)) +#define SLC_FRHOST_BIT9_INT_ST_M (BIT(1)) +#define SLC_FRHOST_BIT9_INT_ST_V 0x1 +#define SLC_FRHOST_BIT9_INT_ST_S 1 +/* SLC_FRHOST_BIT8_INT_ST : RO ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT8_INT_ST (BIT(0)) +#define SLC_FRHOST_BIT8_INT_ST_M (BIT(0)) +#define SLC_FRHOST_BIT8_INT_ST_V 0x1 +#define SLC_FRHOST_BIT8_INT_ST_S 0 + +#define SLC_1INT_ENA_REG (DR_REG_SLC_BASE + 0x1C) +/* SLC_SLC1_TX_ERR_EOF_INT_ENA : R/W ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_ERR_EOF_INT_ENA (BIT(24)) +#define SLC_SLC1_TX_ERR_EOF_INT_ENA_M (BIT(24)) +#define SLC_SLC1_TX_ERR_EOF_INT_ENA_V 0x1 +#define SLC_SLC1_TX_ERR_EOF_INT_ENA_S 24 +/* SLC_SLC1_WR_RETRY_DONE_INT_ENA : R/W ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_WR_RETRY_DONE_INT_ENA (BIT(23)) +#define SLC_SLC1_WR_RETRY_DONE_INT_ENA_M (BIT(23)) +#define SLC_SLC1_WR_RETRY_DONE_INT_ENA_V 0x1 +#define SLC_SLC1_WR_RETRY_DONE_INT_ENA_S 23 +/* SLC_SLC1_HOST_RD_ACK_INT_ENA : R/W ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_HOST_RD_ACK_INT_ENA (BIT(22)) +#define SLC_SLC1_HOST_RD_ACK_INT_ENA_M (BIT(22)) +#define SLC_SLC1_HOST_RD_ACK_INT_ENA_V 0x1 +#define SLC_SLC1_HOST_RD_ACK_INT_ENA_S 22 +/* SLC_SLC1_TX_DSCR_EMPTY_INT_ENA : R/W ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DSCR_EMPTY_INT_ENA (BIT(21)) +#define SLC_SLC1_TX_DSCR_EMPTY_INT_ENA_M (BIT(21)) +#define SLC_SLC1_TX_DSCR_EMPTY_INT_ENA_V 0x1 +#define SLC_SLC1_TX_DSCR_EMPTY_INT_ENA_S 21 +/* SLC_SLC1_RX_DSCR_ERR_INT_ENA : R/W ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_DSCR_ERR_INT_ENA (BIT(20)) +#define SLC_SLC1_RX_DSCR_ERR_INT_ENA_M (BIT(20)) +#define SLC_SLC1_RX_DSCR_ERR_INT_ENA_V 0x1 +#define SLC_SLC1_RX_DSCR_ERR_INT_ENA_S 20 +/* SLC_SLC1_TX_DSCR_ERR_INT_ENA : R/W ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DSCR_ERR_INT_ENA (BIT(19)) +#define SLC_SLC1_TX_DSCR_ERR_INT_ENA_M (BIT(19)) +#define SLC_SLC1_TX_DSCR_ERR_INT_ENA_V 0x1 +#define SLC_SLC1_TX_DSCR_ERR_INT_ENA_S 19 +/* SLC_SLC1_TOHOST_INT_ENA : R/W ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOHOST_INT_ENA (BIT(18)) +#define SLC_SLC1_TOHOST_INT_ENA_M (BIT(18)) +#define SLC_SLC1_TOHOST_INT_ENA_V 0x1 +#define SLC_SLC1_TOHOST_INT_ENA_S 18 +/* SLC_SLC1_RX_EOF_INT_ENA : R/W ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_EOF_INT_ENA (BIT(17)) +#define SLC_SLC1_RX_EOF_INT_ENA_M (BIT(17)) +#define SLC_SLC1_RX_EOF_INT_ENA_V 0x1 +#define SLC_SLC1_RX_EOF_INT_ENA_S 17 +/* SLC_SLC1_RX_DONE_INT_ENA : R/W ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_DONE_INT_ENA (BIT(16)) +#define SLC_SLC1_RX_DONE_INT_ENA_M (BIT(16)) +#define SLC_SLC1_RX_DONE_INT_ENA_V 0x1 +#define SLC_SLC1_RX_DONE_INT_ENA_S 16 +/* SLC_SLC1_TX_SUC_EOF_INT_ENA : R/W ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_SUC_EOF_INT_ENA (BIT(15)) +#define SLC_SLC1_TX_SUC_EOF_INT_ENA_M (BIT(15)) +#define SLC_SLC1_TX_SUC_EOF_INT_ENA_V 0x1 +#define SLC_SLC1_TX_SUC_EOF_INT_ENA_S 15 +/* SLC_SLC1_TX_DONE_INT_ENA : R/W ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DONE_INT_ENA (BIT(14)) +#define SLC_SLC1_TX_DONE_INT_ENA_M (BIT(14)) +#define SLC_SLC1_TX_DONE_INT_ENA_V 0x1 +#define SLC_SLC1_TX_DONE_INT_ENA_S 14 +/* SLC_SLC1_TOKEN1_1TO0_INT_ENA : R/W ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN1_1TO0_INT_ENA (BIT(13)) +#define SLC_SLC1_TOKEN1_1TO0_INT_ENA_M (BIT(13)) +#define SLC_SLC1_TOKEN1_1TO0_INT_ENA_V 0x1 +#define SLC_SLC1_TOKEN1_1TO0_INT_ENA_S 13 +/* SLC_SLC1_TOKEN0_1TO0_INT_ENA : R/W ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN0_1TO0_INT_ENA (BIT(12)) +#define SLC_SLC1_TOKEN0_1TO0_INT_ENA_M (BIT(12)) +#define SLC_SLC1_TOKEN0_1TO0_INT_ENA_V 0x1 +#define SLC_SLC1_TOKEN0_1TO0_INT_ENA_S 12 +/* SLC_SLC1_TX_OVF_INT_ENA : R/W ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_OVF_INT_ENA (BIT(11)) +#define SLC_SLC1_TX_OVF_INT_ENA_M (BIT(11)) +#define SLC_SLC1_TX_OVF_INT_ENA_V 0x1 +#define SLC_SLC1_TX_OVF_INT_ENA_S 11 +/* SLC_SLC1_RX_UDF_INT_ENA : R/W ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_UDF_INT_ENA (BIT(10)) +#define SLC_SLC1_RX_UDF_INT_ENA_M (BIT(10)) +#define SLC_SLC1_RX_UDF_INT_ENA_V 0x1 +#define SLC_SLC1_RX_UDF_INT_ENA_S 10 +/* SLC_SLC1_TX_START_INT_ENA : R/W ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_START_INT_ENA (BIT(9)) +#define SLC_SLC1_TX_START_INT_ENA_M (BIT(9)) +#define SLC_SLC1_TX_START_INT_ENA_V 0x1 +#define SLC_SLC1_TX_START_INT_ENA_S 9 +/* SLC_SLC1_RX_START_INT_ENA : R/W ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_START_INT_ENA (BIT(8)) +#define SLC_SLC1_RX_START_INT_ENA_M (BIT(8)) +#define SLC_SLC1_RX_START_INT_ENA_V 0x1 +#define SLC_SLC1_RX_START_INT_ENA_S 8 +/* SLC_FRHOST_BIT15_INT_ENA : R/W ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT15_INT_ENA (BIT(7)) +#define SLC_FRHOST_BIT15_INT_ENA_M (BIT(7)) +#define SLC_FRHOST_BIT15_INT_ENA_V 0x1 +#define SLC_FRHOST_BIT15_INT_ENA_S 7 +/* SLC_FRHOST_BIT14_INT_ENA : R/W ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT14_INT_ENA (BIT(6)) +#define SLC_FRHOST_BIT14_INT_ENA_M (BIT(6)) +#define SLC_FRHOST_BIT14_INT_ENA_V 0x1 +#define SLC_FRHOST_BIT14_INT_ENA_S 6 +/* SLC_FRHOST_BIT13_INT_ENA : R/W ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT13_INT_ENA (BIT(5)) +#define SLC_FRHOST_BIT13_INT_ENA_M (BIT(5)) +#define SLC_FRHOST_BIT13_INT_ENA_V 0x1 +#define SLC_FRHOST_BIT13_INT_ENA_S 5 +/* SLC_FRHOST_BIT12_INT_ENA : R/W ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT12_INT_ENA (BIT(4)) +#define SLC_FRHOST_BIT12_INT_ENA_M (BIT(4)) +#define SLC_FRHOST_BIT12_INT_ENA_V 0x1 +#define SLC_FRHOST_BIT12_INT_ENA_S 4 +/* SLC_FRHOST_BIT11_INT_ENA : R/W ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT11_INT_ENA (BIT(3)) +#define SLC_FRHOST_BIT11_INT_ENA_M (BIT(3)) +#define SLC_FRHOST_BIT11_INT_ENA_V 0x1 +#define SLC_FRHOST_BIT11_INT_ENA_S 3 +/* SLC_FRHOST_BIT10_INT_ENA : R/W ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT10_INT_ENA (BIT(2)) +#define SLC_FRHOST_BIT10_INT_ENA_M (BIT(2)) +#define SLC_FRHOST_BIT10_INT_ENA_V 0x1 +#define SLC_FRHOST_BIT10_INT_ENA_S 2 +/* SLC_FRHOST_BIT9_INT_ENA : R/W ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT9_INT_ENA (BIT(1)) +#define SLC_FRHOST_BIT9_INT_ENA_M (BIT(1)) +#define SLC_FRHOST_BIT9_INT_ENA_V 0x1 +#define SLC_FRHOST_BIT9_INT_ENA_S 1 +/* SLC_FRHOST_BIT8_INT_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT8_INT_ENA (BIT(0)) +#define SLC_FRHOST_BIT8_INT_ENA_M (BIT(0)) +#define SLC_FRHOST_BIT8_INT_ENA_V 0x1 +#define SLC_FRHOST_BIT8_INT_ENA_S 0 + +#define SLC_1INT_CLR_REG (DR_REG_SLC_BASE + 0x20) +/* SLC_SLC1_TX_ERR_EOF_INT_CLR : WO ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_ERR_EOF_INT_CLR (BIT(24)) +#define SLC_SLC1_TX_ERR_EOF_INT_CLR_M (BIT(24)) +#define SLC_SLC1_TX_ERR_EOF_INT_CLR_V 0x1 +#define SLC_SLC1_TX_ERR_EOF_INT_CLR_S 24 +/* SLC_SLC1_WR_RETRY_DONE_INT_CLR : WO ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_WR_RETRY_DONE_INT_CLR (BIT(23)) +#define SLC_SLC1_WR_RETRY_DONE_INT_CLR_M (BIT(23)) +#define SLC_SLC1_WR_RETRY_DONE_INT_CLR_V 0x1 +#define SLC_SLC1_WR_RETRY_DONE_INT_CLR_S 23 +/* SLC_SLC1_HOST_RD_ACK_INT_CLR : WO ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_HOST_RD_ACK_INT_CLR (BIT(22)) +#define SLC_SLC1_HOST_RD_ACK_INT_CLR_M (BIT(22)) +#define SLC_SLC1_HOST_RD_ACK_INT_CLR_V 0x1 +#define SLC_SLC1_HOST_RD_ACK_INT_CLR_S 22 +/* SLC_SLC1_TX_DSCR_EMPTY_INT_CLR : WO ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DSCR_EMPTY_INT_CLR (BIT(21)) +#define SLC_SLC1_TX_DSCR_EMPTY_INT_CLR_M (BIT(21)) +#define SLC_SLC1_TX_DSCR_EMPTY_INT_CLR_V 0x1 +#define SLC_SLC1_TX_DSCR_EMPTY_INT_CLR_S 21 +/* SLC_SLC1_RX_DSCR_ERR_INT_CLR : WO ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_DSCR_ERR_INT_CLR (BIT(20)) +#define SLC_SLC1_RX_DSCR_ERR_INT_CLR_M (BIT(20)) +#define SLC_SLC1_RX_DSCR_ERR_INT_CLR_V 0x1 +#define SLC_SLC1_RX_DSCR_ERR_INT_CLR_S 20 +/* SLC_SLC1_TX_DSCR_ERR_INT_CLR : WO ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DSCR_ERR_INT_CLR (BIT(19)) +#define SLC_SLC1_TX_DSCR_ERR_INT_CLR_M (BIT(19)) +#define SLC_SLC1_TX_DSCR_ERR_INT_CLR_V 0x1 +#define SLC_SLC1_TX_DSCR_ERR_INT_CLR_S 19 +/* SLC_SLC1_TOHOST_INT_CLR : WO ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOHOST_INT_CLR (BIT(18)) +#define SLC_SLC1_TOHOST_INT_CLR_M (BIT(18)) +#define SLC_SLC1_TOHOST_INT_CLR_V 0x1 +#define SLC_SLC1_TOHOST_INT_CLR_S 18 +/* SLC_SLC1_RX_EOF_INT_CLR : WO ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_EOF_INT_CLR (BIT(17)) +#define SLC_SLC1_RX_EOF_INT_CLR_M (BIT(17)) +#define SLC_SLC1_RX_EOF_INT_CLR_V 0x1 +#define SLC_SLC1_RX_EOF_INT_CLR_S 17 +/* SLC_SLC1_RX_DONE_INT_CLR : WO ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_DONE_INT_CLR (BIT(16)) +#define SLC_SLC1_RX_DONE_INT_CLR_M (BIT(16)) +#define SLC_SLC1_RX_DONE_INT_CLR_V 0x1 +#define SLC_SLC1_RX_DONE_INT_CLR_S 16 +/* SLC_SLC1_TX_SUC_EOF_INT_CLR : WO ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_SUC_EOF_INT_CLR (BIT(15)) +#define SLC_SLC1_TX_SUC_EOF_INT_CLR_M (BIT(15)) +#define SLC_SLC1_TX_SUC_EOF_INT_CLR_V 0x1 +#define SLC_SLC1_TX_SUC_EOF_INT_CLR_S 15 +/* SLC_SLC1_TX_DONE_INT_CLR : WO ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DONE_INT_CLR (BIT(14)) +#define SLC_SLC1_TX_DONE_INT_CLR_M (BIT(14)) +#define SLC_SLC1_TX_DONE_INT_CLR_V 0x1 +#define SLC_SLC1_TX_DONE_INT_CLR_S 14 +/* SLC_SLC1_TOKEN1_1TO0_INT_CLR : WO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN1_1TO0_INT_CLR (BIT(13)) +#define SLC_SLC1_TOKEN1_1TO0_INT_CLR_M (BIT(13)) +#define SLC_SLC1_TOKEN1_1TO0_INT_CLR_V 0x1 +#define SLC_SLC1_TOKEN1_1TO0_INT_CLR_S 13 +/* SLC_SLC1_TOKEN0_1TO0_INT_CLR : WO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN0_1TO0_INT_CLR (BIT(12)) +#define SLC_SLC1_TOKEN0_1TO0_INT_CLR_M (BIT(12)) +#define SLC_SLC1_TOKEN0_1TO0_INT_CLR_V 0x1 +#define SLC_SLC1_TOKEN0_1TO0_INT_CLR_S 12 +/* SLC_SLC1_TX_OVF_INT_CLR : WO ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_OVF_INT_CLR (BIT(11)) +#define SLC_SLC1_TX_OVF_INT_CLR_M (BIT(11)) +#define SLC_SLC1_TX_OVF_INT_CLR_V 0x1 +#define SLC_SLC1_TX_OVF_INT_CLR_S 11 +/* SLC_SLC1_RX_UDF_INT_CLR : WO ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_UDF_INT_CLR (BIT(10)) +#define SLC_SLC1_RX_UDF_INT_CLR_M (BIT(10)) +#define SLC_SLC1_RX_UDF_INT_CLR_V 0x1 +#define SLC_SLC1_RX_UDF_INT_CLR_S 10 +/* SLC_SLC1_TX_START_INT_CLR : WO ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_START_INT_CLR (BIT(9)) +#define SLC_SLC1_TX_START_INT_CLR_M (BIT(9)) +#define SLC_SLC1_TX_START_INT_CLR_V 0x1 +#define SLC_SLC1_TX_START_INT_CLR_S 9 +/* SLC_SLC1_RX_START_INT_CLR : WO ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_START_INT_CLR (BIT(8)) +#define SLC_SLC1_RX_START_INT_CLR_M (BIT(8)) +#define SLC_SLC1_RX_START_INT_CLR_V 0x1 +#define SLC_SLC1_RX_START_INT_CLR_S 8 +/* SLC_FRHOST_BIT15_INT_CLR : WO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT15_INT_CLR (BIT(7)) +#define SLC_FRHOST_BIT15_INT_CLR_M (BIT(7)) +#define SLC_FRHOST_BIT15_INT_CLR_V 0x1 +#define SLC_FRHOST_BIT15_INT_CLR_S 7 +/* SLC_FRHOST_BIT14_INT_CLR : WO ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT14_INT_CLR (BIT(6)) +#define SLC_FRHOST_BIT14_INT_CLR_M (BIT(6)) +#define SLC_FRHOST_BIT14_INT_CLR_V 0x1 +#define SLC_FRHOST_BIT14_INT_CLR_S 6 +/* SLC_FRHOST_BIT13_INT_CLR : WO ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT13_INT_CLR (BIT(5)) +#define SLC_FRHOST_BIT13_INT_CLR_M (BIT(5)) +#define SLC_FRHOST_BIT13_INT_CLR_V 0x1 +#define SLC_FRHOST_BIT13_INT_CLR_S 5 +/* SLC_FRHOST_BIT12_INT_CLR : WO ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT12_INT_CLR (BIT(4)) +#define SLC_FRHOST_BIT12_INT_CLR_M (BIT(4)) +#define SLC_FRHOST_BIT12_INT_CLR_V 0x1 +#define SLC_FRHOST_BIT12_INT_CLR_S 4 +/* SLC_FRHOST_BIT11_INT_CLR : WO ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT11_INT_CLR (BIT(3)) +#define SLC_FRHOST_BIT11_INT_CLR_M (BIT(3)) +#define SLC_FRHOST_BIT11_INT_CLR_V 0x1 +#define SLC_FRHOST_BIT11_INT_CLR_S 3 +/* SLC_FRHOST_BIT10_INT_CLR : WO ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT10_INT_CLR (BIT(2)) +#define SLC_FRHOST_BIT10_INT_CLR_M (BIT(2)) +#define SLC_FRHOST_BIT10_INT_CLR_V 0x1 +#define SLC_FRHOST_BIT10_INT_CLR_S 2 +/* SLC_FRHOST_BIT9_INT_CLR : WO ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT9_INT_CLR (BIT(1)) +#define SLC_FRHOST_BIT9_INT_CLR_M (BIT(1)) +#define SLC_FRHOST_BIT9_INT_CLR_V 0x1 +#define SLC_FRHOST_BIT9_INT_CLR_S 1 +/* SLC_FRHOST_BIT8_INT_CLR : WO ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT8_INT_CLR (BIT(0)) +#define SLC_FRHOST_BIT8_INT_CLR_M (BIT(0)) +#define SLC_FRHOST_BIT8_INT_CLR_V 0x1 +#define SLC_FRHOST_BIT8_INT_CLR_S 0 + +#define SLC_RX_STATUS_REG (DR_REG_SLC_BASE + 0x24) +/* SLC_SLC1_RX_EMPTY : RO ;bitpos:[17] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_RX_EMPTY (BIT(17)) +#define SLC_SLC1_RX_EMPTY_M (BIT(17)) +#define SLC_SLC1_RX_EMPTY_V 0x1 +#define SLC_SLC1_RX_EMPTY_S 17 +/* SLC_SLC1_RX_FULL : RO ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_FULL (BIT(16)) +#define SLC_SLC1_RX_FULL_M (BIT(16)) +#define SLC_SLC1_RX_FULL_V 0x1 +#define SLC_SLC1_RX_FULL_S 16 +/* SLC_SLC0_RX_EMPTY : RO ;bitpos:[1] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC0_RX_EMPTY (BIT(1)) +#define SLC_SLC0_RX_EMPTY_M (BIT(1)) +#define SLC_SLC0_RX_EMPTY_V 0x1 +#define SLC_SLC0_RX_EMPTY_S 1 +/* SLC_SLC0_RX_FULL : RO ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_FULL (BIT(0)) +#define SLC_SLC0_RX_FULL_M (BIT(0)) +#define SLC_SLC0_RX_FULL_V 0x1 +#define SLC_SLC0_RX_FULL_S 0 + +#define SLC_0RXFIFO_PUSH_REG (DR_REG_SLC_BASE + 0x28) +/* SLC_SLC0_RXFIFO_PUSH : R/W ;bitpos:[16] ;default: 1'h0 ; */ +/*description: */ +#define SLC_SLC0_RXFIFO_PUSH (BIT(16)) +#define SLC_SLC0_RXFIFO_PUSH_M (BIT(16)) +#define SLC_SLC0_RXFIFO_PUSH_V 0x1 +#define SLC_SLC0_RXFIFO_PUSH_S 16 +/* SLC_SLC0_RXFIFO_WDATA : R/W ;bitpos:[8:0] ;default: 9'h0 ; */ +/*description: */ +#define SLC_SLC0_RXFIFO_WDATA 0x000001FF +#define SLC_SLC0_RXFIFO_WDATA_M ((SLC_SLC0_RXFIFO_WDATA_V)<<(SLC_SLC0_RXFIFO_WDATA_S)) +#define SLC_SLC0_RXFIFO_WDATA_V 0x1FF +#define SLC_SLC0_RXFIFO_WDATA_S 0 + +#define SLC_1RXFIFO_PUSH_REG (DR_REG_SLC_BASE + 0x2C) +/* SLC_SLC1_RXFIFO_PUSH : R/W ;bitpos:[16] ;default: 1'h0 ; */ +/*description: */ +#define SLC_SLC1_RXFIFO_PUSH (BIT(16)) +#define SLC_SLC1_RXFIFO_PUSH_M (BIT(16)) +#define SLC_SLC1_RXFIFO_PUSH_V 0x1 +#define SLC_SLC1_RXFIFO_PUSH_S 16 +/* SLC_SLC1_RXFIFO_WDATA : R/W ;bitpos:[8:0] ;default: 9'h0 ; */ +/*description: */ +#define SLC_SLC1_RXFIFO_WDATA 0x000001FF +#define SLC_SLC1_RXFIFO_WDATA_M ((SLC_SLC1_RXFIFO_WDATA_V)<<(SLC_SLC1_RXFIFO_WDATA_S)) +#define SLC_SLC1_RXFIFO_WDATA_V 0x1FF +#define SLC_SLC1_RXFIFO_WDATA_S 0 + +#define SLC_TX_STATUS_REG (DR_REG_SLC_BASE + 0x30) +/* SLC_SLC1_TX_EMPTY : RO ;bitpos:[17] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_TX_EMPTY (BIT(17)) +#define SLC_SLC1_TX_EMPTY_M (BIT(17)) +#define SLC_SLC1_TX_EMPTY_V 0x1 +#define SLC_SLC1_TX_EMPTY_S 17 +/* SLC_SLC1_TX_FULL : RO ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_FULL (BIT(16)) +#define SLC_SLC1_TX_FULL_M (BIT(16)) +#define SLC_SLC1_TX_FULL_V 0x1 +#define SLC_SLC1_TX_FULL_S 16 +/* SLC_SLC0_TX_EMPTY : RO ;bitpos:[1] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC0_TX_EMPTY (BIT(1)) +#define SLC_SLC0_TX_EMPTY_M (BIT(1)) +#define SLC_SLC0_TX_EMPTY_V 0x1 +#define SLC_SLC0_TX_EMPTY_S 1 +/* SLC_SLC0_TX_FULL : RO ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_FULL (BIT(0)) +#define SLC_SLC0_TX_FULL_M (BIT(0)) +#define SLC_SLC0_TX_FULL_V 0x1 +#define SLC_SLC0_TX_FULL_S 0 + +#define SLC_0TXFIFO_POP_REG (DR_REG_SLC_BASE + 0x34) +/* SLC_SLC0_TXFIFO_POP : R/W ;bitpos:[16] ;default: 1'h0 ; */ +/*description: */ +#define SLC_SLC0_TXFIFO_POP (BIT(16)) +#define SLC_SLC0_TXFIFO_POP_M (BIT(16)) +#define SLC_SLC0_TXFIFO_POP_V 0x1 +#define SLC_SLC0_TXFIFO_POP_S 16 +/* SLC_SLC0_TXFIFO_RDATA : RO ;bitpos:[10:0] ;default: 11'h0 ; */ +/*description: */ +#define SLC_SLC0_TXFIFO_RDATA 0x000007FF +#define SLC_SLC0_TXFIFO_RDATA_M ((SLC_SLC0_TXFIFO_RDATA_V)<<(SLC_SLC0_TXFIFO_RDATA_S)) +#define SLC_SLC0_TXFIFO_RDATA_V 0x7FF +#define SLC_SLC0_TXFIFO_RDATA_S 0 + +#define SLC_1TXFIFO_POP_REG (DR_REG_SLC_BASE + 0x38) +/* SLC_SLC1_TXFIFO_POP : R/W ;bitpos:[16] ;default: 1'h0 ; */ +/*description: */ +#define SLC_SLC1_TXFIFO_POP (BIT(16)) +#define SLC_SLC1_TXFIFO_POP_M (BIT(16)) +#define SLC_SLC1_TXFIFO_POP_V 0x1 +#define SLC_SLC1_TXFIFO_POP_S 16 +/* SLC_SLC1_TXFIFO_RDATA : RO ;bitpos:[10:0] ;default: 11'h0 ; */ +/*description: */ +#define SLC_SLC1_TXFIFO_RDATA 0x000007FF +#define SLC_SLC1_TXFIFO_RDATA_M ((SLC_SLC1_TXFIFO_RDATA_V)<<(SLC_SLC1_TXFIFO_RDATA_S)) +#define SLC_SLC1_TXFIFO_RDATA_V 0x7FF +#define SLC_SLC1_TXFIFO_RDATA_S 0 + +#define SLC_0RX_LINK_REG (DR_REG_SLC_BASE + 0x3C) +/* SLC_SLC0_RXLINK_PARK : RO ;bitpos:[31] ;default: 1'h0 ; */ +/*description: */ +#define SLC_SLC0_RXLINK_PARK (BIT(31)) +#define SLC_SLC0_RXLINK_PARK_M (BIT(31)) +#define SLC_SLC0_RXLINK_PARK_V 0x1 +#define SLC_SLC0_RXLINK_PARK_S 31 +/* SLC_SLC0_RXLINK_RESTART : R/W ;bitpos:[30] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RXLINK_RESTART (BIT(30)) +#define SLC_SLC0_RXLINK_RESTART_M (BIT(30)) +#define SLC_SLC0_RXLINK_RESTART_V 0x1 +#define SLC_SLC0_RXLINK_RESTART_S 30 +/* SLC_SLC0_RXLINK_START : R/W ;bitpos:[29] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RXLINK_START (BIT(29)) +#define SLC_SLC0_RXLINK_START_M (BIT(29)) +#define SLC_SLC0_RXLINK_START_V 0x1 +#define SLC_SLC0_RXLINK_START_S 29 +/* SLC_SLC0_RXLINK_STOP : R/W ;bitpos:[28] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RXLINK_STOP (BIT(28)) +#define SLC_SLC0_RXLINK_STOP_M (BIT(28)) +#define SLC_SLC0_RXLINK_STOP_V 0x1 +#define SLC_SLC0_RXLINK_STOP_S 28 +/* SLC_SLC0_RXLINK_ADDR : R/W ;bitpos:[19:0] ;default: 20'h0 ; */ +/*description: */ +#define SLC_SLC0_RXLINK_ADDR 0x000FFFFF +#define SLC_SLC0_RXLINK_ADDR_M ((SLC_SLC0_RXLINK_ADDR_V)<<(SLC_SLC0_RXLINK_ADDR_S)) +#define SLC_SLC0_RXLINK_ADDR_V 0xFFFFF +#define SLC_SLC0_RXLINK_ADDR_S 0 + +#define SLC_0TX_LINK_REG (DR_REG_SLC_BASE + 0x40) +/* SLC_SLC0_TXLINK_PARK : RO ;bitpos:[31] ;default: 1'h0 ; */ +/*description: */ +#define SLC_SLC0_TXLINK_PARK (BIT(31)) +#define SLC_SLC0_TXLINK_PARK_M (BIT(31)) +#define SLC_SLC0_TXLINK_PARK_V 0x1 +#define SLC_SLC0_TXLINK_PARK_S 31 +/* SLC_SLC0_TXLINK_RESTART : R/W ;bitpos:[30] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TXLINK_RESTART (BIT(30)) +#define SLC_SLC0_TXLINK_RESTART_M (BIT(30)) +#define SLC_SLC0_TXLINK_RESTART_V 0x1 +#define SLC_SLC0_TXLINK_RESTART_S 30 +/* SLC_SLC0_TXLINK_START : R/W ;bitpos:[29] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TXLINK_START (BIT(29)) +#define SLC_SLC0_TXLINK_START_M (BIT(29)) +#define SLC_SLC0_TXLINK_START_V 0x1 +#define SLC_SLC0_TXLINK_START_S 29 +/* SLC_SLC0_TXLINK_STOP : R/W ;bitpos:[28] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TXLINK_STOP (BIT(28)) +#define SLC_SLC0_TXLINK_STOP_M (BIT(28)) +#define SLC_SLC0_TXLINK_STOP_V 0x1 +#define SLC_SLC0_TXLINK_STOP_S 28 +/* SLC_SLC0_TXLINK_ADDR : R/W ;bitpos:[19:0] ;default: 20'h0 ; */ +/*description: */ +#define SLC_SLC0_TXLINK_ADDR 0x000FFFFF +#define SLC_SLC0_TXLINK_ADDR_M ((SLC_SLC0_TXLINK_ADDR_V)<<(SLC_SLC0_TXLINK_ADDR_S)) +#define SLC_SLC0_TXLINK_ADDR_V 0xFFFFF +#define SLC_SLC0_TXLINK_ADDR_S 0 + +#define SLC_1RX_LINK_REG (DR_REG_SLC_BASE + 0x44) +/* SLC_SLC1_RXLINK_PARK : RO ;bitpos:[31] ;default: 1'h0 ; */ +/*description: */ +#define SLC_SLC1_RXLINK_PARK (BIT(31)) +#define SLC_SLC1_RXLINK_PARK_M (BIT(31)) +#define SLC_SLC1_RXLINK_PARK_V 0x1 +#define SLC_SLC1_RXLINK_PARK_S 31 +/* SLC_SLC1_RXLINK_RESTART : R/W ;bitpos:[30] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RXLINK_RESTART (BIT(30)) +#define SLC_SLC1_RXLINK_RESTART_M (BIT(30)) +#define SLC_SLC1_RXLINK_RESTART_V 0x1 +#define SLC_SLC1_RXLINK_RESTART_S 30 +/* SLC_SLC1_RXLINK_START : R/W ;bitpos:[29] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RXLINK_START (BIT(29)) +#define SLC_SLC1_RXLINK_START_M (BIT(29)) +#define SLC_SLC1_RXLINK_START_V 0x1 +#define SLC_SLC1_RXLINK_START_S 29 +/* SLC_SLC1_RXLINK_STOP : R/W ;bitpos:[28] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RXLINK_STOP (BIT(28)) +#define SLC_SLC1_RXLINK_STOP_M (BIT(28)) +#define SLC_SLC1_RXLINK_STOP_V 0x1 +#define SLC_SLC1_RXLINK_STOP_S 28 +/* SLC_SLC1_BT_PACKET : R/W ;bitpos:[20] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_BT_PACKET (BIT(20)) +#define SLC_SLC1_BT_PACKET_M (BIT(20)) +#define SLC_SLC1_BT_PACKET_V 0x1 +#define SLC_SLC1_BT_PACKET_S 20 +/* SLC_SLC1_RXLINK_ADDR : R/W ;bitpos:[19:0] ;default: 20'h0 ; */ +/*description: */ +#define SLC_SLC1_RXLINK_ADDR 0x000FFFFF +#define SLC_SLC1_RXLINK_ADDR_M ((SLC_SLC1_RXLINK_ADDR_V)<<(SLC_SLC1_RXLINK_ADDR_S)) +#define SLC_SLC1_RXLINK_ADDR_V 0xFFFFF +#define SLC_SLC1_RXLINK_ADDR_S 0 + +#define SLC_1TX_LINK_REG (DR_REG_SLC_BASE + 0x48) +/* SLC_SLC1_TXLINK_PARK : RO ;bitpos:[31] ;default: 1'h0 ; */ +/*description: */ +#define SLC_SLC1_TXLINK_PARK (BIT(31)) +#define SLC_SLC1_TXLINK_PARK_M (BIT(31)) +#define SLC_SLC1_TXLINK_PARK_V 0x1 +#define SLC_SLC1_TXLINK_PARK_S 31 +/* SLC_SLC1_TXLINK_RESTART : R/W ;bitpos:[30] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TXLINK_RESTART (BIT(30)) +#define SLC_SLC1_TXLINK_RESTART_M (BIT(30)) +#define SLC_SLC1_TXLINK_RESTART_V 0x1 +#define SLC_SLC1_TXLINK_RESTART_S 30 +/* SLC_SLC1_TXLINK_START : R/W ;bitpos:[29] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TXLINK_START (BIT(29)) +#define SLC_SLC1_TXLINK_START_M (BIT(29)) +#define SLC_SLC1_TXLINK_START_V 0x1 +#define SLC_SLC1_TXLINK_START_S 29 +/* SLC_SLC1_TXLINK_STOP : R/W ;bitpos:[28] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TXLINK_STOP (BIT(28)) +#define SLC_SLC1_TXLINK_STOP_M (BIT(28)) +#define SLC_SLC1_TXLINK_STOP_V 0x1 +#define SLC_SLC1_TXLINK_STOP_S 28 +/* SLC_SLC1_TXLINK_ADDR : R/W ;bitpos:[19:0] ;default: 20'h0 ; */ +/*description: */ +#define SLC_SLC1_TXLINK_ADDR 0x000FFFFF +#define SLC_SLC1_TXLINK_ADDR_M ((SLC_SLC1_TXLINK_ADDR_V)<<(SLC_SLC1_TXLINK_ADDR_S)) +#define SLC_SLC1_TXLINK_ADDR_V 0xFFFFF +#define SLC_SLC1_TXLINK_ADDR_S 0 + +#define SLC_INTVEC_TOHOST_REG (DR_REG_SLC_BASE + 0x4C) +/* SLC_SLC1_TOHOST_INTVEC : WO ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define SLC_SLC1_TOHOST_INTVEC 0x000000FF +#define SLC_SLC1_TOHOST_INTVEC_M ((SLC_SLC1_TOHOST_INTVEC_V)<<(SLC_SLC1_TOHOST_INTVEC_S)) +#define SLC_SLC1_TOHOST_INTVEC_V 0xFF +#define SLC_SLC1_TOHOST_INTVEC_S 16 +/* SLC_SLC0_TOHOST_INTVEC : WO ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define SLC_SLC0_TOHOST_INTVEC 0x000000FF +#define SLC_SLC0_TOHOST_INTVEC_M ((SLC_SLC0_TOHOST_INTVEC_V)<<(SLC_SLC0_TOHOST_INTVEC_S)) +#define SLC_SLC0_TOHOST_INTVEC_V 0xFF +#define SLC_SLC0_TOHOST_INTVEC_S 0 + +#define SLC_0TOKEN0_REG (DR_REG_SLC_BASE + 0x50) +/* SLC_SLC0_TOKEN0 : RO ;bitpos:[27:16] ;default: 12'h0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN0 0x00000FFF +#define SLC_SLC0_TOKEN0_M ((SLC_SLC0_TOKEN0_V)<<(SLC_SLC0_TOKEN0_S)) +#define SLC_SLC0_TOKEN0_V 0xFFF +#define SLC_SLC0_TOKEN0_S 16 +/* SLC_SLC0_TOKEN0_INC_MORE : WO ;bitpos:[14] ;default: 1'h0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN0_INC_MORE (BIT(14)) +#define SLC_SLC0_TOKEN0_INC_MORE_M (BIT(14)) +#define SLC_SLC0_TOKEN0_INC_MORE_V 0x1 +#define SLC_SLC0_TOKEN0_INC_MORE_S 14 +/* SLC_SLC0_TOKEN0_INC : WO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN0_INC (BIT(13)) +#define SLC_SLC0_TOKEN0_INC_M (BIT(13)) +#define SLC_SLC0_TOKEN0_INC_V 0x1 +#define SLC_SLC0_TOKEN0_INC_S 13 +/* SLC_SLC0_TOKEN0_WR : WO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN0_WR (BIT(12)) +#define SLC_SLC0_TOKEN0_WR_M (BIT(12)) +#define SLC_SLC0_TOKEN0_WR_V 0x1 +#define SLC_SLC0_TOKEN0_WR_S 12 +/* SLC_SLC0_TOKEN0_WDATA : WO ;bitpos:[11:0] ;default: 12'h0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN0_WDATA 0x00000FFF +#define SLC_SLC0_TOKEN0_WDATA_M ((SLC_SLC0_TOKEN0_WDATA_V)<<(SLC_SLC0_TOKEN0_WDATA_S)) +#define SLC_SLC0_TOKEN0_WDATA_V 0xFFF +#define SLC_SLC0_TOKEN0_WDATA_S 0 + +#define SLC_0TOKEN1_REG (DR_REG_SLC_BASE + 0x54) +/* SLC_SLC0_TOKEN1 : RO ;bitpos:[27:16] ;default: 12'h0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN1 0x00000FFF +#define SLC_SLC0_TOKEN1_M ((SLC_SLC0_TOKEN1_V)<<(SLC_SLC0_TOKEN1_S)) +#define SLC_SLC0_TOKEN1_V 0xFFF +#define SLC_SLC0_TOKEN1_S 16 +/* SLC_SLC0_TOKEN1_INC_MORE : WO ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN1_INC_MORE (BIT(14)) +#define SLC_SLC0_TOKEN1_INC_MORE_M (BIT(14)) +#define SLC_SLC0_TOKEN1_INC_MORE_V 0x1 +#define SLC_SLC0_TOKEN1_INC_MORE_S 14 +/* SLC_SLC0_TOKEN1_INC : WO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN1_INC (BIT(13)) +#define SLC_SLC0_TOKEN1_INC_M (BIT(13)) +#define SLC_SLC0_TOKEN1_INC_V 0x1 +#define SLC_SLC0_TOKEN1_INC_S 13 +/* SLC_SLC0_TOKEN1_WR : WO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN1_WR (BIT(12)) +#define SLC_SLC0_TOKEN1_WR_M (BIT(12)) +#define SLC_SLC0_TOKEN1_WR_V 0x1 +#define SLC_SLC0_TOKEN1_WR_S 12 +/* SLC_SLC0_TOKEN1_WDATA : WO ;bitpos:[11:0] ;default: 12'h0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN1_WDATA 0x00000FFF +#define SLC_SLC0_TOKEN1_WDATA_M ((SLC_SLC0_TOKEN1_WDATA_V)<<(SLC_SLC0_TOKEN1_WDATA_S)) +#define SLC_SLC0_TOKEN1_WDATA_V 0xFFF +#define SLC_SLC0_TOKEN1_WDATA_S 0 + +#define SLC_1TOKEN0_REG (DR_REG_SLC_BASE + 0x58) +/* SLC_SLC1_TOKEN0 : RO ;bitpos:[27:16] ;default: 12'h0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN0 0x00000FFF +#define SLC_SLC1_TOKEN0_M ((SLC_SLC1_TOKEN0_V)<<(SLC_SLC1_TOKEN0_S)) +#define SLC_SLC1_TOKEN0_V 0xFFF +#define SLC_SLC1_TOKEN0_S 16 +/* SLC_SLC1_TOKEN0_INC_MORE : WO ;bitpos:[14] ;default: 1'h0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN0_INC_MORE (BIT(14)) +#define SLC_SLC1_TOKEN0_INC_MORE_M (BIT(14)) +#define SLC_SLC1_TOKEN0_INC_MORE_V 0x1 +#define SLC_SLC1_TOKEN0_INC_MORE_S 14 +/* SLC_SLC1_TOKEN0_INC : WO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN0_INC (BIT(13)) +#define SLC_SLC1_TOKEN0_INC_M (BIT(13)) +#define SLC_SLC1_TOKEN0_INC_V 0x1 +#define SLC_SLC1_TOKEN0_INC_S 13 +/* SLC_SLC1_TOKEN0_WR : WO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN0_WR (BIT(12)) +#define SLC_SLC1_TOKEN0_WR_M (BIT(12)) +#define SLC_SLC1_TOKEN0_WR_V 0x1 +#define SLC_SLC1_TOKEN0_WR_S 12 +/* SLC_SLC1_TOKEN0_WDATA : WO ;bitpos:[11:0] ;default: 12'h0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN0_WDATA 0x00000FFF +#define SLC_SLC1_TOKEN0_WDATA_M ((SLC_SLC1_TOKEN0_WDATA_V)<<(SLC_SLC1_TOKEN0_WDATA_S)) +#define SLC_SLC1_TOKEN0_WDATA_V 0xFFF +#define SLC_SLC1_TOKEN0_WDATA_S 0 + +#define SLC_1TOKEN1_REG (DR_REG_SLC_BASE + 0x5C) +/* SLC_SLC1_TOKEN1 : RO ;bitpos:[27:16] ;default: 12'h0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN1 0x00000FFF +#define SLC_SLC1_TOKEN1_M ((SLC_SLC1_TOKEN1_V)<<(SLC_SLC1_TOKEN1_S)) +#define SLC_SLC1_TOKEN1_V 0xFFF +#define SLC_SLC1_TOKEN1_S 16 +/* SLC_SLC1_TOKEN1_INC_MORE : WO ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN1_INC_MORE (BIT(14)) +#define SLC_SLC1_TOKEN1_INC_MORE_M (BIT(14)) +#define SLC_SLC1_TOKEN1_INC_MORE_V 0x1 +#define SLC_SLC1_TOKEN1_INC_MORE_S 14 +/* SLC_SLC1_TOKEN1_INC : WO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN1_INC (BIT(13)) +#define SLC_SLC1_TOKEN1_INC_M (BIT(13)) +#define SLC_SLC1_TOKEN1_INC_V 0x1 +#define SLC_SLC1_TOKEN1_INC_S 13 +/* SLC_SLC1_TOKEN1_WR : WO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN1_WR (BIT(12)) +#define SLC_SLC1_TOKEN1_WR_M (BIT(12)) +#define SLC_SLC1_TOKEN1_WR_V 0x1 +#define SLC_SLC1_TOKEN1_WR_S 12 +/* SLC_SLC1_TOKEN1_WDATA : WO ;bitpos:[11:0] ;default: 12'h0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN1_WDATA 0x00000FFF +#define SLC_SLC1_TOKEN1_WDATA_M ((SLC_SLC1_TOKEN1_WDATA_V)<<(SLC_SLC1_TOKEN1_WDATA_S)) +#define SLC_SLC1_TOKEN1_WDATA_V 0xFFF +#define SLC_SLC1_TOKEN1_WDATA_S 0 + +#define SLC_CONF1_REG (DR_REG_SLC_BASE + 0x60) +/* SLC_CLK_EN : R/W ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define SLC_CLK_EN (BIT(22)) +#define SLC_CLK_EN_M (BIT(22)) +#define SLC_CLK_EN_V 0x1 +#define SLC_CLK_EN_S 22 +/* SLC_SLC1_RX_STITCH_EN : R/W ;bitpos:[21] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_RX_STITCH_EN (BIT(21)) +#define SLC_SLC1_RX_STITCH_EN_M (BIT(21)) +#define SLC_SLC1_RX_STITCH_EN_V 0x1 +#define SLC_SLC1_RX_STITCH_EN_S 21 +/* SLC_SLC1_TX_STITCH_EN : R/W ;bitpos:[20] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_TX_STITCH_EN (BIT(20)) +#define SLC_SLC1_TX_STITCH_EN_M (BIT(20)) +#define SLC_SLC1_TX_STITCH_EN_V 0x1 +#define SLC_SLC1_TX_STITCH_EN_S 20 +/* SLC_HOST_INT_LEVEL_SEL : R/W ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define SLC_HOST_INT_LEVEL_SEL (BIT(19)) +#define SLC_HOST_INT_LEVEL_SEL_M (BIT(19)) +#define SLC_HOST_INT_LEVEL_SEL_V 0x1 +#define SLC_HOST_INT_LEVEL_SEL_S 19 +/* SLC_SLC1_RX_CHECK_SUM_EN : R/W ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_CHECK_SUM_EN (BIT(18)) +#define SLC_SLC1_RX_CHECK_SUM_EN_M (BIT(18)) +#define SLC_SLC1_RX_CHECK_SUM_EN_V 0x1 +#define SLC_SLC1_RX_CHECK_SUM_EN_S 18 +/* SLC_SLC1_TX_CHECK_SUM_EN : R/W ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_CHECK_SUM_EN (BIT(17)) +#define SLC_SLC1_TX_CHECK_SUM_EN_M (BIT(17)) +#define SLC_SLC1_TX_CHECK_SUM_EN_V 0x1 +#define SLC_SLC1_TX_CHECK_SUM_EN_S 17 +/* SLC_SLC1_CHECK_OWNER : R/W ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_CHECK_OWNER (BIT(16)) +#define SLC_SLC1_CHECK_OWNER_M (BIT(16)) +#define SLC_SLC1_CHECK_OWNER_V 0x1 +#define SLC_SLC1_CHECK_OWNER_S 16 +/* SLC_SLC0_RX_STITCH_EN : R/W ;bitpos:[6] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC0_RX_STITCH_EN (BIT(6)) +#define SLC_SLC0_RX_STITCH_EN_M (BIT(6)) +#define SLC_SLC0_RX_STITCH_EN_V 0x1 +#define SLC_SLC0_RX_STITCH_EN_S 6 +/* SLC_SLC0_TX_STITCH_EN : R/W ;bitpos:[5] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC0_TX_STITCH_EN (BIT(5)) +#define SLC_SLC0_TX_STITCH_EN_M (BIT(5)) +#define SLC_SLC0_TX_STITCH_EN_V 0x1 +#define SLC_SLC0_TX_STITCH_EN_S 5 +/* SLC_SLC0_LEN_AUTO_CLR : R/W ;bitpos:[4] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC0_LEN_AUTO_CLR (BIT(4)) +#define SLC_SLC0_LEN_AUTO_CLR_M (BIT(4)) +#define SLC_SLC0_LEN_AUTO_CLR_V 0x1 +#define SLC_SLC0_LEN_AUTO_CLR_S 4 +/* SLC_CMD_HOLD_EN : R/W ;bitpos:[3] ;default: 1'b1 ; */ +/*description: */ +#define SLC_CMD_HOLD_EN (BIT(3)) +#define SLC_CMD_HOLD_EN_M (BIT(3)) +#define SLC_CMD_HOLD_EN_V 0x1 +#define SLC_CMD_HOLD_EN_S 3 +/* SLC_SLC0_RX_CHECK_SUM_EN : R/W ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_CHECK_SUM_EN (BIT(2)) +#define SLC_SLC0_RX_CHECK_SUM_EN_M (BIT(2)) +#define SLC_SLC0_RX_CHECK_SUM_EN_V 0x1 +#define SLC_SLC0_RX_CHECK_SUM_EN_S 2 +/* SLC_SLC0_TX_CHECK_SUM_EN : R/W ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_CHECK_SUM_EN (BIT(1)) +#define SLC_SLC0_TX_CHECK_SUM_EN_M (BIT(1)) +#define SLC_SLC0_TX_CHECK_SUM_EN_V 0x1 +#define SLC_SLC0_TX_CHECK_SUM_EN_S 1 +/* SLC_SLC0_CHECK_OWNER : R/W ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_CHECK_OWNER (BIT(0)) +#define SLC_SLC0_CHECK_OWNER_M (BIT(0)) +#define SLC_SLC0_CHECK_OWNER_V 0x1 +#define SLC_SLC0_CHECK_OWNER_S 0 + +#define SLC_0_STATE0_REG (DR_REG_SLC_BASE + 0x64) +/* SLC_SLC0_STATE0 : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC0_STATE0 0xFFFFFFFF +#define SLC_SLC0_STATE0_M ((SLC_SLC0_STATE0_V)<<(SLC_SLC0_STATE0_S)) +#define SLC_SLC0_STATE0_V 0xFFFFFFFF +#define SLC_SLC0_STATE0_S 0 + +#define SLC_0_STATE1_REG (DR_REG_SLC_BASE + 0x68) +/* SLC_SLC0_STATE1 : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC0_STATE1 0xFFFFFFFF +#define SLC_SLC0_STATE1_M ((SLC_SLC0_STATE1_V)<<(SLC_SLC0_STATE1_S)) +#define SLC_SLC0_STATE1_V 0xFFFFFFFF +#define SLC_SLC0_STATE1_S 0 + +#define SLC_1_STATE0_REG (DR_REG_SLC_BASE + 0x6C) +/* SLC_SLC1_STATE0 : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC1_STATE0 0xFFFFFFFF +#define SLC_SLC1_STATE0_M ((SLC_SLC1_STATE0_V)<<(SLC_SLC1_STATE0_S)) +#define SLC_SLC1_STATE0_V 0xFFFFFFFF +#define SLC_SLC1_STATE0_S 0 + +#define SLC_1_STATE1_REG (DR_REG_SLC_BASE + 0x70) +/* SLC_SLC1_STATE1 : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC1_STATE1 0xFFFFFFFF +#define SLC_SLC1_STATE1_M ((SLC_SLC1_STATE1_V)<<(SLC_SLC1_STATE1_S)) +#define SLC_SLC1_STATE1_V 0xFFFFFFFF +#define SLC_SLC1_STATE1_S 0 + +#define SLC_BRIDGE_CONF_REG (DR_REG_SLC_BASE + 0x74) +/* SLC_TX_PUSH_IDLE_NUM : R/W ;bitpos:[31:16] ;default: 16'ha ; */ +/*description: */ +#define SLC_TX_PUSH_IDLE_NUM 0x0000FFFF +#define SLC_TX_PUSH_IDLE_NUM_M ((SLC_TX_PUSH_IDLE_NUM_V)<<(SLC_TX_PUSH_IDLE_NUM_S)) +#define SLC_TX_PUSH_IDLE_NUM_V 0xFFFF +#define SLC_TX_PUSH_IDLE_NUM_S 16 +/* SLC_SLC1_TX_DUMMY_MODE : R/W ;bitpos:[14] ;default: 1'h1 ; */ +/*description: */ +#define SLC_SLC1_TX_DUMMY_MODE (BIT(14)) +#define SLC_SLC1_TX_DUMMY_MODE_M (BIT(14)) +#define SLC_SLC1_TX_DUMMY_MODE_V 0x1 +#define SLC_SLC1_TX_DUMMY_MODE_S 14 +/* SLC_HDA_MAP_128K : R/W ;bitpos:[13] ;default: 1'h1 ; */ +/*description: */ +#define SLC_HDA_MAP_128K (BIT(13)) +#define SLC_HDA_MAP_128K_M (BIT(13)) +#define SLC_HDA_MAP_128K_V 0x1 +#define SLC_HDA_MAP_128K_S 13 +/* SLC_SLC0_TX_DUMMY_MODE : R/W ;bitpos:[12] ;default: 1'h1 ; */ +/*description: */ +#define SLC_SLC0_TX_DUMMY_MODE (BIT(12)) +#define SLC_SLC0_TX_DUMMY_MODE_M (BIT(12)) +#define SLC_SLC0_TX_DUMMY_MODE_V 0x1 +#define SLC_SLC0_TX_DUMMY_MODE_S 12 +/* SLC_FIFO_MAP_ENA : R/W ;bitpos:[11:8] ;default: 4'h7 ; */ +/*description: */ +#define SLC_FIFO_MAP_ENA 0x0000000F +#define SLC_FIFO_MAP_ENA_M ((SLC_FIFO_MAP_ENA_V)<<(SLC_FIFO_MAP_ENA_S)) +#define SLC_FIFO_MAP_ENA_V 0xF +#define SLC_FIFO_MAP_ENA_S 8 +/* SLC_TXEOF_ENA : R/W ;bitpos:[5:0] ;default: 6'h20 ; */ +/*description: */ +#define SLC_TXEOF_ENA 0x0000003F +#define SLC_TXEOF_ENA_M ((SLC_TXEOF_ENA_V)<<(SLC_TXEOF_ENA_S)) +#define SLC_TXEOF_ENA_V 0x3F +#define SLC_TXEOF_ENA_S 0 + +#define SLC_0_TO_EOF_DES_ADDR_REG (DR_REG_SLC_BASE + 0x78) +/* SLC_SLC0_TO_EOF_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC0_TO_EOF_DES_ADDR 0xFFFFFFFF +#define SLC_SLC0_TO_EOF_DES_ADDR_M ((SLC_SLC0_TO_EOF_DES_ADDR_V)<<(SLC_SLC0_TO_EOF_DES_ADDR_S)) +#define SLC_SLC0_TO_EOF_DES_ADDR_V 0xFFFFFFFF +#define SLC_SLC0_TO_EOF_DES_ADDR_S 0 + +#define SLC_0_TX_EOF_DES_ADDR_REG (DR_REG_SLC_BASE + 0x7C) +/* SLC_SLC0_TX_SUC_EOF_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC0_TX_SUC_EOF_DES_ADDR 0xFFFFFFFF +#define SLC_SLC0_TX_SUC_EOF_DES_ADDR_M ((SLC_SLC0_TX_SUC_EOF_DES_ADDR_V)<<(SLC_SLC0_TX_SUC_EOF_DES_ADDR_S)) +#define SLC_SLC0_TX_SUC_EOF_DES_ADDR_V 0xFFFFFFFF +#define SLC_SLC0_TX_SUC_EOF_DES_ADDR_S 0 + +#define SLC_0_TO_EOF_BFR_DES_ADDR_REG (DR_REG_SLC_BASE + 0x80) +/* SLC_SLC0_TO_EOF_BFR_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC0_TO_EOF_BFR_DES_ADDR 0xFFFFFFFF +#define SLC_SLC0_TO_EOF_BFR_DES_ADDR_M ((SLC_SLC0_TO_EOF_BFR_DES_ADDR_V)<<(SLC_SLC0_TO_EOF_BFR_DES_ADDR_S)) +#define SLC_SLC0_TO_EOF_BFR_DES_ADDR_V 0xFFFFFFFF +#define SLC_SLC0_TO_EOF_BFR_DES_ADDR_S 0 + +#define SLC_1_TO_EOF_DES_ADDR_REG (DR_REG_SLC_BASE + 0x84) +/* SLC_SLC1_TO_EOF_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC1_TO_EOF_DES_ADDR 0xFFFFFFFF +#define SLC_SLC1_TO_EOF_DES_ADDR_M ((SLC_SLC1_TO_EOF_DES_ADDR_V)<<(SLC_SLC1_TO_EOF_DES_ADDR_S)) +#define SLC_SLC1_TO_EOF_DES_ADDR_V 0xFFFFFFFF +#define SLC_SLC1_TO_EOF_DES_ADDR_S 0 + +#define SLC_1_TX_EOF_DES_ADDR_REG (DR_REG_SLC_BASE + 0x88) +/* SLC_SLC1_TX_SUC_EOF_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC1_TX_SUC_EOF_DES_ADDR 0xFFFFFFFF +#define SLC_SLC1_TX_SUC_EOF_DES_ADDR_M ((SLC_SLC1_TX_SUC_EOF_DES_ADDR_V)<<(SLC_SLC1_TX_SUC_EOF_DES_ADDR_S)) +#define SLC_SLC1_TX_SUC_EOF_DES_ADDR_V 0xFFFFFFFF +#define SLC_SLC1_TX_SUC_EOF_DES_ADDR_S 0 + +#define SLC_1_TO_EOF_BFR_DES_ADDR_REG (DR_REG_SLC_BASE + 0x8C) +/* SLC_SLC1_TO_EOF_BFR_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC1_TO_EOF_BFR_DES_ADDR 0xFFFFFFFF +#define SLC_SLC1_TO_EOF_BFR_DES_ADDR_M ((SLC_SLC1_TO_EOF_BFR_DES_ADDR_V)<<(SLC_SLC1_TO_EOF_BFR_DES_ADDR_S)) +#define SLC_SLC1_TO_EOF_BFR_DES_ADDR_V 0xFFFFFFFF +#define SLC_SLC1_TO_EOF_BFR_DES_ADDR_S 0 + +#define SLC_AHB_TEST_REG (DR_REG_SLC_BASE + 0x90) +/* SLC_AHB_TESTADDR : R/W ;bitpos:[5:4] ;default: 2'b0 ; */ +/*description: */ +#define SLC_AHB_TESTADDR 0x00000003 +#define SLC_AHB_TESTADDR_M ((SLC_AHB_TESTADDR_V)<<(SLC_AHB_TESTADDR_S)) +#define SLC_AHB_TESTADDR_V 0x3 +#define SLC_AHB_TESTADDR_S 4 +/* SLC_AHB_TESTMODE : R/W ;bitpos:[2:0] ;default: 3'b0 ; */ +/*description: */ +#define SLC_AHB_TESTMODE 0x00000007 +#define SLC_AHB_TESTMODE_M ((SLC_AHB_TESTMODE_V)<<(SLC_AHB_TESTMODE_S)) +#define SLC_AHB_TESTMODE_V 0x7 +#define SLC_AHB_TESTMODE_S 0 + +#define SLC_SDIO_ST_REG (DR_REG_SLC_BASE + 0x94) +/* SLC_FUNC2_ACC_STATE : RO ;bitpos:[28:24] ;default: 5'b0 ; */ +/*description: */ +#define SLC_FUNC2_ACC_STATE 0x0000001F +#define SLC_FUNC2_ACC_STATE_M ((SLC_FUNC2_ACC_STATE_V)<<(SLC_FUNC2_ACC_STATE_S)) +#define SLC_FUNC2_ACC_STATE_V 0x1F +#define SLC_FUNC2_ACC_STATE_S 24 +/* SLC_FUNC1_ACC_STATE : RO ;bitpos:[20:16] ;default: 5'b0 ; */ +/*description: */ +#define SLC_FUNC1_ACC_STATE 0x0000001F +#define SLC_FUNC1_ACC_STATE_M ((SLC_FUNC1_ACC_STATE_V)<<(SLC_FUNC1_ACC_STATE_S)) +#define SLC_FUNC1_ACC_STATE_V 0x1F +#define SLC_FUNC1_ACC_STATE_S 16 +/* SLC_BUS_ST : RO ;bitpos:[14:12] ;default: 3'b0 ; */ +/*description: */ +#define SLC_BUS_ST 0x00000007 +#define SLC_BUS_ST_M ((SLC_BUS_ST_V)<<(SLC_BUS_ST_S)) +#define SLC_BUS_ST_V 0x7 +#define SLC_BUS_ST_S 12 +/* SLC_SDIO_WAKEUP : RO ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SDIO_WAKEUP (BIT(8)) +#define SLC_SDIO_WAKEUP_M (BIT(8)) +#define SLC_SDIO_WAKEUP_V 0x1 +#define SLC_SDIO_WAKEUP_S 8 +/* SLC_FUNC_ST : RO ;bitpos:[7:4] ;default: 4'b0 ; */ +/*description: */ +#define SLC_FUNC_ST 0x0000000F +#define SLC_FUNC_ST_M ((SLC_FUNC_ST_V)<<(SLC_FUNC_ST_S)) +#define SLC_FUNC_ST_V 0xF +#define SLC_FUNC_ST_S 4 +/* SLC_CMD_ST : RO ;bitpos:[2:0] ;default: 3'b0 ; */ +/*description: */ +#define SLC_CMD_ST 0x00000007 +#define SLC_CMD_ST_M ((SLC_CMD_ST_V)<<(SLC_CMD_ST_S)) +#define SLC_CMD_ST_V 0x7 +#define SLC_CMD_ST_S 0 + +#define SLC_RX_DSCR_CONF_REG (DR_REG_SLC_BASE + 0x98) +/* SLC_SLC1_RD_RETRY_THRESHOLD : R/W ;bitpos:[31:21] ;default: 11'h80 ; */ +/*description: */ +#define SLC_SLC1_RD_RETRY_THRESHOLD 0x000007FF +#define SLC_SLC1_RD_RETRY_THRESHOLD_M ((SLC_SLC1_RD_RETRY_THRESHOLD_V)<<(SLC_SLC1_RD_RETRY_THRESHOLD_S)) +#define SLC_SLC1_RD_RETRY_THRESHOLD_V 0x7FF +#define SLC_SLC1_RD_RETRY_THRESHOLD_S 21 +/* SLC_SLC1_RX_FILL_EN : R/W ;bitpos:[20] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_RX_FILL_EN (BIT(20)) +#define SLC_SLC1_RX_FILL_EN_M (BIT(20)) +#define SLC_SLC1_RX_FILL_EN_V 0x1 +#define SLC_SLC1_RX_FILL_EN_S 20 +/* SLC_SLC1_RX_EOF_MODE : R/W ;bitpos:[19] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_RX_EOF_MODE (BIT(19)) +#define SLC_SLC1_RX_EOF_MODE_M (BIT(19)) +#define SLC_SLC1_RX_EOF_MODE_V 0x1 +#define SLC_SLC1_RX_EOF_MODE_S 19 +/* SLC_SLC1_RX_FILL_MODE : R/W ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_FILL_MODE (BIT(18)) +#define SLC_SLC1_RX_FILL_MODE_M (BIT(18)) +#define SLC_SLC1_RX_FILL_MODE_V 0x1 +#define SLC_SLC1_RX_FILL_MODE_S 18 +/* SLC_SLC1_INFOR_NO_REPLACE : R/W ;bitpos:[17] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_INFOR_NO_REPLACE (BIT(17)) +#define SLC_SLC1_INFOR_NO_REPLACE_M (BIT(17)) +#define SLC_SLC1_INFOR_NO_REPLACE_V 0x1 +#define SLC_SLC1_INFOR_NO_REPLACE_S 17 +/* SLC_SLC1_TOKEN_NO_REPLACE : R/W ;bitpos:[16] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC1_TOKEN_NO_REPLACE (BIT(16)) +#define SLC_SLC1_TOKEN_NO_REPLACE_M (BIT(16)) +#define SLC_SLC1_TOKEN_NO_REPLACE_V 0x1 +#define SLC_SLC1_TOKEN_NO_REPLACE_S 16 +/* SLC_SLC0_RD_RETRY_THRESHOLD : R/W ;bitpos:[15:5] ;default: 11'h80 ; */ +/*description: */ +#define SLC_SLC0_RD_RETRY_THRESHOLD 0x000007FF +#define SLC_SLC0_RD_RETRY_THRESHOLD_M ((SLC_SLC0_RD_RETRY_THRESHOLD_V)<<(SLC_SLC0_RD_RETRY_THRESHOLD_S)) +#define SLC_SLC0_RD_RETRY_THRESHOLD_V 0x7FF +#define SLC_SLC0_RD_RETRY_THRESHOLD_S 5 +/* SLC_SLC0_RX_FILL_EN : R/W ;bitpos:[4] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC0_RX_FILL_EN (BIT(4)) +#define SLC_SLC0_RX_FILL_EN_M (BIT(4)) +#define SLC_SLC0_RX_FILL_EN_V 0x1 +#define SLC_SLC0_RX_FILL_EN_S 4 +/* SLC_SLC0_RX_EOF_MODE : R/W ;bitpos:[3] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC0_RX_EOF_MODE (BIT(3)) +#define SLC_SLC0_RX_EOF_MODE_M (BIT(3)) +#define SLC_SLC0_RX_EOF_MODE_V 0x1 +#define SLC_SLC0_RX_EOF_MODE_S 3 +/* SLC_SLC0_RX_FILL_MODE : R/W ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_FILL_MODE (BIT(2)) +#define SLC_SLC0_RX_FILL_MODE_M (BIT(2)) +#define SLC_SLC0_RX_FILL_MODE_V 0x1 +#define SLC_SLC0_RX_FILL_MODE_S 2 +/* SLC_SLC0_INFOR_NO_REPLACE : R/W ;bitpos:[1] ;default: 1'b1 ; */ +/*description: */ +#define SLC_SLC0_INFOR_NO_REPLACE (BIT(1)) +#define SLC_SLC0_INFOR_NO_REPLACE_M (BIT(1)) +#define SLC_SLC0_INFOR_NO_REPLACE_V 0x1 +#define SLC_SLC0_INFOR_NO_REPLACE_S 1 +/* SLC_SLC0_TOKEN_NO_REPLACE : R/W ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN_NO_REPLACE (BIT(0)) +#define SLC_SLC0_TOKEN_NO_REPLACE_M (BIT(0)) +#define SLC_SLC0_TOKEN_NO_REPLACE_V 0x1 +#define SLC_SLC0_TOKEN_NO_REPLACE_S 0 + +#define SLC_0_TXLINK_DSCR_REG (DR_REG_SLC_BASE + 0x9C) +/* SLC_SLC0_TXLINK_DSCR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_SLC0_TXLINK_DSCR 0xFFFFFFFF +#define SLC_SLC0_TXLINK_DSCR_M ((SLC_SLC0_TXLINK_DSCR_V)<<(SLC_SLC0_TXLINK_DSCR_S)) +#define SLC_SLC0_TXLINK_DSCR_V 0xFFFFFFFF +#define SLC_SLC0_TXLINK_DSCR_S 0 + +#define SLC_0_TXLINK_DSCR_BF0_REG (DR_REG_SLC_BASE + 0xA0) +/* SLC_SLC0_TXLINK_DSCR_BF0 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_SLC0_TXLINK_DSCR_BF0 0xFFFFFFFF +#define SLC_SLC0_TXLINK_DSCR_BF0_M ((SLC_SLC0_TXLINK_DSCR_BF0_V)<<(SLC_SLC0_TXLINK_DSCR_BF0_S)) +#define SLC_SLC0_TXLINK_DSCR_BF0_V 0xFFFFFFFF +#define SLC_SLC0_TXLINK_DSCR_BF0_S 0 + +#define SLC_0_TXLINK_DSCR_BF1_REG (DR_REG_SLC_BASE + 0xA4) +/* SLC_SLC0_TXLINK_DSCR_BF1 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_SLC0_TXLINK_DSCR_BF1 0xFFFFFFFF +#define SLC_SLC0_TXLINK_DSCR_BF1_M ((SLC_SLC0_TXLINK_DSCR_BF1_V)<<(SLC_SLC0_TXLINK_DSCR_BF1_S)) +#define SLC_SLC0_TXLINK_DSCR_BF1_V 0xFFFFFFFF +#define SLC_SLC0_TXLINK_DSCR_BF1_S 0 + +#define SLC_0_RXLINK_DSCR_REG (DR_REG_SLC_BASE + 0xA8) +/* SLC_SLC0_RXLINK_DSCR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_SLC0_RXLINK_DSCR 0xFFFFFFFF +#define SLC_SLC0_RXLINK_DSCR_M ((SLC_SLC0_RXLINK_DSCR_V)<<(SLC_SLC0_RXLINK_DSCR_S)) +#define SLC_SLC0_RXLINK_DSCR_V 0xFFFFFFFF +#define SLC_SLC0_RXLINK_DSCR_S 0 + +#define SLC_0_RXLINK_DSCR_BF0_REG (DR_REG_SLC_BASE + 0xAC) +/* SLC_SLC0_RXLINK_DSCR_BF0 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_SLC0_RXLINK_DSCR_BF0 0xFFFFFFFF +#define SLC_SLC0_RXLINK_DSCR_BF0_M ((SLC_SLC0_RXLINK_DSCR_BF0_V)<<(SLC_SLC0_RXLINK_DSCR_BF0_S)) +#define SLC_SLC0_RXLINK_DSCR_BF0_V 0xFFFFFFFF +#define SLC_SLC0_RXLINK_DSCR_BF0_S 0 + +#define SLC_0_RXLINK_DSCR_BF1_REG (DR_REG_SLC_BASE + 0xB0) +/* SLC_SLC0_RXLINK_DSCR_BF1 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_SLC0_RXLINK_DSCR_BF1 0xFFFFFFFF +#define SLC_SLC0_RXLINK_DSCR_BF1_M ((SLC_SLC0_RXLINK_DSCR_BF1_V)<<(SLC_SLC0_RXLINK_DSCR_BF1_S)) +#define SLC_SLC0_RXLINK_DSCR_BF1_V 0xFFFFFFFF +#define SLC_SLC0_RXLINK_DSCR_BF1_S 0 + +#define SLC_1_TXLINK_DSCR_REG (DR_REG_SLC_BASE + 0xB4) +/* SLC_SLC1_TXLINK_DSCR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_SLC1_TXLINK_DSCR 0xFFFFFFFF +#define SLC_SLC1_TXLINK_DSCR_M ((SLC_SLC1_TXLINK_DSCR_V)<<(SLC_SLC1_TXLINK_DSCR_S)) +#define SLC_SLC1_TXLINK_DSCR_V 0xFFFFFFFF +#define SLC_SLC1_TXLINK_DSCR_S 0 + +#define SLC_1_TXLINK_DSCR_BF0_REG (DR_REG_SLC_BASE + 0xB8) +/* SLC_SLC1_TXLINK_DSCR_BF0 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_SLC1_TXLINK_DSCR_BF0 0xFFFFFFFF +#define SLC_SLC1_TXLINK_DSCR_BF0_M ((SLC_SLC1_TXLINK_DSCR_BF0_V)<<(SLC_SLC1_TXLINK_DSCR_BF0_S)) +#define SLC_SLC1_TXLINK_DSCR_BF0_V 0xFFFFFFFF +#define SLC_SLC1_TXLINK_DSCR_BF0_S 0 + +#define SLC_1_TXLINK_DSCR_BF1_REG (DR_REG_SLC_BASE + 0xBC) +/* SLC_SLC1_TXLINK_DSCR_BF1 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_SLC1_TXLINK_DSCR_BF1 0xFFFFFFFF +#define SLC_SLC1_TXLINK_DSCR_BF1_M ((SLC_SLC1_TXLINK_DSCR_BF1_V)<<(SLC_SLC1_TXLINK_DSCR_BF1_S)) +#define SLC_SLC1_TXLINK_DSCR_BF1_V 0xFFFFFFFF +#define SLC_SLC1_TXLINK_DSCR_BF1_S 0 + +#define SLC_1_RXLINK_DSCR_REG (DR_REG_SLC_BASE + 0xC0) +/* SLC_SLC1_RXLINK_DSCR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_SLC1_RXLINK_DSCR 0xFFFFFFFF +#define SLC_SLC1_RXLINK_DSCR_M ((SLC_SLC1_RXLINK_DSCR_V)<<(SLC_SLC1_RXLINK_DSCR_S)) +#define SLC_SLC1_RXLINK_DSCR_V 0xFFFFFFFF +#define SLC_SLC1_RXLINK_DSCR_S 0 + +#define SLC_1_RXLINK_DSCR_BF0_REG (DR_REG_SLC_BASE + 0xC4) +/* SLC_SLC1_RXLINK_DSCR_BF0 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_SLC1_RXLINK_DSCR_BF0 0xFFFFFFFF +#define SLC_SLC1_RXLINK_DSCR_BF0_M ((SLC_SLC1_RXLINK_DSCR_BF0_V)<<(SLC_SLC1_RXLINK_DSCR_BF0_S)) +#define SLC_SLC1_RXLINK_DSCR_BF0_V 0xFFFFFFFF +#define SLC_SLC1_RXLINK_DSCR_BF0_S 0 + +#define SLC_1_RXLINK_DSCR_BF1_REG (DR_REG_SLC_BASE + 0xC8) +/* SLC_SLC1_RXLINK_DSCR_BF1 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_SLC1_RXLINK_DSCR_BF1 0xFFFFFFFF +#define SLC_SLC1_RXLINK_DSCR_BF1_M ((SLC_SLC1_RXLINK_DSCR_BF1_V)<<(SLC_SLC1_RXLINK_DSCR_BF1_S)) +#define SLC_SLC1_RXLINK_DSCR_BF1_V 0xFFFFFFFF +#define SLC_SLC1_RXLINK_DSCR_BF1_S 0 + +#define SLC_0_TX_ERREOF_DES_ADDR_REG (DR_REG_SLC_BASE + 0xCC) +/* SLC_SLC0_TX_ERR_EOF_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC0_TX_ERR_EOF_DES_ADDR 0xFFFFFFFF +#define SLC_SLC0_TX_ERR_EOF_DES_ADDR_M ((SLC_SLC0_TX_ERR_EOF_DES_ADDR_V)<<(SLC_SLC0_TX_ERR_EOF_DES_ADDR_S)) +#define SLC_SLC0_TX_ERR_EOF_DES_ADDR_V 0xFFFFFFFF +#define SLC_SLC0_TX_ERR_EOF_DES_ADDR_S 0 + +#define SLC_1_TX_ERREOF_DES_ADDR_REG (DR_REG_SLC_BASE + 0xD0) +/* SLC_SLC1_TX_ERR_EOF_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC1_TX_ERR_EOF_DES_ADDR 0xFFFFFFFF +#define SLC_SLC1_TX_ERR_EOF_DES_ADDR_M ((SLC_SLC1_TX_ERR_EOF_DES_ADDR_V)<<(SLC_SLC1_TX_ERR_EOF_DES_ADDR_S)) +#define SLC_SLC1_TX_ERR_EOF_DES_ADDR_V 0xFFFFFFFF +#define SLC_SLC1_TX_ERR_EOF_DES_ADDR_S 0 + +#define SLC_TOKEN_LAT_REG (DR_REG_SLC_BASE + 0xD4) +/* SLC_SLC1_TOKEN : RO ;bitpos:[27:16] ;default: 12'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN 0x00000FFF +#define SLC_SLC1_TOKEN_M ((SLC_SLC1_TOKEN_V)<<(SLC_SLC1_TOKEN_S)) +#define SLC_SLC1_TOKEN_V 0xFFF +#define SLC_SLC1_TOKEN_S 16 +/* SLC_SLC0_TOKEN : RO ;bitpos:[11:0] ;default: 12'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN 0x00000FFF +#define SLC_SLC0_TOKEN_M ((SLC_SLC0_TOKEN_V)<<(SLC_SLC0_TOKEN_S)) +#define SLC_SLC0_TOKEN_V 0xFFF +#define SLC_SLC0_TOKEN_S 0 + +#define SLC_TX_DSCR_CONF_REG (DR_REG_SLC_BASE + 0xD8) +/* SLC_WR_RETRY_THRESHOLD : R/W ;bitpos:[10:0] ;default: 11'h80 ; */ +/*description: */ +#define SLC_WR_RETRY_THRESHOLD 0x000007FF +#define SLC_WR_RETRY_THRESHOLD_M ((SLC_WR_RETRY_THRESHOLD_V)<<(SLC_WR_RETRY_THRESHOLD_S)) +#define SLC_WR_RETRY_THRESHOLD_V 0x7FF +#define SLC_WR_RETRY_THRESHOLD_S 0 + +#define SLC_CMD_INFOR0_REG (DR_REG_SLC_BASE + 0xDC) +/* SLC_CMD_CONTENT0 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_CMD_CONTENT0 0xFFFFFFFF +#define SLC_CMD_CONTENT0_M ((SLC_CMD_CONTENT0_V)<<(SLC_CMD_CONTENT0_S)) +#define SLC_CMD_CONTENT0_V 0xFFFFFFFF +#define SLC_CMD_CONTENT0_S 0 + +#define SLC_CMD_INFOR1_REG (DR_REG_SLC_BASE + 0xE0) +/* SLC_CMD_CONTENT1 : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_CMD_CONTENT1 0xFFFFFFFF +#define SLC_CMD_CONTENT1_M ((SLC_CMD_CONTENT1_V)<<(SLC_CMD_CONTENT1_S)) +#define SLC_CMD_CONTENT1_V 0xFFFFFFFF +#define SLC_CMD_CONTENT1_S 0 + +#define SLC_0_LEN_CONF_REG (DR_REG_SLC_BASE + 0xE4) +/* SLC_SLC0_TX_NEW_PKT_IND : RO ;bitpos:[28] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_NEW_PKT_IND (BIT(28)) +#define SLC_SLC0_TX_NEW_PKT_IND_M (BIT(28)) +#define SLC_SLC0_TX_NEW_PKT_IND_V 0x1 +#define SLC_SLC0_TX_NEW_PKT_IND_S 28 +/* SLC_SLC0_RX_NEW_PKT_IND : RO ;bitpos:[27] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_NEW_PKT_IND (BIT(27)) +#define SLC_SLC0_RX_NEW_PKT_IND_M (BIT(27)) +#define SLC_SLC0_RX_NEW_PKT_IND_V 0x1 +#define SLC_SLC0_RX_NEW_PKT_IND_S 27 +/* SLC_SLC0_TX_GET_USED_DSCR : WO ;bitpos:[26] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_GET_USED_DSCR (BIT(26)) +#define SLC_SLC0_TX_GET_USED_DSCR_M (BIT(26)) +#define SLC_SLC0_TX_GET_USED_DSCR_V 0x1 +#define SLC_SLC0_TX_GET_USED_DSCR_S 26 +/* SLC_SLC0_RX_GET_USED_DSCR : WO ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_GET_USED_DSCR (BIT(25)) +#define SLC_SLC0_RX_GET_USED_DSCR_M (BIT(25)) +#define SLC_SLC0_RX_GET_USED_DSCR_V 0x1 +#define SLC_SLC0_RX_GET_USED_DSCR_S 25 +/* SLC_SLC0_TX_PACKET_LOAD_EN : R/W ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_PACKET_LOAD_EN (BIT(24)) +#define SLC_SLC0_TX_PACKET_LOAD_EN_M (BIT(24)) +#define SLC_SLC0_TX_PACKET_LOAD_EN_V 0x1 +#define SLC_SLC0_TX_PACKET_LOAD_EN_S 24 +/* SLC_SLC0_RX_PACKET_LOAD_EN : R/W ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_PACKET_LOAD_EN (BIT(23)) +#define SLC_SLC0_RX_PACKET_LOAD_EN_M (BIT(23)) +#define SLC_SLC0_RX_PACKET_LOAD_EN_V 0x1 +#define SLC_SLC0_RX_PACKET_LOAD_EN_S 23 +/* SLC_SLC0_LEN_INC_MORE : WO ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_LEN_INC_MORE (BIT(22)) +#define SLC_SLC0_LEN_INC_MORE_M (BIT(22)) +#define SLC_SLC0_LEN_INC_MORE_V 0x1 +#define SLC_SLC0_LEN_INC_MORE_S 22 +/* SLC_SLC0_LEN_INC : WO ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_LEN_INC (BIT(21)) +#define SLC_SLC0_LEN_INC_M (BIT(21)) +#define SLC_SLC0_LEN_INC_V 0x1 +#define SLC_SLC0_LEN_INC_S 21 +/* SLC_SLC0_LEN_WR : WO ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_LEN_WR (BIT(20)) +#define SLC_SLC0_LEN_WR_M (BIT(20)) +#define SLC_SLC0_LEN_WR_V 0x1 +#define SLC_SLC0_LEN_WR_S 20 +/* SLC_SLC0_LEN_WDATA : WO ;bitpos:[19:0] ;default: 20'h0 ; */ +/*description: */ +#define SLC_SLC0_LEN_WDATA 0x000FFFFF +#define SLC_SLC0_LEN_WDATA_M ((SLC_SLC0_LEN_WDATA_V)<<(SLC_SLC0_LEN_WDATA_S)) +#define SLC_SLC0_LEN_WDATA_V 0xFFFFF +#define SLC_SLC0_LEN_WDATA_S 0 + +#define SLC_0_LENGTH_REG (DR_REG_SLC_BASE + 0xE8) +/* SLC_SLC0_LEN : RO ;bitpos:[19:0] ;default: 20'h0 ; */ +/*description: */ +#define SLC_SLC0_LEN 0x000FFFFF +#define SLC_SLC0_LEN_M ((SLC_SLC0_LEN_V)<<(SLC_SLC0_LEN_S)) +#define SLC_SLC0_LEN_V 0xFFFFF +#define SLC_SLC0_LEN_S 0 + +#define SLC_0_TXPKT_H_DSCR_REG (DR_REG_SLC_BASE + 0xEC) +/* SLC_SLC0_TX_PKT_H_DSCR_ADDR : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC0_TX_PKT_H_DSCR_ADDR 0xFFFFFFFF +#define SLC_SLC0_TX_PKT_H_DSCR_ADDR_M ((SLC_SLC0_TX_PKT_H_DSCR_ADDR_V)<<(SLC_SLC0_TX_PKT_H_DSCR_ADDR_S)) +#define SLC_SLC0_TX_PKT_H_DSCR_ADDR_V 0xFFFFFFFF +#define SLC_SLC0_TX_PKT_H_DSCR_ADDR_S 0 + +#define SLC_0_TXPKT_E_DSCR_REG (DR_REG_SLC_BASE + 0xF0) +/* SLC_SLC0_TX_PKT_E_DSCR_ADDR : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC0_TX_PKT_E_DSCR_ADDR 0xFFFFFFFF +#define SLC_SLC0_TX_PKT_E_DSCR_ADDR_M ((SLC_SLC0_TX_PKT_E_DSCR_ADDR_V)<<(SLC_SLC0_TX_PKT_E_DSCR_ADDR_S)) +#define SLC_SLC0_TX_PKT_E_DSCR_ADDR_V 0xFFFFFFFF +#define SLC_SLC0_TX_PKT_E_DSCR_ADDR_S 0 + +#define SLC_0_RXPKT_H_DSCR_REG (DR_REG_SLC_BASE + 0xF4) +/* SLC_SLC0_RX_PKT_H_DSCR_ADDR : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC0_RX_PKT_H_DSCR_ADDR 0xFFFFFFFF +#define SLC_SLC0_RX_PKT_H_DSCR_ADDR_M ((SLC_SLC0_RX_PKT_H_DSCR_ADDR_V)<<(SLC_SLC0_RX_PKT_H_DSCR_ADDR_S)) +#define SLC_SLC0_RX_PKT_H_DSCR_ADDR_V 0xFFFFFFFF +#define SLC_SLC0_RX_PKT_H_DSCR_ADDR_S 0 + +#define SLC_0_RXPKT_E_DSCR_REG (DR_REG_SLC_BASE + 0xF8) +/* SLC_SLC0_RX_PKT_E_DSCR_ADDR : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC0_RX_PKT_E_DSCR_ADDR 0xFFFFFFFF +#define SLC_SLC0_RX_PKT_E_DSCR_ADDR_M ((SLC_SLC0_RX_PKT_E_DSCR_ADDR_V)<<(SLC_SLC0_RX_PKT_E_DSCR_ADDR_S)) +#define SLC_SLC0_RX_PKT_E_DSCR_ADDR_V 0xFFFFFFFF +#define SLC_SLC0_RX_PKT_E_DSCR_ADDR_S 0 + +#define SLC_0_TXPKTU_H_DSCR_REG (DR_REG_SLC_BASE + 0xFC) +/* SLC_SLC0_TX_PKT_START_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC0_TX_PKT_START_DSCR_ADDR 0xFFFFFFFF +#define SLC_SLC0_TX_PKT_START_DSCR_ADDR_M ((SLC_SLC0_TX_PKT_START_DSCR_ADDR_V)<<(SLC_SLC0_TX_PKT_START_DSCR_ADDR_S)) +#define SLC_SLC0_TX_PKT_START_DSCR_ADDR_V 0xFFFFFFFF +#define SLC_SLC0_TX_PKT_START_DSCR_ADDR_S 0 + +#define SLC_0_TXPKTU_E_DSCR_REG (DR_REG_SLC_BASE + 0x100) +/* SLC_SLC0_TX_PKT_END_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC0_TX_PKT_END_DSCR_ADDR 0xFFFFFFFF +#define SLC_SLC0_TX_PKT_END_DSCR_ADDR_M ((SLC_SLC0_TX_PKT_END_DSCR_ADDR_V)<<(SLC_SLC0_TX_PKT_END_DSCR_ADDR_S)) +#define SLC_SLC0_TX_PKT_END_DSCR_ADDR_V 0xFFFFFFFF +#define SLC_SLC0_TX_PKT_END_DSCR_ADDR_S 0 + +#define SLC_0_RXPKTU_H_DSCR_REG (DR_REG_SLC_BASE + 0x104) +/* SLC_SLC0_RX_PKT_START_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC0_RX_PKT_START_DSCR_ADDR 0xFFFFFFFF +#define SLC_SLC0_RX_PKT_START_DSCR_ADDR_M ((SLC_SLC0_RX_PKT_START_DSCR_ADDR_V)<<(SLC_SLC0_RX_PKT_START_DSCR_ADDR_S)) +#define SLC_SLC0_RX_PKT_START_DSCR_ADDR_V 0xFFFFFFFF +#define SLC_SLC0_RX_PKT_START_DSCR_ADDR_S 0 + +#define SLC_0_RXPKTU_E_DSCR_REG (DR_REG_SLC_BASE + 0x108) +/* SLC_SLC0_RX_PKT_END_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'h0 ; */ +/*description: */ +#define SLC_SLC0_RX_PKT_END_DSCR_ADDR 0xFFFFFFFF +#define SLC_SLC0_RX_PKT_END_DSCR_ADDR_M ((SLC_SLC0_RX_PKT_END_DSCR_ADDR_V)<<(SLC_SLC0_RX_PKT_END_DSCR_ADDR_S)) +#define SLC_SLC0_RX_PKT_END_DSCR_ADDR_V 0xFFFFFFFF +#define SLC_SLC0_RX_PKT_END_DSCR_ADDR_S 0 + +#define SLC_SEQ_POSITION_REG (DR_REG_SLC_BASE + 0x114) +/* SLC_SLC1_SEQ_POSITION : R/W ;bitpos:[15:8] ;default: 8'h5 ; */ +/*description: */ +#define SLC_SLC1_SEQ_POSITION 0x000000FF +#define SLC_SLC1_SEQ_POSITION_M ((SLC_SLC1_SEQ_POSITION_V)<<(SLC_SLC1_SEQ_POSITION_S)) +#define SLC_SLC1_SEQ_POSITION_V 0xFF +#define SLC_SLC1_SEQ_POSITION_S 8 +/* SLC_SLC0_SEQ_POSITION : R/W ;bitpos:[7:0] ;default: 8'h9 ; */ +/*description: */ +#define SLC_SLC0_SEQ_POSITION 0x000000FF +#define SLC_SLC0_SEQ_POSITION_M ((SLC_SLC0_SEQ_POSITION_V)<<(SLC_SLC0_SEQ_POSITION_S)) +#define SLC_SLC0_SEQ_POSITION_V 0xFF +#define SLC_SLC0_SEQ_POSITION_S 0 + +#define SLC_0_DSCR_REC_CONF_REG (DR_REG_SLC_BASE + 0x118) +/* SLC_SLC0_RX_DSCR_REC_LIM : R/W ;bitpos:[9:0] ;default: 10'h3ff ; */ +/*description: */ +#define SLC_SLC0_RX_DSCR_REC_LIM 0x000003FF +#define SLC_SLC0_RX_DSCR_REC_LIM_M ((SLC_SLC0_RX_DSCR_REC_LIM_V)<<(SLC_SLC0_RX_DSCR_REC_LIM_S)) +#define SLC_SLC0_RX_DSCR_REC_LIM_V 0x3FF +#define SLC_SLC0_RX_DSCR_REC_LIM_S 0 + +#define SLC_SDIO_CRC_ST0_REG (DR_REG_SLC_BASE + 0x11C) +/* SLC_DAT3_CRC_ERR_CNT : RO ;bitpos:[31:24] ;default: 8'h0 ; */ +/*description: */ +#define SLC_DAT3_CRC_ERR_CNT 0x000000FF +#define SLC_DAT3_CRC_ERR_CNT_M ((SLC_DAT3_CRC_ERR_CNT_V)<<(SLC_DAT3_CRC_ERR_CNT_S)) +#define SLC_DAT3_CRC_ERR_CNT_V 0xFF +#define SLC_DAT3_CRC_ERR_CNT_S 24 +/* SLC_DAT2_CRC_ERR_CNT : RO ;bitpos:[23:16] ;default: 8'h0 ; */ +/*description: */ +#define SLC_DAT2_CRC_ERR_CNT 0x000000FF +#define SLC_DAT2_CRC_ERR_CNT_M ((SLC_DAT2_CRC_ERR_CNT_V)<<(SLC_DAT2_CRC_ERR_CNT_S)) +#define SLC_DAT2_CRC_ERR_CNT_V 0xFF +#define SLC_DAT2_CRC_ERR_CNT_S 16 +/* SLC_DAT1_CRC_ERR_CNT : RO ;bitpos:[15:8] ;default: 8'h0 ; */ +/*description: */ +#define SLC_DAT1_CRC_ERR_CNT 0x000000FF +#define SLC_DAT1_CRC_ERR_CNT_M ((SLC_DAT1_CRC_ERR_CNT_V)<<(SLC_DAT1_CRC_ERR_CNT_S)) +#define SLC_DAT1_CRC_ERR_CNT_V 0xFF +#define SLC_DAT1_CRC_ERR_CNT_S 8 +/* SLC_DAT0_CRC_ERR_CNT : RO ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define SLC_DAT0_CRC_ERR_CNT 0x000000FF +#define SLC_DAT0_CRC_ERR_CNT_M ((SLC_DAT0_CRC_ERR_CNT_V)<<(SLC_DAT0_CRC_ERR_CNT_S)) +#define SLC_DAT0_CRC_ERR_CNT_V 0xFF +#define SLC_DAT0_CRC_ERR_CNT_S 0 + +#define SLC_SDIO_CRC_ST1_REG (DR_REG_SLC_BASE + 0x120) +/* SLC_ERR_CNT_CLR : R/W ;bitpos:[31] ;default: 1'b0 ; */ +/*description: */ +#define SLC_ERR_CNT_CLR (BIT(31)) +#define SLC_ERR_CNT_CLR_M (BIT(31)) +#define SLC_ERR_CNT_CLR_V 0x1 +#define SLC_ERR_CNT_CLR_S 31 +/* SLC_CMD_CRC_ERR_CNT : RO ;bitpos:[7:0] ;default: 8'h0 ; */ +/*description: */ +#define SLC_CMD_CRC_ERR_CNT 0x000000FF +#define SLC_CMD_CRC_ERR_CNT_M ((SLC_CMD_CRC_ERR_CNT_V)<<(SLC_CMD_CRC_ERR_CNT_S)) +#define SLC_CMD_CRC_ERR_CNT_V 0xFF +#define SLC_CMD_CRC_ERR_CNT_S 0 + +#define SLC_0_EOF_START_DES_REG (DR_REG_SLC_BASE + 0x124) +/* SLC_SLC0_EOF_START_DES_ADDR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_SLC0_EOF_START_DES_ADDR 0xFFFFFFFF +#define SLC_SLC0_EOF_START_DES_ADDR_M ((SLC_SLC0_EOF_START_DES_ADDR_V)<<(SLC_SLC0_EOF_START_DES_ADDR_S)) +#define SLC_SLC0_EOF_START_DES_ADDR_V 0xFFFFFFFF +#define SLC_SLC0_EOF_START_DES_ADDR_S 0 + +#define SLC_0_PUSH_DSCR_ADDR_REG (DR_REG_SLC_BASE + 0x128) +/* SLC_SLC0_RX_PUSH_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_PUSH_DSCR_ADDR 0xFFFFFFFF +#define SLC_SLC0_RX_PUSH_DSCR_ADDR_M ((SLC_SLC0_RX_PUSH_DSCR_ADDR_V)<<(SLC_SLC0_RX_PUSH_DSCR_ADDR_S)) +#define SLC_SLC0_RX_PUSH_DSCR_ADDR_V 0xFFFFFFFF +#define SLC_SLC0_RX_PUSH_DSCR_ADDR_S 0 + +#define SLC_0_DONE_DSCR_ADDR_REG (DR_REG_SLC_BASE + 0x12C) +/* SLC_SLC0_RX_DONE_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_DONE_DSCR_ADDR 0xFFFFFFFF +#define SLC_SLC0_RX_DONE_DSCR_ADDR_M ((SLC_SLC0_RX_DONE_DSCR_ADDR_V)<<(SLC_SLC0_RX_DONE_DSCR_ADDR_S)) +#define SLC_SLC0_RX_DONE_DSCR_ADDR_V 0xFFFFFFFF +#define SLC_SLC0_RX_DONE_DSCR_ADDR_S 0 + +#define SLC_0_SUB_START_DES_REG (DR_REG_SLC_BASE + 0x130) +/* SLC_SLC0_SUB_PAC_START_DSCR_ADDR : RO ;bitpos:[31:0] ;default: 32'b0 ; */ +/*description: */ +#define SLC_SLC0_SUB_PAC_START_DSCR_ADDR 0xFFFFFFFF +#define SLC_SLC0_SUB_PAC_START_DSCR_ADDR_M ((SLC_SLC0_SUB_PAC_START_DSCR_ADDR_V)<<(SLC_SLC0_SUB_PAC_START_DSCR_ADDR_S)) +#define SLC_SLC0_SUB_PAC_START_DSCR_ADDR_V 0xFFFFFFFF +#define SLC_SLC0_SUB_PAC_START_DSCR_ADDR_S 0 + +#define SLC_0_DSCR_CNT_REG (DR_REG_SLC_BASE + 0x134) +/* SLC_SLC0_RX_GET_EOF_OCC : RO ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_GET_EOF_OCC (BIT(16)) +#define SLC_SLC0_RX_GET_EOF_OCC_M (BIT(16)) +#define SLC_SLC0_RX_GET_EOF_OCC_V 0x1 +#define SLC_SLC0_RX_GET_EOF_OCC_S 16 +/* SLC_SLC0_RX_DSCR_CNT_LAT : RO ;bitpos:[9:0] ;default: 10'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_DSCR_CNT_LAT 0x000003FF +#define SLC_SLC0_RX_DSCR_CNT_LAT_M ((SLC_SLC0_RX_DSCR_CNT_LAT_V)<<(SLC_SLC0_RX_DSCR_CNT_LAT_S)) +#define SLC_SLC0_RX_DSCR_CNT_LAT_V 0x3FF +#define SLC_SLC0_RX_DSCR_CNT_LAT_S 0 + +#define SLC_0_LEN_LIM_CONF_REG (DR_REG_SLC_BASE + 0x138) +/* SLC_SLC0_LEN_LIM : R/W ;bitpos:[19:0] ;default: 20'h5400 ; */ +/*description: */ +#define SLC_SLC0_LEN_LIM 0x000FFFFF +#define SLC_SLC0_LEN_LIM_M ((SLC_SLC0_LEN_LIM_V)<<(SLC_SLC0_LEN_LIM_S)) +#define SLC_SLC0_LEN_LIM_V 0xFFFFF +#define SLC_SLC0_LEN_LIM_S 0 + +#define SLC_0INT_ST1_REG (DR_REG_SLC_BASE + 0x13C) +/* SLC_SLC0_RX_QUICK_EOF_INT_ST1 : RO ;bitpos:[26] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_QUICK_EOF_INT_ST1 (BIT(26)) +#define SLC_SLC0_RX_QUICK_EOF_INT_ST1_M (BIT(26)) +#define SLC_SLC0_RX_QUICK_EOF_INT_ST1_V 0x1 +#define SLC_SLC0_RX_QUICK_EOF_INT_ST1_S 26 +/* SLC_CMD_DTC_INT_ST1 : RO ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define SLC_CMD_DTC_INT_ST1 (BIT(25)) +#define SLC_CMD_DTC_INT_ST1_M (BIT(25)) +#define SLC_CMD_DTC_INT_ST1_V 0x1 +#define SLC_CMD_DTC_INT_ST1_S 25 +/* SLC_SLC0_TX_ERR_EOF_INT_ST1 : RO ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_ERR_EOF_INT_ST1 (BIT(24)) +#define SLC_SLC0_TX_ERR_EOF_INT_ST1_M (BIT(24)) +#define SLC_SLC0_TX_ERR_EOF_INT_ST1_V 0x1 +#define SLC_SLC0_TX_ERR_EOF_INT_ST1_S 24 +/* SLC_SLC0_WR_RETRY_DONE_INT_ST1 : RO ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_WR_RETRY_DONE_INT_ST1 (BIT(23)) +#define SLC_SLC0_WR_RETRY_DONE_INT_ST1_M (BIT(23)) +#define SLC_SLC0_WR_RETRY_DONE_INT_ST1_V 0x1 +#define SLC_SLC0_WR_RETRY_DONE_INT_ST1_S 23 +/* SLC_SLC0_HOST_RD_ACK_INT_ST1 : RO ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_HOST_RD_ACK_INT_ST1 (BIT(22)) +#define SLC_SLC0_HOST_RD_ACK_INT_ST1_M (BIT(22)) +#define SLC_SLC0_HOST_RD_ACK_INT_ST1_V 0x1 +#define SLC_SLC0_HOST_RD_ACK_INT_ST1_S 22 +/* SLC_SLC0_TX_DSCR_EMPTY_INT_ST1 : RO ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST1 (BIT(21)) +#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST1_M (BIT(21)) +#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST1_V 0x1 +#define SLC_SLC0_TX_DSCR_EMPTY_INT_ST1_S 21 +/* SLC_SLC0_RX_DSCR_ERR_INT_ST1 : RO ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_DSCR_ERR_INT_ST1 (BIT(20)) +#define SLC_SLC0_RX_DSCR_ERR_INT_ST1_M (BIT(20)) +#define SLC_SLC0_RX_DSCR_ERR_INT_ST1_V 0x1 +#define SLC_SLC0_RX_DSCR_ERR_INT_ST1_S 20 +/* SLC_SLC0_TX_DSCR_ERR_INT_ST1 : RO ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DSCR_ERR_INT_ST1 (BIT(19)) +#define SLC_SLC0_TX_DSCR_ERR_INT_ST1_M (BIT(19)) +#define SLC_SLC0_TX_DSCR_ERR_INT_ST1_V 0x1 +#define SLC_SLC0_TX_DSCR_ERR_INT_ST1_S 19 +/* SLC_SLC0_TOHOST_INT_ST1 : RO ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOHOST_INT_ST1 (BIT(18)) +#define SLC_SLC0_TOHOST_INT_ST1_M (BIT(18)) +#define SLC_SLC0_TOHOST_INT_ST1_V 0x1 +#define SLC_SLC0_TOHOST_INT_ST1_S 18 +/* SLC_SLC0_RX_EOF_INT_ST1 : RO ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_EOF_INT_ST1 (BIT(17)) +#define SLC_SLC0_RX_EOF_INT_ST1_M (BIT(17)) +#define SLC_SLC0_RX_EOF_INT_ST1_V 0x1 +#define SLC_SLC0_RX_EOF_INT_ST1_S 17 +/* SLC_SLC0_RX_DONE_INT_ST1 : RO ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_DONE_INT_ST1 (BIT(16)) +#define SLC_SLC0_RX_DONE_INT_ST1_M (BIT(16)) +#define SLC_SLC0_RX_DONE_INT_ST1_V 0x1 +#define SLC_SLC0_RX_DONE_INT_ST1_S 16 +/* SLC_SLC0_TX_SUC_EOF_INT_ST1 : RO ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_SUC_EOF_INT_ST1 (BIT(15)) +#define SLC_SLC0_TX_SUC_EOF_INT_ST1_M (BIT(15)) +#define SLC_SLC0_TX_SUC_EOF_INT_ST1_V 0x1 +#define SLC_SLC0_TX_SUC_EOF_INT_ST1_S 15 +/* SLC_SLC0_TX_DONE_INT_ST1 : RO ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DONE_INT_ST1 (BIT(14)) +#define SLC_SLC0_TX_DONE_INT_ST1_M (BIT(14)) +#define SLC_SLC0_TX_DONE_INT_ST1_V 0x1 +#define SLC_SLC0_TX_DONE_INT_ST1_S 14 +/* SLC_SLC0_TOKEN1_1TO0_INT_ST1 : RO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN1_1TO0_INT_ST1 (BIT(13)) +#define SLC_SLC0_TOKEN1_1TO0_INT_ST1_M (BIT(13)) +#define SLC_SLC0_TOKEN1_1TO0_INT_ST1_V 0x1 +#define SLC_SLC0_TOKEN1_1TO0_INT_ST1_S 13 +/* SLC_SLC0_TOKEN0_1TO0_INT_ST1 : RO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN0_1TO0_INT_ST1 (BIT(12)) +#define SLC_SLC0_TOKEN0_1TO0_INT_ST1_M (BIT(12)) +#define SLC_SLC0_TOKEN0_1TO0_INT_ST1_V 0x1 +#define SLC_SLC0_TOKEN0_1TO0_INT_ST1_S 12 +/* SLC_SLC0_TX_OVF_INT_ST1 : RO ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_OVF_INT_ST1 (BIT(11)) +#define SLC_SLC0_TX_OVF_INT_ST1_M (BIT(11)) +#define SLC_SLC0_TX_OVF_INT_ST1_V 0x1 +#define SLC_SLC0_TX_OVF_INT_ST1_S 11 +/* SLC_SLC0_RX_UDF_INT_ST1 : RO ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_UDF_INT_ST1 (BIT(10)) +#define SLC_SLC0_RX_UDF_INT_ST1_M (BIT(10)) +#define SLC_SLC0_RX_UDF_INT_ST1_V 0x1 +#define SLC_SLC0_RX_UDF_INT_ST1_S 10 +/* SLC_SLC0_TX_START_INT_ST1 : RO ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_START_INT_ST1 (BIT(9)) +#define SLC_SLC0_TX_START_INT_ST1_M (BIT(9)) +#define SLC_SLC0_TX_START_INT_ST1_V 0x1 +#define SLC_SLC0_TX_START_INT_ST1_S 9 +/* SLC_SLC0_RX_START_INT_ST1 : RO ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_START_INT_ST1 (BIT(8)) +#define SLC_SLC0_RX_START_INT_ST1_M (BIT(8)) +#define SLC_SLC0_RX_START_INT_ST1_V 0x1 +#define SLC_SLC0_RX_START_INT_ST1_S 8 +/* SLC_FRHOST_BIT7_INT_ST1 : RO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT7_INT_ST1 (BIT(7)) +#define SLC_FRHOST_BIT7_INT_ST1_M (BIT(7)) +#define SLC_FRHOST_BIT7_INT_ST1_V 0x1 +#define SLC_FRHOST_BIT7_INT_ST1_S 7 +/* SLC_FRHOST_BIT6_INT_ST1 : RO ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT6_INT_ST1 (BIT(6)) +#define SLC_FRHOST_BIT6_INT_ST1_M (BIT(6)) +#define SLC_FRHOST_BIT6_INT_ST1_V 0x1 +#define SLC_FRHOST_BIT6_INT_ST1_S 6 +/* SLC_FRHOST_BIT5_INT_ST1 : RO ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT5_INT_ST1 (BIT(5)) +#define SLC_FRHOST_BIT5_INT_ST1_M (BIT(5)) +#define SLC_FRHOST_BIT5_INT_ST1_V 0x1 +#define SLC_FRHOST_BIT5_INT_ST1_S 5 +/* SLC_FRHOST_BIT4_INT_ST1 : RO ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT4_INT_ST1 (BIT(4)) +#define SLC_FRHOST_BIT4_INT_ST1_M (BIT(4)) +#define SLC_FRHOST_BIT4_INT_ST1_V 0x1 +#define SLC_FRHOST_BIT4_INT_ST1_S 4 +/* SLC_FRHOST_BIT3_INT_ST1 : RO ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT3_INT_ST1 (BIT(3)) +#define SLC_FRHOST_BIT3_INT_ST1_M (BIT(3)) +#define SLC_FRHOST_BIT3_INT_ST1_V 0x1 +#define SLC_FRHOST_BIT3_INT_ST1_S 3 +/* SLC_FRHOST_BIT2_INT_ST1 : RO ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT2_INT_ST1 (BIT(2)) +#define SLC_FRHOST_BIT2_INT_ST1_M (BIT(2)) +#define SLC_FRHOST_BIT2_INT_ST1_V 0x1 +#define SLC_FRHOST_BIT2_INT_ST1_S 2 +/* SLC_FRHOST_BIT1_INT_ST1 : RO ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT1_INT_ST1 (BIT(1)) +#define SLC_FRHOST_BIT1_INT_ST1_M (BIT(1)) +#define SLC_FRHOST_BIT1_INT_ST1_V 0x1 +#define SLC_FRHOST_BIT1_INT_ST1_S 1 +/* SLC_FRHOST_BIT0_INT_ST1 : RO ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT0_INT_ST1 (BIT(0)) +#define SLC_FRHOST_BIT0_INT_ST1_M (BIT(0)) +#define SLC_FRHOST_BIT0_INT_ST1_V 0x1 +#define SLC_FRHOST_BIT0_INT_ST1_S 0 + +#define SLC_0INT_ENA1_REG (DR_REG_SLC_BASE + 0x140) +/* SLC_SLC0_RX_QUICK_EOF_INT_ENA1 : R/W ;bitpos:[26] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_QUICK_EOF_INT_ENA1 (BIT(26)) +#define SLC_SLC0_RX_QUICK_EOF_INT_ENA1_M (BIT(26)) +#define SLC_SLC0_RX_QUICK_EOF_INT_ENA1_V 0x1 +#define SLC_SLC0_RX_QUICK_EOF_INT_ENA1_S 26 +/* SLC_CMD_DTC_INT_ENA1 : R/W ;bitpos:[25] ;default: 1'b0 ; */ +/*description: */ +#define SLC_CMD_DTC_INT_ENA1 (BIT(25)) +#define SLC_CMD_DTC_INT_ENA1_M (BIT(25)) +#define SLC_CMD_DTC_INT_ENA1_V 0x1 +#define SLC_CMD_DTC_INT_ENA1_S 25 +/* SLC_SLC0_TX_ERR_EOF_INT_ENA1 : R/W ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_ERR_EOF_INT_ENA1 (BIT(24)) +#define SLC_SLC0_TX_ERR_EOF_INT_ENA1_M (BIT(24)) +#define SLC_SLC0_TX_ERR_EOF_INT_ENA1_V 0x1 +#define SLC_SLC0_TX_ERR_EOF_INT_ENA1_S 24 +/* SLC_SLC0_WR_RETRY_DONE_INT_ENA1 : R/W ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_WR_RETRY_DONE_INT_ENA1 (BIT(23)) +#define SLC_SLC0_WR_RETRY_DONE_INT_ENA1_M (BIT(23)) +#define SLC_SLC0_WR_RETRY_DONE_INT_ENA1_V 0x1 +#define SLC_SLC0_WR_RETRY_DONE_INT_ENA1_S 23 +/* SLC_SLC0_HOST_RD_ACK_INT_ENA1 : R/W ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_HOST_RD_ACK_INT_ENA1 (BIT(22)) +#define SLC_SLC0_HOST_RD_ACK_INT_ENA1_M (BIT(22)) +#define SLC_SLC0_HOST_RD_ACK_INT_ENA1_V 0x1 +#define SLC_SLC0_HOST_RD_ACK_INT_ENA1_S 22 +/* SLC_SLC0_TX_DSCR_EMPTY_INT_ENA1 : R/W ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA1 (BIT(21)) +#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA1_M (BIT(21)) +#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA1_V 0x1 +#define SLC_SLC0_TX_DSCR_EMPTY_INT_ENA1_S 21 +/* SLC_SLC0_RX_DSCR_ERR_INT_ENA1 : R/W ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_DSCR_ERR_INT_ENA1 (BIT(20)) +#define SLC_SLC0_RX_DSCR_ERR_INT_ENA1_M (BIT(20)) +#define SLC_SLC0_RX_DSCR_ERR_INT_ENA1_V 0x1 +#define SLC_SLC0_RX_DSCR_ERR_INT_ENA1_S 20 +/* SLC_SLC0_TX_DSCR_ERR_INT_ENA1 : R/W ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DSCR_ERR_INT_ENA1 (BIT(19)) +#define SLC_SLC0_TX_DSCR_ERR_INT_ENA1_M (BIT(19)) +#define SLC_SLC0_TX_DSCR_ERR_INT_ENA1_V 0x1 +#define SLC_SLC0_TX_DSCR_ERR_INT_ENA1_S 19 +/* SLC_SLC0_TOHOST_INT_ENA1 : R/W ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOHOST_INT_ENA1 (BIT(18)) +#define SLC_SLC0_TOHOST_INT_ENA1_M (BIT(18)) +#define SLC_SLC0_TOHOST_INT_ENA1_V 0x1 +#define SLC_SLC0_TOHOST_INT_ENA1_S 18 +/* SLC_SLC0_RX_EOF_INT_ENA1 : R/W ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_EOF_INT_ENA1 (BIT(17)) +#define SLC_SLC0_RX_EOF_INT_ENA1_M (BIT(17)) +#define SLC_SLC0_RX_EOF_INT_ENA1_V 0x1 +#define SLC_SLC0_RX_EOF_INT_ENA1_S 17 +/* SLC_SLC0_RX_DONE_INT_ENA1 : R/W ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_DONE_INT_ENA1 (BIT(16)) +#define SLC_SLC0_RX_DONE_INT_ENA1_M (BIT(16)) +#define SLC_SLC0_RX_DONE_INT_ENA1_V 0x1 +#define SLC_SLC0_RX_DONE_INT_ENA1_S 16 +/* SLC_SLC0_TX_SUC_EOF_INT_ENA1 : R/W ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_SUC_EOF_INT_ENA1 (BIT(15)) +#define SLC_SLC0_TX_SUC_EOF_INT_ENA1_M (BIT(15)) +#define SLC_SLC0_TX_SUC_EOF_INT_ENA1_V 0x1 +#define SLC_SLC0_TX_SUC_EOF_INT_ENA1_S 15 +/* SLC_SLC0_TX_DONE_INT_ENA1 : R/W ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_DONE_INT_ENA1 (BIT(14)) +#define SLC_SLC0_TX_DONE_INT_ENA1_M (BIT(14)) +#define SLC_SLC0_TX_DONE_INT_ENA1_V 0x1 +#define SLC_SLC0_TX_DONE_INT_ENA1_S 14 +/* SLC_SLC0_TOKEN1_1TO0_INT_ENA1 : R/W ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN1_1TO0_INT_ENA1 (BIT(13)) +#define SLC_SLC0_TOKEN1_1TO0_INT_ENA1_M (BIT(13)) +#define SLC_SLC0_TOKEN1_1TO0_INT_ENA1_V 0x1 +#define SLC_SLC0_TOKEN1_1TO0_INT_ENA1_S 13 +/* SLC_SLC0_TOKEN0_1TO0_INT_ENA1 : R/W ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TOKEN0_1TO0_INT_ENA1 (BIT(12)) +#define SLC_SLC0_TOKEN0_1TO0_INT_ENA1_M (BIT(12)) +#define SLC_SLC0_TOKEN0_1TO0_INT_ENA1_V 0x1 +#define SLC_SLC0_TOKEN0_1TO0_INT_ENA1_S 12 +/* SLC_SLC0_TX_OVF_INT_ENA1 : R/W ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_OVF_INT_ENA1 (BIT(11)) +#define SLC_SLC0_TX_OVF_INT_ENA1_M (BIT(11)) +#define SLC_SLC0_TX_OVF_INT_ENA1_V 0x1 +#define SLC_SLC0_TX_OVF_INT_ENA1_S 11 +/* SLC_SLC0_RX_UDF_INT_ENA1 : R/W ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_UDF_INT_ENA1 (BIT(10)) +#define SLC_SLC0_RX_UDF_INT_ENA1_M (BIT(10)) +#define SLC_SLC0_RX_UDF_INT_ENA1_V 0x1 +#define SLC_SLC0_RX_UDF_INT_ENA1_S 10 +/* SLC_SLC0_TX_START_INT_ENA1 : R/W ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_TX_START_INT_ENA1 (BIT(9)) +#define SLC_SLC0_TX_START_INT_ENA1_M (BIT(9)) +#define SLC_SLC0_TX_START_INT_ENA1_V 0x1 +#define SLC_SLC0_TX_START_INT_ENA1_S 9 +/* SLC_SLC0_RX_START_INT_ENA1 : R/W ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC0_RX_START_INT_ENA1 (BIT(8)) +#define SLC_SLC0_RX_START_INT_ENA1_M (BIT(8)) +#define SLC_SLC0_RX_START_INT_ENA1_V 0x1 +#define SLC_SLC0_RX_START_INT_ENA1_S 8 +/* SLC_FRHOST_BIT7_INT_ENA1 : R/W ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT7_INT_ENA1 (BIT(7)) +#define SLC_FRHOST_BIT7_INT_ENA1_M (BIT(7)) +#define SLC_FRHOST_BIT7_INT_ENA1_V 0x1 +#define SLC_FRHOST_BIT7_INT_ENA1_S 7 +/* SLC_FRHOST_BIT6_INT_ENA1 : R/W ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT6_INT_ENA1 (BIT(6)) +#define SLC_FRHOST_BIT6_INT_ENA1_M (BIT(6)) +#define SLC_FRHOST_BIT6_INT_ENA1_V 0x1 +#define SLC_FRHOST_BIT6_INT_ENA1_S 6 +/* SLC_FRHOST_BIT5_INT_ENA1 : R/W ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT5_INT_ENA1 (BIT(5)) +#define SLC_FRHOST_BIT5_INT_ENA1_M (BIT(5)) +#define SLC_FRHOST_BIT5_INT_ENA1_V 0x1 +#define SLC_FRHOST_BIT5_INT_ENA1_S 5 +/* SLC_FRHOST_BIT4_INT_ENA1 : R/W ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT4_INT_ENA1 (BIT(4)) +#define SLC_FRHOST_BIT4_INT_ENA1_M (BIT(4)) +#define SLC_FRHOST_BIT4_INT_ENA1_V 0x1 +#define SLC_FRHOST_BIT4_INT_ENA1_S 4 +/* SLC_FRHOST_BIT3_INT_ENA1 : R/W ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT3_INT_ENA1 (BIT(3)) +#define SLC_FRHOST_BIT3_INT_ENA1_M (BIT(3)) +#define SLC_FRHOST_BIT3_INT_ENA1_V 0x1 +#define SLC_FRHOST_BIT3_INT_ENA1_S 3 +/* SLC_FRHOST_BIT2_INT_ENA1 : R/W ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT2_INT_ENA1 (BIT(2)) +#define SLC_FRHOST_BIT2_INT_ENA1_M (BIT(2)) +#define SLC_FRHOST_BIT2_INT_ENA1_V 0x1 +#define SLC_FRHOST_BIT2_INT_ENA1_S 2 +/* SLC_FRHOST_BIT1_INT_ENA1 : R/W ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT1_INT_ENA1 (BIT(1)) +#define SLC_FRHOST_BIT1_INT_ENA1_M (BIT(1)) +#define SLC_FRHOST_BIT1_INT_ENA1_V 0x1 +#define SLC_FRHOST_BIT1_INT_ENA1_S 1 +/* SLC_FRHOST_BIT0_INT_ENA1 : R/W ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT0_INT_ENA1 (BIT(0)) +#define SLC_FRHOST_BIT0_INT_ENA1_M (BIT(0)) +#define SLC_FRHOST_BIT0_INT_ENA1_V 0x1 +#define SLC_FRHOST_BIT0_INT_ENA1_S 0 + +#define SLC_1INT_ST1_REG (DR_REG_SLC_BASE + 0x144) +/* SLC_SLC1_TX_ERR_EOF_INT_ST1 : RO ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_ERR_EOF_INT_ST1 (BIT(24)) +#define SLC_SLC1_TX_ERR_EOF_INT_ST1_M (BIT(24)) +#define SLC_SLC1_TX_ERR_EOF_INT_ST1_V 0x1 +#define SLC_SLC1_TX_ERR_EOF_INT_ST1_S 24 +/* SLC_SLC1_WR_RETRY_DONE_INT_ST1 : RO ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_WR_RETRY_DONE_INT_ST1 (BIT(23)) +#define SLC_SLC1_WR_RETRY_DONE_INT_ST1_M (BIT(23)) +#define SLC_SLC1_WR_RETRY_DONE_INT_ST1_V 0x1 +#define SLC_SLC1_WR_RETRY_DONE_INT_ST1_S 23 +/* SLC_SLC1_HOST_RD_ACK_INT_ST1 : RO ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_HOST_RD_ACK_INT_ST1 (BIT(22)) +#define SLC_SLC1_HOST_RD_ACK_INT_ST1_M (BIT(22)) +#define SLC_SLC1_HOST_RD_ACK_INT_ST1_V 0x1 +#define SLC_SLC1_HOST_RD_ACK_INT_ST1_S 22 +/* SLC_SLC1_TX_DSCR_EMPTY_INT_ST1 : RO ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DSCR_EMPTY_INT_ST1 (BIT(21)) +#define SLC_SLC1_TX_DSCR_EMPTY_INT_ST1_M (BIT(21)) +#define SLC_SLC1_TX_DSCR_EMPTY_INT_ST1_V 0x1 +#define SLC_SLC1_TX_DSCR_EMPTY_INT_ST1_S 21 +/* SLC_SLC1_RX_DSCR_ERR_INT_ST1 : RO ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_DSCR_ERR_INT_ST1 (BIT(20)) +#define SLC_SLC1_RX_DSCR_ERR_INT_ST1_M (BIT(20)) +#define SLC_SLC1_RX_DSCR_ERR_INT_ST1_V 0x1 +#define SLC_SLC1_RX_DSCR_ERR_INT_ST1_S 20 +/* SLC_SLC1_TX_DSCR_ERR_INT_ST1 : RO ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DSCR_ERR_INT_ST1 (BIT(19)) +#define SLC_SLC1_TX_DSCR_ERR_INT_ST1_M (BIT(19)) +#define SLC_SLC1_TX_DSCR_ERR_INT_ST1_V 0x1 +#define SLC_SLC1_TX_DSCR_ERR_INT_ST1_S 19 +/* SLC_SLC1_TOHOST_INT_ST1 : RO ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOHOST_INT_ST1 (BIT(18)) +#define SLC_SLC1_TOHOST_INT_ST1_M (BIT(18)) +#define SLC_SLC1_TOHOST_INT_ST1_V 0x1 +#define SLC_SLC1_TOHOST_INT_ST1_S 18 +/* SLC_SLC1_RX_EOF_INT_ST1 : RO ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_EOF_INT_ST1 (BIT(17)) +#define SLC_SLC1_RX_EOF_INT_ST1_M (BIT(17)) +#define SLC_SLC1_RX_EOF_INT_ST1_V 0x1 +#define SLC_SLC1_RX_EOF_INT_ST1_S 17 +/* SLC_SLC1_RX_DONE_INT_ST1 : RO ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_DONE_INT_ST1 (BIT(16)) +#define SLC_SLC1_RX_DONE_INT_ST1_M (BIT(16)) +#define SLC_SLC1_RX_DONE_INT_ST1_V 0x1 +#define SLC_SLC1_RX_DONE_INT_ST1_S 16 +/* SLC_SLC1_TX_SUC_EOF_INT_ST1 : RO ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_SUC_EOF_INT_ST1 (BIT(15)) +#define SLC_SLC1_TX_SUC_EOF_INT_ST1_M (BIT(15)) +#define SLC_SLC1_TX_SUC_EOF_INT_ST1_V 0x1 +#define SLC_SLC1_TX_SUC_EOF_INT_ST1_S 15 +/* SLC_SLC1_TX_DONE_INT_ST1 : RO ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DONE_INT_ST1 (BIT(14)) +#define SLC_SLC1_TX_DONE_INT_ST1_M (BIT(14)) +#define SLC_SLC1_TX_DONE_INT_ST1_V 0x1 +#define SLC_SLC1_TX_DONE_INT_ST1_S 14 +/* SLC_SLC1_TOKEN1_1TO0_INT_ST1 : RO ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN1_1TO0_INT_ST1 (BIT(13)) +#define SLC_SLC1_TOKEN1_1TO0_INT_ST1_M (BIT(13)) +#define SLC_SLC1_TOKEN1_1TO0_INT_ST1_V 0x1 +#define SLC_SLC1_TOKEN1_1TO0_INT_ST1_S 13 +/* SLC_SLC1_TOKEN0_1TO0_INT_ST1 : RO ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN0_1TO0_INT_ST1 (BIT(12)) +#define SLC_SLC1_TOKEN0_1TO0_INT_ST1_M (BIT(12)) +#define SLC_SLC1_TOKEN0_1TO0_INT_ST1_V 0x1 +#define SLC_SLC1_TOKEN0_1TO0_INT_ST1_S 12 +/* SLC_SLC1_TX_OVF_INT_ST1 : RO ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_OVF_INT_ST1 (BIT(11)) +#define SLC_SLC1_TX_OVF_INT_ST1_M (BIT(11)) +#define SLC_SLC1_TX_OVF_INT_ST1_V 0x1 +#define SLC_SLC1_TX_OVF_INT_ST1_S 11 +/* SLC_SLC1_RX_UDF_INT_ST1 : RO ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_UDF_INT_ST1 (BIT(10)) +#define SLC_SLC1_RX_UDF_INT_ST1_M (BIT(10)) +#define SLC_SLC1_RX_UDF_INT_ST1_V 0x1 +#define SLC_SLC1_RX_UDF_INT_ST1_S 10 +/* SLC_SLC1_TX_START_INT_ST1 : RO ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_START_INT_ST1 (BIT(9)) +#define SLC_SLC1_TX_START_INT_ST1_M (BIT(9)) +#define SLC_SLC1_TX_START_INT_ST1_V 0x1 +#define SLC_SLC1_TX_START_INT_ST1_S 9 +/* SLC_SLC1_RX_START_INT_ST1 : RO ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_START_INT_ST1 (BIT(8)) +#define SLC_SLC1_RX_START_INT_ST1_M (BIT(8)) +#define SLC_SLC1_RX_START_INT_ST1_V 0x1 +#define SLC_SLC1_RX_START_INT_ST1_S 8 +/* SLC_FRHOST_BIT15_INT_ST1 : RO ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT15_INT_ST1 (BIT(7)) +#define SLC_FRHOST_BIT15_INT_ST1_M (BIT(7)) +#define SLC_FRHOST_BIT15_INT_ST1_V 0x1 +#define SLC_FRHOST_BIT15_INT_ST1_S 7 +/* SLC_FRHOST_BIT14_INT_ST1 : RO ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT14_INT_ST1 (BIT(6)) +#define SLC_FRHOST_BIT14_INT_ST1_M (BIT(6)) +#define SLC_FRHOST_BIT14_INT_ST1_V 0x1 +#define SLC_FRHOST_BIT14_INT_ST1_S 6 +/* SLC_FRHOST_BIT13_INT_ST1 : RO ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT13_INT_ST1 (BIT(5)) +#define SLC_FRHOST_BIT13_INT_ST1_M (BIT(5)) +#define SLC_FRHOST_BIT13_INT_ST1_V 0x1 +#define SLC_FRHOST_BIT13_INT_ST1_S 5 +/* SLC_FRHOST_BIT12_INT_ST1 : RO ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT12_INT_ST1 (BIT(4)) +#define SLC_FRHOST_BIT12_INT_ST1_M (BIT(4)) +#define SLC_FRHOST_BIT12_INT_ST1_V 0x1 +#define SLC_FRHOST_BIT12_INT_ST1_S 4 +/* SLC_FRHOST_BIT11_INT_ST1 : RO ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT11_INT_ST1 (BIT(3)) +#define SLC_FRHOST_BIT11_INT_ST1_M (BIT(3)) +#define SLC_FRHOST_BIT11_INT_ST1_V 0x1 +#define SLC_FRHOST_BIT11_INT_ST1_S 3 +/* SLC_FRHOST_BIT10_INT_ST1 : RO ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT10_INT_ST1 (BIT(2)) +#define SLC_FRHOST_BIT10_INT_ST1_M (BIT(2)) +#define SLC_FRHOST_BIT10_INT_ST1_V 0x1 +#define SLC_FRHOST_BIT10_INT_ST1_S 2 +/* SLC_FRHOST_BIT9_INT_ST1 : RO ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT9_INT_ST1 (BIT(1)) +#define SLC_FRHOST_BIT9_INT_ST1_M (BIT(1)) +#define SLC_FRHOST_BIT9_INT_ST1_V 0x1 +#define SLC_FRHOST_BIT9_INT_ST1_S 1 +/* SLC_FRHOST_BIT8_INT_ST1 : RO ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT8_INT_ST1 (BIT(0)) +#define SLC_FRHOST_BIT8_INT_ST1_M (BIT(0)) +#define SLC_FRHOST_BIT8_INT_ST1_V 0x1 +#define SLC_FRHOST_BIT8_INT_ST1_S 0 + +#define SLC_1INT_ENA1_REG (DR_REG_SLC_BASE + 0x148) +/* SLC_SLC1_TX_ERR_EOF_INT_ENA1 : R/W ;bitpos:[24] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_ERR_EOF_INT_ENA1 (BIT(24)) +#define SLC_SLC1_TX_ERR_EOF_INT_ENA1_M (BIT(24)) +#define SLC_SLC1_TX_ERR_EOF_INT_ENA1_V 0x1 +#define SLC_SLC1_TX_ERR_EOF_INT_ENA1_S 24 +/* SLC_SLC1_WR_RETRY_DONE_INT_ENA1 : R/W ;bitpos:[23] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_WR_RETRY_DONE_INT_ENA1 (BIT(23)) +#define SLC_SLC1_WR_RETRY_DONE_INT_ENA1_M (BIT(23)) +#define SLC_SLC1_WR_RETRY_DONE_INT_ENA1_V 0x1 +#define SLC_SLC1_WR_RETRY_DONE_INT_ENA1_S 23 +/* SLC_SLC1_HOST_RD_ACK_INT_ENA1 : R/W ;bitpos:[22] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_HOST_RD_ACK_INT_ENA1 (BIT(22)) +#define SLC_SLC1_HOST_RD_ACK_INT_ENA1_M (BIT(22)) +#define SLC_SLC1_HOST_RD_ACK_INT_ENA1_V 0x1 +#define SLC_SLC1_HOST_RD_ACK_INT_ENA1_S 22 +/* SLC_SLC1_TX_DSCR_EMPTY_INT_ENA1 : R/W ;bitpos:[21] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DSCR_EMPTY_INT_ENA1 (BIT(21)) +#define SLC_SLC1_TX_DSCR_EMPTY_INT_ENA1_M (BIT(21)) +#define SLC_SLC1_TX_DSCR_EMPTY_INT_ENA1_V 0x1 +#define SLC_SLC1_TX_DSCR_EMPTY_INT_ENA1_S 21 +/* SLC_SLC1_RX_DSCR_ERR_INT_ENA1 : R/W ;bitpos:[20] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_DSCR_ERR_INT_ENA1 (BIT(20)) +#define SLC_SLC1_RX_DSCR_ERR_INT_ENA1_M (BIT(20)) +#define SLC_SLC1_RX_DSCR_ERR_INT_ENA1_V 0x1 +#define SLC_SLC1_RX_DSCR_ERR_INT_ENA1_S 20 +/* SLC_SLC1_TX_DSCR_ERR_INT_ENA1 : R/W ;bitpos:[19] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DSCR_ERR_INT_ENA1 (BIT(19)) +#define SLC_SLC1_TX_DSCR_ERR_INT_ENA1_M (BIT(19)) +#define SLC_SLC1_TX_DSCR_ERR_INT_ENA1_V 0x1 +#define SLC_SLC1_TX_DSCR_ERR_INT_ENA1_S 19 +/* SLC_SLC1_TOHOST_INT_ENA1 : R/W ;bitpos:[18] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOHOST_INT_ENA1 (BIT(18)) +#define SLC_SLC1_TOHOST_INT_ENA1_M (BIT(18)) +#define SLC_SLC1_TOHOST_INT_ENA1_V 0x1 +#define SLC_SLC1_TOHOST_INT_ENA1_S 18 +/* SLC_SLC1_RX_EOF_INT_ENA1 : R/W ;bitpos:[17] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_EOF_INT_ENA1 (BIT(17)) +#define SLC_SLC1_RX_EOF_INT_ENA1_M (BIT(17)) +#define SLC_SLC1_RX_EOF_INT_ENA1_V 0x1 +#define SLC_SLC1_RX_EOF_INT_ENA1_S 17 +/* SLC_SLC1_RX_DONE_INT_ENA1 : R/W ;bitpos:[16] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_DONE_INT_ENA1 (BIT(16)) +#define SLC_SLC1_RX_DONE_INT_ENA1_M (BIT(16)) +#define SLC_SLC1_RX_DONE_INT_ENA1_V 0x1 +#define SLC_SLC1_RX_DONE_INT_ENA1_S 16 +/* SLC_SLC1_TX_SUC_EOF_INT_ENA1 : R/W ;bitpos:[15] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_SUC_EOF_INT_ENA1 (BIT(15)) +#define SLC_SLC1_TX_SUC_EOF_INT_ENA1_M (BIT(15)) +#define SLC_SLC1_TX_SUC_EOF_INT_ENA1_V 0x1 +#define SLC_SLC1_TX_SUC_EOF_INT_ENA1_S 15 +/* SLC_SLC1_TX_DONE_INT_ENA1 : R/W ;bitpos:[14] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_DONE_INT_ENA1 (BIT(14)) +#define SLC_SLC1_TX_DONE_INT_ENA1_M (BIT(14)) +#define SLC_SLC1_TX_DONE_INT_ENA1_V 0x1 +#define SLC_SLC1_TX_DONE_INT_ENA1_S 14 +/* SLC_SLC1_TOKEN1_1TO0_INT_ENA1 : R/W ;bitpos:[13] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN1_1TO0_INT_ENA1 (BIT(13)) +#define SLC_SLC1_TOKEN1_1TO0_INT_ENA1_M (BIT(13)) +#define SLC_SLC1_TOKEN1_1TO0_INT_ENA1_V 0x1 +#define SLC_SLC1_TOKEN1_1TO0_INT_ENA1_S 13 +/* SLC_SLC1_TOKEN0_1TO0_INT_ENA1 : R/W ;bitpos:[12] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TOKEN0_1TO0_INT_ENA1 (BIT(12)) +#define SLC_SLC1_TOKEN0_1TO0_INT_ENA1_M (BIT(12)) +#define SLC_SLC1_TOKEN0_1TO0_INT_ENA1_V 0x1 +#define SLC_SLC1_TOKEN0_1TO0_INT_ENA1_S 12 +/* SLC_SLC1_TX_OVF_INT_ENA1 : R/W ;bitpos:[11] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_OVF_INT_ENA1 (BIT(11)) +#define SLC_SLC1_TX_OVF_INT_ENA1_M (BIT(11)) +#define SLC_SLC1_TX_OVF_INT_ENA1_V 0x1 +#define SLC_SLC1_TX_OVF_INT_ENA1_S 11 +/* SLC_SLC1_RX_UDF_INT_ENA1 : R/W ;bitpos:[10] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_UDF_INT_ENA1 (BIT(10)) +#define SLC_SLC1_RX_UDF_INT_ENA1_M (BIT(10)) +#define SLC_SLC1_RX_UDF_INT_ENA1_V 0x1 +#define SLC_SLC1_RX_UDF_INT_ENA1_S 10 +/* SLC_SLC1_TX_START_INT_ENA1 : R/W ;bitpos:[9] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_TX_START_INT_ENA1 (BIT(9)) +#define SLC_SLC1_TX_START_INT_ENA1_M (BIT(9)) +#define SLC_SLC1_TX_START_INT_ENA1_V 0x1 +#define SLC_SLC1_TX_START_INT_ENA1_S 9 +/* SLC_SLC1_RX_START_INT_ENA1 : R/W ;bitpos:[8] ;default: 1'b0 ; */ +/*description: */ +#define SLC_SLC1_RX_START_INT_ENA1 (BIT(8)) +#define SLC_SLC1_RX_START_INT_ENA1_M (BIT(8)) +#define SLC_SLC1_RX_START_INT_ENA1_V 0x1 +#define SLC_SLC1_RX_START_INT_ENA1_S 8 +/* SLC_FRHOST_BIT15_INT_ENA1 : R/W ;bitpos:[7] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT15_INT_ENA1 (BIT(7)) +#define SLC_FRHOST_BIT15_INT_ENA1_M (BIT(7)) +#define SLC_FRHOST_BIT15_INT_ENA1_V 0x1 +#define SLC_FRHOST_BIT15_INT_ENA1_S 7 +/* SLC_FRHOST_BIT14_INT_ENA1 : R/W ;bitpos:[6] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT14_INT_ENA1 (BIT(6)) +#define SLC_FRHOST_BIT14_INT_ENA1_M (BIT(6)) +#define SLC_FRHOST_BIT14_INT_ENA1_V 0x1 +#define SLC_FRHOST_BIT14_INT_ENA1_S 6 +/* SLC_FRHOST_BIT13_INT_ENA1 : R/W ;bitpos:[5] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT13_INT_ENA1 (BIT(5)) +#define SLC_FRHOST_BIT13_INT_ENA1_M (BIT(5)) +#define SLC_FRHOST_BIT13_INT_ENA1_V 0x1 +#define SLC_FRHOST_BIT13_INT_ENA1_S 5 +/* SLC_FRHOST_BIT12_INT_ENA1 : R/W ;bitpos:[4] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT12_INT_ENA1 (BIT(4)) +#define SLC_FRHOST_BIT12_INT_ENA1_M (BIT(4)) +#define SLC_FRHOST_BIT12_INT_ENA1_V 0x1 +#define SLC_FRHOST_BIT12_INT_ENA1_S 4 +/* SLC_FRHOST_BIT11_INT_ENA1 : R/W ;bitpos:[3] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT11_INT_ENA1 (BIT(3)) +#define SLC_FRHOST_BIT11_INT_ENA1_M (BIT(3)) +#define SLC_FRHOST_BIT11_INT_ENA1_V 0x1 +#define SLC_FRHOST_BIT11_INT_ENA1_S 3 +/* SLC_FRHOST_BIT10_INT_ENA1 : R/W ;bitpos:[2] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT10_INT_ENA1 (BIT(2)) +#define SLC_FRHOST_BIT10_INT_ENA1_M (BIT(2)) +#define SLC_FRHOST_BIT10_INT_ENA1_V 0x1 +#define SLC_FRHOST_BIT10_INT_ENA1_S 2 +/* SLC_FRHOST_BIT9_INT_ENA1 : R/W ;bitpos:[1] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT9_INT_ENA1 (BIT(1)) +#define SLC_FRHOST_BIT9_INT_ENA1_M (BIT(1)) +#define SLC_FRHOST_BIT9_INT_ENA1_V 0x1 +#define SLC_FRHOST_BIT9_INT_ENA1_S 1 +/* SLC_FRHOST_BIT8_INT_ENA1 : R/W ;bitpos:[0] ;default: 1'b0 ; */ +/*description: */ +#define SLC_FRHOST_BIT8_INT_ENA1 (BIT(0)) +#define SLC_FRHOST_BIT8_INT_ENA1_M (BIT(0)) +#define SLC_FRHOST_BIT8_INT_ENA1_V 0x1 +#define SLC_FRHOST_BIT8_INT_ENA1_S 0 + +#define SLC_DATE_REG (DR_REG_SLC_BASE + 0x1F8) +/* SLC_DATE : R/W ;bitpos:[31:0] ;default: 32'h16022500 ; */ +/*description: */ +#define SLC_DATE 0xFFFFFFFF +#define SLC_DATE_M ((SLC_DATE_V)<<(SLC_DATE_S)) +#define SLC_DATE_V 0xFFFFFFFF +#define SLC_DATE_S 0 + +#define SLC_ID_REG (DR_REG_SLC_BASE + 0x1FC) +/* SLC_ID : R/W ;bitpos:[31:0] ;default: 32'h0100 ; */ +/*description: */ +#define SLC_ID 0xFFFFFFFF +#define SLC_ID_M ((SLC_ID_V)<<(SLC_ID_S)) +#define SLC_ID_V 0xFFFFFFFF +#define SLC_ID_S 0 + + + + +#endif /*_SOC_SLC_REG_H_ */ + + diff --git a/components/soc/esp32/include/soc/slc_struct.h b/components/soc/esp32/include/soc/slc_struct.h new file mode 100644 index 0000000000..3d93ceef71 --- /dev/null +++ b/components/soc/esp32/include/soc/slc_struct.h @@ -0,0 +1,858 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef _SOC_SLC_STRUCT_H_ +#define _SOC_SLC_STRUCT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef volatile struct { + union { + struct { + uint32_t slc0_tx_rst: 1; + uint32_t slc0_rx_rst: 1; + uint32_t ahbm_fifo_rst: 1; + uint32_t ahbm_rst: 1; + uint32_t slc0_tx_loop_test: 1; + uint32_t slc0_rx_loop_test: 1; + uint32_t slc0_rx_auto_wrback: 1; + uint32_t slc0_rx_no_restart_clr: 1; + uint32_t slc0_rxdscr_burst_en: 1; + uint32_t slc0_rxdata_burst_en: 1; + uint32_t slc0_rxlink_auto_ret: 1; + uint32_t slc0_txlink_auto_ret: 1; + uint32_t slc0_txdscr_burst_en: 1; + uint32_t slc0_txdata_burst_en: 1; + uint32_t slc0_token_auto_clr: 1; + uint32_t slc0_token_sel: 1; + uint32_t slc1_tx_rst: 1; + uint32_t slc1_rx_rst: 1; + uint32_t slc0_wr_retry_mask_en: 1; + uint32_t slc1_wr_retry_mask_en: 1; + uint32_t slc1_tx_loop_test: 1; + uint32_t slc1_rx_loop_test: 1; + uint32_t slc1_rx_auto_wrback: 1; + uint32_t slc1_rx_no_restart_clr: 1; + uint32_t slc1_rxdscr_burst_en: 1; + uint32_t slc1_rxdata_burst_en: 1; + uint32_t slc1_rxlink_auto_ret: 1; + uint32_t slc1_txlink_auto_ret: 1; + uint32_t slc1_txdscr_burst_en: 1; + uint32_t slc1_txdata_burst_en: 1; + uint32_t slc1_token_auto_clr: 1; + uint32_t slc1_token_sel: 1; + }; + uint32_t val; + } conf0; + union { + struct { + uint32_t frhost_bit0: 1; + uint32_t frhost_bit1: 1; + uint32_t frhost_bit2: 1; + uint32_t frhost_bit3: 1; + uint32_t frhost_bit4: 1; + uint32_t frhost_bit5: 1; + uint32_t frhost_bit6: 1; + uint32_t frhost_bit7: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t tx_done: 1; + uint32_t tx_suc_eof: 1; + uint32_t rx_done: 1; + uint32_t rx_eof: 1; + uint32_t tohost: 1; + uint32_t tx_dscr_err: 1; + uint32_t rx_dscr_err: 1; + uint32_t tx_dscr_empty: 1; + uint32_t host_rd_ack: 1; + uint32_t wr_retry_done: 1; + uint32_t tx_err_eof: 1; + uint32_t cmd_dtc: 1; + uint32_t rx_quick_eof: 1; + uint32_t reserved27: 5; + }; + uint32_t val; + } slc0_int_raw; + union { + struct { + uint32_t frhost_bit0: 1; + uint32_t frhost_bit1: 1; + uint32_t frhost_bit2: 1; + uint32_t frhost_bit3: 1; + uint32_t frhost_bit4: 1; + uint32_t frhost_bit5: 1; + uint32_t frhost_bit6: 1; + uint32_t frhost_bit7: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t tx_done: 1; + uint32_t tx_suc_eof: 1; + uint32_t rx_done: 1; + uint32_t rx_eof: 1; + uint32_t tohost: 1; + uint32_t tx_dscr_err: 1; + uint32_t rx_dscr_err: 1; + uint32_t tx_dscr_empty: 1; + uint32_t host_rd_ack: 1; + uint32_t wr_retry_done: 1; + uint32_t tx_err_eof: 1; + uint32_t cmd_dtc: 1; + uint32_t rx_quick_eof: 1; + uint32_t reserved27: 5; + }; + uint32_t val; + } slc0_int_st; + union { + struct { + uint32_t frhost_bit0: 1; + uint32_t frhost_bit1: 1; + uint32_t frhost_bit2: 1; + uint32_t frhost_bit3: 1; + uint32_t frhost_bit4: 1; + uint32_t frhost_bit5: 1; + uint32_t frhost_bit6: 1; + uint32_t frhost_bit7: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t tx_done: 1; + uint32_t tx_suc_eof: 1; + uint32_t rx_done: 1; + uint32_t rx_eof: 1; + uint32_t tohost: 1; + uint32_t tx_dscr_err: 1; + uint32_t rx_dscr_err: 1; + uint32_t tx_dscr_empty: 1; + uint32_t host_rd_ack: 1; + uint32_t wr_retry_done: 1; + uint32_t tx_err_eof: 1; + uint32_t cmd_dtc: 1; + uint32_t rx_quick_eof: 1; + uint32_t reserved27: 5; + }; + uint32_t val; + } slc0_int_ena; + union { + struct { + uint32_t frhost_bit0: 1; + uint32_t frhost_bit1: 1; + uint32_t frhost_bit2: 1; + uint32_t frhost_bit3: 1; + uint32_t frhost_bit4: 1; + uint32_t frhost_bit5: 1; + uint32_t frhost_bit6: 1; + uint32_t frhost_bit7: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t tx_done: 1; + uint32_t tx_suc_eof: 1; + uint32_t rx_done: 1; + uint32_t rx_eof: 1; + uint32_t tohost: 1; + uint32_t tx_dscr_err: 1; + uint32_t rx_dscr_err: 1; + uint32_t tx_dscr_empty: 1; + uint32_t host_rd_ack: 1; + uint32_t wr_retry_done: 1; + uint32_t tx_err_eof: 1; + uint32_t cmd_dtc: 1; + uint32_t rx_quick_eof: 1; + uint32_t reserved27: 5; + }; + uint32_t val; + } slc0_int_clr; + union { + struct { + uint32_t frhost_bit8: 1; + uint32_t frhost_bit9: 1; + uint32_t frhost_bit10: 1; + uint32_t frhost_bit11: 1; + uint32_t frhost_bit12: 1; + uint32_t frhost_bit13: 1; + uint32_t frhost_bit14: 1; + uint32_t frhost_bit15: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t tx_done: 1; + uint32_t tx_suc_eof: 1; + uint32_t rx_done: 1; + uint32_t rx_eof: 1; + uint32_t tohost: 1; + uint32_t tx_dscr_err: 1; + uint32_t rx_dscr_err: 1; + uint32_t tx_dscr_empty: 1; + uint32_t host_rd_ack: 1; + uint32_t wr_retry_done: 1; + uint32_t tx_err_eof: 1; + uint32_t reserved25: 7; + }; + uint32_t val; + } slc1_int_raw; + union { + struct { + uint32_t frhost_bit8: 1; + uint32_t frhost_bit9: 1; + uint32_t frhost_bit10: 1; + uint32_t frhost_bit11: 1; + uint32_t frhost_bit12: 1; + uint32_t frhost_bit13: 1; + uint32_t frhost_bit14: 1; + uint32_t frhost_bit15: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t tx_done: 1; + uint32_t tx_suc_eof: 1; + uint32_t rx_done: 1; + uint32_t rx_eof: 1; + uint32_t tohost: 1; + uint32_t tx_dscr_err: 1; + uint32_t rx_dscr_err: 1; + uint32_t tx_dscr_empty: 1; + uint32_t host_rd_ack: 1; + uint32_t wr_retry_done: 1; + uint32_t tx_err_eof: 1; + uint32_t reserved25: 7; + }; + uint32_t val; + } slc1_int_st; + union { + struct { + uint32_t frhost_bit8: 1; + uint32_t frhost_bit9: 1; + uint32_t frhost_bit10: 1; + uint32_t frhost_bit11: 1; + uint32_t frhost_bit12: 1; + uint32_t frhost_bit13: 1; + uint32_t frhost_bit14: 1; + uint32_t frhost_bit15: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t tx_done: 1; + uint32_t tx_suc_eof: 1; + uint32_t rx_done: 1; + uint32_t rx_eof: 1; + uint32_t tohost: 1; + uint32_t tx_dscr_err: 1; + uint32_t rx_dscr_err: 1; + uint32_t tx_dscr_empty: 1; + uint32_t host_rd_ack: 1; + uint32_t wr_retry_done: 1; + uint32_t tx_err_eof: 1; + uint32_t reserved25: 7; + }; + uint32_t val; + } slc1_int_ena; + union { + struct { + uint32_t frhost_bit8: 1; + uint32_t frhost_bit9: 1; + uint32_t frhost_bit10: 1; + uint32_t frhost_bit11: 1; + uint32_t frhost_bit12: 1; + uint32_t frhost_bit13: 1; + uint32_t frhost_bit14: 1; + uint32_t frhost_bit15: 1; + uint32_t rx_start: 1; + uint32_t tx_start: 1; + uint32_t rx_udf: 1; + uint32_t tx_ovf: 1; + uint32_t token0_1to0: 1; + uint32_t token1_1to0: 1; + uint32_t tx_done: 1; + uint32_t tx_suc_eof: 1; + uint32_t rx_done: 1; + uint32_t rx_eof: 1; + uint32_t tohost: 1; + uint32_t tx_dscr_err: 1; + uint32_t rx_dscr_err: 1; + uint32_t tx_dscr_empty: 1; + uint32_t host_rd_ack: 1; + uint32_t wr_retry_done: 1; + uint32_t tx_err_eof: 1; + uint32_t reserved25: 7; + }; + uint32_t val; + } slc1_int_clr; + union { + struct { + uint32_t slc0_rx_full: 1; + uint32_t slc0_rx_empty: 1; + uint32_t reserved2: 14; + uint32_t slc1_rx_full: 1; + uint32_t slc1_rx_empty: 1; + uint32_t reserved18:14; + }; + uint32_t val; + } rx_status; + union { + struct { + uint32_t rxfifo_wdata: 9; + uint32_t reserved9: 7; + uint32_t rxfifo_push: 1; + uint32_t reserved17: 15; + }; + uint32_t val; + } slc0_rxfifo_push; + union { + struct { + uint32_t rxfifo_wdata: 9; + uint32_t reserved9: 7; + uint32_t rxfifo_push: 1; + uint32_t reserved17: 15; + }; + uint32_t val; + } slc1_rxfifo_push; + union { + struct { + uint32_t slc0_tx_full: 1; + uint32_t slc0_tx_empty: 1; + uint32_t reserved2: 14; + uint32_t slc1_tx_full: 1; + uint32_t slc1_tx_empty: 1; + uint32_t reserved18:14; + }; + uint32_t val; + } tx_status; + union { + struct { + uint32_t txfifo_rdata: 11; + uint32_t reserved11: 5; + uint32_t txfifo_pop: 1; + uint32_t reserved17: 15; + }; + uint32_t val; + } slc0_txfifo_pop; + union { + struct { + uint32_t txfifo_rdata: 11; + uint32_t reserved11: 5; + uint32_t txfifo_pop: 1; + uint32_t reserved17: 15; + }; + uint32_t val; + } slc1_txfifo_pop; + union { + struct { + uint32_t addr: 20; + uint32_t reserved20: 8; + uint32_t stop: 1; + uint32_t start: 1; + uint32_t restart: 1; + uint32_t park: 1; + }; + uint32_t val; + } slc0_rx_link; + union { + struct { + uint32_t addr: 20; + uint32_t reserved20: 8; + uint32_t stop: 1; + uint32_t start: 1; + uint32_t restart: 1; + uint32_t park: 1; + }; + uint32_t val; + } slc0_tx_link; + union { + struct { + uint32_t addr: 20; + uint32_t bt_packet: 1; + uint32_t reserved21: 7; + uint32_t stop: 1; + uint32_t start: 1; + uint32_t restart: 1; + uint32_t park: 1; + }; + uint32_t val; + } slc1_rx_link; + union { + struct { + uint32_t addr: 20; + uint32_t reserved20: 8; + uint32_t stop: 1; + uint32_t start: 1; + uint32_t restart: 1; + uint32_t park: 1; + }; + uint32_t val; + } slc1_tx_link; + union { + struct { + uint32_t slc0_intvec: 8; + uint32_t reserved8: 8; + uint32_t slc1_intvec: 8; + uint32_t reserved24: 8; + }; + uint32_t val; + } intvec_tohost; + union { + struct { + uint32_t wdata: 12; + uint32_t wr: 1; + uint32_t inc: 1; + uint32_t inc_more: 1; + uint32_t reserved15: 1; + uint32_t token0: 12; + uint32_t reserved28: 4; + }; + uint32_t val; + } slc0_token0; + union { + struct { + uint32_t wdata: 12; + uint32_t wr: 1; + uint32_t inc: 1; + uint32_t inc_more: 1; + uint32_t reserved15: 1; + uint32_t token1: 12; + uint32_t reserved28: 4; + }; + uint32_t val; + } slc0_token1; + union { + struct { + uint32_t wdata: 12; + uint32_t wr: 1; + uint32_t inc: 1; + uint32_t inc_more: 1; + uint32_t reserved15: 1; + uint32_t token0: 12; + uint32_t reserved28: 4; + }; + uint32_t val; + } slc1_token0; + union { + struct { + uint32_t wdata: 12; + uint32_t wr: 1; + uint32_t inc: 1; + uint32_t inc_more: 1; + uint32_t reserved15: 1; + uint32_t token1: 12; + uint32_t reserved28: 4; + }; + uint32_t val; + } slc1_token1; + union { + struct { + uint32_t slc0_check_owner: 1; + uint32_t slc0_tx_check_sum_en: 1; + uint32_t slc0_rx_check_sum_en: 1; + uint32_t cmd_hold_en: 1; + uint32_t slc0_len_auto_clr: 1; + uint32_t slc0_tx_stitch_en: 1; + uint32_t slc0_rx_stitch_en: 1; + uint32_t reserved7: 9; + uint32_t slc1_check_owner: 1; + uint32_t slc1_tx_check_sum_en: 1; + uint32_t slc1_rx_check_sum_en: 1; + uint32_t host_int_level_sel: 1; + uint32_t slc1_tx_stitch_en: 1; + uint32_t slc1_rx_stitch_en: 1; + uint32_t clk_en: 1; + uint32_t reserved23: 9; + }; + uint32_t val; + } conf1; + uint32_t slc0_state0; /**/ + uint32_t slc0_state1; /**/ + uint32_t slc1_state0; /**/ + uint32_t slc1_state1; /**/ + union { + struct { + uint32_t txeof_ena: 6; + uint32_t reserved6: 2; + uint32_t fifo_map_ena: 4; + uint32_t slc0_tx_dummy_mode: 1; + uint32_t hda_map_128k: 1; + uint32_t slc1_tx_dummy_mode: 1; + uint32_t reserved15: 1; + uint32_t tx_push_idle_num:16; + }; + uint32_t val; + } bridge_conf; + uint32_t slc0_to_eof_des_addr; /**/ + uint32_t slc0_tx_eof_des_addr; /**/ + uint32_t slc0_to_eof_bfr_des_addr; /**/ + uint32_t slc1_to_eof_des_addr; /**/ + uint32_t slc1_tx_eof_des_addr; /**/ + uint32_t slc1_to_eof_bfr_des_addr; /**/ + union { + struct { + uint32_t mode: 3; + uint32_t reserved3: 1; + uint32_t addr: 2; + uint32_t reserved6: 26; + }; + uint32_t val; + } ahb_test; + union { + struct { + uint32_t cmd_st: 3; + uint32_t reserved3: 1; + uint32_t func_st: 4; + uint32_t sdio_wakeup: 1; + uint32_t reserved9: 3; + uint32_t bus_st: 3; + uint32_t reserved15: 1; + uint32_t func1_acc_state: 5; + uint32_t reserved21: 3; + uint32_t func2_acc_state: 5; + uint32_t reserved29: 3; + }; + uint32_t val; + } sdio_st; + union { + struct { + uint32_t slc0_token_no_replace: 1; + uint32_t slc0_infor_no_replace: 1; + uint32_t slc0_rx_fill_mode: 1; + uint32_t slc0_rx_eof_mode: 1; + uint32_t slc0_rx_fill_en: 1; + uint32_t slc0_rd_retry_threshold:11; + uint32_t slc1_token_no_replace: 1; + uint32_t slc1_infor_no_replace: 1; + uint32_t slc1_rx_fill_mode: 1; + uint32_t slc1_rx_eof_mode: 1; + uint32_t slc1_rx_fill_en: 1; + uint32_t slc1_rd_retry_threshold:11; + }; + uint32_t val; + } rx_dscr_conf; + uint32_t slc0_txlink_dscr; /**/ + uint32_t slc0_txlink_dscr_bf0; /**/ + uint32_t slc0_txlink_dscr_bf1; /**/ + uint32_t slc0_rxlink_dscr; /**/ + uint32_t slc0_rxlink_dscr_bf0; /**/ + uint32_t slc0_rxlink_dscr_bf1; /**/ + uint32_t slc1_txlink_dscr; /**/ + uint32_t slc1_txlink_dscr_bf0; /**/ + uint32_t slc1_txlink_dscr_bf1; /**/ + uint32_t slc1_rxlink_dscr; /**/ + uint32_t slc1_rxlink_dscr_bf0; /**/ + uint32_t slc1_rxlink_dscr_bf1; /**/ + uint32_t slc0_tx_erreof_des_addr; /**/ + uint32_t slc1_tx_erreof_des_addr; /**/ + union { + struct { + uint32_t slc0_token:12; + uint32_t reserved12: 4; + uint32_t slc1_token:12; + uint32_t reserved28: 4; + }; + uint32_t val; + } token_lat; + union { + struct { + uint32_t wr_retry_threshold:11; + uint32_t reserved11: 21; + }; + uint32_t val; + } tx_dscr_conf; + uint32_t cmd_infor0; /**/ + uint32_t cmd_infor1; /**/ + union { + struct { + uint32_t len_wdata: 20; + uint32_t len_wr: 1; + uint32_t len_inc: 1; + uint32_t len_inc_more: 1; + uint32_t rx_packet_load_en: 1; + uint32_t tx_packet_load_en: 1; + uint32_t rx_get_used_dscr: 1; + uint32_t tx_get_used_dscr: 1; + uint32_t rx_new_pkt_ind: 1; + uint32_t tx_new_pkt_ind: 1; + uint32_t reserved29: 3; + }; + uint32_t val; + } slc0_len_conf; + union { + struct { + uint32_t len: 20; + uint32_t reserved20:12; + }; + uint32_t val; + } slc0_length; + uint32_t slc0_txpkt_h_dscr; /**/ + uint32_t slc0_txpkt_e_dscr; /**/ + uint32_t slc0_rxpkt_h_dscr; /**/ + uint32_t slc0_rxpkt_e_dscr; /**/ + uint32_t slc0_txpktu_h_dscr; /**/ + uint32_t slc0_txpktu_e_dscr; /**/ + uint32_t slc0_rxpktu_h_dscr; /**/ + uint32_t slc0_rxpktu_e_dscr; /**/ + uint32_t reserved_10c; + uint32_t reserved_110; + union { + struct { + uint32_t slc0_position: 8; + uint32_t slc1_position: 8; + uint32_t reserved16: 16; + }; + uint32_t val; + } seq_position; + union { + struct { + uint32_t rx_dscr_rec_lim: 10; + uint32_t reserved10: 22; + }; + uint32_t val; + } slc0_dscr_rec_conf; + union { + struct { + uint32_t dat0_crc_err_cnt: 8; + uint32_t dat1_crc_err_cnt: 8; + uint32_t dat2_crc_err_cnt: 8; + uint32_t dat3_crc_err_cnt: 8; + }; + uint32_t val; + } sdio_crc_st0; + union { + struct { + uint32_t cmd_crc_err_cnt: 8; + uint32_t reserved8: 23; + uint32_t err_cnt_clr: 1; + }; + uint32_t val; + } sdio_crc_st1; + uint32_t slc0_eof_start_des; /**/ + uint32_t slc0_push_dscr_addr; /**/ + uint32_t slc0_done_dscr_addr; /**/ + uint32_t slc0_sub_start_des; /**/ + union { + struct { + uint32_t rx_dscr_cnt_lat: 10; + uint32_t reserved10: 6; + uint32_t rx_get_eof_occ: 1; + uint32_t reserved17: 15; + }; + uint32_t val; + } slc0_dscr_cnt; + union { + struct { + uint32_t len_lim: 20; + uint32_t reserved20:12; + }; + uint32_t val; + } slc0_len_lim_conf; + union { + struct { + uint32_t frhost_bit01: 1; + uint32_t frhost_bit11: 1; + uint32_t frhost_bit21: 1; + uint32_t frhost_bit31: 1; + uint32_t frhost_bit41: 1; + uint32_t frhost_bit51: 1; + uint32_t frhost_bit61: 1; + uint32_t frhost_bit71: 1; + uint32_t rx_start1: 1; + uint32_t tx_start1: 1; + uint32_t rx_udf1: 1; + uint32_t tx_ovf1: 1; + uint32_t token0_1to01: 1; + uint32_t token1_1to01: 1; + uint32_t tx_done1: 1; + uint32_t tx_suc_eof1: 1; + uint32_t rx_done1: 1; + uint32_t rx_eof1: 1; + uint32_t tohost1: 1; + uint32_t tx_dscr_err1: 1; + uint32_t rx_dscr_err1: 1; + uint32_t tx_dscr_empty1: 1; + uint32_t host_rd_ack1: 1; + uint32_t wr_retry_done1: 1; + uint32_t tx_err_eof1: 1; + uint32_t cmd_dtc1: 1; + uint32_t rx_quick_eof1: 1; + uint32_t reserved27: 5; + }; + uint32_t val; + } slc0_int_st1; + union { + struct { + uint32_t frhost_bit01: 1; + uint32_t frhost_bit11: 1; + uint32_t frhost_bit21: 1; + uint32_t frhost_bit31: 1; + uint32_t frhost_bit41: 1; + uint32_t frhost_bit51: 1; + uint32_t frhost_bit61: 1; + uint32_t frhost_bit71: 1; + uint32_t rx_start1: 1; + uint32_t tx_start1: 1; + uint32_t rx_udf1: 1; + uint32_t tx_ovf1: 1; + uint32_t token0_1to01: 1; + uint32_t token1_1to01: 1; + uint32_t tx_done1: 1; + uint32_t tx_suc_eof1: 1; + uint32_t rx_done1: 1; + uint32_t rx_eof1: 1; + uint32_t tohost1: 1; + uint32_t tx_dscr_err1: 1; + uint32_t rx_dscr_err1: 1; + uint32_t tx_dscr_empty1: 1; + uint32_t host_rd_ack1: 1; + uint32_t wr_retry_done1: 1; + uint32_t tx_err_eof1: 1; + uint32_t cmd_dtc1: 1; + uint32_t rx_quick_eof1: 1; + uint32_t reserved27: 5; + }; + uint32_t val; + } slc0_int_ena1; + union { + struct { + uint32_t frhost_bit81: 1; + uint32_t frhost_bit91: 1; + uint32_t frhost_bit101: 1; + uint32_t frhost_bit111: 1; + uint32_t frhost_bit121: 1; + uint32_t frhost_bit131: 1; + uint32_t frhost_bit141: 1; + uint32_t frhost_bit151: 1; + uint32_t rx_start1: 1; + uint32_t tx_start1: 1; + uint32_t rx_udf1: 1; + uint32_t tx_ovf1: 1; + uint32_t token0_1to01: 1; + uint32_t token1_1to01: 1; + uint32_t tx_done1: 1; + uint32_t tx_suc_eof1: 1; + uint32_t rx_done1: 1; + uint32_t rx_eof1: 1; + uint32_t tohost1: 1; + uint32_t tx_dscr_err1: 1; + uint32_t rx_dscr_err1: 1; + uint32_t tx_dscr_empty1: 1; + uint32_t host_rd_ack1: 1; + uint32_t wr_retry_done1: 1; + uint32_t tx_err_eof1: 1; + uint32_t reserved25: 7; + }; + uint32_t val; + } slc1_int_st1; + union { + struct { + uint32_t frhost_bit81: 1; + uint32_t frhost_bit91: 1; + uint32_t frhost_bit101: 1; + uint32_t frhost_bit111: 1; + uint32_t frhost_bit121: 1; + uint32_t frhost_bit131: 1; + uint32_t frhost_bit141: 1; + uint32_t frhost_bit151: 1; + uint32_t rx_start1: 1; + uint32_t tx_start1: 1; + uint32_t rx_udf1: 1; + uint32_t tx_ovf1: 1; + uint32_t token0_1to01: 1; + uint32_t token1_1to01: 1; + uint32_t tx_done1: 1; + uint32_t tx_suc_eof1: 1; + uint32_t rx_done1: 1; + uint32_t rx_eof1: 1; + uint32_t tohost1: 1; + uint32_t tx_dscr_err1: 1; + uint32_t rx_dscr_err1: 1; + uint32_t tx_dscr_empty1: 1; + uint32_t host_rd_ack1: 1; + uint32_t wr_retry_done1: 1; + uint32_t tx_err_eof1: 1; + uint32_t reserved25: 7; + }; + uint32_t val; + } slc1_int_ena1; + uint32_t reserved_14c; + uint32_t reserved_150; + uint32_t reserved_154; + uint32_t reserved_158; + uint32_t reserved_15c; + uint32_t reserved_160; + uint32_t reserved_164; + uint32_t reserved_168; + uint32_t reserved_16c; + uint32_t reserved_170; + uint32_t reserved_174; + uint32_t reserved_178; + uint32_t reserved_17c; + uint32_t reserved_180; + uint32_t reserved_184; + uint32_t reserved_188; + uint32_t reserved_18c; + uint32_t reserved_190; + uint32_t reserved_194; + uint32_t reserved_198; + uint32_t reserved_19c; + uint32_t reserved_1a0; + uint32_t reserved_1a4; + uint32_t reserved_1a8; + uint32_t reserved_1ac; + uint32_t reserved_1b0; + uint32_t reserved_1b4; + uint32_t reserved_1b8; + uint32_t reserved_1bc; + uint32_t reserved_1c0; + uint32_t reserved_1c4; + uint32_t reserved_1c8; + uint32_t reserved_1cc; + uint32_t reserved_1d0; + uint32_t reserved_1d4; + uint32_t reserved_1d8; + uint32_t reserved_1dc; + uint32_t reserved_1e0; + uint32_t reserved_1e4; + uint32_t reserved_1e8; + uint32_t reserved_1ec; + uint32_t reserved_1f0; + uint32_t reserved_1f4; + uint32_t date; /**/ + uint32_t id; /**/ +} slc_dev_t; +extern slc_dev_t SLC; + +#ifdef __cplusplus +} +#endif + +#endif /* _SOC_SLC_STRUCT_H_ */ From f613859e29b47e4cb2a7a00da7d3a78f2b7ccfe1 Mon Sep 17 00:00:00 2001 From: michael Date: Wed, 29 Nov 2017 13:33:07 +0800 Subject: [PATCH 147/187] feat(sdio_slave): add new driver for sdio_slave --- components/driver/include/driver/sdio_slave.h | 290 ++++ components/driver/sdio_slave.c | 1275 +++++++++++++++++ 2 files changed, 1565 insertions(+) create mode 100644 components/driver/include/driver/sdio_slave.h create mode 100644 components/driver/sdio_slave.c diff --git a/components/driver/include/driver/sdio_slave.h b/components/driver/include/driver/sdio_slave.h new file mode 100644 index 0000000000..66b3bc5e21 --- /dev/null +++ b/components/driver/include/driver/sdio_slave.h @@ -0,0 +1,290 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _DRIVER_SDIO_SLAVE_H_ +#define _DRIVER_SDIO_SLAVE_H_ + +#include "freertos/FreeRTOS.h" +#include "freertos/portmacro.h" +#include "esp_err.h" +#include "rom/queue.h" + +#include "soc/host_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SDIO_SLAVE_RECV_MAX_BUFFER (4096-4) + +typedef void(*sdio_event_cb_t)(uint8_t event); + +/// Mask of interrupts sending to the host. +typedef enum { + SDIO_SLAVE_HOSTINT_SEND_NEW_PACKET = HOST_SLC0_RX_NEW_PACKET_INT_ENA, ///< New packet available + SDIO_SLAVE_HOSTINT_RECV_OVF = HOST_SLC0_TX_OVF_INT_ENA, ///< Slave receive buffer overflow + SDIO_SLAVE_HOSTINT_SEND_UDF = HOST_SLC0_RX_UDF_INT_ENA, ///< Slave sending buffer underflow (this case only happen when the host do not request for packet according to the packet len). + SDIO_SLAVE_HOSTINT_BIT7 = HOST_SLC0_TOHOST_BIT7_INT_ENA, ///< General purpose interrupt bits that can be used by the user. + SDIO_SLAVE_HOSTINT_BIT6 = HOST_SLC0_TOHOST_BIT6_INT_ENA, + SDIO_SLAVE_HOSTINT_BIT5 = HOST_SLC0_TOHOST_BIT5_INT_ENA, + SDIO_SLAVE_HOSTINT_BIT4 = HOST_SLC0_TOHOST_BIT4_INT_ENA, + SDIO_SLAVE_HOSTINT_BIT3 = HOST_SLC0_TOHOST_BIT3_INT_ENA, + SDIO_SLAVE_HOSTINT_BIT2 = HOST_SLC0_TOHOST_BIT2_INT_ENA, + SDIO_SLAVE_HOSTINT_BIT1 = HOST_SLC0_TOHOST_BIT1_INT_ENA, + SDIO_SLAVE_HOSTINT_BIT0 = HOST_SLC0_TOHOST_BIT0_INT_ENA, +} sdio_slave_hostint_t; + +/// Timing of SDIO slave +typedef enum { + SDIO_SLAVE_TIMING_NSEND_PSAMPLE = 0,///< Send at negedge, and sample at posedge. Default value for SD protocol. + SDIO_SLAVE_TIMING_NSEND_NSAMPLE, ///< Send at negedge, and sample at negedge + SDIO_SLAVE_TIMING_PSEND_PSAMPLE, ///< Send at posedge, and sample at posedge + SDIO_SLAVE_TIMING_PSEND_NSAMPLE, ///< Send at posedge, and sample at negedge +} sdio_slave_timing_t; + +/// Configuration of SDIO slave mode +typedef enum { + SDIO_SLAVE_SEND_STREAM = 0, ///< Stream mode, all packets to send will be combined as one if possible + SDIO_SLAVE_SEND_PACKET = 1, ///< Packet mode, one packets will be sent one after another (only increase packet_len if last packet sent). +} sdio_slave_sending_mode_t; + +/// Configuration of SDIO slave +typedef struct { + sdio_slave_timing_t timing; ///< timing of sdio_slave. see `sdio_slave_timing_t`. + sdio_slave_sending_mode_t sending_mode; ///< mode of sdio_slave. `SDIO_SLAVE_MODE_STREAM` if the data needs to be sent as much as possible; `SDIO_SLAVE_MODE_PACKET` if the data should be sent in packets. + int send_queue_size; ///< max buffers that can be queued before sending. + size_t recv_buffer_size; + ///< If buffer_size is too small, it costs more CPU time to handle larger number of buffers. + ///< If buffer_size is too large, the space larger than the transaction length is left blank but still counts a buffer, and the buffers are easily run out. + ///< Should be set according to length of data really transferred. + ///< All data that do not fully fill a buffer is still counted as one buffer. E.g. 10 bytes data costs 2 buffers if the size is 8 bytes per buffer. + ///< Buffer size of the slave pre-defined between host and slave before communication. All receive buffer given to the driver should be larger than this. + sdio_event_cb_t event_cb; ///< when the host interrupts slave, this callback will be called with interrupt number (0-7). +} sdio_slave_config_t; + +/** Handle of a receive buffer, register a handle by calling ``sdio_slave_recv_register_buf``. Use the handle to load the buffer to the + * driver, or call ``sdio_slave_recv_unregister_buf`` if it is no longer used. + */ +typedef void *sdio_slave_buf_handle_t; + +/** Initialize the sdio slave driver + * + * @param config Configuration of the sdio slave driver. + * + * @return + * - ESP_ERR_NOT_FOUND if no free interrupt found. + * - ESP_ERR_INVALID_STATE if already initialized. + * - ESP_ERR_NO_MEM if fail due to memory allocation failed. + * - ESP_OK if success + */ +esp_err_t sdio_slave_initialize(sdio_slave_config_t *config); + +/** De-initialize the sdio slave driver to release the resources. + */ +void sdio_slave_deinit(); + +/** Start hardware for sending and receiving, as well as set the IOREADY1 to 1. + * + * @note The driver will continue sending from previous data and PKT_LEN counting, keep data received as well as start receiving from current TOKEN1 counting. + * See ``sdio_slave_reset``. + * + * @return + * - ESP_ERR_INVALID_STATE if already started. + * - ESP_OK otherwise. + */ +esp_err_t sdio_slave_start(); + +/** Stop hardware from sending and receiving, also set IOREADY1 to 0. + * + * @note this will not clear the data already in the driver, and also not reset the PKT_LEN and TOKEN1 counting. Call ``sdio_slave_reset`` to do that. + */ +void sdio_slave_stop(); + +/** Clear the data still in the driver, as well as reset the PKT_LEN and TOKEN1 counting. + * + * @return always return ESP_OK. + */ +esp_err_t sdio_slave_reset(); + +/*--------------------------------------------------------------------------- + * Receive + *--------------------------------------------------------------------------*/ +/** Register buffer used for receiving. All buffers should be registered before used, and then can be used (again) in the driver by the handle returned. + * + * @param start The start address of the buffer. + * + * @note The driver will use and only use the amount of space specified in the `recv_buffer_size` member set in the `sdio_slave_config_t`. + * All buffers should be larger than that. The buffer is used by the DMA, so it should be DMA capable and 32-bit aligned. + * + * @return The buffer handle if success, otherwise NULL. + */ +sdio_slave_buf_handle_t sdio_slave_recv_register_buf(uint8_t *start); + +/** Unregister buffer from driver, and free the space used by the descriptor pointing to the buffer. + * + * @param handle Handle to the buffer to release. + * + * @return ESP_OK if success, ESP_ERR_INVALID_ARG if the handle is NULL or the buffer is being used. + */ +esp_err_t sdio_slave_recv_unregister_buf(sdio_slave_buf_handle_t handle); + +/** Load buffer to the queue waiting to receive data. The driver takes ownership of the buffer until the buffer is returned by + * ``sdio_slave_send_get_finished`` after the transaction is finished. + * + * @param handle Handle to the buffer ready to receive data. + * + * @return + * - ESP_ERR_INVALID_ARG if invalid handle or the buffer is already in the queue. Only after the buffer is returened by + * ``sdio_slave_recv`` can you load it again. + * - ESP_OK if success + */ +esp_err_t sdio_slave_recv_load_buf(sdio_slave_buf_handle_t handle); + +/** Get received data if exist. The driver returns the ownership of the buffer to the app. + * + * @param handle_ret Handle to the buffer holding received data. Use this handle in ``sdio_slave_recv_load_buf`` to receive in the same buffer again. + * @param start_o Start address output, set to NULL if not needed. + * @param len_o Actual length of the data in the buffer, set to NULL if not needed. + * @param wait Time to wait before data received. + * + * @note Call ``sdio_slave_load_buf`` with the handle to re-load the buffer onto the link list, and receive with the same buffer again. + * The address and length of the buffer got here is the same as got from `sdio_slave_get_buffer`. + * + * @return + * - ESP_ERR_INVALID_ARG if handle_ret is NULL + * - ESP_ERR_TIMEOUT if timeout before receiving new data + * - ESP_OK if success + */ +esp_err_t sdio_slave_recv(sdio_slave_buf_handle_t* handle_ret, uint8_t **start_o, size_t *len_o, TickType_t wait); + +/** Retrieve the buffer corresponding to a handle. + * + * @param handle Handle to get the buffer. + * @param len_o Output of buffer length + * + * @return buffer address if success, otherwise NULL. + */ +uint8_t* sdio_slave_recv_get_buf( sdio_slave_buf_handle_t handle, size_t *len_o); + +/*--------------------------------------------------------------------------- + * Send + *--------------------------------------------------------------------------*/ +/** Put a new sending transfer into the send queue. The driver takes ownership of the buffer until the buffer is returned by + * ``sdio_slave_send_get_finished`` after the transaction is finished. + * + * @param addr Address for data to be sent. The buffer should be DMA capable and 32-bit aligned. + * @param len Length of the data, should not be longer than 4092 bytes (may support longer in the future). + * @param arg Argument to returned in ``sdio_slave_send_get_finished``. The argument can be used to indicate which transaction is done, + * or as a parameter for a callback. Set to NULL if not needed. + * @param wait Time to wait if the buffer is full. + * + * @return + * - ESP_ERR_INVALID_ARG if the length is not greater than 0. + * - ESP_ERR_TIMEOUT if the queue is still full until timeout. + * - ESP_OK if success. + */ +esp_err_t sdio_slave_send_queue(uint8_t* addr, size_t len, void* arg, TickType_t wait); + +/** Return the ownership of a finished transaction. + * @param arg_o Argument of the finished transaction. + * @param wait Time to wait if there's no finished sending transaction. + * + * @return ESP_ERR_TIMEOUT if no transaction finished, or ESP_OK if succeed. + */ +esp_err_t sdio_slave_send_get_finished(void** arg_o, TickType_t wait); + +/** Start a new sending transfer, and wait for it (blocked) to be finished. + * + * @param addr Start address of the buffer to send + * @param len Length of buffer to send. + * + * @return + * - ESP_ERR_INVALID_ARG if the length of descriptor is not greater than 0. + * - ESP_ERR_TIMEOUT if the queue is full or host do not start a transfer before timeout. + * - ESP_OK if success. + */ +esp_err_t sdio_slave_transmit(uint8_t* addr, size_t len); + +/*--------------------------------------------------------------------------- + * Host + *--------------------------------------------------------------------------*/ +/** Read the spi slave register shared with host. + * + * @param pos register address, 0-27 or 32-63. + * + * @note register 28 to 31 are reserved for interrupt vector. + * + * @return value of the register. + */ +uint8_t sdio_slave_read_reg(int pos); + +/** Write the spi slave register shared with host. + * + * @param pos register address, 0-11, 14-15, 18-19, 24-27 and 32-63, other address are reserved. + * @param reg the value to write. + * + * @note register 29 and 31 are used for interrupt vector. + * + * @return ESP_ERR_INVALID_ARG if address wrong, otherwise ESP_OK. + */ +esp_err_t sdio_slave_write_reg(int pos, uint8_t reg); + +/** Get the interrupt enable for host. + * + * @return the interrupt mask. + */ +sdio_slave_hostint_t sdio_slave_get_host_intena(); + +/** Set the interrupt enable for host. + * + * @param ena Enable mask for host interrupt. + */ +void sdio_slave_set_host_intena(sdio_slave_hostint_t ena); + +/** Interrupt the host by general purpose interrupt. + * + * @param pos Interrupt num, 0-7. + * + * @return + * - ESP_ERR_INVALID_ARG if interrupt num error + * - ESP_OK otherwise + */ +esp_err_t sdio_slave_send_host_int( uint8_t pos ); + +/** Clear general purpose interrupt to host. + * + * @param mask Interrupt bits to clear, by bit mask. + */ +void sdio_slave_clear_host_int(uint8_t mask); + +/** Wait for general purpose interrupt from host. + * + * @param pos Interrupt source number to wait for. + * is set. + * @param wait Time to wait before interrupt triggered. + * + * @note this clears the interrupt at the same time. + * + * @return ESP_OK if success, ESP_ERR_TIMEOUT if timeout. + */ +esp_err_t sdio_slave_wait_int(int pos, TickType_t wait); + + +#ifdef __cplusplus +} +#endif + +#endif /*_DRIVER_SDIO_SLAVE_H */ + + diff --git a/components/driver/sdio_slave.c b/components/driver/sdio_slave.c new file mode 100644 index 0000000000..b63b5c677a --- /dev/null +++ b/components/driver/sdio_slave.c @@ -0,0 +1,1275 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/* +Architecture: + +The whole SDIO slave peripheral consists of three parts: the registers (including the control registers of +interrupts and shared registers), the sending FIFO and the receving FIFO. A document ``esp_slave_protocol.rst`` +describes the functionality of the peripheral detailedly. +The host can access only one of those parts at once, and the hardware functions of these parts are totally +independent. Hence this driver is designed into these three independent parts. The shared registers are quite +simple. As well as the interrupts: when a slave interrupt is written by the host, the slave gets an interrupt; +when one of the host interrupt bits is active, slave hardware output interrupt signals on the DAT1 line. + +For the FIFOs, the peripheral provides counters as registers so that the host can always know whether the slave +is ready to send/receive data. The driver resets the counters during initialization, and the host should somehow +inform the slave to reset the counters again if it should reboot (or lose the counter value for some reasons). +Then the host can read/write the FIFOs by CMD53 commands according to the counters. + +Since we don't want to copy all the data from the buffer each time we use sending/receving buffer, +the buffers are directly loaded onto the sending/receiving linked-list and taken off only after use. +Hence the driver takes ownership of the buffer when the buffer is fed to the driver. + +The driver returns the ownership of buffers when a "finish" function is called. When the hardware finishes +the sending/receiving of a buffer, the ISR is invoked and it goes through the linked-list to see how many buffers +are freed after last interrupt, and send corresponding signals to the app. + +The driver of FIFOs works as below: + +1. The receive driver requires application to "register" a buffer before it's used. The driver + dynamically allocate a linked-list descriptor for the buffer, and return the descriptor as a handle + to the app. + + Each time the app asks to receive by a buffer, the descriptor of the buffer is loaded onto the linked-list, + and the counter of receiving buffers is inreased so that the host will know this by the receiving interrupt. + The hardware will automatically go through the linked list and write data into the buffers loaded on the + list. + + The receiving driver sends a counting semaphore to the app for each buffer finished receiving. A task can only + check the linked list and fetch one finished buffer for a received semaphore. + +2. The sending driver is slightly different due to different hardware working styles. + (TODO: re-write this part if the stitch mode is released) + The hardware has a cache, so that once a descriptor is loaded onto the linked-list, it cannot be modified + until returned (used) by the hardware. This forbids us from loading descriptors onto the linked list during + the transfer (or the time waiting for host to start a transfer). However, we use a "ringbuffer" (different from + the one in ``freertos/`` folder) holding descriptors to solve this: + + 1. The driver allocates continuous memory for several buffer descriptors (the maximum buffer number) during + initialization. Then the driver points the STAILQ_NEXT pointer of all the descriptors except the last one + to the next descriptor of each of them. Then the pointer of the last descriptor points back to the first one: + now the descriptor is in a ring. + + 2. The "ringbuffer" has a write pointer points to where app can write new descriptor. The app writes the new descriptor + indicated by the write pointer without touching the STAILQ_NEXT pointer so that the descriptors are always in a + ring-like linked-list. The app never touches the part of linked-list being used by the hardware. + + 3. When the hardware needs some data to send, it automatically pick a part of connected descriptors. According to the mode: + - Buffer mode: only pick the next one of the last sent one; + - Stream mode: pick the one above to the latest one. + + The driver removes the STAILQ_NEXT pointer of the last descriptor and put the head of the part to the DMA controller so + that it looks like just a linear linked-list rather than a ring to the hardware. + + 4. The counter of sending FIFO can increase when app load new buffers (in STREAM_MODE) or when new transfer should + start (in PACKET_MODE). + + 5. When the sending transfer is finished, the driver goes through the descriptors just send in the ISR and push all + the ``arg`` member of descriptors to the queue back to the app, so that the app can handle finished buffers. The + driver also fix the STAILQ_NEXT pointer of the last descriptor so that the descriptors are now in a ring again. +*/ + + + +#include +#include "driver/sdio_slave.h" +#include "soc/slc_struct.h" +#include "soc/slc_reg.h" +#include "soc/host_struct.h" +#include "soc/hinf_struct.h" +#include "rom/lldesc.h" +#include "esp_log.h" +#include "esp_intr_alloc.h" +#include "freertos/FreeRTOS.h" +#include "soc/dport_access.h" +#include "soc/dport_reg.h" +#include "freertos/semphr.h" +#include "xtensa/core-macros.h" +#include "driver/periph_ctrl.h" + + +#define SDIO_SLAVE_CHECK(res, str, ret_val) do { if(!(res)){\ + SDIO_SLAVE_LOGE( "%s", str);\ + return ret_val;\ +} }while (0) + +#define SDIO_SLAVE_LOGE(s, ...) ESP_LOGE(TAG, "%s:%d (%s):"s, __FILE__,__LINE__,__FUNCTION__,##__VA_ARGS__) +#define SDIO_SLAVE_LOGW(s, ...) ESP_LOGW(TAG, "%s: "s, __FUNCTION__,##__VA_ARGS__) + + +static const char TAG[] = "sdio_slave"; + +typedef enum { + STATE_IDLE = 1, + STATE_WAIT_FOR_START = 2, + STATE_SENDING = 3, +} send_state_t; + +typedef struct { + uint32_t clk; + uint32_t cmd; + uint32_t d0; + uint32_t d1; + uint32_t d2; + uint32_t d3; + int func; +} sdio_slave_slot_info_t ; + +// I/O slot of sdio slave: +// 0: GPIO 6, 11, 7, 8, 9, 10, +// 1: GPIO 14, 15, 2, 4, 12, 13 for CLK, CMD, D0, D1, D2, D3 respectively. +// only one peripheral for SDIO and only one slot can work at the same time. +// currently slot 0 is occupied by SPI for flash +static const sdio_slave_slot_info_t s_slot_info[2] = { + { + .clk = PERIPHS_IO_MUX_SD_CLK_U, + .cmd = PERIPHS_IO_MUX_SD_CMD_U, + .d0 = PERIPHS_IO_MUX_SD_DATA0_U, + .d1 = PERIPHS_IO_MUX_SD_DATA1_U, + .d2 = PERIPHS_IO_MUX_SD_DATA2_U, + .d3 = PERIPHS_IO_MUX_SD_DATA3_U, + .func = 0, + }, { + .clk = PERIPHS_IO_MUX_MTMS_U, + .cmd = PERIPHS_IO_MUX_MTDO_U, + .d0 = PERIPHS_IO_MUX_GPIO2_U, + .d1 = PERIPHS_IO_MUX_GPIO4_U, + .d2 = PERIPHS_IO_MUX_MTDI_U, + .d3 = PERIPHS_IO_MUX_MTCK_U, + .func = 4, + }, +}; + +// first 3 WORDs of this struct is defined by and compatible to the DMA link list format. +// sdio_slave_buf_handle_t is of type buf_desc_t*; +typedef struct buf_desc_s{ + volatile uint32_t size :12, + length:12, + offset: 5, /* h/w reserved 5bit, s/w use it as offset in buffer */ + sosf : 1, /* start of sub-frame */ + eof : 1, /* end of frame */ + owner : 1; /* hw or sw */ + uint8_t* buf; + union{ + TAILQ_ENTRY(buf_desc_s) te; // tailq used by receving + struct { + STAILQ_ENTRY(buf_desc_s) qe; // stailq used by sending and receiving + union { + uint32_t pkt_len; + // shared with the tqe_prev in tailq, happen to be non-zero in the stailq. only + // write to 0 when removed from tailq, set to other will bring invalid pointer. + uint32_t not_receiving; + }; + }; + }; + void* arg; /* to hold some parameters */ +} buf_desc_t; + +typedef STAILQ_HEAD( bufdesc_stailq_head_s, buf_desc_s ) buf_stailq_t; +typedef TAILQ_HEAD( bufdesc_tailq_head_s, buf_desc_s ) buf_tailq_t; + +typedef struct { + uint8_t* data; + uint8_t* write_ptr; + uint8_t* read_ptr; + uint8_t* free_ptr; + size_t item_size; + size_t size; + portMUX_TYPE write_spinlock; + SemaphoreHandle_t remain_cnt; +} sdio_ringbuf_t; + +#define offset_of(type, field) ( (unsigned int)&(((type *)(0))->field) ) +typedef enum { + ringbuf_write_ptr = offset_of(sdio_ringbuf_t, write_ptr), + ringbuf_read_ptr = offset_of(sdio_ringbuf_t, read_ptr), + ringbuf_free_ptr = offset_of(sdio_ringbuf_t, free_ptr), +} sdio_ringbuf_pointer_t; + +#define SDIO_RINGBUF_INITIALIZER() (sdio_ringbuf_t){.write_spinlock = portMUX_INITIALIZER_UNLOCKED,} + +typedef struct { + sdio_slave_config_t config; + intr_handle_t intr_handle; //allocated interrupt handle + /*------- events ---------------*/ + union { + SemaphoreHandle_t events[9]; // 0-7 for gp intr + struct { + SemaphoreHandle_t _events[8]; + SemaphoreHandle_t recv_event; // 8 for recv + }; + }; + portMUX_TYPE reg_spinlock; + /*------- sending ---------------*/ + //desc in the send_link_list are temporary, taken information and space from the ringbuf, return to ringbuf after use. + send_state_t send_state; + sdio_ringbuf_t sendbuf; + QueueHandle_t ret_queue; + buf_desc_t* in_flight; + buf_desc_t* in_flight_end; + buf_desc_t* in_flight_next; + /*------- receiving ---------------*/ + buf_stailq_t recv_link_list; // now ready to/already hold data + buf_tailq_t recv_reg_list; // removed from the link list, registered but not used now + buf_desc_t* recv_cur_ret; + portMUX_TYPE recv_spinlock; +} sdio_context_t; + +static sdio_context_t context = { + .intr_handle = NULL, + /*------- events ---------------*/ + .events = {}, + .reg_spinlock = portMUX_INITIALIZER_UNLOCKED, + /*------- sending ---------------*/ + .send_state = STATE_IDLE, + .sendbuf = SDIO_RINGBUF_INITIALIZER(), + .ret_queue = NULL, + .in_flight = NULL, + .in_flight_end = NULL, + .in_flight_next = NULL, + /*------- receiving ---------------*/ + .recv_link_list = STAILQ_HEAD_INITIALIZER(context.recv_link_list), + .recv_reg_list = TAILQ_HEAD_INITIALIZER(context.recv_reg_list), + .recv_cur_ret = NULL, + .recv_spinlock = portMUX_INITIALIZER_UNLOCKED, +}; + +static void sdio_intr(void*); +static void sdio_intr_host(void*); +static void sdio_intr_send(void*); +static void sdio_intr_recv(void*); + +static esp_err_t send_flush_data(); +static esp_err_t send_reset_counter(); +static void recv_flush_data(); +static void recv_reset_counter(); + +static esp_err_t send_start(); +static void send_stop(); +static esp_err_t recv_start(); +static void recv_stop(); + +static void deinit_context(); + + +/**************** Ring buffer for SDIO use *****************/ +typedef enum { + RINGBUF_GET_ONE = 0, + RINGBUF_GET_ALL = 1, +} ringbuf_get_all_t; + +static void sdio_ringbuf_deinit(sdio_ringbuf_t* buf) +{ + if ( buf->remain_cnt != NULL ) vSemaphoreDelete( buf->remain_cnt ); + if ( buf->data != NULL ) free(buf->data); + *buf = SDIO_RINGBUF_INITIALIZER(); +} + +static esp_err_t sdio_ringbuf_init(sdio_ringbuf_t* buf, int item_size, int item_cnt) +{ + if (buf->data != NULL ) { + SDIO_SLAVE_LOGE( "sdio_ringbuf_init: already initialized"); + return ESP_ERR_INVALID_STATE; + } + buf->item_size = item_size; + //one item is not used. + buf->size = item_size * (item_cnt+1); + //apply for resources + buf->data = (uint8_t*)malloc(buf->size); + if ( buf->data == NULL ) goto no_mem; + buf->remain_cnt = xSemaphoreCreateCounting( item_cnt, item_cnt ); + if ( buf->remain_cnt == NULL ) goto no_mem; + //initialize pointers + buf->write_ptr = buf->data; + buf->read_ptr = buf->data; + buf->free_ptr = buf->data; + return ESP_OK; +no_mem: + sdio_ringbuf_deinit(buf); + return ESP_ERR_NO_MEM; +} + +//calculate a pointer with offset to a original pointer of the specific ringbuffer +static inline uint8_t* sdio_ringbuf_offset_ptr( sdio_ringbuf_t *buf, sdio_ringbuf_pointer_t ptr, uint32_t offset ) +{ + uint8_t *buf_ptr = (uint8_t*)*(uint32_t*)(((uint8_t*)buf)+ptr); //get the specific pointer of the buffer + uint8_t *offset_ptr=buf_ptr+offset; + if (offset_ptr >= buf->data + buf->size) offset_ptr -= buf->size; + return offset_ptr; +} + +static esp_err_t sdio_ringbuf_send( sdio_ringbuf_t* buf, esp_err_t (*copy_callback)(uint8_t*, void*), void* arg, TickType_t wait ) +{ + portBASE_TYPE ret = xSemaphoreTake(buf->remain_cnt, wait); + if ( ret != pdTRUE ) return NULL; + + portENTER_CRITICAL( &buf->write_spinlock ); + uint8_t* get_ptr = sdio_ringbuf_offset_ptr( buf, ringbuf_write_ptr, buf->item_size ); + esp_err_t err = ESP_OK; + if (copy_callback) (*copy_callback)(get_ptr, arg); + if ( err != ESP_OK ) { + portEXIT_CRITICAL( &buf->write_spinlock ); + return err; + } + buf->write_ptr = get_ptr; + portEXIT_CRITICAL( &buf->write_spinlock ); + return ESP_OK; +} + +// this ringbuf is a return-before-recv-again strategy +// since this is designed to be called in the ISR, no parallel logic +static inline esp_err_t sdio_ringbuf_recv(sdio_ringbuf_t* buf, uint8_t **start, uint8_t **end, ringbuf_get_all_t get_all, TickType_t wait) +{ + assert( buf->free_ptr == buf->read_ptr ); //must return before recv again + assert(wait == 0); //only implement wait = 0 case now + if ( start == NULL && end == NULL ) return ESP_ERR_INVALID_ARG; // must have a output + if ( buf->read_ptr == buf->write_ptr ) return ESP_ERR_NOT_FOUND; // no data + + uint8_t *get_start = sdio_ringbuf_offset_ptr(buf, ringbuf_read_ptr, buf->item_size); + + if ( get_all != RINGBUF_GET_ONE ) { + buf->read_ptr = buf->write_ptr; + } else { + buf->read_ptr = get_start; + } + + if ( start != NULL ) *start = get_start; + if ( end != NULL ) *end = buf->read_ptr; + return ESP_OK; +} + +static inline void sdio_ringbuf_return_from_isr(sdio_ringbuf_t* buf, uint8_t *ptr, portBASE_TYPE *yield) +{ + assert( sdio_ringbuf_offset_ptr(buf, ringbuf_free_ptr, buf->item_size) == ptr ); + int size = (buf->read_ptr + buf->size - buf->free_ptr)%buf->size; + int count = size/buf->item_size; + assert( count*buf->item_size==size); + buf->free_ptr = buf->read_ptr; + for( int i = 0; i < count; i ++ ) { + portBASE_TYPE ret = xSemaphoreGiveFromISR( buf->remain_cnt, yield ); + assert( ret == pdTRUE ); + } +} + +static inline void sdio_ringbuf_return(sdio_ringbuf_t* buf, uint8_t *ptr) +{ + assert( sdio_ringbuf_offset_ptr(buf, ringbuf_free_ptr, buf->item_size) == ptr ); + int size = (buf->read_ptr + buf->size - buf->free_ptr)%buf->size; + int count = size/buf->item_size; + assert( count*buf->item_size==size); + buf->free_ptr = buf->read_ptr; + for( int i = 0; i < count; i ++ ) { + portBASE_TYPE ret = xSemaphoreGive( buf->remain_cnt ); + assert( ret == pdTRUE ); + } +} + +static inline uint8_t* sdio_ringbuf_peek_front(sdio_ringbuf_t* buf) +{ + if ( buf->read_ptr != buf->write_ptr ) { + return sdio_ringbuf_offset_ptr(buf, ringbuf_read_ptr, buf->item_size); + } else { + return NULL; + } +} + +static inline uint8_t* sdio_ringbuf_peek_rear( sdio_ringbuf_t *buf ) +{ + return buf->write_ptr; +} + +static inline bool sdio_ringbuf_empty( sdio_ringbuf_t* buf ) +{ + return (buf->read_ptr == buf->write_ptr? true : false); +} +/**************** End of Ring buffer for SDIO *****************/ + +static inline void show_ll(buf_desc_t *item) +{ + ESP_EARLY_LOGD( TAG, "=> %p: size: %d(%d), eof: %d, owner: %d", item, item->size, item->length, item->eof, item->owner ); + ESP_EARLY_LOGD( TAG, " buf: %p, stqe_next: %p, tqe-prev: %p", item->buf, item->qe.stqe_next, item->te.tqe_prev ); +} + +static void __attribute((unused)) dump_ll(buf_stailq_t *queue) +{ + buf_desc_t *item = NULL; + ESP_EARLY_LOGD( TAG, ">>>>> first: %p, last: %p <<<<<", queue->stqh_first, queue->stqh_last ); + STAILQ_FOREACH( item, queue, qe ) { + show_ll(item); + } +} + +static inline void deinit_context() +{ + context.config = (sdio_slave_config_t){}; + for( int i = 0; i < 9; i ++ ) { + if ( context.events[i] != NULL ) { + vSemaphoreDelete(context.events[i]); + context.events[i] = NULL; + } + } + if ( context.ret_queue != NULL ) { + vQueueDelete(context.ret_queue); + context.ret_queue = NULL; + } + sdio_ringbuf_deinit( &context.sendbuf ); +} + +esp_err_t link_desc_to_last(uint8_t* desc, void* arg) +{ + STAILQ_NEXT((buf_desc_t*)arg, qe) = (buf_desc_t*)desc; + return ESP_OK; +} + +static esp_err_t init_ringbuf() +{ + esp_err_t ret = sdio_ringbuf_init( &context.sendbuf, sizeof(buf_desc_t), context.config.send_queue_size ); + if ( ret != ESP_OK ) return ret; + + esp_err_t rcv_res; + buf_desc_t *first=NULL, *last=NULL; + + //no copy for the first descriptor + ret = sdio_ringbuf_send( &context.sendbuf, NULL, NULL, portMAX_DELAY); + if ( ret != ESP_OK ) return ret; + + //loop in the ringbuf to link all the desc one after another as a ring + for ( int i = 0; i < context.config.send_queue_size+1; i++ ) { + rcv_res = sdio_ringbuf_recv( &context.sendbuf, (uint8_t**)&last, NULL, RINGBUF_GET_ONE, 0 ); + assert ( rcv_res == ESP_OK ); + ret = sdio_ringbuf_send( &context.sendbuf, link_desc_to_last, last, portMAX_DELAY); + if ( ret != ESP_OK ) return ret; + sdio_ringbuf_return(&context.sendbuf, (uint8_t*)last); + } + first = NULL; + last = NULL; + //clear the queue + rcv_res = sdio_ringbuf_recv( &context.sendbuf, (uint8_t**)&first, (uint8_t**)&last, RINGBUF_GET_ALL, 0 ); + assert ( rcv_res == ESP_OK ); + assert( first == last ); //there should be only one desc remain + sdio_ringbuf_return(&context.sendbuf, (uint8_t*)first ); + return ESP_OK; +} + +static esp_err_t init_context(sdio_slave_config_t *config) +{ + SDIO_SLAVE_CHECK( *(uint32_t*)&context.config == 0, "sdio slave already initialized", ESP_ERR_INVALID_STATE ); + + context.config = *config; + + // in theory we can queue infinite buffers in the linked list, but for multi-core reason we have to use a queue to + // count the finished buffers. + context.recv_event = xSemaphoreCreateCounting(UINT32_MAX, 0 ); + for( int i = 0; i < 9; i ++ ) { + if ( i < 8 ) { + context.events[i] = xSemaphoreCreateBinary(); + } //for 8, already created. + if ( context.events[i] == NULL ) { + SDIO_SLAVE_LOGE( "event initialize failed"); + goto no_mem; + } + } + + esp_err_t ret = init_ringbuf(); + if ( ret != ESP_OK ) goto no_mem; + + context.ret_queue = xQueueCreate( config->send_queue_size, sizeof(void*) ); + if ( context.ret_queue == NULL ) goto no_mem; + + context.recv_link_list = (buf_stailq_t)STAILQ_HEAD_INITIALIZER(context.recv_link_list); + context.recv_reg_list = (buf_tailq_t)TAILQ_HEAD_INITIALIZER(context.recv_reg_list); + return ESP_OK; + +no_mem: + deinit_context(); + return ESP_ERR_NO_MEM; +} + +static inline void configure_pin(uint32_t io_mux_reg, uint32_t func) +{ + const int sdmmc_func = func; + const int drive_strength = 3; + PIN_INPUT_ENABLE(io_mux_reg); + PIN_FUNC_SELECT(io_mux_reg, sdmmc_func); + PIN_SET_DRV(io_mux_reg, drive_strength); +} + +static inline esp_err_t sdio_slave_hw_init(sdio_slave_config_t *config) +{ + //enable interrupts + SLC.slc0_int_ena.val = 0; + + //initialize pin + const sdio_slave_slot_info_t *slot = &s_slot_info[1]; + configure_pin(slot->clk, slot->func); + configure_pin(slot->cmd, slot->func); + configure_pin(slot->d0, slot->func); + configure_pin(slot->d1, slot->func); + configure_pin(slot->d2, slot->func); + configure_pin(slot->d3, slot->func); + //enable module and config + periph_module_reset(PERIPH_SDIO_SLAVE_MODULE); + periph_module_enable(PERIPH_SDIO_SLAVE_MODULE); + + SLC.conf0.slc0_rx_auto_wrback = 1; + SLC.conf0.slc0_token_auto_clr = 0; + SLC.conf0.slc0_rx_loop_test = 0; + SLC.conf0.slc0_tx_loop_test = 0; + + SLC.conf1.slc0_rx_stitch_en = 0; + SLC.conf1.slc0_tx_stitch_en = 0; + SLC.conf1.slc0_len_auto_clr = 0; + + SLC.rx_dscr_conf.slc0_token_no_replace = 1; + HINF.cfg_data1.highspeed_enable = 1; + + switch( config->timing ) { + case SDIO_SLAVE_TIMING_PSEND_PSAMPLE: + HOST.conf.frc_sdio20 = 0xf; + HOST.conf.frc_sdio11 = 0; + HOST.conf.frc_pos_samp = 0xf; + HOST.conf.frc_neg_samp = 0; + break; + case SDIO_SLAVE_TIMING_PSEND_NSAMPLE: + HOST.conf.frc_sdio20 = 0xf; + HOST.conf.frc_sdio11 = 0; + HOST.conf.frc_pos_samp = 0; + HOST.conf.frc_neg_samp = 0xf; + break; + case SDIO_SLAVE_TIMING_NSEND_PSAMPLE: + HOST.conf.frc_sdio20 = 0; + HOST.conf.frc_sdio11 = 0xf; + HOST.conf.frc_pos_samp = 0xf; + HOST.conf.frc_neg_samp = 0; + break; + case SDIO_SLAVE_TIMING_NSEND_NSAMPLE: + HOST.conf.frc_sdio20 = 0; + HOST.conf.frc_sdio11 = 0xf; + HOST.conf.frc_pos_samp = 0; + HOST.conf.frc_neg_samp = 0xf; + break; + } + + SLC.slc0_int_ena.frhost_bit0 = 1; + SLC.slc0_int_ena.frhost_bit1 = 1; + SLC.slc0_int_ena.frhost_bit2 = 1; + SLC.slc0_int_ena.frhost_bit3 = 1; + SLC.slc0_int_ena.frhost_bit4 = 1; + SLC.slc0_int_ena.frhost_bit5 = 1; + SLC.slc0_int_ena.frhost_bit6 = 1; + SLC.slc0_int_ena.frhost_bit7 = 1; + + return ESP_OK; +} + +esp_err_t sdio_slave_initialize(sdio_slave_config_t *config) +{ + esp_err_t r; + intr_handle_t intr_handle = NULL; + const int flags = 0; + r = esp_intr_alloc(ETS_SLC0_INTR_SOURCE, flags, sdio_intr, NULL, &intr_handle); + if (r != ESP_OK ) return r; + + r = sdio_slave_hw_init(config); + if ( r != ESP_OK ) return r; + r = init_context(config); + if ( r != ESP_OK ) return r; + context.intr_handle = intr_handle; + + sdio_slave_reset(); + return ESP_OK; +} + +void sdio_slave_deinit() +{ + esp_err_t ret = esp_intr_free(context.intr_handle); + assert(ret==ESP_OK); + context.intr_handle = NULL; + deinit_context(); +} + +esp_err_t sdio_slave_start() +{ + esp_err_t ret; + HOST.slc0_int_clr.val = UINT32_MAX;//clear all interrupts + ret = send_start(); + if ( ret != ESP_OK ) return ret; + ret = recv_start(); + if ( ret != ESP_OK ) return ret; + HINF.cfg_data1.sdio_ioready1 = 1; //set IO ready to 1 to allow host to use + return ESP_OK; +} + +esp_err_t sdio_slave_reset() +{ + send_flush_data(); + send_reset_counter(); + recv_flush_data(); + recv_reset_counter(); + return ESP_OK; +} + +void sdio_slave_stop() +{ + HINF.cfg_data1.sdio_ioready1 = 0; //set IO ready to 1 to stop host from using + send_stop(); + recv_stop(); +} + +#define SDIO_SLAVE_SLC_INT_TX_MASK (SLC_SLC0_TX_ERR_EOF_INT_ST_M | SLC_SLC0_TX_DSCR_EMPTY_INT_ST_M | SLC_SLC0_TX_DSCR_ERR_INT_ST_M | SLC_SLC0_TX_SUC_EOF_INT_ST_M | SLC_SLC0_TX_DONE_INT_ST_M | SLC_SLC0_TX_OVF_INT_ST_M | SLC_SLC0_TX_START_INT_ST_M) +#define SDIO_SLAVE_SLC_INT_RX_MASK (SLC_SLC0_RX_DSCR_ERR_INT_ST_M | SLC_SLC0_RX_EOF_INT_ST_M | SLC_SLC0_RX_DONE_INT_ST_M | SLC_SLC0_RX_UDF_INT_ST_M | SLC_SLC0_RX_START_INT_ST_M) +#define SDIO_SLAVE_SLC_INT_HOST_MASK (SLC_FRHOST_BIT7_INT_ST_M | SLC_FRHOST_BIT6_INT_ST_M | SLC_FRHOST_BIT5_INT_ST_M | SLC_FRHOST_BIT4_INT_ST_M | SLC_FRHOST_BIT3_INT_ST_M | SLC_FRHOST_BIT2_INT_ST_M | SLC_FRHOST_BIT1_INT_ST_M | SLC_FRHOST_BIT0_INT_ST_M) + +//strange but `tx_*` regs for host->slave transfers while `rx_*` regs for slave->host transfers +static void sdio_intr(void* arg) +{ + uint32_t int_val = SLC.slc0_int_st.val; + uint32_t int_raw = SLC.slc0_int_raw.val; + ESP_EARLY_LOGV( TAG, "sdio_intr: %08X(%08X)", int_val, int_raw ); + + if ( int_val & SDIO_SLAVE_SLC_INT_RX_MASK ) sdio_intr_send(arg); + if ( int_val & SDIO_SLAVE_SLC_INT_TX_MASK ) sdio_intr_recv(arg); + if ( int_val & SDIO_SLAVE_SLC_INT_HOST_MASK ) sdio_intr_host(arg); +} + +/*--------------------------------------------------------------------------- + * Host + *--------------------------------------------------------------------------*/ +static void sdio_intr_host(void* arg) +{ + uint8_t int_val = SLC.slc0_int_st.val & 0xff; + + portBASE_TYPE yield = pdFALSE; + SLC.slc0_int_clr.val = int_val; + for( int i = 0; i < 8; i ++ ) { + if ( BIT(i) & int_val ) { + if ( context.config.event_cb != NULL ) (*context.config.event_cb)(i); + xSemaphoreGiveFromISR( context.events[i], &yield ); + } + } + if ( yield ) portYIELD_FROM_ISR(); +} + +esp_err_t sdio_slave_wait_int(int pos, TickType_t wait) +{ + SDIO_SLAVE_CHECK( pos >= 0 && pos < 8, "interrupt num invalid", ESP_ERR_INVALID_ARG); + return xSemaphoreTake( context.events[pos], wait ); +} + + +uint8_t sdio_slave_read_reg(int pos) +{ + if ( pos >= 28 && pos <= 31 ) SDIO_SLAVE_LOGW( "%s: interrupt reg, for reference", __FUNCTION__ ); + if ( pos < 0 || pos >= 64 ) SDIO_SLAVE_LOGE( "read register address wrong"); + + return *(uint8_t*)(HOST_SLCHOST_CONF_W_REG(pos)); +} + +esp_err_t sdio_slave_write_reg(int pos, uint8_t reg) +{ + if ( pos >= 28 && pos <= 31 ) { + SDIO_SLAVE_LOGE( "interrupt reg, please use sdio_slave_clear_int" ); + return ESP_ERR_INVALID_ARG; + } + if ( pos < 0 || pos >= 64 ) { + SDIO_SLAVE_LOGE( "write register address wrong"); + return ESP_ERR_INVALID_ARG; + } + uint32_t addr = HOST_SLCHOST_CONF_W_REG(pos) & (~3); + uint32_t shift = (pos % 4)*8; + + portENTER_CRITICAL( &context.reg_spinlock ); + int val = *(uint32_t*)addr; + *(uint32_t*)addr = (val & ~(0xff << shift)) | (reg<host transfers. +/* The link list is handled in the app, while counter and pointer processed in ISR. + * Driver abuse rx_done bit to invoke ISR. + * If driver is stopped, the link list is stopped as well as the ISR invoker. + */ +static inline void send_length_write(uint32_t len) +{ + SLC.slc0_len_conf.val = FIELD_TO_VALUE2( SLC_SLC0_LEN_WDATA, len ) | FIELD_TO_VALUE2( SLC_SLC0_LEN_WR, 1 ); + ESP_EARLY_LOGV(TAG, "send_length_write: %d, last_len: %08X", len, HOST.pkt_len.reg_slc0_len ); +} + +static inline void send_start_transmission(const void* desc) +{ + //reset to flush previous packets + SLC.conf0.slc0_rx_rst = 1; + SLC.conf0.slc0_rx_rst = 0; + SLC.slc0_rx_link.addr = (uint32_t)desc; + SLC.slc0_rx_link.start = 1; +} + +static inline void send_stop_ll_operation() +{ + SLC.slc0_rx_link.stop = 1; +} + +static inline uint32_t send_length_read() +{ + return HOST.pkt_len.reg_slc0_len; +} + +DMA_ATTR static const buf_desc_t start_desc = { + .owner = 1, + .buf = (void*)0x3ffbbbbb, //assign a dma-capable pointer other than NULL, which will not be used + .size = 1, + .length = 1, + .eof = 1, +}; + +static inline void send_isr_invoker_enable() +{ + //force trigger rx_done interrupt. the interrupt is abused to invoke ISR from the app by the enable bit and never cleared. + send_start_transmission( &start_desc ); + //wait for rx_done + while( !SLC.slc0_int_raw.rx_done ); + HOST.slc0_int_clr.rx_new_packet = 1; + send_stop_ll_operation(); +} + +static inline void send_isr_invoker_disable() +{ + SLC.slc0_int_clr.rx_done = 1; +} + +static inline void send_intr_enable() +{ + SLC.slc0_int_ena.rx_eof = 1; + send_isr_invoker_enable(); +} + +static inline void send_intr_disable() +{ + send_isr_invoker_disable(); + SLC.slc0_int_ena.rx_eof = 0; +} + +static inline void send_isr_invoke() +{ + SLC.slc0_int_ena.rx_done = 1; +} + +static inline send_state_t send_get_state() +{ + return context.send_state; +} + +static inline void send_set_state(send_state_t state) +{ + context.send_state = state; +} + +//start hw operation with existing data (if exist) +static esp_err_t send_start() +{ + SDIO_SLAVE_CHECK( send_get_state() == STATE_IDLE, + "already started", ESP_ERR_INVALID_STATE ); + SLC.slc0_int_clr.rx_eof = 1; + send_set_state( STATE_WAIT_FOR_START ); + send_intr_enable(); + return ESP_OK; +} + +//only stop hw operations, no touch to data as well as counter +static void send_stop() +{ + SLC.slc0_rx_link.stop = 1; + send_intr_disable(); + + send_set_state( STATE_IDLE ); +} + +static inline esp_err_t send_isr_eof(portBASE_TYPE *yield) +{ + // inform app to recycle descs + portBASE_TYPE ret = pdTRUE; + buf_desc_t *desc = context.in_flight; + assert( desc != NULL ); + + do { + ESP_EARLY_LOGV(TAG, "end: %x", desc->arg); + ret = xQueueSendFromISR( context.ret_queue, &desc->arg, yield ); + assert(ret == pdTRUE); + buf_desc_t* next = STAILQ_NEXT(desc, qe); + desc = next; + } while(desc!=NULL); + STAILQ_NEXT( context.in_flight_end, qe ) = context.in_flight_next; + sdio_ringbuf_return_from_isr(&context.sendbuf, (uint8_t*)context.in_flight, yield); + context.in_flight = NULL; + context.in_flight_end = NULL; + // Go to wait for packet state + send_set_state( STATE_WAIT_FOR_START ); + return ESP_OK; +} + +static inline esp_err_t send_isr_check_new_pkt(portBASE_TYPE *yield) +{ + esp_err_t ret; + buf_desc_t *start = NULL; + buf_desc_t *end = NULL; + if ( context.config.sending_mode == SDIO_SLAVE_SEND_PACKET ) { + ret = sdio_ringbuf_recv( &context.sendbuf, (uint8_t**)&start, (uint8_t**)&end, RINGBUF_GET_ONE, 0); + } else { //stream mode + ret = sdio_ringbuf_recv( &context.sendbuf, (uint8_t**)&start, (uint8_t**)&end, RINGBUF_GET_ALL, 0); + } + if ( ret == ESP_OK ) { + context.in_flight = start; + context.in_flight_end = end; + end->eof = 1; + //temporarily break the link ring here, the ring will be re-connected in ``send_isr_eof()``. + context.in_flight_next = STAILQ_NEXT(end, qe); + STAILQ_NEXT(end, qe) = NULL; + } + return ESP_OK; +} + +static inline esp_err_t send_isr_new_packet() +{ + // since eof is changed, we have to stop and reset the link list, + // and restart new link list operation + buf_desc_t *const start_desc = context.in_flight; + buf_desc_t *const end_desc = context.in_flight_end; + assert(start_desc != NULL && end_desc != NULL); + + send_stop_ll_operation(); + send_start_transmission( start_desc ); + + // update pkt_len register to allow host reading. + send_length_write( end_desc->pkt_len ); + + send_set_state( STATE_SENDING ); + + ESP_EARLY_LOGD(TAG, "restart new send: %p->%p, pkt_len: %d", start_desc, end_desc, end_desc->pkt_len); + return ESP_OK; +} + +static void sdio_intr_send(void* arg) +{ + ESP_EARLY_LOGV(TAG, "intr_send"); + portBASE_TYPE yield = pdFALSE; + + // this interrupt is abused to get ISR invoked by app + if ( SLC.slc0_int_st.rx_done ) SLC.slc0_int_ena.rx_done = 0; + + // Goto idle state (cur_start=NULL) if transmission done, + // also update sequence and recycle descs. + if ( SLC.slc0_int_st.rx_eof ) { + SLC.slc0_int_clr.rx_eof = 1; + //check current state + assert( send_get_state() == STATE_SENDING );// context.send_start != NOT_YET && context.send_end != NOT_YET ); + send_isr_eof(&yield); + } + + // Go to wait sending state (cur_start!=NULL && cur_end==NULL) if not sending and new packet ready. + // Note we may also enter this state by stopping sending in the app. + if ( send_get_state() == STATE_WAIT_FOR_START ) { + if ( context.in_flight == NULL ) send_isr_check_new_pkt(&yield); + // Go to sending state (cur_start and cur_end != NULL) if has packet to send. + if ( context.in_flight ) send_isr_new_packet(); + } + + if ( yield ) portYIELD_FROM_ISR(); +} + +esp_err_t send_write_desc(uint8_t* desc, void* arg) +{ + buf_desc_t *new_desc = (buf_desc_t*)arg; + buf_desc_t *tail = (buf_desc_t*)sdio_ringbuf_peek_rear(&context.sendbuf); + new_desc->pkt_len = tail->pkt_len + new_desc->size; + //copy and keep the link + STAILQ_NEXT(new_desc, qe) = STAILQ_NEXT((buf_desc_t*)desc, qe); + + memcpy( desc, new_desc, sizeof(buf_desc_t) ); + return ESP_OK; +} + +esp_err_t sdio_slave_send_queue(uint8_t* addr, size_t len, void* arg, TickType_t wait) +{ + SDIO_SLAVE_CHECK( len > 0, "len <= 0", ESP_ERR_INVALID_ARG ); + SDIO_SLAVE_CHECK( esp_ptr_dma_capable(addr) && (uint32_t)addr%4==0, "buffer to send should be DMA capable and 32-bit aligned", + ESP_ERR_INVALID_ARG); + + buf_desc_t new_desc = { + .size = len, + .length = len, + .buf = addr, + .owner = 1, + // in stream mode, the eof is only appended (in ISR) when new packet is ready to be sent + .eof = (context.config.sending_mode == SDIO_SLAVE_SEND_PACKET?1:0), + .arg = arg, + }; + + esp_err_t ret = sdio_ringbuf_send(&context.sendbuf, send_write_desc, &new_desc, wait); + if ( ret != ESP_OK ) return ret; + + send_isr_invoke(); + return ESP_OK; +} + +esp_err_t sdio_slave_send_get_finished(void** arg, TickType_t wait) +{ + portBASE_TYPE err = xQueueReceive( context.ret_queue, arg, wait ); + if ( err != pdTRUE ) return ESP_ERR_TIMEOUT; + return ESP_OK; +} + +esp_err_t sdio_slave_transmit(uint8_t* addr, size_t len) +{ + uint32_t timestamp = XTHAL_GET_CCOUNT(); + uint32_t ret_stamp; + + esp_err_t err = sdio_slave_send_queue( addr, len, (void*)timestamp, portMAX_DELAY ); + if ( err != ESP_OK ) return err; + err = sdio_slave_send_get_finished( (void**)&ret_stamp, portMAX_DELAY ); + if ( err != ESP_OK ) return err; + SDIO_SLAVE_CHECK( ret_stamp == timestamp, "already sent without return before", ESP_ERR_INVALID_STATE); + + return ESP_OK; +} + +//clear data but keep counter +static esp_err_t send_flush_data() +{ + //only works in idle state / wait to send state + SDIO_SLAVE_CHECK( send_get_state() == STATE_IDLE, + "flush data when transmission started", ESP_ERR_INVALID_STATE ); + + HOST.slc0_int_clr.rx_new_packet = 1; + + buf_desc_t *last = NULL; + if ( context.in_flight ) { + buf_desc_t *desc = context.in_flight; + while( desc != NULL ) { + xQueueSend( context.ret_queue, desc->arg, portMAX_DELAY ); + last = desc; + desc = STAILQ_NEXT(desc, qe); + } + STAILQ_NEXT( context.in_flight_end, qe ) = context.in_flight_next; + sdio_ringbuf_return( &context.sendbuf, (uint8_t*)context.in_flight ); + context.in_flight = NULL; + context.in_flight_end = NULL; + } + + buf_desc_t *head; + esp_err_t ret = sdio_ringbuf_recv(&context.sendbuf, (uint8_t**)&head, NULL, RINGBUF_GET_ALL, 0); + if ( ret == ESP_OK ) { + buf_desc_t *desc = head; + while( desc != NULL ) { + xQueueSend( context.ret_queue, desc->arg, portMAX_DELAY ); + last = desc; + desc = STAILQ_NEXT(desc, qe); + } + sdio_ringbuf_return( &context.sendbuf, (uint8_t*)head ); + } + + // if in wait to send state, set the sequence number of tail to the value last sent, just as if the packet wait to + // send never queued. + // Go to idle state (cur_end!=NULL and cur_start=NULL) + send_set_state( STATE_IDLE ); + + if ( last == NULL ) last = (buf_desc_t*)sdio_ringbuf_peek_rear(&context.sendbuf); + last->pkt_len = send_length_read(); + return ESP_OK; +} + +//clear counter but keep data +static esp_err_t send_reset_counter() +{ + SDIO_SLAVE_CHECK( send_get_state() == STATE_IDLE, + "reset counter when transmission started", ESP_ERR_INVALID_STATE ); + + send_length_write( 0 ); + + uint32_t last_cnt=0; + buf_desc_t *desc = context.in_flight; + buf_desc_t *last = NULL; + while( desc != NULL ) { + last_cnt += desc->length; + desc->pkt_len = last_cnt; + last = desc; + desc = STAILQ_NEXT(desc, qe); + } + // in theory the desc should be the one right next to the last of in_flight, + // but the link of last is NULL, so get the desc from the ringbuf directly. + desc = (buf_desc_t*)sdio_ringbuf_peek_front(&context.sendbuf); + while( desc != NULL ) { + last_cnt += desc->length; + desc->pkt_len = last_cnt; + last = desc; + desc = STAILQ_NEXT(desc, qe); + } + if ( last == NULL ) { + last = (buf_desc_t*)sdio_ringbuf_peek_rear(&context.sendbuf); + last->pkt_len = 0; + } + + return ESP_OK; +} + + +/*--------------------------------------------------------------------------- + * Recv + *--------------------------------------------------------------------------*/ +//strange but the registers for host->slave transfers are really called "tx*". + +#define CHECK_HANDLE_IDLE(desc) do { if ( desc == NULL || !desc->not_receiving ) {\ + return ESP_ERR_INVALID_ARG; } } while(0) + +static inline void critical_enter_recv() +{ + portENTER_CRITICAL( &context.recv_spinlock ); +} + +static inline void critical_exit_recv() +{ + portEXIT_CRITICAL( &context.recv_spinlock ); +} + +static inline void recv_size_inc() +{ + // fields wdata and inc_more should be written by the same instruction. + SLC.slc0_token1.val = FIELD_TO_VALUE2( SLC_SLC0_TOKEN1_WDATA, 1) | FIELD_TO_VALUE2( SLC_SLC0_TOKEN1_INC_MORE, 1 ); +} + +static inline void recv_size_reset() +{ + SLC.slc0_token1.val = FIELD_TO_VALUE2( SLC_SLC0_TOKEN1_WDATA, 0) | FIELD_TO_VALUE2( SLC_SLC0_TOKEN1_WR, 1 ); +} + +static inline buf_desc_t* recv_get_first_empty_buf() +{ + buf_stailq_t *const queue = &context.recv_link_list; + buf_desc_t *desc = STAILQ_FIRST(queue); + while( desc && desc->owner == 0 ) { + desc = STAILQ_NEXT( desc, qe ); + } + return desc; +} + +static esp_err_t recv_start() +{ + SLC.conf0.slc0_tx_rst = 1; + SLC.conf0.slc0_tx_rst = 0; + + critical_enter_recv(); + buf_desc_t *desc = recv_get_first_empty_buf(); + if ( !desc ) { + ESP_LOGD(TAG, "recv: restart without desc"); + critical_exit_recv(); + return ESP_OK; // if no buffer loaded, return directly. + } + //the counter is handled when add/flush/reset + SLC.slc0_tx_link.addr = (uint32_t)desc; + SLC.slc0_tx_link.start = 1; + critical_exit_recv(); + + SLC.slc0_int_ena.tx_done = 1; + return ESP_OK; +} + +static void recv_stop() +{ + SLC.slc0_tx_link.stop = 1; + SLC.slc0_int_ena.tx_done = 0; +} + +// reset the counter, but keep the data +static void recv_reset_counter() +{ + recv_size_reset(); + + critical_enter_recv(); + buf_desc_t *desc = recv_get_first_empty_buf(); + while ( desc != NULL ) { + assert( desc->owner == 1 ); + recv_size_inc(); + desc = STAILQ_NEXT( desc, qe ); + } + critical_exit_recv(); +} + +// remove data, still increase the counter +static void recv_flush_data() +{ + buf_stailq_t *const queue = &context.recv_link_list; + + critical_enter_recv(); + while(1) { + portBASE_TYPE ret = xSemaphoreTake( context.recv_event, 0 ); + if ( ret == pdFALSE ) break; + + buf_desc_t *desc = STAILQ_FIRST(queue); + assert ( desc != NULL && desc->owner == 0 ); + STAILQ_REMOVE_HEAD(queue, qe); + desc->owner = 1; + STAILQ_INSERT_TAIL( queue, desc, qe ); + recv_size_inc(); + //we only add it to the tail here, without start the DMA nor increase buffer num. + } + critical_exit_recv(); +} + +static void sdio_intr_recv(void* arg) +{ + portBASE_TYPE yield = 0; + if ( SLC.slc0_int_raw.tx_done ) { + SLC.slc0_int_clr.tx_done = 1; + assert( context.recv_cur_ret != NULL ); + + while ( context.recv_cur_ret && context.recv_cur_ret->owner == 0 ) { + // This may cause the ``cur_ret`` pointer to be NULL, indicating the list is empty, + // in this case the ``tx_done`` should happen no longer until new desc is appended. + // The app is responsible to place the pointer to the right place again when appending new desc. + context.recv_cur_ret = STAILQ_NEXT( context.recv_cur_ret, qe ); + ESP_EARLY_LOGV( TAG, "intr_recv: Give"); + xSemaphoreGiveFromISR( context.recv_event, &yield ); + }; + } + if ( yield ) portYIELD_FROM_ISR(); +} + +esp_err_t sdio_slave_recv_load_buf(sdio_slave_buf_handle_t handle) +{ + buf_desc_t *desc = (buf_desc_t*)handle; + CHECK_HANDLE_IDLE( desc ); + + buf_stailq_t *const queue = &context.recv_link_list; + + critical_enter_recv(); + TAILQ_REMOVE( &context.recv_reg_list, desc, te ); + desc->owner = 1; + desc->not_receiving = 0; //manually remove the prev link (by set not_receiving=0), to indicate this is in the queue + + // 1. If all desc are returned in the ISR, the pointer is moved to NULL. The pointer is set to the newly appended desc here. + // 2. If the pointer is move to some not-returned desc (maybe the one appended here), do nothing. + // The ``cur_ret`` pointer must be checked and set after new desc appended to the list, or the pointer setting may fail. + STAILQ_INSERT_TAIL( queue, desc, qe ); + if ( context.recv_cur_ret == NULL ) { + context.recv_cur_ret = desc; + } + + if ( desc == STAILQ_FIRST(queue) ) { + //no one in the ll, start new ll operation. + SLC.slc0_tx_link.addr = (uint32_t)desc; + SLC.slc0_tx_link.start = 1; + ESP_LOGV(TAG, "recv_load_buf: start new"); + } else { + //restart former ll operation + SLC.slc0_tx_link.restart = 1; + ESP_LOGV(TAG, "recv_load_buf: restart"); + } + critical_exit_recv(); + recv_size_inc(); + + return ESP_OK; +} + +sdio_slave_buf_handle_t sdio_slave_recv_register_buf(uint8_t *start) +{ + SDIO_SLAVE_CHECK( esp_ptr_dma_capable(start) && (uint32_t)start%4==0, + "buffer to register should be DMA capable and 32-bit aligned", NULL); + buf_desc_t *desc = (buf_desc_t*)malloc(sizeof(buf_desc_t)); + if ( desc == NULL ) { + SDIO_SLAVE_LOGE( "cannot allocate lldesc for new buffer" ); + return NULL; + } + + //initially in the reg list + *desc = (buf_desc_t) { + .size = context.config.recv_buffer_size, + .buf = start, + //no length required, eof always=0 + }; + critical_enter_recv(); + TAILQ_INSERT_TAIL( &context.recv_reg_list, desc, te ); + critical_exit_recv(); + return desc; +} + +esp_err_t sdio_slave_recv(sdio_slave_buf_handle_t* handle_ret, uint8_t **start_o, size_t *len_o, TickType_t wait) +{ + SDIO_SLAVE_CHECK( handle_ret != NULL, "handle address cannot be 0", ESP_ERR_INVALID_ARG); + portBASE_TYPE ret = xSemaphoreTake( context.recv_event, wait ); + if ( ret == pdFALSE ) return ESP_ERR_TIMEOUT; + + buf_stailq_t *const queue = &context.recv_link_list; + + critical_enter_recv(); + //remove from queue, add back to reg list. + buf_desc_t *desc = STAILQ_FIRST(queue); + STAILQ_REMOVE_HEAD(queue, qe); + TAILQ_INSERT_TAIL( &context.recv_reg_list, desc, te ); + critical_exit_recv(); + + assert( desc != NULL && desc->owner == 0 ); + *handle_ret = (sdio_slave_buf_handle_t)desc; + if ( start_o ) *start_o = desc->buf; + if ( len_o ) *len_o = desc->length; + return ESP_OK; +} + +esp_err_t sdio_slave_recv_unregister_buf(sdio_slave_buf_handle_t handle) +{ + buf_desc_t *desc = (buf_desc_t*)handle; + CHECK_HANDLE_IDLE( desc ); //in the queue, fail. + + critical_enter_recv(); + TAILQ_REMOVE( &context.recv_reg_list, desc, te ); + critical_exit_recv(); + free(desc); + return ESP_OK; +} + +uint8_t* sdio_slave_recv_get_buf( sdio_slave_buf_handle_t handle, size_t *len_o ) +{ + buf_desc_t *desc = (buf_desc_t*)handle; + if ( handle == NULL ) return NULL; + + if ( len_o!= NULL ) *len_o= desc->length; + return desc->buf; +} From 1b45e1117b192885aeb9f2afcc3ad6506fed0b04 Mon Sep 17 00:00:00 2001 From: michael Date: Mon, 4 Dec 2017 20:05:09 +0800 Subject: [PATCH 148/187] doc(sdio_slave): documentation for SDIO slave driver --- docs/Doxyfile | 2 + .../peripherals/esp_slave_protocol.rst | 85 +++++++ docs/en/api-reference/peripherals/index.rst | 1 + .../api-reference/peripherals/sdio_slave.rst | 227 ++++++++++++++++++ .../peripherals/esp_slave_protocol.rst | 1 + .../api-reference/peripherals/sdio_slave.rst | 1 + 6 files changed, 317 insertions(+) create mode 100644 docs/en/api-reference/peripherals/esp_slave_protocol.rst create mode 100644 docs/en/api-reference/peripherals/sdio_slave.rst create mode 100644 docs/zh_CN/api-reference/peripherals/esp_slave_protocol.rst create mode 100644 docs/zh_CN/api-reference/peripherals/sdio_slave.rst diff --git a/docs/Doxyfile b/docs/Doxyfile index 481eaa3fe5..53b31af2b6 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -107,6 +107,8 @@ INPUT = \ ../../components/driver/include/driver/sdmmc_host.h \ ../../components/driver/include/driver/sdmmc_types.h \ ../../components/driver/include/driver/sdspi_host.h \ + ## SDIO slave + ../../components/driver/include/driver/sdio_slave.h \ ## Non-Volatile Storage ../../components/nvs_flash/include/nvs.h \ ../../components/nvs_flash/include/nvs_flash.h \ diff --git a/docs/en/api-reference/peripherals/esp_slave_protocol.rst b/docs/en/api-reference/peripherals/esp_slave_protocol.rst new file mode 100644 index 0000000000..04cecca534 --- /dev/null +++ b/docs/en/api-reference/peripherals/esp_slave_protocol.rst @@ -0,0 +1,85 @@ +ESP SDIO slave protocol +======================= + +The protocol is based on Function 1 access by CMD52 and CMD53, offering 3 services: (1) sending and receiving FIFO, (2) 52 8-bit R/W +register shared by host and slave, (3) 8 general purpose interrupt sources from host to slave and 8 in the oppsite direction. + +The host should access the registers below as described to communicate with slave. + +Slave register table +-------------------- + +32-bit +^^^^^^^ +- 0x044 (TOKEN_RDATA): in which bit 27-16 holds the receiving buffer number. +- 0x058 (INT_ST): holds the interrupt source bits from slave to host. +- 0x060 (PKT_LEN): holds the accumulated length (by byte) to be sent from slave to host. +- 0x0D4 (INT_CLR): write 1 to clear interrupt bits corresponding to INT_ST. +- 0x0DC (INT_ENA): mask bits for interrupts from slave to host. + +8-bit +^^^^^ +Shared general purpose registers: + +- 0x06C-0x077: R/W registers 0-11 shared by slave and host. +- 0x07A-0x07B: R/W registers 14-15 shared by slave and host. +- 0x07E-0x07F: R/W registers 18-19 shared by slave and host. +- 0x088-0x08B: R/W registers 24-27 shared by slave and host. +- 0x09C-0x0BB: R/W registers 32-63 shared by slave and host. + +Interrupt Registers: +- 0x08D (SLAVE_INT): bits for host to interrupt slave. auto clear. + +FIFO (sending and receiving) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +0x090 - 0x1F7FF are reserved for FIFOs. + +.. note:: This includes the CMD52 and CMD53 (block mode or byte mode). + + The function number should be set to 1, OP Code should be set to 1 (for CMD53). + + The slave will respond with the length according to the length field in CMD53 (1 of CMD52), with the data longer + than *requested length* filled with 0 (sending) or discard (receiving). + +Interrupts +---------- + +For the host interrupts, the slave raise the interrupt by pulling DAT1 line down at a proper time (level sensitive). +The host detect this and read the INT_ST register to see the source. Then the host can clear it by writing the INT_CLR +register and do something with the interrupt. The host can also mask unneeded sources by clearing the bits in INT_ENA +register corresponding to the sources. If all the sources are cleared (or masked), the DAT1 line goes inactive. + +``sdio_slave_hostint_t`` (:doc:`sdio_slave`) shows the bit definition corresponding to host interrupt sources. + +For the slave interrupts, the host send transfers to write the SLAVE_INT register. Once a bit is written from 0 to 1, +the slave hardware and driver will detect it and inform the app. + +Receiving FIFO +-------------- + +To write the receiving FIFO in the slave, host should work in the following steps: + +1. Read the TOKEN1 field (bits 27-16) of TOKEN_RDATA (0x044) register. The buffer number remaining is TOKEN1 minus + the number of buffers used by host. +2. Make sure the buffer number is sufficient (*buffer_size* * *buffer_num* is greater than data to write, *buffer_size* + is pre-defined between the host and the slave before the communication starts). Or go back to step 1 until the buffer + is enough. +3. Write to the FIFO address with CMD53. Note that the *requested length* should not be larger than calculated in step 2, + and the FIFO address is related to *rquested length*. +4. Calculate used buffers, note that non-full buffer at the tail should be seen as one that is used. + +Sending FIFO +------------ + +To read the sending FIFO in the slave, host should work in the following steps: + +1. Wait for the interrupt line to be active (optional, low by default). +2. Read (poll) the interrupt bits in INT_ST register to see whether new packets exists. +3. If new packets are ready, reads the PKT_LEN reg. The data length to read from slave is PKT_LEN minuses the length + that has been read from the host. If the PKT_LEN is not larger than used, wait and poll until the slave is ready and + update the PKT_LEN. +4. Read from the FIFO with CMD53. Note that the *requested length* should not be larger than calculated in step3, and + the FIFO address is related to *requested length*. +5. Recored read length. + diff --git a/docs/en/api-reference/peripherals/index.rst b/docs/en/api-reference/peripherals/index.rst index 0b0d18a8ad..930e12a7b3 100644 --- a/docs/en/api-reference/peripherals/index.rst +++ b/docs/en/api-reference/peripherals/index.rst @@ -15,6 +15,7 @@ Peripherals API Remote Control SDMMC Host SD SPI Host + SDIO Slave Sigma-delta Modulation SPI Master SPI Slave diff --git a/docs/en/api-reference/peripherals/sdio_slave.rst b/docs/en/api-reference/peripherals/sdio_slave.rst new file mode 100644 index 0000000000..9e9b222ee3 --- /dev/null +++ b/docs/en/api-reference/peripherals/sdio_slave.rst @@ -0,0 +1,227 @@ +SDIO Card Slave Driver +====================== + +Overview +-------- + +.. note:: At the moment, this code has been proven to work on the Wrover-Kit V3. Earlier versions of the Wrover-Kit + and other development kits are electrically incompatible with this code. Functionality on other devboards is untested. + +The ESP32 SDIO Card peripherals (Host, Slave) shares two sets of pins as below table. +The first set is usually occupied by SPI0 bus which is responsible for the SPI flash holding the code to run. +This means SDIO slave driver can only runs on the second set of pins while SDIO host is not using it. + ++----------+-------+-------+ +| Pin Name | Slot1 | Slot2 | ++ +-------+-------+ +| | GPIO Number | ++==========+=======+=======+ +| CLK | 6 | 14 | ++----------+-------+-------+ +| CMD | 11 | 15 | ++----------+-------+-------+ +| DAT0 | 7 | 2 | ++----------+-------+-------+ +| DAT1 | 8 | 4 | ++----------+-------+-------+ +| DAT2 | 9 | 12 | ++----------+-------+-------+ +| DAT3 | 10 | 13 | ++----------+-------+-------+ + +The SDIO slave can run under 3 modes: SPI, 1-bit SD and 4-bit SD modes, which is detected automatically by the +hardware. According to the SDIO specification, the host initialize the slave into SD mode by first sending CMD0 with +DAT3 pin high, while initialize the slave into SPI mode by sending CMD0 with CS pin (the same pin as DAT3) low. After the +initialization, the host can enable the 4-bit SD mode by writing CCCR register 0x07 by CMD52. All the bus detection +process are handled by the slave peripheral. + +The host has to communicate with the slave by an ESP-slave-specific protocol. The slave driver offers 3 services over +Function 1 access by CMD52 and CMD53: (1) a sending FIFO and a receiving FIFO, (2) 52 8-bit R/W registers shared by +host and slave, (3) 16 interrupt sources (8 from host to slave, and 8 from slave to host). + +Terminology +^^^^^^^^^^^ + +The SDIO slave driver uses the following terms: + +- Transfer: a transfer is always started by a command token from the host, and may contain a reply and several data + blocks. ESP32 slave software is based on transfers. +- Sending: slave to host transfers. +- Receiving: host to slave transfers. + +.. note:: Register names in ESP Rechnical Reference Manual are oriented from the point of view of the host, i.e. 'rx' + registers refer to sending, while 'tx' registers refer to receiving. We're not using `tx` or `rx` in the driver to + avoid ambiguities. + +- FIFO: specific address in Function 1 that can be access by CMD53 to read/write large amount of data. The address is + related to the length requested to read from/write to the slave in a single transfer: + *requested length* = 0x1F800-address. +- Ownership: When the driver takes ownership of a buffer, it means the driver can randomly read/write the buffer + (mostly by the hardware). The application should not read/write the buffer until the ownership is returned to the + application. If the application reads from a buffer owned by a receiving driver, the data read can be random; if + the application writes to a buffer owned by a sending driver, the data sent may be corrupted. +- Requested length: The length requested in one transfer determined by the FIFO address. +- Transfer length: The length requested in one transfer determined by the CMD53 byte/block count field. + +.. note:: Requested length is different from the transfer length. ESP32 slave DMA base on the *requested length* rather + than the *transfer length*. The *transfer length* should be no shorter than the *requested length*, and the rest + part will be filled with 0 (sending) or discard (receiving). + +- Receiving buffer size: The buffer size is pre-defined between the host and the slave before communication starts. + Slave application has to set the buffer size during initialization by the ``recv_buffer_size`` member of + ``sdio_slave_config_t``. +- Interrupts: the esp32 slave support interrupts in two directions: from host to slave (called slave interrupts below) + and from slave to host (called host interrupts below). See more in :ref:`interrupts`. +- Registers: specific address in Function 1 access by CMD52 or CMD53. + +ESP SDIO Slave Protocol +^^^^^^^^^^^^^^^^^^^^^^^ + +The communication protocol slave used to communicate with the host is ESP32 specific, please refer to +:doc:`esp_slave_protocol`, or example :example:`peripherals/sdio` for designing a host. + +.. toctree:: + :hidden: + + esp_slave_protocol + +.. _interrupts: + +Interrupts +^^^^^^^^^^ + +There are interrupts from host to slave, and from slave to host to help communicating conveniently. + +Slave Interrupts +"""""""""""""""" + +The host can interrupt the slave by writing any one bit in the register 0x08D. Once any bit of the register is +set, an interrupt is raised and the SDIO slave driver calls the callback function defined in the ``slave_intr_cb`` member +in the ``sdio_slave_config_t`` structure. + +.. note:: The callback function is called in the ISR, do not use any delay, loop or spinlock in the callback. + +There's another set of functions can be used. You can call ``sdio_slave_wait_int`` to wait for an interrupt within a +certain time, or call ``sdio_slave_clear_int`` to clear interrupts from host. The callback function can work with the +wait functions perfectly. + +Host Interrupts +""""""""""""""" + +The slave can interrupt the host by an interrupt line (at certain time) which is level sensitive. When the host see the +interrupt line pulled down, it may read the slave interrupt status register, to see the interrupt source. Host can clear +interrupt bits, or choose to disable a interrupt source. The interrupt line will hold active until all the sources are +cleared or disabled. + +There are several dedicated interrupt sources as well as general purpose sources. see ``sdio_slave_hostint_t`` for +more information. + +Shared Registers +^^^^^^^^^^^^^^^^ + +There are 52 8-bit R/W shared registers to share information between host and slave. The slave can write or read the +registers at any time by ``sdio_slave_read_reg`` and ``sdio_slave_write_reg``. The host can access (R/W) the register by CMD52 or CMD53. + +Receiving FIFO +^^^^^^^^^^^^^^ + +When the host is going to send the slave some packets, it has to check whether the slave is ready to receive by reading +the buffer number of slave. + +To allow the host sending data to the slave, the application has to load buffers to the slave driver by the following steps: + +1. Register the buffer by calling ``sdio_slave_recv_register_buf``, and get the handle of the registered buffer. The driver + will allocate memory for the linked-list descriptor needed to link the buffer onto the hardware. +2. Load buffers onto the driver by passing the buffer handle to ``sdio_slave_recv_load_buf``. +3. Call ``sdio_slave_recv`` to get the received data. If non-blocking call is needed, set ``wait=0``. +4. Pass the handle of processed buffer back to the driver by ``sdio_recv_load_buf`` again. + +.. note:: To avoid overhead from copying data, the driver itself doesn't have any buffer inside, the application is + responsible to offer new buffers in time. The DMA will automatically store received data to the buffer. + +Sending FIFO +^^^^^^^^^^^^ + +Each time the slave has data to send, it raises an interrupt and the host will request for the packet length. There are +two sending modes: + +- Stream Mode: when a buffer is loaded to the driver, the buffer length will be counted into the packet length requested + by host in the incoming communications. Regardless previous packets are sent or not. This means the host can get data + of several buffers in one transfer. +- Packet Mode: the packet length is updated packet by packet, and only when previous packet is sent. This means that the + host can only get data of one buffer in one transfer. + +.. note:: To avoid overhead from copying data, the driver itself doesn't have any buffer inside. Namely, the DMA takes + data directly from the buffer provided by the application. The application should not touch the buffer until the + sending is finished. + +The sending mode can be set in the ``sending_mode`` member of ``sdio_slave_config_t``, and the buffer numbers can be +set in the ``send_queue_size``. All the buffers are restricted to be no larger than 4092 bytes. Though in the stream +mode several buffers can be sent in one transfer, each buffer is still counted as one in the queue. + +The application can call ``sdio_slave_transmit`` to send packets. In this case the function returns when the transfer +is sucessfully done, so the queue is not fully used. When higher effeciency is required, the application can use the +following functions instead: + +1. Pass buffer information (address, length, as well as an ``arg`` indicating the buffer) to ``sdio_slave_send_queue``. + If non-blocking call is needed, set ``wait=0``. If the ``wait`` is not ``portMAX_DELAY`` (wait until success), + application has to check the result to know whether the data is put in to the queue or discard. + +2. Call ``sdio_slave_send_get_finished`` to get and deal with a finished transfer. A buffer should be keep unmodified + until returned from ``sdio_slave_send_get_finished``. This means the buffer is actually sent to the host, rather + than just staying in the queue. + +There are several ways to use the ``arg`` in the queue parameter: + + 1. Directly point ``arg`` to a dynamic-allocated buffer, and use the ``arg`` to free it when transfer finished. + 2. Wrap transfer informations in a transfer structure, and point ``arg`` to the structure. You can use the + structure to do more things like:: + + typedef struct { + uint8_t* buffer; + size_t size; + int id; + }sdio_transfer_t; + + //and send as: + sdio_transfer_t trans = { + .buffer = ADDRESS_TO_SEND, + .size = 8, + .id = 3, //the 3rd transfer so far + }; + sdio_slave_send_queue(trans.buffer, trans.size, &trans, portMAX_DELAY); + + //... maybe more transfers are sent here + + //and deal with finished transfer as: + sdio_transfer_t* arg = NULL; + sdio_slave_send_get_finished((void**)&arg, portMAX_DELAY); + ESP_LOGI("tag", "(%d) successfully send %d bytes of %p", arg->id, arg->size, arg->buffer); + some_post_callback(arg); //do more things + + 3. Working with the receiving part of this driver, point ``arg`` to the receive buffer handle of this buffer. So + that we can directly use the buffer to receive data when it's sent:: + + uint8_t buffer[256]={1,2,3,4,5,6,7,8}; + sdio_slave_buf_handle_t handle = sdio_slave_recv_register_buf(buffer); + sdio_slave_send_queue(buffer, 8, handle, portMAX_DELAY); + + //... maybe more transfers are sent here + + //and load finished buffer to receive as + sdio_slave_buf_handle_t handle = NULL; + sdio_slave_send_get_finished((void**)&handle, portMAX_DELAY); + sdio_slave_recv_load_buf(handle); + + More about this, see :example:`peripherals/sdio`. + +Application Example +------------------- + +Slave/master communication: :example:`peripherals/sdio`. + +API Reference +------------- + +.. include:: /_build/inc/sdio_slave.inc + diff --git a/docs/zh_CN/api-reference/peripherals/esp_slave_protocol.rst b/docs/zh_CN/api-reference/peripherals/esp_slave_protocol.rst new file mode 100644 index 0000000000..6fc80e9b9d --- /dev/null +++ b/docs/zh_CN/api-reference/peripherals/esp_slave_protocol.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/peripherals/esp_slave_protocol.rst \ No newline at end of file diff --git a/docs/zh_CN/api-reference/peripherals/sdio_slave.rst b/docs/zh_CN/api-reference/peripherals/sdio_slave.rst new file mode 100644 index 0000000000..98a10bd77f --- /dev/null +++ b/docs/zh_CN/api-reference/peripherals/sdio_slave.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/peripherals/sdio_slave.rst \ No newline at end of file From e5b280f173a1bc02ce8966241fd49922e5edcaa5 Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Mon, 21 May 2018 15:10:03 +0500 Subject: [PATCH 149/187] dport: Bigfix dport_read code move to IRAM A new method of workaround an error with DPORT is to ensure that the APB is read and followed by the DPORT register without interruptions and pauses. This fix places this implementation in the IRAM to exclude errors associated with the cache miss. --- components/esp32/dport_access.c | 74 +++++++++++++++++++ components/esp32/include/esp_dport_access.h | 3 +- .../soc/esp32/include/soc/dport_access.h | 53 +++---------- 3 files changed, 85 insertions(+), 45 deletions(-) diff --git a/components/esp32/dport_access.c b/components/esp32/dport_access.c index 4e5d5b1776..731bdb7ec5 100644 --- a/components/esp32/dport_access.c +++ b/components/esp32/dport_access.c @@ -236,3 +236,77 @@ void IRAM_ATTR esp_dport_access_read_buffer(uint32_t *buff_out, uint32_t address } DPORT_INTERRUPT_RESTORE(); } + +/** + * @brief Read value from register, SMP-safe version. + * + * This method uses the pre-reading of the APB register before reading the register of the DPORT. + * This implementation is useful for reading DORT registers for single reading without stall other CPU. + * There is disable/enable interrupt. + * + * @param reg Register address + * @return Value + */ +uint32_t IRAM_ATTR esp_dport_access_reg_read(uint32_t reg) +{ +#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM) + return _DPORT_REG_READ(reg); +#else + uint32_t apb; + unsigned int intLvl; + __asm__ __volatile__ (\ + "movi %[APB], "XTSTR(0x3ff40078)"\n"\ + "rsil %[LVL], "XTSTR(3)"\n"\ + "l32i %[APB], %[APB], 0\n"\ + "l32i %[REG], %[REG], 0\n"\ + "wsr %[LVL], "XTSTR(PS)"\n"\ + "rsync\n"\ + : [APB]"=a"(apb), [REG]"+a"(reg), [LVL]"=a"(intLvl)\ + : \ + : "memory" \ + ); + return reg; +#endif +} + +/** + * @brief Read value from register, NOT SMP-safe version. + * + * This method uses the pre-reading of the APB register before reading the register of the DPORT. + * There is not disable/enable interrupt. + * The difference from DPORT_REG_READ() is that the user himself must disable interrupts while DPORT reading. + * This implementation is useful for reading DORT registers in loop without stall other CPU. Note the usage example. + * The recommended way to read registers sequentially without stall other CPU + * is to use the method esp_dport_read_buffer(buff_out, address, num_words). It allows you to read registers in the buffer. + * + * \code{c} + * // This example shows how to use it. + * { // Use curly brackets to limit the visibility of variables in macros DPORT_INTERRUPT_DISABLE/RESTORE. + * DPORT_INTERRUPT_DISABLE(); // Disable interrupt only on current CPU. + * for (i = 0; i < max; ++i) { + * array[i] = esp_dport_access_sequence_reg_read(Address + i * 4); // reading DPORT registers + * } + * DPORT_INTERRUPT_RESTORE(); // restore the previous interrupt level + * } + * \endcode + * + * @param reg Register address + * @return Value + */ +uint32_t IRAM_ATTR esp_dport_access_sequence_reg_read(uint32_t reg) +{ +#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM) + return _DPORT_REG_READ(reg); +#else + uint32_t apb; + __asm__ __volatile__ (\ + "movi %[APB], "XTSTR(0x3ff40078)"\n"\ + "l32i %[APB], %[APB], 0\n"\ + "l32i %[REG], %[REG], 0\n"\ + : [APB]"=a"(apb), [REG]"+a"(reg)\ + : \ + : "memory" \ + ); + return reg; +#endif +} diff --git a/components/esp32/include/esp_dport_access.h b/components/esp32/include/esp_dport_access.h index 1a46fa00c9..adbb828201 100644 --- a/components/esp32/include/esp_dport_access.h +++ b/components/esp32/include/esp_dport_access.h @@ -27,6 +27,8 @@ void esp_dport_access_int_init(void); void esp_dport_access_int_pause(void); void esp_dport_access_int_resume(void); void esp_dport_access_read_buffer(uint32_t *buff_out, uint32_t address, uint32_t num_words); +uint32_t esp_dport_access_reg_read(uint32_t reg); +uint32_t esp_dport_access_sequence_reg_read(uint32_t reg); //This routine does not stop the dport routines in any way that is recoverable. Please //only call in case of panic(). void esp_dport_access_int_abort(void); @@ -34,7 +36,6 @@ void esp_dport_access_int_abort(void); #if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM) #define DPORT_STALL_OTHER_CPU_START() #define DPORT_STALL_OTHER_CPU_END() -#define DPORT_STALL_OTHER_CPU_START() #define DPORT_INTERRUPT_DISABLE() #define DPORT_INTERRUPT_RESTORE() #else diff --git a/components/soc/esp32/include/soc/dport_access.h b/components/soc/esp32/include/soc/dport_access.h index db39082413..00e7c83810 100644 --- a/components/soc/esp32/include/soc/dport_access.h +++ b/components/soc/esp32/include/soc/dport_access.h @@ -73,23 +73,10 @@ extern "C" { */ static inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg) { -#ifndef CONFIG_FREERTOS_UNICORE - uint32_t apb; - unsigned int intLvl; - __asm__ __volatile__ (\ - "movi %[APB], "XTSTR(0x3ff40078)"\n"\ - "rsil %[LVL], "XTSTR(3)"\n"\ - "l32i %[APB], %[APB], 0\n"\ - "l32i %[REG], %[REG], 0\n"\ - "wsr %[LVL], "XTSTR(PS)"\n"\ - "rsync\n"\ - : [APB]"=a"(apb), [REG]"+a"(reg), [LVL]"=a"(intLvl)\ - : \ - : "memory" \ - ); - return reg; -#else +#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM) return _DPORT_REG_READ(reg); +#else + return esp_dport_access_reg_read(reg); #endif } @@ -119,19 +106,10 @@ static inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg) */ static inline uint32_t IRAM_ATTR DPORT_SEQUENCE_REG_READ(uint32_t reg) { -#ifndef CONFIG_FREERTOS_UNICORE - uint32_t apb; - __asm__ __volatile__ (\ - "movi %[APB], "XTSTR(0x3ff40078)"\n"\ - "l32i %[APB], %[APB], 0\n"\ - "l32i %[REG], %[REG], 0\n"\ - : [APB]"=a"(apb), [REG]"+a"(reg)\ - : \ - : "memory" \ - ); - return reg; -#else +#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM) return _DPORT_REG_READ(reg); +#else + return esp_dport_access_sequence_reg_read(reg); #endif } @@ -188,23 +166,10 @@ static inline uint32_t IRAM_ATTR DPORT_SEQUENCE_REG_READ(uint32_t reg) */ static inline uint32_t IRAM_ATTR DPORT_READ_PERI_REG(uint32_t reg) { -#ifndef CONFIG_FREERTOS_UNICORE - uint32_t apb; - unsigned int intLvl; - __asm__ __volatile__ (\ - "movi %[APB], "XTSTR(0x3ff40078)"\n"\ - "rsil %[LVL], "XTSTR(3)"\n"\ - "l32i %[APB], %[APB], 0\n"\ - "l32i %[REG], %[REG], 0\n"\ - "wsr %[LVL], "XTSTR(PS)"\n"\ - "rsync\n"\ - : [APB]"=a"(apb), [REG]"+a"(reg), [LVL]"=a"(intLvl)\ - : \ - : "memory" \ - ); - return reg; +#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM) + return _DPORT_REG_READ(reg); #else - return _DPORT_READ_PERI_REG(reg); + return esp_dport_access_reg_read(reg); #endif } From 6d85d159d643917f2c69acb039f3f2a548610942 Mon Sep 17 00:00:00 2001 From: krzychb Date: Sat, 19 May 2018 17:28:36 +0200 Subject: [PATCH 150/187] Updated pictures of user configurable jumpers to reflect Version 3 of ESP-WROVER-KIT. This includes changing the picture of JTAG jumper block by removing the jumper on S_TDI. It has been reported by a number of users that removing this jumper fixes random communication issues observed in OpenOCD. --- docs/_static/esp-wrover-kit-v3-jp11-tx-rx.png | Bin 0 -> 66108 bytes docs/_static/esp-wrover-kit-v3-jp14.png | Bin 0 -> 88307 bytes docs/_static/esp-wrover-kit-v3-jp7-ext_5v.png | Bin 0 -> 60364 bytes docs/_static/esp-wrover-kit-v3-jp7-usb_5v.png | Bin 0 -> 63333 bytes docs/_static/esp-wrover-kit-v3-jp8.png | Bin 0 -> 74599 bytes docs/en/get-started/get-started-wrover-kit.rst | 13 +++++-------- 6 files changed, 5 insertions(+), 8 deletions(-) create mode 100644 docs/_static/esp-wrover-kit-v3-jp11-tx-rx.png create mode 100644 docs/_static/esp-wrover-kit-v3-jp14.png create mode 100644 docs/_static/esp-wrover-kit-v3-jp7-ext_5v.png create mode 100644 docs/_static/esp-wrover-kit-v3-jp7-usb_5v.png create mode 100644 docs/_static/esp-wrover-kit-v3-jp8.png diff --git a/docs/_static/esp-wrover-kit-v3-jp11-tx-rx.png b/docs/_static/esp-wrover-kit-v3-jp11-tx-rx.png new file mode 100644 index 0000000000000000000000000000000000000000..39c1c54c2fe32cb425cf1f5d2f5008e7901f6fd2 GIT binary patch literal 66108 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 Rs%!uN002ovPDHLkV1k58xsd<> literal 0 HcmV?d00001 diff --git a/docs/_static/esp-wrover-kit-v3-jp7-usb_5v.png b/docs/_static/esp-wrover-kit-v3-jp7-usb_5v.png new file mode 100644 index 0000000000000000000000000000000000000000..efe66d9789eb238506e95a5332844d82d65a56f1 GIT binary patch literal 63333 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 z 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 Date: Sat, 19 May 2018 17:45:40 +0200 Subject: [PATCH 151/187] Provided links to 'Touch Sensor Application Note' and 'Guide for ESP32-Sense Development Kit' --- docs/_static/esp-wrover-kit-v3-jp11-tx-rx.png | Bin 66108 -> 68947 bytes docs/_static/esp-wrover-kit-v3-jp14.png | Bin 88307 -> 80704 bytes docs/_static/esp-wrover-kit-v3-jp7-ext_5v.png | Bin 60364 -> 58329 bytes docs/_static/esp-wrover-kit-v3-jp7-usb_5v.png | Bin 63333 -> 60034 bytes docs/_static/esp-wrover-kit-v3-jp8.png | Bin 74599 -> 74337 bytes .../api-reference/peripherals/touch_pad.rst | 2 ++ 6 files changed, 2 insertions(+) diff --git a/docs/_static/esp-wrover-kit-v3-jp11-tx-rx.png b/docs/_static/esp-wrover-kit-v3-jp11-tx-rx.png index 39c1c54c2fe32cb425cf1f5d2f5008e7901f6fd2..4411642e4bf488af8595d641bed6d96fd1e4684f 100644 GIT binary patch literal 68947 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

x+ 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

iQ=r2qrh?LF$>;LEJ;aj( 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

L;aTtKMr}>NVbmnYVy{c3|>CmJLiFt&X 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 Rs%!uN002ovPDHLkV1k58xsd<> diff --git a/docs/_static/esp-wrover-kit-v3-jp7-usb_5v.png b/docs/_static/esp-wrover-kit-v3-jp7-usb_5v.png index efe66d9789eb238506e95a5332844d82d65a56f1..579870c73d328d7e2951d748624abc3907696304 100644 GIT binary patch literal 60034 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%0AeyG+U8)s@iCsnVs(+7|R!nFrLk1#>OV} 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 literal 63333 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 z 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 z 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 Hu0mjf;eh9v literal 74599 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 (PDF). Please refer to it for additional details how this subsystem works. +In depth details of design of touch sensors and firmware development guidelines for the ESP32 are available in `Touch Sensor Application Note `_. If you would like to test touch sensors in various configurations without building them on your own, check `Guide for ESP32-Sense Development Kit `_. + Functionality Overview ---------------------- From 5bc8ae3b3a8be3e276c3318865efa9f0b5d82720 Mon Sep 17 00:00:00 2001 From: kooho <2229179028@qq.com> Date: Sat, 24 Feb 2018 13:36:49 +0800 Subject: [PATCH 152/187] driver(rmt):Add API supports sending uint8_t type data. --- components/driver/include/driver/rmt.h | 59 +++++++++ components/driver/rmt.c | 123 ++++++++++++++++-- .../peripherals/rmt_tx/main/rmt_tx_main.c | 38 +++++- 3 files changed, 208 insertions(+), 12 deletions(-) diff --git a/components/driver/include/driver/rmt.h b/components/driver/include/driver/rmt.h index a1bcbe8195..7abf63ec08 100644 --- a/components/driver/include/driver/rmt.h +++ b/components/driver/include/driver/rmt.h @@ -129,6 +129,32 @@ typedef struct { void *arg; /*!< Optional argument passed to function */ } rmt_tx_end_callback_t; +/** + * @brief User callback function to convert uint8_t type data to rmt format(rmt_item32_t). + * + * This function may be called from an ISR, so, the code should be short and efficient. + * + * @param src Pointer to the buffer storing the raw data that needs to be converted to rmt format. + * + * @param[out] dest Pointer to the buffer storing the rmt format data. + * + * @param src_size The raw data size. + * + * @param wanted_num The number of rmt format data that wanted to get. + * + * @param[out] translated_size The size of the raw data that has been converted to rmt format, + * it should return 0 if no data is converted in user callback. + * + * @param[out] item_num The number of the rmt format data that actually converted to, it can be less than wanted_num if there is not enough raw data, + * but cannot exceed wanted_num. it should return 0 if no data was converted. + * + * @note + * In fact, item_num should be a multiple of translated_size, e.g. : + * When we convert each byte of uint8_t type data to rmt format data, + * the relation between item_num and translated_size should be `item_num = translated_size*8`. + */ +typedef void (*sample_to_rmt_t)(const void* src, rmt_item32_t* dest, size_t src_size, size_t wanted_num, size_t* translated_size, size_t* item_num); + /** * @brief Set RMT clock divider, channel clock is divided from source clock. * @@ -714,6 +740,39 @@ esp_err_t rmt_wait_tx_done(rmt_channel_t channel, TickType_t wait_time); */ esp_err_t rmt_get_ringbuf_handle(rmt_channel_t channel, RingbufHandle_t* buf_handle); +/** + * @brief Init rmt translator and register user callback. + * The callback will convert the raw data that needs to be sent to rmt format. + * If a channel is initialized more than once, tha user callback will be replaced by the later. + * + * @param channel RMT channel (0 - 7). + * + * @param fn Point to the data conversion function. + * + * @return + * - ESP_FAIL Init fail. + * - ESP_OK Init success. + */ +esp_err_t rmt_translator_init(rmt_channel_t channel, sample_to_rmt_t fn); + +/** + * @brief Translate uint8_t type of data into rmt format and send it out. + * Requires rmt_translator_init to init the translator first. + * + * @param channel RMT channel (0 - 7). + * + * @param src Pointer to the raw data. + * + * @param src_size The size of the raw data. + * + * @param wait_tx_done Set true to wait all data send done. + * + * @return + * - ESP_FAIL Send fail + * - ESP_OK Send success + */ +esp_err_t rmt_write_sample(rmt_channel_t channel, const uint8_t *src, size_t src_size, bool wait_tx_done); + /** * @brief Registers a callback that will be called when transmission ends. * diff --git a/components/driver/rmt.c b/components/driver/rmt.c index ca0dc6a28c..9460cefa71 100644 --- a/components/driver/rmt.c +++ b/components/driver/rmt.c @@ -46,6 +46,8 @@ #define RMT_DRIVER_ERROR_STR "RMT DRIVER ERR" #define RMT_DRIVER_LENGTH_ERROR_STR "RMT PARAM LEN ERROR" #define RMT_PSRAM_BUFFER_WARN_STR "Using buffer allocated from psram" +#define RMT_TRANSLATOR_NULL_STR "RMT translator is null" +#define RMT_TRANSLATOR_UNINIT_STR "RMT translator not init" static const char* RMT_TAG = "rmt"; static uint8_t s_rmt_driver_channels; // Bitmask (bits 0-7) of installed drivers' channels @@ -64,9 +66,10 @@ static portMUX_TYPE rmt_spinlock = portMUX_INITIALIZER_UNLOCKED; static _lock_t rmt_driver_isr_lock; typedef struct { - int tx_offset; - int tx_len_rem; - int tx_sub_len; + size_t tx_offset; + size_t tx_len_rem; + size_t tx_sub_len; + bool translator; bool wait_done; //Mark whether wait tx done. rmt_channel_t channel; const rmt_item32_t* tx_data; @@ -75,8 +78,11 @@ typedef struct { int intr_alloc_flags; StaticSemaphore_t tx_sem_buffer; #endif - RingbufHandle_t tx_buf; + rmt_item32_t* tx_buf; RingbufHandle_t rx_buf; + sample_to_rmt_t sample_to_rmt; + size_t sample_size_remain; + const uint8_t *sample_cur; } rmt_obj_t; rmt_obj_t* p_rmt_obj[RMT_CHANNEL_MAX] = {0}; @@ -559,9 +565,6 @@ static void IRAM_ATTR rmt_driver_isr_default(void* arg) xSemaphoreGiveFromISR(p_rmt->tx_sem, &HPTaskAwoken); RMT.conf_ch[channel].conf1.mem_rd_rst = 1; RMT.conf_ch[channel].conf1.mem_rd_rst = 0; - if(HPTaskAwoken == pdTRUE) { - portYIELD_FROM_ISR(); - } p_rmt->tx_data = NULL; p_rmt->tx_len_rem = 0; p_rmt->tx_offset = 0; @@ -583,9 +586,6 @@ static void IRAM_ATTR rmt_driver_isr_default(void* arg) } else { } - if(HPTaskAwoken == pdTRUE) { - portYIELD_FROM_ISR(); - } } else { ESP_EARLY_LOGE(RMT_TAG, "RMT RX BUFFER ERROR\n"); } @@ -613,6 +613,24 @@ static void IRAM_ATTR rmt_driver_isr_default(void* arg) if(p_rmt->tx_data == NULL) { //skip } else { + if(p_rmt->translator) { + if(p_rmt->sample_size_remain > 0) { + size_t translated_size = 0; + p_rmt->sample_to_rmt((void *) p_rmt->sample_cur, + p_rmt->tx_buf, + p_rmt->sample_size_remain, + p_rmt->tx_sub_len, + &translated_size, + &p_rmt->tx_len_rem + ); + p_rmt->sample_size_remain -= translated_size; + p_rmt->sample_cur += translated_size; + p_rmt->tx_data = p_rmt->tx_buf; + } else { + p_rmt->sample_cur = NULL; + p_rmt->translator = false; + } + } const rmt_item32_t* pdata = p_rmt->tx_data; int len_rem = p_rmt->tx_len_rem; if(len_rem >= p_rmt->tx_sub_len) { @@ -636,6 +654,9 @@ static void IRAM_ATTR rmt_driver_isr_default(void* arg) } } } + if(HPTaskAwoken == pdTRUE) { + portYIELD_FROM_ISR(); + } } esp_err_t rmt_driver_uninstall(rmt_channel_t channel) @@ -677,6 +698,13 @@ esp_err_t rmt_driver_uninstall(rmt_channel_t channel) vRingbufferDelete(p_rmt_obj[channel]->rx_buf); p_rmt_obj[channel]->rx_buf = NULL; } + if(p_rmt_obj[channel]->tx_buf) { + free(p_rmt_obj[channel]->tx_buf); + p_rmt_obj[channel]->tx_buf = NULL; + } + if(p_rmt_obj[channel]->sample_to_rmt) { + p_rmt_obj[channel]->sample_to_rmt = NULL; + } free(p_rmt_obj[channel]); p_rmt_obj[channel] = NULL; @@ -717,7 +745,8 @@ esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int intr p_rmt_obj[channel]->tx_offset = 0; p_rmt_obj[channel]->tx_sub_len = 0; p_rmt_obj[channel]->wait_done = false; - + p_rmt_obj[channel]->translator = false; + p_rmt_obj[channel]->sample_to_rmt = NULL; if(p_rmt_obj[channel]->tx_sem == NULL) { #if !CONFIG_SPIRAM_USE_MALLOC p_rmt_obj[channel]->tx_sem = xSemaphoreCreateBinary(); @@ -829,3 +858,75 @@ rmt_tx_end_callback_t rmt_register_tx_end_callback(rmt_tx_end_fn_t function, voi rmt_tx_end_callback.arg = arg; return previous; } + +esp_err_t rmt_translator_init(rmt_channel_t channel, sample_to_rmt_t fn) +{ + RMT_CHECK(fn != NULL, RMT_TRANSLATOR_NULL_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(p_rmt_obj[channel] != NULL, RMT_DRIVER_ERROR_STR, ESP_FAIL); + const uint32_t block_size = RMT.conf_ch[channel].conf0.mem_size * RMT_MEM_ITEM_NUM * sizeof(rmt_item32_t); + if (p_rmt_obj[channel]->tx_buf == NULL) { +#if !CONFIG_SPIRAM_USE_MALLOC + p_rmt_obj[channel]->tx_buf = (rmt_item32_t *)malloc(block_size); +#else + if( p_rmt_obj[channel]->intr_alloc_flags & ESP_INTR_FLAG_IRAM ) { + p_rmt_obj[channel]->tx_buf = (rmt_item32_t *)malloc(block_size); + } else { + p_rmt_obj[channel]->tx_buf = (rmt_item32_t *)heap_caps_calloc(1, block_size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + } +#endif + if(p_rmt_obj[channel]->tx_buf == NULL) { + ESP_LOGE(RMT_TAG, "RMT translator buffer create fail"); + return ESP_FAIL; + } + } + p_rmt_obj[channel]->sample_to_rmt = fn; + p_rmt_obj[channel]->sample_size_remain = 0; + p_rmt_obj[channel]->sample_cur = NULL; + ESP_LOGD(RMT_TAG, "RMT translator init done"); + return ESP_OK; +} + +esp_err_t rmt_write_sample(rmt_channel_t channel, const uint8_t *src, size_t src_size, bool wait_tx_done) +{ + RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG); + RMT_CHECK(p_rmt_obj[channel] != NULL, RMT_DRIVER_ERROR_STR, ESP_FAIL); + RMT_CHECK(p_rmt_obj[channel]->sample_to_rmt != NULL,RMT_TRANSLATOR_UNINIT_STR, ESP_FAIL); +#if CONFIG_SPIRAM_USE_MALLOC + if( p_rmt_obj[channel]->intr_alloc_flags & ESP_INTR_FLAG_IRAM ) { + if( !esp_ptr_internal(src) ) { + ESP_LOGE(RMT_TAG, RMT_PSRAM_BUFFER_WARN_STR); + return ESP_ERR_INVALID_ARG; + } + } +#endif + size_t item_num = 0; + size_t translated_size = 0; + rmt_obj_t* p_rmt = p_rmt_obj[channel]; + const uint32_t item_block_len = RMT.conf_ch[channel].conf0.mem_size * RMT_MEM_ITEM_NUM; + const uint32_t item_sub_len = item_block_len / 2; + xSemaphoreTake(p_rmt->tx_sem, portMAX_DELAY); + p_rmt->sample_to_rmt((void *)src, p_rmt->tx_buf, src_size, item_block_len, &translated_size, &item_num); + p_rmt->sample_size_remain = src_size - translated_size; + p_rmt->sample_cur = src + translated_size; + rmt_fill_memory(channel, p_rmt->tx_buf, item_num, 0); + if (item_num == item_block_len) { + rmt_set_tx_thr_intr_en(channel, 1, item_sub_len); + p_rmt->tx_data = p_rmt->tx_buf; + p_rmt->tx_offset = 0; + p_rmt->tx_sub_len = item_sub_len; + p_rmt->translator = true; + } else { + RMTMEM.chan[channel].data32[item_num].val = 0; + p_rmt->tx_len_rem = 0; + p_rmt->sample_cur = NULL; + p_rmt->translator = false; + } + rmt_tx_start(channel, true); + p_rmt->wait_done = wait_tx_done; + if (wait_tx_done) { + xSemaphoreTake(p_rmt->tx_sem, portMAX_DELAY); + xSemaphoreGive(p_rmt->tx_sem); + } + return ESP_OK; +} \ No newline at end of file diff --git a/examples/peripherals/rmt_tx/main/rmt_tx_main.c b/examples/peripherals/rmt_tx/main/rmt_tx_main.c index d71663a58e..ad6e4f6f65 100644 --- a/examples/peripherals/rmt_tx/main/rmt_tx_main.c +++ b/examples/peripherals/rmt_tx/main/rmt_tx_main.c @@ -15,6 +15,7 @@ static const char *RMT_TX_TAG = "RMT Tx"; #define RMT_TX_CHANNEL RMT_CHANNEL_0 #define RMT_TX_GPIO 18 +#define SAMPLE_CNT (10) /* * Prepare a raw table with a message in the Morse code @@ -48,6 +49,37 @@ rmt_item32_t items[] = { {{{ 0, 1, 0, 0 }}} }; +//Convert uint8_t type of data to rmt format data. +static void IRAM_ATTR u8_to_rmt(const void* src, rmt_item32_t* dest, size_t src_size, + size_t wanted_num, size_t* translated_size, size_t* item_num) +{ + if(src == NULL || dest == NULL) { + *translated_size = 0; + *item_num = 0; + return; + } + const rmt_item32_t bit0 = {{{ 32767, 1, 15000, 0 }}}; //Logical 0 + const rmt_item32_t bit1 = {{{ 32767, 1, 32767, 0 }}}; //Logical 1 + size_t size = 0; + size_t num = 0; + uint8_t *psrc = (uint8_t *)src; + rmt_item32_t* pdest = dest; + while (size < src_size && num < wanted_num) { + for(int i = 0; i < 8; i++) { + if(*psrc & (0x1 << i)) { + pdest->val = bit1.val; + } else { + pdest->val = bit0.val; + } + num++; + pdest++; + } + size++; + psrc++; + } + *translated_size = size; + *item_num = num; +} /* * Initialize the RMT Tx channel @@ -77,18 +109,22 @@ static void rmt_tx_int() ESP_ERROR_CHECK(rmt_config(&config)); ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0)); + ESP_ERROR_CHECK(rmt_translator_init(config.channel, u8_to_rmt)); } - void app_main(void *ignore) { ESP_LOGI(RMT_TX_TAG, "Configuring transmitter"); rmt_tx_int(); int number_of_items = sizeof(items) / sizeof(items[0]); + const uint8_t sample[SAMPLE_CNT] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; while (1) { ESP_ERROR_CHECK(rmt_write_items(RMT_TX_CHANNEL, items, number_of_items, true)); ESP_LOGI(RMT_TX_TAG, "Transmission complete"); + vTaskDelay(1000 / portTICK_PERIOD_MS); + ESP_ERROR_CHECK(rmt_write_sample(RMT_TX_CHANNEL, sample, SAMPLE_CNT, true)); + ESP_LOGI(RMT_TX_TAG, "Sample transmission complete"); vTaskDelay(2000 / portTICK_PERIOD_MS); } vTaskDelete(NULL); From 3fe862dacb7fa38f874a8f054f97f24d71eb0e5c Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 22 May 2018 09:46:15 +1000 Subject: [PATCH 153/187] test_multi_heap_host: Remove race conditions from parallel "make clean test" --- components/heap/test_multi_heap_host/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/heap/test_multi_heap_host/Makefile b/components/heap/test_multi_heap_host/Makefile index f0d5ab1fc1..16fd6439c5 100644 --- a/components/heap/test_multi_heap_host/Makefile +++ b/components/heap/test_multi_heap_host/Makefile @@ -1,6 +1,10 @@ TEST_PROGRAM=test_multi_heap all: $(TEST_PROGRAM) +ifneq ($(filter clean,$(MAKECMDGOALS)),) +.NOTPARALLEL: # prevent make clean racing the other targets +endif + SOURCE_FILES = $(abspath \ ../multi_heap.c \ ../multi_heap_poisoning.c \ From 800c2bae38c3efe07701ee39b6443eeba226c299 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 22 May 2018 09:47:16 +1000 Subject: [PATCH 154/187] gitignore: Add test_multi_heap_host --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 8448bf404e..df90fbb194 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,5 @@ examples/protocols/aws_iot/*/main/certs/*.pem.* *.gcno coverage.info coverage_report/ + +test_multi_heap_host From f2aea4f5b67029ebf2dd2dd3ddfa8d8fc65794a4 Mon Sep 17 00:00:00 2001 From: Tuan PM Date: Tue, 22 May 2018 10:55:18 +0700 Subject: [PATCH 155/187] Add http status enum & return ESP_FAIL as error code --- components/esp_http_client/esp_http_client.c | 31 ++++++++++++++----- .../esp_http_client/include/esp_http_client.h | 3 +- components/esp_http_client/lib/http_auth.c | 2 +- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c index 60d8857fad..a0aedf99b9 100644 --- a/components/esp_http_client/esp_http_client.c +++ b/components/esp_http_client/esp_http_client.c @@ -119,6 +119,8 @@ static esp_err_t _clear_connection_info(esp_http_client_handle_t client); #define DEFAULT_HTTP_PORT (80) #define DEFAULT_HTTPS_PORT (443) +#define HTTP_LENGTH_CHUNKED_ENCODING (-1) + static const char *DEFAULT_HTTP_USER_AGENT = "ESP32 HTTP Client/1.0"; static const char *DEFAULT_HTTP_PROTOCOL = "HTTP/1.1"; static const char *DEFAULT_HTTP_PATH = "/"; @@ -133,6 +135,19 @@ static const char *HTTP_METHOD_MAPPING[] = { "DELETE" }; +/** + * Enum for the HTTP status codes. + */ +enum HttpStatus_Code +{ + /* 3xx - Redirection */ + HttpStatus_MovedPermanently = 301, + HttpStatus_Found = 302, + + /* 4xx - Client Error */ + HttpStatus_Unauthorized = 401 +}; + static esp_err_t http_dispatch_event(esp_http_client_t *client, esp_http_client_event_id_t event_id, void *data, int len) { esp_http_client_event_t *event = &client->event; @@ -525,14 +540,14 @@ static esp_err_t esp_http_check_response(esp_http_client_handle_t client) return ESP_ERR_HTTP_MAX_REDIRECT; } switch (client->response->status_code) { - case 301: - case 302: + case HttpStatus_MovedPermanently: + case HttpStatus_Found: ESP_LOGI(TAG, "Redirect to %s", client->location); esp_http_client_set_url(client, client->location); client->redirect_counter ++; client->process_again = 1; break; - case 401: + case HttpStatus_Unauthorized: auth_header = client->auth_header; http_utils_trim_whitespace(&auth_header); ESP_LOGI(TAG, "UNAUTHORIZED: %s", auth_header); @@ -675,7 +690,7 @@ esp_err_t esp_http_client_set_method(esp_http_client_handle_t client, esp_http_c static int esp_http_client_get_data(esp_http_client_handle_t client) { if (client->state < HTTP_STATE_RES_COMPLETE_HEADER) { - return -1; + return ESP_FAIL; } esp_http_buffer_t *res_buffer = client->response->buffer; @@ -692,7 +707,7 @@ int esp_http_client_read(esp_http_client_handle_t client, char *buffer, int len) { esp_http_buffer_t *res_buffer = client->response->buffer; - int rlen = -1, ridx = 0; + int rlen = ESP_FAIL, ridx = 0; if (res_buffer->raw_len) { int remain_len = client->response->buffer->raw_len; if (remain_len > len) { @@ -790,7 +805,7 @@ esp_err_t esp_http_client_perform(esp_http_client_handle_t client) int esp_http_client_fetch_headers(esp_http_client_handle_t client) { if (client->state < HTTP_STATE_REQ_COMPLETE_HEADER) { - return -1; + return ESP_FAIL; } client->state = HTTP_STATE_REQ_COMPLETE_DATA; @@ -800,7 +815,7 @@ int esp_http_client_fetch_headers(esp_http_client_handle_t client) while (client->state < HTTP_STATE_RES_COMPLETE_HEADER) { buffer->len = transport_read(client->transport, buffer->data, client->buffer_size, client->timeout_ms); if (buffer->len <= 0) { - return -1; + return ESP_FAIL; } http_parser_execute(client->parser, client->parser_settings, buffer->data, buffer->len); } @@ -903,7 +918,7 @@ esp_err_t esp_http_client_open(esp_http_client_handle_t client, int write_len) int esp_http_client_write(esp_http_client_handle_t client, const char *buffer, int len) { if (client->state < HTTP_STATE_REQ_COMPLETE_HEADER) { - return -1; + return ESP_FAIL; } int need_write; int wlen = 0, widx = 0; diff --git a/components/esp_http_client/include/esp_http_client.h b/components/esp_http_client/include/esp_http_client.h index 2690cfe5d9..687cf8d3b5 100644 --- a/components/esp_http_client/include/esp_http_client.h +++ b/components/esp_http_client/include/esp_http_client.h @@ -258,7 +258,8 @@ int esp_http_client_write(esp_http_client_handle_t client, const char *buffer, i * @param[in] client The esp_http_client handle * * @return - * - (-1) if stream doesn't contain content-length header, or chunked encoding (checked by `esp_http_client_is_chunked` response) + * - (0) if stream doesn't contain content-length header, or chunked encoding (checked by `esp_http_client_is_chunked` response) + * - (-1: ESP_FAIL) if any errors * - Download data length defined by content-length header */ int esp_http_client_fetch_headers(esp_http_client_handle_t client); diff --git a/components/esp_http_client/lib/http_auth.c b/components/esp_http_client/lib/http_auth.c index 4e07ce5f3a..cd1d4ef721 100644 --- a/components/esp_http_client/lib/http_auth.c +++ b/components/esp_http_client/lib/http_auth.c @@ -51,7 +51,7 @@ static int md5_printf(char *md, const char *fmt, ...) va_start(ap, fmt); len = vasprintf((char **)&buf, fmt, ap); if (buf == NULL) { - return -1; + return ESP_FAIL; } MD5Init(&md5_ctx); From 64ce589f6f6c0013c6d2c59677913c87e3748782 Mon Sep 17 00:00:00 2001 From: Tuan PM Date: Tue, 22 May 2018 12:04:47 +0700 Subject: [PATCH 156/187] Remove unused macro --- components/esp_http_client/esp_http_client.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/esp_http_client/esp_http_client.c b/components/esp_http_client/esp_http_client.c index a0aedf99b9..6a6f799e30 100644 --- a/components/esp_http_client/esp_http_client.c +++ b/components/esp_http_client/esp_http_client.c @@ -119,8 +119,6 @@ static esp_err_t _clear_connection_info(esp_http_client_handle_t client); #define DEFAULT_HTTP_PORT (80) #define DEFAULT_HTTPS_PORT (443) -#define HTTP_LENGTH_CHUNKED_ENCODING (-1) - static const char *DEFAULT_HTTP_USER_AGENT = "ESP32 HTTP Client/1.0"; static const char *DEFAULT_HTTP_PROTOCOL = "HTTP/1.1"; static const char *DEFAULT_HTTP_PATH = "/"; From 67424816ccb339b9a6fa8ba7d81514f981c2b504 Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Sat, 19 May 2018 12:13:34 +0800 Subject: [PATCH 157/187] esp32: some changes relating to phy v3900 1. Store the calibration data to NVS if PHY does full calibration because of calibration data checksum failure 2. Pass the station's mac to PHY for checksum calculation --- components/esp32/include/esp_phy_init.h | 4 +++- components/esp32/phy.h | 4 +++- components/esp32/phy_init.c | 12 +++++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/components/esp32/include/esp_phy_init.h b/components/esp32/include/esp_phy_init.h index 75cb8fb58e..0228edf1cf 100644 --- a/components/esp32/include/esp_phy_init.h +++ b/components/esp32/include/esp_phy_init.h @@ -37,7 +37,9 @@ typedef struct { * @brief Opaque PHY calibration data */ typedef struct { - uint8_t opaque[1904]; /*!< calibration data */ + uint8_t version[4]; /*!< PHY version */ + uint8_t mac[6]; /*!< The MAC address of the station */ + uint8_t opaque[1894]; /*!< calibration data */ } esp_phy_calibration_data_t; typedef enum { diff --git a/components/esp32/phy.h b/components/esp32/phy.h index 71c44cd3d1..37066d00f9 100644 --- a/components/esp32/phy.h +++ b/components/esp32/phy.h @@ -19,6 +19,8 @@ extern "C" { #endif +#define ESP_CAL_DATA_CHECK_FAIL 1 + /** * @file phy.h * @brief Declarations for functions provided by libphy.a @@ -34,7 +36,7 @@ void phy_get_romfunc_addr(void); * @param[in] init_data Initialization parameters to be used by the PHY * @param[inout] cal_data As input, calibration data previously obtained. As output, will contain new calibration data. * @param[in] cal_mode RF calibration mode - * @return reserved for future use + * @return ESP_CAL_DATA_CHECK_FAIL if calibration data checksum fails, other values are reserved for future use */ int register_chipv7_phy(const esp_phy_init_data_t* init_data, esp_phy_calibration_data_t *cal_data, esp_phy_calibration_mode_t cal_mode); diff --git a/components/esp32/phy_init.c b/components/esp32/phy_init.c index 027e6733aa..cf1853387d 100644 --- a/components/esp32/phy_init.c +++ b/components/esp32/phy_init.c @@ -119,7 +119,16 @@ esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data, esp_phy_calibrat // Enable WiFi/BT common peripheral clock periph_module_enable(PERIPH_WIFI_BT_COMMON_MODULE); phy_set_wifi_mode_only(0); - register_chipv7_phy(init_data, calibration_data, mode); + + if (ESP_CAL_DATA_CHECK_FAIL == register_chipv7_phy(init_data, calibration_data, mode)) { + ESP_LOGW(TAG, "saving new calibration data because of checksum failure, mode(%d)", mode); +#ifdef CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE + if (mode != PHY_RF_CAL_FULL) { + esp_phy_store_cal_data_to_nvs(calibration_data); + } +#endif + } + coex_bt_high_prio(); } } @@ -476,6 +485,7 @@ static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle, ESP_LOGD(TAG, "%s: invalid length of cal_data (%d)", __func__, length); return ESP_ERR_INVALID_SIZE; } + memcpy(out_cal_data->mac, sta_mac, 6); return ESP_OK; } From 8ad8a447091462ecb35386ccc19906af6ce766c9 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Mon, 21 May 2018 12:42:43 +0530 Subject: [PATCH 158/187] docs: fix (in remaining places) link for FTDI VCP drivers Signed-off-by: Mahavir Jain --- docs/en/hw-reference/modules-and-boards-previous.rst | 2 +- docs/en/hw-reference/modules-and-boards.rst | 2 +- docs/zh_CN/get-started/establish-serial-connection.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/en/hw-reference/modules-and-boards-previous.rst b/docs/en/hw-reference/modules-and-boards-previous.rst index 41f7642502..27fefb8a64 100644 --- a/docs/en/hw-reference/modules-and-boards-previous.rst +++ b/docs/en/hw-reference/modules-and-boards-previous.rst @@ -134,4 +134,4 @@ Related Documents * :doc:`modules-and-boards` -.. _FTDI Virtual COM Port Drivers: http://www.ftdichip.com/Drivers/D2XX.htm +.. _FTDI Virtual COM Port Drivers: http://www.ftdichip.com/Drivers/VCP.htm diff --git a/docs/en/hw-reference/modules-and-boards.rst b/docs/en/hw-reference/modules-and-boards.rst index c1d8cd08d1..0ab45789ac 100644 --- a/docs/en/hw-reference/modules-and-boards.rst +++ b/docs/en/hw-reference/modules-and-boards.rst @@ -206,4 +206,4 @@ Related Documents * :doc:`modules-and-boards-previous` -.. _FTDI Virtual COM Port Drivers: http://www.ftdichip.com/Drivers/D2XX.htm +.. _FTDI Virtual COM Port Drivers: http://www.ftdichip.com/Drivers/VCP.htm diff --git a/docs/zh_CN/get-started/establish-serial-connection.rst b/docs/zh_CN/get-started/establish-serial-connection.rst index f934dba3d8..e9d8d3c4ec 100644 --- a/docs/zh_CN/get-started/establish-serial-connection.rst +++ b/docs/zh_CN/get-started/establish-serial-connection.rst @@ -13,7 +13,7 @@ * ESP32-PICO-KIT 和 ESP32-DevKitC - `CP210x USB to UART Bridge VCP Drivers `_ -* ESP32-WROVER-KIT 和 ESP32 Demo Board - `FTDI Virtual COM Port Drivers `_ +* ESP32-WROVER-KIT 和 ESP32 Demo Board - `FTDI Virtual COM Port Drivers `_ 以上驱动仅用于参考。当您将上述 ESP32 开发板与 PC 连接时,对应驱动程序应该已经被打包在操作系统中并自动安装。 From 97a4332ed9ab8ad3bfc1c259955fc75f20aa969c Mon Sep 17 00:00:00 2001 From: zhiweijian Date: Sat, 27 Jan 2018 17:18:21 +0800 Subject: [PATCH 159/187] Component/bt: add bt_ble_coex demo --- examples/bluetooth/a2dp_gatts_coex/README.md | 7 + .../a2dp_gatts_coex/main/Kconfig.projbuild | 43 ++ .../a2dp_gatts_coex/main/bt_app_av.c | 199 +++++ .../a2dp_gatts_coex/main/bt_app_av.h | 33 + .../a2dp_gatts_coex/main/bt_app_core.c | 112 +++ .../a2dp_gatts_coex/main/bt_app_core.h | 47 ++ .../a2dp_gatts_coex/main/component.mk | 5 + .../bluetooth/a2dp_gatts_coex/main/main.c | 706 ++++++++++++++++++ .../a2dp_gatts_coex/sdkconfig.defaults | 30 + 9 files changed, 1182 insertions(+) create mode 100755 examples/bluetooth/a2dp_gatts_coex/README.md create mode 100644 examples/bluetooth/a2dp_gatts_coex/main/Kconfig.projbuild create mode 100644 examples/bluetooth/a2dp_gatts_coex/main/bt_app_av.c create mode 100644 examples/bluetooth/a2dp_gatts_coex/main/bt_app_av.h create mode 100644 examples/bluetooth/a2dp_gatts_coex/main/bt_app_core.c create mode 100644 examples/bluetooth/a2dp_gatts_coex/main/bt_app_core.h create mode 100755 examples/bluetooth/a2dp_gatts_coex/main/component.mk create mode 100644 examples/bluetooth/a2dp_gatts_coex/main/main.c create mode 100644 examples/bluetooth/a2dp_gatts_coex/sdkconfig.defaults diff --git a/examples/bluetooth/a2dp_gatts_coex/README.md b/examples/bluetooth/a2dp_gatts_coex/README.md new file mode 100755 index 0000000000..c36b22737d --- /dev/null +++ b/examples/bluetooth/a2dp_gatts_coex/README.md @@ -0,0 +1,7 @@ +ESP-IDF A2DP-GATTS_COEX demo +====================== +This demo showcases APIs to create a GATT service and A2DP profile and demonstrates BLE and classic Bluetooth coexistence. + +The BLE GATT SERVER part of demo creates a GATT service and then starts advertising, waiting to be connected by a GATT client. After the program is started, the GATT client can discover a device named "ESP_COEX_BLE_DEMO". Once a connection is established, GATT client can read or write data to the device. Or GATT client can receive notification or indication data. + +The classic bluetooth A2DP part of the demo implements Advanced Audio Distribution Profile to receive an audio stream. After the program is started, other bluetooth devices such as smart phones can discover a device named "ESP_COEX_A2DP_DEMO". Once a connection is established, audio data can be transmitted. This will be visible in the application log including a count of audio data packets. \ No newline at end of file diff --git a/examples/bluetooth/a2dp_gatts_coex/main/Kconfig.projbuild b/examples/bluetooth/a2dp_gatts_coex/main/Kconfig.projbuild new file mode 100644 index 0000000000..c984308d24 --- /dev/null +++ b/examples/bluetooth/a2dp_gatts_coex/main/Kconfig.projbuild @@ -0,0 +1,43 @@ +menu "A2DP Example Configuration" + +choice A2DP_SINK_OUTPUT + prompt "A2DP Sink Output" + default A2DP_SINK_OUTPUT_EXTERNAL_I2S + help + Select to use Internal DAC or external I2S driver + +config A2DP_SINK_OUTPUT_INTERNAL_DAC + bool "Internal DAC" + help + Select this to use Internal DAC sink output + +config A2DP_SINK_OUTPUT_EXTERNAL_I2S + bool "External I2S Codec" + help + Select this to use External I2S sink output + +endchoice + +config I2S_LRCK_PIN + int "I2S LRCK (WS) GPIO" + default 22 + depends on A2DP_SINK_OUTPUT_EXTERNAL_I2S + help + GPIO number to use for I2S LRCK(WS) Driver. + +config I2S_BCK_PIN + int "I2S BCK GPIO" + default 26 + depends on A2DP_SINK_OUTPUT_EXTERNAL_I2S + help + GPIO number to use for I2S BCK Driver. + +config I2S_DATA_PIN + int "I2S DATA GPIO" + default 25 + depends on A2DP_SINK_OUTPUT_EXTERNAL_I2S + help + GPIO number to use for I2S Data Driver. + + +endmenu diff --git a/examples/bluetooth/a2dp_gatts_coex/main/bt_app_av.c b/examples/bluetooth/a2dp_gatts_coex/main/bt_app_av.c new file mode 100644 index 0000000000..0b966ccda7 --- /dev/null +++ b/examples/bluetooth/a2dp_gatts_coex/main/bt_app_av.c @@ -0,0 +1,199 @@ + +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include +#include +#include "esp_log.h" + +#include "bt_app_core.h" +#include "bt_app_av.h" +#include "esp_bt_main.h" +#include "esp_bt_device.h" +#include "esp_gap_bt_api.h" +#include "esp_a2dp_api.h" +#include "esp_avrc_api.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "driver/i2s.h" + +/* a2dp event handler */ +static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param); +/* avrc event handler */ +static void bt_av_hdl_avrc_evt(uint16_t event, void *p_param); + +static uint32_t m_pkt_cnt = 0; +static esp_a2d_audio_state_t m_audio_state = ESP_A2D_AUDIO_STATE_STOPPED; +static const char *m_a2d_conn_state_str[] = {"Disconnected", "Connecting", "Connected", "Disconnecting"}; +static const char *m_a2d_audio_state_str[] = {"Suspended", "Stopped", "Started"}; + +/* callback for A2DP sink */ +void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param) +{ + switch (event) { + case ESP_A2D_CONNECTION_STATE_EVT: + case ESP_A2D_AUDIO_STATE_EVT: + case ESP_A2D_AUDIO_CFG_EVT: { + bt_app_work_dispatch(bt_av_hdl_a2d_evt, event, param, sizeof(esp_a2d_cb_param_t), NULL); + break; + } + default: + ESP_LOGE(BT_AV_TAG, "Invalid A2DP event: %d", event); + break; + } +} + +void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len) +{ + i2s_write_bytes(0, (const char *)data, len, portMAX_DELAY); + if (++m_pkt_cnt % 100 == 0) { + ESP_LOGI(BT_AV_TAG, "Audio packet count %u", m_pkt_cnt); + } +} + +void bt_app_alloc_meta_buffer(esp_avrc_ct_cb_param_t *param) +{ + esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(param); + uint8_t *attr_text = (uint8_t *) malloc (rc->meta_rsp.attr_length + 1); + if(!attr_text) { + ESP_LOGI(BT_AV_TAG, "malloc failed "); + return; + } + memcpy(attr_text, rc->meta_rsp.attr_text, rc->meta_rsp.attr_length); + attr_text[rc->meta_rsp.attr_length] = 0; + + rc->meta_rsp.attr_text = attr_text; +} + +void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param) +{ + switch (event) { + case ESP_AVRC_CT_METADATA_RSP_EVT: + bt_app_alloc_meta_buffer(param); + case ESP_AVRC_CT_CONNECTION_STATE_EVT: + case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: + case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: + case ESP_AVRC_CT_REMOTE_FEATURES_EVT: { + bt_app_work_dispatch(bt_av_hdl_avrc_evt, event, param, sizeof(esp_avrc_ct_cb_param_t), NULL); + break; + } + default: + ESP_LOGE(BT_AV_TAG, "Invalid AVRC event: %d", event); + break; + } +} + +static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param) +{ + ESP_LOGD(BT_AV_TAG, "%s evt %d", __func__, event); + esp_a2d_cb_param_t *a2d = NULL; + switch (event) { + case ESP_A2D_CONNECTION_STATE_EVT: { + a2d = (esp_a2d_cb_param_t *)(p_param); + uint8_t *bda = a2d->conn_stat.remote_bda; + ESP_LOGI(BT_AV_TAG, "A2DP connection state: %s, [%02x:%02x:%02x:%02x:%02x:%02x]", + m_a2d_conn_state_str[a2d->conn_stat.state], bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + break; + } + case ESP_A2D_AUDIO_STATE_EVT: { + a2d = (esp_a2d_cb_param_t *)(p_param); + ESP_LOGI(BT_AV_TAG, "A2DP audio state: %s", m_a2d_audio_state_str[a2d->audio_stat.state]); + m_audio_state = a2d->audio_stat.state; + if (ESP_A2D_AUDIO_STATE_STARTED == a2d->audio_stat.state) { + m_pkt_cnt = 0; + } + break; + } + case ESP_A2D_AUDIO_CFG_EVT: { + a2d = (esp_a2d_cb_param_t *)(p_param); + ESP_LOGI(BT_AV_TAG, "A2DP audio stream configuration, codec type %d", a2d->audio_cfg.mcc.type); + // for now only SBC stream is supported + if (a2d->audio_cfg.mcc.type == ESP_A2D_MCT_SBC) { + int sample_rate = 16000; + char oct0 = a2d->audio_cfg.mcc.cie.sbc[0]; + if (oct0 & (0x01 << 6)) { + sample_rate = 32000; + } else if (oct0 & (0x01 << 5)) { + sample_rate = 44100; + } else if (oct0 & (0x01 << 4)) { + sample_rate = 48000; + } + i2s_set_clk(0, sample_rate, 16, 2); + + ESP_LOGI(BT_AV_TAG, "Configure audio player 0x%x-0x%x-0x%x-0x%x", + a2d->audio_cfg.mcc.cie.sbc[0], + a2d->audio_cfg.mcc.cie.sbc[1], + a2d->audio_cfg.mcc.cie.sbc[2], + a2d->audio_cfg.mcc.cie.sbc[3]); + ESP_LOGI(BT_AV_TAG, "Audio player configured, sample rate=%d", sample_rate); + } + break; + } + default: + ESP_LOGE(BT_AV_TAG, "%s unhandled evt %d", __func__, event); + break; + } +} + +static void bt_av_new_track() +{ + //Register notifications and request metadata + esp_avrc_ct_send_metadata_cmd(0, ESP_AVRC_MD_ATTR_TITLE | ESP_AVRC_MD_ATTR_ARTIST | ESP_AVRC_MD_ATTR_ALBUM | ESP_AVRC_MD_ATTR_GENRE); + esp_avrc_ct_send_register_notification_cmd(1, ESP_AVRC_RN_TRACK_CHANGE, 0); +} + +void bt_av_notify_evt_handler(uint8_t event_id, uint32_t event_parameter) +{ + switch (event_id) { + case ESP_AVRC_RN_TRACK_CHANGE: + bt_av_new_track(); + break; + } +} + +static void bt_av_hdl_avrc_evt(uint16_t event, void *p_param) +{ + ESP_LOGD(BT_AV_TAG, "%s evt %d", __func__, event); + esp_avrc_ct_cb_param_t *rc = (esp_avrc_ct_cb_param_t *)(p_param); + switch (event) { + case ESP_AVRC_CT_CONNECTION_STATE_EVT: { + uint8_t *bda = rc->conn_stat.remote_bda; + ESP_LOGI(BT_AV_TAG, "AVRC conn_state evt: state %d, [%02x:%02x:%02x:%02x:%02x:%02x]", + rc->conn_stat.connected, bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]); + + if (rc->conn_stat.connected) { + bt_av_new_track(); + } + break; + } + case ESP_AVRC_CT_PASSTHROUGH_RSP_EVT: { + ESP_LOGI(BT_AV_TAG, "AVRC passthrough rsp: key_code 0x%x, key_state %d", rc->psth_rsp.key_code, rc->psth_rsp.key_state); + break; + } + case ESP_AVRC_CT_METADATA_RSP_EVT: { + ESP_LOGI(BT_AV_TAG, "AVRC metadata rsp: attribute id 0x%x, %s", rc->meta_rsp.attr_id, rc->meta_rsp.attr_text); + free(rc->meta_rsp.attr_text); + break; + } + case ESP_AVRC_CT_CHANGE_NOTIFY_EVT: { + ESP_LOGI(BT_AV_TAG, "AVRC event notification: %d, param: %d", rc->change_ntf.event_id, rc->change_ntf.event_parameter); + bt_av_notify_evt_handler(rc->change_ntf.event_id, rc->change_ntf.event_parameter); + break; + } + case ESP_AVRC_CT_REMOTE_FEATURES_EVT: { + ESP_LOGI(BT_AV_TAG, "AVRC remote features 0x%x", rc->rmt_feats.feat_mask); + break; + } + default: + ESP_LOGE(BT_AV_TAG, "%s unhandled evt %d", __func__, event); + break; + } +} diff --git a/examples/bluetooth/a2dp_gatts_coex/main/bt_app_av.h b/examples/bluetooth/a2dp_gatts_coex/main/bt_app_av.h new file mode 100644 index 0000000000..6648eb95e9 --- /dev/null +++ b/examples/bluetooth/a2dp_gatts_coex/main/bt_app_av.h @@ -0,0 +1,33 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#ifndef __BT_APP_AV_H__ +#define __BT_APP_AV_H__ + +#include +#include "esp_a2dp_api.h" +#include "esp_avrc_api.h" + +#define BT_AV_TAG "BT_AV" + +/** + * @brief callback function for A2DP sink + */ +void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param); + +/** + * @brief callback function for A2DP sink audio data stream + */ +void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len); + +/** + * @brief callback function for AVRCP controller + */ +void bt_app_rc_ct_cb(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param); + +#endif /* __BT_APP_AV_H__*/ diff --git a/examples/bluetooth/a2dp_gatts_coex/main/bt_app_core.c b/examples/bluetooth/a2dp_gatts_coex/main/bt_app_core.c new file mode 100644 index 0000000000..644c5c11f7 --- /dev/null +++ b/examples/bluetooth/a2dp_gatts_coex/main/bt_app_core.c @@ -0,0 +1,112 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include +#include "freertos/xtensa_api.h" +#include "freertos/FreeRTOSConfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "bt_app_core.h" + +static void bt_app_task_handler(void *arg); +static bool bt_app_send_msg(bt_app_msg_t *msg); +static void bt_app_work_dispatched(bt_app_msg_t *msg); + +static xQueueHandle bt_app_task_queue = NULL; +static xTaskHandle bt_app_task_handle = NULL; + +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback) +{ + ESP_LOGD(BT_APP_CORE_TAG, "%s event 0x%x, param len %d", __func__, event, param_len); + + bt_app_msg_t msg = { }; + + msg.sig = BT_APP_SIG_WORK_DISPATCH; + msg.event = event; + msg.cb = p_cback; + + if (param_len == 0) { + return bt_app_send_msg(&msg); + } else if (p_params && param_len > 0) { + if ((msg.param = malloc(param_len)) != NULL) { + memcpy(msg.param, p_params, param_len); + /* check if caller has provided a copy callback to do the deep copy */ + if (p_copy_cback) { + p_copy_cback(&msg, msg.param, p_params); + } + return bt_app_send_msg(&msg); + } + } + + return false; +} + +static bool bt_app_send_msg(bt_app_msg_t *msg) +{ + if (msg == NULL) { + return false; + } + + if (xQueueSend(bt_app_task_queue, msg, 10 / portTICK_RATE_MS) != pdTRUE) { + ESP_LOGE(BT_APP_CORE_TAG, "%s xQueue send failed", __func__); + return false; + } + return true; +} + +static void bt_app_work_dispatched(bt_app_msg_t *msg) +{ + if (msg->cb) { + msg->cb(msg->event, msg->param); + } +} + +static void bt_app_task_handler(void *arg) +{ + bt_app_msg_t msg; + for (;;) { + if (pdTRUE == xQueueReceive(bt_app_task_queue, &msg, (portTickType)portMAX_DELAY)) { + ESP_LOGD(BT_APP_CORE_TAG, "%s, sig 0x%x, 0x%x", __func__, msg.sig, msg.event); + switch (msg.sig) { + case BT_APP_SIG_WORK_DISPATCH: + bt_app_work_dispatched(&msg); + break; + default: + ESP_LOGW(BT_APP_CORE_TAG, "%s, unhandled sig: 0x%x", __func__, msg.sig); + break; + } // switch (msg.sig) + + if (msg.param) { + free(msg.param); + } + } + } +} + +void bt_app_task_start_up(void) +{ + bt_app_task_queue = xQueueCreate(10, sizeof(bt_app_msg_t)); + xTaskCreate(bt_app_task_handler, "BtAppT", 2048, NULL, configMAX_PRIORITIES - 3, bt_app_task_handle); + return; +} + +void bt_app_task_shut_down(void) +{ + if (bt_app_task_handle) { + vTaskDelete(bt_app_task_handle); + bt_app_task_handle = NULL; + } + if (bt_app_task_queue) { + vQueueDelete(bt_app_task_queue); + bt_app_task_queue = NULL; + } +} diff --git a/examples/bluetooth/a2dp_gatts_coex/main/bt_app_core.h b/examples/bluetooth/a2dp_gatts_coex/main/bt_app_core.h new file mode 100644 index 0000000000..4415058a71 --- /dev/null +++ b/examples/bluetooth/a2dp_gatts_coex/main/bt_app_core.h @@ -0,0 +1,47 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#ifndef __BT_APP_CORE_H__ +#define __BT_APP_CORE_H__ + +#include +#include +#include + +#define BT_APP_CORE_TAG "BT_APP_CORE" + +#define BT_APP_SIG_WORK_DISPATCH (0x01) + +/** + * @brief handler for the dispatched work + */ +typedef void (* bt_app_cb_t) (uint16_t event, void *param); + +/* message to be sent */ +typedef struct { + uint16_t sig; /*!< signal to bt_app_task */ + uint16_t event; /*!< message event id */ + bt_app_cb_t cb; /*!< context switch callback */ + void *param; /*!< parameter area needs to be last */ +} bt_app_msg_t; + +/** + * @brief parameter deep-copy function to be customized + */ +typedef void (* bt_app_copy_cb_t) (bt_app_msg_t *msg, void *p_dest, void *p_src); + +/** + * @brief work dispatcher for the application task + */ +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback); + +void bt_app_task_start_up(void); + +void bt_app_task_shut_down(void); + +#endif /* __BT_APP_CORE_H__ */ diff --git a/examples/bluetooth/a2dp_gatts_coex/main/component.mk b/examples/bluetooth/a2dp_gatts_coex/main/component.mk new file mode 100755 index 0000000000..0b9d7585e7 --- /dev/null +++ b/examples/bluetooth/a2dp_gatts_coex/main/component.mk @@ -0,0 +1,5 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + diff --git a/examples/bluetooth/a2dp_gatts_coex/main/main.c b/examples/bluetooth/a2dp_gatts_coex/main/main.c new file mode 100644 index 0000000000..b57e4249c2 --- /dev/null +++ b/examples/bluetooth/a2dp_gatts_coex/main/main.c @@ -0,0 +1,706 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +/**************************************************************************** +* The demo shows BLE and classic Bluetooth coexistence. You can use BLE gatt server and classic bluetooth A2DP together. + +* The BLE GATT SERVER part of demo creates GATT a service and then starts advertising, waiting to be connected by a GATT client. +* After the program is started, the GATT client can discover a device named "ESP_COEX_BLE_DEMO". Once a connection is established, +* GATT client can reaad or write data to the device. Or GATT client receive notification or indication data. +* Attention: IF you test the demo with iphone, BLE gatt server adv name will change to "ESP_COEX_A2DP_DEMO" afte you connect it. + +* The classic bluetooth A2DP part of the demo of API implementing Advanced Audio Distribution Profile to receive an audio stream. +* After the program is started, other bluetooth devices such as smart phones can discover a device named "ESP_COEX_A2DP_DEMO". +* Once a connection is established, audio data can be transmitted. This will be visible in the application log including a count +* of audio data packets. +****************************************************************************/ + + +#include +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "nvs.h" +#include "nvs_flash.h" +#include "esp_system.h" +#include "esp_log.h" + +#include "esp_bt.h" +#include "bt_app_core.h" +#include "bt_app_av.h" +#include "esp_bt_main.h" +#include "esp_bt_device.h" +#include "esp_gap_bt_api.h" +#include "esp_a2dp_api.h" +#include "esp_avrc_api.h" +#include "driver/i2s.h" + +#include "esp_gap_ble_api.h" +#include "esp_gatts_api.h" +#include "esp_bt_defs.h" +#include "esp_gatt_common_api.h" + +#define BT_BLE_COEX_TAG "BT_BLE_COEX" +#define BT_DEVICE_NAME "ESP_COEX_A2DP_DEMO" +#define BLE_ADV_NAME "ESP_COEX_BLE_DEMO" + +#define GATTS_SERVICE_UUID_A 0x00FF +#define GATTS_CHAR_UUID_A 0xFF01 +#define GATTS_DESCR_UUID_A 0x3333 +#define GATTS_NUM_HANDLE_A 4 + +#define GATTS_SERVICE_UUID_B 0x00EE +#define GATTS_CHAR_UUID_B 0xEE01 +#define GATTS_DESCR_UUID_B 0x2222 +#define GATTS_NUM_HANDLE_B 4 + +#define GATTS_DEMO_CHAR_VAL_LEN_MAX 0x40 +#define PREPARE_BUF_MAX_SIZE 1024 +#define PROFILE_NUM 2 +#define PROFILE_A_APP_ID 0 +#define PROFILE_B_APP_ID 1 + +typedef struct { + uint8_t *prepare_buf; + int prepare_len; +} prepare_type_env_t; + +static prepare_type_env_t a_prepare_write_env; +static prepare_type_env_t b_prepare_write_env; + +//Declare the static function +static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); +static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); +void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param); +void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param); + +/* event for handler "bt_av_hdl_stack_up */ +enum { + BT_APP_EVT_STACK_UP = 0, +}; +static uint8_t ble_char_value_str[] = {0x11, 0x22, 0x33}; +esp_gatt_char_prop_t a_property = 0; +esp_gatt_char_prop_t b_property = 0; + +esp_attr_value_t gatts_initial_char_val = { + .attr_max_len = GATTS_DEMO_CHAR_VAL_LEN_MAX, + .attr_len = sizeof(ble_char_value_str), + .attr_value = ble_char_value_str, +}; + +static esp_ble_adv_params_t adv_params = { + .adv_int_min = 0x060, + .adv_int_max = 0x060, + .adv_type = ADV_TYPE_IND, + .own_addr_type = BLE_ADDR_TYPE_RANDOM, + .channel_map = ADV_CHNL_ALL, + .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, +}; + +struct gatts_profile_inst { + esp_gatts_cb_t gatts_cb; + uint16_t gatts_if; + uint16_t app_id; + uint16_t conn_id; + uint16_t service_handle; + esp_gatt_srvc_id_t service_id; + uint16_t char_handle; + esp_bt_uuid_t char_uuid; + esp_gatt_perm_t perm; + esp_gatt_char_prop_t property; + uint16_t descr_handle; + esp_bt_uuid_t descr_uuid; +}; + +/* One gatt-based profile one app_id and one gatts_if, this array will store the gatts_if returned by ESP_GATTS_REG_EVT */ +static struct gatts_profile_inst gl_profile_tab[PROFILE_NUM] = { + [PROFILE_A_APP_ID] = { + .gatts_cb = gatts_profile_a_event_handler, + .gatts_if = ESP_GATT_IF_NONE, /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */ + }, + [PROFILE_B_APP_ID] = { + .gatts_cb = gatts_profile_b_event_handler,/* This demo does not implement, similar as profile A */ + .gatts_if = ESP_GATT_IF_NONE, /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */ + }, +}; +static void ble_init_adv_data(const char *name) +{ + int len = strlen(name); + uint8_t raw_adv_data[len+5]; + //flag + raw_adv_data[0] = 2; + raw_adv_data[1] = ESP_BT_EIR_TYPE_FLAGS; + raw_adv_data[2] = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT); + //adv name + raw_adv_data[3] = len + 1; + raw_adv_data[4] = ESP_BLE_AD_TYPE_NAME_CMPL; + for (int i = 0;i < len;i++) + { + raw_adv_data[i+5] = *(name++); + } + //The length of adv data must be less than 31 bytes + esp_err_t raw_adv_ret = esp_ble_gap_config_adv_data_raw(raw_adv_data, sizeof(raw_adv_data)); + if (raw_adv_ret){ + ESP_LOGE(BT_BLE_COEX_TAG, "config raw adv data failed, error code = 0x%x ", raw_adv_ret); + } + esp_err_t raw_scan_ret = esp_ble_gap_config_scan_rsp_data_raw(raw_adv_data, sizeof(raw_adv_data)); + if (raw_scan_ret){ + ESP_LOGE(BT_BLE_COEX_TAG, "config raw scan rsp data failed, error code = 0x%x", raw_scan_ret); + } +} + +static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) +{ + switch (event) { + case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: + //esp_ble_gap_start_advertising(&adv_params); + break; + case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT: + esp_ble_gap_start_advertising(&adv_params); + break; + case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: + //advertising start complete event to indicate advertising start successfully or failed + if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(BT_BLE_COEX_TAG, "Advertising start failed\n"); + }else { + ESP_LOGI(BT_BLE_COEX_TAG, "Start adv successfully\n"); + } + break; + case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: + if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(BT_BLE_COEX_TAG, "Advertising stop failed\n"); + } + else { + ESP_LOGI(BT_BLE_COEX_TAG, "Stop adv successfully\n"); + } + break; + case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT: + ESP_LOGI(BT_BLE_COEX_TAG, "update connetion params status = %d, min_int = %d, max_int = %d,conn_int = %d,latency = %d, timeout = %d", + param->update_conn_params.status, + param->update_conn_params.min_int, + param->update_conn_params.max_int, + param->update_conn_params.conn_int, + param->update_conn_params.latency, + param->update_conn_params.timeout); + break; + default: + break; + } +} + +void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param){ + esp_gatt_status_t status = ESP_GATT_OK; + if (param->write.need_rsp){ + if (param->write.is_prep){ + if (prepare_write_env->prepare_buf == NULL) { + prepare_write_env->prepare_buf = (uint8_t *)malloc(PREPARE_BUF_MAX_SIZE*sizeof(uint8_t)); + prepare_write_env->prepare_len = 0; + if (prepare_write_env->prepare_buf == NULL) { + ESP_LOGE(BT_BLE_COEX_TAG, "Gatt_server prep no mem\n"); + status = ESP_GATT_NO_RESOURCES; + } + } else { + if(param->write.offset > PREPARE_BUF_MAX_SIZE) { + status = ESP_GATT_INVALID_OFFSET; + } else if ((param->write.offset + param->write.len) > PREPARE_BUF_MAX_SIZE) { + status = ESP_GATT_INVALID_ATTR_LEN; + } + } + + esp_gatt_rsp_t *gatt_rsp = (esp_gatt_rsp_t *)malloc(sizeof(esp_gatt_rsp_t)); + gatt_rsp->attr_value.len = param->write.len; + gatt_rsp->attr_value.handle = param->write.handle; + gatt_rsp->attr_value.offset = param->write.offset; + gatt_rsp->attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE; + memcpy(gatt_rsp->attr_value.value, param->write.value, param->write.len); + esp_err_t response_err = esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, gatt_rsp); + if (response_err != ESP_OK){ + ESP_LOGE(BT_BLE_COEX_TAG, "Send response error\n"); + } + free(gatt_rsp); + if (status != ESP_GATT_OK){ + return; + } + memcpy(prepare_write_env->prepare_buf + param->write.offset, + param->write.value, + param->write.len); + prepare_write_env->prepare_len += param->write.len; + + }else{ + esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, NULL); + } + } +} + +void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param){ + if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC){ + esp_log_buffer_hex(BT_BLE_COEX_TAG, prepare_write_env->prepare_buf, prepare_write_env->prepare_len); + }else{ + ESP_LOGI(BT_BLE_COEX_TAG,"ESP_GATT_PREP_WRITE_CANCEL"); + } + if (prepare_write_env->prepare_buf) { + free(prepare_write_env->prepare_buf); + prepare_write_env->prepare_buf = NULL; + } + prepare_write_env->prepare_len = 0; +} + +static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) { + switch (event) { + case ESP_GATTS_REG_EVT: + ESP_LOGI(BT_BLE_COEX_TAG, "REGISTER_APP_EVT, status %d, app_id %d\n", param->reg.status, param->reg.app_id); + esp_ble_gap_config_local_privacy(true); + gl_profile_tab[PROFILE_A_APP_ID].service_id.is_primary = true; + gl_profile_tab[PROFILE_A_APP_ID].service_id.id.inst_id = 0x00; + gl_profile_tab[PROFILE_A_APP_ID].service_id.id.uuid.len = ESP_UUID_LEN_16; + gl_profile_tab[PROFILE_A_APP_ID].service_id.id.uuid.uuid.uuid16 = GATTS_SERVICE_UUID_A; + //init BLE adv data and scan response data + ble_init_adv_data(BLE_ADV_NAME); + esp_ble_gatts_create_service(gatts_if, &gl_profile_tab[PROFILE_A_APP_ID].service_id, GATTS_NUM_HANDLE_A); + break; + case ESP_GATTS_READ_EVT: { + ESP_LOGI(BT_BLE_COEX_TAG, "GATT_READ_EVT, conn_id %d, trans_id %d, handle %d\n", param->read.conn_id, param->read.trans_id, param->read.handle); + esp_gatt_rsp_t rsp; + memset(&rsp, 0, sizeof(esp_gatt_rsp_t)); + rsp.attr_value.handle = param->read.handle; + rsp.attr_value.len = 4; + rsp.attr_value.value[0] = 0xde; + rsp.attr_value.value[1] = 0xed; + rsp.attr_value.value[2] = 0xbe; + rsp.attr_value.value[3] = 0xef; + esp_ble_gatts_send_response(gatts_if, param->read.conn_id, param->read.trans_id, + ESP_GATT_OK, &rsp); + break; + } + case ESP_GATTS_WRITE_EVT: { + ESP_LOGI(BT_BLE_COEX_TAG, "GATT_WRITE_EVT, conn_id %d, trans_id %d, handle %d", param->write.conn_id, param->write.trans_id, param->write.handle); + if (!param->write.is_prep){ + ESP_LOGI(BT_BLE_COEX_TAG, "GATT_WRITE_EVT, value len %d, value :", param->write.len); + esp_log_buffer_hex(BT_BLE_COEX_TAG, param->write.value, param->write.len); + if (gl_profile_tab[PROFILE_A_APP_ID].descr_handle == param->write.handle && param->write.len == 2){ + uint16_t descr_value = param->write.value[1]<<8 | param->write.value[0]; + if (descr_value == 0x0001){ + if (a_property & ESP_GATT_CHAR_PROP_BIT_NOTIFY){ + ESP_LOGI(BT_BLE_COEX_TAG, "notify enable"); + uint8_t notify_data[15]; + for (int i = 0; i < sizeof(notify_data); ++i) + { + notify_data[i] = i%0xff; + } + //the size of notify_data[] need less than MTU size + esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gl_profile_tab[PROFILE_A_APP_ID].char_handle, + sizeof(notify_data), notify_data, false); + } + }else if (descr_value == 0x0002){ + if (a_property & ESP_GATT_CHAR_PROP_BIT_INDICATE){ + ESP_LOGI(BT_BLE_COEX_TAG, "indicate enable"); + uint8_t indicate_data[15]; + for (int i = 0; i < sizeof(indicate_data); ++i) + { + indicate_data[i] = i%0xff; + } + //the size of indicate_data[] need less than MTU size + esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gl_profile_tab[PROFILE_A_APP_ID].char_handle, + sizeof(indicate_data), indicate_data, true); + } + } + else if (descr_value == 0x0000){ + ESP_LOGI(BT_BLE_COEX_TAG, "notify/indicate disable "); + }else{ + ESP_LOGE(BT_BLE_COEX_TAG, "unknown descr value"); + esp_log_buffer_hex(BT_BLE_COEX_TAG, param->write.value, param->write.len); + } + + } + } + example_write_event_env(gatts_if, &a_prepare_write_env, param); + break; + } + case ESP_GATTS_EXEC_WRITE_EVT: + ESP_LOGI(BT_BLE_COEX_TAG,"ESP_GATTS_EXEC_WRITE_EVT"); + esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL); + example_exec_write_event_env(&a_prepare_write_env, param); + break; + case ESP_GATTS_MTU_EVT: + ESP_LOGI(BT_BLE_COEX_TAG, "ESP_GATTS_MTU_EVT, MTU %d", param->mtu.mtu); + break; + case ESP_GATTS_UNREG_EVT: + break; + case ESP_GATTS_CREATE_EVT: + ESP_LOGI(BT_BLE_COEX_TAG, "CREATE_SERVICE_EVT, status %d, service_handle %d\n", param->create.status, param->create.service_handle); + gl_profile_tab[PROFILE_A_APP_ID].service_handle = param->create.service_handle; + gl_profile_tab[PROFILE_A_APP_ID].char_uuid.len = ESP_UUID_LEN_16; + gl_profile_tab[PROFILE_A_APP_ID].char_uuid.uuid.uuid16 = GATTS_CHAR_UUID_A; + + esp_ble_gatts_start_service(gl_profile_tab[PROFILE_A_APP_ID].service_handle); + a_property = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY; + esp_err_t add_char_ret = esp_ble_gatts_add_char(gl_profile_tab[PROFILE_A_APP_ID].service_handle, &gl_profile_tab[PROFILE_A_APP_ID].char_uuid, + ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, + a_property, + &gatts_initial_char_val, NULL); + if (add_char_ret){ + ESP_LOGE(BT_BLE_COEX_TAG, "add char failed, error code = 0x%x",add_char_ret); + } + break; + case ESP_GATTS_ADD_INCL_SRVC_EVT: + break; + case ESP_GATTS_ADD_CHAR_EVT: { + ESP_LOGI(BT_BLE_COEX_TAG, "ADD_CHAR_EVT, status %d, attr_handle %d, service_handle %d\n", + param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle); + gl_profile_tab[PROFILE_A_APP_ID].char_handle = param->add_char.attr_handle; + gl_profile_tab[PROFILE_A_APP_ID].descr_uuid.len = ESP_UUID_LEN_16; + gl_profile_tab[PROFILE_A_APP_ID].descr_uuid.uuid.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG; + esp_err_t add_descr_ret = esp_ble_gatts_add_char_descr(gl_profile_tab[PROFILE_A_APP_ID].service_handle, &gl_profile_tab[PROFILE_A_APP_ID].descr_uuid, + ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, NULL, NULL); + if (add_descr_ret){ + ESP_LOGE(BT_BLE_COEX_TAG, "add char descr failed, error code = 0x%x", add_descr_ret); + } + break; + } + case ESP_GATTS_ADD_CHAR_DESCR_EVT: + gl_profile_tab[PROFILE_A_APP_ID].descr_handle = param->add_char_descr.attr_handle; + ESP_LOGI(BT_BLE_COEX_TAG, "ADD_DESCR_EVT, status %d, attr_handle %d, service_handle %d\n", + param->add_char_descr.status, param->add_char_descr.attr_handle, param->add_char_descr.service_handle); + break; + case ESP_GATTS_DELETE_EVT: + break; + case ESP_GATTS_START_EVT: + ESP_LOGI(BT_BLE_COEX_TAG, "SERVICE_START_EVT, status %d, service_handle %d\n", + param->start.status, param->start.service_handle); + break; + case ESP_GATTS_STOP_EVT: + break; + case ESP_GATTS_CONNECT_EVT: { + esp_ble_conn_update_params_t conn_params = {0}; + memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t)); + break; + } + case ESP_GATTS_DISCONNECT_EVT: + ESP_LOGI(BT_BLE_COEX_TAG, "ESP_GATTS_DISCONNECT_EVT"); + esp_ble_gap_start_advertising(&adv_params); + break; + case ESP_GATTS_CONF_EVT: + ESP_LOGI(BT_BLE_COEX_TAG, "ESP_GATTS_CONF_EVT, status %d", param->conf.status); + if (param->conf.status != ESP_GATT_OK){ + esp_log_buffer_hex(BT_BLE_COEX_TAG, param->conf.value, param->conf.len); + } + break; + case ESP_GATTS_OPEN_EVT: + case ESP_GATTS_CANCEL_OPEN_EVT: + case ESP_GATTS_CLOSE_EVT: + case ESP_GATTS_LISTEN_EVT: + case ESP_GATTS_CONGEST_EVT: + default: + break; + } +} + +static void gatts_profile_b_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) { + switch (event) { + case ESP_GATTS_REG_EVT: + ESP_LOGI(BT_BLE_COEX_TAG, "REGISTER_APP_EVT, status %d, app_id %d\n", param->reg.status, param->reg.app_id); + gl_profile_tab[PROFILE_B_APP_ID].service_id.is_primary = true; + gl_profile_tab[PROFILE_B_APP_ID].service_id.id.inst_id = 0x00; + gl_profile_tab[PROFILE_B_APP_ID].service_id.id.uuid.len = ESP_UUID_LEN_16; + gl_profile_tab[PROFILE_B_APP_ID].service_id.id.uuid.uuid.uuid16 = GATTS_SERVICE_UUID_B; + + esp_ble_gatts_create_service(gatts_if, &gl_profile_tab[PROFILE_B_APP_ID].service_id, GATTS_NUM_HANDLE_B); + break; + case ESP_GATTS_READ_EVT: { + ESP_LOGI(BT_BLE_COEX_TAG, "GATT_READ_EVT, conn_id %d, trans_id %d, handle %d\n", param->read.conn_id, param->read.trans_id, param->read.handle); + esp_gatt_rsp_t rsp; + memset(&rsp, 0, sizeof(esp_gatt_rsp_t)); + rsp.attr_value.handle = param->read.handle; + rsp.attr_value.len = 4; + rsp.attr_value.value[0] = 0xde; + rsp.attr_value.value[1] = 0xed; + rsp.attr_value.value[2] = 0xbe; + rsp.attr_value.value[3] = 0xef; + esp_ble_gatts_send_response(gatts_if, param->read.conn_id, param->read.trans_id, + ESP_GATT_OK, &rsp); + break; + } + case ESP_GATTS_WRITE_EVT: { + ESP_LOGI(BT_BLE_COEX_TAG, "GATT_WRITE_EVT, conn_id %d, trans_id %d, handle %d\n", param->write.conn_id, param->write.trans_id, param->write.handle); + if (!param->write.is_prep){ + ESP_LOGI(BT_BLE_COEX_TAG, "GATT_WRITE_EVT, value len %d, value :", param->write.len); + esp_log_buffer_hex(BT_BLE_COEX_TAG, param->write.value, param->write.len); + if (gl_profile_tab[PROFILE_B_APP_ID].descr_handle == param->write.handle && param->write.len == 2){ + uint16_t descr_value= param->write.value[1]<<8 | param->write.value[0]; + if (descr_value == 0x0001){ + if (b_property & ESP_GATT_CHAR_PROP_BIT_NOTIFY){ + ESP_LOGI(BT_BLE_COEX_TAG, "notify enable"); + uint8_t notify_data[15]; + for (int i = 0; i < sizeof(notify_data); ++i) + { + notify_data[i] = i%0xff; + } + //the size of notify_data[] need less than MTU size + esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gl_profile_tab[PROFILE_B_APP_ID].char_handle, + sizeof(notify_data), notify_data, false); + } + }else if (descr_value == 0x0002){ + if (b_property & ESP_GATT_CHAR_PROP_BIT_INDICATE){ + ESP_LOGI(BT_BLE_COEX_TAG, "indicate enable"); + uint8_t indicate_data[15]; + for (int i = 0; i < sizeof(indicate_data); ++i) + { + indicate_data[i] = i%0xff; + } + //the size of indicate_data[] need less than MTU size + esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gl_profile_tab[PROFILE_B_APP_ID].char_handle, + sizeof(indicate_data), indicate_data, true); + } + } + else if (descr_value == 0x0000){ + ESP_LOGI(BT_BLE_COEX_TAG, "notify/indicate disable "); + }else{ + ESP_LOGE(BT_BLE_COEX_TAG, "unknown value"); + } + + } + } + example_write_event_env(gatts_if, &b_prepare_write_env, param); + break; + } + case ESP_GATTS_EXEC_WRITE_EVT: + ESP_LOGI(BT_BLE_COEX_TAG,"ESP_GATTS_EXEC_WRITE_EVT"); + esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL); + example_exec_write_event_env(&b_prepare_write_env, param); + break; + case ESP_GATTS_MTU_EVT: + ESP_LOGI(BT_BLE_COEX_TAG, "ESP_GATTS_MTU_EVT, MTU %d", param->mtu.mtu); + break; + case ESP_GATTS_UNREG_EVT: + break; + case ESP_GATTS_CREATE_EVT: + ESP_LOGI(BT_BLE_COEX_TAG, "CREATE_SERVICE_EVT, status %d, service_handle %d\n", param->create.status, param->create.service_handle); + gl_profile_tab[PROFILE_B_APP_ID].service_handle = param->create.service_handle; + gl_profile_tab[PROFILE_B_APP_ID].char_uuid.len = ESP_UUID_LEN_16; + gl_profile_tab[PROFILE_B_APP_ID].char_uuid.uuid.uuid16 = GATTS_CHAR_UUID_B; + + esp_ble_gatts_start_service(gl_profile_tab[PROFILE_B_APP_ID].service_handle); + b_property = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY; + esp_err_t add_char_ret =esp_ble_gatts_add_char( gl_profile_tab[PROFILE_B_APP_ID].service_handle, &gl_profile_tab[PROFILE_B_APP_ID].char_uuid, + ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, + b_property, + NULL, NULL); + if (add_char_ret){ + ESP_LOGE(BT_BLE_COEX_TAG, "add char failed, error code = 0x%x",add_char_ret); + } + break; + case ESP_GATTS_ADD_INCL_SRVC_EVT: + break; + case ESP_GATTS_ADD_CHAR_EVT: + ESP_LOGI(BT_BLE_COEX_TAG, "ADD_CHAR_EVT, status %d, attr_handle %d, service_handle %d\n", + param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle); + + gl_profile_tab[PROFILE_B_APP_ID].char_handle = param->add_char.attr_handle; + gl_profile_tab[PROFILE_B_APP_ID].descr_uuid.len = ESP_UUID_LEN_16; + gl_profile_tab[PROFILE_B_APP_ID].descr_uuid.uuid.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG; + esp_ble_gatts_add_char_descr(gl_profile_tab[PROFILE_B_APP_ID].service_handle, &gl_profile_tab[PROFILE_B_APP_ID].descr_uuid, + ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, + NULL, NULL); + break; + case ESP_GATTS_ADD_CHAR_DESCR_EVT: + gl_profile_tab[PROFILE_B_APP_ID].descr_handle = param->add_char_descr.attr_handle; + ESP_LOGI(BT_BLE_COEX_TAG, "ADD_DESCR_EVT, status %d, attr_handle %d, service_handle %d\n", + param->add_char_descr.status, param->add_char_descr.attr_handle, param->add_char_descr.service_handle); + break; + case ESP_GATTS_DELETE_EVT: + break; + case ESP_GATTS_START_EVT: + ESP_LOGI(BT_BLE_COEX_TAG, "SERVICE_START_EVT, status %d, service_handle %d\n", + param->start.status, param->start.service_handle); + break; + case ESP_GATTS_STOP_EVT: + break; + case ESP_GATTS_CONNECT_EVT: + ESP_LOGI(BT_BLE_COEX_TAG, "CONNECT_EVT, conn_id %d, remote %02x:%02x:%02x:%02x:%02x:%02x:", + param->connect.conn_id, + param->connect.remote_bda[0], param->connect.remote_bda[1], param->connect.remote_bda[2], + param->connect.remote_bda[3], param->connect.remote_bda[4], param->connect.remote_bda[5]); + gl_profile_tab[PROFILE_B_APP_ID].conn_id = param->connect.conn_id; + break; + case ESP_GATTS_CONF_EVT: + ESP_LOGI(BT_BLE_COEX_TAG, "ESP_GATTS_CONF_EVT status %d", param->conf.status); + if (param->conf.status != ESP_GATT_OK){ + esp_log_buffer_hex(BT_BLE_COEX_TAG, param->conf.value, param->conf.len); + } + break; + case ESP_GATTS_DISCONNECT_EVT: + case ESP_GATTS_OPEN_EVT: + case ESP_GATTS_CANCEL_OPEN_EVT: + case ESP_GATTS_CLOSE_EVT: + case ESP_GATTS_LISTEN_EVT: + case ESP_GATTS_CONGEST_EVT: + default: + break; + } +} + +static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) +{ + /* If event is register event, store the gatts_if for each profile */ + if (event == ESP_GATTS_REG_EVT) { + if (param->reg.status == ESP_GATT_OK) { + gl_profile_tab[param->reg.app_id].gatts_if = gatts_if; + } else { + ESP_LOGI(BT_BLE_COEX_TAG, "Reg app failed, app_id %04x, status %d\n", + param->reg.app_id, + param->reg.status); + return; + } + } + + /* If the gatts_if equal to profile A, call profile A cb handler, + * so here call each profile's callback */ + do { + int idx; + for (idx = 0; idx < PROFILE_NUM; idx++) { + if (gatts_if == ESP_GATT_IF_NONE || /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */ + gatts_if == gl_profile_tab[idx].gatts_if) { + if (gl_profile_tab[idx].gatts_cb) { + gl_profile_tab[idx].gatts_cb(event, gatts_if, param); + } + } + } + } while (0); +} + +static void ble_gatts_init(void) +{ + esp_err_t ret = esp_ble_gatts_register_callback(gatts_event_handler); + if (ret){ + ESP_LOGE(BT_BLE_COEX_TAG, "gatts register error, error code = 0x%x", ret); + return; + } + ret = esp_ble_gap_register_callback(gap_event_handler); + if (ret){ + ESP_LOGE(BT_BLE_COEX_TAG, "gap register error, error code = 0x%x", ret); + return; + } + ret = esp_ble_gatts_app_register(PROFILE_A_APP_ID); + if (ret){ + ESP_LOGE(BT_BLE_COEX_TAG, "gatts app register error, error code = 0x%x", ret); + return; + } + ret = esp_ble_gatts_app_register(PROFILE_B_APP_ID); + if (ret){ + ESP_LOGE(BT_BLE_COEX_TAG, "gatts app register error, error code = 0x%x", ret); + return; + } + esp_err_t local_mtu_ret = esp_ble_gatt_set_local_mtu(500); + if (local_mtu_ret){ + ESP_LOGE(BT_BLE_COEX_TAG, "set local MTU failed, error code = 0x%x", local_mtu_ret); + } +} +/* handler for bluetooth stack enabled events */ +static void bt_av_hdl_stack_evt(uint16_t event, void *p_param) +{ + ESP_LOGD(BT_BLE_COEX_TAG, "%s evt %d", __func__, event); + switch (event) { + case BT_APP_EVT_STACK_UP: { + /* set up bt device name */ + esp_bt_dev_set_device_name(BT_DEVICE_NAME); + + /* initialize A2DP sink */ + esp_a2d_register_callback(&bt_app_a2d_cb); + esp_a2d_sink_register_data_callback(bt_app_a2d_data_cb); + esp_a2d_sink_init(); + + /* initialize AVRCP controller */ + esp_avrc_ct_init(); + esp_avrc_ct_register_callback(bt_app_rc_ct_cb); + + /* set discoverable and connectable mode, wait to be connected */ + esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE); + break; + } + default: + ESP_LOGE(BT_BLE_COEX_TAG, "%s unhandled evt %d", __func__, event); + break; + } +} + +void app_main() +{ + esp_err_t ret; + + // Initialize NVS. + ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK( ret ); + + i2s_config_t i2s_config = { +#ifdef CONFIG_A2DP_SINK_OUTPUT_INTERNAL_DAC + .mode = I2S_MODE_DAC_BUILT_IN, +#else + .mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX +#endif + .sample_rate = 44100, + .bits_per_sample = 16, + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels + .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB, + .dma_buf_count = 6, + .dma_buf_len = 60, // + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 //Interrupt level 1 + }; + + + i2s_driver_install(0, &i2s_config, 0, NULL); +#ifdef CONFIG_A2DP_SINK_OUTPUT_INTERNAL_DAC + i2s_set_pin(0, NULL); +#else + i2s_pin_config_t pin_config = { + .bck_io_num = CONFIG_I2S_BCK_PIN, + .ws_io_num = CONFIG_I2S_LRCK_PIN, + .data_out_num = CONFIG_I2S_DATA_PIN, + .data_in_num = -1 //Not used + }; + + i2s_set_pin(0, &pin_config); +#endif + + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + ret = esp_bt_controller_init(&bt_cfg); + if (ret) { + ESP_LOGE(BT_BLE_COEX_TAG, "%s initialize controller failed\n", __func__); + return; + } + + ret = esp_bt_controller_enable(ESP_BT_MODE_BTDM); + if (ret) { + ESP_LOGE(BT_BLE_COEX_TAG, "%s enable controller failed\n", __func__); + return; + } + + ret = esp_bluedroid_init(); + if (ret) { + ESP_LOGE(BT_BLE_COEX_TAG, "%s init bluetooth failed\n", __func__); + return; + } + ret = esp_bluedroid_enable(); + if (ret) { + ESP_LOGE(BT_BLE_COEX_TAG, "%s enable bluetooth failed\n", __func__); + return; + } + + /* create application task */ + bt_app_task_start_up(); + + /* Bluetooth device name, connection mode and profile set up */ + bt_app_work_dispatch(bt_av_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL); + //gatt server init + ble_gatts_init(); +} \ No newline at end of file diff --git a/examples/bluetooth/a2dp_gatts_coex/sdkconfig.defaults b/examples/bluetooth/a2dp_gatts_coex/sdkconfig.defaults new file mode 100644 index 0000000000..07275e1e7d --- /dev/null +++ b/examples/bluetooth/a2dp_gatts_coex/sdkconfig.defaults @@ -0,0 +1,30 @@ +# Override some defaults so BT stack is enabled and +# Classic BT is enabled and BT_DRAM_RELEASE is disabled +CONFIG_BT_ENABLED=y +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_0=y +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_1= +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 +CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI=y +CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4= +CONFIG_BLUEDROID_ENABLED=y +CONFIG_BLUEDROID_PINNED_TO_CORE_0=y +CONFIG_BLUEDROID_PINNED_TO_CORE_1= +CONFIG_BLUEDROID_PINNED_TO_CORE=0 +CONFIG_BTC_TASK_STACK_SIZE=3072 +CONFIG_BLUEDROID_MEM_DEBUG= +CONFIG_CLASSIC_BT_ENABLED=y +CONFIG_A2DP_ENABLE=y +CONFIG_A2DP_SINK_ENABLE=y +CONFIG_A2DP_SRC_ENABLE= +CONFIG_A2DP_SINK_TASK_STACK_SIZE=2048 +CONFIG_BT_SPP_ENABLED= +CONFIG_GATTS_ENABLE=y +CONFIG_GATTC_ENABLE= +CONFIG_BLE_SMP_ENABLE= +CONFIG_BLE_ENABLE_SRVCHG_REG=y +CONFIG_BT_STACK_NO_LOG= +CONFIG_BT_ACL_CONNECTIONS=4 +CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST= +CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY= +CONFIG_SMP_ENABLE=y +CONFIG_BT_RESERVE_DRAM=0x10000 From e983230be933fb83cebdd1945ba6539a7dc99b28 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Fri, 4 May 2018 16:42:54 +0200 Subject: [PATCH 160/187] MDNS-Fuzzer: AFL fuzzer tests for mdsn packet parser --- components/mdns/include/mdns.h | 4 - components/mdns/mdns.c | 318 +----------------- components/mdns/mdns_networking.c | 284 ++++++++++++++++ .../mdns/private_include/mdns_networking.h | 52 +++ components/mdns/test_afl_fuzz_host/Makefile | 22 +- .../mdns/test_afl_fuzz_host/esp32_compat.h | 153 +++++++-- .../mdns/test_afl_fuzz_host/esp32_mock.c | 84 +++++ .../mdns/test_afl_fuzz_host/esp32_mock.h | 45 +++ components/mdns/test_afl_fuzz_host/mdns_di.h | 53 +++ components/mdns/test_afl_fuzz_host/test.c | 209 +++++++++--- 10 files changed, 833 insertions(+), 391 deletions(-) create mode 100644 components/mdns/mdns_networking.c create mode 100644 components/mdns/private_include/mdns_networking.h create mode 100644 components/mdns/test_afl_fuzz_host/esp32_mock.c create mode 100644 components/mdns/test_afl_fuzz_host/esp32_mock.h create mode 100644 components/mdns/test_afl_fuzz_host/mdns_di.h diff --git a/components/mdns/include/mdns.h b/components/mdns/include/mdns.h index db0e3b522a..a5ebb809f6 100644 --- a/components/mdns/include/mdns.h +++ b/components/mdns/include/mdns.h @@ -18,12 +18,8 @@ extern "C" { #endif -#ifndef MDNS_TEST_MODE #include #include "esp_event.h" -#else -#include "esp32_compat.h" -#endif #define MDNS_TYPE_A 0x0001 #define MDNS_TYPE_PTR 0x000C diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index da00d7e5db..73c5f99c9f 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -11,25 +11,11 @@ // 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 "mdns.h" - -#include -#include "sdkconfig.h" -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "freertos/semphr.h" -#include "lwip/ip_addr.h" -#include "lwip/pbuf.h" -#include "lwip/igmp.h" -#include "lwip/udp.h" -#include "lwip/mld6.h" -#include "lwip/priv/tcpip_priv.h" -#include "esp_wifi.h" -#include "esp_system.h" -#include "esp_timer.h" -#include "esp_event_loop.h" - #include "mdns_private.h" +#include "mdns_networking.h" +#include #ifdef MDNS_ENABLE_DEBUG void mdns_debug_packet(const uint8_t * data, size_t len); @@ -38,7 +24,7 @@ void mdns_debug_packet(const uint8_t * data, size_t len); static const char * MDNS_DEFAULT_DOMAIN = "local"; static const char * MDNS_SUB_STR = "_sub"; -static mdns_server_t * _mdns_server = NULL; +mdns_server_t * _mdns_server = NULL; static volatile TaskHandle_t _mdns_service_task_handle = NULL; static SemaphoreHandle_t _mdns_service_semaphore = NULL; @@ -110,14 +96,7 @@ static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char return NULL; } -/* - * MDNS Server Networking - * */ - -/** - * @brief Queue RX packet action - */ -static esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet) +esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet) { mdns_action_t * action = NULL; @@ -135,286 +114,6 @@ static esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet) return ESP_OK; } -/** - * @brief the receive callback of the raw udp api. Packets are received here - * - */ -static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport) -{ - uint8_t i; - while (pb != NULL) { - struct pbuf * this_pb = pb; - pb = pb->next; - this_pb->next = NULL; - - mdns_rx_packet_t * packet = (mdns_rx_packet_t *)malloc(sizeof(mdns_rx_packet_t)); - if (!packet) { - //missed packet - no memory - pbuf_free(this_pb); - continue; - } - - packet->tcpip_if = TCPIP_ADAPTER_IF_MAX; - packet->pb = this_pb; - packet->src_port = rport; - memcpy(&packet->src, raddr, sizeof(ip_addr_t)); - packet->dest.type = packet->src.type; - - if (packet->src.type == IPADDR_TYPE_V4) { - packet->ip_protocol = MDNS_IP_PROTOCOL_V4; - struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP_HLEN); - packet->dest.u_addr.ip4.addr = iphdr->dest.addr; - } else { - packet->ip_protocol = MDNS_IP_PROTOCOL_V6; - struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP6_HLEN); - memcpy(&packet->dest.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16); - } - packet->multicast = ip_addr_ismulticast(&(packet->dest)); - - //lwip does not return the proper pcb if you have more than one for the same multicast address (but different interfaces) - struct netif * netif = NULL; - void * nif = NULL; - struct udp_pcb * pcb = NULL; - for (i=0; iinterfaces[i].pcbs[packet->ip_protocol].pcb; - tcpip_adapter_get_netif (i, &nif); - netif = (struct netif *)nif; - if (pcb && netif && netif == ip_current_input_netif ()) { - if (packet->src.type == IPADDR_TYPE_V4) { - if ((packet->src.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr) != (netif->ip_addr.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr)) { - //packet source is not in the same subnet - pcb = NULL; - break; - } - } - packet->tcpip_if = i; - break; - } - pcb = NULL; - } - - if (!pcb || !_mdns_server || !_mdns_server->action_queue - || _mdns_send_rx_action(packet) != ESP_OK) { - pbuf_free(this_pb); - free(packet); - } - } -} - -/** - * @brief Stop PCB Main code - */ -static void _udp_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - if (!_mdns_server) { - return; - } - mdns_pcb_t * _pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; - if (_pcb->pcb) { - _pcb->state = PCB_OFF; - udp_recv(_pcb->pcb, NULL, NULL); - udp_disconnect(_pcb->pcb); - udp_remove(_pcb->pcb); - free(_pcb->probe_services); - _pcb->pcb = NULL; - _pcb->probe_ip = false; - _pcb->probe_services = NULL; - _pcb->probe_services_len = 0; - _pcb->probe_running = false; - _pcb->failed_probes = 0; - } -} - -/** - * @brief Start PCB V4 - */ -static esp_err_t _udp_pcb_v4_init(tcpip_adapter_if_t tcpip_if) -{ - tcpip_adapter_ip_info_t if_ip_info; - - if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb) { - return ESP_ERR_INVALID_STATE; - } - - if (tcpip_adapter_get_ip_info(tcpip_if, &if_ip_info) || if_ip_info.ip.addr == 0) { - return ESP_ERR_INVALID_ARG; - } - - ip_addr_t interface_addr = IPADDR4_INIT(if_ip_info.ip.addr); - - ip_addr_t multicast_addr; - IP_ADDR4(&multicast_addr, 224, 0, 0, 251); - - if (igmp_joingroup((const struct ip4_addr *)&interface_addr.u_addr.ip4, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) { - return ESP_ERR_INVALID_STATE; - } - - struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V4); - if (!pcb) { - return ESP_ERR_NO_MEM; - } - - if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) { - udp_remove(pcb); - return ESP_ERR_INVALID_STATE; - } - - pcb->mcast_ttl = 1; - pcb->remote_port = MDNS_SERVICE_PORT; - ip_addr_copy(pcb->multicast_ip, interface_addr); - ip_addr_copy(pcb->remote_ip, multicast_addr); - - _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb = pcb; - _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].failed_probes = 0; - udp_recv(pcb, &_udp_recv, _mdns_server); - - return ESP_OK; -} - -/** - * @brief Start PCB V6 - */ -static esp_err_t _udp_pcb_v6_init(tcpip_adapter_if_t tcpip_if) -{ - ip_addr_t multicast_addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000); - ip_addr_t interface_addr; - interface_addr.type = IPADDR_TYPE_V6; - - if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb) { - return ESP_ERR_INVALID_STATE; - } - - if (tcpip_adapter_get_ip6_linklocal(tcpip_if, &interface_addr.u_addr.ip6)) { - return ESP_ERR_INVALID_ARG; - } - - if (mld6_joingroup(&(interface_addr.u_addr.ip6), &(multicast_addr.u_addr.ip6))) { - return ESP_ERR_INVALID_STATE; - } - - struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V6); - if (!pcb) { - return ESP_ERR_NO_MEM; - } - - if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) { - udp_remove(pcb); - return ESP_ERR_INVALID_STATE; - } - - pcb->remote_port = MDNS_SERVICE_PORT; - ip_addr_copy(pcb->remote_ip, multicast_addr); - - _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb = pcb; - _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].failed_probes = 0; - udp_recv(pcb, &_udp_recv, _mdns_server); - - return ESP_OK; -} - -/** - * @brief Start PCB Main code - */ -static esp_err_t _udp_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - if (ip_protocol == MDNS_IP_PROTOCOL_V4) { - return _udp_pcb_v4_init(tcpip_if); - } else if (ip_protocol == MDNS_IP_PROTOCOL_V6) { - return _udp_pcb_v6_init(tcpip_if); - } - return ESP_ERR_INVALID_ARG; -} - -typedef struct { - struct tcpip_api_call call; - tcpip_adapter_if_t tcpip_if; - mdns_ip_protocol_t ip_protocol; - esp_err_t err; -} mdns_api_call_t; - -/** - * @brief Start PCB from LwIP thread - */ -static err_t _mdns_pcb_init_api(struct tcpip_api_call *api_call_msg) -{ - mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg; - msg->err = _udp_pcb_init(msg->tcpip_if, msg->ip_protocol); - return msg->err; -} - -/** - * @brief Start PCB - */ -static esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - mdns_api_call_t msg = { - .tcpip_if = tcpip_if, - .ip_protocol = ip_protocol - }; - tcpip_api_call(_mdns_pcb_init_api, (struct tcpip_api_call*)&msg); - return msg.err; -} - -/** - * @brief Stop PCB from LwIP thread - */ -static err_t _mdns_pcb_deinit_api(struct tcpip_api_call *api_call_msg) -{ - mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg; - _udp_pcb_deinit(msg->tcpip_if, msg->ip_protocol); - msg->err = ESP_OK; - return ESP_OK; -} - -/** - * @brief Stop PCB - */ -static esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) -{ - mdns_api_call_t msg = { - .tcpip_if = tcpip_if, - .ip_protocol = ip_protocol - }; - tcpip_api_call(_mdns_pcb_deinit_api, (struct tcpip_api_call*)&msg); - return msg.err; -} - - -/** - * @brief send packet over UDP - * - * @param server The server - * @param data byte array containing the packet data - * @param len length of the packet data - * - * @return length of sent packet or 0 on error - */ -static size_t _udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len) -{ -#ifndef MDNS_TEST_MODE - struct netif * netif = NULL; - void * nif = NULL; - esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif); - netif = (struct netif *)nif; - if (err) { - return 0; - } - - struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if (pbt == NULL) { - return 0; - } - memcpy((uint8_t *)pbt->payload, data, len); - - err = udp_sendto_if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb, pbt, ip, port, netif); - pbuf_free(pbt); - if (err) { - return 0; - } -#endif - return len; -} - /** * @brief Get the service name of a service */ @@ -1235,7 +934,7 @@ static void _mdns_dispatch_tx_packet(mdns_tx_packet_t * p) mdns_debug_packet(packet, index); #endif - _udp_pcb_write(p->tcpip_if, p->ip_protocol, &p->dst, p->port, packet, index); + _mdns_udp_pcb_write(p->tcpip_if, p->ip_protocol, &p->dst, p->port, packet, index); } /** @@ -4192,7 +3891,6 @@ static esp_err_t _mdns_stop_timer(){ */ static esp_err_t _mdns_service_task_start() { -#ifndef MDNS_TEST_MODE if (!_mdns_service_semaphore) { _mdns_service_semaphore = xSemaphoreCreateMutex(); if (!_mdns_service_semaphore) { @@ -4212,8 +3910,6 @@ static esp_err_t _mdns_service_task_start() } } MDNS_SERVICE_UNLOCK(); -#endif - return ESP_OK; } @@ -4225,7 +3921,6 @@ static esp_err_t _mdns_service_task_start() */ static esp_err_t _mdns_service_task_stop() { -#ifndef MDNS_TEST_MODE MDNS_SERVICE_LOCK(); _mdns_stop_timer(); if (_mdns_service_task_handle) { @@ -4241,7 +3936,6 @@ static esp_err_t _mdns_service_task_stop() } } MDNS_SERVICE_UNLOCK(); -#endif return ESP_OK; } diff --git a/components/mdns/mdns_networking.c b/components/mdns/mdns_networking.c new file mode 100644 index 0000000000..e4ab816dec --- /dev/null +++ b/components/mdns/mdns_networking.c @@ -0,0 +1,284 @@ + +/* + * MDNS Server Networking + * + */ +#include +#include "mdns_networking.h" + + +extern mdns_server_t * _mdns_server; + +/* + * MDNS Server Networking + * + */ + +/** + * @brief the receive callback of the raw udp api. Packets are received here + * + */ +static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport) +{ + + uint8_t i; + while (pb != NULL) { + struct pbuf * this_pb = pb; + pb = pb->next; + this_pb->next = NULL; + + mdns_rx_packet_t * packet = (mdns_rx_packet_t *)malloc(sizeof(mdns_rx_packet_t)); + if (!packet) { + //missed packet - no memory + pbuf_free(this_pb); + continue; + } + + packet->tcpip_if = TCPIP_ADAPTER_IF_MAX; + packet->pb = this_pb; + packet->src_port = rport; + memcpy(&packet->src, raddr, sizeof(ip_addr_t)); + packet->dest.type = packet->src.type; + + if (packet->src.type == IPADDR_TYPE_V4) { + packet->ip_protocol = MDNS_IP_PROTOCOL_V4; + struct ip_hdr * iphdr = (struct ip_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP_HLEN); + packet->dest.u_addr.ip4.addr = iphdr->dest.addr; + } else { + packet->ip_protocol = MDNS_IP_PROTOCOL_V6; + struct ip6_hdr * ip6hdr = (struct ip6_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP6_HLEN); + memcpy(&packet->dest.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16); + } + packet->multicast = ip_addr_ismulticast(&(packet->dest)); + + //lwip does not return the proper pcb if you have more than one for the same multicast address (but different interfaces) + struct netif * netif = NULL; + void * nif = NULL; + struct udp_pcb * pcb = NULL; + for (i=0; iinterfaces[i].pcbs[packet->ip_protocol].pcb; + tcpip_adapter_get_netif (i, &nif); + netif = (struct netif *)nif; + if (pcb && netif && netif == ip_current_input_netif ()) { + if (packet->src.type == IPADDR_TYPE_V4) { + if ((packet->src.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr) != (netif->ip_addr.u_addr.ip4.addr & netif->netmask.u_addr.ip4.addr)) { + //packet source is not in the same subnet + pcb = NULL; + break; + } + } + packet->tcpip_if = i; + break; + } + pcb = NULL; + } + + if (!pcb || !_mdns_server || !_mdns_server->action_queue + || _mdns_send_rx_action(packet) != ESP_OK) { + pbuf_free(this_pb); + free(packet); + } + } + +} + +/** + * @brief Stop PCB Main code + */ +static void _udp_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + if (!_mdns_server) { + return; + } + mdns_pcb_t * _pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; + if (_pcb->pcb) { + _pcb->state = PCB_OFF; + udp_recv(_pcb->pcb, NULL, NULL); + udp_disconnect(_pcb->pcb); + udp_remove(_pcb->pcb); + free(_pcb->probe_services); + _pcb->pcb = NULL; + _pcb->probe_ip = false; + _pcb->probe_services = NULL; + _pcb->probe_services_len = 0; + _pcb->probe_running = false; + _pcb->failed_probes = 0; + } +} + +/** + * @brief Start PCB V4 + */ +static esp_err_t _udp_pcb_v4_init(tcpip_adapter_if_t tcpip_if) +{ + tcpip_adapter_ip_info_t if_ip_info; + + if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb) { + return ESP_ERR_INVALID_STATE; + } + + if (tcpip_adapter_get_ip_info(tcpip_if, &if_ip_info) || if_ip_info.ip.addr == 0) { + return ESP_ERR_INVALID_ARG; + } + + ip_addr_t interface_addr = IPADDR4_INIT(if_ip_info.ip.addr); + + ip_addr_t multicast_addr; + IP_ADDR4(&multicast_addr, 224, 0, 0, 251); + + if (igmp_joingroup((const struct ip4_addr *)&interface_addr.u_addr.ip4, (const struct ip4_addr *)&multicast_addr.u_addr.ip4)) { + return ESP_ERR_INVALID_STATE; + } + + struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V4); + if (!pcb) { + return ESP_ERR_NO_MEM; + } + + if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) { + udp_remove(pcb); + return ESP_ERR_INVALID_STATE; + } + + pcb->mcast_ttl = 1; + pcb->remote_port = MDNS_SERVICE_PORT; + ip_addr_copy(pcb->multicast_ip, interface_addr); + ip_addr_copy(pcb->remote_ip, multicast_addr); + + _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].pcb = pcb; + _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].failed_probes = 0; + udp_recv(pcb, &_udp_recv, _mdns_server); + + return ESP_OK; +} + +/** + * @brief Start PCB V6 + */ +static esp_err_t _udp_pcb_v6_init(tcpip_adapter_if_t tcpip_if) +{ + ip_addr_t multicast_addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000); + ip_addr_t interface_addr; + interface_addr.type = IPADDR_TYPE_V6; + + if (!_mdns_server || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb) { + return ESP_ERR_INVALID_STATE; + } + + if (tcpip_adapter_get_ip6_linklocal(tcpip_if, &interface_addr.u_addr.ip6)) { + return ESP_ERR_INVALID_ARG; + } + + if (mld6_joingroup(&(interface_addr.u_addr.ip6), &(multicast_addr.u_addr.ip6))) { + return ESP_ERR_INVALID_STATE; + } + + struct udp_pcb * pcb = udp_new_ip_type(IPADDR_TYPE_V6); + if (!pcb) { + return ESP_ERR_NO_MEM; + } + + if (udp_bind(pcb, &interface_addr, MDNS_SERVICE_PORT) != 0) { + udp_remove(pcb); + return ESP_ERR_INVALID_STATE; + } + + pcb->remote_port = MDNS_SERVICE_PORT; + ip_addr_copy(pcb->remote_ip, multicast_addr); + + _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].pcb = pcb; + _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].failed_probes = 0; + udp_recv(pcb, &_udp_recv, _mdns_server); + + return ESP_OK; +} + +/** + * @brief Start PCB Main code + */ +static esp_err_t _udp_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + if (ip_protocol == MDNS_IP_PROTOCOL_V4) { + return _udp_pcb_v4_init(tcpip_if); + } else if (ip_protocol == MDNS_IP_PROTOCOL_V6) { + return _udp_pcb_v6_init(tcpip_if); + } + return ESP_ERR_INVALID_ARG; +} + +typedef struct { + struct tcpip_api_call call; + tcpip_adapter_if_t tcpip_if; + mdns_ip_protocol_t ip_protocol; + esp_err_t err; +} mdns_api_call_t; + +/** + * @brief Start PCB from LwIP thread + */ +static err_t _mdns_pcb_init_api(struct tcpip_api_call *api_call_msg) +{ + mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg; + msg->err = _udp_pcb_init(msg->tcpip_if, msg->ip_protocol); + return msg->err; +} + +/** + * @brief Stop PCB from LwIP thread + */ +static err_t _mdns_pcb_deinit_api(struct tcpip_api_call *api_call_msg) +{ + mdns_api_call_t * msg = (mdns_api_call_t *)api_call_msg; + _udp_pcb_deinit(msg->tcpip_if, msg->ip_protocol); + msg->err = ESP_OK; + return ESP_OK; +} + +/* + * Non-static functions below are + * - _mdns prefixed + * - commented in mdns_networking.h header + */ +esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_api_call_t msg = { + .tcpip_if = tcpip_if, + .ip_protocol = ip_protocol + }; + tcpip_api_call(_mdns_pcb_init_api, (struct tcpip_api_call*)&msg); + return msg.err; +} + +esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_api_call_t msg = { + .tcpip_if = tcpip_if, + .ip_protocol = ip_protocol + }; + tcpip_api_call(_mdns_pcb_deinit_api, (struct tcpip_api_call*)&msg); + return msg.err; +} + +size_t _mdns_udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len) +{ + struct netif * netif = NULL; + void * nif = NULL; + esp_err_t err = tcpip_adapter_get_netif(tcpip_if, &nif); + netif = (struct netif *)nif; + if (err) { + return 0; + } + + struct pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pbt == NULL) { + return 0; + } + memcpy((uint8_t *)pbt->payload, data, len); + + err = udp_sendto_if (_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].pcb, pbt, ip, port, netif); + pbuf_free(pbt); + if (err) { + return 0; + } + return len; +} diff --git a/components/mdns/private_include/mdns_networking.h b/components/mdns/private_include/mdns_networking.h new file mode 100644 index 0000000000..5b56f8066d --- /dev/null +++ b/components/mdns/private_include/mdns_networking.h @@ -0,0 +1,52 @@ +#ifndef ESP_MDNS_NETWORKING_H_ +#define ESP_MDNS_NETWORKING_H_ + +/* + * MDNS Server Networking -- private include + * + */ +#include "mdns.h" +#include "mdns_private.h" +#include "sdkconfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "lwip/ip_addr.h" +#include "lwip/pbuf.h" +#include "lwip/igmp.h" +#include "lwip/udp.h" +#include "lwip/mld6.h" +#include "lwip/priv/tcpip_priv.h" +#include "esp_wifi.h" +#include "esp_system.h" +#include "esp_timer.h" +#include "esp_event_loop.h" + + +/** + * @brief Queue RX packet action + */ +esp_err_t _mdns_send_rx_action(mdns_rx_packet_t * packet); + +/** + * @brief Start PCB + */ +esp_err_t _mdns_pcb_init(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Stop PCB + */ +esp_err_t _mdns_pcb_deinit(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief send packet over UDP + * + * @param server The server + * @param data byte array containing the packet data + * @param len length of the packet data + * + * @return length of sent packet or 0 on error + */ +size_t _mdns_udp_pcb_write(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const ip_addr_t *ip, uint16_t port, uint8_t * data, size_t len); + +#endif /* ESP_MDNS_NETWORKING_H_ */ diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile index 65a318ef24..61bedc5209 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -1,17 +1,25 @@ TEST_NAME=test FUZZ=afl-fuzz -CC=afl-clang-fast +COMPONENTS_DIR=../.. +CFLAGS=-g -DMDNS_TEST_MODE -I. -I.. -I../include -I../private_include -I$(COMPONENTS_DIR)/tcpip_adapter/include -I$(COMPONENTS_DIR)/esp32/include -include esp32_compat.h +MDNS_C_DEPENDENCY_INJECTION=-include mdns_di.h +ifeq ($(INSTR),off) + CC=gcc + CFLAGS+=-DINSTR_IS_OFF + TEST_NAME=test_sim +else + CC=afl-clang-fast +endif CPP=$(CC) LD=$(CC) -OBJECTS=mdns.o test.o -CFLAGS=-DMDNS_TEST_MODE -I. -I../include +OBJECTS=mdns.o esp32_mock.o test.o OS := $(shell uname) ifeq ($(OS),Darwin) LDLIBS= else - LDLIBS=-lbsd - CFLAGS+=-DUSE_BSD_STRING + LDLIBS=-lbsd + CFLAGS+=-DUSE_BSD_STRING endif all: $(TEST_NAME) @@ -22,11 +30,11 @@ all: $(TEST_NAME) mdns.o: ../mdns.c @echo "[CC] $<" - @$(CC) $(CFLAGS) -c $< -o $@ + @$(CC) $(CFLAGS) $(MDNS_C_DEPENDENCY_INJECTION) -c $< -o $@ $(TEST_NAME): $(OBJECTS) @echo "[LD] $@" - @$(LD) $(LDLIBS) $(OBJECTS) -o $@ + @$(LD) $(OBJECTS) -o $@ $(LDLIBS) fuzz: $(TEST_NAME) @$(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME) diff --git a/components/mdns/test_afl_fuzz_host/esp32_compat.h b/components/mdns/test_afl_fuzz_host/esp32_compat.h index fd21b23657..402807c4f5 100644 --- a/components/mdns/test_afl_fuzz_host/esp32_compat.h +++ b/components/mdns/test_afl_fuzz_host/esp32_compat.h @@ -17,6 +17,12 @@ #ifdef MDNS_TEST_MODE +// Not to include +#define ESP_MDNS_NETWORKING_H_ +#define _TCPIP_ADAPTER_H_ +#define __ESP_EVENT_H__ + + #ifdef USE_BSD_STRING #include #endif @@ -28,6 +34,7 @@ #include #include + #define ERR_OK 0 #define ESP_OK 0 #define ESP_FAIL -1 @@ -44,21 +51,26 @@ #define pdTRUE true #define pdFALSE false +#define pdPASS ( pdTRUE ) +#define pdFAIL ( pdFALSE ) #define portMAX_DELAY 0xFFFFFFFF #define portTICK_PERIOD_MS 1 #define xSemaphoreTake(s,d) +#define xTaskDelete(a) +#define vTaskDelete(a) free(a) #define xSemaphoreGive(s) +#define _mdns_pcb_init(a,b) true +#define _mdns_pcb_deinit(a,b) true #define xSemaphoreCreateMutex() malloc(1) #define vSemaphoreDelete(s) free(s) -#define xQueueCreate(n,s) malloc((n)*(s)) -#define vQueueDelete(q) free(q) -#define xQueueReceive(q, d, t) (ESP_OK) -#define vTaskDelay(m) usleep((m)*1000) +#define xTaskCreatePinnedToCore(a,b,c,d,e,f,g) *(f) = malloc(1) +#define vTaskDelay(m) usleep((m)*0) #define pbuf_free(p) free(p) - -#define tcpip_adapter_get_ip_info(i,d) +#define esp_random() (rand()%UINT32_MAX) +#define tcpip_adapter_get_ip_info(i,d) true +#define tcpip_adapter_dhcpc_get_status(a, b) TCPIP_ADAPTER_DHCP_STARTED #define tcpip_adapter_get_ip6_linklocal(i,d) (ESP_OK) #define tcpip_adapter_get_hostname(i, n) *(n) = "esp32-0123456789AB" @@ -67,17 +79,31 @@ ((uint32_t)((c) & 0xff) << 16) | \ ((uint32_t)((b) & 0xff) << 8) | \ (uint32_t)((a) & 0xff) +#define ip_2_ip6(ipaddr) (&((ipaddr)->u_addr.ip6)) +#define ip_2_ip4(ipaddr) (&((ipaddr)->u_addr.ip4)) + +#define IPADDR_TYPE_V4 0U +#define IPADDR_TYPE_V6 6U +#define IPADDR_TYPE_ANY 46U +#define IP_SET_TYPE_VAL(ipaddr, iptype) do { (ipaddr).type = (iptype); }while(0) +#define IP_ADDR4(ipaddr,a,b,c,d) do { IP4_ADDR(ip_2_ip4(ipaddr),a,b,c,d); \ + IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V4); } while(0) +#define IP_ADDR6(ipaddr,i0,i1,i2,i3) do { IP6_ADDR(ip_2_ip6(ipaddr),i0,i1,i2,i3); \ + IP_SET_TYPE_VAL(*(ipaddr), IPADDR_TYPE_V6); } while(0) + +#define IPADDR6_INIT(a, b, c, d) { { { { a, b, c, d } } }, IPADDR_TYPE_V6 } + typedef int32_t esp_err_t; typedef void * xSemaphoreHandle; +typedef void * SemaphoreHandle_t; typedef void * xQueueHandle; +typedef void * QueueHandle_t; +typedef void * TaskHandle_t; +typedef void * esp_timer_handle_t; +typedef uint32_t TickType_t; +typedef uint32_t portTickType; -typedef enum { - TCPIP_ADAPTER_IF_STA = 0, /**< ESP32 station interface */ - TCPIP_ADAPTER_IF_AP, /**< ESP32 soft-AP interface */ - TCPIP_ADAPTER_IF_ETH, /**< ESP32 ethernet interface */ - TCPIP_ADAPTER_IF_MAX -} tcpip_adapter_if_t; typedef enum { WIFI_MODE_NULL = 0, /**< null mode */ @@ -87,6 +113,42 @@ typedef enum { WIFI_MODE_MAX } wifi_mode_t; +/* status of DHCP client or DHCP server */ +typedef enum { + TCPIP_ADAPTER_DHCP_INIT = 0, /**< DHCP client/server in initial state */ + TCPIP_ADAPTER_DHCP_STARTED, /**< DHCP client/server already been started */ + TCPIP_ADAPTER_DHCP_STOPPED, /**< DHCP client/server already been stopped */ + TCPIP_ADAPTER_DHCP_STATUS_MAX +} tcpip_adapter_dhcp_status_t; + +typedef enum { + SYSTEM_EVENT_WIFI_READY = 0, /**< ESP32 WiFi ready */ + SYSTEM_EVENT_SCAN_DONE, /**< ESP32 finish scanning AP */ + SYSTEM_EVENT_STA_START, /**< ESP32 station start */ + SYSTEM_EVENT_STA_STOP, /**< ESP32 station stop */ + SYSTEM_EVENT_STA_CONNECTED, /**< ESP32 station connected to AP */ + SYSTEM_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected from AP */ + SYSTEM_EVENT_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by ESP32 station changed */ + SYSTEM_EVENT_STA_GOT_IP, /**< ESP32 station got IP from connected AP */ + SYSTEM_EVENT_STA_LOST_IP, /**< ESP32 station lost IP and the IP is reset to 0 */ + SYSTEM_EVENT_STA_WPS_ER_SUCCESS, /**< ESP32 station wps succeeds in enrollee mode */ + SYSTEM_EVENT_STA_WPS_ER_FAILED, /**< ESP32 station wps fails in enrollee mode */ + SYSTEM_EVENT_STA_WPS_ER_TIMEOUT, /**< ESP32 station wps timeout in enrollee mode */ + SYSTEM_EVENT_STA_WPS_ER_PIN, /**< ESP32 station wps pin code in enrollee mode */ + SYSTEM_EVENT_AP_START, /**< ESP32 soft-AP start */ + SYSTEM_EVENT_AP_STOP, /**< ESP32 soft-AP stop */ + SYSTEM_EVENT_AP_STACONNECTED, /**< a station connected to ESP32 soft-AP */ + SYSTEM_EVENT_AP_STADISCONNECTED, /**< a station disconnected from ESP32 soft-AP */ + SYSTEM_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */ + SYSTEM_EVENT_GOT_IP6, /**< ESP32 station or ap or ethernet interface v6IP addr is preferred */ + SYSTEM_EVENT_ETH_START, /**< ESP32 ethernet start */ + SYSTEM_EVENT_ETH_STOP, /**< ESP32 ethernet stop */ + SYSTEM_EVENT_ETH_CONNECTED, /**< ESP32 ethernet phy link up */ + SYSTEM_EVENT_ETH_DISCONNECTED, /**< ESP32 ethernet phy link down */ + SYSTEM_EVENT_ETH_GOT_IP, /**< ESP32 ethernet got IP from connected AP */ + SYSTEM_EVENT_MAX +} system_event_id_t; + struct udp_pcb { uint8_t dummy; }; @@ -101,27 +163,76 @@ struct ip6_addr { }; typedef struct ip6_addr ip6_addr_t; +typedef struct _ip_addr { + union { + ip6_addr_t ip6; + ip4_addr_t ip4; + } u_addr; + uint8_t type; +} ip_addr_t; + typedef struct { ip4_addr_t ip; ip4_addr_t netmask; ip4_addr_t gw; } tcpip_adapter_ip_info_t; +// typedef int32_t system_event_id_t; +typedef enum { + TCPIP_ADAPTER_IF_STA = 0, /**< ESP32 station interface */ + TCPIP_ADAPTER_IF_AP, /**< ESP32 soft-AP interface */ + TCPIP_ADAPTER_IF_ETH, /**< ESP32 ethernet interface */ + TCPIP_ADAPTER_IF_MAX +} tcpip_adapter_if_t; + +typedef struct { + ip6_addr_t ip; +} tcpip_adapter_ip6_info_t; +typedef struct { + tcpip_adapter_if_t if_index; + tcpip_adapter_ip6_info_t ip6_info; +} system_event_got_ip6_t; +typedef union { + system_event_got_ip6_t got_ip6; /**< ESP32 station or ap or ethernet ipv6 addr state change to preferred */ +} system_event_info_t; + +typedef struct { + system_event_id_t event_id; /**< event ID */ + system_event_info_t event_info; /**< event information */ +} system_event_t; + inline esp_err_t esp_wifi_get_mode(wifi_mode_t * mode) { *mode = WIFI_MODE_APSTA; return ESP_OK; } -inline uint32_t xTaskGetTickCount() -{ - struct timeval tv; - struct timezone tz; - if (gettimeofday(&tv, &tz) == 0) { - return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); - } - return 0; -} +struct pbuf { + struct pbuf *next; + void *payload; + uint16_t tot_len; + uint16_t len; + uint8_t /*pbuf_type*/ type; + uint8_t flags; + uint16_t ref; +}; + +#define IP_GET_TYPE(ipaddr) ((ipaddr)->type) +#define IP_IS_V6_VAL(ipaddr) (IP_GET_TYPE(&ipaddr) == IPADDR_TYPE_V6) +#define ip4_addr_copy(dest, src) ((dest).addr = (src).addr) +#define ip6_addr_copy(dest, src) do{(dest).addr[0] = (src).addr[0]; \ + (dest).addr[1] = (src).addr[1]; \ + (dest).addr[2] = (src).addr[2]; \ + (dest).addr[3] = (src).addr[3];}while(0) + +#define ip_addr_copy(dest, src) do{ IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&src)); if(IP_IS_V6_VAL(src)){ \ + ip6_addr_copy(*ip_2_ip6(&(dest)), *ip_2_ip6(&(src))); }else{ \ + ip4_addr_copy(*ip_2_ip4(&(dest)), *ip_2_ip4(&(src))); }}while(0) + +#include "esp32_mock.h" + +uint32_t xTaskGetTickCount(); + #endif //MDNS_TEST_MODE diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.c b/components/mdns/test_afl_fuzz_host/esp32_mock.c new file mode 100644 index 0000000000..aa9ca7f720 --- /dev/null +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include +#include "esp32_compat.h" + +void* g_queue; +int g_queue_send_shall_fail = 0; +int g_size = 0; + +esp_err_t esp_timer_delete(esp_timer_handle_t timer) +{ + return ESP_OK; +} + +esp_err_t esp_timer_stop(esp_timer_handle_t timer) +{ + return ESP_OK; +} + +esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) +{ + return ESP_OK; +} + +esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, + esp_timer_handle_t* out_handle) +{ + return ESP_OK; +} + +uint32_t xTaskGetTickCount() +{ + struct timeval tv; + struct timezone tz; + if (gettimeofday(&tv, &tz) == 0) { + return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); + } + return 0; +} + +/// Queue mock + QueueHandle_t xQueueCreate( uint32_t uxQueueLength, uint32_t uxItemSize ) + { + g_size = uxItemSize; + g_queue = malloc((uxQueueLength)*(uxItemSize)); + return g_queue; + } + + +void vQueueDelete( QueueHandle_t xQueue ) +{ + free(xQueue); +} + +uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait) +{ + if (g_queue_send_shall_fail) + { + return pdFALSE; + } + else + { + memcpy(xQueue, pvItemToQueue, g_size); + return pdPASS; + } +} + + +uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait) +{ + return pdFALSE; +} + +void GetLastItem(void *pvBuffer) +{ + memcpy(pvBuffer, g_queue, g_size); +} + +void ForceTaskDelete() +{ + g_queue_send_shall_fail = 1; +} diff --git a/components/mdns/test_afl_fuzz_host/esp32_mock.h b/components/mdns/test_afl_fuzz_host/esp32_mock.h new file mode 100644 index 0000000000..7246e29683 --- /dev/null +++ b/components/mdns/test_afl_fuzz_host/esp32_mock.h @@ -0,0 +1,45 @@ +#ifndef ESP32_MOCK_H_ +#define ESP32_MOCK_H_ + +typedef void (*esp_timer_cb_t)(void* arg); + +typedef enum +{ + ESP_TIMER_TASK, //!< Callback is called from timer task +} esp_timer_dispatch_t; + +typedef struct +{ + esp_timer_cb_t callback; //!< Function to call when timer expires + void* arg; //!< Argument to pass to the callback + esp_timer_dispatch_t dispatch_method; //!< Call the callback from task or from ISR + const char* name; //!< Timer name, used in esp_timer_dump function +} esp_timer_create_args_t; + +esp_err_t esp_timer_delete(esp_timer_handle_t timer); + +esp_err_t esp_timer_stop(esp_timer_handle_t timer); + +esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period); + +esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, + esp_timer_handle_t* out_handle); + + +// Queue mock + QueueHandle_t xQueueCreate( uint32_t uxQueueLength, + uint32_t uxItemSize ); + +void vQueueDelete( QueueHandle_t xQueue ); + +uint32_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait); + +uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait); + +void GetLastItem(void *pvBuffer); + +void ForceTaskDelete(); + +#define _mdns_udp_pcb_write(tcpip_if, ip_protocol, ip, port, data, len) len + +#endif /* ESP32_MOCK_H_ */ \ No newline at end of file diff --git a/components/mdns/test_afl_fuzz_host/mdns_di.h b/components/mdns/test_afl_fuzz_host/mdns_di.h new file mode 100644 index 0000000000..05aeb8bd54 --- /dev/null +++ b/components/mdns/test_afl_fuzz_host/mdns_di.h @@ -0,0 +1,53 @@ +/* + * MDNS Dependecy injection -- preincluded to inject interface test functions into static variables + * + */ + +#include "mdns.h" +#include "mdns_private.h" + +void (*mdns_test_static_execute_action)(mdns_action_t *) = NULL; +mdns_srv_item_t * (*mdns_test_static_mdns_get_service_item)(const char * service, const char * proto) = NULL; +mdns_search_once_t * (*mdns_test_static_search_init)(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results) = NULL; +esp_err_t (*mdns_test_static_send_search_action)(mdns_action_type_t type, mdns_search_once_t * search) = NULL; +void (*mdns_test_static_search_free)(mdns_search_once_t * search) = NULL; + +static void _mdns_execute_action(mdns_action_t * action); +static mdns_srv_item_t * _mdns_get_service_item(const char * service, const char * proto); +static mdns_search_once_t * _mdns_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results); +static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t * search); +static void _mdns_search_free(mdns_search_once_t * search); + +void mdns_test_init_di() +{ + mdns_test_static_execute_action = _mdns_execute_action; + mdns_test_static_mdns_get_service_item = _mdns_get_service_item; + mdns_test_static_search_init = _mdns_search_init; + mdns_test_static_send_search_action = _mdns_send_search_action; + mdns_test_static_search_free = _mdns_search_free; +} + +void mdns_test_execute_action(void * action) +{ + mdns_test_static_execute_action((mdns_action_t *)action); +} + +void mdns_test_search_free(mdns_search_once_t * search) +{ + return mdns_test_static_search_free(search); +} + +esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once_t * search) +{ + return mdns_test_static_send_search_action(type, search); +} + +mdns_search_once_t * mdns_test_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results) +{ + return mdns_test_static_search_init(name, service, proto, type, timeout, max_results); +} + +mdns_srv_item_t * mdns_test_mdns_get_service_item(const char * service, const char * proto) +{ + return mdns_test_static_mdns_get_service_item(service, proto); +} \ No newline at end of file diff --git a/components/mdns/test_afl_fuzz_host/test.c b/components/mdns/test_afl_fuzz_host/test.c index be06ac0bfe..8ea72d95c1 100644 --- a/components/mdns/test_afl_fuzz_host/test.c +++ b/components/mdns/test_afl_fuzz_host/test.c @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifdef MDNS_TEST_MODE - #include #include #include @@ -21,93 +19,210 @@ #include #include "mdns.h" +#include "mdns_private.h" -void mdns_parse_packet(mdns_server_t * server, const uint8_t * data, size_t len); +// +// Global stuctures containing packet payload, search +mdns_rx_packet_t g_packet; +struct pbuf mypbuf; +mdns_search_once_t * search = NULL; +// +// Dependency injected test functions +void mdns_test_execute_action(void * action); +mdns_srv_item_t * mdns_test_mdns_get_service_item(const char * service, const char * proto); +mdns_search_once_t * mdns_test_search_init(const char * name, const char * service, const char * proto, uint16_t type, uint32_t timeout, uint8_t max_results); +esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once_t * search); +void mdns_test_search_free(mdns_search_once_t * search); +void mdns_test_init_di(); + +// +// mdns function wrappers for mdns setup in test mode +static int mdns_test_hostname_set(const char * mdns_hostname) +{ + int ret = mdns_hostname_set(mdns_hostname); + mdns_action_t * a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + return ret; +} + +static int mdns_test_service_instance_name_set(const char * service, const char * proto, const char * instance) +{ + int ret = mdns_service_instance_name_set(service, proto, instance); + mdns_action_t * a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + return ret; +} + +static int mdns_test_service_txt_set(const char * service, const char * proto, uint8_t num_items, mdns_txt_item_t txt[]) +{ + int ret = mdns_service_txt_set(service, proto, txt, num_items); + mdns_action_t * a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + return ret; +} + +static int mdns_test_service_add(const char * service_name, const char * proto, uint32_t port) +{ + if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) { + // This is expected failure as the service thread is not running + } + mdns_action_t * a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + + if (mdns_test_mdns_get_service_item(service_name, proto)==NULL) { + return ESP_FAIL; + } + return ESP_OK; +} + +static mdns_result_t* mdns_test_query(const char * service_name, const char * proto) +{ + search = mdns_test_search_init(NULL, service_name, proto, MDNS_TYPE_PTR, 3000, 20); + if (!search) { + abort(); + } + + if (mdns_test_send_search_action(ACTION_SEARCH_ADD, search)) { + mdns_test_search_free(search); + abort(); + } + + mdns_action_t * a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + return NULL; +} + +static void mdns_test_query_free() +{ + mdns_test_search_free(search); +} + +// +// function "under test" where afl-mangled packets passed +// +void mdns_parse_packet(mdns_rx_packet_t * packet); + +// +// Test starts here +// int main(int argc, char** argv) { + int i; const char * mdns_hostname = "minifritz"; const char * mdns_instance = "Hristo's Time Capsule"; - const char * arduTxtData[4] = { - "board=esp32", - "tcp_check=no", - "ssh_upload=no", - "auth_upload=no" + mdns_txt_item_t arduTxtData[4] = { + {"board","esp32"}, + {"tcp_check","no"}, + {"ssh_upload","no"}, + {"auth_upload","no"} }; + const uint8_t mac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x32}; - mdns_server_t * mdns = NULL; uint8_t buf[1460]; char winstance[21+strlen(mdns_hostname)]; sprintf(winstance, "%s [%02x:%02x:%02x:%02x:%02x:%02x]", mdns_hostname, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - if (mdns_init(TCPIP_ADAPTER_IF_ETH, &mdns)) { + // Init depencency injected methods + mdns_test_init_di(); + + if (mdns_init()) { abort(); } - if (mdns_set_hostname(mdns, mdns_hostname)) { + if (mdns_test_hostname_set(mdns_hostname)) { abort(); } - if (mdns_set_instance(mdns, mdns_instance)) { + if (mdns_test_service_add("_workstation", "_tcp", 9)) { + abort(); + } + if (mdns_test_service_instance_name_set("_workstation", "_tcp", winstance)) { abort(); } - if (mdns_service_add(mdns, "_workstation", "_tcp", 9)) { + if (mdns_test_service_add("_arduino", "_tcp", 3232)) { abort(); } - if (mdns_service_instance_set(mdns, "_workstation", "_tcp", winstance)) { + if (mdns_test_service_txt_set("_arduino", "_tcp", 4, arduTxtData)) { abort(); } - if (mdns_service_add(mdns, "_arduino", "_tcp", 3232)) { + if (mdns_test_service_add("_http", "_tcp", 80)) { abort(); } - if (mdns_service_txt_set(mdns, "_arduino", "_tcp", 4, arduTxtData)) { - abort(); - } - - if (mdns_service_add(mdns, "_http", "_tcp", 80)) { - abort(); - } - - if (mdns_service_instance_set(mdns, "_http", "_tcp", "ESP WebServer")) { + if (mdns_test_service_instance_name_set("_http", "_tcp", "ESP WebServer")) { abort(); } if ( - mdns_service_add(mdns, "_afpovertcp", "_tcp", 548) - || mdns_service_add(mdns, "_rfb", "_tcp", 885) - || mdns_service_add(mdns, "_smb", "_tcp", 885) - || mdns_service_add(mdns, "_adisk", "_tcp", 885) - || mdns_service_add(mdns, "_airport", "_tcp", 885) - || mdns_service_add(mdns, "_printer", "_tcp", 885) - || mdns_service_add(mdns, "_airplay", "_tcp", 885) - || mdns_service_add(mdns, "_raop", "_tcp", 885) - || mdns_service_add(mdns, "_uscan", "_tcp", 885) - || mdns_service_add(mdns, "_uscans", "_tcp", 885) - || mdns_service_add(mdns, "_ippusb", "_tcp", 885) - || mdns_service_add(mdns, "_scanner", "_tcp", 885) - || mdns_service_add(mdns, "_ipp", "_tcp", 885) - || mdns_service_add(mdns, "_ipps", "_tcp", 885) - || mdns_service_add(mdns, "_pdl-datastream", "_tcp", 885) - || mdns_service_add(mdns, "_ptp", "_tcp", 885) - || mdns_service_add(mdns, "_sleep-proxy", "_udp", 885)) + mdns_test_service_add("_afpovertcp", "_tcp", 548) + || mdns_test_service_add("_rfb", "_tcp", 885) + || mdns_test_service_add("_smb", "_tcp", 885) + || mdns_test_service_add("_adisk", "_tcp", 885) + || mdns_test_service_add("_airport", "_tcp", 885) + || mdns_test_service_add("_printer", "_tcp", 885) + || mdns_test_service_add("_airplay", "_tcp", 885) + || mdns_test_service_add("_raop", "_tcp", 885) + || mdns_test_service_add("_uscan", "_tcp", 885) + || mdns_test_service_add("_uscans", "_tcp", 885) + || mdns_test_service_add("_ippusb", "_tcp", 885) + || mdns_test_service_add("_scanner", "_tcp", 885) + || mdns_test_service_add("_ipp", "_tcp", 885) + || mdns_test_service_add("_ipps", "_tcp", 885) + || mdns_test_service_add("_pdl-datastream", "_tcp", 885) + || mdns_test_service_add("_ptp", "_tcp", 885) + || mdns_test_service_add("_sleep-proxy", "_udp", 885)) { - abort(); + abort(); + } + + mdns_result_t * results = NULL; + FILE *file; + size_t nread; + +#ifdef INSTR_IS_OFF + size_t len = 1460; + memset(buf, 0, 1460); + + if (argc != 2) + { + printf("Non-instrumentation mode: please supply a file name created by AFL to reproduce crash\n"); + return 1; + } + else + { + // + // Note: parameter1 is a file (mangled packet) which caused the crash + file = fopen(argv[1], "r"); + if (file) { + len = fread(buf, 1, 1460, file); + } + fclose(file); } + for (i=0; i<1; i++) { +#else while (__AFL_LOOP(1000)) { memset(buf, 0, 1460); size_t len = read(0, buf, 1460); - mdns_query(mdns, "_afpovertcp", "_tcp", 0); - mdns_parse_packet(mdns, buf, len); - mdns_query_end(mdns); +#endif + mypbuf.payload = buf; + mypbuf.len = len; + g_packet.pb = &mypbuf; + mdns_test_query("_afpovertcp", "_tcp"); + mdns_parse_packet(&g_packet); } + ForceTaskDelete(); + mdns_free(); return 0; } - -#endif From fffbf7b75065b5852e064e04b0c5102dd0fc2244 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 22 May 2018 11:10:27 +0200 Subject: [PATCH 161/187] Fixed nullptr dereference in MDNS.c --- components/mdns/mdns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/mdns/mdns.c b/components/mdns/mdns.c index 73c5f99c9f..8ead7c44d5 100644 --- a/components/mdns/mdns.c +++ b/components/mdns/mdns.c @@ -2269,7 +2269,7 @@ static bool _mdns_question_matches(mdns_parsed_question_t * question, uint16_t t } } else if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { const char * name = _mdns_get_service_instance_name(service->service); - if (name && !strcasecmp(name, question->host) + if (name && question->host && !strcasecmp(name, question->host) && !strcasecmp(service->service->service, question->service) && !strcasecmp(service->service->proto, question->proto) && !strcasecmp(MDNS_DEFAULT_DOMAIN, question->domain)) { From 04c74efedd62ef50beddca7e1050beba9d21f419 Mon Sep 17 00:00:00 2001 From: Liu Zhi Fu Date: Tue, 15 May 2018 11:59:32 +0800 Subject: [PATCH 162/187] esp32: add multiple antenna 1. Support multiple antenna support 2. libphy.a is updated to v3910 --- components/esp32/include/esp_wifi.h | 49 ++++++++++++++++++++ components/esp32/include/esp_wifi_types.h | 53 +++++++++++++++++++++- components/esp32/lib | 2 +- docs/en/api-guides/wifi.rst | 55 +++++++++++++++++++++++ 4 files changed, 157 insertions(+), 2 deletions(-) diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h index bacfb13c67..02bf87e3da 100755 --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -1025,6 +1025,55 @@ esp_err_t esp_wifi_set_csi_config(const wifi_csi_config_t *config); */ esp_err_t esp_wifi_set_csi(bool en); +/** + * @brief Set antenna GPIO configuration + * + * @param config Antenna GPIO configuration. + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + * - ESP_ERR_WIFI_ARG: Invalid argument, e.g. parameter is NULL, invalid GPIO number etc + */ +esp_err_t esp_wifi_set_ant_gpio(const wifi_ant_gpio_config_t *config); + +/** + * @brief Get current antenna GPIO configuration + * + * @param config Antenna GPIO configuration. + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument, e.g. parameter is NULL + */ +esp_err_t esp_wifi_get_ant_gpio(wifi_ant_gpio_config_t *config); + + +/** + * @brief Set antenna configuration + * + * @param config Antenna configuration. + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + * - ESP_ERR_WIFI_ARG: Invalid argument, e.g. parameter is NULL, invalid antenna mode or invalid GPIO number + */ +esp_err_t esp_wifi_set_ant(const wifi_ant_config_t *config); + +/** + * @brief Get current antenna configuration + * + * @param config Antenna configuration. + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + * - ESP_ERR_WIFI_ARG: invalid argument, e.g. parameter is NULL + */ +esp_err_t esp_wifi_get_ant(wifi_ant_config_t *config); + #ifdef __cplusplus } #endif diff --git a/components/esp32/include/esp_wifi_types.h b/components/esp32/include/esp_wifi_types.h index be4a68c289..97757f0b8a 100755 --- a/components/esp32/include/esp_wifi_types.h +++ b/components/esp32/include/esp_wifi_types.h @@ -140,7 +140,17 @@ typedef enum { WIFI_CIPHER_TYPE_UNKNOWN, /**< the cipher type is unknown */ } wifi_cipher_type_t; -/** @brief Description of an WiFi AP */ +/** + * @brief WiFi antenna + * + */ +typedef enum { + WIFI_ANT_ANT0, /**< WiFi antenna 0 */ + WIFI_ANT_ANT1, /**< WiFi antenna 1 */ + WIFI_ANT_MAX, /**< Invalid WiFi antenna */ +} wifi_ant_t; + +/** @brief Description of a WiFi AP */ typedef struct { uint8_t bssid[6]; /**< MAC address of AP */ uint8_t ssid[33]; /**< SSID of AP */ @@ -150,6 +160,7 @@ typedef struct { wifi_auth_mode_t authmode; /**< authmode of AP */ wifi_cipher_type_t pairwise_cipher; /**< pairwise cipher of AP */ wifi_cipher_type_t group_cipher; /**< group cipher of AP */ + wifi_ant_t ant; /**< antenna used to receive beacon from AP */ uint32_t phy_11b:1; /**< bit: 0 flag to identify if 11b mode is enabled or not */ uint32_t phy_11g:1; /**< bit: 1 flag to identify if 11g mode is enabled or not */ uint32_t phy_11n:1; /**< bit: 2 flag to identify if 11n mode is enabled or not */ @@ -395,6 +406,46 @@ typedef struct { uint16_t len; /**< length of CSI data */ } wifi_csi_info_t; +/** + * @brief WiFi GPIO configuration for antenna selection + * + */ +typedef struct { + uint8_t gpio_select: 1, /**< Whether this GPIO is connected to external antenna switch */ + gpio_num: 7; /**< The GPIO number that connects to external antenna switch */ +} wifi_ant_gpio_t; + +/** + * @brief WiFi GPIOs configuration for antenna selection + * + */ +typedef struct { + wifi_ant_gpio_t gpio_cfg[4]; /**< The configurations of GPIOs that connect to external antenna switch */ +} wifi_ant_gpio_config_t; + +/** + * @brief WiFi antenna mode + * + */ +typedef enum { + WIFI_ANT_MODE_ANT0, /**< Enable WiFi antenna 0 only */ + WIFI_ANT_MODE_ANT1, /**< Enable WiFi antenna 1 only */ + WIFI_ANT_MODE_AUTO, /**< Enable WiFi antenna 0 and 1, automatically select an antenna */ + WIFI_ANT_MODE_MAX, /**< Invalid WiFi enabled antenna */ +} wifi_ant_mode_t; + +/** + * @brief WiFi antenna configuration + * + */ +typedef struct { + wifi_ant_mode_t rx_ant_mode; /**< WiFi antenna mode for receiving */ + wifi_ant_t rx_ant_default; /**< Default antenna mode for receiving, it's ignored if rx_ant_mode is not WIFI_ANT_MODE_AUTO */ + wifi_ant_mode_t tx_ant_mode; /**< WiFi antenna mode for transmission, it can be set to WIFI_ANT_MODE_AUTO only if rx_ant_mode is set to WIFI_ANT_MODE_AUTO */ + uint8_t enabled_ant0: 4, /**< Index (in antenna GPIO configuration) of enabled WIFI_ANT_MODE_ANT0 */ + enabled_ant1: 4; /**< Index (in antenna GPIO configuration) of enabled WIFI_ANT_MODE_ANT1 */ +} wifi_ant_config_t; + #ifdef __cplusplus } #endif diff --git a/components/esp32/lib b/components/esp32/lib index 8b2f4de9d7..963fb2baa4 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 8b2f4de9d779f72829a6ce54be2b7b5f1d9add09 +Subproject commit 963fb2baa4bf6320a89674ef1ba1de6f15ddd06d diff --git a/docs/en/api-guides/wifi.rst b/docs/en/api-guides/wifi.rst index 8afdf88aa3..aefbb39302 100755 --- a/docs/en/api-guides/wifi.rst +++ b/docs/en/api-guides/wifi.rst @@ -1420,6 +1420,61 @@ The Wi-Fi sniffer mode can be enabled in the Wi-Fi mode of WIFI_MODE_NULL, or WI Another noteworthy issue about the sniffer is the callback wifi_promiscuous_cb_t. The callback will be called directly in the Wi-Fi driver task, so if the application has a lot of work to do for each filtered packet, the recommendation is to post an event to the application task in the callback and defer the real work to the application task. +Wi-Fi Multiple Antennas +-------------------------- +The Wi-Fi multiple antennas selecting can be depicted as following picture:: + + __________ + |Enabled | + ___|Antenna 0 |\\ _________ + |__________| \\ GPIO[0] <----> antenna_select[0] ---| | --- antenna 0 + RX/TX ___ \\____\ GPIO[1] <----> antenna_select[1] ---| Antenna | --- antenna 1 + \ __________ // / GPIO[2] <----> antenna_select[2] ---| Switch | ... ... + \ ___|Enabled | // GPIO[3] <----> antenna_select[3] ---|_________| --- antenna 15 + \ |Antenna 1 |// + |__________| + + +ESP32 supports up to sixteen antennas through external antenna switch. The antenna switch can be controlled by up to four address pins - antenna_select[0:3]. Different input value of antenna_select[0:3] means selecting different antenna. E.g. the value '0b1011' means the antenna 11 is selected. The default value of antenna_select[3:0] is '0b0000', it means the antenna 0 is selected by default. + +Up to four GPIOs are connected to the four active high antenna_select pins. ESP32 can select the antenna by control the GPIO[0:3]. The API :cpp:func:`esp_wifi_set_ant_gpio()` is used to configure which GPIOs are connected to antenna_selects. If GPIO[x] is connected to antenna_select[x], then gpio_config->gpio_cfg[x].gpio_select should be set to 1 and gpio_config->gpio_cfg[x].gpio_num should be provided. + +Although up to sixteen anteenas are supported, only one or two antennas can be simultaneously enabled for RX/TX. The API :cpp:func:`esp_wifi_set_ant()` is used to configure which antennas are enabled. + +The enabled antennas selecting algorithm is also configured by :cpp:func:`esp_wifi_set_ant()`. The RX/TX antenna mode can be WIFI_ANT_MODE_ANT0, WIFI_ANT_MODE_ANT1 or WIFI_ANT_MODE_AUTO. If the antenna mode is WIFI_ANT_MODE_ANT0, the enabled antenna 0 is selected for RX/TX data. If the antenna mode is WIFI_ANT_MODE_ANT1, the enabled antenna 1 is selected for RX/TX data. Otherwise, WiFi automatically selects the antenna that has better signal from the enabled antennas. + +If the RX antenna mode is WIFI_ANT_MODE_AUTO, the default antenna mode also needs to be set. Because the RX antenna switching only happens when some conditions are met, e.g. the RX antenna starts to switch if the RSSI is lower than -65dBm and if another antenna has better signal etc, RX uses the default antenna if the conditions are not met. If the default antenna mode is WIFI_ANT_MODE_ANT1, the enabled antenna 1 is used as the default RX antenna, otherwise the enabled antenna 0 is used as the default RX antenna. + +Some limitations need to be considered: + - The TX antenna can be set to WIFI_ANT_MODE_AUTO only if the RX antenna mode is WIFI_ANT_MODE_AUTO because TX antenna selecting algorithm is based on RX antenna in WIFI_ANT_MODE_AUTO type. + - Currently BT doesn't support the multiple antennas feature, please don't use multiple antennas related APIs. + +Following is the recommended scenarios to use the multiple antennas: + - In Wi-Fi mode WIFI_MODE_STA, both RX/TX antenna modes are configured to WIFI_ANT_MODE_AUTO. The WiFi driver selects the better RX/TX antenna automatically. + - The RX antenna mode is configured to WIFI_ANT_MODE_AUTO. The TX antenna mode is configured to WIFI_ANT_MODE_ANT0 or WIFI_ANT_MODE_ANT1. The applications can choose to always select a specified antenna for TX, or implement their own TX antenna selecting algorithm, e.g. selecting the TX antenna mode based on the channel switch information etc. + - Both RX/TX antenna modes are configured to WIFI_ANT_MODE_ANT0 or WIFI_ANT_MODE_ANT1. + + +Wi-Fi Multiple Antennas Configuration ++++++++++++++++++++++++++++++++++++++ + +Generally, following steps can be taken to configure the multiple antennas: + - Configure which GPIOs are connected to the antenna_selects, for example, if four antennas are supported and GPIO20/GPIO21 are connected to antenna_select[0]/antenna_select[1], the configurations look like:: + + wifi_ant_gpio_config_t config = { + { .gpio_select = 1, .gpio_num = 20 }, + { .gpio_select = 1, .gpio_num = 21 } + }; + - Configure which antennas are enabled and how RX/TX use the enabled antennas, for example, if antenna1 and antenna3 are enabled, the RX needs to select the better antenna automatically and uses antenna1 as its default antenna, the TX always selects the antenna3. The configuration looks like:: + + wifi_ant_config_t config = { + .rx_ant_mode = WIFI_ANT_MODE_AUTO, + .rx_ant_default = WIFI_ANT_ANT0, + .tx_ant_mode = WIFI_ANT_MODE_ANT1, + .enabled_ant0 = 1, + .enabled_ant1 = 3 + }; + Wi-Fi Buffer Usage -------------------------- From 3fd199c54a37c0152d14e080cd53e5ff9b9a544c Mon Sep 17 00:00:00 2001 From: Alexey Gerenkov Date: Tue, 22 May 2018 16:45:07 +0300 Subject: [PATCH 163/187] docs: Makes core dump's documentation slightly clearer Merges https://github.com/espressif/esp-idf/pull/1968 --- docs/en/api-guides/core_dump.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/en/api-guides/core_dump.rst b/docs/en/api-guides/core_dump.rst index 47cfd89c07..84eec82976 100644 --- a/docs/en/api-guides/core_dump.rst +++ b/docs/en/api-guides/core_dump.rst @@ -63,6 +63,8 @@ Base64-encoded body of core dump will be between the following header and footer ================= CORE DUMP END =================== +The `CORE DUMP START` and `CORE DUMP END` lines must not be included in core dump text file. + Running 'espcoredump.py' ------------------------------------ From 004bf84d8c1f6b46b28e3f105995d82f9f1733e6 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Wed, 23 May 2018 08:25:46 +0200 Subject: [PATCH 164/187] VFS: Optionally disable the VFS implementation of select() This allows to temporarily resolve issues like https://github.com/espressif/esp-idf/issues/1987 while bugs are fixed in the VFS implementation of select(). --- components/lwip/Kconfig | 10 ++++++++++ components/newlib/select.c | 9 +++++++++ components/vfs/README.rst | 4 ++++ 3 files changed, 23 insertions(+) diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig index c24910e368..efd053b5f2 100755 --- a/components/lwip/Kconfig +++ b/components/lwip/Kconfig @@ -37,6 +37,16 @@ config LWIP_MAX_SOCKETS the maximum amount of sockets here. The valid value is from 1 to 16. +config USE_ONLY_LWIP_SELECT + bool "Support LWIP socket select() only" + default n + help + The virtual filesystem layer of select() redirects sockets to + lwip_select() and non-socket file descriptors to their respective driver + implementations. If this option is enabled then all calls of select() + will be redirected to lwip_select(), therefore, select can be used + for sockets only. + config LWIP_SO_REUSE bool "Enable SO_REUSEADDR option" default y diff --git a/components/newlib/select.c b/components/newlib/select.c index dc945eafb4..e802a4d329 100644 --- a/components/newlib/select.c +++ b/components/newlib/select.c @@ -14,8 +14,17 @@ #include #include "esp_vfs.h" +#include "sdkconfig.h" + +#ifdef CONFIG_USE_ONLY_LWIP_SELECT +#include "lwip/sockets.h" +#endif int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout) { +#ifdef CONFIG_USE_ONLY_LWIP_SELECT + return lwip_select(nfds, readfds, writefds, errorfds, timeout); +#else return esp_vfs_select(nfds, readfds, writefds, errorfds, timeout); +#endif } diff --git a/components/vfs/README.rst b/components/vfs/README.rst index 4644689a93..36af5c388c 100644 --- a/components/vfs/README.rst +++ b/components/vfs/README.rst @@ -93,6 +93,10 @@ Examples demonstrating the use of :cpp:func:`select` with VFS file descriptors are the :example:`peripherals/uart_select` and the :example:`system/select` examples. +If :cpp:func:`select` is used for socket file descriptors only then one can +enable the :ref:`CONFIG_USE_ONLY_LWIP_SELECT` option which can reduce the code +size and improve performance. + Paths ----- From feaa6e8a8fea2e8e473cbf02269027507bf771cb Mon Sep 17 00:00:00 2001 From: qiyueixa Date: Mon, 21 May 2018 17:22:04 +0800 Subject: [PATCH 165/187] mesh: add manual networking function 1. add mesh_assoc_t to esp_mesh_internal.h file. 2. rename "node" to "device" in esp_mesh.h. 3. add MESH_EVENT_SCAN_DONE event. 4. add APIs esp_mesh_scan_get_ap_record() and esp_mesh_scan_get_ap_ie_len() to get scan results. 5. modify API esp_mesh_set_self_organized() by adding parameter "select_parent". 6. modify API esp_mesh_set_parent() by adding parameter "parent_mesh_id" 7. add manual networking example. --- components/esp32/include/esp_mesh.h | 197 +++++++---- components/esp32/include/esp_mesh_internal.h | 40 +++ components/esp32/lib | 2 +- examples/mesh/manual_networking/Makefile | 9 + .../manual_networking/main/Kconfig.projbuild | 80 +++++ .../mesh/manual_networking/main/component.mk | 4 + .../main/include/mesh_light.h | 57 +++ .../mesh/manual_networking/main/mesh_light.c | 180 ++++++++++ .../mesh/manual_networking/main/mesh_main.c | 327 ++++++++++++++++++ 9 files changed, 821 insertions(+), 75 deletions(-) create mode 100644 examples/mesh/manual_networking/Makefile create mode 100644 examples/mesh/manual_networking/main/Kconfig.projbuild create mode 100644 examples/mesh/manual_networking/main/component.mk create mode 100644 examples/mesh/manual_networking/main/include/mesh_light.h create mode 100644 examples/mesh/manual_networking/main/mesh_light.c create mode 100644 examples/mesh/manual_networking/main/mesh_main.c diff --git a/components/esp32/include/esp_mesh.h b/components/esp32/include/esp_mesh.h index b504149e13..14bd21f7ea 100644 --- a/components/esp32/include/esp_mesh.h +++ b/components/esp32/include/esp_mesh.h @@ -68,7 +68,7 @@ * * In present implementation, applications are able to access mesh stack directly without having to go through LwIP stack. * Applications use esp_mesh_send() and esp_mesh_recv() to send and receive messages over the mesh network. - * In mesh stack design, normal nodes don't require LwIP stack. But since IDF hasn't supported system without initializing LwIP stack yet, + * In mesh stack design, normal devices don't require LwIP stack. But since IDF hasn't supported system without initializing LwIP stack yet, * applications still need to do LwIP initialization and two more things are required to be done * (1)stop DHCP server on softAP interface by default * (2)stop DHCP client on station interface by default. @@ -78,7 +78,7 @@ * tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); * * Over the mesh network, only root is able to access external IP network. - * In application mesh event handler, once a node becomes a root, start DHCP client immediately if DHCP is chosen. + * In application mesh event handler, once a device becomes a root, start DHCP client immediately if DHCP is chosen. */ #ifndef __ESP_MESH_H__ @@ -142,6 +142,14 @@ extern "C" { #define MESH_OPT_SEND_GROUP (7) /**< data transmission by group; used with esp_mesh_send() and shall have payload */ #define MESH_OPT_RECV_DS_ADDR (8) /**< return a remote IP address; used with esp_mesh_send() and esp_mesh_recv() */ +/** + * @brief flag of mesh networking IE + */ +#define MESH_ASSOC_FLAG_VOTE_IN_PROGRESS (0x02) /**< vote in progress */ +#define MESH_ASSOC_FLAG_NETWORK_FREE (0x08) /**< no root in current network */ +#define MESH_ASSOC_FLAG_ROOTS_FOUND (0x20) /**< root conflict is found */ +#define MESH_ASSOC_FLAG_ROOT_FIXED (0x40) /**< root is fixed */ + /******************************************************* * Enumerations *******************************************************/ @@ -172,19 +180,21 @@ typedef enum { and this device is specified to be a root by users, users should set a new parent for this device. if self organized is enabled, this device will find a new parent by itself, users could ignore this event. */ - MESH_EVENT_ROOT_FIXED, /**< When nodes join a network, if the setting of Root Fixed for one node is different - from that of its parent, the node will update the setting the same as its parent's. - Root Fixed setting of each node is variable as that setting changes of root. */ + MESH_EVENT_ROOT_FIXED, /**< when devices join a network, if the setting of Fixed Root for one device is different + from that of its parent, the device will update the setting the same as its parent's. + Fixed Root setting of each device is variable as that setting changes of root. */ + MESH_EVENT_SCAN_DONE, /**< if self-organized networking is disabled, user can call esp_wifi_scan_start() to trigger + this event, and add the corresponding scan done handler in this event. */ MESH_EVENT_MAX, } mesh_event_id_t; /** - * @brief node type + * @brief device type */ typedef enum { MESH_IDLE, /**< hasn't joined the mesh network yet */ MESH_ROOT, /**< the only sink of the mesh network. Has the ability to access external IP network */ - MESH_NODE, /**< intermediate node. Has the ability to forward packets over the mesh network */ + MESH_NODE, /**< intermediate device. Has the ability to forward packets over the mesh network */ MESH_LEAF, /**< has no forwarding ability */ } mesh_type_t; @@ -221,7 +231,7 @@ typedef enum { typedef enum { MESH_REASON_CYCLIC = 100, /**< cyclic is detected */ MESH_REASON_PARENT_IDLE, /**< parent is idle */ - MESH_REASON_LEAF, /**< the connected node is changed to a leaf */ + MESH_REASON_LEAF, /**< the connected device is changed to a leaf */ MESH_REASON_DIFF_ID, /**< in different mesh ID */ MESH_REASON_ROOTS, /**< root conflict is detected */ MESH_REASON_PARENT_STOPPED, /**< parent has stopped the mesh */ @@ -331,7 +341,7 @@ typedef struct { */ typedef struct { int8_t rssi; /**< rssi with router */ - uint16_t capacity; /**< the number of nodes in its network */ + uint16_t capacity; /**< the number of devices in current network */ uint8_t addr[6]; /**< other powerful root address */ } mesh_event_root_conflict_t; @@ -350,6 +360,13 @@ typedef struct { bool is_fixed; /**< status */ } mesh_event_root_fixed_t; +/** + * @brief scan done event information + */ +typedef struct { + uint8_t number; /**< the number of scanned APs */ +} mesh_event_scan_done_t; + /** * @brief mesh event information */ @@ -362,16 +379,17 @@ typedef union { mesh_event_disconnected_t disconnected; /**< parent disconnected */ mesh_event_no_parent_found_t no_parent; /**< no parent found */ mesh_event_layer_change_t layer_change; /**< layer change */ - mesh_event_toDS_state_t toDS_state; /**< toDS state, nodes should check this state firstly before trying to send packets to - external IP network. This state indicates right now if root is capable - of sending packets out. If not, nodes had better to wait until this state changes - to be MESH_TODS_REACHABLE. */ + mesh_event_toDS_state_t toDS_state; /**< toDS state, devices shall check this state firstly before trying to send packets to + external IP network. This state indicates right now if root is capable of sending + packets out. If not, devices had better to wait until this state changes to be + MESH_TODS_REACHABLE. */ mesh_event_vote_started_t vote_started; /**< vote started */ mesh_event_root_got_ip_t got_ip; /**< root obtains IP address */ mesh_event_root_address_t root_addr; /**< root address */ mesh_event_root_switch_req_t switch_req; /**< root switch request */ mesh_event_root_conflict_t root_conflict; /**< other powerful root */ mesh_event_root_fixed_t root_fixed; /**< root fixed */ + mesh_event_scan_done_t scan_done; /**< scan done */ } mesh_event_info_t; /** @@ -497,7 +515,7 @@ extern mesh_event_cb_t g_mesh_event_cb; * Check if WiFi is started. * Initialize mesh global variables with default values. * - * @attention This API should be called after WiFi is started. + * @attention This API shall be called after WiFi is started. * * @return * - ESP_OK @@ -522,7 +540,7 @@ esp_err_t esp_mesh_deinit(void); * Create TX and RX queues according to the configuration * Register mesh packets receive callback * - * @attention This API should be called after esp_mesh_init() and esp_mesh_set_config(). + * @attention This API shall be called after esp_mesh_init() and esp_mesh_set_config(). * * @return * - ESP_OK @@ -552,7 +570,7 @@ esp_err_t esp_mesh_stop(void); /** * @brief send a packet over the mesh network - * Send a packet to any node in the mesh network. + * Send a packet to any device in the mesh network. * Send a packet to external IP network. * * @attention This API is not reentrant. @@ -566,9 +584,9 @@ esp_err_t esp_mesh_stop(void); * Should specify the transmission tos(type of service), P2P reliable by default. * @param flag * (1)used to speed up the route selection - * if the packet is target to an internal node, MESH_DATA_P2P should be set. + * if the packet is target to an internal device, MESH_DATA_P2P should be set. * if the packet is outgoing to root or to external IP network, MESH_DATA_TODS should be set. - * if the packet is from root to an internal node, MESH_DATA_FROMDS should be set. + * if the packet is from root to an internal device, MESH_DATA_FROMDS should be set. * (2)specify if this API is block or non-block, block by default * if needs non-block, MESH_DATA_NONBLOCK should be set. * (3)in the situation of root having been changed, MESH_DATA_DROP identifies this packet can be dropped by new root @@ -581,7 +599,7 @@ esp_err_t esp_mesh_stop(void); * @param opt options * (1)in case of sending a packet to a specified group, MESH_OPT_SEND_GROUP is a good choice. * In this option, the value field should specify the target receiver addresses in this group. - * (2)root sends a packet to an internal node, this packet is from external IP network in case the receiver node responds + * (2)root sends a packet to an internal device, this packet is from external IP network in case the receiver device responds * this packet, MESH_OPT_RECV_DS_ADDR is required to attach the target DS address. * @param opt_count option count * Currently, this API only takes one option, so opt_count is only supported to be 1. @@ -601,7 +619,7 @@ esp_err_t esp_mesh_stop(void); * - ESP_ERR_MESH_DISCARD */ esp_err_t esp_mesh_send(const mesh_addr_t *to, const mesh_data_t *data, - const int flag, const mesh_opt_t opt[], const int opt_count); + int flag, const mesh_opt_t opt[], int opt_count); /** * @brief receive a packet targeted to self over the mesh network @@ -679,10 +697,10 @@ esp_err_t esp_mesh_recv_toDS(mesh_addr_t *from, mesh_addr_t *to, * Root conflict function could eliminate redundant roots connected with the same BSSID, but couldn't handle roots * connected with different BSSID. Because users might have such requirements of setting up routers with same SSID * for the future replacement. But in that case, if the above situations happen, please make sure applications - * implement forward functions on root to guarantee nodes in different mesh network could communicate with each other. + * implement forward functions on root to guarantee devices in different mesh network can communicate with each other. * max_connection of mesh softAP is limited by the max number of WiFi softAP supported(max:10). * - * @attention This API should be called between esp_mesh_init() and esp_mesh_start(). + * @attention This API shall be called between esp_mesh_init() and esp_mesh_start(). * * @param config pointer to mesh stack configuration * @@ -707,7 +725,7 @@ esp_err_t esp_mesh_get_config(mesh_cfg_t *config); /** * @brief set router configuration * - * @attention This API should be called between esp_mesh_init() and esp_mesh_start(). + * @attention This API shall be called between esp_mesh_init() and esp_mesh_start(). * * @param router pointer to router configuration * @@ -731,7 +749,7 @@ esp_err_t esp_mesh_get_router(mesh_router_t *router); /** * @brief set mesh network ID * - * @attention This API should be called between esp_mesh_init() and esp_mesh_start(). + * @attention This API could be called either before esp_mesh_start() or after esp_mesh_start(). * * @param id pointer to mesh network ID * @@ -753,20 +771,20 @@ esp_err_t esp_mesh_set_id(const mesh_addr_t *id); esp_err_t esp_mesh_get_id(mesh_addr_t *id); /** - * @brief set node type over the mesh network(Unimplemented) + * @brief set device type over the mesh network(Unimplemented) * - * @param type node type + * @param type device type * * @return * - ESP_OK * - ESP_ERR_MESH_NOT_ALLOWED */ -esp_err_t esp_mesh_set_type(const mesh_type_t type); +esp_err_t esp_mesh_set_type(mesh_type_t type); /** - * @brief get node type over mesh network + * @brief get device type over mesh network * - * @attention This API should be called after having received the event MESH_EVENT_PARENT_CONNECTED. + * @attention This API shall be called after having received the event MESH_EVENT_PARENT_CONNECTED. * * @return mesh type * @@ -776,7 +794,7 @@ mesh_type_t esp_mesh_get_type(void); /** * @brief set max layer configuration(max:15, default:15) * - * @attention This API should be called before esp_mesh_start(). + * @attention This API shall be called before esp_mesh_start(). * * @param max_layer max layer value * @@ -785,7 +803,7 @@ mesh_type_t esp_mesh_get_type(void); * - ESP_ERR_MESH_ARGUMENT * - ESP_ERR_MESH_NOT_ALLOWED */ -esp_err_t esp_mesh_set_max_layer(const int max_layer); +esp_err_t esp_mesh_set_max_layer(int max_layer); /** * @brief get max layer configuration @@ -797,7 +815,7 @@ int esp_mesh_get_max_layer(void); /** * @brief set mesh softAP password * - * @attention This API should be called before esp_mesh_start(). + * @attention This API shall be called before esp_mesh_start(). * * @param pwd pointer to the password * @param len password length @@ -807,12 +825,12 @@ int esp_mesh_get_max_layer(void); * - ESP_ERR_MESH_ARGUMENT * - ESP_ERR_MESH_NOT_ALLOWED */ -esp_err_t esp_mesh_set_ap_password(const uint8_t *pwd, const int len); +esp_err_t esp_mesh_set_ap_password(const uint8_t *pwd, int len); /** * @brief set mesh softAP authentication mode value * - * @attention This API should be called before esp_mesh_start(). + * @attention This API shall be called before esp_mesh_start(). * * @param authmode authentication mode * @@ -821,7 +839,7 @@ esp_err_t esp_mesh_set_ap_password(const uint8_t *pwd, const int len); * - ESP_ERR_MESH_ARGUMENT * - ESP_ERR_MESH_NOT_ALLOWED */ -esp_err_t esp_mesh_set_ap_authmode(const wifi_auth_mode_t authmode); +esp_err_t esp_mesh_set_ap_authmode(wifi_auth_mode_t authmode); /** * @brief get mesh softAP authentication mode @@ -834,7 +852,7 @@ wifi_auth_mode_t esp_mesh_get_ap_authmode(void); /** * @brief set mesh softAP max connection value * - * @attention This API should be called before esp_mesh_start(). + * @attention This API shall be called before esp_mesh_start(). * * @param connections the number of max connections * @@ -842,7 +860,7 @@ wifi_auth_mode_t esp_mesh_get_ap_authmode(void); * - ESP_OK * - ESP_ERR_MESH_ARGUMENT */ -esp_err_t esp_mesh_set_ap_connections(const int connections); +esp_err_t esp_mesh_set_ap_connections(int connections); /** * @brief get mesh softAP max connection configuration @@ -855,7 +873,7 @@ int esp_mesh_get_ap_connections(void); /** * @brief get current layer value over the mesh network * - * @attention This API should be called after having received the event MESH_EVENT_PARENT_CONNECTED. + * @attention This API shall be called after having received the event MESH_EVENT_PARENT_CONNECTED. * * @return layer value * @@ -865,7 +883,7 @@ int esp_mesh_get_layer(void); /** * @brief get parent BSSID * - * @attention This API should be called after having received the event MESH_EVENT_PARENT_CONNECTED. + * @attention This API shall be called after having received the event MESH_EVENT_PARENT_CONNECTED. * * @param bssid pointer to parent BSSID * @@ -876,7 +894,7 @@ int esp_mesh_get_layer(void); esp_err_t esp_mesh_get_parent_bssid(mesh_addr_t *bssid); /** - * @brief return if the node is root + * @brief return if the device is root * * @return true/false * @@ -885,16 +903,20 @@ bool esp_mesh_is_root(void); /** * @brief enable/disable mesh networking self-organized, self-organized by default - * if self-organized is disabled, users should set a parent for this node via + * if self-organized is disabled, users should set a parent for this device via * esp_mesh_set_parent(); * - * @param enable + * @attention This API could be called either before esp_mesh_start() or after esp_mesh_start(). + * + * @param enable enable or disable self-organized networking + * @param select_parent if enable self-organized networking, let the device select a new parent or + * keep connecting to the previous parent. * * @return * - ESP_OK * - ESP_FAIL */ -esp_err_t esp_mesh_set_self_organized(const bool enable); +esp_err_t esp_mesh_set_self_organized(bool enable, bool select_parent); /** * @brief return if mesh networking is self-organized or not @@ -906,7 +928,7 @@ bool esp_mesh_get_self_organized(void); /** * @brief root waive itself - * A node is elected to be a root during the networking mostly because it has a strong RSSI with router. + * A device is elected to be a root during the networking mostly because it has a strong RSSI with router. * If such superior conditions change, users could call this API to perform a root switch. * * In this API, users could specify a desired root address to replace itself or specify an attempts value @@ -931,14 +953,14 @@ bool esp_mesh_get_self_organized(void); * - ESP_OK * - ESP_FAIL */ -esp_err_t esp_mesh_waive_root(const mesh_vote_t *vote, const int reason); +esp_err_t esp_mesh_waive_root(const mesh_vote_t *vote, int reason); /** * @brief set vote percentage threshold for approval of being a root * During the networking, only obtaining vote percentage reaches this threshold, - * the node could be a root. + * the device could be a root. * - * @attention This API should be called before esp_mesh_start(). + * @attention This API shall be called before esp_mesh_start(). * * @param percentage vote percentage threshold * @@ -946,7 +968,7 @@ esp_err_t esp_mesh_waive_root(const mesh_vote_t *vote, const int reason); * - ESP_OK * - ESP_FAIL */ -esp_err_t esp_mesh_set_vote_percentage(const float percentage); +esp_err_t esp_mesh_set_vote_percentage(float percentage); /** * @brief get vote percentage threshold for approval of being a root @@ -966,7 +988,7 @@ float esp_mesh_get_vote_percentage(void); * - ESP_OK * - ESP_FAIL */ -esp_err_t esp_mesh_set_ap_assoc_expire(const int seconds); +esp_err_t esp_mesh_set_ap_assoc_expire(int seconds); /** * @brief get mesh softAP associate expired time @@ -976,27 +998,27 @@ esp_err_t esp_mesh_set_ap_assoc_expire(const int seconds); int esp_mesh_get_ap_assoc_expire(void); /** - * @brief get total number of nodes over the mesh network(including root) + * @brief get total number of devices in current network(including root) * * @attention The returned value might be incorrect when the network is changing. ** - * @return total number of nodes(including root) + * @return total number of devices(including root) */ int esp_mesh_get_total_node_num(void); /** - * @brief get the number of nodes in routing table(including self) + * @brief get the number of devices in this device's sub-network(including self) * - * @return the number of nodes in routing table(including self) + * @return the number of devices over this device's sub-network(including self) */ int esp_mesh_get_routing_table_size(void); /** - * @brief get routing table(including itself) + * @brief get routing table of this device's sub-network(including itself) * * @param mac pointer to routing table * @param len routing table size(in bytes) - * @param size pointer to the number of nodes in routing table(including itself) + * @param size pointer to the number of devices in routing table(including itself) * * @return * - ESP_OK @@ -1015,7 +1037,7 @@ esp_err_t esp_mesh_get_routing_table(mesh_addr_t *mac, int len, int *size); * - ESP_OK * - ESP_FAIL */ -esp_err_t esp_mesh_post_toDS_state(const bool reachable); +esp_err_t esp_mesh_post_toDS_state(bool reachable); /** * @brief return the number of packets pending in the queue waiting to be sent by the mesh stack @@ -1052,9 +1074,9 @@ int esp_mesh_available_txupQ_num(const mesh_addr_t *addr, uint32_t *xseqno_in); /** * @brief set queue size * - * @attention This API should be called before esp_mesh_start(). + * @attention This API shall be called before esp_mesh_start(). * - * @param qsize default:72(min:36, max:105) + * @param qsize default:32(min:16) * * @return * - ESP_OK @@ -1079,7 +1101,7 @@ int esp_mesh_get_xon_qsize(void); * - ESP_WIFI_ERR_NOT_INIT * - ESP_WIFI_ERR_NOT_START */ -esp_err_t esp_mesh_allow_root_conflicts(const bool allowed); +esp_err_t esp_mesh_allow_root_conflicts(bool allowed); /** * @brief check if allow more than one root to exist in one network @@ -1098,7 +1120,7 @@ bool esp_mesh_is_root_conflicts_allowed(void); * - ESP_OK * - ESP_MESH_ERR_ARGUMENT */ -esp_err_t esp_mesh_set_group_id(const mesh_addr_t *addr, const int num); +esp_err_t esp_mesh_set_group_id(const mesh_addr_t *addr, int num); /** * @brief delete group ID addresses @@ -1110,7 +1132,7 @@ esp_err_t esp_mesh_set_group_id(const mesh_addr_t *addr, const int num); * - ESP_OK * - ESP_MESH_ERR_ARGUMENT */ -esp_err_t esp_mesh_delete_group_id(const mesh_addr_t *addr, const int num); +esp_err_t esp_mesh_delete_group_id(const mesh_addr_t *addr, int num); /** * @brief get the number of group ID addresses @@ -1129,7 +1151,7 @@ int esp_mesh_get_group_num(void); * - ESP_OK * - ESP_MESH_ERR_ARGUMENT */ -esp_err_t esp_mesh_get_group_list(mesh_addr_t *addr, const int num); +esp_err_t esp_mesh_get_group_list(mesh_addr_t *addr, int num); /** * @brief check if the specified group address is my group @@ -1141,7 +1163,7 @@ bool esp_mesh_is_my_group(const mesh_addr_t *addr); /** * @brief set mesh network capacity * - * @attention This API should be called before esp_mesh_start(). + * @attention This API shall be called before esp_mesh_start(). * * @param num mesh network capacity * @@ -1172,7 +1194,7 @@ esp_err_t esp_mesh_set_ie_crypto_funcs(const mesh_crypto_funcs_t *crypto_funcs); /** * @brief set mesh ie crypto key * - * @attention This API should be called after esp_mesh_set_config() and before esp_mesh_start(). + * @attention This API shall be called after esp_mesh_set_config() and before esp_mesh_start(). * * @param key ASCII crypto key * @param len length in bytes, range:8~64 @@ -1225,21 +1247,21 @@ int esp_mesh_get_root_healing_delay(void); esp_err_t esp_mesh_set_event_cb(const mesh_event_cb_t event_cb); /** - * @brief set Root Fixed setting for nodes - * If Root Fixed setting of nodes is enabled, they won't compete to be a root. - * If a scenario needs a fixed root, all nodes in this network shall enable this setting. + * @brief set Fixed Root setting for the device + * If Fixed Root setting of the device is enabled, it won't compete to be a root. + * If a scenario needs a fixed root, all devices in this network shall enable this setting. * * @param enable enable or not * * @return * - ESP_OK */ -esp_err_t esp_mesh_fix_root(const bool enable); +esp_err_t esp_mesh_fix_root(bool enable); /** - * @brief check if Root Fixed setting is enabled - * Root Fixed setting can be changed by API esp_mesh_fix_root(). - * Root Fixed setting can also be changed by event MESH_EVENT_ROOT_FIXED. + * @brief check if Fixed Root setting is enabled + * Fixed Root setting can be changed by API esp_mesh_fix_root(). + * Fixed Root setting can also be changed by event MESH_EVENT_ROOT_FIXED. * * @return true/false */ @@ -1247,9 +1269,9 @@ bool esp_mesh_is_root_fixed(void); /** * @brief set a specified parent - * self-organized networking will be disabled. * - * @param parent parent configuration + * @param parent parent configuration, the ssid and the channel of the parent are mandatory. + * @param parent_mesh_id parent mesh ID, if not set, use the device default one. * @param my_type my mesh type * @param my_layer my mesh layer * @@ -1258,8 +1280,35 @@ bool esp_mesh_is_root_fixed(void); * - ESP_ERR_ARGUMENT * - ESP_ERR_MESH_NOT_CONFIG */ -esp_err_t esp_mesh_set_parent(wifi_config_t *parent, mesh_type_t my_type, int my_layer); +esp_err_t esp_mesh_set_parent(const wifi_config_t *parent, const mesh_addr_t *parent_mesh_id, mesh_type_t my_type, int my_layer); +/** + * @brief get mesh networking IE length of one AP + * + * @param len mesh networking IE length + * + * @return + * - ESP_OK + * - ESP_ERR_WIFI_NOT_INIT + * - ESP_ERR_WIFI_ARG + * - ESP_ERR_WIFI_FAIL + */ +esp_err_t esp_mesh_scan_get_ap_ie_len(int *len); + +/** + * @brief get AP record + * Different from esp_wifi_scan_get_ap_records(), this API only gets one of scanned APs each time. + * + * @param ap_record pointer to the AP record + * @param buffer pointer to the mesh networking IE of this AP + * + * @return + * - ESP_OK + * - ESP_ERR_WIFI_NOT_INIT + * - ESP_ERR_WIFI_ARG + * - ESP_ERR_WIFI_FAIL + */ +esp_err_t esp_mesh_scan_get_ap_record(wifi_ap_record_t *ap_record, void *buffer); #ifdef __cplusplus } diff --git a/components/esp32/include/esp_mesh_internal.h b/components/esp32/include/esp_mesh_internal.h index 19273ba06d..da349297eb 100644 --- a/components/esp32/include/esp_mesh_internal.h +++ b/components/esp32/include/esp_mesh_internal.h @@ -49,6 +49,46 @@ typedef struct { int backoff_rssi; /* RSSI threshold for connecting to the root */ } mesh_switch_parent_t; +/** + * @brief mesh networking IE + */ +typedef struct { + /**< mesh networking IE head */ + uint8_t eid; /**< element ID */ + uint8_t len; /**< element length */ + uint8_t oui[3]; /**< organization identifier */ + /**< mesh networking IE content */ + uint8_t type; /** mesh networking IE type */ + uint8_t encryped : 1; /**< if mesh networking IE is encrypted */ + uint8_t version : 7; /**< mesh networking IE version */ + /**< content */ + uint8_t mesh_type; /**< mesh device type */ + uint8_t mesh_id[6]; /**< mesh ID */ + uint8_t layer_cap; /**< max layer */ + uint8_t layer; /**< current layer */ + uint8_t assoc_cap; /**< max connections of mesh AP */ + uint8_t assoc; /**< current connections */ + uint8_t leaf_cap; /**< leaf capacity */ + uint8_t leaf_assoc; /**< the number of current connected leaf */ + uint16_t root_cap; /**< root capacity */ + uint16_t self_cap; /**< self capacity */ + uint16_t layer2_cap; /**< layer2 capacity */ + uint16_t scan_ap_num; /**< the number of scanned APs */ + int8_t rssi; /**< rssi of the parent */ + int8_t router_rssi; /**< rssi of the router */ + uint8_t flag; /**< flag of networking */ + uint8_t rc_addr[6]; /**< root address */ + int8_t rc_rssi; /**< root rssi */ + uint8_t vote_addr[6]; /**< voter address */ + int8_t vote_rssi; /**< vote rssi of the router */ + uint8_t vote_ttl; /**< vote ttl */ + uint16_t votes; /**< votes */ + uint16_t my_votes; /**< my votes */ + uint8_t reason; /**< reason */ + uint8_t child[6]; /**< child address */ + uint8_t toDS; /**< toDS state */ +} __attribute__((packed)) mesh_assoc_t; + /******************************************************* * Function Definitions *******************************************************/ diff --git a/components/esp32/lib b/components/esp32/lib index 963fb2baa4..8b6d5837a4 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 963fb2baa4bf6320a89674ef1ba1de6f15ddd06d +Subproject commit 8b6d5837a4215b83ff8a3ff088ccbb716adf05fb diff --git a/examples/mesh/manual_networking/Makefile b/examples/mesh/manual_networking/Makefile new file mode 100644 index 0000000000..6a51b332dc --- /dev/null +++ b/examples/mesh/manual_networking/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := manual_networking + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/mesh/manual_networking/main/Kconfig.projbuild b/examples/mesh/manual_networking/main/Kconfig.projbuild new file mode 100644 index 0000000000..a3bad4bfd0 --- /dev/null +++ b/examples/mesh/manual_networking/main/Kconfig.projbuild @@ -0,0 +1,80 @@ +menu "Example Configuration" + +config MESH_CHANNEL + int "channel" + range 1 14 + default 1 + help + mesh network channel. + +config MESH_ROUTER_SSID + string "Router SSID" + default "ROUTER_SSID" + help + Router SSID. + +config MESH_ROUTER_PASSWD + string "Router password" + default "ROUTER_PASSWD" + help + Router password. + +choice + bool "Mesh AP Authentication Mode" + default MAP_AUTH_MODE_OPEN + help + Authentication mode. + +config WIFI_AUTH_OPEN + bool "WIFI_AUTH_OPEN" +config WIFI_AUTH_WPA_PSK + bool "WIFI_AUTH_WPA_PSK" +config WIFI_AUTH_WPA2_PSK + bool "WIFI_AUTH_WPA2_PSK" +config WIFI_AUTH_WPA_WPA2_PSK + bool "WIFI_AUTH_WPA_WPA2_PSK" +endchoice + +config MESH_AP_AUTHMODE + int + default 0 if WIFI_AUTH_OPEN + default 2 if WIFI_AUTH_WPA_PSK + default 3 if WIFI_AUTH_WPA2_PSK + default 4 if WIFI_AUTH_WPA_WPA2_PSK + help + Mesh AP authentication mode. + +config MESH_AP_PASSWD + string "Mesh AP Password" + default "MAP_PASSWD" + help + Mesh AP password. + +config MESH_AP_CONNECTIONS + int "Mesh AP Connections" + range 1 10 + default 6 + help + The number of stations allowed to connect in. + +config MESH_MAX_LAYER + int "Mesh Max Layer" + range 1 15 + default 6 + help + Max layer allowed in mesh network. + +config MESH_ROUTE_TABLE_SIZE + int "Mesh Routing Table Size" + range 1 300 + default 50 + help + The number of devices over the network(max: 300). + +config MESH_PARENT_SSID + string "Parent SSID" + default "PARENT_SSID" + help + Parent SSID. +endmenu + diff --git a/examples/mesh/manual_networking/main/component.mk b/examples/mesh/manual_networking/main/component.mk new file mode 100644 index 0000000000..a98f634eae --- /dev/null +++ b/examples/mesh/manual_networking/main/component.mk @@ -0,0 +1,4 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) diff --git a/examples/mesh/manual_networking/main/include/mesh_light.h b/examples/mesh/manual_networking/main/include/mesh_light.h new file mode 100644 index 0000000000..ecf4e06782 --- /dev/null +++ b/examples/mesh/manual_networking/main/include/mesh_light.h @@ -0,0 +1,57 @@ +/* Mesh Manual Networking Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#ifndef __MESH_LIGHT_H__ +#define __MESH_LIGHT_H__ + +#include "esp_err.h" + +/******************************************************* + * Constants + *******************************************************/ +#define MESH_LIGHT_RED (0xff) +#define MESH_LIGHT_GREEN (0xfe) +#define MESH_LIGHT_BLUE (0xfd) +#define MESH_LIGHT_YELLOW (0xfc) +#define MESH_LIGHT_PINK (0xfb) +#define MESH_LIGHT_INIT (0xfa) +#define MESH_LIGHT_WARNING (0xf9) + +#define MESH_TOKEN_ID (0x0) +#define MESH_TOKEN_VALUE (0xbeef) +#define MESH_CONTROL_CMD (0x2) + +/******************************************************* + * Type Definitions + *******************************************************/ + +/******************************************************* + * Structures + *******************************************************/ +typedef struct { + uint8_t cmd; + bool on; + uint8_t token_id; + uint16_t token_value; +} mesh_light_ctl_t; + +/******************************************************* + * Variables Declarations + *******************************************************/ + +/******************************************************* + * Function Definitions + *******************************************************/ +esp_err_t mesh_light_init(void); +esp_err_t mesh_light_set(int color); +esp_err_t mesh_light_process(mesh_addr_t *from, uint8_t *buf, uint16_t len); +void mesh_connected_indicator(int layer); +void mesh_disconnected_indicator(void); + +#endif /* __MESH_LIGHT_H__ */ diff --git a/examples/mesh/manual_networking/main/mesh_light.c b/examples/mesh/manual_networking/main/mesh_light.c new file mode 100644 index 0000000000..4780503817 --- /dev/null +++ b/examples/mesh/manual_networking/main/mesh_light.c @@ -0,0 +1,180 @@ +/* Mesh Manual Networking Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include "esp_err.h" +#include "esp_mesh.h" +#include "mesh_light.h" +#include "driver/gpio.h" +#include "driver/ledc.h" + +/******************************************************* + * Constants + *******************************************************/ +/* RGB configuration on ESP-WROVER-KIT board */ +#define LEDC_IO_0 (0) +#define LEDC_IO_1 (2) +#define LEDC_IO_2 (4) +#define LEDC_IO_3 (5) + +/******************************************************* + * Variable Definitions + *******************************************************/ +static bool s_light_inited = false; + +/******************************************************* + * Function Definitions + *******************************************************/ +esp_err_t mesh_light_init(void) +{ + if (s_light_inited == true) { + return ESP_OK; + } + s_light_inited = true; + + ledc_timer_config_t ledc_timer = { + .bit_num = LEDC_TIMER_13_BIT, + .freq_hz = 5000, + .speed_mode = LEDC_HIGH_SPEED_MODE, + .timer_num = LEDC_TIMER_0 + }; + ledc_timer_config(&ledc_timer); + + ledc_channel_config_t ledc_channel = { + .channel = LEDC_CHANNEL_0, + .duty = 100, + .gpio_num = LEDC_IO_0, + .intr_type = LEDC_INTR_FADE_END, + .speed_mode = LEDC_HIGH_SPEED_MODE, + .timer_sel = LEDC_TIMER_0 + }; + ledc_channel_config(&ledc_channel); + ledc_channel.channel = LEDC_CHANNEL_1; + ledc_channel.gpio_num = LEDC_IO_1; + ledc_channel_config(&ledc_channel); + ledc_channel.channel = LEDC_CHANNEL_2; + ledc_channel.gpio_num = LEDC_IO_2; + ledc_channel_config(&ledc_channel); + ledc_channel.channel = LEDC_CHANNEL_3; + ledc_channel.gpio_num = LEDC_IO_3; + ledc_channel_config(&ledc_channel); + ledc_fade_func_install(0); + + mesh_light_set(MESH_LIGHT_INIT); + return ESP_OK; +} + +esp_err_t mesh_light_set(int color) +{ + switch (color) { + case MESH_LIGHT_RED: + /* Red */ + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 3000); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 0); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 0); + break; + case MESH_LIGHT_GREEN: + /* Green */ + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 0); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 3000); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 0); + break; + case MESH_LIGHT_BLUE: + /* Blue */ + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 0); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 0); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 3000); + break; + case MESH_LIGHT_YELLOW: + /* Yellow */ + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 3000); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 3000); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 0); + break; + case MESH_LIGHT_PINK: + /* Pink */ + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 3000); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 0); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 3000); + break; + case MESH_LIGHT_INIT: + /* can't say */ + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 0); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 3000); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 3000); + break; + case MESH_LIGHT_WARNING: + /* warning */ + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 3000); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 3000); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 3000); + break; + default: + /* off */ + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 0); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, 0); + ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, 0); + } + + ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0); + ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1); + ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2); + + return ESP_OK; +} + +void mesh_connected_indicator(int layer) +{ + switch (layer) { + case 1: + mesh_light_set(MESH_LIGHT_PINK); + break; + case 2: + mesh_light_set(MESH_LIGHT_YELLOW); + break; + case 3: + mesh_light_set(MESH_LIGHT_RED); + break; + case 4: + mesh_light_set(MESH_LIGHT_BLUE); + break; + case 5: + mesh_light_set(MESH_LIGHT_GREEN); + break; + case 6: + mesh_light_set(MESH_LIGHT_WARNING); + break; + default: + mesh_light_set(0); + } +} + +void mesh_disconnected_indicator(void) +{ + mesh_light_set(MESH_LIGHT_WARNING); +} + +esp_err_t mesh_light_process(mesh_addr_t *from, uint8_t *buf, uint16_t len) +{ + mesh_light_ctl_t *in = (mesh_light_ctl_t *) buf; + if (!from || !buf || len < sizeof(mesh_light_ctl_t)) { + return ESP_FAIL; + } + if (in->token_id != MESH_TOKEN_ID || in->token_value != MESH_TOKEN_VALUE) { + return ESP_FAIL; + } + if (in->cmd == MESH_CONTROL_CMD) { + if (in->on) { + mesh_connected_indicator(esp_mesh_get_layer()); + } else { + mesh_light_set(0); + } + } + return ESP_OK; +} diff --git a/examples/mesh/manual_networking/main/mesh_main.c b/examples/mesh/manual_networking/main/mesh_main.c new file mode 100644 index 0000000000..2703dd5b63 --- /dev/null +++ b/examples/mesh/manual_networking/main/mesh_main.c @@ -0,0 +1,327 @@ +/* Mesh Manual Networking Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include "esp_wifi.h" +#include "esp_system.h" +#include "esp_event_loop.h" +#include "esp_log.h" +#include "esp_mesh.h" +#include "esp_mesh_internal.h" +#include "mesh_light.h" +#include "nvs_flash.h" + +/******************************************************* + * Macros + *******************************************************/ +//#define MESH_SET_ROOT + +#ifndef MESH_SET_ROOT +#define MESH_SET_NODE +#endif + +/******************************************************* + * Constants + *******************************************************/ + +/******************************************************* + * Variable Definitions + *******************************************************/ +static const char *MESH_TAG = "mesh_main"; +static const uint8_t MESH_ID[6] = { 0x77, 0x77, 0x77, 0x77, 0x77, 0x77}; +static mesh_addr_t mesh_parent_addr; +static int mesh_layer = -1; + +/******************************************************* + * Function Declarations + *******************************************************/ +void mesh_event_handler(mesh_event_t event); +void mesh_scan_done_handler(int num); + +/******************************************************* + * Function Definitions + *******************************************************/ +void mesh_scan_done_handler(int num) +{ + int i; + int ie_len = 0; + mesh_assoc_t assoc; + mesh_assoc_t parent_assoc = { .layer = CONFIG_MESH_MAX_LAYER, .rssi = -120 }; + wifi_ap_record_t record; + wifi_ap_record_t parent_record = { 0, }; + bool parent_found = false; + mesh_type_t my_type = MESH_IDLE; + int my_layer = -1; + + for (i = 0; i < num; i++) { + esp_mesh_scan_get_ap_ie_len(&ie_len); + esp_mesh_scan_get_ap_record(&record, &assoc); + if (ie_len == sizeof(assoc)) { + ESP_LOGW(MESH_TAG, + "[%d]%s, layer:%d/%d, assoc:%d/%d, %d, "MACSTR", channel:%u, rssi:%d, ID<"MACSTR">", + i, record.ssid, assoc.layer, assoc.layer_cap, assoc.assoc, + assoc.assoc_cap, assoc.layer2_cap, MAC2STR(record.bssid), + record.primary, record.rssi, MAC2STR(assoc.mesh_id)); +#ifdef MESH_SET_NODE + if (assoc.mesh_type != MESH_IDLE && assoc.layer_cap + && assoc.assoc < assoc.assoc_cap && record.rssi > -70) { + if (assoc.layer < parent_assoc.layer || assoc.layer2_cap < parent_assoc.layer2_cap) { + parent_found = true; + memcpy(&parent_record, &record, sizeof(record)); + memcpy(&parent_assoc, &assoc, sizeof(assoc)); + if (parent_assoc.layer_cap != 1) { + my_type = MESH_NODE; + } else { + my_type = MESH_LEAF; + } + my_layer = parent_assoc.layer + 1; + } + } +#endif + } else { + ESP_LOGI(MESH_TAG, "[%d]%s, "MACSTR", channel:%u, rssi:%d", i, + record.ssid, MAC2STR(record.bssid), record.primary, + record.rssi); +#ifdef MESH_SET_ROOT + if (!strcmp(CONFIG_MESH_ROUTER_SSID, (char *) record.ssid)) { + parent_found = true; + memcpy(&parent_record, &record, sizeof(record)); + my_type = MESH_ROOT; + my_layer = MESH_ROOT_LAYER; + } +#endif + } + } + + if (parent_found) { + /* + * parent + * Both channel and ssid of the parent are mandatory. + */ + wifi_config_t parent = { 0, }; + parent.sta.channel = parent_record.primary; + memcpy(&parent.sta.ssid, &parent_record.ssid, + sizeof(parent_record.ssid)); + parent.sta.bssid_set = 1; + memcpy(&parent.sta.bssid, parent_record.bssid, 6); + if (my_type == MESH_ROOT) { + ESP_LOGW(MESH_TAG, "%s, "MACSTR", channel:%u, rssi:%d", + parent_record.ssid, MAC2STR(parent_record.bssid), + parent_record.primary, parent_record.rssi); + } else { + ESP_LOGW(MESH_TAG, + "%s, layer:%d/%d, assoc:%d/%d, %d, "MACSTR", channel:%u, rssi:%d", + parent_record.ssid, parent_assoc.layer, + parent_assoc.layer_cap, parent_assoc.assoc, + parent_assoc.assoc_cap, parent_assoc.layer2_cap, + MAC2STR(parent_record.bssid), parent_record.primary, + parent_record.rssi); + } + ESP_ERROR_CHECK(esp_mesh_set_parent(&parent, (mesh_addr_t*)&parent_assoc.mesh_id, my_type, my_layer)); + + } else { + ESP_LOGW(MESH_TAG, + "no parent found, enable self-organized networking."); + ESP_ERROR_CHECK(esp_mesh_set_self_organized(1, 1)); + } +} + +void mesh_event_handler(mesh_event_t event) +{ + mesh_addr_t id = {0,}; + static uint8_t last_layer = 0; + ESP_LOGD(MESH_TAG, "esp_event_handler:%d", event.id); + + switch (event.id) { + case MESH_EVENT_STARTED: + esp_mesh_get_id(&id); + ESP_LOGI(MESH_TAG, "ID:"MACSTR"", MAC2STR(id.addr)); + mesh_layer = esp_mesh_get_layer(); + ESP_ERROR_CHECK(esp_mesh_set_self_organized(0, 0)); + ESP_ERROR_CHECK(esp_wifi_scan_stop()); + wifi_scan_config_t scan_config = { 0 }; + /* mesh softAP is hidden */ + scan_config.show_hidden = 1; + ESP_ERROR_CHECK(esp_wifi_scan_start(&scan_config, 0)); + break; + case MESH_EVENT_STOPPED: + ESP_LOGI(MESH_TAG, ""); + mesh_layer = esp_mesh_get_layer(); + break; + case MESH_EVENT_CHILD_CONNECTED: + ESP_LOGI(MESH_TAG, "aid:%d, "MACSTR"", + event.info.child_connected.aid, + MAC2STR(event.info.child_connected.mac)); + break; + case MESH_EVENT_CHILD_DISCONNECTED: + ESP_LOGI(MESH_TAG, "aid:%d, "MACSTR"", + event.info.child_disconnected.aid, + MAC2STR(event.info.child_disconnected.mac)); + break; + case MESH_EVENT_ROUTING_TABLE_ADD: + ESP_LOGW(MESH_TAG, "add %d, new:%d", + event.info.routing_table.rt_size_change, + event.info.routing_table.rt_size_new); + break; + case MESH_EVENT_ROUTING_TABLE_REMOVE: + ESP_LOGW(MESH_TAG, "remove %d, new:%d", + event.info.routing_table.rt_size_change, + event.info.routing_table.rt_size_new); + break; + case MESH_EVENT_NO_PARNET_FOUND: + ESP_LOGI(MESH_TAG, "scan times:%d", + event.info.no_parent.scan_times); + /* TODO handler for the failure */ + break; + case MESH_EVENT_PARENT_CONNECTED: + esp_mesh_get_id(&id); + mesh_layer = event.info.connected.self_layer; + memcpy(&mesh_parent_addr.addr, event.info.connected.connected.bssid, 6); + ESP_LOGI(MESH_TAG, + "layer:%d-->%d, parent:"MACSTR"%s, ID:"MACSTR"", + last_layer, mesh_layer, MAC2STR(mesh_parent_addr.addr), + esp_mesh_is_root() ? "" : + (mesh_layer == 2) ? "" : "", MAC2STR(id.addr)); + last_layer = mesh_layer; + mesh_connected_indicator(mesh_layer); + if (esp_mesh_is_root()) { + tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA); + } + break; + case MESH_EVENT_PARENT_DISCONNECTED: + ESP_LOGI(MESH_TAG, + "reason:%d", + event.info.disconnected.reason); + mesh_disconnected_indicator(); + mesh_layer = esp_mesh_get_layer(); + break; + case MESH_EVENT_LAYER_CHANGE: + mesh_layer = event.info.layer_change.new_layer; + ESP_LOGI(MESH_TAG, "layer:%d-->%d%s", + last_layer, mesh_layer, + esp_mesh_is_root() ? "" : + (mesh_layer == 2) ? "" : ""); + last_layer = mesh_layer; + mesh_connected_indicator(mesh_layer); + break; + case MESH_EVENT_ROOT_ADDRESS: + ESP_LOGI(MESH_TAG, "root address:"MACSTR"", + MAC2STR(event.info.root_addr.addr)); + break; + case MESH_EVENT_ROOT_GOT_IP: + /* root starts to connect to server */ + ESP_LOGI(MESH_TAG, + "sta ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR, + IP2STR(&event.info.got_ip.ip_info.ip), + IP2STR(&event.info.got_ip.ip_info.netmask), + IP2STR(&event.info.got_ip.ip_info.gw)); + break; + case MESH_EVENT_ROOT_LOST_IP: + ESP_LOGI(MESH_TAG, ""); + break; + case MESH_EVENT_VOTE_STARTED: + ESP_LOGI(MESH_TAG, + "attempts:%d, reason:%d, rc_addr:"MACSTR"", + event.info.vote_started.attempts, + event.info.vote_started.reason, + MAC2STR(event.info.vote_started.rc_addr.addr)); + break; + case MESH_EVENT_VOTE_STOPPED: + ESP_LOGI(MESH_TAG, ""); + break; + case MESH_EVENT_ROOT_SWITCH_REQ: + ESP_LOGI(MESH_TAG, + "reason:%d, rc_addr:"MACSTR"", + event.info.switch_req.reason, + MAC2STR( event.info.switch_req.rc_addr.addr)); + break; + case MESH_EVENT_ROOT_SWITCH_ACK: + /* new root */ + mesh_layer = esp_mesh_get_layer(); + esp_mesh_get_parent_bssid(&mesh_parent_addr); + ESP_LOGI(MESH_TAG, "layer:%d, parent:"MACSTR"", mesh_layer, MAC2STR(mesh_parent_addr.addr)); + break; + case MESH_EVENT_TODS_STATE: + ESP_LOGI(MESH_TAG, "state:%d", + event.info.toDS_state); + break; + case MESH_EVENT_ROOT_FIXED: + ESP_LOGI(MESH_TAG, "%s", + event.info.root_fixed.is_fixed ? "fixed" : "not fixed"); + break; + case MESH_EVENT_ROOT_ASKED_YIELD: + ESP_LOGI(MESH_TAG, + ""MACSTR", rssi:%d, capacity:%d", + MAC2STR(event.info.root_conflict.addr), + event.info.root_conflict.rssi, + event.info.root_conflict.capacity); + break; + case MESH_EVENT_CHANNEL_SWITCH: + ESP_LOGI(MESH_TAG, ""); + break; + case MESH_EVENT_SCAN_DONE: + ESP_LOGI(MESH_TAG, "number:%d", + event.info.scan_done.number); + mesh_scan_done_handler(event.info.scan_done.number); + break; + default: + ESP_LOGI(MESH_TAG, "unknown id:%d", event.id); + break; + } +} + +void app_main(void) +{ + ESP_ERROR_CHECK(mesh_light_init()); + ESP_ERROR_CHECK(nvs_flash_init()); + /* tcpip initialization */ + tcpip_adapter_init(); + /* for mesh + * stop DHCP server on softAP interface by default + * stop DHCP client on station interface by default + * */ + ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP)); + ESP_ERROR_CHECK(tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA)); +#if 0 + /* static ip settings */ + tcpip_adapter_ip_info_t sta_ip; + sta_ip.ip.addr = ipaddr_addr("192.168.1.102"); + sta_ip.gw.addr = ipaddr_addr("192.168.1.1"); + sta_ip.netmask.addr = ipaddr_addr("255.255.255.0"); + tcpip_adapter_set_ip_info(WIFI_IF_STA, &sta_ip); +#endif + /* wifi initialization */ + ESP_ERROR_CHECK(esp_event_loop_init(NULL, NULL)); + wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&config)); + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_FLASH)); + ESP_ERROR_CHECK(esp_wifi_start()); + /* mesh initialization */ + ESP_ERROR_CHECK(esp_mesh_init()); + ESP_ERROR_CHECK(esp_mesh_set_ap_authmode(WIFI_AUTH_OPEN)); + mesh_cfg_t cfg = MESH_INIT_CONFIG_DEFAULT(); + /* mesh ID */ + memcpy((uint8_t *) &cfg.mesh_id, MESH_ID, 6); + /* mesh event callback */ + cfg.event_cb = &mesh_event_handler; + /* router */ + cfg.channel = CONFIG_MESH_CHANNEL; + cfg.router.ssid_len = strlen(CONFIG_MESH_ROUTER_SSID); + memcpy((uint8_t *) &cfg.router.ssid, CONFIG_MESH_ROUTER_SSID, cfg.router.ssid_len); + memcpy((uint8_t *) &cfg.router.password, CONFIG_MESH_ROUTER_PASSWD, + strlen(CONFIG_MESH_ROUTER_PASSWD)); + /* mesh softAP */ + cfg.mesh_ap.max_connection = CONFIG_MESH_AP_CONNECTIONS; + memcpy((uint8_t *) &cfg.mesh_ap.password, CONFIG_MESH_AP_PASSWD, + strlen(CONFIG_MESH_AP_PASSWD)); + ESP_ERROR_CHECK(esp_mesh_set_config(&cfg)); + /* mesh start */ + ESP_ERROR_CHECK(esp_mesh_start()); + ESP_LOGI(MESH_TAG, "mesh starts successfully, heap:%d, %s\n", esp_get_free_heap_size(), + esp_mesh_is_root_fixed() ? "root fixed" : "root not fixed"); +} From 2e63a445d93c6e5b88a48b761158cfe3bb0f8c11 Mon Sep 17 00:00:00 2001 From: zhiweijian Date: Tue, 22 May 2018 16:54:08 +0800 Subject: [PATCH 166/187] Component/bt: fix set scan params command completer error --- .../bt/bluedroid/stack/btm/btm_ble_gap.c | 39 ++++++++----------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/components/bt/bluedroid/stack/btm/btm_ble_gap.c b/components/bt/bluedroid/stack/btm/btm_ble_gap.c index 4444a11d94..109a816896 100644 --- a/components/bt/bluedroid/stack/btm/btm_ble_gap.c +++ b/components/bt/bluedroid/stack/btm/btm_ble_gap.c @@ -441,6 +441,7 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT32 duration, tBTM_STATUS BTM_BleScan(BOOLEAN start, UINT32 duration, tBTM_INQ_RESULTS_CB *p_results_cb, tBTM_CMPL_CB *p_cmpl_cb) { + tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var; tBTM_STATUS status = BTM_WRONG_MODE; if (!controller_get_interface()->supports_ble()) { @@ -465,6 +466,20 @@ tBTM_STATUS BTM_BleScan(BOOLEAN start, UINT32 duration, /* enable resolving list */ btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_SCAN); #endif + // if not set scan params, set default scan params + if (!p_inq->scan_params_set) { + /* allow config of scan type */ + p_inq->scan_type = BTM_BLE_SCAN_MODE_ACTI; + p_inq->scan_interval = BTM_BLE_GAP_DISC_SCAN_INT; + p_inq->scan_window = BTM_BLE_GAP_DISC_SCAN_WIN; + p_inq->sfp = BTM_BLE_DEFAULT_SFP; + p_inq->scan_params_set = TRUE; + p_inq->scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE; + btsnd_hcic_ble_set_scan_params(p_inq->scan_type, p_inq->scan_interval, + p_inq->scan_window, + btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, + p_inq->sfp); + } status = btm_ble_start_scan(); } @@ -3211,25 +3226,6 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt } } -static void btm_ble_recover_scan_params(void) -{ - tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var; - - if (p_inq->scan_params_set) { - /// set back the scan params to the controller after stop the scan - btsnd_hcic_ble_set_scan_params(p_inq->scan_type, p_inq->scan_interval, - p_inq->scan_window, - btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type, - p_inq->sfp); - } else { - /// set the default value if the scan params not set yet - btm_update_scanner_filter_policy(SP_ADV_ALL); - - btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_SCAN; - } - -} - /******************************************************************************* ** ** Function btm_ble_start_scan @@ -3243,8 +3239,7 @@ tBTM_STATUS btm_ble_start_scan(void) { tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var; tBTM_STATUS status = BTM_CMD_STARTED; - // recoverly the scan parameters to the controller before start scan - btm_ble_recover_scan_params(); + if(p_inq->scan_duplicate_filter > BTM_BLE_DUPLICATE_MAX) { p_inq->scan_duplicate_filter = BTM_BLE_DUPLICATE_DISABLE; } @@ -3378,8 +3373,6 @@ static void btm_ble_stop_discover(void) btm_cb.ble_ctr_cb.inq_var.state = BTM_BLE_STOP_SCAN; /* stop discovery now */ btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE); - // recoverly the scan parameters to the controller after stop scan - btm_ble_recover_scan_params(); } if (p_scan_cb) { From 3b24bc42d2b52cefbac02e3302bde5c31fc1b62a Mon Sep 17 00:00:00 2001 From: He Yin Ling Date: Tue, 15 May 2018 11:51:56 +0800 Subject: [PATCH 167/187] CI: assign unit test cases according to sdkconfig: We have built unit-test-app with different configs. Currently we use the config name as tags to match runners. It's not easy to add new configs (need to update tags to existed runners). Now we'll parse required test runner tags from `sdkconfig` file. For example, if config enables `CONFIG_SPIRAM_SUPPORT`, then it requires `psram` tag. This will make adding new configs easier. In this commit we change the one behavior of assign test: match keys of cases should be exactly the same with job tags. This fixes cases select jobs include their tags, and jobs requires those tags can't be assigned. --- .gitlab-ci.yml | 249 ++++++++---------- tools/tiny-test-fw/CIAssignExampleTest.py | 8 +- tools/tiny-test-fw/CIAssignUnitTest.py | 22 +- tools/tiny-test-fw/Utility/CIAssignTest.py | 4 +- tools/tiny-test-fw/Utility/GitlabCIJob.py | 14 +- .../unit-test-app/tools/ConfigDependency.yml | 1 + tools/unit-test-app/tools/UnitTestParser.py | 69 +++-- tools/unit-test-app/unit_test.py | 3 + 8 files changed, 175 insertions(+), 195 deletions(-) create mode 100644 tools/unit-test-app/tools/ConfigDependency.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f7bff45e30..9c83055ea7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -662,287 +662,250 @@ UT_001_01: tags: - ESP32_IDF - UT_T1_1 - - UT_default UT_001_02: <<: *unit_test_template tags: - ESP32_IDF - UT_T1_1 - - UT_default UT_001_03: <<: *unit_test_template tags: - ESP32_IDF - UT_T1_1 - - UT_default UT_001_04: <<: *unit_test_template tags: - ESP32_IDF - UT_T1_1 - - UT_default UT_001_05: <<: *unit_test_template tags: - ESP32_IDF - - UT_T1_SDMODE - - UT_default + - UT_T1_1 UT_001_06: <<: *unit_test_template tags: - ESP32_IDF - - UT_T1_SPIMODE - - UT_default + - UT_T1_1 UT_001_07: <<: *unit_test_template tags: - ESP32_IDF - UT_T1_1 - - UT_default UT_001_08: <<: *unit_test_template tags: - ESP32_IDF - UT_T1_1 - - UT_default UT_001_09: <<: *unit_test_template tags: - ESP32_IDF - UT_T1_1 - - UT_default UT_001_10: <<: *unit_test_template tags: - ESP32_IDF - UT_T1_1 - - UT_default + +UT_001_11: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_12: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_13: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_14: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_15: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_16: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_17: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_18: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_19: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_20: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_21: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_22: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_23: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_001_24: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 UT_002_01: <<: *unit_test_template tags: - ESP32_IDF - - UT_T1_1 - - UT_release + - UT_T1_SDMODE UT_002_02: <<: *unit_test_template tags: - ESP32_IDF - - UT_T1_1 - - UT_release + - UT_T1_SDMODE UT_002_03: - <<: *unit_test_template - tags: - - ESP32_IDF - - UT_T1_1 - - UT_release - -UT_002_04: - <<: *unit_test_template - tags: - - ESP32_IDF - - UT_T1_1 - - UT_release - -UT_002_05: <<: *unit_test_template tags: - ESP32_IDF - UT_T1_SDMODE - - UT_release - -UT_002_06: - <<: *unit_test_template - tags: - - ESP32_IDF - - UT_T1_SPIMODE - - UT_release - -UT_002_07: - <<: *unit_test_template - tags: - - ESP32_IDF - - UT_T1_1 - - UT_release - -UT_002_08: - <<: *unit_test_template - tags: - - ESP32_IDF - - UT_T1_1 - - UT_release - -UT_002_09: - <<: *unit_test_template - tags: - - ESP32_IDF - - UT_T1_1 - - UT_release - -UT_002_10: - <<: *unit_test_template - tags: - - ESP32_IDF - - UT_T1_1 - - UT_release UT_003_01: <<: *unit_test_template tags: - ESP32_IDF - - UT_T1_1 - - UT_single_core + - UT_T1_SPIMODE UT_003_02: <<: *unit_test_template tags: - ESP32_IDF - - UT_T1_1 - - UT_single_core + - UT_T1_SPIMODE UT_003_03: - <<: *unit_test_template - tags: - - ESP32_IDF - - UT_T1_1 - - UT_single_core - -UT_003_04: - <<: *unit_test_template - tags: - - ESP32_IDF - - UT_T1_1 - - UT_single_core - -UT_003_05: - <<: *unit_test_template - tags: - - ESP32_IDF - - UT_T1_SDMODE - - UT_single_core - -UT_003_06: <<: *unit_test_template tags: - ESP32_IDF - UT_T1_SPIMODE - - UT_single_core - -UT_003_07: - <<: *unit_test_template - tags: - - ESP32_IDF - - UT_T1_1 - - UT_single_core - -UT_003_08: - <<: *unit_test_template - tags: - - ESP32_IDF - - UT_T1_1 - - UT_single_core - -UT_003_09: - <<: *unit_test_template - tags: - - ESP32_IDF - - UT_T1_1 - - UT_single_core - -UT_003_10: - <<: *unit_test_template - tags: - - ESP32_IDF - - UT_T1_1 - - UT_single_core UT_004_01: <<: *unit_test_template tags: - ESP32_IDF - UT_T1_1 - - UT_psram + - psram UT_004_02: <<: *unit_test_template tags: - ESP32_IDF - UT_T1_1 - - UT_psram + - psram UT_004_03: <<: *unit_test_template tags: - ESP32_IDF - UT_T1_1 - - UT_psram + - psram UT_004_04: <<: *unit_test_template tags: - ESP32_IDF - UT_T1_1 - - UT_psram + - psram UT_004_05: <<: *unit_test_template tags: - ESP32_IDF - - UT_T1_SDMODE - - UT_psram + - UT_T1_1 + - psram UT_004_06: <<: *unit_test_template tags: - ESP32_IDF - - UT_T1_SPIMODE - - UT_psram + - UT_T1_1 + - psram UT_004_07: <<: *unit_test_template tags: - ESP32_IDF - UT_T1_1 - - UT_psram + - psram UT_004_08: <<: *unit_test_template tags: - ESP32_IDF - UT_T1_1 - - UT_psram + - psram -UT_004_09: +UT_005_01: <<: *unit_test_template tags: - ESP32_IDF - - UT_T1_1 - - UT_psram + - UT_T1_SDMODE + - psram -UT_004_10: +UT_005_02: <<: *unit_test_template tags: - ESP32_IDF - - UT_T1_1 - - UT_psram - -UT_004_11: - <<: *unit_test_template - tags: - - ESP32_IDF - - UT_T1_1 - - UT_psram + - UT_T1_SPIMODE + - psram IT_001_01: <<: *test_template diff --git a/tools/tiny-test-fw/CIAssignExampleTest.py b/tools/tiny-test-fw/CIAssignExampleTest.py index f13a803e44..3d9df0360b 100644 --- a/tools/tiny-test-fw/CIAssignExampleTest.py +++ b/tools/tiny-test-fw/CIAssignExampleTest.py @@ -26,7 +26,11 @@ test_fw_path = os.getenv("TEST_FW_PATH") if test_fw_path: sys.path.insert(0, test_fw_path) -from Utility.CIAssignTest import AssignTest +from Utility.CIAssignTest import AssignTest, Group + + +class ExampleGroup(Group): + SORT_KEYS = CI_JOB_MATCH_KEYS = ["env_tag", "chip"] class CIExampleAssignTest(AssignTest): @@ -43,6 +47,6 @@ if __name__ == '__main__': help="output path of config files") args = parser.parse_args() - assign_test = CIExampleAssignTest(args.test_case, args.ci_config_file) + assign_test = CIExampleAssignTest(args.test_case, args.ci_config_file, case_group=ExampleGroup) assign_test.assign_cases() assign_test.output_configs(args.output_path) diff --git a/tools/tiny-test-fw/CIAssignUnitTest.py b/tools/tiny-test-fw/CIAssignUnitTest.py index 3c31514589..9885d4fd7d 100644 --- a/tools/tiny-test-fw/CIAssignUnitTest.py +++ b/tools/tiny-test-fw/CIAssignUnitTest.py @@ -17,12 +17,18 @@ from Utility import CIAssignTest class Group(CIAssignTest.Group): - SORT_KEYS = ["Test App", "SDK", "test environment", "multi_device", "multi_stage"] - CI_JOB_MATCH_KEYS = ["Test App", "SDK", "test environment"] + SORT_KEYS = ["config", "SDK", "test environment", "multi_device", "multi_stage", "tags"] MAX_CASE = 30 ATTR_CONVERT_TABLE = { "execution_time": "execution time" } + # when IDF support multiple chips, SDK will be moved into tags, we can remove it + CI_JOB_MATCH_KEYS = ["test environment", "SDK"] + + def __init__(self, case): + super(Group, self).__init__(case) + for tag in self._get_case_attr(case, "tags"): + self.ci_job_match_keys.add(tag) @staticmethod def _get_case_attr(case, attr): @@ -30,13 +36,6 @@ class Group(CIAssignTest.Group): attr = Group.ATTR_CONVERT_TABLE[attr] return case[attr] - @staticmethod - def _get_ut_config(test_app): - # we format test app "UT_ + config" when parsing test cases - # now we need to extract config - assert test_app[:3] == "UT_" - return test_app[3:] - def _create_extra_data(self, test_function): """ For unit test case, we need to copy some attributes of test cases into config file. @@ -45,7 +44,7 @@ class Group(CIAssignTest.Group): case_data = [] for case in self.case_list: one_case_data = { - "config": self._get_ut_config(self._get_case_attr(case, "Test App")), + "config": self._get_case_attr(case, "config"), "name": self._get_case_attr(case, "summary"), "reset": self._get_case_attr(case, "reset"), "timeout": self._get_case_attr(case, "timeout"), @@ -101,8 +100,7 @@ class UnitTestAssignTest(CIAssignTest.AssignTest): def __init__(self, test_case_path, ci_config_file): CIAssignTest.AssignTest.__init__(self, test_case_path, ci_config_file, case_group=Group) - @staticmethod - def _search_cases(test_case_path, case_filter=None): + def _search_cases(self, test_case_path, case_filter=None): """ For unit test case, we don't search for test functions. The unit test cases is stored in a yaml file which is created in job build-idf-test. diff --git a/tools/tiny-test-fw/Utility/CIAssignTest.py b/tools/tiny-test-fw/Utility/CIAssignTest.py index 3e570cc31a..ca0204aaba 100644 --- a/tools/tiny-test-fw/Utility/CIAssignTest.py +++ b/tools/tiny-test-fw/Utility/CIAssignTest.py @@ -63,8 +63,8 @@ class Group(object): self.execution_time = 0 self.case_list = [case] self.filters = dict(zip(self.SORT_KEYS, [self._get_case_attr(case, x) for x in self.SORT_KEYS])) - self.ci_job_match_keys = dict(zip(self.CI_JOB_MATCH_KEYS, - [self._get_case_attr(case, x) for x in self.CI_JOB_MATCH_KEYS])) + # we use ci_job_match_keys to match CI job tags. It's a set of required tags. + self.ci_job_match_keys = set([self._get_case_attr(case, x) for x in self.CI_JOB_MATCH_KEYS]) @staticmethod def _get_case_attr(case, attr): diff --git a/tools/tiny-test-fw/Utility/GitlabCIJob.py b/tools/tiny-test-fw/Utility/GitlabCIJob.py index 79676cf004..e6173b035c 100644 --- a/tools/tiny-test-fw/Utility/GitlabCIJob.py +++ b/tools/tiny-test-fw/Utility/GitlabCIJob.py @@ -27,6 +27,7 @@ class Job(dict): def __init__(self, job, job_name): super(Job, self).__init__(job) self["name"] = job_name + self.tags = set(self["tags"]) def match_group(self, group): """ @@ -37,17 +38,8 @@ class Job(dict): :return: True or False """ match_result = False - for _ in range(1): - if "case group" in self: - # this job is already assigned - break - for value in group.ci_job_match_keys.values(): - if value not in self["tags"]: - break - else: - continue - break - else: + if "case group" not in self and group.ci_job_match_keys == self.tags: + # group not assigned and all tags match match_result = True return match_result diff --git a/tools/unit-test-app/tools/ConfigDependency.yml b/tools/unit-test-app/tools/ConfigDependency.yml new file mode 100644 index 0000000000..3af3e565b5 --- /dev/null +++ b/tools/unit-test-app/tools/ConfigDependency.yml @@ -0,0 +1 @@ +"psram": "CONFIG_SPIRAM_SUPPORT=y" diff --git a/tools/unit-test-app/tools/UnitTestParser.py b/tools/unit-test-app/tools/UnitTestParser.py index 688e4ce37d..1898bf6598 100644 --- a/tools/unit-test-app/tools/UnitTestParser.py +++ b/tools/unit-test-app/tools/UnitTestParser.py @@ -20,13 +20,8 @@ TEST_CASE_PATTERN = { "test environment": "UT_T1_1", "reset": "", "expected result": "1. set succeed", - "cmd set": "test_unit_test_case" -} - -CONFIG_FILE_PATTERN = { - "Config": {"execute count": 1, "execute order": "in order"}, - "DUT": [], - "Filter": [{"Add": {"ID": []}}] + "cmd set": "test_unit_test_case", + "Test App": "UT", } @@ -39,11 +34,12 @@ class Parser(object): # file path (relative to idf path) TAG_DEF_FILE = os.path.join("tools", "unit-test-app", "tools", "TagDefinition.yml") MODULE_DEF_FILE = os.path.join("tools", "unit-test-app", "tools", "ModuleDefinition.yml") + CONFIG_DEPENDENCY_FILE = os.path.join("tools", "unit-test-app", "tools", "ConfigDependency.yml") MODULE_ARTIFACT_FILE = os.path.join("components", "idf_test", "ModuleDefinition.yml") TEST_CASE_FILE = os.path.join("components", "idf_test", "unit_test", "TestCaseAll.yml") - UT_BIN_FOLDER = os.path.join("tools", "unit-test-app", "builds") + UT_BIN_FOLDER = os.path.join("tools", "unit-test-app", "output") ELF_FILE = "unit-test-app.elf" - APP_NAME_PREFIX = "UT_" + SDKCONFIG_FILE = "sdkconfig" def __init__(self, idf_path=os.getenv("IDF_PATH")): self.test_env_tags = {} @@ -52,21 +48,24 @@ class Parser(object): self.idf_path = idf_path self.tag_def = yaml.load(open(os.path.join(idf_path, self.TAG_DEF_FILE), "r")) self.module_map = yaml.load(open(os.path.join(idf_path, self.MODULE_DEF_FILE), "r")) + self.config_dependency = yaml.load(open(os.path.join(idf_path, self.CONFIG_DEPENDENCY_FILE), "r")) # used to check if duplicated test case names self.test_case_names = set() self.parsing_errors = [] - def parse_test_cases_from_elf(self, elf_file, app_name): + def parse_test_cases_for_one_config(self, config_output_folder, config_name): """ parse test cases from elf and save test cases need to be executed to unit test folder - :param elf_file: elf file path - :param app_name: built unit test app name + :param config_output_folder: build folder of this config + :param config_name: built unit test config name """ + elf_file = os.path.join(config_output_folder, self.ELF_FILE) subprocess.check_output('xtensa-esp32-elf-objdump -t {} | grep test_desc > case_address.tmp'.format(elf_file), shell=True) subprocess.check_output('xtensa-esp32-elf-objdump -s {} > section_table.tmp'.format(elf_file), shell=True) table = CreateSectionTable.SectionTable("section_table.tmp") + tags = self.parse_tags(os.path.join(config_output_folder, self.SDKCONFIG_FILE)) test_cases = [] with open("case_address.tmp", "r") as f: for line in f: @@ -82,17 +81,17 @@ class Parser(object): name = table.get_string("any", name_addr) desc = table.get_string("any", desc_addr) file_name = table.get_string("any", file_name_addr) - tc = self.parse_one_test_case(name, desc, file_name, app_name) + tc = self.parse_one_test_case(name, desc, file_name, config_name, tags) # check if duplicated case names # we need to use it to select case, # if duplicated IDs, Unity could select incorrect case to run # and we need to check all cases no matter if it's going te be executed by CI # also add app_name here, we allow same case for different apps - if (tc["summary"] + app_name) in self.test_case_names: + if (tc["summary"] + config_name) in self.test_case_names: self.parsing_errors.append("duplicated test case ID: " + tc["summary"]) else: - self.test_case_names.add(tc["summary"] + app_name) + self.test_case_names.add(tc["summary"] + config_name) if tc["CI ready"] == "Yes": # update test env list and the cases of same env list @@ -150,13 +149,32 @@ class Parser(object): pass return p - def parse_one_test_case(self, name, description, file_name, app_name): + def parse_tags(self, sdkconfig_file): + """ + Some test configs could requires different DUTs. + For example, if CONFIG_SPIRAM_SUPPORT is enabled, we need WROVER-Kit to run test. + This method will get tags for runners according to ConfigDependency.yml(maps tags to sdkconfig). + + :param sdkconfig_file: sdkconfig file of the unit test config + :return: required tags for runners + """ + required_tags = [] + with open(sdkconfig_file, "r") as f: + configs_raw_data = f.read() + configs = configs_raw_data.splitlines(False) + for tag in self.config_dependency: + if self.config_dependency[tag] in configs: + required_tags.append(tag) + return required_tags + + def parse_one_test_case(self, name, description, file_name, config_name, tags): """ parse one test case :param name: test case name (summary) :param description: test case description (tag string) :param file_name: the file defines this test case - :param app_name: built unit test app name + :param config_name: built unit test app name + :param tags: tags to select runners :return: parsed test case """ prop = self.parse_case_properities(description) @@ -179,7 +197,7 @@ class Parser(object): self.file_name_cache[file_name_hash]) test_case = deepcopy(TEST_CASE_PATTERN) - test_case.update({"Test App": self.APP_NAME_PREFIX + app_name, + test_case.update({"config": config_name, "module": self.module_map[prop["module"]]['module'], "CI ready": "No" if prop["ignore"] == "Yes" else "Yes", "ID": tc_id, @@ -191,7 +209,8 @@ class Parser(object): "summary": name, "multi_device": prop["multi_device"], "multi_stage": prop["multi_stage"], - "timeout": int(prop["timeout"])}) + "timeout": int(prop["timeout"]), + "tags": tags}) return test_case def dump_test_cases(self, test_cases): @@ -212,12 +231,12 @@ class Parser(object): """ parse test cases from multiple built unit test apps """ test_cases = [] - test_app_folder = os.path.join(self.idf_path, self.UT_BIN_FOLDER) - test_apps = os.listdir(test_app_folder) - for app in test_apps: - elf_file = os.path.join(test_app_folder, app, self.ELF_FILE) - if os.path.exists(elf_file): - test_cases.extend(self.parse_test_cases_from_elf(elf_file, app)) + output_folder = os.path.join(self.idf_path, self.UT_BIN_FOLDER) + test_configs = os.listdir(output_folder) + for config in test_configs: + config_output_folder = os.path.join(output_folder, config) + if os.path.exists(config_output_folder): + test_cases.extend(self.parse_test_cases_for_one_config(config_output_folder, config)) self.dump_test_cases(test_cases) diff --git a/tools/unit-test-app/unit_test.py b/tools/unit-test-app/unit_test.py index e049e7505e..b7453722e5 100644 --- a/tools/unit-test-app/unit_test.py +++ b/tools/unit-test-app/unit_test.py @@ -131,6 +131,7 @@ def run_unit_test_cases(env, extra_data): failed_cases = [] for ut_config in case_config: + Utility.console_log("Running unit test for config: " + ut_config, "O") dut = env.get_dut("unit-test-app", app_path=ut_config) dut.start_app() @@ -365,6 +366,7 @@ def run_multiple_devices_cases(env, extra_data): case_config = format_test_case_config(extra_data) DUTS = {} for ut_config in case_config: + Utility.console_log("Running unit test for config: " + ut_config, "O") for one_case in case_config[ut_config]: case_run(DUTS, ut_config, env, one_case, failed_cases) @@ -396,6 +398,7 @@ def run_multiple_stage_cases(env, extra_data): failed_cases = [] for ut_config in case_config: + Utility.console_log("Running unit test for config: " + ut_config, "O") dut = env.get_dut("unit-test-app", app_path=ut_config) dut.start_app() From a68b93d6f305efbb1a924a5379290b35e6f37216 Mon Sep 17 00:00:00 2001 From: He Yin Ling Date: Tue, 15 May 2018 17:41:57 +0800 Subject: [PATCH 168/187] tiny-test-fw: show descriptive error when test case assignment fails: Will give hint when any job failed to assign: ``` Please add the following jobs to .gitlab-ci.yml with specific tags: * Add job with: psram, ESP32_IDF, UT_T1_1 * Add job with: psram, ESP32_IDF, UT_T1_1 ``` --- tools/tiny-test-fw/Utility/CIAssignTest.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/tiny-test-fw/Utility/CIAssignTest.py b/tools/tiny-test-fw/Utility/CIAssignTest.py index ca0204aaba..d4c5b723db 100644 --- a/tools/tiny-test-fw/Utility/CIAssignTest.py +++ b/tools/tiny-test-fw/Utility/CIAssignTest.py @@ -45,7 +45,7 @@ import json import yaml -from Utility import (CaseConfig, SearchCases, GitlabCIJob) +from Utility import (CaseConfig, SearchCases, GitlabCIJob, console_log) class Group(object): @@ -206,7 +206,11 @@ class AssignTest(object): break else: failed_to_assign.append(group) - assert not failed_to_assign + if failed_to_assign: + console_log("Please add the following jobs to .gitlab-ci.yml with specific tags:", "R") + for group in failed_to_assign: + console_log("* Add job with: " + ",".join(group.ci_job_match_keys), "R") + raise RuntimeError("Failed to assign test case to CI jobs") def output_configs(self, output_path): """ From eaedb2272ef0db3b7009dac5e3040d192e195ffa Mon Sep 17 00:00:00 2001 From: He Yin Ling Date: Tue, 15 May 2018 23:04:21 +0800 Subject: [PATCH 169/187] CI: remove unnecessary artifacts of assign_test --- .gitlab-ci.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9c83055ea7..e790ddf1d6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -505,23 +505,16 @@ assign_test: - build_ssc_02 - build_esp_idf_tests variables: - UT_BIN_PATH: "tools/unit-test-app/output" - OUTPUT_BIN_PATH: "test_bins/ESP32_IDF" TEST_FW_PATH: "$CI_PROJECT_DIR/tools/tiny-test-fw" EXAMPLE_CONFIG_OUTPUT_PATH: "$CI_PROJECT_DIR/examples/test_configs" artifacts: paths: - - $OUTPUT_BIN_PATH - components/idf_test/*/CIConfigs - components/idf_test/*/TC.sqlite - $EXAMPLE_CONFIG_OUTPUT_PATH - - tools/unit-test-app/output expire_in: 1 mos before_script: *add_gitlab_key_before script: - # first move test bins together: test_bins/CHIP_SDK/TestApp/bin_files - - mkdir -p $OUTPUT_BIN_PATH - - cp -r SSC/ssc_bin/* $OUTPUT_BIN_PATH # assign example tests - python $TEST_FW_PATH/CIAssignExampleTest.py $IDF_PATH/examples $IDF_PATH/.gitlab-ci.yml $EXAMPLE_CONFIG_OUTPUT_PATH # assign unit test cases @@ -572,6 +565,7 @@ assign_test: stage: unit_test dependencies: - assign_test + - build_esp_idf_tests variables: TEST_FW_PATH: "$CI_PROJECT_DIR/tools/tiny-test-fw" TEST_CASE_PATH: "$CI_PROJECT_DIR/tools/unit-test-app" From 1a1514b69c26f891d3cc30f4ff0d778cfffe1945 Mon Sep 17 00:00:00 2001 From: He Yin Ling Date: Tue, 22 May 2018 14:33:35 +0800 Subject: [PATCH 170/187] unit-test-app: udpate CI related part to README --- tools/unit-test-app/README.md | 83 +++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/tools/unit-test-app/README.md b/tools/unit-test-app/README.md index 1f06be55bf..d3581d0233 100644 --- a/tools/unit-test-app/README.md +++ b/tools/unit-test-app/README.md @@ -10,6 +10,7 @@ ESP-IDF unit tests are run using Unit Test App. The app can be built with the un * `make menuconfig` to configure the Unit Test App. * `make TEST_COMPONENTS=` with `TEST_COMPONENTS` set to names of the components to be included in the test app. Or `make TESTS_ALL=1` to build the test app with all the tests for components having `test` subdirectory. * Follow the printed instructions to flash, or run `make flash`. +* Unit test have a few preset sdkconfigs. It provides command `make ut-clean-config_name` and `make ut-build-config_name` (where `config_name` is the file name under `unit-test-app/configs` folder) to build with preset configs. For example, you can use `make ut-build-default TESTS_ALL=1` to build with config file `unit-test-app/configs/default`. Built binary for this config will be copied to `unit-test-app/output/config_name` folder. # Running Unit Tests @@ -20,3 +21,85 @@ The unit test loader will prompt by showing a menu of available tests to run: * `[tagname]` to run tests with "tag" * `![tagname]` to run tests without "tag" (`![ignore]` is very useful as it runs all CI-enabled tests.) * `"test name here"` to run test with given name + +# Testing Unit Tests with CI + +## CI Test Flow for Unit Test + +Unit test uses 3 stages in CI: `build`, `assign_test`, `unit_test`. + +### Build Stage: + +`build_esp_idf_tests` job will build all UT configs and parse test cases form built elf files. Built binary (`tools/unit-test-app/output`) and parsed cases (`components/idf_test/unit_test/TestCaseAll.yml`) will be saved as artifacts. + +When we add new test case, it will construct a structure to save case data during build. We'll parse the test case from this structure. The description (defined in test case: `TEST_CASE("name", "description")`) is used to extend test case definition. The format of test description is a list of tags: + +1. first tag is always group of test cases, it's mandatory +2. the rest tags should be [type=value]. Tags could have default value and omitted value. For example, reset tag default value is "POWERON_RESET", omitted value is "" (do not reset) : + * "[reset]" equal to [reset=POWERON_RESET] + * if reset tag doesn't exist, then it equals to [reset=""] + +`TagDefinition.yml` defines how we should parse the description. In `TagDefinition.yml`, we declare the tags we are interested in, their default value and omitted value. Parser will parse the properities of test cases according to this file, and add them as test case attributes. + +We will build unit-test-app with different sdkconfigs. Some config items requires specific board to run. For example, if `CONFIG_SPIRAM_SUPPORT` is enabled, then unit test app must run on board supports PSRAM. `ConfigDependency.yml` is used to define the mapping between sdkconfig items and tags. The tags will be saved as case attributes, used to select jobs and runners. In the previous example, `psram` tag is generated, will only select jobs and runners also contains `psram` tag. + +### Assign Test Stage: + +`assign_test` job will try to assign all cases to test jobs defined in `.gitlab-ci.yml`, according to test environment and tags. For each job, one config file with same name of test job will be generated in `components/idf_test/unit_test/CIConfigs/`(this folder will be passed to test jobs as artifacts). These config files will tell test jobs which cases it need to run, and pass some extra configs (like if the case will reset) of test case to runner. + +Please check related document in tiny-test-fw for details. + +### Unit Test Stage: + +All jobs in `unit_test` stage will run job according to unit test configs. Then unit test jobs will use tiny-test-fw runner to run the test cases. The test logs will be saved as artifacts. + +Unit test jobs will do reset before running each case (because some cases do not cleanup when failed). This makes test cases independent with each other during execution. + +## Handle Unit Test CI Issues + +### 1. Assign Test Failures + +Gitlab CI do not support create jobs at runtime. We must maunally add all jobs to CI config file. To make test running in parallel, we limit the number of cases running on each job. When add new unit test cases, it could exceed the limitation that current unit test jobs support. In this case, assign test job will raise error, remind you to add jobs to `.gitlab-ci.yml`. + +``` +Please add the following jobs to .gitlab-ci.yml with specific tags: +* Add job with: UT_T1_1, ESP32_IDF, psram +* Add job with: UT_T1_1, ESP32_IDF +``` + +The above is an example of error message in assign test job. In this case, please add the following jobs in `.gitlab-ci.yml`: + +``` +UT_001_25: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + +UT_004_09: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + - psram +``` + +The naming rule of jobs are `UT` + `job type index` + `job index`. Each combination of tags is a different job type. + +### 2. Debugging Failed Cases + +First you can check the logs. It's saved as unit test job artifacts. You can download from the test job page. + +If you want to reproduce locally, you need to: + +1. Download artifacts of `build_esp_idf_tests`. The built binary is in `tools/unit-test-app/output` folder. + * Built binary in CI could be slightly different from locally built binary with the same revision, some cases might only fails with CI built binary. +2. Check the following print in CI job to get the config name: `Running unit test for config: config_name`. Then flash the binary of this config to your board. +3. Run the failed case on your board (refer to Running Unit Tests section). + * There're some special UT cases (multiple stages case, multiple devices cases) which requires user interaction: + * You can refer to [unit test document](https://esp-idf.readthedocs.io/en/latest/api-guides/unit-tests.html#running-unit-tests) to run test manually. + * Or, you can use `tools/unit-test-app/unit_test.py` to run the test cases: + * read document of tiny-test-fw, set correct `TEST_FW_PATH` and `IDF_PATH` + * modify `unit_test.py`, pass the test cases need to test as parameter (refer to test function doc string for supported parameter format) to test functions. + * use `python unit_test.py` to run test + * You can also use `tools/tiny-test-fw/Runner.py` to run test cases (it will be the same as what Runner do). Please use `python Runner.py -c $CONFIG_FILE $IDF_PATH/tools/unit-test-app` command, where `CONFIG_FILE` is a YAML file with same name with CI job in `components/idf_test/unit_test/CIConfigs` (artifacts, need to be download from `assign_test` job). From 5f39b58b8373e117ac7ce74e31a5821b61613232 Mon Sep 17 00:00:00 2001 From: Tian Hao Date: Thu, 24 May 2018 15:47:16 +0800 Subject: [PATCH 171/187] component/bt : fix bug that assert rwbt.c 265 8192 error --- components/bt/lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/bt/lib b/components/bt/lib index 7c55331605..cfd66eb9b7 160000 --- a/components/bt/lib +++ b/components/bt/lib @@ -1 +1 @@ -Subproject commit 7c55331605beefea4882efc4343c23b28eb38d83 +Subproject commit cfd66eb9b77d6d98dae79ba505378f438b2ef095 From ae10abff2f70aa1488b355093477fd63405b06ab Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Mon, 23 Apr 2018 17:19:04 +0500 Subject: [PATCH 172/187] bootloader: Add factory reset and start test app Added feature: - reset firmware to Factory app.(by long pressing of the button) - boot Test app. (by long pressing of the button) - Added feature erase data partitions from factory reset. TW10281 TW10280 --- components/bootloader/Kconfig.projbuild | 65 +++++++++ .../subproject/main/bootloader_start.c | 31 ++++- .../include/bootloader_common.h | 39 ++++++ .../src/bootloader_common.c | 129 ++++++++++++++++++ .../src/bootloader_utility.c | 16 ++- .../test/test_verify_image.c | 47 ++++++- docs/en/api-guides/bootloader.rst | 45 ++++++ 7 files changed, 365 insertions(+), 7 deletions(-) diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index 18989dc089..f5394dc274 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -62,6 +62,71 @@ config BOOTLOADER_VDDSDIO_BOOST_1_9V bool "1.9V" endchoice +config BOOTLOADER_FACTORY_RESET + bool "GPIO triggers factory reset" + default N + help + Allows to reset the device to factory settings: + - clear one or more data partitions; + - boot from "factory" partition. + The factory reset will occur if there is a GPIO input pulled low while device starts up. + See settings below. + +config BOOTLOADER_NUM_PIN_FACTORY_RESET + int "Number of the GPIO input for factory reset" + depends on BOOTLOADER_FACTORY_RESET + range 0 39 + default 4 + help + The selected GPIO will be configured as an input with internal pull-up enabled. + To trigger a factory reset, this GPIO must be pulled low on reset. + Note that GPIO34-39 do not have an internal pullup and an external one must be provided. + +config BOOTLOADER_OTA_DATA_ERASE + bool "Clear OTA data on factory reset (select factory partition)" + depends on BOOTLOADER_FACTORY_RESET + help + The device will boot from "factory" partition (or OTA slot 0 if no factory partition is present) after a factory reset. + +config BOOTLOADER_DATA_FACTORY_RESET + string "Comma-separated names of partitions to clear on factory reset" + depends on BOOTLOADER_FACTORY_RESET + default "nvs" + help + Allows customers to select which data partitions will be erased while factory reset. + + Specify the names of partitions as a comma-delimited with optional spaces for readability. (Like this: "nvs, phy_init, ...") + Make sure that the name specified in the partition table and here are the same. + Partitions of type "app" cannot be specified here. + +config BOOTLOADER_APP_TEST + bool "GPIO triggers boot from test app partition" + default N + help + Allows to run the test app from "TEST" partition. + A boot from "test" partition will occur if there is a GPIO input pulled low while device starts up. + See settings below. + +config BOOTLOADER_NUM_PIN_APP_TEST + int "Number of the GPIO input to boot TEST partition" + depends on BOOTLOADER_APP_TEST + range 0 39 + default 18 + help + The selected GPIO will be configured as an input with internal pull-up enabled. + To trigger a test app, this GPIO must be pulled low on reset. + After the GPIO input is deactivated and the device reboots, the old application will boot. + (factory or OTA[x]). + Note that GPIO34-39 do not have an internal pullup and an external one must be provided. + +config BOOTLOADER_HOLD_TIME_GPIO + int "Hold time of GPIO for reset/test mode (seconds)" + depends on BOOTLOADER_FACTORY_RESET || BOOTLOADER_APP_TEST + default 5 + help + The GPIO must be held low continuously for this period of time after reset + before a factory reset or test partition boot (as applicable) is performed. + endmenu # Bootloader diff --git a/components/bootloader/subproject/main/bootloader_start.c b/components/bootloader/subproject/main/bootloader_start.c index 6abad59109..64af8268e4 100644 --- a/components/bootloader/subproject/main/bootloader_start.c +++ b/components/bootloader/subproject/main/bootloader_start.c @@ -17,6 +17,7 @@ #include "esp_log.h" #include "rom/gpio.h" +#include "rom/spi_flash.h" #include "bootloader_config.h" #include "bootloader_init.h" #include "bootloader_utility.h" @@ -83,7 +84,35 @@ static int selected_boot_partition(const bootloader_state_t *bs) if (boot_index == INVALID_INDEX) { return boot_index; // Unrecoverable failure (not due to corrupt ota data or bad partition contents) } else { - // Check for reset to the factory firmware or for launch OTA[x] firmware. + // Factory firmware. +#ifdef CONFIG_BOOTLOADER_FACTORY_RESET + if (bootloader_common_check_long_hold_gpio(CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET, CONFIG_BOOTLOADER_HOLD_TIME_GPIO) == 1) { + ESP_LOGI(TAG, "Detect a condition of the factory reset"); + bool ota_data_erase = false; +#ifdef CONFIG_BOOTLOADER_OTA_DATA_ERASE + ota_data_erase = true; +#endif + const char *list_erase = CONFIG_BOOTLOADER_DATA_FACTORY_RESET; + ESP_LOGI(TAG, "Data partitions to erase: %s", list_erase); + if (bootloader_common_erase_part_type_data(list_erase, ota_data_erase) == false) { + ESP_LOGE(TAG, "Not all partitions were erased"); + } + return bootloader_utility_get_selected_boot_partition(bs); + } +#endif + // TEST firmware. +#ifdef CONFIG_BOOTLOADER_APP_TEST + if (bootloader_common_check_long_hold_gpio(CONFIG_BOOTLOADER_NUM_PIN_APP_TEST, CONFIG_BOOTLOADER_HOLD_TIME_GPIO) == 1) { + ESP_LOGI(TAG, "Detect a boot condition of the test firmware"); + if (bs->test.offset != 0) { + boot_index = TEST_APP_INDEX; + return boot_index; + } else { + ESP_LOGE(TAG, "Test firmware is not found in partition table"); + return INVALID_INDEX; + } + } +#endif // Customer implementation. // if (gpio_pin_1 == true && ...){ // boot_index = required_boot_partition; diff --git a/components/bootloader_support/include/bootloader_common.h b/components/bootloader_support/include/bootloader_common.h index 36eea822d9..07fc9341c5 100644 --- a/components/bootloader_support/include/bootloader_common.h +++ b/components/bootloader_support/include/bootloader_common.h @@ -13,6 +13,14 @@ // limitations under the License. #pragma once +#include "esp_flash_data_types.h" + +/// Type of hold a GPIO in low state +typedef enum { + GPIO_LONG_HOLD = 1, /*!< The long hold GPIO */ + GPIO_SHORT_HOLD = -1, /*!< The short hold GPIO */ + GPIO_NOT_HOLD = 0 /*!< If the GPIO input is not low */ +} esp_comm_gpio_hold_t; /** * @brief Calculate crc for the OTA data partition. @@ -29,3 +37,34 @@ uint32_t bootloader_common_ota_select_crc(const esp_ota_select_entry_t *s); * @return Returns true on valid, false otherwise. */ bool bootloader_common_ota_select_valid(const esp_ota_select_entry_t *s); + +/** + * @brief Check if the GPIO input is a long hold or a short hold. + * + * Number of the GPIO input will be configured as an input with internal pull-up enabled. + * If the GPIO input is held low continuously for delay_sec period then it is a long hold. + * If the GPIO input is held low for less period then it is a short hold. + * + * @param[in] num_pin Number of the GPIO input. + * @param[in] delay_sec Input must be driven low for at least this long, continuously. + * @return esp_comm_gpio_hold_t Defines type of hold a GPIO in low state. + */ +esp_comm_gpio_hold_t bootloader_common_check_long_hold_gpio(uint32_t num_pin, uint32_t delay_sec); + +/** + * @brief Erase the partition data that is specified in the transferred list. + * + * @param[in] list_erase String containing a list of cleared partitions. Like this "nvs, phy". The string must be null-terminal. + * @param[in] ota_data_erase If true then the OTA data partition will be cleared (if there is it in partition table). + * @return Returns true on success, false otherwise. + */ +bool bootloader_common_erase_part_type_data(const char *list_erase, bool ota_data_erase); + +/** + * @brief Determines if the list contains the label + * + * @param[in] list A string of names delimited by commas or spaces. Like this "nvs, phy, data". The string must be null-terminated. + * @param[in] label The substring that will be searched in the list. + * @return Returns true if the list contains the label, false otherwise. + */ +bool bootloader_common_label_search(const char *list, char *label); diff --git a/components/bootloader_support/src/bootloader_common.c b/components/bootloader_support/src/bootloader_common.c index 0e3722ed98..0d72c3e119 100644 --- a/components/bootloader_support/src/bootloader_common.c +++ b/components/bootloader_support/src/bootloader_common.c @@ -12,8 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. #include +#include +#include "string.h" +#include "sdkconfig.h" +#include "esp_err.h" +#include "esp_log.h" +#include "rom/spi_flash.h" #include "rom/crc.h" +#include "rom/ets_sys.h" +#include "rom/gpio.h" #include "esp_flash_data_types.h" +#include "esp_secure_boot.h" +#include "esp_flash_partitions.h" +#include "bootloader_flash.h" +#include "bootloader_common.h" + +static const char* TAG = "boot_comm"; uint32_t bootloader_common_ota_select_crc(const esp_ota_select_entry_t *s) { @@ -24,3 +38,118 @@ bool bootloader_common_ota_select_valid(const esp_ota_select_entry_t *s) { return s->ota_seq != UINT32_MAX && s->crc == bootloader_common_ota_select_crc(s); } + +esp_comm_gpio_hold_t bootloader_common_check_long_hold_gpio(uint32_t num_pin, uint32_t delay_sec) +{ + gpio_pad_select_gpio(num_pin); + gpio_pad_pullup(num_pin); + uint32_t tm_start = esp_log_early_timestamp(); + if (GPIO_INPUT_GET(num_pin) == 1) { + return GPIO_NOT_HOLD; + } + do { + if (GPIO_INPUT_GET(num_pin) != 0) { + return GPIO_SHORT_HOLD; + } + } while (delay_sec > ((esp_log_early_timestamp() - tm_start) / 1000L)); + return GPIO_LONG_HOLD; +} + +// Search for a label in the list. list = "nvs1, nvs2, otadata, nvs"; label = "nvs". +bool bootloader_common_label_search(const char *list, char *label) +{ + if (list == NULL || label == NULL) { + return false; + } + const char *sub_list_start_like_label = strstr(list, label); + while (sub_list_start_like_label != NULL) { + + // ["," or " "] + label + ["," or " " or "\0"] + // first character before the label found there must be a delimiter ["," or " "]. + int idx_first = sub_list_start_like_label - list; + if (idx_first == 0 || (idx_first != 0 && (list[idx_first - 1] == ',' || list[idx_first - 1] == ' '))) { + // next character after the label found there must be a delimiter ["," or " " or "\0"]. + int len_label = strlen(label); + if (sub_list_start_like_label[len_label] == 0 || + sub_list_start_like_label[len_label] == ',' || + sub_list_start_like_label[len_label] == ' ') { + return true; + } + } + + // [start_delim] + label + [end_delim] was not found. + // Position is moving to next delimiter if it is not the end of list. + int pos_delim = strcspn(sub_list_start_like_label, ", "); + if (pos_delim == strlen(sub_list_start_like_label)) { + break; + } + sub_list_start_like_label = strstr(&sub_list_start_like_label[pos_delim], label); + } + return false; +} + +bool bootloader_common_erase_part_type_data(const char *list_erase, bool ota_data_erase) +{ + const esp_partition_info_t *partitions; + const char *marker; + esp_err_t err; + int num_partitions; + bool ret = true; + +#ifdef CONFIG_SECURE_BOOT_ENABLED + if (esp_secure_boot_enabled()) { + ESP_LOGI(TAG, "Verifying partition table signature..."); + err = esp_secure_boot_verify_signature(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_MAX_LEN); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to verify partition table signature."); + return false; + } + ESP_LOGD(TAG, "Partition table signature verified"); + } +#endif + + partitions = bootloader_mmap(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_MAX_LEN); + if (!partitions) { + ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_MAX_LEN); + return false; + } + ESP_LOGD(TAG, "mapped partition table 0x%x at 0x%x", ESP_PARTITION_TABLE_ADDR, (intptr_t)partitions); + + err = esp_partition_table_basic_verify(partitions, true, &num_partitions); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to verify partition table"); + ret = false; + } else { + ESP_LOGI(TAG, "## Label Usage Offset Length Cleaned"); + for (int i = 0; i < num_partitions; i++) { + const esp_partition_info_t *partition = &partitions[i]; + char label[sizeof(partition->label) + 1] = {0}; + if (partition->type == PART_TYPE_DATA) { + bool fl_ota_data_erase = false; + if (ota_data_erase == true && partition->subtype == PART_SUBTYPE_DATA_OTA) { + fl_ota_data_erase = true; + } + // partition->label is not null-terminated string. + strncpy(label, (char *)&partition->label, sizeof(partition->label)); + if (fl_ota_data_erase == true || (bootloader_common_label_search(list_erase, label) == true)) { + err = esp_rom_spiflash_erase_area(partition->pos.offset, partition->pos.size); + if (err != ESP_OK) { + ret = false; + marker = "err"; + } else { + marker = "yes"; + } + } else { + marker = "no"; + } + + ESP_LOGI(TAG, "%2d %-16s data %08x %08x [%s]", i, partition->label, + partition->pos.offset, partition->pos.size, marker); + } + } + } + + bootloader_munmap(partitions); + + return ret; +} diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index 883f937b03..eeaee21798 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -67,7 +67,6 @@ static void set_cache_and_start_app(uint32_t drom_addr, bool bootloader_utility_load_partition_table(bootloader_state_t* bs) { const esp_partition_info_t *partitions; - const int ESP_PARTITION_TABLE_DATA_LEN = 0xC00; /* length of actual data (signature is appended to this) */ const char *partition_usage; esp_err_t err; int num_partitions; @@ -75,7 +74,7 @@ bool bootloader_utility_load_partition_table(bootloader_state_t* bs) #ifdef CONFIG_SECURE_BOOT_ENABLED if(esp_secure_boot_enabled()) { ESP_LOGI(TAG, "Verifying partition table signature..."); - err = esp_secure_boot_verify_signature(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_DATA_LEN); + err = esp_secure_boot_verify_signature(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_MAX_LEN); if (err != ESP_OK) { ESP_LOGE(TAG, "Failed to verify partition table signature."); return false; @@ -84,9 +83,9 @@ bool bootloader_utility_load_partition_table(bootloader_state_t* bs) } #endif - partitions = bootloader_mmap(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_DATA_LEN); + partitions = bootloader_mmap(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_MAX_LEN); if (!partitions) { - ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_DATA_LEN); + ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_MAX_LEN); return false; } ESP_LOGD(TAG, "mapped partition table 0x%x at 0x%x", ESP_PARTITION_TABLE_ADDR, (intptr_t)partitions); @@ -292,7 +291,14 @@ bool bootloader_utility_load_boot_image(const bootloader_state_t *bs, int start_ { int index = start_index; esp_partition_pos_t part; - + if(start_index == TEST_APP_INDEX) { + if (try_load_partition(&bs->test, result)) { + return true; + } else { + ESP_LOGE(TAG, "No bootable test partition in the partition table"); + return false; + } + } /* work backwards from start_index, down to the factory app */ for(index = start_index; index >= FACTORY_INDEX; index--) { part = index_to_partition(bs, index); diff --git a/components/bootloader_support/test/test_verify_image.c b/components/bootloader_support/test/test_verify_image.c index a7c3794922..7994667f33 100644 --- a/components/bootloader_support/test/test_verify_image.c +++ b/components/bootloader_support/test/test_verify_image.c @@ -4,6 +4,7 @@ #include #include +#include "string.h" #include "rom/ets_sys.h" #include "freertos/FreeRTOS.h" @@ -12,7 +13,7 @@ #include "freertos/queue.h" #include "freertos/xtensa_api.h" #include "unity.h" - +#include "bootloader_common.h" #include "esp_partition.h" #include "esp_ota_ops.h" #include "esp_image_format.h" @@ -47,3 +48,47 @@ TEST_CASE("Verify unit test app image", "[bootloader_support]") TEST_ASSERT_TRUE(data.image_len <= running->size); } +void check_label_search (int num_test, const char *list, const char *t_label, bool result) +{ + // gen_esp32part.py trims up to 16 characters + // and the string may not have a null terminal symbol. + // below is cutting as it does the generator. + char label[16 + 1] = {0}; + strncpy(label, t_label, sizeof(label) - 1); + + bool ret = bootloader_common_label_search(list, label); + if (ret != result) { + printf("%d) %s | %s \n", num_test, list, label); + } + TEST_ASSERT_MESSAGE(ret == result, "Test failed"); +} + +TEST_CASE("Test label_search", "[bootloader_support]") +{ + TEST_ASSERT_FALSE(bootloader_common_label_search(NULL, NULL)); + TEST_ASSERT_FALSE(bootloader_common_label_search("nvs", NULL)); + + check_label_search(1, "nvs", "nvs", true); + check_label_search(2, "nvs, ", "nvs", true); + check_label_search(3, "nvs1", "nvs", false); + check_label_search(3, "nvs1, ", "nvs", false); + check_label_search(4, "nvs1nvs1, phy", "nvs1", false); + check_label_search(5, "nvs1, nvs1, phy", "nvs1", true); + check_label_search(6, "nvs12, nvs12, phy", "nvs1", false); + check_label_search(7, "nvs12, nvs1, phy", "nvs1", true); + check_label_search(8, "nvs12, nvs3, phy, nvs1","nvs1", true); + check_label_search(9, "nvs1nvs1, phy, nvs", "nvs", true); + check_label_search(10, "nvs1nvs1, phy, nvs1", "nvs", false); + check_label_search(11, "nvs1, nvs, phy, nvs1", "nvs", true); + check_label_search(12, "nvs1, nvs2, phy, nvs","nvs", true); + check_label_search(13, "ota_data, backup_nvs", "nvs", false); + check_label_search(14, "nvs1, nvs2, ota, nvs", "vs1", false); + + check_label_search(20, "12345678901234, phy, nvs1", "12345678901234", true); + check_label_search(21, "123456789012345, phy, nvs1", "123456789012345", true); + check_label_search(22, "1234567890123456, phy, nvs1", "1234567890123456", true); + check_label_search(23, "12345678901234567, phy, nvs1", "12345678901234567", false); + check_label_search(24, "1234567890123456, phy, nvs1", "12345678901234567", true); + check_label_search(25, "phy, 1234567890123456, nvs1", "12345678901234567", true); + +} diff --git a/docs/en/api-guides/bootloader.rst b/docs/en/api-guides/bootloader.rst index 0b4509e640..6e5efbcc04 100644 --- a/docs/en/api-guides/bootloader.rst +++ b/docs/en/api-guides/bootloader.rst @@ -9,7 +9,52 @@ Bootloader performs the following functions: Bootloader is located at the address `0x1000` in the flash. +FACTORY reset +--------------------------- +The user can write a basic working firmware and load it into the factory partition. +Next, update the firmware via OTA (over the air). The updated firmware will be loaded into an OTA app partition slot and the OTA data partition is updated to boot from this partition. +If you want to be able to roll back to the factory firmware and clear the settings, then you need to set :ref:`CONFIG_BOOTLOADER_FACTORY_RESET`. +The factory reset mechanism allows to reset the device to factory settings: + +- Clear one or more data partitions. +- Boot from "factory" partition. + +:ref:`CONFIG_BOOTLOADER_DATA_FACTORY_RESET` allows customers to select which data partitions will be erased when the factory reset is executed. +Can specify the names of partitions through comma-delimited with optional spaces for readability. (Like this: "nvs, phy_init, nvs_custom, ..."). +Make sure that the name specified in the partition table and here are the same. +Partitions of type "app" cannot be specified here. + +:ref:`CONFIG_BOOTLOADER_OTA_DATA_ERASE` - the device will boot from "factory" partition after a factory reset. The OTA data partition will be cleared. + +:ref:`CONFIG_BOOTLOADER_NUM_PIN_FACTORY_RESET`- number of the GPIO input for factory reset uses to trigger a factory reset, this GPIO must be pulled low on reset to trigger this. + +:ref:`CONFIG_BOOTLOADER_HOLD_TIME_GPIO`- this is hold time of GPIO for reset/test mode (by default 5 seconds). The GPIO must be held low continuously for this period of time after reset before a factory reset or test partition boot (as applicable) is performed. + +Partition table.:: + + # Name, Type, SubType, Offset, Size, Flags + # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild + nvs, data, nvs, 0x9000, 0x4000 + otadata, data, ota, 0xd000, 0x2000 + phy_init, data, phy, 0xf000, 0x1000 + factory, 0, 0, 0x10000, 1M + test, 0, test, , 512K + ota_0, 0, ota_0, , 512K + ota_1, 0, ota_1, , 512K + +Boot from TEST firmware +------------------------ +The user can write a special firmware for testing in production, and run it as needed. The partition table also needs a dedicated partition for this testing firmware (See `partition table`). +To trigger a test app you need to set :ref:`CONFIG_BOOTLOADER_APP_TEST`. + +:ref:`CONFIG_BOOTLOADER_NUM_PIN_APP_TEST` - number of the GPIO input to boot TEST partition. The selected GPIO will be configured as an input with internal pull-up enabled. To trigger a test app, this GPIO must be pulled low on reset. +After the GPIO input is deactivated and the device reboots, the old application will boot (factory or any OTA slot). + +:ref:`CONFIG_BOOTLOADER_HOLD_TIME_GPIO` - this is hold time of GPIO for reset/test mode (by default 5 seconds). The GPIO must be held low continuously for this period of time after reset before a factory reset or test partition boot (as applicable) is performed. + Customer bootloader --------------------- The current bootloader implementation allows the customer to override it. To do this, you must copy the folder `/esp-idf/components/bootloader` and then edit `/your_project/components/bootloader/subproject/main/bootloader_main.c`. +In the bootloader space, you can not use the drivers and functions from other components. If necessary, then the required functionality should be placed in the folder bootloader (note that this will increase its size). +It is necessary to monitor its size because there can be overlays in memory with a partition table leading to damage. At the moment the bootloader is limited to the partition table from the address `0x8000`. From 10eab26854da01244135682fe178afe76b499322 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 25 May 2018 12:16:26 +1000 Subject: [PATCH 173/187] unit test app: Require 4MB flash PSRAM config unit tests had outgrown the 0x14000 byte allocated factory size. --- tools/unit-test-app/README.md | 6 ++++++ tools/unit-test-app/partition_table_unit_test_app.csv | 6 ++++-- tools/unit-test-app/sdkconfig.defaults | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/tools/unit-test-app/README.md b/tools/unit-test-app/README.md index d3581d0233..d59e71f74a 100644 --- a/tools/unit-test-app/README.md +++ b/tools/unit-test-app/README.md @@ -12,6 +12,12 @@ ESP-IDF unit tests are run using Unit Test App. The app can be built with the un * Follow the printed instructions to flash, or run `make flash`. * Unit test have a few preset sdkconfigs. It provides command `make ut-clean-config_name` and `make ut-build-config_name` (where `config_name` is the file name under `unit-test-app/configs` folder) to build with preset configs. For example, you can use `make ut-build-default TESTS_ALL=1` to build with config file `unit-test-app/configs/default`. Built binary for this config will be copied to `unit-test-app/output/config_name` folder. +# Flash Size + +The unit test partition table assumes a 4MB flash size. When testing `TESTS_ALL=1`, this additional factory app partition size is required. + +If building unit tests to run on a smaller flash size, edit `partition_table_unit_tests_app.csv` and use `TEST_COMPONENTS=` instead of `TESTS_ALL` if tests don't fit in a smaller factory app partition (exact size will depend on configured options). + # Running Unit Tests The unit test loader will prompt by showing a menu of available tests to run: diff --git a/tools/unit-test-app/partition_table_unit_test_app.csv b/tools/unit-test-app/partition_table_unit_test_app.csv index 46173719b5..5f80c5e79f 100644 --- a/tools/unit-test-app/partition_table_unit_test_app.csv +++ b/tools/unit-test-app/partition_table_unit_test_app.csv @@ -5,10 +5,12 @@ nvs, data, nvs, 0x9000, 0x4000 otadata, data, ota, 0xd000, 0x2000 phy_init, data, phy, 0xf000, 0x1000 -factory, 0, 0, 0x10000, 0x140000 +factory, 0, 0, 0x10000, 0x240000 # these OTA partitions are used for tests, but can't fit real OTA apps in them -# (done this way so tests can run in 2MB of flash.) +# (done this way to reduce total flash usage.) ota_0, 0, ota_0, , 64K ota_1, 0, ota_1, , 64K # flash_test partition used for SPI flash tests, WL FAT tests, and SPIFFS tests flash_test, data, fat, , 528K + +# Note: still 1MB of a 4MB flash left free for some other purpose diff --git a/tools/unit-test-app/sdkconfig.defaults b/tools/unit-test-app/sdkconfig.defaults index e2ca5f4339..a9b24b60e9 100644 --- a/tools/unit-test-app/sdkconfig.defaults +++ b/tools/unit-test-app/sdkconfig.defaults @@ -1,6 +1,6 @@ CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y CONFIG_ESPTOOLPY_BAUD_921600B=y -CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=n CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partition_table_unit_test_app.csv" From d775cc4c4c87dc4b9260abc8e7c8183c0012c748 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 25 May 2018 14:52:41 +1000 Subject: [PATCH 174/187] soc: Fix description of rtc_config_t.tieh, add macros Usage of TIEH was correct but description had 1.8V & 3.3V backwards. Add macro definitions for TIEH values to improve readability. --- components/bootloader_support/src/bootloader_init.c | 2 +- components/esp32/spiram_psram.c | 2 +- components/soc/esp32/include/soc/rtc.h | 5 ++++- components/soc/esp32/rtc_init.c | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/components/bootloader_support/src/bootloader_init.c b/components/bootloader_support/src/bootloader_init.c index 5a1ecd6ab9..73a7995625 100644 --- a/components/bootloader_support/src/bootloader_init.c +++ b/components/bootloader_support/src/bootloader_init.c @@ -276,7 +276,7 @@ static void vddsdio_configure() { #if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config(); - if (cfg.enable == 1 && cfg.tieh == 0) { // VDDSDIO regulator is enabled @ 1.8V + if (cfg.enable == 1 && cfg.tieh == RTC_VDDSDIO_TIEH_1_8V) { // VDDSDIO regulator is enabled @ 1.8V cfg.drefh = 3; cfg.drefm = 3; cfg.drefl = 3; diff --git a/components/esp32/spiram_psram.c b/components/esp32/spiram_psram.c index 50a8571d84..ed20375da8 100644 --- a/components/esp32/spiram_psram.c +++ b/components/esp32/spiram_psram.c @@ -570,7 +570,7 @@ esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vad #if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V // For flash 80Mhz, we must update ldo voltage in case older version of bootloader didn't do this. rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config(); - if (cfg.enable == 1 && cfg.tieh == 0) { // VDDSDIO regulator is enabled @ 1.8V + if (cfg.enable == 1 && cfg.tieh == RTC_VDDSDIO_TIEH_1_8V) { // VDDSDIO regulator is enabled @ 1.8V cfg.drefh = 3; cfg.drefm = 3; cfg.drefl = 3; diff --git a/components/soc/esp32/include/soc/rtc.h b/components/soc/esp32/include/soc/rtc.h index 86beea5342..1ece26c975 100644 --- a/components/soc/esp32/include/soc/rtc.h +++ b/components/soc/esp32/include/soc/rtc.h @@ -578,13 +578,16 @@ typedef struct { */ void rtc_init(rtc_config_t cfg); +#define RTC_VDDSDIO_TIEH_1_8V 0 //!< TIEH field value for 1.8V VDDSDIO +#define RTC_VDDSDIO_TIEH_3_3V 1 //!< TIEH field value for 3.3V VDDSDIO + /** * Structure describing vddsdio configuration */ typedef struct { uint32_t force : 1; //!< If 1, use configuration from RTC registers; if 0, use EFUSE/bootstrapping pins. uint32_t enable : 1; //!< Enable VDDSDIO regulator - uint32_t tieh : 1; //!< Select VDDSDIO voltage: 1 — 1.8V, 0 — 3.3V + uint32_t tieh : 1; //!< Select VDDSDIO voltage. One of RTC_VDDSDIO_TIEH_1_8V, RTC_VDDSDIO_TIEH_3_3V uint32_t drefh : 2; //!< Tuning parameter for VDDSDIO regulator uint32_t drefm : 2; //!< Tuning parameter for VDDSDIO regulator uint32_t drefl : 2; //!< Tuning parameter for VDDSDIO regulator diff --git a/components/soc/esp32/rtc_init.c b/components/soc/esp32/rtc_init.c index 43374d6b02..0fa5d8687d 100644 --- a/components/soc/esp32/rtc_init.c +++ b/components/soc/esp32/rtc_init.c @@ -132,8 +132,8 @@ rtc_vddsdio_config_t rtc_vddsdio_get_config() // Otherwise, VDD_SDIO is controlled by bootstrapping pin uint32_t strap_reg = REG_READ(GPIO_STRAP_REG); result.force = 0; - result.tieh = (strap_reg & BIT(5)) ? 0 : 1; - result.enable = result.tieh == 0; // only power on the regulator if VDD=1.8 + result.tieh = (strap_reg & BIT(5)) ? RTC_VDDSDIO_TIEH_1_8V : RTC_VDDSDIO_TIEH_3_3V; + result.enable = result.tieh == RTC_VDDSDIO_TIEH_1_8V; // only power on the regulator if VDD=1.8 return result; } From 3e1a93e5a747c088414dd74891ff681b77f20f11 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 25 May 2018 14:53:03 +1000 Subject: [PATCH 175/187] soc: rtc_vddsdio_get_config() In default configuration, VDD_SDIO LDO is always enabled When using bootstrapping pin to enable VDD_SDIO, the internal LDO is always enabled at either 1.8V or 3.3V. --- components/soc/esp32/rtc_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/soc/esp32/rtc_init.c b/components/soc/esp32/rtc_init.c index 0fa5d8687d..7236225d43 100644 --- a/components/soc/esp32/rtc_init.c +++ b/components/soc/esp32/rtc_init.c @@ -133,7 +133,7 @@ rtc_vddsdio_config_t rtc_vddsdio_get_config() uint32_t strap_reg = REG_READ(GPIO_STRAP_REG); result.force = 0; result.tieh = (strap_reg & BIT(5)) ? RTC_VDDSDIO_TIEH_1_8V : RTC_VDDSDIO_TIEH_3_3V; - result.enable = result.tieh == RTC_VDDSDIO_TIEH_1_8V; // only power on the regulator if VDD=1.8 + result.enable = 1; return result; } From e6ae121f41006a4c19934b6c3ec4751999c991a9 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Thu, 24 May 2018 10:02:24 +0200 Subject: [PATCH 176/187] VFS select: Correct reseting of socket FDs When using multiple sockets, some of them could be incorrectly removed from the fd_sets before passing these fd_sets forward to the socket select function. Closes https://github.com/espressif/esp-idf/issues/1987 --- components/vfs/test/test_vfs_select.c | 26 ++++++++++++++++++++++++-- components/vfs/vfs.c | 16 +++++++++------- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/components/vfs/test/test_vfs_select.c b/components/vfs/test/test_vfs_select.c index 5febf39a47..be74ebe910 100644 --- a/components/vfs/test/test_vfs_select.c +++ b/components/vfs/test/test_vfs_select.c @@ -33,6 +33,24 @@ typedef struct { static const char message[] = "Hello world!"; +static int open_dummy_socket() +{ + const struct addrinfo hints = { + .ai_family = AF_INET, + .ai_socktype = SOCK_DGRAM, + }; + struct addrinfo *res = NULL; + + const int err = getaddrinfo("localhost", "80", &hints, &res); + TEST_ASSERT_EQUAL(0, err); + TEST_ASSERT_NOT_NULL(res); + + const int dummy_socket_fd = socket(res->ai_family, res->ai_socktype, 0); + TEST_ASSERT(dummy_socket_fd >= 0); + + return dummy_socket_fd; +} + static int socket_init() { const struct addrinfo hints = { @@ -185,11 +203,13 @@ TEST_CASE("socket can do select()", "[vfs]") char recv_message[sizeof(message)]; init(&uart_fd, &socket_fd); + const int dummy_socket_fd = open_dummy_socket(); fd_set rfds; FD_ZERO(&rfds); FD_SET(uart_fd, &rfds); FD_SET(socket_fd, &rfds); + FD_SET(dummy_socket_fd, &rfds); const test_task_param_t test_task_param = { .fd = socket_fd, @@ -199,9 +219,10 @@ TEST_CASE("socket can do select()", "[vfs]") TEST_ASSERT_NOT_NULL(test_task_param.sem); start_task(&test_task_param); - const int s = select(MAX(uart_fd, socket_fd) + 1, &rfds, NULL, NULL, &tv); - TEST_ASSERT_EQUAL(s, 1); + const int s = select(MAX(MAX(uart_fd, socket_fd), dummy_socket_fd) + 1, &rfds, NULL, NULL, &tv); + TEST_ASSERT_EQUAL(1, s); TEST_ASSERT_UNLESS(FD_ISSET(uart_fd, &rfds)); + TEST_ASSERT_UNLESS(FD_ISSET(dummy_socket_fd, &rfds)); TEST_ASSERT(FD_ISSET(socket_fd, &rfds)); int read_bytes = read(socket_fd, recv_message, sizeof(message)); @@ -212,6 +233,7 @@ TEST_CASE("socket can do select()", "[vfs]") vSemaphoreDelete(test_task_param.sem); deinit(uart_fd, socket_fd); + close(dummy_socket_fd); } TEST_CASE("select() timeout", "[vfs]") diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index 36944ddda5..a5f3c74c7d 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -782,13 +782,15 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds continue; } - if (!socket_select && is_socket_fd) { - // no socket_select found yet and the fd is for a socket so take a look - if ((readfds && FD_ISSET(fd, readfds)) || - (writefds && FD_ISSET(fd, writefds)) || - (errorfds && FD_ISSET(fd, errorfds))) { - const vfs_entry_t *vfs = s_vfs[vfs_index]; - socket_select = vfs->vfs.socket_select; + if (is_socket_fd) { + if (!socket_select) { + // no socket_select found yet so take a look + if ((readfds && FD_ISSET(fd, readfds)) || + (writefds && FD_ISSET(fd, writefds)) || + (errorfds && FD_ISSET(fd, errorfds))) { + const vfs_entry_t *vfs = s_vfs[vfs_index]; + socket_select = vfs->vfs.socket_select; + } } continue; } From e86738205d52cecfb5817c80b3bc1fca5f8e317a Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Thu, 24 May 2018 13:47:00 +0200 Subject: [PATCH 177/187] Fix redefinition of select() on platforms where ESP_PLATFORM is discarded Ref: https://github.com/espressif/esp-idf/issues/1987 --- components/lwip/include/lwip/lwip/sockets.h | 9 ++++----- components/lwip/include/lwip/port/lwipopts.h | 2 ++ .../newlib/{include => platform_include}/sys/select.h | 0 3 files changed, 6 insertions(+), 5 deletions(-) rename components/newlib/{include => platform_include}/sys/select.h (100%) diff --git a/components/lwip/include/lwip/lwip/sockets.h b/components/lwip/include/lwip/lwip/sockets.h index 5978b38c49..e9ebff6560 100755 --- a/components/lwip/include/lwip/lwip/sockets.h +++ b/components/lwip/include/lwip/lwip/sockets.h @@ -38,7 +38,6 @@ #if LWIP_SOCKET /* don't build if not configured for use in lwipopts.h */ -#include #include /* for size_t */ #include /* for FD_ZERO */ @@ -590,10 +589,10 @@ static inline int sendto(int s,const void *dataptr,size_t size,int flags,const s { return lwip_sendto_r(s,dataptr,size,flags,to,tolen); } static inline int socket(int domain,int type,int protocol) { return lwip_socket(domain,type,protocol); } -#ifndef ESP_PLATFORM +#ifndef ESP_HAS_SELECT static inline int select(int maxfdp1,fd_set *readset,fd_set *writeset,fd_set *exceptset,struct timeval *timeout) { return lwip_select(maxfdp1,readset,writeset,exceptset,timeout); } -#endif /* ESP_PLATFORM */ +#endif /* ESP_HAS_SELECT */ static inline int ioctlsocket(int s,long cmd,void *argp) { return lwip_ioctl_r(s,cmd,argp); } @@ -646,10 +645,10 @@ static inline int sendto(int s,const void *dataptr,size_t size,int flags,const s { return lwip_sendto(s,dataptr,size,flags,to,tolen); } static inline int socket(int domain,int type,int protocol) { return lwip_socket(domain,type,protocol); } -#ifndef ESP_PLATFORM +#ifndef ESP_HAS_SELECT static inline int select(int maxfdp1,fd_set t*readset,fd_set *writeset,fd_set *exceptset,struct timeval *timeout) { return lwip_select(maxfdp1,readset,writeset,exceptset,timeout); } -#endif /* ESP_PLATFORM */ +#endif /* ESP_HAS_SELECT */ static inline int ioctlsocket(int s,long cmd,void *argp) { return lwip_ioctl(s,cmd,argp); } diff --git a/components/lwip/include/lwip/port/lwipopts.h b/components/lwip/include/lwip/port/lwipopts.h index 4f43ed990c..4d4ceb564f 100644 --- a/components/lwip/include/lwip/port/lwipopts.h +++ b/components/lwip/include/lwip/port/lwipopts.h @@ -39,6 +39,7 @@ #include #include #include +#include #include "esp_task.h" #include "esp_system.h" #include "sdkconfig.h" @@ -730,6 +731,7 @@ #define ESP_DHCP_TIMER 1 #define ESP_LWIP_LOGI(...) ESP_LOGI("lwip", __VA_ARGS__) #define ESP_PING 1 +#define ESP_HAS_SELECT 1 #if CONFIG_LWIP_IRAM_OPTIMIZATION #define ESP_IRAM_ATTR IRAM_ATTR diff --git a/components/newlib/include/sys/select.h b/components/newlib/platform_include/sys/select.h similarity index 100% rename from components/newlib/include/sys/select.h rename to components/newlib/platform_include/sys/select.h From 585df5cfdb835d948d458cfe12fd6b3a72f1f8f9 Mon Sep 17 00:00:00 2001 From: Alexey Gerenkov Date: Fri, 25 May 2018 16:42:18 +0300 Subject: [PATCH 178/187] docs: Corrects OpenOCD command usage in logtrace readme --- examples/system/app_trace_to_host/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/system/app_trace_to_host/README.md b/examples/system/app_trace_to_host/README.md index c7955ceb80..67f6bcb4a5 100644 --- a/examples/system/app_trace_to_host/README.md +++ b/examples/system/app_trace_to_host/README.md @@ -107,21 +107,21 @@ To run the example and retrieve the log from the host, do the following: 6. In telnet execute the following command: ``` - esp32 apptrace start file://adc0.log file://adc1.log 0 9000 5 0 0 + esp32 apptrace start file://adc.log 0 9000 5 0 0 ``` - This command should collect 9000 bytes of log data and save them to `adc0.log` file in `~/esp/openocd-esp32` folder. The `adc1.log` file will be empty / is not used. + This command should collect 9000 bytes of log data and save them to `adc.log` file in `~/esp/openocd-esp32` folder. 7. Decode and print out retrieved log file by executing: ``` - $IDF_PATH/tools/esp_app_trace/logtrace_proc.py ~/esp/openocd-esp32/adc0.log ~/esp/app_trace_to_host/build/app_trace_to_host_test.elf + $IDF_PATH/tools/esp_app_trace/logtrace_proc.py ~/esp/openocd-esp32/adc.log ~/esp/app_trace_to_host/build/app_trace_to_host_test.elf ``` This should provide a similar output: ``` - Parse trace file '/user-home/esp/openocd-esp32/adc0.log'... + Parse trace file '/user-home/esp/openocd-esp32/adc.log'... Unprocessed 7 bytes of log record args! Parsing completed. ==================================================================== From b32b93a607d1e47f1fb4eda6bad8c5154c587e5e Mon Sep 17 00:00:00 2001 From: XiaXiaotian Date: Thu, 19 Oct 2017 17:42:55 +0800 Subject: [PATCH 179/187] Add OS adapter to WiFi driver 1.add os adapter to wifi driver 2.type of encrypt funcs not correct --- components/esp32/fast_crypto_ops.c | 57 +- components/esp32/include/esp_wifi.h | 3 + .../esp32/include/esp_wifi_crypto_types.h | 503 +++++++++++++++++- components/esp32/include/esp_wifi_internal.h | 12 + .../esp32/include/esp_wifi_os_adapter.h | 139 +++++ components/esp32/include/rom/ets_sys.h | 9 + components/esp32/lib | 2 +- components/esp32/phy_init.c | 6 + components/esp32/test/component.mk | 4 + components/esp32/test/test_os_adapter_md5.c | 18 + components/esp32/wifi_internal.c | 116 ---- components/esp32/wifi_os_adapter.c | 498 +++++++++++++++++ .../wpa_supplicant/include/crypto/crypto.h | 2 + .../wpa_supplicant/include/crypto/dh_group5.h | 2 + .../wpa_supplicant/include/crypto/md5.h | 18 +- .../wpa_supplicant/include/crypto/sha1.h | 24 +- .../include/wpa2/eap_peer/eap_methods.h | 1 + components/wpa_supplicant/include/wps/wps.h | 4 +- 18 files changed, 1258 insertions(+), 160 deletions(-) create mode 100644 components/esp32/include/esp_wifi_os_adapter.h create mode 100644 components/esp32/test/test_os_adapter_md5.c delete mode 100644 components/esp32/wifi_internal.c create mode 100644 components/esp32/wifi_os_adapter.c diff --git a/components/esp32/fast_crypto_ops.c b/components/esp32/fast_crypto_ops.c index 2f28a24804..aa0054d707 100644 --- a/components/esp32/fast_crypto_ops.c +++ b/components/esp32/fast_crypto_ops.c @@ -16,8 +16,18 @@ #include "crypto/aes_wrap.h" #include "crypto/sha256.h" #include "crypto/crypto.h" +#include "crypto/md5.h" +#include "crypto/sha1.h" +#include "crypto/aes.h" +#include "crypto/dh_group5.h" +#include "wps/wps.h" +#include "wps/wps_i.h" +#include "wpa2/eap_peer/eap.h" +#include "wpa2/tls/tls.h" +#include "wpa2/eap_peer/eap_methods.h" +#include "wpa2/eap_peer/eap_i.h" +#include "wpa2/eap_peer/eap_common.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 @@ -29,7 +39,22 @@ 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 + .sha256_prf = (esp_sha256_prf_t)fast_sha256_prf, + .hmac_md5 = (esp_hmac_md5_t)hmac_md5, + .hamc_md5_vector = (esp_hmac_md5_vector_t)hmac_md5_vector, + .hmac_sha1 = (esp_hmac_sha1_t)hmac_sha1, + .hmac_sha1_vector = (esp_hmac_sha1_vector_t)hmac_sha1_vector, + .sha1_prf = (esp_sha1_prf_t)sha1_prf, + .sha1_vector = (esp_sha1_vector_t)sha1_vector, + .pbkdf2_sha1 = (esp_pbkdf2_sha1_t)pbkdf2_sha1, + .rc4_skip = (esp_rc4_skip_t)rc4_skip, + .md5_vector = (esp_md5_vector_t)md5_vector, + .aes_encrypt = (esp_aes_encrypt_t)aes_encrypt, + .aes_encrypt_init = (esp_aes_encrypt_init_t)aes_encrypt_init, + .aes_encrypt_deinit = (esp_aes_encrypt_deinit_t)aes_encrypt_deinit, + .aes_decrypt = (esp_aes_decrypt_t)aes_decrypt, + .aes_decrypt_init = (esp_aes_decrypt_init_t)aes_decrypt_init, + .aes_decrypt_deinit = (esp_aes_decrypt_deinit_t)aes_decrypt_deinit }; const wps_crypto_funcs_t g_wifi_default_wps_crypto_funcs = { @@ -38,7 +63,19 @@ const wps_crypto_funcs_t g_wifi_default_wps_crypto_funcs = { .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 + .sha256_vector = (esp_sha256_vector_t)fast_sha256_vector, + .uuid_gen_mac_addr = (esp_uuid_gen_mac_addr_t)uuid_gen_mac_addr, + .dh5_free = (esp_dh5_free_t)dh5_free, + .wps_build_assoc_req_ie = (esp_wps_build_assoc_req_ie_t)wps_build_assoc_req_ie, + .wps_build_assoc_resp_ie = (esp_wps_build_assoc_resp_ie_t)wps_build_assoc_resp_ie, + .wps_build_probe_req_ie = (esp_wps_build_probe_req_ie_t)wps_build_probe_req_ie, + .wps_build_public_key = (esp_wps_build_public_key_t)wps_build_public_key, + .wps_enrollee_get_msg = (esp_wps_enrollee_get_msg_t)wps_enrollee_get_msg, + .wps_enrollee_process_msg = (esp_wps_enrollee_process_msg_t)wps_enrollee_process_msg, + .wps_generate_pin = (esp_wps_generate_pin_t)wps_generate_pin, + .wps_is_selected_pin_registrar = (esp_wps_is_selected_pin_registrar_t)wps_is_selected_pin_registrar, + .wps_is_selected_pbc_registrar = (esp_wps_is_selected_pbc_registrar_t)wps_is_selected_pbc_registrar, + .eap_msg_alloc = (esp_eap_msg_alloc_t)eap_msg_alloc }; /* @@ -56,7 +93,19 @@ const wpa2_crypto_funcs_t g_wifi_default_wpa2_crypto_funcs = { .crypto_cipher_decrypt = (esp_crypto_cipher_decrypt_t)fast_crypto_cipher_decrypt, .crypto_cipher_deinit = (esp_crypto_cipher_deinit_t)fast_crypto_cipher_deinit, .crypto_mod_exp = (esp_crypto_mod_exp_t)crypto_mod_exp, - .sha256_vector = (esp_sha256_vector_t)fast_sha256_vector + .sha256_vector = (esp_sha256_vector_t)fast_sha256_vector, + .tls_init = (esp_tls_init_t)tls_init, + .tls_deinit = (esp_tls_deinit_t)tls_deinit, + .eap_peer_blob_init = (esp_eap_peer_blob_init_t)eap_peer_blob_init, + .eap_peer_blob_deinit = (esp_eap_peer_blob_deinit_t)eap_peer_blob_deinit, + .eap_peer_config_init = (esp_eap_peer_config_init_t)eap_peer_config_init, + .eap_peer_config_deinit = (esp_eap_peer_config_deinit_t)eap_peer_config_deinit, + .eap_deinit_prev_method = (esp_eap_deinit_prev_method_t)eap_deinit_prev_method, + .eap_peer_get_eap_method = (esp_eap_peer_get_eap_method_t)eap_peer_get_eap_method, + .eap_sm_abort = (esp_eap_sm_abort_t)eap_sm_abort, + .eap_sm_build_nak = (esp_eap_sm_build_nak_t)eap_sm_build_nak, + .eap_sm_build_identity_resp = (esp_eap_sm_build_identity_resp_t)eap_sm_build_identity_resp, + .eap_msg_alloc = (esp_eap_msg_alloc_t)eap_msg_alloc }; const mesh_crypto_funcs_t g_wifi_default_mesh_crypto_funcs = { diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h index 02bf87e3da..daaa14f89d 100755 --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -67,6 +67,7 @@ #include "esp_wifi_types.h" #include "esp_wifi_crypto_types.h" #include "esp_event.h" +#include "esp_wifi_os_adapter.h" #ifdef __cplusplus extern "C" { @@ -93,6 +94,7 @@ extern "C" { */ typedef struct { system_event_handler_t event_handler; /**< WiFi event handler */ + wifi_osi_funcs_t* osi_funcs; /**< WiFi OS functions */ 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 */ @@ -176,6 +178,7 @@ extern const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs; #define WIFI_INIT_CONFIG_DEFAULT() { \ .event_handler = &esp_event_send, \ + .osi_funcs = &g_wifi_osi_funcs, \ .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,\ diff --git a/components/esp32/include/esp_wifi_crypto_types.h b/components/esp32/include/esp_wifi_crypto_types.h index c97682daf0..2e605d870c 100644 --- a/components/esp32/include/esp_wifi_crypto_types.h +++ b/components/esp32/include/esp_wifi_crypto_types.h @@ -80,7 +80,7 @@ typedef esp_crypto_hash_t * (*esp_crypto_hash_init_t)(esp_crypto_hash_alg_t alg, * @param len Length of the buffer. * */ -typedef void * (*esp_crypto_hash_update_t)(esp_crypto_hash_t *ctx, const unsigned char *data, int len); +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. @@ -95,7 +95,7 @@ typedef void * (*esp_crypto_hash_update_t)(esp_crypto_hash_t *ctx, const unsigne * 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); +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. @@ -105,7 +105,7 @@ typedef int * (*esp_crypto_hash_finish_t)(esp_crypto_hash_t *ctx, unsigned char * @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); +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. @@ -116,7 +116,7 @@ typedef int * (*esp_aes_128_encrypt_t)(const unsigned char *key, const unsigned * @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); +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. @@ -127,7 +127,7 @@ typedef int * (*esp_aes_128_decrypt_t)(const unsigned char *key, const unsigned * @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); +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. @@ -138,7 +138,7 @@ typedef int * (*esp_aes_wrap_t)(const unsigned char *kek, int n, const unsigned * @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); +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. @@ -162,7 +162,7 @@ typedef esp_crypto_cipher_t * (*esp_crypto_cipher_init_t)(esp_crypto_cipher_alg_ * @param len Length of the plaintext. * */ -typedef int * (*esp_crypto_cipher_encrypt_t)(esp_crypto_cipher_t *ctx, +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. @@ -174,7 +174,7 @@ typedef int * (*esp_crypto_cipher_encrypt_t)(esp_crypto_cipher_t *ctx, * @param len Length of the cipher text. * */ -typedef int * (*esp_crypto_cipher_decrypt_t)(esp_crypto_cipher_t *ctx, +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. @@ -183,7 +183,7 @@ typedef int * (*esp_crypto_cipher_decrypt_t)(esp_crypto_cipher_t *ctx, * @param ctx Context pointer from esp_crypto_cipher_init_t callback function. * */ -typedef void * (*esp_crypto_cipher_deinit_t)(esp_crypto_cipher_t *ctx); +typedef void (*esp_crypto_cipher_deinit_t)(esp_crypto_cipher_t *ctx); /** * @brief The SHA256 callback function when do WPS connect. @@ -195,7 +195,7 @@ typedef void * (*esp_crypto_cipher_deinit_t)(esp_crypto_cipher_t *ctx); * @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, +typedef void (*esp_hmac_sha256_t)(const unsigned char *key, int key_len, const unsigned char *data, int data_len, unsigned char *mac); /** @@ -209,7 +209,7 @@ typedef void * (*esp_hmac_sha256_t)(const unsigned char *key, int key_len, const * @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, +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); /** @@ -224,7 +224,7 @@ typedef void * (*esp_hmac_sha256_vector_t)(const unsigned char *key, int key_len * @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, +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); /** @@ -233,10 +233,10 @@ typedef void * (*esp_sha256_prf_t)(const unsigned char *key, int key_len, const * @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. + * @paramac Buffer for the hash. * */ -typedef int * (*esp_sha256_vector_t)(int num_elem, const unsigned char *addr[], const int *len, +typedef int (*esp_sha256_vector_t)(int num_elem, const unsigned char *addr[], const int *len, unsigned char *mac); /** @@ -253,10 +253,444 @@ typedef int * (*esp_sha256_vector_t)(int num_elem, const unsigned char *addr[], * @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, +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 HMAC-MD5 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 (16 bytes) + * Returns: 0 on success, -1 on failure + */ +typedef int (*esp_hmac_md5_t)(const unsigned char *key, unsigned int key_len, const unsigned char *data, + unsigned int data_len, unsigned char *mac); + +/** + * @brief HMAC-MD5 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 (16 bytes) + * Returns: 0 on success, -1 on failure + */ +typedef int (*esp_hmac_md5_vector_t)(const unsigned char *key, unsigned int key_len, unsigned int num_elem, + const unsigned char *addr[], const unsigned int *len, unsigned char *mac); + +/** + * @brief HMAC-SHA1 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) + * Returns: 0 on success, -1 of failure + */ +typedef int (*esp_hmac_sha1_t)(const unsigned char *key, unsigned int key_len, const unsigned char *data, + unsigned int data_len, unsigned char *mac); + +/** + * @brief HMAC-SHA1 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 (20 bytes) + * Returns: 0 on success, -1 on failure + */ +typedef int (*esp_hmac_sha1_vector_t)(const unsigned char *key, unsigned int key_len, unsigned int num_elem, + const unsigned char *addr[], const unsigned int *len, unsigned char *mac); + +/** + * @brief SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1) + * + * @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 + * Returns: 0 on success, -1 of failure + * + * This function is used to derive new, cryptographically separate keys from a + * given key (e.g., PMK in IEEE 802.11i). + */ +typedef int (*esp_sha1_prf_t)(const unsigned char *key, unsigned int key_len, const char *label, + const unsigned char *data, unsigned int data_len, unsigned char *buf, unsigned int buf_len); + +/** + * @brief SHA-1 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 + */ +typedef int (*esp_sha1_vector_t)(unsigned int num_elem, const unsigned char *addr[], const unsigned int *len, + unsigned char *mac); + +/** + * @brief SHA1-based key derivation function (PBKDF2) for IEEE 802.11i + * + * @passphrase: ASCII passphrase + * @ssid: SSID + * @ssid_len: SSID length in bytes + * @iterations: Number of iterations to run + * @buf: Buffer for the generated key + * @buflen: Length of the buffer in bytes + * Returns: 0 on success, -1 of failure + * + * This function is used to derive PSK for WPA-PSK. For this protocol, + * iterations is set to 4096 and buflen to 32. This function is described in + * IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0. + */ +typedef int (*esp_pbkdf2_sha1_t)(const char *passphrase, const char *ssid, unsigned int ssid_len, + int iterations, unsigned char *buf, unsigned int buflen); + +/** + * @brief XOR RC4 stream to given data with skip-stream-start + * + * @key: RC4 key + * @keylen: RC4 key length + * @skip: number of bytes to skip from the beginning of the RC4 stream + * @data: data to be XOR'ed with RC4 stream + * @data_len: buf length + * Returns: 0 on success, -1 on failure + * + * Generate RC4 pseudo random stream for the given key, skip beginning of the + * stream, and XOR the end result with the data buffer to perform RC4 + * encryption/decryption. + */ +typedef int (*esp_rc4_skip_t)(const unsigned char *key, unsigned int keylen, unsigned int skip, + unsigned char *data, unsigned int data_len); + +/** + * @brief MD5 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 + */ +typedef int (*esp_md5_vector_t)(unsigned int num_elem, const unsigned char *addr[], const unsigned int *len, + unsigned char *mac); + +/** + * @brief Encrypt one AES block + * + * @ctx: Context pointer from aes_encrypt_init() + * @plain: Plaintext data to be encrypted (16 bytes) + * @crypt: Buffer for the encrypted data (16 bytes) + */ +typedef void (*esp_aes_encrypt_t)(void *ctx, const unsigned char *plain, unsigned char *crypt); + +/** + * @brief Initialize AES for encryption + * + * @key: Encryption key + * @len: Key length in bytes (usually 16, i.e., 128 bits) + * Returns: Pointer to context data or %NULL on failure + */ +typedef void * (*esp_aes_encrypt_init_t)(const unsigned char *key, unsigned int len); + +/** + * @brief Deinitialize AES encryption + * + * @ctx: Context pointer from aes_encrypt_init() + */ +typedef void (*esp_aes_encrypt_deinit_t)(void *ctx); + +/** + * @brief Decrypt one AES block + * + * @ctx: Context pointer from aes_encrypt_init() + * @crypt: Encrypted data (16 bytes) + * @plain: Buffer for the decrypted data (16 bytes) + */ +typedef void (*esp_aes_decrypt_t)(void *ctx, const unsigned char *crypt, unsigned char *plain); + +/** + * @brief Initialize AES for decryption + * + * @key: Decryption key + * @len: Key length in bytes (usually 16, i.e., 128 bits) + * Returns: Pointer to context data or %NULL on failure + */ +typedef void * (*esp_aes_decrypt_init_t)(const unsigned char *key, unsigned int len); + +/** + * @brief Deinitialize AES decryption + * + * @ctx: Context pointer from aes_encrypt_init() + */ +typedef void (*esp_aes_decrypt_deinit_t)(void *ctx); + +/** + * @brief Initialize TLS library + * + * @conf: Configuration data for TLS library + * Returns: Context data to be used as tls_ctx in calls to other functions, + * or %NULL on failure. + * + * Called once during program startup and once for each RSN pre-authentication + * session. In other words, there can be two concurrent TLS contexts. If global + * library initialization is needed (i.e., one that is shared between both + * authentication types), the TLS library wrapper should maintain a reference + * counter and do global initialization only when moving from 0 to 1 reference. + */ +typedef void * (*esp_tls_init_t)(void); + +/** + * @brief Deinitialize TLS library + * + * @tls_ctx: TLS context data from tls_init() + * + * Called once during program shutdown and once for each RSN pre-authentication + * session. If global library deinitialization is needed (i.e., one that is + * shared between both authentication types), the TLS library wrapper should + * maintain a reference counter and do global deinitialization only when moving + * from 1 to 0 references. + */ +typedef void (*esp_tls_deinit_t)(void *tls_ctx); + +/** + * @brief Add certificate and private key for connect + + * @sm: eap state machine + * + * Returns: 0 for success, -1 state machine didn't exist, -2 short of certificate or key + */ +typedef int (*esp_eap_peer_blob_init_t)(void *sm); + +/** + * @brief delete the certificate and private + * + * @sm: eap state machine + * + */ +typedef void (*esp_eap_peer_blob_deinit_t)(void *sm); + +/** + * @brief Initialize the eap state machine + * + * @sm: eap state machine + * @private_key_passwd: the start address of private_key_passwd + * @private_key_passwd_len: length of private_key_password + * + * Returns: 0 is success, -1 state machine didn't exist, -2 short of parameters + * + */ +typedef int (*esp_eap_peer_config_init_t)(void *sm, unsigned char *private_key_passwd,int private_key_passwd_len); + +/** + * @brief Deinit the eap state machine + * + * @sm: eap state machine + * + */ +typedef void (*esp_eap_peer_config_deinit_t)(void *sm); + +/** + * @brief Register the eap method + * + * Note: ESP32 only support PEAP/TTLS/TLS three eap methods now. + * + */ +typedef int (*esp_eap_peer_register_methods_t)(void); + +/** + * @brief remove the eap method + * + * Note: ESP32 only support PEAP/TTLS/TLS three eap methods now. + * + */ +typedef void (*esp_eap_peer_unregister_methods_t)(void); + +/** + * @brief remove the eap method before build new connect + * + * @sm: eap state machine + * @txt: not used now + */ +typedef void (*esp_eap_deinit_prev_method_t)(void *sm, const char *txt); + +/** + * @brief Get EAP method based on type number + * + * @vendor: EAP Vendor-Id (0 = IETF) + * @method: EAP type number + * Returns: Pointer to EAP method or %NULL if not found + */ +typedef const void * (*esp_eap_peer_get_eap_method_t)(int vendor, int method); + +/** + * @brief Abort EAP authentication + * + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * + * Release system resources that have been allocated for the authentication + * session without fully deinitializing the EAP state machine. + */ +typedef void (*esp_eap_sm_abort_t)(void *sm); + +/** + * @brief Build EAP-NAK for the current network + * + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @type: EAP type of the fail reason + * @id: EAP identifier for the packet + * + * This function allocates and builds a nak packet for the + * current network. The caller is responsible for freeing the returned data. + */ +typedef void * (*esp_eap_sm_build_nak_t)(void *sm, int type, unsigned char id); + +/** + * @brief Build EAP-Identity/Response for the current network + * + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @id: EAP identifier for the packet + * @encrypted: Whether the packet is for encrypted tunnel (EAP phase 2) + * Returns: Pointer to the allocated EAP-Identity/Response packet or %NULL on + * failure + * + * This function allocates and builds an EAP-Identity/Response packet for the + * current network. The caller is responsible for freeing the returned data. + */ +typedef void * (*esp_eap_sm_build_identity_resp_t)(void *sm, unsigned char id, int encrypted); + +/** + * @brief Allocate a buffer for an EAP message + * + * @vendor: Vendor-Id (0 = IETF) + * @type: EAP type + * @payload_len: Payload length in bytes (data after Type) + * @code: Message Code (EAP_CODE_*) + * @identifier: Identifier + * Returns: Pointer to the allocated message buffer or %NULL on error + * + * This function can be used to allocate a buffer for an EAP message and fill + * in the EAP header. This function is automatically using expanded EAP header + * if the selected Vendor-Id is not IETF. In other words, most EAP methods do + * not need to separately select which header type to use when using this + * function to allocate the message buffers. The returned buffer has room for + * payload_len bytes and has the EAP header and Type field already filled in. + */ +typedef void * (*esp_eap_msg_alloc_t)(int vendor, int type, unsigned int payload_len, + unsigned char code, unsigned char identifier); + +/** + * @brief get the enrollee mac address + * @mac_addr: instore the mac address of enrollee + * @uuid: Universally Unique Identifer of the enrollee + * + */ +typedef void (*esp_uuid_gen_mac_addr_t)(const unsigned char *mac_addr, unsigned char *uuid); + +/** + * @brief free the message after finish DH + * + */ +typedef void * (*esp_dh5_free_t)(void *ctx); + +/** + * @brief Build WPS IE for (Re)Association Request + * + * @req_type: Value for Request Type attribute + * Returns: WPS IE or %NULL on failure + * + * The caller is responsible for freeing the buffer. + */ +typedef void * (*esp_wps_build_assoc_req_ie_t)(int req_type); + +/** + * @brief Build WPS IE for (Re)Association Response + * + * Returns: WPS IE or %NULL on failure + * + * The caller is responsible for freeing the buffer. + */ +typedef void * (*esp_wps_build_assoc_resp_ie_t)(void); + +/** + * @brief Build WPS IE for Probe Request + * + * @pw_id: Password ID (DEV_PW_PUSHBUTTON for active PBC and DEV_PW_DEFAULT for + * most other use cases) + * @dev: Device attributes + * @uuid: Own UUID + * @req_type: Value for Request Type attribute + * @num_req_dev_types: Number of requested device types + * @req_dev_types: Requested device types (8 * num_req_dev_types octets) or + * %NULL if none + * Returns: WPS IE or %NULL on failure + * + * The caller is responsible for freeing the buffer. + */ +typedef void * (*esp_wps_build_probe_req_ie_t)(uint16_t pw_id, void *dev, const unsigned char *uuid, + int req_type, unsigned int num_req_dev_types, const unsigned char *req_dev_types); + +/** + * @brief build public key for exchange in M1 + * + * + */ +typedef int (*esp_wps_build_public_key_t)(void *wps, void *msg, int mode); + + +/** + * @brief get the wps information in exchange password + * + * + */ +typedef void * (*esp_wps_enrollee_get_msg_t)(void *wps, void *op_code); + +/** + * @brief deal with the wps information in exchange password + * + * + */ +typedef int (*esp_wps_enrollee_process_msg_t)(void *wps, int op_code, const void *msg); + +/** + * @brief Generate a random PIN + * + * Returns: Eight digit PIN (i.e., including the checksum digit) + */ +typedef unsigned int (*esp_wps_generate_pin_t)(void); + +/** + * @brief Check whether WPS IE indicates active PIN + * + * @msg: WPS IE contents from Beacon or Probe Response frame + * Returns: 1 if PIN Registrar is active, 0 if not + */ +typedef int (*esp_wps_is_selected_pin_registrar_t)(const void *msg, unsigned char *bssid); + +/** + * @brief Check whether WPS IE indicates active PBC + * + * @msg: WPS IE contents from Beacon or Probe Response frame + * Returns: 1 if PBC Registrar is active, 0 if not + */ +typedef int (*esp_wps_is_selected_pbc_registrar_t)(const void *msg, unsigned char *bssid); + + + /** * @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 @@ -267,6 +701,21 @@ typedef struct { 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 */ + esp_hmac_md5_t hmac_md5; + esp_hmac_md5_vector_t hamc_md5_vector; + esp_hmac_sha1_t hmac_sha1; + esp_hmac_sha1_vector_t hmac_sha1_vector; + esp_sha1_prf_t sha1_prf; + esp_sha1_vector_t sha1_vector; + esp_pbkdf2_sha1_t pbkdf2_sha1; + esp_rc4_skip_t rc4_skip; + esp_md5_vector_t md5_vector; + esp_aes_encrypt_t aes_encrypt; + esp_aes_encrypt_init_t aes_encrypt_init; + esp_aes_encrypt_deinit_t aes_encrypt_deinit; + esp_aes_decrypt_t aes_decrypt; + esp_aes_decrypt_init_t aes_decrypt_init; + esp_aes_decrypt_deinit_t aes_decrypt_deinit; }wpa_crypto_funcs_t; /** @@ -281,6 +730,18 @@ typedef struct{ 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 */ + esp_uuid_gen_mac_addr_t uuid_gen_mac_addr; + esp_dh5_free_t dh5_free; + esp_wps_build_assoc_req_ie_t wps_build_assoc_req_ie; + esp_wps_build_assoc_resp_ie_t wps_build_assoc_resp_ie; + esp_wps_build_probe_req_ie_t wps_build_probe_req_ie; + esp_wps_build_public_key_t wps_build_public_key; + esp_wps_enrollee_get_msg_t wps_enrollee_get_msg; + esp_wps_enrollee_process_msg_t wps_enrollee_process_msg; + esp_wps_generate_pin_t wps_generate_pin; + esp_wps_is_selected_pin_registrar_t wps_is_selected_pin_registrar; + esp_wps_is_selected_pbc_registrar_t wps_is_selected_pbc_registrar; + esp_eap_msg_alloc_t eap_msg_alloc; }wps_crypto_funcs_t; /** @@ -298,6 +759,18 @@ typedef struct { esp_crypto_cipher_deinit_t crypto_cipher_deinit; /**< function used to free context when use TLSV1 */ esp_crypto_mod_exp_t crypto_mod_exp; /**< function used to do key exchange when use TLSV1 */ esp_sha256_vector_t sha256_vector; /**< function used to do X.509v3 certificate parsing and processing */ + esp_tls_init_t tls_init; + esp_tls_deinit_t tls_deinit; + esp_eap_peer_blob_init_t eap_peer_blob_init; + esp_eap_peer_blob_deinit_t eap_peer_blob_deinit; + esp_eap_peer_config_init_t eap_peer_config_init; + esp_eap_peer_config_deinit_t eap_peer_config_deinit; + esp_eap_deinit_prev_method_t eap_deinit_prev_method; + esp_eap_peer_get_eap_method_t eap_peer_get_eap_method; + esp_eap_sm_abort_t eap_sm_abort; + esp_eap_sm_build_nak_t eap_sm_build_nak; + esp_eap_sm_build_identity_resp_t eap_sm_build_identity_resp; + esp_eap_msg_alloc_t eap_msg_alloc; } wpa2_crypto_funcs_t; /** diff --git a/components/esp32/include/esp_wifi_internal.h b/components/esp32/include/esp_wifi_internal.h index 8eb7c0b6bd..875e5ac04a 100755 --- a/components/esp32/include/esp_wifi_internal.h +++ b/components/esp32/include/esp_wifi_internal.h @@ -35,6 +35,7 @@ #include "esp_err.h" #include "esp_wifi_types.h" #include "esp_event.h" +#include "esp_wifi.h" #ifdef __cplusplus extern "C" { @@ -126,6 +127,17 @@ esp_err_t esp_wifi_internal_reg_rxcb(wifi_interface_t ifx, wifi_rxcb_t fn); */ esp_err_t esp_wifi_internal_set_sta_ip(void); +/** + * @brief Check the MD5 values of the OS adapter header files in IDF and WiFi library + * + * @attention 1. It is used for internal CI version check + * + * @return + * - ESP_OK : succeed + * - ESP_WIFI_INVALID_ARG : MD5 check fail + */ +esp_err_t esp_wifi_internal_osi_funcs_md5_check(const char *md5); + /** * @brief Allocate a chunk of memory for WiFi driver * diff --git a/components/esp32/include/esp_wifi_os_adapter.h b/components/esp32/include/esp_wifi_os_adapter.h new file mode 100644 index 0000000000..1dd522c49c --- /dev/null +++ b/components/esp32/include/esp_wifi_os_adapter.h @@ -0,0 +1,139 @@ +// Copyright 2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ESP_WIFI_OS_ADAPTER_H_ +#define ESP_WIFI_OS_ADAPTER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define ESP_WIFI_OS_ADAPTER_VERSION 0x00000001 +#define ESP_WIFI_OS_ADAPTER_MAGIC 0xDEADBEAF + +#define OSI_FUNCS_TIME_BLOCKING 0xffffffff + +#define OSI_QUEUE_SEND_FRONT 0 +#define OSI_QUEUE_SEND_BACK 1 +#define OSI_QUEUE_SEND_OVERWRITE 2 + +typedef struct { + int32_t _version; + void (*_set_isr)(int32_t n, void *f, void *arg); + void (*_ints_on)(uint32_t mask); + void (*_ints_off)(uint32_t mask); + void *(* _spin_lock_create)(void); + void (* _spin_lock_delete)(void *lock); + uint32_t (*_wifi_int_disable)(void *wifi_int_mux); + void (*_wifi_int_restore)(void *wifi_int_mux, uint32_t tmp); + void (*_task_yield)(void); + void (*_task_yield_from_isr)(void); + void *(*_semphr_create)(uint32_t max, uint32_t init); + void (*_semphr_delete)(void *semphr); + int32_t (*_semphr_take_from_isr)(void *semphr, void *hptw); + int32_t (*_semphr_give_from_isr)(void *semphr, void *hptw); + int32_t (*_semphr_take)(void *semphr, uint32_t block_time_tick); + int32_t (*_semphr_give)(void *semphr); + void *(*_mutex_create)(void); + void *(*_recursive_mutex_create)(void); + void (*_mutex_delete)(void *mutex); + int32_t (*_mutex_lock)(void *mutex); + int32_t (*_mutex_unlock)(void *mutex); + void *(* _queue_create)(uint32_t queue_len, uint32_t item_size); + void (* _queue_delete)(void *queue); + int32_t (* _queue_send)(void *queue, void *item, uint32_t block_time_tick); + int32_t (* _queue_send_from_isr)(void *queue, void *item, void *hptw); + int32_t (* _queue_send_to_back)(void *queue, void *item, uint32_t block_time_tick); + int32_t (* _queue_send_to_front)(void *queue, void *item, uint32_t block_time_tick); + int32_t (* _queue_recv)(void *queue, void *item, uint32_t block_time_tick); + int32_t (* _queue_recv_from_isr)(void *queue, void * const item, int32_t * const hptw); + uint32_t (* _queue_msg_waiting)(void *queue); + void *(* _event_group_create)(void); + void (* _event_group_delete)(void *event); + uint32_t (* _event_group_set_bits)(void *event, uint32_t bits); + uint32_t (* _event_group_clear_bits)(void *event, uint32_t bits); + uint32_t (* _event_group_wait_bits)(void *event, uint32_t bits_to_wait_for, int32_t clear_on_exit, int32_t wait_for_all_bits, uint32_t block_time_tick); + int32_t (* _task_create_pinned_to_core)(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id); + int32_t (* _task_create)(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle); + void (* _task_delete)(void *task_handle); + void (* _task_delay)(uint32_t tick); + int32_t (* _task_ms_to_tick)(uint32_t ms); + void *(* _task_get_current_task)(void); + int32_t (* _task_get_max_priority)(void); + int32_t (* _is_in_isr)(void); + void *(* _malloc)(uint32_t size); + void (* _free)(void *p); + uint32_t (* _get_free_heap_size)(void); + uint32_t (* _rand)(void); + void (* _dport_access_stall_other_cpu_start_wrap)(void); + void (* _dport_access_stall_other_cpu_end_wrap)(void); + int32_t (* _phy_rf_init)(const void * init_data, uint32_t mode, void * calibration_data, uint32_t module); + int32_t (* _phy_rf_deinit)(uint32_t module); + void (* _phy_load_cal_and_init)(uint32_t module); + int32_t (* _read_mac)(uint8_t* mac, uint32_t type); + void (* _timer_init)(void); + void (* _timer_deinit)(void); + void (* _timer_arm)(void *timer, uint32_t tmout, bool repeat); + void (* _timer_disarm)(void *timer); + void (* _timer_done)(void *ptimer); + void (* _timer_setfn)(void *ptimer, void *pfunction, void *parg); + void (* _timer_arm_us)(void *ptimer, uint32_t us, bool repeat); + void (* _periph_module_enable)(uint32_t periph); + void (* _periph_module_disable)(uint32_t periph); + int64_t (* _esp_timer_get_time)(void); + int32_t (* _nvs_set_i8)(uint32_t handle, const char* key, int8_t value); + int32_t (* _nvs_get_i8)(uint32_t handle, const char* key, int8_t* out_value); + int32_t (* _nvs_set_u8)(uint32_t handle, const char* key, uint8_t value); + int32_t (* _nvs_get_u8)(uint32_t handle, const char* key, uint8_t* out_value); + int32_t (* _nvs_set_u16)(uint32_t handle, const char* key, uint16_t value); + int32_t (* _nvs_get_u16)(uint32_t handle, const char* key, uint16_t* out_value); + int32_t (* _nvs_open)(const char* name, uint32_t open_mode, uint32_t *out_handle); + void (* _nvs_close)(uint32_t handle); + int32_t (* _nvs_commit)(uint32_t handle); + int32_t (* _nvs_set_blob)(uint32_t handle, const char* key, const void* value, size_t length); + int32_t (* _nvs_get_blob)(uint32_t handle, const char* key, void* out_value, size_t* length); + int32_t (* _nvs_erase_key)(uint32_t handle, const char* key); + int32_t (* _get_random)(uint8_t *buf, size_t len); + int32_t (* _get_time)(void *t); + unsigned long (* _random)(void); + void (* _log_write)(uint32_t level, const char* tag, const char* format, ...); + uint32_t (* _log_timestamp)(void); + void * (* _malloc_internal)(size_t size); + void * (* _realloc_internal)(void *ptr, size_t size); + void * (* _calloc_internal)(size_t n, size_t size); + void * (* _zalloc_internal)(size_t size); + void * (* _wifi_malloc)(size_t size); + void * (* _wifi_realloc)(void *ptr, size_t size); + void * (* _wifi_calloc)(size_t n, size_t size); + void * (* _wifi_zalloc)(size_t size); + void * (* _wifi_create_queue)(int32_t queue_len, int32_t item_size); + void (* _wifi_delete_queue)(void * queue); + int32_t (* _modem_sleep_enter)(uint32_t module); + int32_t (* _modem_sleep_exit)(uint32_t module); + int32_t (* _modem_sleep_register)(uint32_t module); + int32_t (* _modem_sleep_deregister)(uint32_t module); + void (* _sc_ack_send)(void *param); + void (* _sc_ack_send_stop)(void); + int32_t _magic; +} wifi_osi_funcs_t; + +extern wifi_osi_funcs_t g_wifi_osi_funcs; + +#ifdef __cplusplus +} +#endif + +#endif /* ESP_WIFI_OS_ADAPTER_H_ */ diff --git a/components/esp32/include/rom/ets_sys.h b/components/esp32/include/rom/ets_sys.h index 0f972f2c33..6e27b38beb 100644 --- a/components/esp32/include/rom/ets_sys.h +++ b/components/esp32/include/rom/ets_sys.h @@ -301,6 +301,15 @@ typedef struct _ETSTIMER_ { */ void ets_timer_init(void); +/** + * @brief In FreeRTOS, please call FreeRTOS apis, never call this api. + * + * @param None + * + * @return None + */ +void ets_timer_deinit(void); + /** * @brief Arm an ets timer, this timer range is 640 us to 429496 ms. * In FreeRTOS, please call FreeRTOS apis, never call this api. diff --git a/components/esp32/lib b/components/esp32/lib index 8b6d5837a4..f56b7bd412 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 8b6d5837a4215b83ff8a3ff088ccbb716adf05fb +Subproject commit f56b7bd4127aa01dbd50eb8ac3c637690bd98f84 diff --git a/components/esp32/phy_init.c b/components/esp32/phy_init.c index cf1853387d..314f142683 100644 --- a/components/esp32/phy_init.c +++ b/components/esp32/phy_init.c @@ -38,6 +38,7 @@ #include "phy_init_data.h" #include "coexist_internal.h" #include "driver/periph_ctrl.h" +#include "esp_wifi_internal.h" static const char* TAG = "phy_init"; @@ -129,6 +130,11 @@ esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data, esp_phy_calibrat #endif } +extern esp_err_t wifi_osi_funcs_register(wifi_osi_funcs_t *osi_funcs); + status = wifi_osi_funcs_register(&g_wifi_osi_funcs); + if(status != ESP_OK) { + return ESP_FAIL; + } coex_bt_high_prio(); } } diff --git a/components/esp32/test/component.mk b/components/esp32/test/component.mk index 76f6f71328..178dd4cf4d 100644 --- a/components/esp32/test/component.mk +++ b/components/esp32/test/component.mk @@ -8,6 +8,10 @@ COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-a COMPONENT_SRCDIRS := . test_vectors +# Calculate MD5 value of header file esp_wifi_os_adapter.h +WIFI_OS_ADAPTER_MD5_VAL=\"$(shell md5sum $(IDF_PATH)/components/esp32/include/esp_wifi_os_adapter.h | cut -c 1-7)\" +CFLAGS+=-DWIFI_OS_ADAPTER_MD5=$(WIFI_OS_ADAPTER_MD5_VAL) + test_tjpgd.o: test_tjpgd_logo.h test_tjpgd_logo.h: $(COMPONENT_PATH)/logo.jpg diff --git a/components/esp32/test/test_os_adapter_md5.c b/components/esp32/test/test_os_adapter_md5.c new file mode 100644 index 0000000000..315a386081 --- /dev/null +++ b/components/esp32/test/test_os_adapter_md5.c @@ -0,0 +1,18 @@ +/* + Tests for the Wi-Fi +*/ +#include "unity.h" +#include "esp_log.h" +#include "esp_wifi_internal.h" + +static const char* TAG = "test_os_adapter_md5"; + +TEST_CASE("wifi os adapter MD5","[wifi]") +{ + const char *test_wifi_os_funcs_md5 = WIFI_OS_ADAPTER_MD5; + + ESP_LOGI(TAG, "test wifi os adapter MD5..."); + TEST_ESP_OK(esp_wifi_internal_osi_funcs_md5_check(test_wifi_os_funcs_md5)); + + ESP_LOGI(TAG, "test passed..."); +} diff --git a/components/esp32/wifi_internal.c b/components/esp32/wifi_internal.c deleted file mode 100644 index 7d7a772098..0000000000 --- a/components/esp32/wifi_internal.c +++ /dev/null @@ -1,116 +0,0 @@ -// 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 -#include "esp_attr.h" -#include "esp_heap_caps.h" -#include "sdkconfig.h" -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "esp_wifi.h" -#include "esp_wifi_internal.h" - -/* - If CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is enabled. Prefer to allocate a chunk of memory in SPIRAM firstly. - If failed, try to allocate it in internal memory then. - */ -IRAM_ATTR void *wifi_malloc( size_t size ) -{ -#if CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST - return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); -#else - return malloc(size); -#endif -} - -/* - If CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is enabled. Prefer to allocate a chunk of memory in SPIRAM firstly. - If failed, try to allocate it in internal memory then. - */ -IRAM_ATTR void *wifi_realloc( void *ptr, size_t size ) -{ -#if CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST - return heap_caps_realloc_prefer(ptr, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); -#else - return realloc(ptr, size); -#endif -} - -/* - If CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is enabled. Prefer to allocate a chunk of memory in SPIRAM firstly. - If failed, try to allocate it in internal memory then. - */ -IRAM_ATTR void *wifi_calloc( size_t n, size_t size ) -{ -#if CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST - return heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); -#else - return calloc(n, size); -#endif -} - -wifi_static_queue_t* wifi_create_queue( int queue_len, int item_size) -{ - wifi_static_queue_t *queue = NULL; - - queue = (wifi_static_queue_t*)heap_caps_malloc(sizeof(wifi_static_queue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); - if (!queue) { - return NULL; - } - -#if CONFIG_SPIRAM_USE_MALLOC - - queue->storage = heap_caps_calloc(1, sizeof(StaticQueue_t) + (queue_len*item_size), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); - if (!queue->storage) { - goto _error; - } - - queue->handle = xQueueCreateStatic( queue_len, item_size, ((uint8_t*)(queue->storage)) + sizeof(StaticQueue_t), (StaticQueue_t*)(queue->storage)); - - if (!queue->handle) { - goto _error; - } - - return queue; - -_error: - if (queue) { - if (queue->storage) { - free(queue->storage); - } - - free(queue); - } - - return NULL; -#else - queue->handle = xQueueCreate( queue_len, item_size); - return queue; -#endif -} - -void wifi_delete_queue(wifi_static_queue_t *queue) -{ - if (queue) { - vQueueDelete(queue->handle); - -#if CONFIG_SPIRAM_USE_MALLOC - if (queue->storage) { - free(queue->storage); - } -#endif - - free(queue); - } -} diff --git a/components/esp32/wifi_os_adapter.c b/components/esp32/wifi_os_adapter.c new file mode 100644 index 0000000000..e63b0135fc --- /dev/null +++ b/components/esp32/wifi_os_adapter.c @@ -0,0 +1,498 @@ +// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "freertos/event_groups.h" +#include "freertos/xtensa_api.h" +#include "freertos/portmacro.h" +#include "freertos/xtensa_api.h" +#include "esp_types.h" +#include "esp_system.h" +#include "esp_task.h" +#include "esp_intr.h" +#include "esp_attr.h" +#include "esp_log.h" +#include "esp_heap_caps.h" +#include "esp_wifi_os_adapter.h" +#include "esp_wifi_internal.h" +#include "esp_phy_init.h" +#include "crypto/md5.h" +#include "crypto/sha1.h" +#include "crypto/crypto.h" +#include "crypto/aes.h" +#include "crypto/dh_group5.h" +#include "driver/periph_ctrl.h" +#include "nvs.h" +#include "os.h" +#include "esp_smartconfig.h" +#include "smartconfig_ack.h" + + +extern void esp_dport_access_stall_other_cpu_start_wrap(void); +extern void esp_dport_access_stall_other_cpu_end_wrap(void); + +/* + If CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is enabled. Prefer to allocate a chunk of memory in SPIRAM firstly. + If failed, try to allocate it in internal memory then. + */ +IRAM_ATTR void *wifi_malloc( size_t size ) +{ +#if CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST + return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); +#else + return malloc(size); +#endif +} + +/* + If CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is enabled. Prefer to allocate a chunk of memory in SPIRAM firstly. + If failed, try to allocate it in internal memory then. + */ +IRAM_ATTR void *wifi_realloc( void *ptr, size_t size ) +{ +#if CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST + return heap_caps_realloc_prefer(ptr, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); +#else + return realloc(ptr, size); +#endif +} + +/* + If CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is enabled. Prefer to allocate a chunk of memory in SPIRAM firstly. + If failed, try to allocate it in internal memory then. + */ +IRAM_ATTR void *wifi_calloc( size_t n, size_t size ) +{ +#if CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST + return heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); +#else + return calloc(n, size); +#endif +} + +static void * IRAM_ATTR wifi_zalloc_wrapper(size_t size) +{ + void *ptr = wifi_calloc(1, size); + if (ptr) { + memset(ptr, 0, size); + } + return ptr; +} + +wifi_static_queue_t* wifi_create_queue( int queue_len, int item_size) +{ + wifi_static_queue_t *queue = NULL; + + queue = (wifi_static_queue_t*)heap_caps_malloc(sizeof(wifi_static_queue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + if (!queue) { + return NULL; + } + +#if CONFIG_SPIRAM_USE_MALLOC + + queue->storage = heap_caps_calloc(1, sizeof(StaticQueue_t) + (queue_len*item_size), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + if (!queue->storage) { + goto _error; + } + + queue->handle = xQueueCreateStatic( queue_len, item_size, ((uint8_t*)(queue->storage)) + sizeof(StaticQueue_t), (StaticQueue_t*)(queue->storage)); + + if (!queue->handle) { + goto _error; + } + + return queue; + +_error: + if (queue) { + if (queue->storage) { + free(queue->storage); + } + + free(queue); + } + + return NULL; +#else + queue->handle = xQueueCreate( queue_len, item_size); + return queue; +#endif +} + +void wifi_delete_queue(wifi_static_queue_t *queue) +{ + if (queue) { + vQueueDelete(queue->handle); + +#if CONFIG_SPIRAM_USE_MALLOC + if (queue->storage) { + free(queue->storage); + } +#endif + + free(queue); + } +} + +static void * IRAM_ATTR wifi_create_queue_wrapper(int queue_len, int item_size) +{ + return wifi_create_queue(queue_len, item_size); +} + +static void IRAM_ATTR wifi_delete_queue_wrapper(void *queue) +{ + wifi_delete_queue(queue); +} + +static void IRAM_ATTR set_isr_wrapper(int32_t n, void *f, void *arg) +{ + xt_set_interrupt_handler(n, (xt_handler)f, arg); +} + +static void * IRAM_ATTR spin_lock_create_wrapper(void) +{ + portMUX_TYPE tmp = portMUX_INITIALIZER_UNLOCKED; + void *mux = malloc(sizeof(portMUX_TYPE)); + + if (mux) { + memcpy(mux,&tmp,sizeof(portMUX_TYPE)); + return mux; + } + return NULL; +} + +static uint32_t IRAM_ATTR wifi_int_disable_wrapper(void *wifi_int_mux) +{ + if (xPortInIsrContext()) { + portENTER_CRITICAL_ISR(wifi_int_mux); + } else { + portENTER_CRITICAL(wifi_int_mux); + } + + return 0; +} + +static void IRAM_ATTR wifi_int_restore_wrapper(void *wifi_int_mux, uint32_t tmp) +{ + if (xPortInIsrContext()) { + portEXIT_CRITICAL_ISR(wifi_int_mux); + } else { + portEXIT_CRITICAL(wifi_int_mux); + } +} + +static void IRAM_ATTR task_yield_from_isr_wrapper(void) +{ + portYIELD_FROM_ISR(); +} + +static void *IRAM_ATTR semphr_create_wrapper(uint32_t max, uint32_t init) +{ + return (void *)xSemaphoreCreateCounting(max, init); +} + +static void IRAM_ATTR semphr_delete_wrapper(void *semphr) +{ + vSemaphoreDelete(semphr); +} + +static int32_t IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw) +{ + return (int32_t)xSemaphoreTakeFromISR(semphr, hptw); +} + +static int32_t IRAM_ATTR semphr_give_from_isr_wrapper(void *semphr, void *hptw) +{ + return (int32_t)xSemaphoreGiveFromISR(semphr, hptw); +} + +static int32_t IRAM_ATTR semphr_take_wrapper(void *semphr, uint32_t block_time_tick) +{ + if (block_time_tick == OSI_FUNCS_TIME_BLOCKING) { + return (int32_t)xSemaphoreTake(semphr, portMAX_DELAY); + } else { + return (int32_t)xSemaphoreTake(semphr, block_time_tick); + } +} + +static int32_t IRAM_ATTR semphr_give_wrapper(void *semphr) +{ + return (int32_t)xSemaphoreGive(semphr); +} + +static void *IRAM_ATTR recursive_mutex_create_wrapper(void) +{ + return (void *)xSemaphoreCreateRecursiveMutex(); +} + +static void *IRAM_ATTR mutex_create_wrapper(void) +{ + return (void *)xSemaphoreCreateMutex(); +} + +static void IRAM_ATTR mutex_delete_wrapper(void *mutex) +{ + vSemaphoreDelete(mutex); +} + +static int32_t IRAM_ATTR mutex_lock_wrapper(void *mutex) +{ + return (int32_t)xSemaphoreTakeRecursive(mutex, portMAX_DELAY); +} + +static int32_t IRAM_ATTR mutex_unlock_wrapper(void *mutex) +{ + return (int32_t)xSemaphoreGiveRecursive(mutex); +} + +static void *IRAM_ATTR queue_create_wrapper(uint32_t queue_len, uint32_t item_size) +{ + return (void *)xQueueCreate(queue_len, item_size); +} + +static int32_t IRAM_ATTR queue_send_wrapper(void *queue, void *item, uint32_t block_time_tick) +{ + if (block_time_tick == OSI_FUNCS_TIME_BLOCKING) { + return (int32_t)xQueueSend(queue, item, portMAX_DELAY); + } else { + return (int32_t)xQueueSend(queue, item, block_time_tick); + } +} + +static int32_t IRAM_ATTR queue_send_from_isr_wrapper(void *queue, void *item, void *hptw) +{ + return (int32_t)xQueueSendFromISR(queue, item, hptw); +} + +static int32_t IRAM_ATTR queue_send_to_back_wrapper(void *queue, void *item, uint32_t block_time_tick) +{ + return (int32_t)xQueueGenericSend(queue, item, block_time_tick, queueSEND_TO_BACK); +} + +static int32_t IRAM_ATTR queue_send_to_front_wrapper(void *queue, void *item, uint32_t block_time_tick) +{ + return (int32_t)xQueueGenericSend(queue, item, block_time_tick, queueSEND_TO_FRONT); +} + +static int32_t IRAM_ATTR queue_recv_wrapper(void *queue, void *item, uint32_t block_time_tick) +{ + if (block_time_tick == OSI_FUNCS_TIME_BLOCKING) { + return (int32_t)xQueueReceive(queue, item, portMAX_DELAY); + } else { + return (int32_t)xQueueReceive(queue, item, block_time_tick); + } +} + +static uint32_t IRAM_ATTR event_group_wait_bits_wrapper(void *event, uint32_t bits_to_wait_for, int clear_on_exit, int wait_for_all_bits, uint32_t block_time_tick) +{ + if (block_time_tick == OSI_FUNCS_TIME_BLOCKING) { + return (uint32_t)xEventGroupWaitBits(event, bits_to_wait_for, clear_on_exit, wait_for_all_bits, portMAX_DELAY); + } else { + return (uint32_t)xEventGroupWaitBits(event, bits_to_wait_for, clear_on_exit, wait_for_all_bits, block_time_tick); + } +} + +static int32_t IRAM_ATTR task_create_pinned_to_core_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id) +{ + return (uint32_t)xTaskCreatePinnedToCore(task_func, name, stack_depth, param, prio, task_handle, (core_id < portNUM_PROCESSORS ? core_id : tskNO_AFFINITY)); +} + +static int32_t IRAM_ATTR task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle) +{ + return (uint32_t)xTaskCreate(task_func, name, stack_depth, param, prio, task_handle); +} + +static int32_t IRAM_ATTR task_ms_to_tick_wrapper(uint32_t ms) +{ + return (int32_t)(ms / portTICK_PERIOD_MS); +} + + +static int32_t IRAM_ATTR task_get_max_priority_wrapper(void) +{ + return (int32_t)(configMAX_PRIORITIES); +} + +static int32_t IRAM_ATTR phy_rf_init_wrapper(const void* init_data, uint32_t mode, void* calibration_data, uint32_t module) +{ + return esp_phy_rf_init( init_data, mode, calibration_data, module); +} + +static void IRAM_ATTR timer_arm_wrapper(void *timer, uint32_t tmout, bool repeat) +{ + ets_timer_arm(timer, tmout, repeat); +} + +static void IRAM_ATTR timer_disarm_wrapper(void *timer) +{ + ets_timer_disarm(timer); +} + +static void IRAM_ATTR timer_done_wrapper(void *ptimer) +{ + ets_timer_done(ptimer); +} + +static void IRAM_ATTR timer_setfn_wrapper(void *ptimer, void *pfunction, void *parg) +{ + ets_timer_setfn(ptimer, pfunction, parg); +} + +static void IRAM_ATTR timer_arm_us_wrapper(void *ptimer, uint32_t us, bool repeat) +{ + ets_timer_arm_us(ptimer, us, repeat); +} + +static int IRAM_ATTR get_time_wrapper(void *t) +{ + return os_get_time(t); +} + +static void * IRAM_ATTR malloc_internal_wrapper(size_t size) +{ + return heap_caps_malloc(size, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); +} + +static void * IRAM_ATTR realloc_internal_wrapper(void *ptr, size_t size) +{ + return heap_caps_realloc(ptr, size, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); +} + +static void * IRAM_ATTR calloc_internal_wrapper(size_t n, size_t size) +{ + return heap_caps_calloc(n, size, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); +} + +static void * IRAM_ATTR zalloc_internal_wrapper(size_t size) +{ + void *ptr = heap_caps_calloc(1, size, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); + if (ptr) { + memset(ptr, 0, size); + } + return ptr; +} + +static void IRAM_ATTR sc_ack_send_wrapper(void *param) +{ + return sc_ack_send((sc_ack_t *)param); +} + +wifi_osi_funcs_t g_wifi_osi_funcs = { + ._version = ESP_WIFI_OS_ADAPTER_VERSION, + ._set_isr = set_isr_wrapper, + ._ints_on = xt_ints_on, + ._ints_off = xt_ints_off, + ._spin_lock_create = spin_lock_create_wrapper, + ._spin_lock_delete = free, + ._wifi_int_disable = wifi_int_disable_wrapper, + ._wifi_int_restore = wifi_int_restore_wrapper, + ._task_yield = vPortYield, + ._task_yield_from_isr = task_yield_from_isr_wrapper, + ._semphr_create = semphr_create_wrapper, + ._semphr_delete = semphr_delete_wrapper, + ._semphr_take_from_isr = semphr_take_from_isr_wrapper, + ._semphr_give_from_isr = semphr_give_from_isr_wrapper, + ._semphr_take = semphr_take_wrapper, + ._semphr_give = semphr_give_wrapper, + ._mutex_create = mutex_create_wrapper, + ._recursive_mutex_create = recursive_mutex_create_wrapper, + ._mutex_delete = mutex_delete_wrapper, + ._mutex_lock = mutex_lock_wrapper, + ._mutex_unlock = mutex_unlock_wrapper, + ._queue_create = queue_create_wrapper, + ._queue_delete = vQueueDelete, + ._queue_send = queue_send_wrapper, + ._queue_send_from_isr = queue_send_from_isr_wrapper, + ._queue_send_to_back = queue_send_to_back_wrapper, + ._queue_send_to_front = queue_send_to_front_wrapper, + ._queue_recv = queue_recv_wrapper, + ._queue_recv_from_isr = xQueueReceiveFromISR, + ._queue_msg_waiting = uxQueueMessagesWaiting, + ._event_group_create = xEventGroupCreate, + ._event_group_delete = vEventGroupDelete, + ._event_group_set_bits = xEventGroupSetBits, + ._event_group_clear_bits = xEventGroupClearBits, + ._event_group_wait_bits = event_group_wait_bits_wrapper, + ._task_create_pinned_to_core = task_create_pinned_to_core_wrapper, + ._task_create = task_create_wrapper, + ._task_delete = vTaskDelete, + ._task_delay = vTaskDelay, + ._task_ms_to_tick = task_ms_to_tick_wrapper, + ._task_get_current_task = xTaskGetCurrentTaskHandle, + ._task_get_max_priority = task_get_max_priority_wrapper, + ._is_in_isr = xPortInIsrContext, + ._malloc = malloc, + ._free = free, + ._get_free_heap_size = esp_get_free_heap_size, + ._rand = esp_random, + ._dport_access_stall_other_cpu_start_wrap = esp_dport_access_stall_other_cpu_start_wrap, + ._dport_access_stall_other_cpu_end_wrap = esp_dport_access_stall_other_cpu_end_wrap, + ._phy_rf_init = phy_rf_init_wrapper, + ._phy_rf_deinit = esp_phy_rf_deinit, + ._phy_load_cal_and_init = esp_phy_load_cal_and_init, + ._read_mac = esp_read_mac, + ._timer_init = ets_timer_init, + ._timer_deinit = ets_timer_deinit, + ._timer_arm = timer_arm_wrapper, + ._timer_disarm = timer_disarm_wrapper, + ._timer_done = timer_done_wrapper, + ._timer_setfn = timer_setfn_wrapper, + ._timer_arm_us = timer_arm_us_wrapper, + ._periph_module_enable = periph_module_enable, + ._periph_module_disable = periph_module_disable, + ._esp_timer_get_time = esp_timer_get_time, + ._nvs_set_i8 = nvs_set_i8, + ._nvs_get_i8 = nvs_get_i8, + ._nvs_set_u8 = nvs_set_u8, + ._nvs_get_u8 = nvs_get_u8, + ._nvs_set_u16 = nvs_set_u16, + ._nvs_get_u16 = nvs_get_u16, + ._nvs_open = nvs_open, + ._nvs_close = nvs_close, + ._nvs_commit = nvs_commit, + ._nvs_set_blob = nvs_set_blob, + ._nvs_get_blob = nvs_get_blob, + ._nvs_erase_key = nvs_erase_key, + ._get_random = os_get_random, + ._get_time = get_time_wrapper, + ._random = os_random, + ._log_write = esp_log_write, + ._log_timestamp = esp_log_timestamp, + ._malloc_internal = malloc_internal_wrapper, + ._realloc_internal = realloc_internal_wrapper, + ._calloc_internal = calloc_internal_wrapper, + ._zalloc_internal = zalloc_internal_wrapper, + ._wifi_malloc = wifi_malloc, + ._wifi_realloc = wifi_realloc, + ._wifi_calloc = wifi_calloc, + ._wifi_zalloc = wifi_zalloc_wrapper, + ._wifi_create_queue = wifi_create_queue_wrapper, + ._wifi_delete_queue = wifi_delete_queue_wrapper, + ._modem_sleep_enter = esp_modem_sleep_enter, + ._modem_sleep_exit = esp_modem_sleep_exit, + ._modem_sleep_register = esp_modem_sleep_register, + ._modem_sleep_deregister = esp_modem_sleep_deregister, + ._sc_ack_send = sc_ack_send_wrapper, + ._sc_ack_send_stop = sc_ack_send_stop, + ._magic = ESP_WIFI_OS_ADAPTER_MAGIC, +}; diff --git a/components/wpa_supplicant/include/crypto/crypto.h b/components/wpa_supplicant/include/crypto/crypto.h index b8877993df..bccb6fed7f 100644 --- a/components/wpa_supplicant/include/crypto/crypto.h +++ b/components/wpa_supplicant/include/crypto/crypto.h @@ -27,6 +27,8 @@ #ifndef CRYPTO_H #define CRYPTO_H +#include "common.h" + /** * md4_vector - MD4 hash for data vector * @num_elem: Number of elements in the data vector diff --git a/components/wpa_supplicant/include/crypto/dh_group5.h b/components/wpa_supplicant/include/crypto/dh_group5.h index 595f1114fe..f92c1115d5 100644 --- a/components/wpa_supplicant/include/crypto/dh_group5.h +++ b/components/wpa_supplicant/include/crypto/dh_group5.h @@ -15,6 +15,8 @@ #ifndef DH_GROUP5_H #define DH_GROUP5_H +#include "wpa/wpabuf.h" + void * dh5_init(struct wpabuf **priv, struct wpabuf **publ); struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, const struct wpabuf *own_private); diff --git a/components/wpa_supplicant/include/crypto/md5.h b/components/wpa_supplicant/include/crypto/md5.h index 8952590782..6de3a5b5f1 100644 --- a/components/wpa_supplicant/include/crypto/md5.h +++ b/components/wpa_supplicant/include/crypto/md5.h @@ -17,16 +17,16 @@ #define MD5_MAC_LEN 16 -int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac); +int hmac_md5_vector(const uint8_t *key, size_t key_len, size_t num_elem, + const uint8_t *addr[], const size_t *len, uint8_t *mac); +int hmac_md5(const uint8_t *key, size_t key_len, const uint8_t *data, size_t data_len, + uint8_t *mac); #ifdef CONFIG_FIPS -int hmac_md5_vector_non_fips_allow(const u8 *key, size_t key_len, - size_t num_elem, const u8 *addr[], - const size_t *len, u8 *mac); -int hmac_md5_non_fips_allow(const u8 *key, size_t key_len, const u8 *data, - size_t data_len, u8 *mac); +int hmac_md5_vector_non_fips_allow(const uint8_t *key, size_t key_len, + size_t num_elem, const uint8_t *addr[], + const size_t *len, uint8_t *mac); +int hmac_md5_non_fips_allow(const uint8_t *key, size_t key_len, const uint8_t *data, + size_t data_len, uint8_t *mac); #else /* CONFIG_FIPS */ #define hmac_md5_vector_non_fips_allow hmac_md5_vector #define hmac_md5_non_fips_allow hmac_md5 diff --git a/components/wpa_supplicant/include/crypto/sha1.h b/components/wpa_supplicant/include/crypto/sha1.h index b3d186bdbc..65e3958fc6 100644 --- a/components/wpa_supplicant/include/crypto/sha1.h +++ b/components/wpa_supplicant/include/crypto/sha1.h @@ -17,17 +17,17 @@ #define SHA1_MAC_LEN 20 -int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac); -int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, - u8 *mac); -int sha1_prf(const u8 *key, size_t key_len, const char *label, - const u8 *data, size_t data_len, u8 *buf, size_t buf_len); -int sha1_t_prf(const u8 *key, size_t key_len, const char *label, - const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len); -//int __must_check tls_prf(const u8 *secret, size_t secret_len, -// const char *label, const u8 *seed, size_t seed_len, -// u8 *out, size_t outlen); +int hmac_sha1_vector(const uint8_t *key, size_t key_len, size_t num_elem, + const uint8_t *addr[], const size_t *len, uint8_t *mac); +int hmac_sha1(const uint8_t *key, size_t key_len, const uint8_t *data, size_t data_len, + uint8_t *mac); +int sha1_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); +int sha1_t_prf(const uint8_t *key, size_t key_len, const char *label, + const uint8_t *seed, size_t seed_len, uint8_t *buf, size_t buf_len); +//int __must_check tls_prf(const uint8_t *secret, size_t secret_len, +// const char *label, const uint8_t *seed, size_t seed_len, +// uint8_t *out, size_t outlen); int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, - int iterations, u8 *buf, size_t buflen); + int iterations, uint8_t *buf, size_t buflen); #endif /* SHA1_H */ diff --git a/components/wpa_supplicant/include/wpa2/eap_peer/eap_methods.h b/components/wpa_supplicant/include/wpa2/eap_peer/eap_methods.h index baa493d292..253b2d8a17 100644 --- a/components/wpa_supplicant/include/wpa2/eap_peer/eap_methods.h +++ b/components/wpa_supplicant/include/wpa2/eap_peer/eap_methods.h @@ -10,6 +10,7 @@ #define EAP_METHODS_H #include "eap_defs.h" +#include "eap_config.h" const struct eap_method * eap_peer_get_eap_method(int vendor, EapType method); const struct eap_method * eap_peer_get_methods(size_t *count); diff --git a/components/wpa_supplicant/include/wps/wps.h b/components/wpa_supplicant/include/wps/wps.h index c69aedb30d..b731b9b95f 100644 --- a/components/wpa_supplicant/include/wps/wps.h +++ b/components/wpa_supplicant/include/wps/wps.h @@ -233,9 +233,7 @@ enum wps_process_res wps_process_msg(struct wps_data *wps, struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code); int wps_is_selected_pbc_registrar(const struct wpabuf *msg, u8 *bssid); -#ifdef CONFIG_WPS_PIN int wps_is_selected_pin_registrar(const struct wpabuf *msg, u8 *bssid); -#endif int wps_ap_priority_compar(const struct wpabuf *wps_a, const struct wpabuf *wps_b); int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr, @@ -803,9 +801,9 @@ int wps_build_credential_wrap(struct wpabuf *msg, unsigned int wps_pin_checksum(unsigned int pin); unsigned int wps_pin_valid(unsigned int pin); -unsigned int wps_generate_pin(void); int wps_pin_str_valid(const char *pin); #endif +unsigned int wps_generate_pin(void); #ifdef CONFIG_WPS_OOB From 4c8d9278b5f668591939ae2cb12dc0a7f76bd1db Mon Sep 17 00:00:00 2001 From: baohongde Date: Mon, 28 May 2018 17:43:53 +0800 Subject: [PATCH 180/187] component/bt: Fix mem leak of esp_ble_gap_set_security_param --- .../btc/profile/std/gap/btc_gap_ble.c | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c index f5b21f00c0..c3937cf652 100644 --- a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c +++ b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c @@ -442,7 +442,7 @@ static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params, tBT } return; } - + BTC_TRACE_DEBUG("API_Ble_AppStartAdvertising\n"); memcpy(peer_addr.bda, ble_adv_params->peer_addr, ESP_BD_ADDR_LEN); @@ -647,12 +647,12 @@ static void btc_add_whitelist_complete_callback(UINT8 status, tBTM_WL_OPERATION } } -static void btc_set_rand_addr_callback(UINT8 status) +static void btc_set_rand_addr_callback(UINT8 status) { esp_ble_gap_cb_param_t param; bt_status_t ret; btc_msg_t msg; - param.set_rand_addr_cmpl.status = btc_btm_status_to_esp_status(status); //todo status + param.set_rand_addr_cmpl.status = btc_btm_status_to_esp_status(status); //todo status msg.sig = BTC_SIG_API_CB; msg.pid = BTC_PID_GAP_BLE; msg.act = ESP_GAP_BLE_SET_STATIC_RAND_ADDR_EVT; @@ -939,6 +939,13 @@ void btc_gap_ble_arg_deep_free(btc_msg_t *msg) } break; } + case BTC_GAP_BLE_SET_SECURITY_PARAM_EVT: { + uint8_t *value = ((btc_ble_gap_args_t *)msg->arg)->set_security_param.value; + if (value) { + osi_free(value); + } + break; + } default: BTC_TRACE_DEBUG("Unhandled deep free %d\n", msg->act); break; @@ -1040,36 +1047,37 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) break; } case BTC_GAP_BLE_SET_SECURITY_PARAM_EVT: { + uint8_t *value = arg->set_security_param.value; switch(arg->set_security_param.param_type) { case ESP_BLE_SM_PASSKEY: break; case ESP_BLE_SM_AUTHEN_REQ_MODE: { uint8_t authen_req = 0; - STREAM_TO_UINT8(authen_req, arg->set_security_param.value); + STREAM_TO_UINT8(authen_req, value); bta_dm_co_ble_set_auth_req(authen_req); break; } case ESP_BLE_SM_IOCAP_MODE: { uint8_t iocap = 0; - STREAM_TO_UINT8(iocap, arg->set_security_param.value); + STREAM_TO_UINT8(iocap, value); bta_dm_co_ble_set_io_cap(iocap); break; } case ESP_BLE_SM_SET_INIT_KEY: { uint8_t init_key = 0; - STREAM_TO_UINT8(init_key, arg->set_security_param.value); + STREAM_TO_UINT8(init_key, value); bta_dm_co_ble_set_init_key_req(init_key); break; } case ESP_BLE_SM_SET_RSP_KEY: { uint8_t rsp_key = 0; - STREAM_TO_UINT8(rsp_key, arg->set_security_param.value); + STREAM_TO_UINT8(rsp_key, value); bta_dm_co_ble_set_rsp_key_req(rsp_key); break; } case ESP_BLE_SM_MAX_KEY_SIZE: { uint8_t key_size = 0; - STREAM_TO_UINT8(key_size, arg->set_security_param.value); + STREAM_TO_UINT8(key_size, value); bta_dm_co_ble_set_max_key_size(key_size); break; } From 6f529cbe64ac926aebaec90b72bf6bef1415b849 Mon Sep 17 00:00:00 2001 From: Konstantin Kondrashov Date: Mon, 28 May 2018 17:36:04 +0500 Subject: [PATCH 181/187] newlib: Add adjtime - makes a gradual adjustment the system clock This function speeds up or slows down the system clock in order to make a gradual adjustment. This ensures that the calendar time reported by the system clock is always monotonically increasing, which might not happen if you simply set the clock. The delta argument specifies a relative adjustment to be made to the clock time. If negative, the system clock is slowed down for a while until it has lost this much elapsed time. If positive, the system clock is speeded up for a while. If the olddelta argument is not a null pointer, the adjtime function returns information about any previous time adjustment that has not yet completed. The return value is 0 on success and -1 on failure. To stop the adjustement, call the function settimeofday(current_time). --- components/newlib/test/test_time.c | 238 +++++++++++++++++++++++++++++ components/newlib/time.c | 109 ++++++++++++- 2 files changed, 345 insertions(+), 2 deletions(-) diff --git a/components/newlib/test/test_time.c b/components/newlib/test/test_time.c index 8cf9bc6c39..47df5b9de2 100644 --- a/components/newlib/test/test_time.c +++ b/components/newlib/test/test_time.c @@ -51,3 +51,241 @@ TEST_CASE("Reading RTC registers on APP CPU doesn't affect clock", "[newlib]") } #endif // portNUM_PROCESSORS == 2 + +TEST_CASE("test adjtime function", "[newlib]") +{ + struct timeval tv_time; + struct timeval tv_delta; + struct timeval tv_outdelta; + + TEST_ASSERT_EQUAL(adjtime(NULL, NULL), 0); + + tv_time.tv_sec = 5000; + tv_time.tv_usec = 5000; + TEST_ASSERT_EQUAL(settimeofday(&tv_time, NULL), 0); + + tv_outdelta.tv_sec = 5; + tv_outdelta.tv_usec = 5; + TEST_ASSERT_EQUAL(adjtime(NULL, &tv_outdelta), 0); + TEST_ASSERT_EQUAL(tv_outdelta.tv_sec, 0); + TEST_ASSERT_EQUAL(tv_outdelta.tv_usec, 0); + + tv_delta.tv_sec = INT_MAX / 1000000L; + TEST_ASSERT_EQUAL(adjtime(&tv_delta, &tv_outdelta), -1); + + tv_delta.tv_sec = INT_MIN / 1000000L; + TEST_ASSERT_EQUAL(adjtime(&tv_delta, &tv_outdelta), -1); + + tv_delta.tv_sec = 0; + tv_delta.tv_usec = -900000; + TEST_ASSERT_EQUAL(adjtime(&tv_delta, &tv_outdelta), 0); + TEST_ASSERT_TRUE(tv_outdelta.tv_usec <= 0); + + tv_delta.tv_sec = 0; + tv_delta.tv_usec = 900000; + TEST_ASSERT_EQUAL(adjtime(&tv_delta, &tv_outdelta), 0); + TEST_ASSERT_TRUE(tv_outdelta.tv_usec >= 0); + + tv_delta.tv_sec = -4; + tv_delta.tv_usec = -900000; + TEST_ASSERT_EQUAL(adjtime(&tv_delta, &tv_outdelta), 0); + TEST_ASSERT_EQUAL(tv_outdelta.tv_sec, -4); + TEST_ASSERT_TRUE(tv_outdelta.tv_usec <= 0); + + // after settimeofday() adjtime() is stopped + tv_delta.tv_sec = 15; + tv_delta.tv_usec = 900000; + TEST_ASSERT_EQUAL(adjtime(&tv_delta, &tv_outdelta), 0); + TEST_ASSERT_EQUAL(tv_outdelta.tv_sec, 15); + TEST_ASSERT_TRUE(tv_outdelta.tv_usec >= 0); + + TEST_ASSERT_EQUAL(gettimeofday(&tv_time, NULL), 0); + TEST_ASSERT_EQUAL(settimeofday(&tv_time, NULL), 0); + + TEST_ASSERT_EQUAL(adjtime(NULL, &tv_outdelta), 0); + TEST_ASSERT_EQUAL(tv_outdelta.tv_sec, 0); + TEST_ASSERT_EQUAL(tv_outdelta.tv_usec, 0); + + // after gettimeofday() adjtime() is not stopped + tv_delta.tv_sec = 15; + tv_delta.tv_usec = 900000; + TEST_ASSERT_EQUAL(adjtime(&tv_delta, &tv_outdelta), 0); + TEST_ASSERT_EQUAL(tv_outdelta.tv_sec, 15); + TEST_ASSERT_TRUE(tv_outdelta.tv_usec >= 0); + + TEST_ASSERT_EQUAL(gettimeofday(&tv_time, NULL), 0); + + TEST_ASSERT_EQUAL(adjtime(NULL, &tv_outdelta), 0); + TEST_ASSERT_EQUAL(tv_outdelta.tv_sec, 15); + TEST_ASSERT_TRUE(tv_outdelta.tv_usec >= 0); + + tv_delta.tv_sec = 1; + tv_delta.tv_usec = 0; + TEST_ASSERT_EQUAL(adjtime(&tv_delta, NULL), 0); + vTaskDelay(1000 / portTICK_PERIOD_MS); + TEST_ASSERT_EQUAL(adjtime(NULL, &tv_outdelta), 0); + TEST_ASSERT_TRUE(tv_outdelta.tv_sec == 0); + // the correction will be equal to (1_000_000us >> 6) = 15_625 us. + TEST_ASSERT_TRUE(1000000L - tv_outdelta.tv_usec >= 15600); + TEST_ASSERT_TRUE(1000000L - tv_outdelta.tv_usec <= 15650); +} + +static volatile bool exit_flag; +static bool adjtime_test_result; +static bool gettimeofday_test_result; +static uint64_t count_adjtime; +static uint64_t count_settimeofday; +static uint64_t count_gettimeofday; + +static void adjtimeTask2(void *pvParameters) +{ + struct timeval delta = {.tv_sec = 0, .tv_usec = 0}; + struct timeval outdelta; + + // although exit flag is set in another task, checking (exit_flag == false) is safe + while (exit_flag == false) { + delta.tv_sec += 1; + delta.tv_usec = 900000; + if (delta.tv_sec >= 2146) delta.tv_sec = 1; + adjtime(&delta, &outdelta); + count_adjtime++; + } + vTaskDelete(NULL); +} + +static void settimeofdayTask2(void *pvParameters) +{ + struct timeval tv_time = { .tv_sec = 1520000000, .tv_usec = 900000 }; + + // although exit flag is set in another task, checking (exit_flag == false) is safe + while (exit_flag == false) { + tv_time.tv_sec += 1; + settimeofday(&tv_time, NULL); + count_settimeofday++; + vTaskDelay(1); + } + vTaskDelete(NULL); +} + +static void gettimeofdayTask2(void *pvParameters) +{ + struct timeval tv_time; + // although exit flag is set in another task, checking (exit_flag == false) is safe + while (exit_flag == false) { + gettimeofday(&tv_time, NULL); + count_gettimeofday++; + vTaskDelay(1); + } + vTaskDelete(NULL); +} + +TEST_CASE("test for no interlocking adjtime, gettimeofday and settimeofday functions", "[newlib]") +{ + TaskHandle_t th[4]; + exit_flag = false; + count_adjtime = 0; + count_settimeofday = 0; + count_gettimeofday = 0; + struct timeval tv_time = { .tv_sec = 1520000000, .tv_usec = 900000 }; + TEST_ASSERT_EQUAL(settimeofday(&tv_time, NULL), 0); + +#ifndef CONFIG_FREERTOS_UNICORE + printf("CPU0 and CPU1. Tasks run: 1 - adjtimeTask, 2 - gettimeofdayTask, 3 - settimeofdayTask \n"); + xTaskCreatePinnedToCore(adjtimeTask2, "adjtimeTask1", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[0], 0); + xTaskCreatePinnedToCore(gettimeofdayTask2, "gettimeofdayTask1", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[1], 1); + xTaskCreatePinnedToCore(settimeofdayTask2, "settimeofdayTask1", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[2], 0); +#else + printf("Only one CPU. Tasks run: 1 - adjtimeTask, 2 - gettimeofdayTask, 3 - settimeofdayTask\n"); + xTaskCreate(adjtimeTask2, "adjtimeTask1", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[0]); + xTaskCreate(gettimeofdayTask2, "gettimeofdayTask1", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[1]); + xTaskCreate(settimeofdayTask2, "settimeofdayTask1", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[2]); +#endif + + printf("start wait for 10 seconds\n"); + vTaskDelay(10000 / portTICK_PERIOD_MS); + + // set exit flag to let thread exit + exit_flag = true; + vTaskDelay(20 / portTICK_PERIOD_MS); + printf("count_adjtime %lld, count_settimeofday %lld, count_gettimeofday %lld\n", count_adjtime, count_settimeofday, count_gettimeofday); + TEST_ASSERT(count_adjtime > 1000LL && count_settimeofday > 1000LL && count_gettimeofday > 1000LL); +} + +static void adjtimeTask(void *pvParameters) +{ + struct timeval delta = {.tv_sec = 0, .tv_usec = 0}; + struct timeval outdelta = {.tv_sec = 0, .tv_usec = 0}; + + // although exit flag is set in another task, checking (exit_flag == false) is safe + while (exit_flag == false) { + delta.tv_sec = 1000; + delta.tv_usec = 0; + if(adjtime(&delta, &outdelta) != 0) { + adjtime_test_result = true; + exit_flag = true; + } + delta.tv_sec = 0; + delta.tv_usec = 1000; + if(adjtime(&delta, &outdelta) != 0) { + adjtime_test_result = true; + exit_flag = true; + } + } + vTaskDelete(NULL); +} + +static void gettimeofdayTask(void *pvParameters) +{ + struct timeval tv_time; + + gettimeofday(&tv_time, NULL); + uint64_t time_old = (uint64_t)tv_time.tv_sec * 1000000L + tv_time.tv_usec; + // although exit flag is set in another task, checking (exit_flag == false) is safe + while (exit_flag == false) { + gettimeofday(&tv_time, NULL); + uint64_t time = (uint64_t)tv_time.tv_sec * 1000000L + tv_time.tv_usec; + if(((time - time_old) > 1000000LL) || (time_old > time)) { + printf("ERROR: time jumped for %lld/1000 seconds. No locks. Need to use locks.\n", (time - time_old)/1000000LL); + gettimeofday_test_result = true; + exit_flag = true; + } + time_old = time; + } + vTaskDelete(NULL); +} + +TEST_CASE("test for thread safety adjtime and gettimeofday functions", "[newlib]") +{ + TaskHandle_t th[4]; + exit_flag = false; + adjtime_test_result = false; + gettimeofday_test_result = false; + + struct timeval tv_time = { .tv_sec = 1520000000, .tv_usec = 900000 }; + TEST_ASSERT_EQUAL(settimeofday(&tv_time, NULL), 0); + +#ifndef CONFIG_FREERTOS_UNICORE + printf("CPU0 and CPU1. Tasks run: 1 - adjtimeTask, 2 - gettimeofdayTask\n"); + xTaskCreatePinnedToCore(adjtimeTask, "adjtimeTask1", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[0], 0); + xTaskCreatePinnedToCore(gettimeofdayTask, "gettimeofdayTask1", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[1], 1); + + xTaskCreatePinnedToCore(adjtimeTask, "adjtimeTask2", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[2], 0); + xTaskCreatePinnedToCore(gettimeofdayTask, "gettimeofdayTask2", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[3], 1); +#else + printf("Only one CPU. Tasks run: 1 - adjtimeTask, 2 - gettimeofdayTask\n"); + xTaskCreate(adjtimeTask, "adjtimeTask1", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[0]); + xTaskCreate(gettimeofdayTask, "gettimeofdayTask1", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[1]); + + xTaskCreate(adjtimeTask, "adjtimeTask2", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[2]); + xTaskCreate(gettimeofdayTask, "gettimeofdayTask2", 2048, NULL, UNITY_FREERTOS_PRIORITY - 1, &th[3]); +#endif + + printf("start wait for 10 seconds\n"); + vTaskDelay(10000 / portTICK_PERIOD_MS); + + // set exit flag to let thread exit + exit_flag = true; + vTaskDelay(20 / portTICK_PERIOD_MS); + + TEST_ASSERT(adjtime_test_result == false && gettimeofday_test_result == false); +} diff --git a/components/newlib/time.c b/components/newlib/time.c index 8443d2b54b..37b78f3de5 100644 --- a/components/newlib/time.c +++ b/components/newlib/time.c @@ -78,8 +78,14 @@ static uint64_t s_boot_time; #if defined(WITH_RTC) || defined(WITH_FRC) static _lock_t s_boot_time_lock; +static _lock_t s_adjust_time_lock; +// stores the start time of the slew +RTC_DATA_ATTR static uint64_t adjtime_start = 0; +// is how many microseconds total to slew +RTC_DATA_ATTR static int64_t adjtime_total_correction = 0; +#define ADJTIME_CORRECTION_FACTOR 6 +static uint64_t get_time_since_boot(); #endif - // Offset between FRC timer and the RTC. // Initialized after reset or light sleep. #if defined(WITH_RTC) && defined(WITH_FRC) @@ -111,8 +117,106 @@ static uint64_t get_boot_time() _lock_release(&s_boot_time_lock); return result; } + +// This function gradually changes boot_time to the correction value and immediately updates it. +static uint64_t adjust_boot_time() +{ + uint64_t boot_time = get_boot_time(); + if ((boot_time == 0) || (get_time_since_boot() < adjtime_start)) { + adjtime_start = 0; + } + if (adjtime_start > 0) { + uint64_t since_boot = get_time_since_boot(); + // If to call this function once per second, then (since_boot - adjtime_start) will be 1_000_000 (1 second), + // and the correction will be equal to (1_000_000us >> 6) = 15_625 us. + // The minimum possible correction step can be (64us >> 6) = 1us. + // Example: if the time error is 1 second, then it will be compensate for 1 sec / 0,015625 = 64 seconds. + int64_t correction = (since_boot - adjtime_start) >> ADJTIME_CORRECTION_FACTOR; + if (correction > 0) { + adjtime_start = since_boot; + if (adjtime_total_correction < 0) { + if ((adjtime_total_correction + correction) >= 0) { + boot_time = boot_time + adjtime_total_correction; + adjtime_start = 0; + } else { + adjtime_total_correction += correction; + boot_time -= correction; + } + } else { + if ((adjtime_total_correction - correction) <= 0) { + boot_time = boot_time + adjtime_total_correction; + adjtime_start = 0; + } else { + adjtime_total_correction -= correction; + boot_time += correction; + } + } + set_boot_time(boot_time); + } + } + return boot_time; +} + +// Get the adjusted boot time. +static uint64_t get_adjusted_boot_time (void) +{ + _lock_acquire(&s_adjust_time_lock); + uint64_t adjust_time = adjust_boot_time(); + _lock_release(&s_adjust_time_lock); + return adjust_time; +} + +// Applying the accumulated correction to boot_time and stopping the smooth time adjustment. +static void adjtime_corr_stop (void) +{ + _lock_acquire(&s_adjust_time_lock); + if (adjtime_start != 0){ + adjust_boot_time(); + adjtime_start = 0; + } + _lock_release(&s_adjust_time_lock); +} #endif //defined(WITH_RTC) || defined(WITH_FRC) +int adjtime(const struct timeval *delta, struct timeval *outdelta) +{ +#if defined( WITH_FRC ) || defined( WITH_RTC ) + if(delta != NULL){ + int64_t sec = delta->tv_sec; + int64_t usec = delta->tv_usec; + if(llabs(sec) > ((INT_MAX / 1000000L) - 1L)) { + return -1; + } + /* + * If adjusting the system clock by adjtime () is already done during the second call adjtime (), + * and the delta of the second call is not NULL, the earlier tuning is stopped, + * but the already completed part of the adjustment is not canceled. + */ + _lock_acquire(&s_adjust_time_lock); + // If correction is already in progress (adjtime_start != 0), then apply accumulated corrections. + adjust_boot_time(); + adjtime_start = get_time_since_boot(); + adjtime_total_correction = sec * 1000000L + usec; + _lock_release(&s_adjust_time_lock); + } + if(outdelta != NULL){ + _lock_acquire(&s_adjust_time_lock); + adjust_boot_time(); + if (adjtime_start != 0) { + outdelta->tv_sec = adjtime_total_correction / 1000000L; + outdelta->tv_usec = adjtime_total_correction % 1000000L; + } else { + outdelta->tv_sec = 0; + outdelta->tv_usec = 0; + } + _lock_release(&s_adjust_time_lock); + } + return 0; +#else + return -1; +#endif + +} void esp_clk_slowclk_cal_set(uint32_t new_cal) { @@ -190,7 +294,7 @@ int IRAM_ATTR _gettimeofday_r(struct _reent *r, struct timeval *tv, void *tz) (void) tz; #if defined( WITH_FRC ) || defined( WITH_RTC ) if (tv) { - uint64_t microseconds = get_boot_time() + get_time_since_boot(); + uint64_t microseconds = get_adjusted_boot_time() + get_time_since_boot(); tv->tv_sec = microseconds / 1000000; tv->tv_usec = microseconds % 1000000; } @@ -206,6 +310,7 @@ int settimeofday(const struct timeval *tv, const struct timezone *tz) (void) tz; #if defined( WITH_FRC ) || defined( WITH_RTC ) if (tv) { + adjtime_corr_stop(); uint64_t now = ((uint64_t) tv->tv_sec) * 1000000LL + tv->tv_usec; uint64_t since_boot = get_time_since_boot(); set_boot_time(now - since_boot); From bdbcc492cf16a49d93fa07e89abf041293ca8b0e Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Tue, 29 May 2018 11:01:25 +0200 Subject: [PATCH 182/187] VFS: Add debugging outputs for select() related functions --- components/newlib/select.c | 38 +++++++++++++++++++-- components/vfs/Kconfig | 12 +++++++ components/vfs/vfs.c | 69 +++++++++++++++++++++++++++++++++++++- 3 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 components/vfs/Kconfig diff --git a/components/newlib/select.c b/components/newlib/select.c index e802a4d329..6063150654 100644 --- a/components/newlib/select.c +++ b/components/newlib/select.c @@ -18,12 +18,46 @@ #ifdef CONFIG_USE_ONLY_LWIP_SELECT #include "lwip/sockets.h" -#endif + +#ifdef CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT +#define LOG_LOCAL_LEVEL ESP_LOG_NONE +#endif //CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT +#include "esp_log.h" + +static const char *TAG = "newlib_select"; + +static void log_fd_set(const char *fds_name, const fd_set *fds) +{ + if (fds_name && fds) { + ESP_LOGD(TAG, "FDs in %s =", fds_name); + for (int i = 0; i < MAX_FDS; ++i) { + if (FD_ISSET(i, fds)) { + ESP_LOGD(TAG, "%d", i); + } + } + } +} +#endif //CONFIG_USE_ONLY_LWIP_SELECT int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout) { #ifdef CONFIG_USE_ONLY_LWIP_SELECT - return lwip_select(nfds, readfds, writefds, errorfds, timeout); + ESP_LOGD(TAG, "lwip_select starts with nfds = %d", nfds); + if (timeout) { + ESP_LOGD(TAG, "timeout is %lds + %ldus", timeout->tv_sec, timeout->tv_usec); + } + log_fd_set("readfds", readfds); + log_fd_set("writefds", writefds); + log_fd_set("errorfds", errorfds); + + int ret = lwip_select(nfds, readfds, writefds, errorfds, timeout); + + ESP_LOGD(TAG, "lwip_select returns %d", ret); + log_fd_set("readfds", readfds); + log_fd_set("writefds", writefds); + log_fd_set("errorfds", errorfds); + + return ret; #else return esp_vfs_select(nfds, readfds, writefds, errorfds, timeout); #endif diff --git a/components/vfs/Kconfig b/components/vfs/Kconfig new file mode 100644 index 0000000000..d3d4ae9ad2 --- /dev/null +++ b/components/vfs/Kconfig @@ -0,0 +1,12 @@ +menu "Virtual file system" + +config SUPPRESS_SELECT_DEBUG_OUTPUT + bool "Suppress select() related debug outputs" + default y + help + Select() related functions might produce an unconveniently lot of + debug outputs when one sets the default log level to DEBUG or higher. + It is possible to suppress these debug outputs by enabling this + option. + +endmenu diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index a5f3c74c7d..cd9a2aceca 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -25,8 +25,15 @@ #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "esp_vfs.h" +#include "sdkconfig.h" + +#ifdef CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT +#define LOG_LOCAL_LEVEL ESP_LOG_NONE +#endif //CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT #include "esp_log.h" +static const char *TAG = "vfs"; + #define VFS_MAX_COUNT 8 /* max number of VFS entries (registered filesystems) */ #define LEN_PATH_PREFIX_IGNORED SIZE_MAX /* special length value for VFS which is never recognised by open() */ #define FD_TABLE_ENTRY_UNUSED (fd_table_t) { .permanent = false, .vfs_index = -1, .local_fd = -1 } @@ -127,6 +134,7 @@ esp_err_t esp_vfs_register(const char* base_path, const esp_vfs_t* vfs, void* ct esp_err_t esp_vfs_register_fd_range(const esp_vfs_t *vfs, void *ctx, int min_fd, int max_fd) { if (min_fd < 0 || max_fd < 0 || min_fd > MAX_FDS || max_fd > MAX_FDS || min_fd > max_fd) { + ESP_LOGD(TAG, "Invalid arguments: esp_vfs_register_fd_range(0x%x, 0x%x, %d, %d)", (int) vfs, (int) ctx, min_fd, max_fd); return ESP_ERR_INVALID_ARG; } @@ -145,6 +153,7 @@ esp_err_t esp_vfs_register_fd_range(const esp_vfs_t *vfs, void *ctx, int min_fd, } } _lock_release(&s_fd_table_lock); + ESP_LOGD(TAG, "esp_vfs_register_fd_range cannot set fd %d (used by other VFS)", i); return ESP_ERR_INVALID_ARG; } s_fd_table[i].permanent = true; @@ -154,6 +163,8 @@ esp_err_t esp_vfs_register_fd_range(const esp_vfs_t *vfs, void *ctx, int min_fd, _lock_release(&s_fd_table_lock); } + ESP_LOGD(TAG, "esp_vfs_register_fd_range is successful for range <%d; %d) and VFS ID %d", min_fd, max_fd, index); + return ret; } @@ -196,6 +207,7 @@ esp_err_t esp_vfs_unregister(const char* base_path) esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int *fd) { if (vfs_id < 0 || vfs_id >= s_vfs_count || fd == NULL) { + ESP_LOGD(TAG, "Invalid arguments for esp_vfs_register_fd(%d, 0x%x)", vfs_id, (int) fd); return ESP_ERR_INVALID_ARG; } @@ -213,6 +225,8 @@ esp_err_t esp_vfs_register_fd(esp_vfs_id_t vfs_id, int *fd) } _lock_release(&s_fd_table_lock); + ESP_LOGD(TAG, "esp_vfs_register_fd(%d, 0x%x) finished with %s", vfs_id, (int) fd, esp_err_to_name(ret)); + return ret; } @@ -221,6 +235,7 @@ esp_err_t esp_vfs_unregister_fd(esp_vfs_id_t vfs_id, int fd) esp_err_t ret = ESP_ERR_INVALID_ARG; if (vfs_id < 0 || vfs_id >= s_vfs_count || fd < 0 || fd >= MAX_FDS) { + ESP_LOGD(TAG, "Invalid arguments for esp_vfs_unregister_fd(%d, %d)", vfs_id, fd); return ret; } @@ -232,6 +247,8 @@ esp_err_t esp_vfs_unregister_fd(esp_vfs_id_t vfs_id, int fd) } _lock_release(&s_fd_table_lock); + ESP_LOGD(TAG, "esp_vfs_unregister_fd(%d, %d) finished with %s", vfs_id, fd, esp_err_to_name(ret)); + return ret; } @@ -390,7 +407,7 @@ int esp_vfs_open(struct _reent *r, const char * path, int flags, int mode) _lock_release(&s_fd_table_lock); int ret; CHECK_AND_CALL(ret, r, vfs, close, fd_within_vfs); - (void) ret; // remove "set but not used" warning + (void) ret; // remove "set but not used" warning __errno_r(r) = ENOMEM; return -1; } @@ -730,14 +747,17 @@ static int set_global_fd_sets(const fds_triple_t *vfs_fds_triple, int size, fd_s for (int fd = 0; fd < MAX_FDS; ++fd) { const int local_fd = s_fd_table[fd].local_fd; // single read -> no locking is required if (readfds && FD_ISSET(local_fd, &item->readfds)) { + ESP_LOGD(TAG, "FD %d in readfds was set from VFS ID %d", fd, i); FD_SET(fd, readfds); ++ret; } if (writefds && FD_ISSET(local_fd, &item->writefds)) { + ESP_LOGD(TAG, "FD %d in writefds was set from VFS ID %d", fd, i); FD_SET(fd, writefds); ++ret; } if (errorfds && FD_ISSET(local_fd, &item->errorfds)) { + ESP_LOGD(TAG, "FD %d in errorfds was set from VFS ID %d", fd, i); FD_SET(fd, errorfds); ++ret; } @@ -748,17 +768,39 @@ static int set_global_fd_sets(const fds_triple_t *vfs_fds_triple, int size, fd_s return ret; } +static void esp_vfs_log_fd_set(const char *fds_name, const fd_set *fds) +{ + if (fds_name && fds) { + ESP_LOGD(TAG, "FDs in %s =", fds_name); + for (int i = 0; i < MAX_FDS; ++i) { + if (FD_ISSET(i, fds)) { + ESP_LOGD(TAG, "%d", i); + } + } + } +} + int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout) { int ret = 0; struct _reent* r = __getreent(); + ESP_LOGD(TAG, "esp_vfs_select starts with nfds = %d", nfds); + if (timeout) { + ESP_LOGD(TAG, "timeout is %lds + %ldus", timeout->tv_sec, timeout->tv_usec); + } + esp_vfs_log_fd_set("readfds", readfds); + esp_vfs_log_fd_set("writefds", writefds); + esp_vfs_log_fd_set("errorfds", errorfds); + if (nfds > MAX_FDS || nfds < 0) { + ESP_LOGD(TAG, "incorrect nfds"); __errno_r(r) = EINVAL; return -1; } if (_lock_try_acquire(&s_one_select_lock)) { + ESP_LOGD(TAG, "concurrent select is not supported"); __errno_r(r) = EINTR; return -1; } @@ -767,6 +809,7 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds if ((vfs_fds_triple = calloc(s_vfs_count, sizeof(fds_triple_t))) == NULL) { __errno_r(r) = ENOMEM; _lock_release(&s_one_select_lock); + ESP_LOGD(TAG, "calloc is unsuccessful"); return -1; } @@ -800,16 +843,19 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds item->isset = true; FD_SET(local_fd, &item->readfds); FD_CLR(fd, readfds); + ESP_LOGD(TAG, "removing %d from readfds and adding as local FD %d to fd_set of VFS ID %d", fd, local_fd, vfs_index); } if (writefds && FD_ISSET(fd, writefds)) { item->isset = true; FD_SET(local_fd, &item->writefds); FD_CLR(fd, writefds); + ESP_LOGD(TAG, "removing %d from writefds and adding as local FD %d to fd_set of VFS ID %d", fd, local_fd, vfs_index); } if (errorfds && FD_ISSET(fd, errorfds)) { item->isset = true; FD_SET(local_fd, &item->errorfds); FD_CLR(fd, errorfds); + ESP_LOGD(TAG, "removing %d from errorfds and adding as local FD %d to fd_set of VFS ID %d", fd, local_fd, vfs_index); } } @@ -824,6 +870,7 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds free(vfs_fds_triple); __errno_r(r) = ENOMEM; _lock_release(&s_one_select_lock); + ESP_LOGD(TAG, "cannot create s_select_sem"); return -1; } } @@ -835,6 +882,10 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds if (vfs && vfs->vfs.start_select && item->isset) { // call start_select for all non-socket VFSs with has at least one FD set in readfds, writefds, or errorfds // note: it can point to socket VFS but item->isset will be false for that + ESP_LOGD(TAG, "calling start_select for VFS ID %d with the following local FDs", i); + esp_vfs_log_fd_set("readfds", &item->readfds); + esp_vfs_log_fd_set("writefds", &item->writefds); + esp_vfs_log_fd_set("errorfds", &item->errorfds); esp_err_t err = vfs->vfs.start_select(nfds, &item->readfds, &item->writefds, &item->errorfds); if (err != ESP_OK) { @@ -847,13 +898,22 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds free(vfs_fds_triple); __errno_r(r) = ENOMEM; _lock_release(&s_one_select_lock); + ESP_LOGD(TAG, "start_select failed"); return -1; } } } if (socket_select) { + ESP_LOGD(TAG, "calling socket_select with the following FDs"); + esp_vfs_log_fd_set("readfds", readfds); + esp_vfs_log_fd_set("writefds", writefds); + esp_vfs_log_fd_set("errorfds", errorfds); ret = socket_select(nfds, readfds, writefds, errorfds, timeout); + ESP_LOGD(TAG, "socket_select returned %d and the FDs are the following", ret); + esp_vfs_log_fd_set("readfds", readfds); + esp_vfs_log_fd_set("writefds", writefds); + esp_vfs_log_fd_set("errorfds", errorfds); } else { if (readfds) { FD_ZERO(readfds); @@ -869,7 +929,9 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds if (timeout) { uint32_t timeout_ms = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; ticks_to_wait = timeout_ms / portTICK_PERIOD_MS; + ESP_LOGD(TAG, "timeout is %dms", timeout_ms); } + ESP_LOGD(TAG, "waiting without calling socket_select"); xSemaphoreTake(s_select_sem, ticks_to_wait); } @@ -883,6 +945,11 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds } free(vfs_fds_triple); _lock_release(&s_one_select_lock); + + ESP_LOGD(TAG, "esp_vfs_select returns %d", ret); + esp_vfs_log_fd_set("readfds", readfds); + esp_vfs_log_fd_set("writefds", writefds); + esp_vfs_log_fd_set("errorfds", errorfds); return ret; } From 15b26f8841049d3cb5d50eded25639b2e491781b Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Tue, 29 May 2018 11:01:25 +0200 Subject: [PATCH 183/187] VFS: esp_vfs_select() needs to be callable from concurrent tasks This fix is for compatibility with lwip_select(). It moves the lock to UART which is the only VFS driver which is implemented and is not "thread-safe". --- components/vfs/include/esp_vfs.h | 9 ++-- components/vfs/test/test_vfs_select.c | 49 ++++++++++++++++++---- components/vfs/vfs.c | 59 +++++++++++---------------- components/vfs/vfs_uart.c | 29 ++++++++++--- 4 files changed, 94 insertions(+), 52 deletions(-) diff --git a/components/vfs/include/esp_vfs.h b/components/vfs/include/esp_vfs.h index d06dd223fc..61b01b76f1 100644 --- a/components/vfs/include/esp_vfs.h +++ b/components/vfs/include/esp_vfs.h @@ -175,7 +175,7 @@ typedef struct int (*access)(const char *path, int amode); }; /** start_select is called for setting up synchronous I/O multiplexing of the desired file descriptors in the given VFS */ - esp_err_t (*start_select)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds); + esp_err_t (*start_select)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, SemaphoreHandle_t *signal_sem); /** socket select function for socket FDs with the functionality of POSIX select(); this should be set only for the socket VFS */ int (*socket_select)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout); /** called by VFS to interrupt the socket_select call when select is activated from a non-socket VFS driver; set only for the socket driver */ @@ -326,8 +326,10 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds * * This function is called when the VFS driver detects a read/write/error * condition as it was requested by the previous call to start_select. + * + * @param signal_sem semaphore handle which was passed to the driver by the start_select call */ -void esp_vfs_select_triggered(); +void esp_vfs_select_triggered(SemaphoreHandle_t *signal_sem); /** * @brief Notification from a VFS driver about a read/write/error condition (ISR version) @@ -335,9 +337,10 @@ void esp_vfs_select_triggered(); * This function is called when the VFS driver detects a read/write/error * condition as it was requested by the previous call to start_select. * + * @param signal_sem semaphore handle which was passed to the driver by the start_select call * @param woken is set to pdTRUE if the function wakes up a task with higher priority */ -void esp_vfs_select_triggered_isr(BaseType_t *woken); +void esp_vfs_select_triggered_isr(SemaphoreHandle_t *signal_sem, BaseType_t *woken); #ifdef __cplusplus } // extern "C" diff --git a/components/vfs/test/test_vfs_select.c b/components/vfs/test/test_vfs_select.c index be74ebe910..f9927a54f6 100644 --- a/components/vfs/test/test_vfs_select.c +++ b/components/vfs/test/test_vfs_select.c @@ -275,8 +275,12 @@ static void select_task(void *param) .tv_usec = 100000, }; - int s = select(1, NULL, NULL, NULL, &tv); - TEST_ASSERT_EQUAL(s, 0); //timeout + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(test_task_param->fd, &rfds); + + int s = select(test_task_param->fd + 1, &rfds, NULL, NULL, &tv); + TEST_ASSERT_EQUAL(0, s); //timeout if (test_task_param->sem) { xSemaphoreGive(test_task_param->sem); @@ -284,23 +288,52 @@ static void select_task(void *param) vTaskDelete(NULL); } -TEST_CASE("concurent select() fails", "[vfs]") +TEST_CASE("concurent selects work", "[vfs]") { struct timeval tv = { .tv_sec = 0, .tv_usec = 100000,//irrelevant }; - const test_task_param_t test_task_param = { + + int uart_fd, socket_fd; + const int dummy_socket_fd = open_dummy_socket(); + init(&uart_fd, &socket_fd); + + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(uart_fd, &rfds); + + test_task_param_t test_task_param = { + .fd = uart_fd, .sem = xSemaphoreCreateBinary(), }; TEST_ASSERT_NOT_NULL(test_task_param.sem); + xTaskCreate(select_task, "select_task", 4*1024, (void *) &test_task_param, 5, NULL); vTaskDelay(10 / portTICK_PERIOD_MS); //make sure the task has started and waits in select() - int s = select(1, NULL, NULL, NULL, &tv); - TEST_ASSERT_EQUAL(s, -1); //this select should fail because the other one is "waiting" - TEST_ASSERT_EQUAL(errno, EINTR); + int s = select(uart_fd + 1, &rfds, NULL, NULL, &tv); + TEST_ASSERT_EQUAL(-1, s); //this select should fail because two selects are accessing UART + //(the other one is waiting for the timeout) + TEST_ASSERT_EQUAL(EINTR, errno); - TEST_ASSERT_EQUAL(xSemaphoreTake(test_task_param.sem, 1000 / portTICK_PERIOD_MS), pdTRUE); + TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(test_task_param.sem, 1000 / portTICK_PERIOD_MS)); + + FD_ZERO(&rfds); + FD_SET(socket_fd, &rfds); + + test_task_param.fd = dummy_socket_fd; + + xTaskCreate(select_task, "select_task", 4*1024, (void *) &test_task_param, 5, NULL); + vTaskDelay(10 / portTICK_PERIOD_MS); //make sure the task has started and waits in select() + + s = select(socket_fd + 1, &rfds, NULL, NULL, &tv); + TEST_ASSERT_EQUAL(0, s); //this select should timeout as well as the concurrent one because + //concurrent socket select should work + + TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(test_task_param.sem, 1000 / portTICK_PERIOD_MS)); vSemaphoreDelete(test_task_param.sem); + + deinit(uart_fd, socket_fd); + close(dummy_socket_fd); } diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index cd9a2aceca..dfcb07aa89 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -72,15 +72,6 @@ static size_t s_vfs_count = 0; static fd_table_t s_fd_table[MAX_FDS] = { [0 ... MAX_FDS-1] = FD_TABLE_ENTRY_UNUSED }; static _lock_t s_fd_table_lock; -/* Semaphore used for waiting select events from other VFS drivers when socket - * select is not used (not registered or socket FDs are not observed by the - * given call of select) - */ -static SemaphoreHandle_t s_select_sem = NULL; - -/* Lock ensuring that select is called from only one task at the time */ -static _lock_t s_one_select_lock; - static esp_err_t esp_vfs_register_common(const char* base_path, size_t len, const esp_vfs_t* vfs, void* ctx, int *vfs_index) { if (len != LEN_PATH_PREFIX_IGNORED) { @@ -799,16 +790,9 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds return -1; } - if (_lock_try_acquire(&s_one_select_lock)) { - ESP_LOGD(TAG, "concurrent select is not supported"); - __errno_r(r) = EINTR; - return -1; - } - fds_triple_t *vfs_fds_triple; if ((vfs_fds_triple = calloc(s_vfs_count, sizeof(fds_triple_t))) == NULL) { __errno_r(r) = ENOMEM; - _lock_release(&s_one_select_lock); ESP_LOGD(TAG, "calloc is unsuccessful"); return -1; } @@ -863,14 +847,19 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds // the global readfds, writefds and errorfds contain only socket FDs (if // there any) + /* Semaphore used for waiting select events from other VFS drivers when socket + * select is not used (not registered or socket FDs are not observed by the + * given call of select) + */ + SemaphoreHandle_t select_sem = NULL; + if (!socket_select) { // There is no socket VFS registered or select() wasn't called for // any socket. Therefore, we will use our own signalization. - if ((s_select_sem = xSemaphoreCreateBinary()) == NULL) { + if ((select_sem = xSemaphoreCreateBinary()) == NULL) { free(vfs_fds_triple); __errno_r(r) = ENOMEM; - _lock_release(&s_one_select_lock); - ESP_LOGD(TAG, "cannot create s_select_sem"); + ESP_LOGD(TAG, "cannot create select_sem"); return -1; } } @@ -886,18 +875,17 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds esp_vfs_log_fd_set("readfds", &item->readfds); esp_vfs_log_fd_set("writefds", &item->writefds); esp_vfs_log_fd_set("errorfds", &item->errorfds); - esp_err_t err = vfs->vfs.start_select(nfds, &item->readfds, &item->writefds, &item->errorfds); + esp_err_t err = vfs->vfs.start_select(nfds, &item->readfds, &item->writefds, &item->errorfds, &select_sem); if (err != ESP_OK) { call_end_selects(i, vfs_fds_triple); (void) set_global_fd_sets(vfs_fds_triple, s_vfs_count, readfds, writefds, errorfds); - if (s_select_sem) { - vSemaphoreDelete(s_select_sem); - s_select_sem = NULL; + if (select_sem) { + vSemaphoreDelete(select_sem); + select_sem = NULL; } free(vfs_fds_triple); - __errno_r(r) = ENOMEM; - _lock_release(&s_one_select_lock); + __errno_r(r) = EINTR; ESP_LOGD(TAG, "start_select failed"); return -1; } @@ -932,19 +920,18 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds ESP_LOGD(TAG, "timeout is %dms", timeout_ms); } ESP_LOGD(TAG, "waiting without calling socket_select"); - xSemaphoreTake(s_select_sem, ticks_to_wait); + xSemaphoreTake(select_sem, ticks_to_wait); } call_end_selects(s_vfs_count, vfs_fds_triple); // for VFSs for start_select was called before if (ret >= 0) { ret += set_global_fd_sets(vfs_fds_triple, s_vfs_count, readfds, writefds, errorfds); } - if (s_select_sem) { - vSemaphoreDelete(s_select_sem); - s_select_sem = NULL; + if (select_sem) { + vSemaphoreDelete(select_sem); + select_sem = NULL; } free(vfs_fds_triple); - _lock_release(&s_one_select_lock); ESP_LOGD(TAG, "esp_vfs_select returns %d", ret); esp_vfs_log_fd_set("readfds", readfds); @@ -953,10 +940,10 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds return ret; } -void esp_vfs_select_triggered() +void esp_vfs_select_triggered(SemaphoreHandle_t *signal_sem) { - if (s_select_sem) { - xSemaphoreGive(s_select_sem); + if (signal_sem && (*signal_sem)) { + xSemaphoreGive(*signal_sem); } else { // Another way would be to go through s_fd_table and find the VFS // which has a permanent FD. But in order to avoid to lock @@ -971,10 +958,10 @@ void esp_vfs_select_triggered() } } -void esp_vfs_select_triggered_isr(BaseType_t *woken) +void esp_vfs_select_triggered_isr(SemaphoreHandle_t *signal_sem, BaseType_t *woken) { - if (s_select_sem) { - xSemaphoreGiveFromISR(s_select_sem, woken); + if (signal_sem && (*signal_sem)) { + xSemaphoreGiveFromISR(*signal_sem, woken); } else { // Another way would be to go through s_fd_table and find the VFS // which has a permanent FD. But in order to avoid to lock diff --git a/components/vfs/vfs_uart.c b/components/vfs/vfs_uart.c index c1c12066cb..4b4762c344 100644 --- a/components/vfs/vfs_uart.c +++ b/components/vfs/vfs_uart.c @@ -58,6 +58,10 @@ static int s_peek_char[UART_NUM] = { NONE, NONE, NONE }; // driver is used. static bool s_non_blocking[UART_NUM]; +/* Lock ensuring that uart_select is used from only one task at the time */ +static _lock_t s_one_select_lock; + +static SemaphoreHandle_t *_signal_sem = NULL; static fd_set *_readfds = NULL; static fd_set *_writefds = NULL; static fd_set *_errorfds = NULL; @@ -303,47 +307,55 @@ static void select_notif_callback(uart_port_t uart_num, uart_select_notif_t uart case UART_SELECT_READ_NOTIF: if (FD_ISSET(uart_num, _readfds_orig)) { FD_SET(uart_num, _readfds); - esp_vfs_select_triggered_isr(task_woken); + esp_vfs_select_triggered_isr(_signal_sem, task_woken); } break; case UART_SELECT_WRITE_NOTIF: if (FD_ISSET(uart_num, _writefds_orig)) { FD_SET(uart_num, _writefds); - esp_vfs_select_triggered_isr(task_woken); + esp_vfs_select_triggered_isr(_signal_sem, task_woken); } break; case UART_SELECT_ERROR_NOTIF: if (FD_ISSET(uart_num, _errorfds_orig)) { FD_SET(uart_num, _errorfds); - esp_vfs_select_triggered_isr(task_woken); + esp_vfs_select_triggered_isr(_signal_sem, task_woken); } break; } } -static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds) +static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, SemaphoreHandle_t *signal_sem) { + if (_lock_try_acquire(&s_one_select_lock)) { + return ESP_ERR_INVALID_STATE; + } + const int max_fds = MIN(nfds, UART_NUM); taskENTER_CRITICAL(uart_get_selectlock()); - if (_readfds || _writefds || _errorfds || _readfds_orig || _writefds_orig || _errorfds_orig) { + if (_readfds || _writefds || _errorfds || _readfds_orig || _writefds_orig || _errorfds_orig || _signal_sem) { taskEXIT_CRITICAL(uart_get_selectlock()); + _lock_release(&s_one_select_lock); return ESP_ERR_INVALID_STATE; } if ((_readfds_orig = malloc(sizeof(fd_set))) == NULL) { taskEXIT_CRITICAL(uart_get_selectlock()); + _lock_release(&s_one_select_lock); return ESP_ERR_NO_MEM; } if ((_writefds_orig = malloc(sizeof(fd_set))) == NULL) { taskEXIT_CRITICAL(uart_get_selectlock()); + _lock_release(&s_one_select_lock); return ESP_ERR_NO_MEM; } if ((_errorfds_orig = malloc(sizeof(fd_set))) == NULL) { taskEXIT_CRITICAL(uart_get_selectlock()); + _lock_release(&s_one_select_lock); return ESP_ERR_NO_MEM; } @@ -354,6 +366,8 @@ static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds, } } + _signal_sem = signal_sem; + _readfds = readfds; _writefds = writefds; _errorfds = exceptfds; @@ -367,6 +381,8 @@ static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds, FD_ZERO(exceptfds); taskEXIT_CRITICAL(uart_get_selectlock()); + // s_one_select_lock is not released on successfull exit - will be + // released in uart_end_select() return ESP_OK; } @@ -378,6 +394,8 @@ static void uart_end_select() uart_set_select_notif_callback(i, NULL); } + _signal_sem = NULL; + _readfds = NULL; _writefds = NULL; _errorfds = NULL; @@ -397,6 +415,7 @@ static void uart_end_select() _errorfds_orig = NULL; } taskEXIT_CRITICAL(uart_get_selectlock()); + _lock_release(&s_one_select_lock); } void esp_vfs_dev_uart_register() From 634e8cd54b0ff6fc3f1fc40ba4701b242ae551da Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Tue, 29 May 2018 11:01:25 +0200 Subject: [PATCH 184/187] VFS: Use convenience function for safe FD_ISSET --- components/vfs/vfs.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index dfcb07aa89..778db912a0 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -728,6 +728,11 @@ static void call_end_selects(int end_index, const fds_triple_t *vfs_fds_triple) } } +static inline bool esp_vfs_safe_fd_isset(int fd, const fd_set *fds) +{ + return fds && FD_ISSET(fd, fds); +} + static int set_global_fd_sets(const fds_triple_t *vfs_fds_triple, int size, fd_set *readfds, fd_set *writefds, fd_set *errorfds) { int ret = 0; @@ -737,17 +742,17 @@ static int set_global_fd_sets(const fds_triple_t *vfs_fds_triple, int size, fd_s if (item->isset) { for (int fd = 0; fd < MAX_FDS; ++fd) { const int local_fd = s_fd_table[fd].local_fd; // single read -> no locking is required - if (readfds && FD_ISSET(local_fd, &item->readfds)) { + if (readfds && esp_vfs_safe_fd_isset(local_fd, &item->readfds)) { ESP_LOGD(TAG, "FD %d in readfds was set from VFS ID %d", fd, i); FD_SET(fd, readfds); ++ret; } - if (writefds && FD_ISSET(local_fd, &item->writefds)) { + if (writefds && esp_vfs_safe_fd_isset(local_fd, &item->writefds)) { ESP_LOGD(TAG, "FD %d in writefds was set from VFS ID %d", fd, i); FD_SET(fd, writefds); ++ret; } - if (errorfds && FD_ISSET(local_fd, &item->errorfds)) { + if (errorfds && esp_vfs_safe_fd_isset(local_fd, &item->errorfds)) { ESP_LOGD(TAG, "FD %d in errorfds was set from VFS ID %d", fd, i); FD_SET(fd, errorfds); ++ret; @@ -764,7 +769,7 @@ static void esp_vfs_log_fd_set(const char *fds_name, const fd_set *fds) if (fds_name && fds) { ESP_LOGD(TAG, "FDs in %s =", fds_name); for (int i = 0; i < MAX_FDS; ++i) { - if (FD_ISSET(i, fds)) { + if (esp_vfs_safe_fd_isset(i, fds)) { ESP_LOGD(TAG, "%d", i); } } @@ -812,9 +817,9 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds if (is_socket_fd) { if (!socket_select) { // no socket_select found yet so take a look - if ((readfds && FD_ISSET(fd, readfds)) || - (writefds && FD_ISSET(fd, writefds)) || - (errorfds && FD_ISSET(fd, errorfds))) { + if (esp_vfs_safe_fd_isset(fd, readfds) || + esp_vfs_safe_fd_isset(fd, writefds) || + esp_vfs_safe_fd_isset(fd, errorfds)) { const vfs_entry_t *vfs = s_vfs[vfs_index]; socket_select = vfs->vfs.socket_select; } @@ -823,19 +828,19 @@ int esp_vfs_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds } fds_triple_t *item = &vfs_fds_triple[vfs_index]; // FD sets for VFS which belongs to fd - if (readfds && FD_ISSET(fd, readfds)) { + if (esp_vfs_safe_fd_isset(fd, readfds)) { item->isset = true; FD_SET(local_fd, &item->readfds); FD_CLR(fd, readfds); ESP_LOGD(TAG, "removing %d from readfds and adding as local FD %d to fd_set of VFS ID %d", fd, local_fd, vfs_index); } - if (writefds && FD_ISSET(fd, writefds)) { + if (esp_vfs_safe_fd_isset(fd, writefds)) { item->isset = true; FD_SET(local_fd, &item->writefds); FD_CLR(fd, writefds); ESP_LOGD(TAG, "removing %d from writefds and adding as local FD %d to fd_set of VFS ID %d", fd, local_fd, vfs_index); } - if (errorfds && FD_ISSET(fd, errorfds)) { + if (esp_vfs_safe_fd_isset(fd, errorfds)) { item->isset = true; FD_SET(local_fd, &item->errorfds); FD_CLR(fd, errorfds); From ecaf234c39472f4d4ba839bcfde66e02bb8bcac5 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Tue, 29 May 2018 11:01:25 +0200 Subject: [PATCH 185/187] VFS: fix possible memory leak in UART --- components/vfs/vfs_uart.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/components/vfs/vfs_uart.c b/components/vfs/vfs_uart.c index 4b4762c344..e52b5dd74f 100644 --- a/components/vfs/vfs_uart.c +++ b/components/vfs/vfs_uart.c @@ -89,6 +89,8 @@ static esp_line_endings_t s_rx_mode = ESP_LINE_ENDINGS_LF; #endif +static void uart_end_select(); + // Functions used to write bytes to UART. Default to "basic" functions. static tx_func_t s_uart_tx_func[UART_NUM] = { &uart_tx_char, &uart_tx_char, &uart_tx_char @@ -337,25 +339,25 @@ static esp_err_t uart_start_select(int nfds, fd_set *readfds, fd_set *writefds, if (_readfds || _writefds || _errorfds || _readfds_orig || _writefds_orig || _errorfds_orig || _signal_sem) { taskEXIT_CRITICAL(uart_get_selectlock()); - _lock_release(&s_one_select_lock); + uart_end_select(); return ESP_ERR_INVALID_STATE; } if ((_readfds_orig = malloc(sizeof(fd_set))) == NULL) { taskEXIT_CRITICAL(uart_get_selectlock()); - _lock_release(&s_one_select_lock); + uart_end_select(); return ESP_ERR_NO_MEM; } if ((_writefds_orig = malloc(sizeof(fd_set))) == NULL) { taskEXIT_CRITICAL(uart_get_selectlock()); - _lock_release(&s_one_select_lock); + uart_end_select(); return ESP_ERR_NO_MEM; } if ((_errorfds_orig = malloc(sizeof(fd_set))) == NULL) { taskEXIT_CRITICAL(uart_get_selectlock()); - _lock_release(&s_one_select_lock); + uart_end_select(); return ESP_ERR_NO_MEM; } From 74928b9bcb6fd2bcaecd2db84b143b589de97c79 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 29 May 2018 02:01:43 +0800 Subject: [PATCH 186/187] ci: check for executable flag on source files --- .gitlab-ci.yml | 14 +++++++++++ tools/ci/check-executable.sh | 48 ++++++++++++++++++++++++++++++++++++ tools/ci/executable-list.txt | 33 +++++++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100755 tools/ci/check-executable.sh create mode 100644 tools/ci/executable-list.txt diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e790ddf1d6..17feb07fbe 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -475,6 +475,20 @@ check_commit_msg: # commit start with "WIP: " need to be squashed before merge - 'git log --pretty=%s master.. -- | grep "^WIP: " && exit 1 || exit 0' +check_permissions: + stage: deploy + image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG + tags: + - build + except: + - master + - /^release\/v/ + - /^v\d+\.\d+(\.\d+)?($|-)/ + dependencies: [] + before_script: *do_nothing_before + script: + - tools/ci/check-executable.sh + check_submodule_sync: stage: deploy image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG diff --git a/tools/ci/check-executable.sh b/tools/ci/check-executable.sh new file mode 100755 index 0000000000..35b1b7704a --- /dev/null +++ b/tools/ci/check-executable.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# This script finds executable files in the repository, excluding some directories, +# then prints the list of all files which are not in executable-list.txt. +# Returns with error if this list is non-empty. + +cd $IDF_PATH + +tmp_list=$(mktemp) +out_list=$(mktemp) + +# build exclude pattern like '-o -path ./components/component/submodule' for each submodule +submodule_excludes=$(git config --file .gitmodules --get-regexp path | awk '{ print "-o -path ./" $2 }') + +# figure out which flag to use when searching for executable files +if [ "$(uname -s)" == "Darwin" ]; then + perm_flag="-perm +111" +else + perm_flag="-executable" +fi + +find . -type d \( \ + -path ./.git \ + -o -name build \ + -o -name builds \ + $submodule_excludes \ + \) -prune -o -type f $perm_flag -print \ + | sed "s|^\./||" > $tmp_list + +# this looks for lines present in tmp_list but not in executable-list.txt +comm -13 <(cat tools/ci/executable-list.txt | sed -n "/^#/!p" | sort) <(sort $tmp_list) > $out_list + +ret=0 +if [ -s $out_list ]; then + ret=1 + echo "Error: the following file(s) have executable flag set:" + echo "" + cat $out_list + echo "" + echo "If any files need to be executable (usually, scripts), add them to tools/ci/executable-list.txt" + echo "Make the rest of the files non-executable using 'chmod -x '." + echo "On Windows, use 'git update-index --chmod=-x filename' instead." + echo "" +fi + +rm $tmp_list +rm $out_list + +exit $ret diff --git a/tools/ci/executable-list.txt b/tools/ci/executable-list.txt new file mode 100644 index 0000000000..a78581024d --- /dev/null +++ b/tools/ci/executable-list.txt @@ -0,0 +1,33 @@ +# Some tools +components/esp32/ld/elf_to_ld.sh +components/espcoredump/espcoredump.py +components/heap/test_multi_heap_host/test_all_configs.sh +components/idf_test/unit_test/TestCaseScript/IDFUnitTest/__init__.py +components/partition_table/gen_esp32part.py +components/partition_table/test_gen_esp32part_host/gen_esp32part_tests.py +components/ulp/esp32ulp_mapgen.py +docs/check_doc_warnings.sh +docs/check_lang_folder_sync.sh +docs/gen-kconfig-doc.py +tools/ci/apply_bot_filter.py +tools/ci/build_examples.sh +tools/ci/check-executable.sh +tools/ci/checkout_project_ref.py +tools/ci/get-full-sources.sh +tools/ci/mirror-submodule-update.sh +tools/ci/mirror-synchronize.sh +tools/ci/test_build_system.sh +tools/ci/test_configure_ci_environment.sh +tools/esp_app_trace/apptrace_proc.py +tools/esp_app_trace/logtrace_proc.py +tools/format.sh +tools/gen_esp_err_to_name.py +tools/idf_monitor.py +tools/idf_size.py +tools/kconfig/check.sh +tools/kconfig/lxdialog/check-lxdialog.sh +tools/kconfig/merge_config.sh +tools/kconfig/streamline_config.pl +tools/kconfig/conf +tools/kconfig/mconf +tools/windows/eclipse_make.sh From cb649e452f3c64a7db1f4a61e162a16b70248204 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 29 May 2018 02:08:38 +0800 Subject: [PATCH 187/187] remove executable permission from source files --- components/app_update/component.mk | 0 components/app_update/include/esp_ota_ops.h | 0 components/bootloader_support/component.mk | 0 components/esp32/Kconfig | 0 components/esp32/include/esp_types.h | 0 components/esp32/include/esp_wifi.h | 0 components/esp32/include/esp_wifi_internal.h | 0 components/esp32/include/esp_wifi_types.h | 0 components/esp32/include/rom/md5_hash.h | 0 components/esp32/include/rom/queue.h | 0 components/esp32/include/xtensa/board.h | 0 components/esp32/include/xtensa/c6x-compat.h | 0 components/esp32/include/xtensa/cacheasm.h | 0 components/esp32/include/xtensa/cacheattrasm.h | 0 components/esp32/include/xtensa/core-macros.h | 0 components/esp32/include/xtensa/coreasm.h | 0 components/esp32/include/xtensa/corebits.h | 0 components/esp32/include/xtensa/debugfs.h | 0 components/esp32/include/xtensa/feedback.h | 0 components/esp32/include/xtensa/gdbio.h | 0 components/esp32/include/xtensa/hal.h | 0 components/esp32/include/xtensa/jtag-xtensa.h | 0 .../include/xtensa/lcd-splc780d-4bitmode-board.h | 0 .../esp32/include/xtensa/lcd-splc780d-4bitmode.h | 0 components/esp32/include/xtensa/lcd-splc780d.h | 0 components/esp32/include/xtensa/overlay.h | 0 components/esp32/include/xtensa/overlay_os_asm.h | 0 components/esp32/include/xtensa/sim.h | 0 components/esp32/include/xtensa/simboard.h | 0 components/esp32/include/xtensa/simcall-errno.h | 0 components/esp32/include/xtensa/simcall-fcntl.h | 0 components/esp32/include/xtensa/simcall.h | 0 components/esp32/include/xtensa/specreg.h | 0 components/esp32/include/xtensa/trax-api.h | 0 components/esp32/include/xtensa/trax-core-config.h | 0 components/esp32/include/xtensa/trax-proto.h | 0 components/esp32/include/xtensa/trax-util.h | 0 components/esp32/include/xtensa/trax.h | 0 components/esp32/include/xtensa/traxfile.h | 0 components/esp32/include/xtensa/traxreg.h | 0 components/esp32/include/xtensa/uart-16550-board.h | 0 components/esp32/include/xtensa/uart-16550.h | 0 components/esp32/include/xtensa/udma.h | 0 components/esp32/include/xtensa/xdm-regs.h | 0 components/esp32/include/xtensa/xmon.h | 0 components/esp32/include/xtensa/xmp-library.h | 0 components/esp32/include/xtensa/xos.h | 0 components/esp32/include/xtensa/xos_common.h | 0 components/esp32/include/xtensa/xos_cond.h | 0 components/esp32/include/xtensa/xos_errors.h | 0 components/esp32/include/xtensa/xos_event.h | 0 components/esp32/include/xtensa/xos_internal.h | 0 components/esp32/include/xtensa/xos_msgq.h | 0 components/esp32/include/xtensa/xos_mutex.h | 0 components/esp32/include/xtensa/xos_params.h | 0 components/esp32/include/xtensa/xos_regaccess.h | 0 components/esp32/include/xtensa/xos_semaphore.h | 0 components/esp32/include/xtensa/xos_stopwatch.h | 0 components/esp32/include/xtensa/xos_syslog.h | 0 components/esp32/include/xtensa/xos_thread.h | 0 components/esp32/include/xtensa/xos_timer.h | 0 components/esp32/include/xtensa/xos_types.h | 0 components/esp32/include/xtensa/xt_perf_consts.h | 0 components/esp32/include/xtensa/xt_perfmon.h | 0 components/esp32/include/xtensa/xt_profiling.h | 0 components/esp32/include/xtensa/xt_reftb.h | 0 components/esp32/include/xtensa/xtav110.h | 0 .../esp32/include/xtensa/xtav110/xtensa/board.h | 0 components/esp32/include/xtensa/xtav200.h | 0 .../esp32/include/xtensa/xtav200/xtensa/board.h | 0 components/esp32/include/xtensa/xtav60.h | 0 .../esp32/include/xtensa/xtav60/xtensa/board.h | 0 .../xtensa/xtav60/xtensa/lcd-splc780d-board.h | 0 components/esp32/include/xtensa/xtbsp.h | 0 .../esp32/include/xtensa/xtensa-libdb-macros.h | 0 components/esp32/include/xtensa/xtensa-versions.h | 0 components/esp32/include/xtensa/xtensa-xer.h | 0 components/esp32/include/xtensa/xtkc705.h | 0 .../esp32/include/xtensa/xtkc705/xtensa/board.h | 0 components/esp32/include/xtensa/xtload-api.h | 0 components/esp32/include/xtensa/xtml605.h | 0 .../esp32/include/xtensa/xtml605/xtensa/board.h | 0 .../esp32/include/xtensa/xtruntime-core-state.h | 0 components/esp32/include/xtensa/xtruntime-frames.h | 0 components/esp32/include/xtensa/xtruntime.h | 0 components/esp32/include/xtensa/xtutil.h | 0 components/ethernet/component.mk | 0 components/idf_test/component.mk | 0 components/log/component.mk | 0 components/lwip/CHANGELOG | 0 components/lwip/COPYING | 0 components/lwip/Kconfig | 0 components/lwip/README | 0 components/lwip/api/api_lib.c | 0 components/lwip/api/api_msg.c | 0 components/lwip/api/err.c | 0 components/lwip/api/netbuf.c | 0 components/lwip/api/netdb.c | 0 components/lwip/api/netifapi.c | 0 components/lwip/api/pppapi.c | 0 components/lwip/api/sockets.c | 0 components/lwip/api/tcpip.c | 0 components/lwip/core/def.c | 0 components/lwip/core/dns.c | 0 components/lwip/core/inet_chksum.c | 0 components/lwip/core/init.c | 0 components/lwip/core/ip.c | 0 components/lwip/core/ipv4/autoip.c | 0 components/lwip/core/ipv4/dhcp.c | 0 components/lwip/core/ipv4/icmp.c | 0 components/lwip/core/ipv4/igmp.c | 0 components/lwip/core/ipv4/ip4.c | 0 components/lwip/core/ipv4/ip4_addr.c | 0 components/lwip/core/ipv4/ip_frag.c | 0 components/lwip/core/ipv6/README | 0 components/lwip/core/ipv6/dhcp6.c | 0 components/lwip/core/ipv6/ethip6.c | 0 components/lwip/core/ipv6/icmp6.c | 0 components/lwip/core/ipv6/inet6.c | 0 components/lwip/core/ipv6/ip6.c | 0 components/lwip/core/ipv6/ip6_addr.c | 0 components/lwip/core/ipv6/ip6_frag.c | 0 components/lwip/core/ipv6/mld6.c | 0 components/lwip/core/ipv6/nd6.c | 0 components/lwip/core/mem.c | 0 components/lwip/core/memp.c | 0 components/lwip/core/netif.c | 0 components/lwip/core/pbuf.c | 0 components/lwip/core/raw.c | 0 components/lwip/core/stats.c | 0 components/lwip/core/sys.c | 0 components/lwip/core/tcp.c | 0 components/lwip/core/tcp_in.c | 0 components/lwip/core/tcp_out.c | 0 components/lwip/core/timers.c | 0 components/lwip/core/udp.c | 0 components/lwip/include/lwip/lwip/api.h | 0 components/lwip/include/lwip/lwip/arch.h | 0 components/lwip/include/lwip/lwip/autoip.h | 0 components/lwip/include/lwip/lwip/debug.h | 0 components/lwip/include/lwip/lwip/def.h | 0 components/lwip/include/lwip/lwip/dhcp.h | 0 components/lwip/include/lwip/lwip/dhcp6.h | 0 components/lwip/include/lwip/lwip/dns.h | 0 components/lwip/include/lwip/lwip/err.h | 0 components/lwip/include/lwip/lwip/ethip6.h | 0 components/lwip/include/lwip/lwip/icmp.h | 0 components/lwip/include/lwip/lwip/icmp6.h | 0 components/lwip/include/lwip/lwip/igmp.h | 0 components/lwip/include/lwip/lwip/inet.h | 0 components/lwip/include/lwip/lwip/inet_chksum.h | 0 components/lwip/include/lwip/lwip/init.h | 0 components/lwip/include/lwip/lwip/ip.h | 0 components/lwip/include/lwip/lwip/ip4.h | 0 components/lwip/include/lwip/lwip/ip4_addr.h | 0 components/lwip/include/lwip/lwip/ip6.h | 0 components/lwip/include/lwip/lwip/ip6_addr.h | 0 components/lwip/include/lwip/lwip/ip6_frag.h | 0 components/lwip/include/lwip/lwip/ip_addr.h | 0 components/lwip/include/lwip/lwip/ip_frag.h | 0 components/lwip/include/lwip/lwip/mem.h | 0 components/lwip/include/lwip/lwip/memp.h | 0 components/lwip/include/lwip/lwip/mld6.h | 0 components/lwip/include/lwip/lwip/nd6.h | 0 components/lwip/include/lwip/lwip/netbuf.h | 0 components/lwip/include/lwip/lwip/netdb.h | 0 components/lwip/include/lwip/lwip/netif.h | 0 components/lwip/include/lwip/lwip/netifapi.h | 0 components/lwip/include/lwip/lwip/opt.h | 0 components/lwip/include/lwip/lwip/pbuf.h | 0 components/lwip/include/lwip/lwip/pppapi.h | 0 components/lwip/include/lwip/lwip/priv/api_msg.h | 0 components/lwip/include/lwip/lwip/priv/memp_priv.h | 0 components/lwip/include/lwip/lwip/priv/memp_std.h | 0 components/lwip/include/lwip/lwip/priv/tcp_priv.h | 0 components/lwip/include/lwip/lwip/priv/tcpip_priv.h | 0 components/lwip/include/lwip/lwip/raw.h | 0 components/lwip/include/lwip/lwip/sio.h | 0 components/lwip/include/lwip/lwip/snmp.h | 0 components/lwip/include/lwip/lwip/sockets.h | 0 components/lwip/include/lwip/lwip/stats.h | 0 components/lwip/include/lwip/lwip/sys.h | 0 components/lwip/include/lwip/lwip/tcp.h | 0 components/lwip/include/lwip/lwip/tcpip.h | 0 components/lwip/include/lwip/lwip/timers.h | 0 components/lwip/include/lwip/lwip/udp.h | 0 components/lwip/include/lwip/netif/etharp.h | 0 components/lwip/include/lwip/netif/ethernet.h | 0 components/lwip/include/lwip/netif/lowpan6.h | 0 components/lwip/include/lwip/netif/lowpan6_opts.h | 0 components/lwip/include/lwip/netif/ppp/ccp.h | 0 components/lwip/include/lwip/netif/ppp/chap-md5.h | 0 components/lwip/include/lwip/netif/ppp/chap-new.h | 0 components/lwip/include/lwip/netif/ppp/chap_ms.h | 0 components/lwip/include/lwip/netif/ppp/eap.h | 0 components/lwip/include/lwip/netif/ppp/ecp.h | 0 components/lwip/include/lwip/netif/ppp/eui64.h | 0 components/lwip/include/lwip/netif/ppp/fsm.h | 0 components/lwip/include/lwip/netif/ppp/ipcp.h | 0 components/lwip/include/lwip/netif/ppp/ipv6cp.h | 0 components/lwip/include/lwip/netif/ppp/lcp.h | 0 components/lwip/include/lwip/netif/ppp/magic.h | 0 components/lwip/include/lwip/netif/ppp/mppe.h | 0 .../lwip/include/lwip/netif/ppp/polarssl/arc4.h | 0 .../lwip/include/lwip/netif/ppp/polarssl/des.h | 0 .../lwip/include/lwip/netif/ppp/polarssl/md4.h | 0 .../lwip/include/lwip/netif/ppp/polarssl/md5.h | 0 .../lwip/include/lwip/netif/ppp/polarssl/sha1.h | 0 components/lwip/include/lwip/netif/ppp/ppp.h | 0 components/lwip/include/lwip/netif/ppp/ppp_impl.h | 0 components/lwip/include/lwip/netif/ppp/pppcrypt.h | 0 components/lwip/include/lwip/netif/ppp/pppdebug.h | 0 components/lwip/include/lwip/netif/ppp/pppoe.h | 0 components/lwip/include/lwip/netif/ppp/pppol2tp.h | 0 components/lwip/include/lwip/netif/ppp/pppos.h | 0 components/lwip/include/lwip/netif/ppp/upap.h | 0 components/lwip/include/lwip/netif/ppp/vj.h | 0 components/lwip/include/lwip/netif/slipif.h | 0 .../lwip/include/lwip/port/netif/ethernetif.h | 0 components/lwip/include/lwip/port/netif/wlanif.h | 0 components/lwip/include/lwip/posix/netdb.h | 0 components/lwip/include/lwip/posix/sys/socket.h | 0 components/lwip/netif/FILES | 0 components/lwip/netif/etharp.c | 0 components/lwip/netif/ethernet.c | 0 components/lwip/netif/ethernetif.c | 0 components/lwip/netif/lowpan6.c | 0 components/lwip/netif/ppp/PPPD_FOLLOWUP | 0 components/lwip/netif/ppp/auth.c | 0 components/lwip/netif/ppp/ccp.c | 0 components/lwip/netif/ppp/chap-md5.c | 0 components/lwip/netif/ppp/chap-new.c | 0 components/lwip/netif/ppp/chap_ms.c | 0 components/lwip/netif/ppp/demand.c | 0 components/lwip/netif/ppp/eap.c | 0 components/lwip/netif/ppp/ecp.c | 0 components/lwip/netif/ppp/eui64.c | 0 components/lwip/netif/ppp/fsm.c | 0 components/lwip/netif/ppp/ipcp.c | 0 components/lwip/netif/ppp/ipv6cp.c | 0 components/lwip/netif/ppp/lcp.c | 0 components/lwip/netif/ppp/magic.c | 0 components/lwip/netif/ppp/mppe.c | 0 components/lwip/netif/ppp/multilink.c | 0 components/lwip/netif/ppp/polarssl/README | 0 components/lwip/netif/ppp/polarssl/arc4.c | 0 components/lwip/netif/ppp/polarssl/des.c | 0 components/lwip/netif/ppp/polarssl/md4.c | 0 components/lwip/netif/ppp/polarssl/md5.c | 0 components/lwip/netif/ppp/polarssl/sha1.c | 0 components/lwip/netif/ppp/ppp.c | 0 components/lwip/netif/ppp/pppcrypt.c | 0 components/lwip/netif/ppp/pppoe.c | 0 components/lwip/netif/ppp/pppol2tp.c | 0 components/lwip/netif/ppp/pppos.c | 0 components/lwip/netif/ppp/upap.c | 0 components/lwip/netif/ppp/utils.c | 0 components/lwip/netif/ppp/vj.c | 0 components/lwip/netif/slipif.c | 0 components/lwip/port/freertos/sys_arch.c | 0 components/mdns/test_afl_fuzz_host/in/test-14.bin | Bin components/mdns/test_afl_fuzz_host/in/test-15.bin | Bin components/mdns/test_afl_fuzz_host/in/test-16.bin | Bin components/mdns/test_afl_fuzz_host/in/test-28.bin | Bin components/mdns/test_afl_fuzz_host/in/test-29.bin | Bin components/mdns/test_afl_fuzz_host/in/test-31.bin | Bin components/mdns/test_afl_fuzz_host/in/test-53.bin | Bin components/mdns/test_afl_fuzz_host/in/test-56.bin | Bin components/mdns/test_afl_fuzz_host/in/test-63.bin | Bin components/mdns/test_afl_fuzz_host/in/test-83.bin | Bin components/mdns/test_afl_fuzz_host/in/test-88.bin | Bin components/mdns/test_afl_fuzz_host/in/test-89.bin | Bin components/mdns/test_afl_fuzz_host/in/test-95.bin | Bin components/mdns/test_afl_fuzz_host/in/test-96.bin | Bin components/nvs_flash/component.mk | 0 components/openssl/include/openssl/ssl.h | 0 components/openssl/platform/ssl_pm.c | 0 components/sdmmc/component.mk | 0 components/smartconfig_ack/smartconfig_ack.c | 0 components/spi_flash/component.mk | 0 components/spiffs/include/spiffs_config.h | 0 components/tcpip_adapter/component.mk | 0 components/ulp/component.mk | 0 components/vfs/component.mk | 0 components/wear_levelling/Kconfig | 0 components/wear_levelling/WL_Ext_Perf.cpp | 0 components/wear_levelling/WL_Ext_Safe.cpp | 0 .../wear_levelling/private_include/WL_Ext_Cfg.h | 0 .../wear_levelling/private_include/WL_Ext_Perf.h | 0 .../wear_levelling/private_include/WL_Ext_Safe.h | 0 components/xtensa-debug-module/component.mk | 0 docs/en/api-guides/ulp_instruction_set.rst | 0 docs/en/api-guides/wifi.rst | 0 docs/zh_CN/api-guides/ulp_instruction_set.rst | 0 examples/bluetooth/a2dp_gatts_coex/README.md | 0 .../bluetooth/a2dp_gatts_coex/main/component.mk | 0 examples/bluetooth/a2dp_sink/Makefile | 0 examples/bluetooth/a2dp_sink/README.md | 0 examples/bluetooth/a2dp_sink/main/component.mk | 0 examples/bluetooth/a2dp_source/Makefile | 0 examples/bluetooth/a2dp_source/README.md | 0 examples/bluetooth/a2dp_source/main/component.mk | 0 examples/bluetooth/bt_discovery/Makefile | 0 examples/bluetooth/bt_discovery/README.rst | 0 examples/bluetooth/bt_discovery/main/component.mk | 0 examples/peripherals/i2s_adc_dac/Makefile | 0 examples/peripherals/i2s_adc_dac/README.md | 0 examples/peripherals/i2s_adc_dac/main/component.mk | 0 examples/protocols/mdns/main/mdns_example_main.c | 0 .../protocols/openssl_server/main/Kconfig.projbuild | 0 .../openssl_server/main/openssl_server_example.h | 0 .../main/openssl_server_example_main.c | 0 examples/wifi/iperf/Makefile | 0 examples/wifi/iperf/components/component.mk | 0 examples/wifi/power_save/README.md | 0 examples/wifi/power_save/main/Kconfig.projbuild | 0 316 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 components/app_update/component.mk mode change 100755 => 100644 components/app_update/include/esp_ota_ops.h mode change 100755 => 100644 components/bootloader_support/component.mk mode change 100755 => 100644 components/esp32/Kconfig mode change 100755 => 100644 components/esp32/include/esp_types.h mode change 100755 => 100644 components/esp32/include/esp_wifi.h mode change 100755 => 100644 components/esp32/include/esp_wifi_internal.h mode change 100755 => 100644 components/esp32/include/esp_wifi_types.h mode change 100755 => 100644 components/esp32/include/rom/md5_hash.h mode change 100755 => 100644 components/esp32/include/rom/queue.h mode change 100755 => 100644 components/esp32/include/xtensa/board.h mode change 100755 => 100644 components/esp32/include/xtensa/c6x-compat.h mode change 100755 => 100644 components/esp32/include/xtensa/cacheasm.h mode change 100755 => 100644 components/esp32/include/xtensa/cacheattrasm.h mode change 100755 => 100644 components/esp32/include/xtensa/core-macros.h mode change 100755 => 100644 components/esp32/include/xtensa/coreasm.h mode change 100755 => 100644 components/esp32/include/xtensa/corebits.h mode change 100755 => 100644 components/esp32/include/xtensa/debugfs.h mode change 100755 => 100644 components/esp32/include/xtensa/feedback.h mode change 100755 => 100644 components/esp32/include/xtensa/gdbio.h mode change 100755 => 100644 components/esp32/include/xtensa/hal.h mode change 100755 => 100644 components/esp32/include/xtensa/jtag-xtensa.h mode change 100755 => 100644 components/esp32/include/xtensa/lcd-splc780d-4bitmode-board.h mode change 100755 => 100644 components/esp32/include/xtensa/lcd-splc780d-4bitmode.h mode change 100755 => 100644 components/esp32/include/xtensa/lcd-splc780d.h mode change 100755 => 100644 components/esp32/include/xtensa/overlay.h mode change 100755 => 100644 components/esp32/include/xtensa/overlay_os_asm.h mode change 100755 => 100644 components/esp32/include/xtensa/sim.h mode change 100755 => 100644 components/esp32/include/xtensa/simboard.h mode change 100755 => 100644 components/esp32/include/xtensa/simcall-errno.h mode change 100755 => 100644 components/esp32/include/xtensa/simcall-fcntl.h mode change 100755 => 100644 components/esp32/include/xtensa/simcall.h mode change 100755 => 100644 components/esp32/include/xtensa/specreg.h mode change 100755 => 100644 components/esp32/include/xtensa/trax-api.h mode change 100755 => 100644 components/esp32/include/xtensa/trax-core-config.h mode change 100755 => 100644 components/esp32/include/xtensa/trax-proto.h mode change 100755 => 100644 components/esp32/include/xtensa/trax-util.h mode change 100755 => 100644 components/esp32/include/xtensa/trax.h mode change 100755 => 100644 components/esp32/include/xtensa/traxfile.h mode change 100755 => 100644 components/esp32/include/xtensa/traxreg.h mode change 100755 => 100644 components/esp32/include/xtensa/uart-16550-board.h mode change 100755 => 100644 components/esp32/include/xtensa/uart-16550.h mode change 100755 => 100644 components/esp32/include/xtensa/udma.h mode change 100755 => 100644 components/esp32/include/xtensa/xdm-regs.h mode change 100755 => 100644 components/esp32/include/xtensa/xmon.h mode change 100755 => 100644 components/esp32/include/xtensa/xmp-library.h mode change 100755 => 100644 components/esp32/include/xtensa/xos.h mode change 100755 => 100644 components/esp32/include/xtensa/xos_common.h mode change 100755 => 100644 components/esp32/include/xtensa/xos_cond.h mode change 100755 => 100644 components/esp32/include/xtensa/xos_errors.h mode change 100755 => 100644 components/esp32/include/xtensa/xos_event.h mode change 100755 => 100644 components/esp32/include/xtensa/xos_internal.h mode change 100755 => 100644 components/esp32/include/xtensa/xos_msgq.h mode change 100755 => 100644 components/esp32/include/xtensa/xos_mutex.h mode change 100755 => 100644 components/esp32/include/xtensa/xos_params.h mode change 100755 => 100644 components/esp32/include/xtensa/xos_regaccess.h mode change 100755 => 100644 components/esp32/include/xtensa/xos_semaphore.h mode change 100755 => 100644 components/esp32/include/xtensa/xos_stopwatch.h mode change 100755 => 100644 components/esp32/include/xtensa/xos_syslog.h mode change 100755 => 100644 components/esp32/include/xtensa/xos_thread.h mode change 100755 => 100644 components/esp32/include/xtensa/xos_timer.h mode change 100755 => 100644 components/esp32/include/xtensa/xos_types.h mode change 100755 => 100644 components/esp32/include/xtensa/xt_perf_consts.h mode change 100755 => 100644 components/esp32/include/xtensa/xt_perfmon.h mode change 100755 => 100644 components/esp32/include/xtensa/xt_profiling.h mode change 100755 => 100644 components/esp32/include/xtensa/xt_reftb.h mode change 100755 => 100644 components/esp32/include/xtensa/xtav110.h mode change 100755 => 100644 components/esp32/include/xtensa/xtav110/xtensa/board.h mode change 100755 => 100644 components/esp32/include/xtensa/xtav200.h mode change 100755 => 100644 components/esp32/include/xtensa/xtav200/xtensa/board.h mode change 100755 => 100644 components/esp32/include/xtensa/xtav60.h mode change 100755 => 100644 components/esp32/include/xtensa/xtav60/xtensa/board.h mode change 100755 => 100644 components/esp32/include/xtensa/xtav60/xtensa/lcd-splc780d-board.h mode change 100755 => 100644 components/esp32/include/xtensa/xtbsp.h mode change 100755 => 100644 components/esp32/include/xtensa/xtensa-libdb-macros.h mode change 100755 => 100644 components/esp32/include/xtensa/xtensa-versions.h mode change 100755 => 100644 components/esp32/include/xtensa/xtensa-xer.h mode change 100755 => 100644 components/esp32/include/xtensa/xtkc705.h mode change 100755 => 100644 components/esp32/include/xtensa/xtkc705/xtensa/board.h mode change 100755 => 100644 components/esp32/include/xtensa/xtload-api.h mode change 100755 => 100644 components/esp32/include/xtensa/xtml605.h mode change 100755 => 100644 components/esp32/include/xtensa/xtml605/xtensa/board.h mode change 100755 => 100644 components/esp32/include/xtensa/xtruntime-core-state.h mode change 100755 => 100644 components/esp32/include/xtensa/xtruntime-frames.h mode change 100755 => 100644 components/esp32/include/xtensa/xtruntime.h mode change 100755 => 100644 components/esp32/include/xtensa/xtutil.h mode change 100755 => 100644 components/ethernet/component.mk mode change 100755 => 100644 components/idf_test/component.mk mode change 100755 => 100644 components/log/component.mk mode change 100755 => 100644 components/lwip/CHANGELOG mode change 100755 => 100644 components/lwip/COPYING mode change 100755 => 100644 components/lwip/Kconfig mode change 100755 => 100644 components/lwip/README mode change 100755 => 100644 components/lwip/api/api_lib.c mode change 100755 => 100644 components/lwip/api/api_msg.c mode change 100755 => 100644 components/lwip/api/err.c mode change 100755 => 100644 components/lwip/api/netbuf.c mode change 100755 => 100644 components/lwip/api/netdb.c mode change 100755 => 100644 components/lwip/api/netifapi.c mode change 100755 => 100644 components/lwip/api/pppapi.c mode change 100755 => 100644 components/lwip/api/sockets.c mode change 100755 => 100644 components/lwip/api/tcpip.c mode change 100755 => 100644 components/lwip/core/def.c mode change 100755 => 100644 components/lwip/core/dns.c mode change 100755 => 100644 components/lwip/core/inet_chksum.c mode change 100755 => 100644 components/lwip/core/init.c mode change 100755 => 100644 components/lwip/core/ip.c mode change 100755 => 100644 components/lwip/core/ipv4/autoip.c mode change 100755 => 100644 components/lwip/core/ipv4/dhcp.c mode change 100755 => 100644 components/lwip/core/ipv4/icmp.c mode change 100755 => 100644 components/lwip/core/ipv4/igmp.c mode change 100755 => 100644 components/lwip/core/ipv4/ip4.c mode change 100755 => 100644 components/lwip/core/ipv4/ip4_addr.c mode change 100755 => 100644 components/lwip/core/ipv4/ip_frag.c mode change 100755 => 100644 components/lwip/core/ipv6/README mode change 100755 => 100644 components/lwip/core/ipv6/dhcp6.c mode change 100755 => 100644 components/lwip/core/ipv6/ethip6.c mode change 100755 => 100644 components/lwip/core/ipv6/icmp6.c mode change 100755 => 100644 components/lwip/core/ipv6/inet6.c mode change 100755 => 100644 components/lwip/core/ipv6/ip6.c mode change 100755 => 100644 components/lwip/core/ipv6/ip6_addr.c mode change 100755 => 100644 components/lwip/core/ipv6/ip6_frag.c mode change 100755 => 100644 components/lwip/core/ipv6/mld6.c mode change 100755 => 100644 components/lwip/core/ipv6/nd6.c mode change 100755 => 100644 components/lwip/core/mem.c mode change 100755 => 100644 components/lwip/core/memp.c mode change 100755 => 100644 components/lwip/core/netif.c mode change 100755 => 100644 components/lwip/core/pbuf.c mode change 100755 => 100644 components/lwip/core/raw.c mode change 100755 => 100644 components/lwip/core/stats.c mode change 100755 => 100644 components/lwip/core/sys.c mode change 100755 => 100644 components/lwip/core/tcp.c mode change 100755 => 100644 components/lwip/core/tcp_in.c mode change 100755 => 100644 components/lwip/core/tcp_out.c mode change 100755 => 100644 components/lwip/core/timers.c mode change 100755 => 100644 components/lwip/core/udp.c mode change 100755 => 100644 components/lwip/include/lwip/lwip/api.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/arch.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/autoip.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/debug.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/def.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/dhcp.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/dhcp6.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/dns.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/err.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/ethip6.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/icmp.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/icmp6.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/igmp.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/inet.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/inet_chksum.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/init.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/ip.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/ip4.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/ip4_addr.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/ip6.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/ip6_addr.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/ip6_frag.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/ip_addr.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/ip_frag.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/mem.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/memp.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/mld6.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/nd6.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/netbuf.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/netdb.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/netif.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/netifapi.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/opt.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/pbuf.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/pppapi.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/priv/api_msg.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/priv/memp_priv.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/priv/memp_std.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/priv/tcp_priv.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/priv/tcpip_priv.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/raw.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/sio.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/snmp.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/sockets.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/stats.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/sys.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/tcp.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/tcpip.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/timers.h mode change 100755 => 100644 components/lwip/include/lwip/lwip/udp.h mode change 100755 => 100644 components/lwip/include/lwip/netif/etharp.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ethernet.h mode change 100755 => 100644 components/lwip/include/lwip/netif/lowpan6.h mode change 100755 => 100644 components/lwip/include/lwip/netif/lowpan6_opts.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/ccp.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/chap-md5.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/chap-new.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/chap_ms.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/eap.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/ecp.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/eui64.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/fsm.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/ipcp.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/ipv6cp.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/lcp.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/magic.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/mppe.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/polarssl/arc4.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/polarssl/des.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/polarssl/md4.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/polarssl/md5.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/polarssl/sha1.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/ppp.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/ppp_impl.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/pppcrypt.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/pppdebug.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/pppoe.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/pppol2tp.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/pppos.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/upap.h mode change 100755 => 100644 components/lwip/include/lwip/netif/ppp/vj.h mode change 100755 => 100644 components/lwip/include/lwip/netif/slipif.h mode change 100755 => 100644 components/lwip/include/lwip/port/netif/ethernetif.h mode change 100755 => 100644 components/lwip/include/lwip/port/netif/wlanif.h mode change 100755 => 100644 components/lwip/include/lwip/posix/netdb.h mode change 100755 => 100644 components/lwip/include/lwip/posix/sys/socket.h mode change 100755 => 100644 components/lwip/netif/FILES mode change 100755 => 100644 components/lwip/netif/etharp.c mode change 100755 => 100644 components/lwip/netif/ethernet.c mode change 100755 => 100644 components/lwip/netif/ethernetif.c mode change 100755 => 100644 components/lwip/netif/lowpan6.c mode change 100755 => 100644 components/lwip/netif/ppp/PPPD_FOLLOWUP mode change 100755 => 100644 components/lwip/netif/ppp/auth.c mode change 100755 => 100644 components/lwip/netif/ppp/ccp.c mode change 100755 => 100644 components/lwip/netif/ppp/chap-md5.c mode change 100755 => 100644 components/lwip/netif/ppp/chap-new.c mode change 100755 => 100644 components/lwip/netif/ppp/chap_ms.c mode change 100755 => 100644 components/lwip/netif/ppp/demand.c mode change 100755 => 100644 components/lwip/netif/ppp/eap.c mode change 100755 => 100644 components/lwip/netif/ppp/ecp.c mode change 100755 => 100644 components/lwip/netif/ppp/eui64.c mode change 100755 => 100644 components/lwip/netif/ppp/fsm.c mode change 100755 => 100644 components/lwip/netif/ppp/ipcp.c mode change 100755 => 100644 components/lwip/netif/ppp/ipv6cp.c mode change 100755 => 100644 components/lwip/netif/ppp/lcp.c mode change 100755 => 100644 components/lwip/netif/ppp/magic.c mode change 100755 => 100644 components/lwip/netif/ppp/mppe.c mode change 100755 => 100644 components/lwip/netif/ppp/multilink.c mode change 100755 => 100644 components/lwip/netif/ppp/polarssl/README mode change 100755 => 100644 components/lwip/netif/ppp/polarssl/arc4.c mode change 100755 => 100644 components/lwip/netif/ppp/polarssl/des.c mode change 100755 => 100644 components/lwip/netif/ppp/polarssl/md4.c mode change 100755 => 100644 components/lwip/netif/ppp/polarssl/md5.c mode change 100755 => 100644 components/lwip/netif/ppp/polarssl/sha1.c mode change 100755 => 100644 components/lwip/netif/ppp/ppp.c mode change 100755 => 100644 components/lwip/netif/ppp/pppcrypt.c mode change 100755 => 100644 components/lwip/netif/ppp/pppoe.c mode change 100755 => 100644 components/lwip/netif/ppp/pppol2tp.c mode change 100755 => 100644 components/lwip/netif/ppp/pppos.c mode change 100755 => 100644 components/lwip/netif/ppp/upap.c mode change 100755 => 100644 components/lwip/netif/ppp/utils.c mode change 100755 => 100644 components/lwip/netif/ppp/vj.c mode change 100755 => 100644 components/lwip/netif/slipif.c mode change 100755 => 100644 components/lwip/port/freertos/sys_arch.c mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-14.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-15.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-16.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-28.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-29.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-31.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-53.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-56.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-63.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-83.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-88.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-89.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-95.bin mode change 100755 => 100644 components/mdns/test_afl_fuzz_host/in/test-96.bin mode change 100755 => 100644 components/nvs_flash/component.mk mode change 100755 => 100644 components/openssl/include/openssl/ssl.h mode change 100755 => 100644 components/openssl/platform/ssl_pm.c mode change 100755 => 100644 components/sdmmc/component.mk mode change 100755 => 100644 components/smartconfig_ack/smartconfig_ack.c mode change 100755 => 100644 components/spi_flash/component.mk mode change 100755 => 100644 components/spiffs/include/spiffs_config.h mode change 100755 => 100644 components/tcpip_adapter/component.mk mode change 100755 => 100644 components/ulp/component.mk mode change 100755 => 100644 components/vfs/component.mk mode change 100755 => 100644 components/wear_levelling/Kconfig mode change 100755 => 100644 components/wear_levelling/WL_Ext_Perf.cpp mode change 100755 => 100644 components/wear_levelling/WL_Ext_Safe.cpp mode change 100755 => 100644 components/wear_levelling/private_include/WL_Ext_Cfg.h mode change 100755 => 100644 components/wear_levelling/private_include/WL_Ext_Perf.h mode change 100755 => 100644 components/wear_levelling/private_include/WL_Ext_Safe.h mode change 100755 => 100644 components/xtensa-debug-module/component.mk mode change 100755 => 100644 docs/en/api-guides/ulp_instruction_set.rst mode change 100755 => 100644 docs/en/api-guides/wifi.rst mode change 100755 => 100644 docs/zh_CN/api-guides/ulp_instruction_set.rst mode change 100755 => 100644 examples/bluetooth/a2dp_gatts_coex/README.md mode change 100755 => 100644 examples/bluetooth/a2dp_gatts_coex/main/component.mk mode change 100755 => 100644 examples/bluetooth/a2dp_sink/Makefile mode change 100755 => 100644 examples/bluetooth/a2dp_sink/README.md mode change 100755 => 100644 examples/bluetooth/a2dp_sink/main/component.mk mode change 100755 => 100644 examples/bluetooth/a2dp_source/Makefile mode change 100755 => 100644 examples/bluetooth/a2dp_source/README.md mode change 100755 => 100644 examples/bluetooth/a2dp_source/main/component.mk mode change 100755 => 100644 examples/bluetooth/bt_discovery/Makefile mode change 100755 => 100644 examples/bluetooth/bt_discovery/README.rst mode change 100755 => 100644 examples/bluetooth/bt_discovery/main/component.mk mode change 100755 => 100644 examples/peripherals/i2s_adc_dac/Makefile mode change 100755 => 100644 examples/peripherals/i2s_adc_dac/README.md mode change 100755 => 100644 examples/peripherals/i2s_adc_dac/main/component.mk mode change 100755 => 100644 examples/protocols/mdns/main/mdns_example_main.c mode change 100755 => 100644 examples/protocols/openssl_server/main/Kconfig.projbuild mode change 100755 => 100644 examples/protocols/openssl_server/main/openssl_server_example.h mode change 100755 => 100644 examples/protocols/openssl_server/main/openssl_server_example_main.c mode change 100755 => 100644 examples/wifi/iperf/Makefile mode change 100755 => 100644 examples/wifi/iperf/components/component.mk mode change 100755 => 100644 examples/wifi/power_save/README.md mode change 100755 => 100644 examples/wifi/power_save/main/Kconfig.projbuild diff --git a/components/app_update/component.mk b/components/app_update/component.mk old mode 100755 new mode 100644 diff --git a/components/app_update/include/esp_ota_ops.h b/components/app_update/include/esp_ota_ops.h old mode 100755 new mode 100644 diff --git a/components/bootloader_support/component.mk b/components/bootloader_support/component.mk old mode 100755 new mode 100644 diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig old mode 100755 new mode 100644 diff --git a/components/esp32/include/esp_types.h b/components/esp32/include/esp_types.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/esp_wifi_internal.h b/components/esp32/include/esp_wifi_internal.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/esp_wifi_types.h b/components/esp32/include/esp_wifi_types.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/rom/md5_hash.h b/components/esp32/include/rom/md5_hash.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/rom/queue.h b/components/esp32/include/rom/queue.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/board.h b/components/esp32/include/xtensa/board.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/c6x-compat.h b/components/esp32/include/xtensa/c6x-compat.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/cacheasm.h b/components/esp32/include/xtensa/cacheasm.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/cacheattrasm.h b/components/esp32/include/xtensa/cacheattrasm.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/core-macros.h b/components/esp32/include/xtensa/core-macros.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/coreasm.h b/components/esp32/include/xtensa/coreasm.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/corebits.h b/components/esp32/include/xtensa/corebits.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/debugfs.h b/components/esp32/include/xtensa/debugfs.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/feedback.h b/components/esp32/include/xtensa/feedback.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/gdbio.h b/components/esp32/include/xtensa/gdbio.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/hal.h b/components/esp32/include/xtensa/hal.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/jtag-xtensa.h b/components/esp32/include/xtensa/jtag-xtensa.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/lcd-splc780d-4bitmode-board.h b/components/esp32/include/xtensa/lcd-splc780d-4bitmode-board.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/lcd-splc780d-4bitmode.h b/components/esp32/include/xtensa/lcd-splc780d-4bitmode.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/lcd-splc780d.h b/components/esp32/include/xtensa/lcd-splc780d.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/overlay.h b/components/esp32/include/xtensa/overlay.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/overlay_os_asm.h b/components/esp32/include/xtensa/overlay_os_asm.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/sim.h b/components/esp32/include/xtensa/sim.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/simboard.h b/components/esp32/include/xtensa/simboard.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/simcall-errno.h b/components/esp32/include/xtensa/simcall-errno.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/simcall-fcntl.h b/components/esp32/include/xtensa/simcall-fcntl.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/simcall.h b/components/esp32/include/xtensa/simcall.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/specreg.h b/components/esp32/include/xtensa/specreg.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/trax-api.h b/components/esp32/include/xtensa/trax-api.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/trax-core-config.h b/components/esp32/include/xtensa/trax-core-config.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/trax-proto.h b/components/esp32/include/xtensa/trax-proto.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/trax-util.h b/components/esp32/include/xtensa/trax-util.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/trax.h b/components/esp32/include/xtensa/trax.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/traxfile.h b/components/esp32/include/xtensa/traxfile.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/traxreg.h b/components/esp32/include/xtensa/traxreg.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/uart-16550-board.h b/components/esp32/include/xtensa/uart-16550-board.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/uart-16550.h b/components/esp32/include/xtensa/uart-16550.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/udma.h b/components/esp32/include/xtensa/udma.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xdm-regs.h b/components/esp32/include/xtensa/xdm-regs.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xmon.h b/components/esp32/include/xtensa/xmon.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xmp-library.h b/components/esp32/include/xtensa/xmp-library.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xos.h b/components/esp32/include/xtensa/xos.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xos_common.h b/components/esp32/include/xtensa/xos_common.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xos_cond.h b/components/esp32/include/xtensa/xos_cond.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xos_errors.h b/components/esp32/include/xtensa/xos_errors.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xos_event.h b/components/esp32/include/xtensa/xos_event.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xos_internal.h b/components/esp32/include/xtensa/xos_internal.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xos_msgq.h b/components/esp32/include/xtensa/xos_msgq.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xos_mutex.h b/components/esp32/include/xtensa/xos_mutex.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xos_params.h b/components/esp32/include/xtensa/xos_params.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xos_regaccess.h b/components/esp32/include/xtensa/xos_regaccess.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xos_semaphore.h b/components/esp32/include/xtensa/xos_semaphore.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xos_stopwatch.h b/components/esp32/include/xtensa/xos_stopwatch.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xos_syslog.h b/components/esp32/include/xtensa/xos_syslog.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xos_thread.h b/components/esp32/include/xtensa/xos_thread.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xos_timer.h b/components/esp32/include/xtensa/xos_timer.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xos_types.h b/components/esp32/include/xtensa/xos_types.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xt_perf_consts.h b/components/esp32/include/xtensa/xt_perf_consts.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xt_perfmon.h b/components/esp32/include/xtensa/xt_perfmon.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xt_profiling.h b/components/esp32/include/xtensa/xt_profiling.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xt_reftb.h b/components/esp32/include/xtensa/xt_reftb.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtav110.h b/components/esp32/include/xtensa/xtav110.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtav110/xtensa/board.h b/components/esp32/include/xtensa/xtav110/xtensa/board.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtav200.h b/components/esp32/include/xtensa/xtav200.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtav200/xtensa/board.h b/components/esp32/include/xtensa/xtav200/xtensa/board.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtav60.h b/components/esp32/include/xtensa/xtav60.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtav60/xtensa/board.h b/components/esp32/include/xtensa/xtav60/xtensa/board.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtav60/xtensa/lcd-splc780d-board.h b/components/esp32/include/xtensa/xtav60/xtensa/lcd-splc780d-board.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtbsp.h b/components/esp32/include/xtensa/xtbsp.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtensa-libdb-macros.h b/components/esp32/include/xtensa/xtensa-libdb-macros.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtensa-versions.h b/components/esp32/include/xtensa/xtensa-versions.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtensa-xer.h b/components/esp32/include/xtensa/xtensa-xer.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtkc705.h b/components/esp32/include/xtensa/xtkc705.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtkc705/xtensa/board.h b/components/esp32/include/xtensa/xtkc705/xtensa/board.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtload-api.h b/components/esp32/include/xtensa/xtload-api.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtml605.h b/components/esp32/include/xtensa/xtml605.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtml605/xtensa/board.h b/components/esp32/include/xtensa/xtml605/xtensa/board.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtruntime-core-state.h b/components/esp32/include/xtensa/xtruntime-core-state.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtruntime-frames.h b/components/esp32/include/xtensa/xtruntime-frames.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtruntime.h b/components/esp32/include/xtensa/xtruntime.h old mode 100755 new mode 100644 diff --git a/components/esp32/include/xtensa/xtutil.h b/components/esp32/include/xtensa/xtutil.h old mode 100755 new mode 100644 diff --git a/components/ethernet/component.mk b/components/ethernet/component.mk old mode 100755 new mode 100644 diff --git a/components/idf_test/component.mk b/components/idf_test/component.mk old mode 100755 new mode 100644 diff --git a/components/log/component.mk b/components/log/component.mk old mode 100755 new mode 100644 diff --git a/components/lwip/CHANGELOG b/components/lwip/CHANGELOG old mode 100755 new mode 100644 diff --git a/components/lwip/COPYING b/components/lwip/COPYING old mode 100755 new mode 100644 diff --git a/components/lwip/Kconfig b/components/lwip/Kconfig old mode 100755 new mode 100644 diff --git a/components/lwip/README b/components/lwip/README old mode 100755 new mode 100644 diff --git a/components/lwip/api/api_lib.c b/components/lwip/api/api_lib.c old mode 100755 new mode 100644 diff --git a/components/lwip/api/api_msg.c b/components/lwip/api/api_msg.c old mode 100755 new mode 100644 diff --git a/components/lwip/api/err.c b/components/lwip/api/err.c old mode 100755 new mode 100644 diff --git a/components/lwip/api/netbuf.c b/components/lwip/api/netbuf.c old mode 100755 new mode 100644 diff --git a/components/lwip/api/netdb.c b/components/lwip/api/netdb.c old mode 100755 new mode 100644 diff --git a/components/lwip/api/netifapi.c b/components/lwip/api/netifapi.c old mode 100755 new mode 100644 diff --git a/components/lwip/api/pppapi.c b/components/lwip/api/pppapi.c old mode 100755 new mode 100644 diff --git a/components/lwip/api/sockets.c b/components/lwip/api/sockets.c old mode 100755 new mode 100644 diff --git a/components/lwip/api/tcpip.c b/components/lwip/api/tcpip.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/def.c b/components/lwip/core/def.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/dns.c b/components/lwip/core/dns.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/inet_chksum.c b/components/lwip/core/inet_chksum.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/init.c b/components/lwip/core/init.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/ip.c b/components/lwip/core/ip.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/ipv4/autoip.c b/components/lwip/core/ipv4/autoip.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/ipv4/dhcp.c b/components/lwip/core/ipv4/dhcp.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/ipv4/icmp.c b/components/lwip/core/ipv4/icmp.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/ipv4/igmp.c b/components/lwip/core/ipv4/igmp.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/ipv4/ip4.c b/components/lwip/core/ipv4/ip4.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/ipv4/ip4_addr.c b/components/lwip/core/ipv4/ip4_addr.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/ipv4/ip_frag.c b/components/lwip/core/ipv4/ip_frag.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/ipv6/README b/components/lwip/core/ipv6/README old mode 100755 new mode 100644 diff --git a/components/lwip/core/ipv6/dhcp6.c b/components/lwip/core/ipv6/dhcp6.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/ipv6/ethip6.c b/components/lwip/core/ipv6/ethip6.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/ipv6/icmp6.c b/components/lwip/core/ipv6/icmp6.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/ipv6/inet6.c b/components/lwip/core/ipv6/inet6.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/ipv6/ip6.c b/components/lwip/core/ipv6/ip6.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/ipv6/ip6_addr.c b/components/lwip/core/ipv6/ip6_addr.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/ipv6/ip6_frag.c b/components/lwip/core/ipv6/ip6_frag.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/ipv6/mld6.c b/components/lwip/core/ipv6/mld6.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/ipv6/nd6.c b/components/lwip/core/ipv6/nd6.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/mem.c b/components/lwip/core/mem.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/memp.c b/components/lwip/core/memp.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/netif.c b/components/lwip/core/netif.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/pbuf.c b/components/lwip/core/pbuf.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/raw.c b/components/lwip/core/raw.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/stats.c b/components/lwip/core/stats.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/sys.c b/components/lwip/core/sys.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/tcp.c b/components/lwip/core/tcp.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/tcp_in.c b/components/lwip/core/tcp_in.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/tcp_out.c b/components/lwip/core/tcp_out.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/timers.c b/components/lwip/core/timers.c old mode 100755 new mode 100644 diff --git a/components/lwip/core/udp.c b/components/lwip/core/udp.c old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/api.h b/components/lwip/include/lwip/lwip/api.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/arch.h b/components/lwip/include/lwip/lwip/arch.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/autoip.h b/components/lwip/include/lwip/lwip/autoip.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/debug.h b/components/lwip/include/lwip/lwip/debug.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/def.h b/components/lwip/include/lwip/lwip/def.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/dhcp.h b/components/lwip/include/lwip/lwip/dhcp.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/dhcp6.h b/components/lwip/include/lwip/lwip/dhcp6.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/dns.h b/components/lwip/include/lwip/lwip/dns.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/err.h b/components/lwip/include/lwip/lwip/err.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/ethip6.h b/components/lwip/include/lwip/lwip/ethip6.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/icmp.h b/components/lwip/include/lwip/lwip/icmp.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/icmp6.h b/components/lwip/include/lwip/lwip/icmp6.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/igmp.h b/components/lwip/include/lwip/lwip/igmp.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/inet.h b/components/lwip/include/lwip/lwip/inet.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/inet_chksum.h b/components/lwip/include/lwip/lwip/inet_chksum.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/init.h b/components/lwip/include/lwip/lwip/init.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/ip.h b/components/lwip/include/lwip/lwip/ip.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/ip4.h b/components/lwip/include/lwip/lwip/ip4.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/ip4_addr.h b/components/lwip/include/lwip/lwip/ip4_addr.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/ip6.h b/components/lwip/include/lwip/lwip/ip6.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/ip6_addr.h b/components/lwip/include/lwip/lwip/ip6_addr.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/ip6_frag.h b/components/lwip/include/lwip/lwip/ip6_frag.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/ip_addr.h b/components/lwip/include/lwip/lwip/ip_addr.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/ip_frag.h b/components/lwip/include/lwip/lwip/ip_frag.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/mem.h b/components/lwip/include/lwip/lwip/mem.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/memp.h b/components/lwip/include/lwip/lwip/memp.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/mld6.h b/components/lwip/include/lwip/lwip/mld6.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/nd6.h b/components/lwip/include/lwip/lwip/nd6.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/netbuf.h b/components/lwip/include/lwip/lwip/netbuf.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/netdb.h b/components/lwip/include/lwip/lwip/netdb.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/netif.h b/components/lwip/include/lwip/lwip/netif.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/netifapi.h b/components/lwip/include/lwip/lwip/netifapi.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/opt.h b/components/lwip/include/lwip/lwip/opt.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/pbuf.h b/components/lwip/include/lwip/lwip/pbuf.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/pppapi.h b/components/lwip/include/lwip/lwip/pppapi.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/priv/api_msg.h b/components/lwip/include/lwip/lwip/priv/api_msg.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/priv/memp_priv.h b/components/lwip/include/lwip/lwip/priv/memp_priv.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/priv/memp_std.h b/components/lwip/include/lwip/lwip/priv/memp_std.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/priv/tcp_priv.h b/components/lwip/include/lwip/lwip/priv/tcp_priv.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/priv/tcpip_priv.h b/components/lwip/include/lwip/lwip/priv/tcpip_priv.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/raw.h b/components/lwip/include/lwip/lwip/raw.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/sio.h b/components/lwip/include/lwip/lwip/sio.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/snmp.h b/components/lwip/include/lwip/lwip/snmp.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/sockets.h b/components/lwip/include/lwip/lwip/sockets.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/stats.h b/components/lwip/include/lwip/lwip/stats.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/sys.h b/components/lwip/include/lwip/lwip/sys.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/tcp.h b/components/lwip/include/lwip/lwip/tcp.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/tcpip.h b/components/lwip/include/lwip/lwip/tcpip.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/timers.h b/components/lwip/include/lwip/lwip/timers.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/lwip/udp.h b/components/lwip/include/lwip/lwip/udp.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/etharp.h b/components/lwip/include/lwip/netif/etharp.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ethernet.h b/components/lwip/include/lwip/netif/ethernet.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/lowpan6.h b/components/lwip/include/lwip/netif/lowpan6.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/lowpan6_opts.h b/components/lwip/include/lwip/netif/lowpan6_opts.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/ccp.h b/components/lwip/include/lwip/netif/ppp/ccp.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/chap-md5.h b/components/lwip/include/lwip/netif/ppp/chap-md5.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/chap-new.h b/components/lwip/include/lwip/netif/ppp/chap-new.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/chap_ms.h b/components/lwip/include/lwip/netif/ppp/chap_ms.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/eap.h b/components/lwip/include/lwip/netif/ppp/eap.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/ecp.h b/components/lwip/include/lwip/netif/ppp/ecp.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/eui64.h b/components/lwip/include/lwip/netif/ppp/eui64.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/fsm.h b/components/lwip/include/lwip/netif/ppp/fsm.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/ipcp.h b/components/lwip/include/lwip/netif/ppp/ipcp.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/ipv6cp.h b/components/lwip/include/lwip/netif/ppp/ipv6cp.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/lcp.h b/components/lwip/include/lwip/netif/ppp/lcp.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/magic.h b/components/lwip/include/lwip/netif/ppp/magic.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/mppe.h b/components/lwip/include/lwip/netif/ppp/mppe.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/polarssl/arc4.h b/components/lwip/include/lwip/netif/ppp/polarssl/arc4.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/polarssl/des.h b/components/lwip/include/lwip/netif/ppp/polarssl/des.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/polarssl/md4.h b/components/lwip/include/lwip/netif/ppp/polarssl/md4.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/polarssl/md5.h b/components/lwip/include/lwip/netif/ppp/polarssl/md5.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/polarssl/sha1.h b/components/lwip/include/lwip/netif/ppp/polarssl/sha1.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/ppp.h b/components/lwip/include/lwip/netif/ppp/ppp.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/ppp_impl.h b/components/lwip/include/lwip/netif/ppp/ppp_impl.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/pppcrypt.h b/components/lwip/include/lwip/netif/ppp/pppcrypt.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/pppdebug.h b/components/lwip/include/lwip/netif/ppp/pppdebug.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/pppoe.h b/components/lwip/include/lwip/netif/ppp/pppoe.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/pppol2tp.h b/components/lwip/include/lwip/netif/ppp/pppol2tp.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/pppos.h b/components/lwip/include/lwip/netif/ppp/pppos.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/upap.h b/components/lwip/include/lwip/netif/ppp/upap.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/ppp/vj.h b/components/lwip/include/lwip/netif/ppp/vj.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/netif/slipif.h b/components/lwip/include/lwip/netif/slipif.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/port/netif/ethernetif.h b/components/lwip/include/lwip/port/netif/ethernetif.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/port/netif/wlanif.h b/components/lwip/include/lwip/port/netif/wlanif.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/posix/netdb.h b/components/lwip/include/lwip/posix/netdb.h old mode 100755 new mode 100644 diff --git a/components/lwip/include/lwip/posix/sys/socket.h b/components/lwip/include/lwip/posix/sys/socket.h old mode 100755 new mode 100644 diff --git a/components/lwip/netif/FILES b/components/lwip/netif/FILES old mode 100755 new mode 100644 diff --git a/components/lwip/netif/etharp.c b/components/lwip/netif/etharp.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ethernet.c b/components/lwip/netif/ethernet.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ethernetif.c b/components/lwip/netif/ethernetif.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/lowpan6.c b/components/lwip/netif/lowpan6.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/PPPD_FOLLOWUP b/components/lwip/netif/ppp/PPPD_FOLLOWUP old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/auth.c b/components/lwip/netif/ppp/auth.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/ccp.c b/components/lwip/netif/ppp/ccp.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/chap-md5.c b/components/lwip/netif/ppp/chap-md5.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/chap-new.c b/components/lwip/netif/ppp/chap-new.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/chap_ms.c b/components/lwip/netif/ppp/chap_ms.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/demand.c b/components/lwip/netif/ppp/demand.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/eap.c b/components/lwip/netif/ppp/eap.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/ecp.c b/components/lwip/netif/ppp/ecp.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/eui64.c b/components/lwip/netif/ppp/eui64.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/fsm.c b/components/lwip/netif/ppp/fsm.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/ipcp.c b/components/lwip/netif/ppp/ipcp.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/ipv6cp.c b/components/lwip/netif/ppp/ipv6cp.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/lcp.c b/components/lwip/netif/ppp/lcp.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/magic.c b/components/lwip/netif/ppp/magic.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/mppe.c b/components/lwip/netif/ppp/mppe.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/multilink.c b/components/lwip/netif/ppp/multilink.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/polarssl/README b/components/lwip/netif/ppp/polarssl/README old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/polarssl/arc4.c b/components/lwip/netif/ppp/polarssl/arc4.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/polarssl/des.c b/components/lwip/netif/ppp/polarssl/des.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/polarssl/md4.c b/components/lwip/netif/ppp/polarssl/md4.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/polarssl/md5.c b/components/lwip/netif/ppp/polarssl/md5.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/polarssl/sha1.c b/components/lwip/netif/ppp/polarssl/sha1.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/ppp.c b/components/lwip/netif/ppp/ppp.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/pppcrypt.c b/components/lwip/netif/ppp/pppcrypt.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/pppoe.c b/components/lwip/netif/ppp/pppoe.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/pppol2tp.c b/components/lwip/netif/ppp/pppol2tp.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/pppos.c b/components/lwip/netif/ppp/pppos.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/upap.c b/components/lwip/netif/ppp/upap.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/utils.c b/components/lwip/netif/ppp/utils.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/ppp/vj.c b/components/lwip/netif/ppp/vj.c old mode 100755 new mode 100644 diff --git a/components/lwip/netif/slipif.c b/components/lwip/netif/slipif.c old mode 100755 new mode 100644 diff --git a/components/lwip/port/freertos/sys_arch.c b/components/lwip/port/freertos/sys_arch.c old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-14.bin b/components/mdns/test_afl_fuzz_host/in/test-14.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-15.bin b/components/mdns/test_afl_fuzz_host/in/test-15.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-16.bin b/components/mdns/test_afl_fuzz_host/in/test-16.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-28.bin b/components/mdns/test_afl_fuzz_host/in/test-28.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-29.bin b/components/mdns/test_afl_fuzz_host/in/test-29.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-31.bin b/components/mdns/test_afl_fuzz_host/in/test-31.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-53.bin b/components/mdns/test_afl_fuzz_host/in/test-53.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-56.bin b/components/mdns/test_afl_fuzz_host/in/test-56.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-63.bin b/components/mdns/test_afl_fuzz_host/in/test-63.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-83.bin b/components/mdns/test_afl_fuzz_host/in/test-83.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-88.bin b/components/mdns/test_afl_fuzz_host/in/test-88.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-89.bin b/components/mdns/test_afl_fuzz_host/in/test-89.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-95.bin b/components/mdns/test_afl_fuzz_host/in/test-95.bin old mode 100755 new mode 100644 diff --git a/components/mdns/test_afl_fuzz_host/in/test-96.bin b/components/mdns/test_afl_fuzz_host/in/test-96.bin old mode 100755 new mode 100644 diff --git a/components/nvs_flash/component.mk b/components/nvs_flash/component.mk old mode 100755 new mode 100644 diff --git a/components/openssl/include/openssl/ssl.h b/components/openssl/include/openssl/ssl.h old mode 100755 new mode 100644 diff --git a/components/openssl/platform/ssl_pm.c b/components/openssl/platform/ssl_pm.c old mode 100755 new mode 100644 diff --git a/components/sdmmc/component.mk b/components/sdmmc/component.mk old mode 100755 new mode 100644 diff --git a/components/smartconfig_ack/smartconfig_ack.c b/components/smartconfig_ack/smartconfig_ack.c old mode 100755 new mode 100644 diff --git a/components/spi_flash/component.mk b/components/spi_flash/component.mk old mode 100755 new mode 100644 diff --git a/components/spiffs/include/spiffs_config.h b/components/spiffs/include/spiffs_config.h old mode 100755 new mode 100644 diff --git a/components/tcpip_adapter/component.mk b/components/tcpip_adapter/component.mk old mode 100755 new mode 100644 diff --git a/components/ulp/component.mk b/components/ulp/component.mk old mode 100755 new mode 100644 diff --git a/components/vfs/component.mk b/components/vfs/component.mk old mode 100755 new mode 100644 diff --git a/components/wear_levelling/Kconfig b/components/wear_levelling/Kconfig old mode 100755 new mode 100644 diff --git a/components/wear_levelling/WL_Ext_Perf.cpp b/components/wear_levelling/WL_Ext_Perf.cpp old mode 100755 new mode 100644 diff --git a/components/wear_levelling/WL_Ext_Safe.cpp b/components/wear_levelling/WL_Ext_Safe.cpp old mode 100755 new mode 100644 diff --git a/components/wear_levelling/private_include/WL_Ext_Cfg.h b/components/wear_levelling/private_include/WL_Ext_Cfg.h old mode 100755 new mode 100644 diff --git a/components/wear_levelling/private_include/WL_Ext_Perf.h b/components/wear_levelling/private_include/WL_Ext_Perf.h old mode 100755 new mode 100644 diff --git a/components/wear_levelling/private_include/WL_Ext_Safe.h b/components/wear_levelling/private_include/WL_Ext_Safe.h old mode 100755 new mode 100644 diff --git a/components/xtensa-debug-module/component.mk b/components/xtensa-debug-module/component.mk old mode 100755 new mode 100644 diff --git a/docs/en/api-guides/ulp_instruction_set.rst b/docs/en/api-guides/ulp_instruction_set.rst old mode 100755 new mode 100644 diff --git a/docs/en/api-guides/wifi.rst b/docs/en/api-guides/wifi.rst old mode 100755 new mode 100644 diff --git a/docs/zh_CN/api-guides/ulp_instruction_set.rst b/docs/zh_CN/api-guides/ulp_instruction_set.rst old mode 100755 new mode 100644 diff --git a/examples/bluetooth/a2dp_gatts_coex/README.md b/examples/bluetooth/a2dp_gatts_coex/README.md old mode 100755 new mode 100644 diff --git a/examples/bluetooth/a2dp_gatts_coex/main/component.mk b/examples/bluetooth/a2dp_gatts_coex/main/component.mk old mode 100755 new mode 100644 diff --git a/examples/bluetooth/a2dp_sink/Makefile b/examples/bluetooth/a2dp_sink/Makefile old mode 100755 new mode 100644 diff --git a/examples/bluetooth/a2dp_sink/README.md b/examples/bluetooth/a2dp_sink/README.md old mode 100755 new mode 100644 diff --git a/examples/bluetooth/a2dp_sink/main/component.mk b/examples/bluetooth/a2dp_sink/main/component.mk old mode 100755 new mode 100644 diff --git a/examples/bluetooth/a2dp_source/Makefile b/examples/bluetooth/a2dp_source/Makefile old mode 100755 new mode 100644 diff --git a/examples/bluetooth/a2dp_source/README.md b/examples/bluetooth/a2dp_source/README.md old mode 100755 new mode 100644 diff --git a/examples/bluetooth/a2dp_source/main/component.mk b/examples/bluetooth/a2dp_source/main/component.mk old mode 100755 new mode 100644 diff --git a/examples/bluetooth/bt_discovery/Makefile b/examples/bluetooth/bt_discovery/Makefile old mode 100755 new mode 100644 diff --git a/examples/bluetooth/bt_discovery/README.rst b/examples/bluetooth/bt_discovery/README.rst old mode 100755 new mode 100644 diff --git a/examples/bluetooth/bt_discovery/main/component.mk b/examples/bluetooth/bt_discovery/main/component.mk old mode 100755 new mode 100644 diff --git a/examples/peripherals/i2s_adc_dac/Makefile b/examples/peripherals/i2s_adc_dac/Makefile old mode 100755 new mode 100644 diff --git a/examples/peripherals/i2s_adc_dac/README.md b/examples/peripherals/i2s_adc_dac/README.md old mode 100755 new mode 100644 diff --git a/examples/peripherals/i2s_adc_dac/main/component.mk b/examples/peripherals/i2s_adc_dac/main/component.mk old mode 100755 new mode 100644 diff --git a/examples/protocols/mdns/main/mdns_example_main.c b/examples/protocols/mdns/main/mdns_example_main.c old mode 100755 new mode 100644 diff --git a/examples/protocols/openssl_server/main/Kconfig.projbuild b/examples/protocols/openssl_server/main/Kconfig.projbuild old mode 100755 new mode 100644 diff --git a/examples/protocols/openssl_server/main/openssl_server_example.h b/examples/protocols/openssl_server/main/openssl_server_example.h old mode 100755 new mode 100644 diff --git a/examples/protocols/openssl_server/main/openssl_server_example_main.c b/examples/protocols/openssl_server/main/openssl_server_example_main.c old mode 100755 new mode 100644 diff --git a/examples/wifi/iperf/Makefile b/examples/wifi/iperf/Makefile old mode 100755 new mode 100644 diff --git a/examples/wifi/iperf/components/component.mk b/examples/wifi/iperf/components/component.mk old mode 100755 new mode 100644 diff --git a/examples/wifi/power_save/README.md b/examples/wifi/power_save/README.md old mode 100755 new mode 100644 diff --git a/examples/wifi/power_save/main/Kconfig.projbuild b/examples/wifi/power_save/main/Kconfig.projbuild old mode 100755 new mode 100644

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