diff --git a/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/DebugConfig/TencentOS_tiny_STM32L431RCTx.dbgconf b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/DebugConfig/TencentOS_tiny_STM32L431RCTx.dbgconf
new file mode 100644
index 00000000..c9811753
--- /dev/null
+++ b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/DebugConfig/TencentOS_tiny_STM32L431RCTx.dbgconf
@@ -0,0 +1,97 @@
+// File: STM32L43x_44x_45x_46x.dbgconf
+// Version: 1.0.0
+// Note: refer to STM32L43xxx STM32L44xxx STM32L45xxx STM32L46xxx Reference manual (RM0394)
+// refer to STM32L431xx, STM32L432xx, STM32L433xx, STM32L442xx, STM32L443xx, STM32L451xx, STM32L452xx, STM32L462xx datasheets
+
+// <<< Use Configuration Wizard in Context Menu >>>
+
+// Debug MCU configuration register (DBGMCU_CR)
+// DBG_STANDBY
+// Debug Standby mode
+// 0: (FCLK=Off, HCLK=Off) The whole digital part is unpowered.
+// 1: (FCLK=On, HCLK=On) The digital part is not unpowered and FCLK and HCLK are provided by the internal RC oscillator which remains active
+// DBG_STOP
+// Debug Stop mode
+// 0: (FCLK=Off, HCLK=Off) In STOP mode, the clock controller disables all clocks (including HCLK and FCLK).
+// 1: (FCLK=On, HCLK=On) When entering STOP mode, FCLK and HCLK are provided by the internal RC oscillator which remains active in STOP mode.
+// DBG_SLEEP
+// Debug Sleep mode
+// 0: (FCLK=On, HCLK=Off) In Sleep mode, FCLK is clocked by the system clock as previously configured by the software while HCLK is disabled.
+// 1: (FCLK=On, HCLK=On) When entering Sleep mode, HCLK is fed by the same clock that is provided to FCLK (system clock as previously configured by the software).
+//
+DbgMCU_CR = 0x00000007;
+
+// Debug MCU APB1 freeze register1 (DBGMCU_APB1FZR1)
+// DBG_LPTIM1_STOP
+// LPTIM1 counter stopped when core is halted
+// 0: The counter clock of LPTIM1 is fed even if the core is halted
+// 1: The counter clock of LPTIM1 is stopped when the core is halted
+// DBG_CAN_STOP
+// bxCAN1 stopped when core is halted
+// 0: Same behavior as in normal mode
+// 1: The bxCAN1 receive registers are frozen
+// DBG_I2C3_STOP
+// I2C3 SMBUS timeout counter stopped when core is halted
+// 0: Same behavior as in normal mode
+// 1: The I2C3 SMBus timeout is frozen
+// DBG_I2C2_STOP
+// I2C2 SMBUS timeout counter stopped when core is halted
+// 0: Same behavior as in normal mode
+// 1: The I2C2 SMBus timeout is frozen
+// DBG_I2C1_STOP
+// I2C1 SMBUS timeout counter stopped when core is halted
+// 0: Same behavior as in normal mode
+// 1: The I2C1 SMBus timeout is frozen
+// DBG_IWDG_STOP
+// Independent watchdog counter stopped when core is halted
+// 0: The independent watchdog counter clock continues even if the core is halted
+// 1: The independent watchdog counter clock is stopped when the core is halted
+// DBG_WWDG_STOP
+// Window watchdog counter stopped when core is halted
+// 0: The window watchdog counter clock continues even if the core is halted
+// 1: The window watchdog counter clock is stopped when the core is halted
+// DBG_RTC_STOP
+// RTC counter stopped when core is halted
+// 0: The clock of the RTC counter is fed even if the core is halted
+// 1: The clock of the RTC counter is stopped when the core is halted
+// DBG_TIM7_STOP
+// TIM7 counter stopped when core is halted
+// 0: The counter clock of TIM7 is fed even if the core is halted
+// 1: The counter clock of TIM7 is stopped when the core is halted
+// DBG_TIM6_STOP
+// TIM6 counter stopped when core is halted
+// 0: The counter clock of TIM6 is fed even if the core is halted
+// 1: The counter clock of TIM6 is stopped when the core is halted
+// DBG_TIM2_STOP
+// TIM2 counter stopped when core is halted
+// 0: The counter clock of TIM2 is fed even if the core is halted
+// 1: The counter clock of TIM2 is stopped when the core is halted
+//
+DbgMCU_APB1_Fz1 = 0x00000000;
+
+// Debug MCU APB1 freeze register 2 (DBGMCU_APB1FZR2)
+// DBG_LPTIM2_STOP
+// LPTIM2 counter stopped when core is halted
+// 0: The counter clock of LPTIM2 is fed even if the core is halted
+// 1: The counter clock of LPTIM2 is stopped when the core is halted
+//
+DbgMCU_APB1_Fz2 = 0x00000000;
+
+// Debug MCU APB2 freeze register (DBGMCU_APB2FZR)
+// DBG_TIM16_STOP
+// TIM16 counter stopped when core is halted
+// 0: The clock of the TIM16 counter is fed even if the core is halted
+// 1: The clock of the TIM16 counter is stopped when the core is halted
+// DBG_TIM15_STOP
+// TIM15 counter stopped when core is halted
+// 0: The clock of the TIM15 counter is fed even if the core is halted
+// 1: The clock of the TIM15 counter is stopped when the core is halted
+// DBG_TIM1_STOP
+// TIM1 counter stopped when core is halted
+// 0: The clock of the TIM1 counter is fed even if the core is halted
+// 1: The clock of the TIM1 counter is stopped when the core is halted
+//
+DbgMCU_APB2_Fz = 0x00000000;
+//
+
+// <<< end of configuration section >>>
\ No newline at end of file
diff --git a/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/RTE/_TencentOS_tiny/RTE_Components.h b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/RTE/_TencentOS_tiny/RTE_Components.h
new file mode 100644
index 00000000..45b7722b
--- /dev/null
+++ b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/RTE/_TencentOS_tiny/RTE_Components.h
@@ -0,0 +1,20 @@
+
+/*
+ * Auto generated Run-Time-Environment Component Configuration File
+ * *** Do not modify ! ***
+ *
+ * Project: 'TencentOS_tiny'
+ * Target: 'TencentOS_tiny'
+ */
+
+#ifndef RTE_COMPONENTS_H
+#define RTE_COMPONENTS_H
+
+
+/*
+ * Define the Device Header File:
+ */
+#define CMSIS_device_header "stm32l4xx.h"
+
+
+#endif /* RTE_COMPONENTS_H */
diff --git a/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/TencentOS_tiny.uvoptx b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/TencentOS_tiny.uvoptx
new file mode 100644
index 00000000..fc0de570
--- /dev/null
+++ b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/TencentOS_tiny.uvoptx
@@ -0,0 +1,2647 @@
+
+
+
+ 1.0
+
+ ### uVision Project, (C) Keil Software
+
+
+ *.c
+ *.s*; *.src; *.a*
+ *.obj; *.o
+ *.lib
+ *.txt; *.h; *.inc
+ *.plm
+ *.cpp
+ 0
+
+
+
+ 0
+ 0
+
+
+
+ TencentOS_tiny
+ 0x4
+ ARM-ADS
+
+ 80000000
+
+ 1
+ 1
+ 0
+ 1
+ 0
+
+
+ 1
+ 65535
+ 0
+ 0
+ 0
+
+
+ 79
+ 66
+ 8
+ .\list\
+
+
+ 1
+ 1
+ 1
+ 0
+ 1
+ 1
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+
+
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+
+
+ 1
+ 0
+ 1
+
+ 18
+
+ 0
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 0
+ 0
+ 6
+
+
+
+
+
+
+
+
+
+
+ STLink\ST-LINKIII-KEIL_SWO.dll
+
+
+
+ 0
+ ARMRTXEVENTFLAGS
+ -L70 -Z18 -C0 -M0 -T1
+
+
+ 0
+ DLGTARM
+ (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0)
+
+
+ 0
+ ARMDBGFLAGS
+
+
+
+ 0
+ DLGUARM
+ (105=-1,-1,-1,-1,0)
+
+
+ 0
+ UL2CM3
+ UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32L4xx_256 -FS08000000 -FL040000 -FP0($$Device:STM32L431RCTx$CMSIS\Flash\STM32L4xx_256.FLM))
+
+
+ 0
+ ST-LINKIII-KEIL_SWO
+ -U303030303030303030303031 -O10446 -SF4000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P1 -N00("ARM CoreSight SW-DP") -D00(2BA01477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO15 -FD20000000 -FC1000 -FN1 -FF0STM32L4xx_256.FLM -FS08000000 -FL040000 -FP0($$Device:STM32L431RCTx$CMSIS\Flash\STM32L4xx_256.FLM)
+
+
+
+
+ 0
+ 0
+ 54
+ 1
+ 134240894
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ D:\Code\tencentos_tiny\temp_develop\TencentOS-tiny\examples\mqtt\mqtt_demo.c
+
+ \\TencentOS_tiny\../../../../examples/mqtt/mqtt_demo.c\54
+
+
+ 1
+ 0
+ 107
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ D:\github\TencentOS-tiny\components\connectivity\Eclipse-Paho-MQTT\wrapper\src\mqtt_wrapper.c
+
+
+
+
+
+
+ 0
+ 1
+ huart3
+
+
+
+
+ 0
+ 2
+ con_param
+
+
+
+ 0
+
+
+ 0
+ 1
+ 1
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+ 1
+ 1
+ 0
+ 2
+ 10000000
+
+
+
+
+
+ Application/MDK-ARM
+ 0
+ 0
+ 0
+ 0
+
+ 1
+ 1
+ 2
+ 0
+ 0
+ 0
+ startup_stm32l431xx.s
+ startup_stm32l431xx.s
+ 0
+ 0
+
+
+
+
+ Application/User
+ 0
+ 0
+ 0
+ 0
+
+ 2
+ 2
+ 1
+ 0
+ 0
+ 0
+ ..\..\BSP\Src\gpio.c
+ gpio.c
+ 0
+ 0
+
+
+ 2
+ 3
+ 1
+ 0
+ 0
+ 0
+ ..\..\BSP\Src\main.c
+ main.c
+ 0
+ 0
+
+
+ 2
+ 4
+ 1
+ 0
+ 0
+ 0
+ ..\..\BSP\Src\mcu_init.c
+ mcu_init.c
+ 0
+ 0
+
+
+ 2
+ 5
+ 1
+ 0
+ 0
+ 0
+ ..\..\BSP\Src\stm32l4xx_hal_msp.c
+ stm32l4xx_hal_msp.c
+ 0
+ 0
+
+
+ 2
+ 6
+ 1
+ 0
+ 0
+ 0
+ ..\..\BSP\Src\usart.c
+ usart.c
+ 0
+ 0
+
+
+ 2
+ 7
+ 1
+ 0
+ 0
+ 0
+ ..\..\BSP\Src\adc.c
+ adc.c
+ 0
+ 0
+
+
+ 2
+ 8
+ 1
+ 0
+ 0
+ 0
+ ..\..\BSP\Src\dac.c
+ dac.c
+ 0
+ 0
+
+
+ 2
+ 9
+ 1
+ 0
+ 0
+ 0
+ ..\..\BSP\Src\i2c.c
+ i2c.c
+ 0
+ 0
+
+
+ 2
+ 10
+ 1
+ 0
+ 0
+ 0
+ ..\..\BSP\Src\spi.c
+ spi.c
+ 0
+ 0
+
+
+ 2
+ 11
+ 1
+ 0
+ 0
+ 0
+ ..\..\BSP\Src\stm32l4xx_it_module.c
+ stm32l4xx_it_module.c
+ 0
+ 0
+
+
+
+
+ examples
+ 0
+ 0
+ 0
+ 0
+
+ 3
+ 12
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\examples\aliyun_iotkit_csdk_mqtt\mqtt_example.c
+ mqtt_example.c
+ 0
+ 0
+
+
+ 3
+ 13
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\examples\aliyun_iotkit_csdk_mqtt\aliyun_iotkit_csdk_mqtt.c
+ aliyun_iotkit_csdk_mqtt.c
+ 0
+ 0
+
+
+
+
+ Drivers/STM32L4xx_HAL_Driver
+ 0
+ 0
+ 0
+ 0
+
+ 4
+ 14
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_tim.c
+ stm32l4xx_hal_tim.c
+ 0
+ 0
+
+
+ 4
+ 15
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_tim_ex.c
+ stm32l4xx_hal_tim_ex.c
+ 0
+ 0
+
+
+ 4
+ 16
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_uart.c
+ stm32l4xx_hal_uart.c
+ 0
+ 0
+
+
+ 4
+ 17
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_uart_ex.c
+ stm32l4xx_hal_uart_ex.c
+ 0
+ 0
+
+
+ 4
+ 18
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal.c
+ stm32l4xx_hal.c
+ 0
+ 0
+
+
+ 4
+ 19
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_i2c.c
+ stm32l4xx_hal_i2c.c
+ 0
+ 0
+
+
+ 4
+ 20
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_i2c_ex.c
+ stm32l4xx_hal_i2c_ex.c
+ 0
+ 0
+
+
+ 4
+ 21
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_rcc.c
+ stm32l4xx_hal_rcc.c
+ 0
+ 0
+
+
+ 4
+ 22
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_rcc_ex.c
+ stm32l4xx_hal_rcc_ex.c
+ 0
+ 0
+
+
+ 4
+ 23
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_flash.c
+ stm32l4xx_hal_flash.c
+ 0
+ 0
+
+
+ 4
+ 24
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_flash_ex.c
+ stm32l4xx_hal_flash_ex.c
+ 0
+ 0
+
+
+ 4
+ 25
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_flash_ramfunc.c
+ stm32l4xx_hal_flash_ramfunc.c
+ 0
+ 0
+
+
+ 4
+ 26
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_gpio.c
+ stm32l4xx_hal_gpio.c
+ 0
+ 0
+
+
+ 4
+ 27
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dma.c
+ stm32l4xx_hal_dma.c
+ 0
+ 0
+
+
+ 4
+ 28
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dma_ex.c
+ stm32l4xx_hal_dma_ex.c
+ 0
+ 0
+
+
+ 4
+ 29
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_pwr.c
+ stm32l4xx_hal_pwr.c
+ 0
+ 0
+
+
+ 4
+ 30
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_pwr_ex.c
+ stm32l4xx_hal_pwr_ex.c
+ 0
+ 0
+
+
+ 4
+ 31
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_cortex.c
+ stm32l4xx_hal_cortex.c
+ 0
+ 0
+
+
+ 4
+ 32
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_adc_ex.c
+ stm32l4xx_hal_adc_ex.c
+ 0
+ 0
+
+
+ 4
+ 33
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_adc.c
+ stm32l4xx_hal_adc.c
+ 0
+ 0
+
+
+ 4
+ 34
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dac.c
+ stm32l4xx_hal_dac.c
+ 0
+ 0
+
+
+ 4
+ 35
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dac_ex.c
+ stm32l4xx_hal_dac_ex.c
+ 0
+ 0
+
+
+ 4
+ 36
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_spi.c
+ stm32l4xx_hal_spi.c
+ 0
+ 0
+
+
+ 4
+ 37
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_spi_ex.c
+ stm32l4xx_hal_spi_ex.c
+ 0
+ 0
+
+
+
+
+ Drivers/CMSIS
+ 0
+ 0
+ 0
+ 0
+
+ 5
+ 38
+ 1
+ 0
+ 0
+ 0
+ ..\..\BSP\Src\system_stm32l4xx.c
+ system_stm32l4xx.c
+ 0
+ 0
+
+
+
+
+ Hardware
+ 0
+ 0
+ 0
+ 0
+
+ 6
+ 39
+ 1
+ 0
+ 0
+ 0
+ ..\..\BSP\Hardware\DHT11\DHT11_BUS.c
+ DHT11_BUS.c
+ 0
+ 0
+
+
+ 6
+ 40
+ 1
+ 0
+ 0
+ 0
+ ..\..\BSP\Hardware\OLED\oled.c
+ oled.c
+ 0
+ 0
+
+
+ 6
+ 41
+ 1
+ 0
+ 0
+ 0
+ ..\..\BSP\Hardware\BH1750\BH1750.c
+ BH1750.c
+ 0
+ 0
+
+
+
+
+ kernel
+ 0
+ 0
+ 0
+ 0
+
+ 7
+ 42
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_binary_heap.c
+ tos_binary_heap.c
+ 0
+ 0
+
+
+ 7
+ 43
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_char_fifo.c
+ tos_char_fifo.c
+ 0
+ 0
+
+
+ 7
+ 44
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_completion.c
+ tos_completion.c
+ 0
+ 0
+
+
+ 7
+ 45
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_countdownlatch.c
+ tos_countdownlatch.c
+ 0
+ 0
+
+
+ 7
+ 46
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_event.c
+ tos_event.c
+ 0
+ 0
+
+
+ 7
+ 47
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_global.c
+ tos_global.c
+ 0
+ 0
+
+
+ 7
+ 48
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_mail_queue.c
+ tos_mail_queue.c
+ 0
+ 0
+
+
+ 7
+ 49
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_message_queue.c
+ tos_message_queue.c
+ 0
+ 0
+
+
+ 7
+ 50
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_mmblk.c
+ tos_mmblk.c
+ 0
+ 0
+
+
+ 7
+ 51
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_mmheap.c
+ tos_mmheap.c
+ 0
+ 0
+
+
+ 7
+ 52
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_mutex.c
+ tos_mutex.c
+ 0
+ 0
+
+
+ 7
+ 53
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_pend.c
+ tos_pend.c
+ 0
+ 0
+
+
+ 7
+ 54
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_priority_mail_queue.c
+ tos_priority_mail_queue.c
+ 0
+ 0
+
+
+ 7
+ 55
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_priority_message_queue.c
+ tos_priority_message_queue.c
+ 0
+ 0
+
+
+ 7
+ 56
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_priority_queue.c
+ tos_priority_queue.c
+ 0
+ 0
+
+
+ 7
+ 57
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_ring_queue.c
+ tos_ring_queue.c
+ 0
+ 0
+
+
+ 7
+ 58
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_robin.c
+ tos_robin.c
+ 0
+ 0
+
+
+ 7
+ 59
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_sched.c
+ tos_sched.c
+ 0
+ 0
+
+
+ 7
+ 60
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_sem.c
+ tos_sem.c
+ 0
+ 0
+
+
+ 7
+ 61
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_sys.c
+ tos_sys.c
+ 0
+ 0
+
+
+ 7
+ 62
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_task.c
+ tos_task.c
+ 0
+ 0
+
+
+ 7
+ 63
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_tick.c
+ tos_tick.c
+ 0
+ 0
+
+
+ 7
+ 64
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_time.c
+ tos_time.c
+ 0
+ 0
+
+
+ 7
+ 65
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\kernel\core\tos_timer.c
+ tos_timer.c
+ 0
+ 0
+
+
+
+
+ cpu
+ 0
+ 0
+ 0
+ 0
+
+ 8
+ 66
+ 2
+ 0
+ 0
+ 0
+ ..\..\..\..\arch\arm\arm-v7m\cortex-m4\armcc\port_s.S
+ port_s.S
+ 0
+ 0
+
+
+ 8
+ 67
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\arch\arm\arm-v7m\common\tos_cpu.c
+ tos_cpu.c
+ 0
+ 0
+
+
+ 8
+ 68
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\arch\arm\arm-v7m\cortex-m4\armcc\port_c.c
+ port_c.c
+ 0
+ 0
+
+
+
+
+ cmsis
+ 0
+ 0
+ 0
+ 0
+
+ 9
+ 69
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\osal\cmsis_os\cmsis_os.c
+ cmsis_os.c
+ 0
+ 0
+
+
+
+
+ config
+ 0
+ 0
+ 0
+ 0
+
+ 10
+ 70
+ 5
+ 0
+ 0
+ 0
+ ..\..\TOS-CONFIG\tos_config.h
+ tos_config.h
+ 0
+ 0
+
+
+
+
+ devices
+ 0
+ 0
+ 0
+ 0
+
+ 11
+ 71
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\devices\bc35_28_95\bc35_28_95.c
+ bc35_28_95.c
+ 0
+ 0
+
+
+ 11
+ 72
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\devices\esp8266\esp8266.c
+ esp8266.c
+ 0
+ 0
+
+
+
+
+ hal
+ 0
+ 0
+ 0
+ 0
+
+ 12
+ 73
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\platform\hal\st\stm32l4xx\src\tos_hal_uart.c
+ tos_hal_uart.c
+ 0
+ 0
+
+
+
+
+ at
+ 0
+ 0
+ 0
+ 0
+
+ 13
+ 74
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\net\at\src\tos_at.c
+ tos_at.c
+ 0
+ 0
+
+
+ 13
+ 75
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\net\at\src\tos_at_utils.c
+ tos_at_utils.c
+ 0
+ 0
+
+
+ 13
+ 76
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\net\sal_module_wrapper\sal_module_wrapper.c
+ sal_module_wrapper.c
+ 0
+ 0
+
+
+
+
+ port/TencentOS_tiny
+ 0
+ 0
+ 0
+ 0
+
+ 14
+ 77
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\port\TencentOS_tiny\osal_os.c
+ osal_os.c
+ 0
+ 0
+
+
+ 14
+ 78
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\port\TencentOS_tiny\osal_tcp_module.c
+ osal_tcp_module.c
+ 0
+ 0
+
+
+ 14
+ 79
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\port\TencentOS_tiny\osal_timer.c
+ osal_timer.c
+ 0
+ 0
+
+
+
+
+ iotkit/mqtt
+ 0
+ 0
+ 0
+ 0
+
+ 15
+ 80
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\mqtt_api.c
+ mqtt_api.c
+ 0
+ 0
+
+
+ 15
+ 81
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\iotx_mqtt_client.c
+ iotx_mqtt_client.c
+ 0
+ 0
+
+
+ 15
+ 82
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTConnectClient.c
+ MQTTConnectClient.c
+ 0
+ 0
+
+
+ 15
+ 83
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTDeserializePublish.c
+ MQTTDeserializePublish.c
+ 0
+ 0
+
+
+ 15
+ 84
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTPacket.c
+ MQTTPacket.c
+ 0
+ 0
+
+
+ 15
+ 85
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTSerializePublish.c
+ MQTTSerializePublish.c
+ 0
+ 0
+
+
+ 15
+ 86
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTSubscribeClient.c
+ MQTTSubscribeClient.c
+ 0
+ 0
+
+
+ 15
+ 87
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTUnsubscribeClient.c
+ MQTTUnsubscribeClient.c
+ 0
+ 0
+
+
+
+
+ iotkit/infra
+ 0
+ 0
+ 0
+ 0
+
+ 16
+ 88
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_aes.c
+ infra_aes.c
+ 0
+ 0
+
+
+ 16
+ 89
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_cjson.c
+ infra_cjson.c
+ 0
+ 0
+
+
+ 16
+ 90
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_compat.c
+ infra_compat.c
+ 0
+ 0
+
+
+ 16
+ 91
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_defs.c
+ infra_defs.c
+ 0
+ 0
+
+
+ 16
+ 92
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_httpc.c
+ infra_httpc.c
+ 0
+ 0
+
+
+ 16
+ 93
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_json_parser.c
+ infra_json_parser.c
+ 0
+ 0
+
+
+ 16
+ 94
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_log.c
+ infra_log.c
+ 0
+ 0
+
+
+ 16
+ 95
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_md5.c
+ infra_md5.c
+ 0
+ 0
+
+
+ 16
+ 96
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_mem_stats.c
+ infra_mem_stats.c
+ 0
+ 0
+
+
+ 16
+ 97
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_net.c
+ infra_net.c
+ 0
+ 0
+
+
+ 16
+ 98
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_preauth.c
+ infra_preauth.c
+ 0
+ 0
+
+
+ 16
+ 99
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_prt_nwk_payload.c
+ infra_prt_nwk_payload.c
+ 0
+ 0
+
+
+ 16
+ 100
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_report.c
+ infra_report.c
+ 0
+ 0
+
+
+ 16
+ 101
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_sha1.c
+ infra_sha1.c
+ 0
+ 0
+
+
+ 16
+ 102
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_sha256.c
+ infra_sha256.c
+ 0
+ 0
+
+
+ 16
+ 103
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_string.c
+ infra_string.c
+ 0
+ 0
+
+
+ 16
+ 104
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_timer.c
+ infra_timer.c
+ 0
+ 0
+
+
+
+
+ iotkit/dev_sign
+ 0
+ 0
+ 0
+ 0
+
+ 17
+ 105
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\dev_sign\dev_sign_mqtt.c
+ dev_sign_mqtt.c
+ 0
+ 0
+
+
+
+
+ mbedtls
+ 0
+ 0
+ 0
+ 0
+
+ 18
+ 106
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\aes.c
+ aes.c
+ 0
+ 0
+
+
+ 18
+ 107
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\aesni.c
+ aesni.c
+ 0
+ 0
+
+
+ 18
+ 108
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\arc4.c
+ arc4.c
+ 0
+ 0
+
+
+ 18
+ 109
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\aria.c
+ aria.c
+ 0
+ 0
+
+
+ 18
+ 110
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\asn1parse.c
+ asn1parse.c
+ 0
+ 0
+
+
+ 18
+ 111
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\asn1write.c
+ asn1write.c
+ 0
+ 0
+
+
+ 18
+ 112
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\base64.c
+ base64.c
+ 0
+ 0
+
+
+ 18
+ 113
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\bignum.c
+ bignum.c
+ 0
+ 0
+
+
+ 18
+ 114
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\blowfish.c
+ blowfish.c
+ 0
+ 0
+
+
+ 18
+ 115
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\camellia.c
+ camellia.c
+ 0
+ 0
+
+
+ 18
+ 116
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ccm.c
+ ccm.c
+ 0
+ 0
+
+
+ 18
+ 117
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\certs.c
+ certs.c
+ 0
+ 0
+
+
+ 18
+ 118
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\chacha20.c
+ chacha20.c
+ 0
+ 0
+
+
+ 18
+ 119
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\chachapoly.c
+ chachapoly.c
+ 0
+ 0
+
+
+ 18
+ 120
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\cipher.c
+ cipher.c
+ 0
+ 0
+
+
+ 18
+ 121
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\cipher_wrap.c
+ cipher_wrap.c
+ 0
+ 0
+
+
+ 18
+ 122
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\cmac.c
+ cmac.c
+ 0
+ 0
+
+
+ 18
+ 123
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ctr_drbg.c
+ ctr_drbg.c
+ 0
+ 0
+
+
+ 18
+ 124
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\debug.c
+ debug.c
+ 0
+ 0
+
+
+ 18
+ 125
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\des.c
+ des.c
+ 0
+ 0
+
+
+ 18
+ 126
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\dhm.c
+ dhm.c
+ 0
+ 0
+
+
+ 18
+ 127
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ecdh.c
+ ecdh.c
+ 0
+ 0
+
+
+ 18
+ 128
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ecdsa.c
+ ecdsa.c
+ 0
+ 0
+
+
+ 18
+ 129
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ecjpake.c
+ ecjpake.c
+ 0
+ 0
+
+
+ 18
+ 130
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ecp.c
+ ecp.c
+ 0
+ 0
+
+
+ 18
+ 131
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ecp_curves.c
+ ecp_curves.c
+ 0
+ 0
+
+
+ 18
+ 132
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\entropy.c
+ entropy.c
+ 0
+ 0
+
+
+ 18
+ 133
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\entropy_poll.c
+ entropy_poll.c
+ 0
+ 0
+
+
+ 18
+ 134
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\error.c
+ error.c
+ 0
+ 0
+
+
+ 18
+ 135
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\gcm.c
+ gcm.c
+ 0
+ 0
+
+
+ 18
+ 136
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\havege.c
+ havege.c
+ 0
+ 0
+
+
+ 18
+ 137
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\hkdf.c
+ hkdf.c
+ 0
+ 0
+
+
+ 18
+ 138
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\hmac_drbg.c
+ hmac_drbg.c
+ 0
+ 0
+
+
+ 18
+ 139
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\md.c
+ md.c
+ 0
+ 0
+
+
+ 18
+ 140
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\md_wrap.c
+ md_wrap.c
+ 0
+ 0
+
+
+ 18
+ 141
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\md2.c
+ md2.c
+ 0
+ 0
+
+
+ 18
+ 142
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\md4.c
+ md4.c
+ 0
+ 0
+
+
+ 18
+ 143
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\md5.c
+ md5.c
+ 0
+ 0
+
+
+ 18
+ 144
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\memory_buffer_alloc.c
+ memory_buffer_alloc.c
+ 0
+ 0
+
+
+ 18
+ 145
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\net_sockets.c
+ net_sockets.c
+ 0
+ 0
+
+
+ 18
+ 146
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\nist_kw.c
+ nist_kw.c
+ 0
+ 0
+
+
+ 18
+ 147
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\oid.c
+ oid.c
+ 0
+ 0
+
+
+ 18
+ 148
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\padlock.c
+ padlock.c
+ 0
+ 0
+
+
+ 18
+ 149
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\pem.c
+ pem.c
+ 0
+ 0
+
+
+ 18
+ 150
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\pk.c
+ pk.c
+ 0
+ 0
+
+
+ 18
+ 151
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\pk_wrap.c
+ pk_wrap.c
+ 0
+ 0
+
+
+ 18
+ 152
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\pkcs5.c
+ pkcs5.c
+ 0
+ 0
+
+
+ 18
+ 153
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\pkcs11.c
+ pkcs11.c
+ 0
+ 0
+
+
+ 18
+ 154
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\pkcs12.c
+ pkcs12.c
+ 0
+ 0
+
+
+ 18
+ 155
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\pkparse.c
+ pkparse.c
+ 0
+ 0
+
+
+ 18
+ 156
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\pkwrite.c
+ pkwrite.c
+ 0
+ 0
+
+
+ 18
+ 157
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\platform.c
+ platform.c
+ 0
+ 0
+
+
+ 18
+ 158
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\platform_util.c
+ platform_util.c
+ 0
+ 0
+
+
+ 18
+ 159
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\poly1305.c
+ poly1305.c
+ 0
+ 0
+
+
+ 18
+ 160
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ripemd160.c
+ ripemd160.c
+ 0
+ 0
+
+
+ 18
+ 161
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\rsa.c
+ rsa.c
+ 0
+ 0
+
+
+ 18
+ 162
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\rsa_internal.c
+ rsa_internal.c
+ 0
+ 0
+
+
+ 18
+ 163
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\sha1.c
+ sha1.c
+ 0
+ 0
+
+
+ 18
+ 164
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\sha256.c
+ sha256.c
+ 0
+ 0
+
+
+ 18
+ 165
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\sha512.c
+ sha512.c
+ 0
+ 0
+
+
+ 18
+ 166
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_cache.c
+ ssl_cache.c
+ 0
+ 0
+
+
+ 18
+ 167
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_ciphersuites.c
+ ssl_ciphersuites.c
+ 0
+ 0
+
+
+ 18
+ 168
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_cli.c
+ ssl_cli.c
+ 0
+ 0
+
+
+ 18
+ 169
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_cookie.c
+ ssl_cookie.c
+ 0
+ 0
+
+
+ 18
+ 170
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_srv.c
+ ssl_srv.c
+ 0
+ 0
+
+
+ 18
+ 171
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_ticket.c
+ ssl_ticket.c
+ 0
+ 0
+
+
+ 18
+ 172
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_tls.c
+ ssl_tls.c
+ 0
+ 0
+
+
+ 18
+ 173
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\threading.c
+ threading.c
+ 0
+ 0
+
+
+ 18
+ 174
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\timing.c
+ timing.c
+ 0
+ 0
+
+
+ 18
+ 175
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\version.c
+ version.c
+ 0
+ 0
+
+
+ 18
+ 176
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\version_features.c
+ version_features.c
+ 0
+ 0
+
+
+ 18
+ 177
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\x509.c
+ x509.c
+ 0
+ 0
+
+
+ 18
+ 178
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\x509_create.c
+ x509_create.c
+ 0
+ 0
+
+
+ 18
+ 179
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\x509_crl.c
+ x509_crl.c
+ 0
+ 0
+
+
+ 18
+ 180
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\x509_crt.c
+ x509_crt.c
+ 0
+ 0
+
+
+ 18
+ 181
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\x509_csr.c
+ x509_csr.c
+ 0
+ 0
+
+
+ 18
+ 182
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\x509write_crt.c
+ x509write_crt.c
+ 0
+ 0
+
+
+ 18
+ 183
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\x509write_csr.c
+ x509write_csr.c
+ 0
+ 0
+
+
+ 18
+ 184
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\xtea.c
+ xtea.c
+ 0
+ 0
+
+
+ 18
+ 185
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\wrapper\src\entropy_hardware_alt.c
+ entropy_hardware_alt.c
+ 0
+ 0
+
+
+ 18
+ 186
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\wrapper\src\net_module_alt.c
+ net_module_alt.c
+ 0
+ 0
+
+
+ 18
+ 187
+ 1
+ 0
+ 0
+ 0
+ ..\..\..\..\components\security\mbedtls\wrapper\src\timing_alt.c
+ timing_alt.c
+ 0
+ 0
+
+
+
+
+ ::CMSIS
+ 0
+ 0
+ 0
+ 1
+
+
+
diff --git a/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/TencentOS_tiny.uvprojx b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/TencentOS_tiny.uvprojx
new file mode 100644
index 00000000..d8c88ce9
--- /dev/null
+++ b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/TencentOS_tiny.uvprojx
@@ -0,0 +1,1427 @@
+
+
+
+ 2.1
+
+ ### uVision Project, (C) Keil Software
+
+
+
+ TencentOS_tiny
+ 0x4
+ ARM-ADS
+ 5060750::V5.06 update 6 (build 750)::ARMCC
+ 0
+
+
+ STM32L431RCTx
+ STMicroelectronics
+ Keil.STM32L4xx_DFP.2.0.0
+ http://www.keil.com/pack
+ IRAM(0x20000000-0x2000FFFF) IROM(0x8000000-0x803FFFF) CLOCK(8000000) FPU2 CPUTYPE("Cortex-M4")
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $$Device:STM32L431RCTx$CMSIS\SVD\STM32L4x1.svd
+ 0
+ 0
+
+
+
+
+
+
+ 0
+ 0
+ 0
+ 0
+ 1
+
+ .\obj\
+ TencentOS_tiny
+ 1
+ 0
+ 1
+ 1
+ 0
+ .\list\
+ 1
+ 0
+ 0
+
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+ 0
+
+ 0
+
+
+
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 3
+
+
+ 0
+
+
+ SARMCM3.DLL
+ -REMAP -MPU
+ DCM.DLL
+ -pCM4
+ SARMCM3.DLL
+ -MPU
+ TCM.DLL
+ -pCM4
+
+
+
+ 1
+ 0
+ 0
+ 0
+ 16
+
+
+
+
+ 1
+ 0
+ 0
+ 1
+ 1
+ 4107
+
+ 1
+ STLink\ST-LINKIII-KEIL_SWO.dll
+
+
+
+
+
+ 0
+
+
+
+ 0
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 1
+ 1
+ 0
+ 1
+ 1
+ 0
+ 0
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ "Cortex-M4"
+
+ 0
+ 0
+ 0
+ 1
+ 1
+ 0
+ 0
+ 2
+ 0
+ 0
+ 0
+ 8
+ 1
+ 0
+ 0
+ 0
+ 3
+ 3
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x20000000
+ 0x10000
+
+
+ 1
+ 0x8000000
+ 0x40000
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 1
+ 0x8000000
+ 0x40000
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x20000000
+ 0x10000
+
+
+ 0
+ 0x0
+ 0x0
+
+
+
+
+
+ 1
+ 1
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 2
+ 0
+ 0
+ 1
+ 0
+ 0
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ 0
+
+
+ USE_HAL_DRIVER,STM32L431xx,PLATFORM_HAS_STDINT,INFRA_COMPAT,INFRA_LOG,INFRA_TIMER,INFRA_REPORT,INFRA_NET,INFRA_STRING,INFRA_SHA256,MBEDTLS_CONFIG_FILE=<qcloud/tls_psk_config.h>
+
+ ..\..\BSP\Inc;..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Inc;..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Legacy;..\..\..\..\platform\vendor_bsp\st\CMSIS\Device\ST\STM32L4xx\Include;..\..\..\..\platform\vendor_bsp\st\CMSIS\Include;..\..\..\..\kernel\core\include;..\..\TOS-CONFIG;..\..\..\..\platform\arch\arm\cortex-m4\keil;..\..\..\..\kernel\pm\include;..\..\..\..\osal\cmsis_os;..\..\..\..\arch\arm\arm-v7m\common\include;..\..\..\..\arch\arm\arm-v7m\cortex-m4\armcc;..\..\BSP\Hardware\DHT11;..\..\BSP\Hardware\BH1750;..\..\BSP\Hardware\OLED;..\..\..\..\examples\helloworld;..\..\..\..\net\at\include;..\..\..\..\kernel\hal\include;..\..\..\..\net\sal_module_wrapper;..\..\..\..\examples\mqtt;..\..\..\..\devices\bc35_28_95;..\..\..\..\devices\esp8266;..\..\..\..\devices\m26;..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra;..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\dev_sign;..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt;..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\wrappers;..\..\..\..\components\security\mbedtls\3rdparty\include;..\..\..\..\components\security\mbedtls\wrapper\include
+
+
+
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+
+ 1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0x08000000
+ 0x20000000
+
+
+
+
+
+
+
+
+
+
+
+
+ Application/MDK-ARM
+
+
+ startup_stm32l431xx.s
+ 2
+ startup_stm32l431xx.s
+
+
+
+
+ Application/User
+
+
+ gpio.c
+ 1
+ ..\..\BSP\Src\gpio.c
+
+
+ main.c
+ 1
+ ..\..\BSP\Src\main.c
+
+
+ mcu_init.c
+ 1
+ ..\..\BSP\Src\mcu_init.c
+
+
+ stm32l4xx_hal_msp.c
+ 1
+ ..\..\BSP\Src\stm32l4xx_hal_msp.c
+
+
+ usart.c
+ 1
+ ..\..\BSP\Src\usart.c
+
+
+ adc.c
+ 1
+ ..\..\BSP\Src\adc.c
+
+
+ dac.c
+ 1
+ ..\..\BSP\Src\dac.c
+
+
+ i2c.c
+ 1
+ ..\..\BSP\Src\i2c.c
+
+
+ spi.c
+ 1
+ ..\..\BSP\Src\spi.c
+
+
+ stm32l4xx_it_module.c
+ 1
+ ..\..\BSP\Src\stm32l4xx_it_module.c
+
+
+
+
+ examples
+
+
+ mqtt_example.c
+ 1
+ ..\..\..\..\examples\aliyun_iotkit_csdk_mqtt\mqtt_example.c
+
+
+ aliyun_iotkit_csdk_mqtt.c
+ 1
+ ..\..\..\..\examples\aliyun_iotkit_csdk_mqtt\aliyun_iotkit_csdk_mqtt.c
+
+
+
+
+ Drivers/STM32L4xx_HAL_Driver
+
+
+ stm32l4xx_hal_tim.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_tim.c
+
+
+ stm32l4xx_hal_tim_ex.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_tim_ex.c
+
+
+ stm32l4xx_hal_uart.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_uart.c
+
+
+ stm32l4xx_hal_uart_ex.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_uart_ex.c
+
+
+ stm32l4xx_hal.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal.c
+
+
+ stm32l4xx_hal_i2c.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_i2c.c
+
+
+ stm32l4xx_hal_i2c_ex.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_i2c_ex.c
+
+
+ stm32l4xx_hal_rcc.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_rcc.c
+
+
+ stm32l4xx_hal_rcc_ex.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_rcc_ex.c
+
+
+ stm32l4xx_hal_flash.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_flash.c
+
+
+ stm32l4xx_hal_flash_ex.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_flash_ex.c
+
+
+ stm32l4xx_hal_flash_ramfunc.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_flash_ramfunc.c
+
+
+ stm32l4xx_hal_gpio.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_gpio.c
+
+
+ stm32l4xx_hal_dma.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dma.c
+
+
+ stm32l4xx_hal_dma_ex.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dma_ex.c
+
+
+ stm32l4xx_hal_pwr.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_pwr.c
+
+
+ stm32l4xx_hal_pwr_ex.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_pwr_ex.c
+
+
+ stm32l4xx_hal_cortex.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_cortex.c
+
+
+ stm32l4xx_hal_adc_ex.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_adc_ex.c
+
+
+ stm32l4xx_hal_adc.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_adc.c
+
+
+ stm32l4xx_hal_dac.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dac.c
+
+
+ stm32l4xx_hal_dac_ex.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_dac_ex.c
+
+
+ stm32l4xx_hal_spi.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_spi.c
+
+
+ stm32l4xx_hal_spi_ex.c
+ 1
+ ..\..\..\..\platform\vendor_bsp\st\STM32L4xx_HAL_Driver\Src\stm32l4xx_hal_spi_ex.c
+
+
+
+
+ Drivers/CMSIS
+
+
+ system_stm32l4xx.c
+ 1
+ ..\..\BSP\Src\system_stm32l4xx.c
+
+
+
+
+ Hardware
+
+
+ DHT11_BUS.c
+ 1
+ ..\..\BSP\Hardware\DHT11\DHT11_BUS.c
+
+
+ oled.c
+ 1
+ ..\..\BSP\Hardware\OLED\oled.c
+
+
+ BH1750.c
+ 1
+ ..\..\BSP\Hardware\BH1750\BH1750.c
+
+
+
+
+ kernel
+
+
+ tos_binary_heap.c
+ 1
+ ..\..\..\..\kernel\core\tos_binary_heap.c
+
+
+ tos_char_fifo.c
+ 1
+ ..\..\..\..\kernel\core\tos_char_fifo.c
+
+
+ tos_completion.c
+ 1
+ ..\..\..\..\kernel\core\tos_completion.c
+
+
+ tos_countdownlatch.c
+ 1
+ ..\..\..\..\kernel\core\tos_countdownlatch.c
+
+
+ tos_event.c
+ 1
+ ..\..\..\..\kernel\core\tos_event.c
+
+
+ tos_global.c
+ 1
+ ..\..\..\..\kernel\core\tos_global.c
+
+
+ tos_mail_queue.c
+ 1
+ ..\..\..\..\kernel\core\tos_mail_queue.c
+
+
+ tos_message_queue.c
+ 1
+ ..\..\..\..\kernel\core\tos_message_queue.c
+
+
+ tos_mmblk.c
+ 1
+ ..\..\..\..\kernel\core\tos_mmblk.c
+
+
+ tos_mmheap.c
+ 1
+ ..\..\..\..\kernel\core\tos_mmheap.c
+
+
+ tos_mutex.c
+ 1
+ ..\..\..\..\kernel\core\tos_mutex.c
+
+
+ tos_pend.c
+ 1
+ ..\..\..\..\kernel\core\tos_pend.c
+
+
+ tos_priority_mail_queue.c
+ 1
+ ..\..\..\..\kernel\core\tos_priority_mail_queue.c
+
+
+ tos_priority_message_queue.c
+ 1
+ ..\..\..\..\kernel\core\tos_priority_message_queue.c
+
+
+ tos_priority_queue.c
+ 1
+ ..\..\..\..\kernel\core\tos_priority_queue.c
+
+
+ tos_ring_queue.c
+ 1
+ ..\..\..\..\kernel\core\tos_ring_queue.c
+
+
+ tos_robin.c
+ 1
+ ..\..\..\..\kernel\core\tos_robin.c
+
+
+ tos_sched.c
+ 1
+ ..\..\..\..\kernel\core\tos_sched.c
+
+
+ tos_sem.c
+ 1
+ ..\..\..\..\kernel\core\tos_sem.c
+
+
+ tos_sys.c
+ 1
+ ..\..\..\..\kernel\core\tos_sys.c
+
+
+ tos_task.c
+ 1
+ ..\..\..\..\kernel\core\tos_task.c
+
+
+ tos_tick.c
+ 1
+ ..\..\..\..\kernel\core\tos_tick.c
+
+
+ tos_time.c
+ 1
+ ..\..\..\..\kernel\core\tos_time.c
+
+
+ tos_timer.c
+ 1
+ ..\..\..\..\kernel\core\tos_timer.c
+
+
+
+
+ cpu
+
+
+ port_s.S
+ 2
+ ..\..\..\..\arch\arm\arm-v7m\cortex-m4\armcc\port_s.S
+
+
+ tos_cpu.c
+ 1
+ ..\..\..\..\arch\arm\arm-v7m\common\tos_cpu.c
+
+
+ port_c.c
+ 1
+ ..\..\..\..\arch\arm\arm-v7m\cortex-m4\armcc\port_c.c
+
+
+
+
+ cmsis
+
+
+ cmsis_os.c
+ 1
+ ..\..\..\..\osal\cmsis_os\cmsis_os.c
+
+
+
+
+ config
+
+
+ tos_config.h
+ 5
+ ..\..\TOS-CONFIG\tos_config.h
+
+
+
+
+ devices
+
+
+ bc35_28_95.c
+ 1
+ ..\..\..\..\devices\bc35_28_95\bc35_28_95.c
+
+
+ esp8266.c
+ 1
+ ..\..\..\..\devices\esp8266\esp8266.c
+
+
+
+
+ hal
+
+
+ tos_hal_uart.c
+ 1
+ ..\..\..\..\platform\hal\st\stm32l4xx\src\tos_hal_uart.c
+
+
+
+
+ at
+
+
+ tos_at.c
+ 1
+ ..\..\..\..\net\at\src\tos_at.c
+
+
+ tos_at_utils.c
+ 1
+ ..\..\..\..\net\at\src\tos_at_utils.c
+
+
+ sal_module_wrapper.c
+ 1
+ ..\..\..\..\net\sal_module_wrapper\sal_module_wrapper.c
+
+
+
+
+ port/TencentOS_tiny
+
+
+ osal_os.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\port\TencentOS_tiny\osal_os.c
+
+
+ osal_tcp_module.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\port\TencentOS_tiny\osal_tcp_module.c
+
+
+ osal_timer.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\port\TencentOS_tiny\osal_timer.c
+
+
+
+
+ iotkit/mqtt
+
+
+ mqtt_api.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\mqtt_api.c
+
+
+ iotx_mqtt_client.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\iotx_mqtt_client.c
+
+
+ MQTTConnectClient.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTConnectClient.c
+
+
+ MQTTDeserializePublish.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTDeserializePublish.c
+
+
+ MQTTPacket.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTPacket.c
+
+
+ MQTTSerializePublish.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTSerializePublish.c
+
+
+ MQTTSubscribeClient.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTSubscribeClient.c
+
+
+ MQTTUnsubscribeClient.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\mqtt\impl\MQTTUnsubscribeClient.c
+
+
+
+
+ iotkit/infra
+
+
+ infra_aes.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_aes.c
+
+
+ infra_cjson.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_cjson.c
+
+
+ infra_compat.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_compat.c
+
+
+ infra_defs.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_defs.c
+
+
+ infra_httpc.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_httpc.c
+
+
+ infra_json_parser.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_json_parser.c
+
+
+ infra_log.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_log.c
+
+
+ infra_md5.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_md5.c
+
+
+ infra_mem_stats.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_mem_stats.c
+
+
+ infra_net.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_net.c
+
+
+ infra_preauth.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_preauth.c
+
+
+ infra_prt_nwk_payload.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_prt_nwk_payload.c
+
+
+ infra_report.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_report.c
+
+
+ infra_sha1.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_sha1.c
+
+
+ infra_sha256.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_sha256.c
+
+
+ infra_string.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_string.c
+
+
+ infra_timer.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\infra\infra_timer.c
+
+
+
+
+ iotkit/dev_sign
+
+
+ dev_sign_mqtt.c
+ 1
+ ..\..\..\..\components\connectivity\iotkit-embedded-3.0.1\3rdparty\src\dev_sign\dev_sign_mqtt.c
+
+
+
+
+ mbedtls
+
+
+ aes.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\aes.c
+
+
+ aesni.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\aesni.c
+
+
+ arc4.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\arc4.c
+
+
+ aria.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\aria.c
+
+
+ asn1parse.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\asn1parse.c
+
+
+ asn1write.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\asn1write.c
+
+
+ base64.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\base64.c
+
+
+ bignum.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\bignum.c
+
+
+ blowfish.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\blowfish.c
+
+
+ camellia.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\camellia.c
+
+
+ ccm.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ccm.c
+
+
+ certs.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\certs.c
+
+
+ chacha20.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\chacha20.c
+
+
+ chachapoly.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\chachapoly.c
+
+
+ cipher.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\cipher.c
+
+
+ cipher_wrap.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\cipher_wrap.c
+
+
+ cmac.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\cmac.c
+
+
+ ctr_drbg.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ctr_drbg.c
+
+
+ debug.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\debug.c
+
+
+ des.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\des.c
+
+
+ dhm.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\dhm.c
+
+
+ ecdh.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ecdh.c
+
+
+ ecdsa.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ecdsa.c
+
+
+ ecjpake.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ecjpake.c
+
+
+ ecp.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ecp.c
+
+
+ ecp_curves.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ecp_curves.c
+
+
+ entropy.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\entropy.c
+
+
+ entropy_poll.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\entropy_poll.c
+
+
+ error.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\error.c
+
+
+ gcm.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\gcm.c
+
+
+ havege.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\havege.c
+
+
+ hkdf.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\hkdf.c
+
+
+ hmac_drbg.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\hmac_drbg.c
+
+
+ md.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\md.c
+
+
+ md_wrap.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\md_wrap.c
+
+
+ md2.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\md2.c
+
+
+ md4.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\md4.c
+
+
+ md5.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\md5.c
+
+
+ memory_buffer_alloc.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\memory_buffer_alloc.c
+
+
+ net_sockets.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\net_sockets.c
+
+
+ nist_kw.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\nist_kw.c
+
+
+ oid.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\oid.c
+
+
+ padlock.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\padlock.c
+
+
+ pem.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\pem.c
+
+
+ pk.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\pk.c
+
+
+ pk_wrap.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\pk_wrap.c
+
+
+ pkcs5.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\pkcs5.c
+
+
+ pkcs11.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\pkcs11.c
+
+
+ pkcs12.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\pkcs12.c
+
+
+ pkparse.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\pkparse.c
+
+
+ pkwrite.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\pkwrite.c
+
+
+ platform.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\platform.c
+
+
+ platform_util.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\platform_util.c
+
+
+ poly1305.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\poly1305.c
+
+
+ ripemd160.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ripemd160.c
+
+
+ rsa.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\rsa.c
+
+
+ rsa_internal.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\rsa_internal.c
+
+
+ sha1.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\sha1.c
+
+
+ sha256.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\sha256.c
+
+
+ sha512.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\sha512.c
+
+
+ ssl_cache.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_cache.c
+
+
+ ssl_ciphersuites.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_ciphersuites.c
+
+
+ ssl_cli.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_cli.c
+
+
+ ssl_cookie.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_cookie.c
+
+
+ ssl_srv.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_srv.c
+
+
+ ssl_ticket.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_ticket.c
+
+
+ ssl_tls.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\ssl_tls.c
+
+
+ threading.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\threading.c
+
+
+ timing.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\timing.c
+
+
+ version.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\version.c
+
+
+ version_features.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\version_features.c
+
+
+ x509.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\x509.c
+
+
+ x509_create.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\x509_create.c
+
+
+ x509_crl.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\x509_crl.c
+
+
+ x509_crt.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\x509_crt.c
+
+
+ x509_csr.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\x509_csr.c
+
+
+ x509write_crt.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\x509write_crt.c
+
+
+ x509write_csr.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\x509write_csr.c
+
+
+ xtea.c
+ 1
+ ..\..\..\..\components\security\mbedtls\3rdparty\src\xtea.c
+
+
+ entropy_hardware_alt.c
+ 1
+ ..\..\..\..\components\security\mbedtls\wrapper\src\entropy_hardware_alt.c
+
+
+ net_module_alt.c
+ 1
+ ..\..\..\..\components\security\mbedtls\wrapper\src\net_module_alt.c
+
+
+ timing_alt.c
+ 1
+ ..\..\..\..\components\security\mbedtls\wrapper\src\timing_alt.c
+
+
+
+
+ ::CMSIS
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/obj/TencentOS_tiny.build_log.htm b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/obj/TencentOS_tiny.build_log.htm
new file mode 100644
index 00000000..eac2a534
--- /dev/null
+++ b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/obj/TencentOS_tiny.build_log.htm
@@ -0,0 +1,60 @@
+
+
+ADC1_IRQHandler ⇒ ADC1_IRQHandler
+
+
+
+Function Pointers
+
+ - ADC1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- BusFault_Handler from stm32l4xx_it_module.o(i.BusFault_Handler) referenced from startup_stm32l431xx.o(RESET)
+
- CAN1_RX0_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- CAN1_RX1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- CAN1_SCE_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- CAN1_TX_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- COMP_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- CRS_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- DMA1_Channel1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- DMA1_Channel2_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- DMA1_Channel3_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- DMA1_Channel4_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- DMA1_Channel5_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- DMA1_Channel6_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- DMA1_Channel7_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- DMA2_Channel1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- DMA2_Channel2_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- DMA2_Channel3_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- DMA2_Channel4_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- DMA2_Channel5_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- DMA2_Channel6_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- DMA2_Channel7_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- DebugMon_Handler from stm32l4xx_it_module.o(i.DebugMon_Handler) referenced from startup_stm32l431xx.o(RESET)
+
- EXTI0_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- EXTI15_10_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- EXTI1_IRQHandler from stm32l4xx_it_module.o(i.EXTI1_IRQHandler) referenced from startup_stm32l431xx.o(RESET)
+
- EXTI2_IRQHandler from stm32l4xx_it_module.o(i.EXTI2_IRQHandler) referenced from startup_stm32l431xx.o(RESET)
+
- EXTI3_IRQHandler from stm32l4xx_it_module.o(i.EXTI3_IRQHandler) referenced from startup_stm32l431xx.o(RESET)
+
- EXTI4_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- EXTI9_5_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- FLASH_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- FPU_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- HardFault_Handler from stm32l4xx_it_module.o(i.HardFault_Handler) referenced from startup_stm32l431xx.o(RESET)
+
- I2C1_ER_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- I2C1_EV_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- I2C2_ER_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- I2C2_EV_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- I2C3_ER_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- I2C3_EV_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- IOT_MQTT_Publish_Simple from mqtt_api.o(i.IOT_MQTT_Publish_Simple) referenced from mqtt_api.o(i.iotx_mqtt_report_funcs)
+
- LPTIM1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- LPTIM2_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- LPUART1_IRQHandler from stm32l4xx_it_module.o(i.LPUART1_IRQHandler) referenced from startup_stm32l431xx.o(RESET)
+
- MemManage_Handler from stm32l4xx_it_module.o(i.MemManage_Handler) referenced from startup_stm32l431xx.o(RESET)
+
- NMI_Handler from stm32l4xx_it_module.o(i.NMI_Handler) referenced from startup_stm32l431xx.o(RESET)
+
- PVD_PVM_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- PendSV_Handler from port_s.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- QUADSPI_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- RCC_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- RNG_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- RTC_Alarm_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- RTC_WKUP_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- Reset_Handler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- SAI1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- SDMMC1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- SPI1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- SPI2_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- SPI3_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- SVC_Handler from stm32l4xx_it_module.o(i.SVC_Handler) referenced from startup_stm32l431xx.o(RESET)
+
- SWPMI1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- SysTick_Handler from stm32l4xx_it_module.o(i.SysTick_Handler) referenced from startup_stm32l431xx.o(RESET)
+
- SystemInit from system_stm32l4xx.o(i.SystemInit) referenced from startup_stm32l431xx.o(.text)
+
- TAMP_STAMP_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- TIM1_BRK_TIM15_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- TIM1_CC_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- TIM1_TRG_COM_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- TIM1_UP_TIM16_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- TIM2_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- TIM6_DAC_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- TIM7_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- TSC_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- UART_DMAAbortOnError from stm32l4xx_hal_uart.o(i.UART_DMAAbortOnError) referenced from stm32l4xx_hal_uart.o(i.HAL_UART_IRQHandler)
+
- UART_RxISR_16BIT from stm32l4xx_hal_uart.o(i.UART_RxISR_16BIT) referenced from stm32l4xx_hal_uart.o(i.HAL_UART_Receive_IT)
+
- UART_RxISR_8BIT from stm32l4xx_hal_uart.o(i.UART_RxISR_8BIT) referenced from stm32l4xx_hal_uart.o(i.HAL_UART_Receive_IT)
+
- USART1_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- USART2_IRQHandler from stm32l4xx_it_module.o(i.USART2_IRQHandler) referenced from startup_stm32l431xx.o(RESET)
+
- USART3_IRQHandler from stm32l4xx_it_module.o(i.USART3_IRQHandler) referenced from startup_stm32l431xx.o(RESET)
+
- UsageFault_Handler from stm32l4xx_it_module.o(i.UsageFault_Handler) referenced from startup_stm32l431xx.o(RESET)
+
- WWDG_IRQHandler from startup_stm32l431xx.o(.text) referenced from startup_stm32l431xx.o(RESET)
+
- __main from entry.o(.ARM.Collect$$$$00000000) referenced from startup_stm32l431xx.o(.text)
+
- _sbackspace from _sgetc.o(.text) referenced from __0sscanf.o(.text)
+
- _scanf_char_input from scanf_char.o(.text) referenced from scanf_char.o(.text)
+
- _sgetc from _sgetc.o(.text) referenced from __0sscanf.o(.text)
+
- _snputc from printfa.o(i._snputc) referenced from printfa.o(i.__0snprintf)
+
- _snputc from printfa.o(i._snputc) referenced from printfa.o(i.__0vsnprintf)
+
- application_entry from aliyun_iotkit_csdk_mqtt.o(i.application_entry) referenced from main.o(.constdata)
+
- at_parser from tos_at.o(i.at_parser) referenced from tos_at.o(i.tos_at_init)
+
- bufchar from mqttpacket.o(i.bufchar) referenced from mqttpacket.o(i.MQTTPacket_decodeBuf)
+
- esp8266_close from esp8266.o(i.esp8266_close) referenced 2 times from esp8266.o(.data)
+
- esp8266_connect from esp8266.o(i.esp8266_connect) referenced 2 times from esp8266.o(.data)
+
- esp8266_incoming_data_process from esp8266.o(i.esp8266_incoming_data_process) referenced 2 times from esp8266.o(.data)
+
- esp8266_init from esp8266.o(i.esp8266_init) referenced 2 times from esp8266.o(.data)
+
- esp8266_parse_domain from esp8266.o(i.esp8266_parse_domain) referenced 2 times from esp8266.o(.data)
+
- esp8266_recv from esp8266.o(i.esp8266_recv) referenced 2 times from esp8266.o(.data)
+
- esp8266_recv_timeout from esp8266.o(i.esp8266_recv_timeout) referenced 2 times from esp8266.o(.data)
+
- esp8266_recvfrom from esp8266.o(i.esp8266_recvfrom) referenced 2 times from esp8266.o(.data)
+
- esp8266_recvfrom_timeout from esp8266.o(i.esp8266_recvfrom_timeout) referenced 2 times from esp8266.o(.data)
+
- esp8266_send from esp8266.o(i.esp8266_send) referenced 2 times from esp8266.o(.data)
+
- esp8266_sendto from esp8266.o(i.esp8266_sendto) referenced 2 times from esp8266.o(.data)
+
- example_event_handle from mqtt_example.o(i.example_event_handle) referenced from mqtt_example.o(i.mqtt_basic_thread)
+
- example_message_arrive from mqtt_example.o(i.example_message_arrive) referenced from mqtt_example.o(i.example_subscribe)
+
- fputc from mcu_init.o(i.fputc) referenced from printfa.o(i.__0printf)
+
- fputc from mcu_init.o(i.fputc) referenced from printfa.o(i.__0vprintf)
+
- iotx_net_connect from infra_net.o(i.iotx_net_connect) referenced from infra_net.o(i.iotx_net_init)
+
- iotx_net_disconnect from infra_net.o(i.iotx_net_disconnect) referenced from infra_net.o(i.iotx_net_init)
+
- isspace from isspace_c.o(.text) referenced from scanf_char.o(.text)
+
- knl_idle_entry from tos_sys.o(i.knl_idle_entry) referenced from tos_sys.o(i.knl_idle_init)
+
- main from main.o(i.main) referenced from entry9a.o(.ARM.Collect$$$$0000000B)
+
- task_exit from tos_task.o(i.task_exit) referenced from tos_task.o(i.tos_task_create)
+
- utils_net_read from infra_net.o(i.utils_net_read) referenced from infra_net.o(i.iotx_net_init)
+
- utils_net_write from infra_net.o(i.utils_net_write) referenced from infra_net.o(i.iotx_net_init)
+
+
+
+Global Symbols
+
+__main (Thumb, 0 bytes, Stack size unknown bytes, entry.o(.ARM.Collect$$$$00000000))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(.text)
+
+_main_stk (Thumb, 0 bytes, Stack size unknown bytes, entry2.o(.ARM.Collect$$$$00000001))
+
+
_main_scatterload (Thumb, 0 bytes, Stack size unknown bytes, entry5.o(.ARM.Collect$$$$00000004))
+
[Calls]
+
+__main_after_scatterload (Thumb, 0 bytes, Stack size unknown bytes, entry5.o(.ARM.Collect$$$$00000004))
+
[Called By]
+
+_main_clock (Thumb, 0 bytes, Stack size unknown bytes, entry7b.o(.ARM.Collect$$$$00000008))
+
+
_main_cpp_init (Thumb, 0 bytes, Stack size unknown bytes, entry8b.o(.ARM.Collect$$$$0000000A))
+
+
_main_init (Thumb, 0 bytes, Stack size unknown bytes, entry9a.o(.ARM.Collect$$$$0000000B))
+
+
__rt_final_cpp (Thumb, 0 bytes, Stack size unknown bytes, entry10a.o(.ARM.Collect$$$$0000000D))
+
+
__rt_final_exit (Thumb, 0 bytes, Stack size unknown bytes, entry11a.o(.ARM.Collect$$$$0000000F))
+
+
Reset_Handler (Thumb, 8 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+ADC1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Calls]
+
[Called By]
+
[Address Reference Count : 1]- startup_stm32l431xx.o(RESET)
+
+CAN1_RX0_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+CAN1_RX1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+CAN1_SCE_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+CAN1_TX_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+COMP_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+CRS_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+DMA1_Channel1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+DMA1_Channel2_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+DMA1_Channel3_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+DMA1_Channel4_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+DMA1_Channel5_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+DMA1_Channel6_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+DMA1_Channel7_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+DMA2_Channel1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+DMA2_Channel2_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+DMA2_Channel3_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+DMA2_Channel4_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+DMA2_Channel5_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+DMA2_Channel6_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+DMA2_Channel7_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+EXTI0_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+EXTI15_10_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+EXTI4_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+EXTI9_5_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+FLASH_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+FPU_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+I2C1_ER_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+I2C1_EV_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+I2C2_ER_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+I2C2_EV_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+I2C3_ER_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+I2C3_EV_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+LPTIM1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+LPTIM2_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+PVD_PVM_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+QUADSPI_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+RCC_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+RNG_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+RTC_Alarm_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+RTC_WKUP_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+SAI1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+SDMMC1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+SPI1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+SPI2_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+SPI3_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+SWPMI1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+TAMP_STAMP_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+TIM1_BRK_TIM15_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+TIM1_CC_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+TIM1_TRG_COM_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+TIM1_UP_TIM16_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+TIM2_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+TIM6_DAC_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+TIM7_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+TSC_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+USART1_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+WWDG_IRQHandler (Thumb, 0 bytes, Stack size 0 bytes, startup_stm32l431xx.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+port_int_disable (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text), UNUSED)
+
+
port_int_enable (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text), UNUSED)
+
+
port_cpsr_save (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text))
+
[Called By]
+
+port_cpsr_restore (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text))
+
[Called By]
- >> tos_cpu_cpsr_restore
+
+
+port_clz (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text))
+
[Called By]
+
+port_sched_start (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text))
+
[Called By]
+
+port_context_switch (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text))
+
[Called By]
+
+port_irq_context_switch (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text))
+
[Called By]
- >> cpu_irq_context_switch
+
+
+PendSV_Handler (Thumb, 0 bytes, Stack size unknown bytes, port_s.o(.text))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+__aeabi_uldivmod (Thumb, 98 bytes, Stack size 40 bytes, uldiv.o(.text))
+
[Stack]
- Max Depth = 40
- Call Chain = __aeabi_uldivmod
+
+
[Calls]- >> __aeabi_llsl
+
- >> __aeabi_llsr
+
+
[Called By]- >> UART_SetConfig
+
- >> tos_sleep_hmsm
+
- >> tos_millisec2tick
+
- >> cpu_init
+
- >> _printf_core
+
- >> _fp_digits
+
+
+__aeabi_llsl (Thumb, 30 bytes, Stack size 0 bytes, llshl.o(.text))
+
[Called By]
- >> __aeabi_uldivmod
+
- >> _double_epilogue
+
- >> __aeabi_dadd
+
- >> __aeabi_d2ulz
+
+
+_ll_shift_l (Thumb, 0 bytes, Stack size 0 bytes, llshl.o(.text), UNUSED)
+
+
___aeabi_memcpy8$move (Thumb, 0 bytes, Stack size 8 bytes, memmovea.o(.text), UNUSED)
+
+
__aeabi_memcpy (Thumb, 64 bytes, Stack size 8 bytes, memmovea.o(.text))
+
[Stack]
- Max Depth = 8
- Call Chain = __aeabi_memcpy
+
+
[Called By]- >> IOT_MQTT_Construct
+
- >> tos_ring_q_enqueue
+
- >> tos_ring_q_dequeue
+
- >> at_echo_buffer_copy
+
- >> iotx_mc_push_pubInfo_to
+
- >> MQTTSubscribe
+
- >> _sign_get_clientid
+
- >> IOT_Sign_MQTT
+
- >> IOT_Ioctl
+
- >> iotx_mqtt_offline_subscribe
+
- >> utils_sha256_update
+
- >> utils_hmac_sha256
+
- >> writeMQTTString
+
- >> writeCString
+
- >> MQTTSerialize_publish
+
- >> _iotx_generate_sign_string
+
+
+__aeabi_memcpy4 (Thumb, 0 bytes, Stack size 8 bytes, memmovea.o(.text))
+
[Stack]
- Max Depth = 8
- Call Chain = __aeabi_memcpy4
+
+
[Called By]- >> IOT_MQTT_Construct
+
- >> iotx_mc_init
+
- >> _iotx_generate_sign_string
+
+
+__aeabi_memmove (Thumb, 0 bytes, Stack size 8 bytes, memmovea.o(.text), UNUSED)
+
+
__aeabi_memmove4 (Thumb, 0 bytes, Stack size 8 bytes, memmovea.o(.text), UNUSED)
+
+
__aeabi_memmove8 (Thumb, 0 bytes, Stack size 8 bytes, memmovea.o(.text), UNUSED)
+
+
__aeabi_memset (Thumb, 14 bytes, Stack size 0 bytes, memseta.o(.text))
+
[Called By]
- >> memset
+
- >> __aeabi_memclr
+
+
+__aeabi_memset4 (Thumb, 0 bytes, Stack size 0 bytes, memseta.o(.text), UNUSED)
+
+
__aeabi_memset8 (Thumb, 0 bytes, Stack size 0 bytes, memseta.o(.text), UNUSED)
+
+
__aeabi_memclr (Thumb, 4 bytes, Stack size 0 bytes, memseta.o(.text))
+
[Calls]
+
[Called By]- >> HAL_GetProductKey
+
- >> HAL_GetDeviceSecret
+
- >> HAL_GetDeviceName
+
- >> example_subscribe
+
- >> example_publish
+
- >> at_uart_line_parse
+
- >> tos_at_echo_create
+
- >> iotx_report_devinfo
+
- >> _sign_get_clientid
+
- >> IOT_Sign_MQTT
+
- >> IOT_Ioctl
+
- >> HAL_GetFirmwareVersion
+
- >> LITE_syslog_routine
+
- >> infra_strtok
+
+
+__aeabi_memclr4 (Thumb, 0 bytes, Stack size 0 bytes, memseta.o(.text))
+
[Called By]
- >> HAL_UART_MspInit
+
- >> SystemClock_Config
+
- >> MX_GPIO_Init
+
- >> IOT_MQTT_Publish_Simple
+
- >> IOT_MQTT_Construct
+
- >> mqtt_basic_thread
+
- >> at_channel_init
+
- >> tos_at_init
+
- >> tos_at_channel_free
+
- >> iotx_mc_release
+
- >> iotx_mc_read_packet
+
- >> iotx_mc_pub_wait_list_init
+
- >> iotx_mc_pub_wait_list_deinit
+
- >> iotx_mc_init
+
- >> iotx_mc_handle_recv_PUBLISH
+
- >> iotx_mc_check_topic
+
- >> MQTTSubscribe
+
- >> MQTTPubInfoProc
+
- >> wrapper_mqtt_release
+
- >> iotx_report_firmware_version
+
- >> iotx_report_devinfo
+
- >> IOT_Sign_MQTT
+
- >> IOT_Ioctl
+
- >> iotx_mqtt_offline_subscribe
+
- >> _offline_subs_list_init
+
- >> _offline_subs_list_deinit
+
- >> utils_sha256_init
+
- >> utils_hmac_sha256
+
- >> MQTTPublish
+
- >> _iotx_generate_sign_string
+
+
+__aeabi_memclr8 (Thumb, 0 bytes, Stack size 0 bytes, memseta.o(.text), UNUSED)
+
+
memset (Thumb, 18 bytes, Stack size 8 bytes, memseta.o(.text), UNUSED)
+
[Calls]
+
+strstr (Thumb, 36 bytes, Stack size 12 bytes, strstr.o(.text))
+
[Stack]
- Max Depth = 12
- Call Chain = strstr
+
+
[Called By]- >> IOT_MQTT_Construct
+
- >> at_echo_status_set
+
- >> esp8266_parse_domain
+
- >> esp8266_is_link_broken
+
+
+strncpy (Thumb, 24 bytes, Stack size 8 bytes, strncpy.o(.text))
+
[Stack]
- Max Depth = 8
- Call Chain = strncpy
+
+
[Called By]- >> HAL_GetProductKey
+
- >> HAL_GetDeviceSecret
+
- >> HAL_GetDeviceName
+
- >> iotx_mc_check_topic
+
- >> HAL_GetFirmwareVersion
+
+
+strlen (Thumb, 14 bytes, Stack size 0 bytes, strlen.o(.text))
+
[Called By]
- >> IOT_MQTT_Subscribe
+
- >> IOT_MQTT_Publish_Simple
+
- >> IOT_MQTT_Construct
+
- >> HAL_GetProductKey
+
- >> HAL_GetDeviceSecret
+
- >> HAL_GetDeviceName
+
- >> example_subscribe
+
- >> example_publish
+
- >> at_is_echo_expect
+
- >> at_event_do_get
+
- >> iotx_mc_check_topic
+
- >> iotx_mc_check_rule
+
- >> iotx_mc_check_handle_is_identical_ex
+
- >> MQTTSubscribe
+
- >> wrapper_mqtt_subscribe
+
- >> iotx_report_firmware_version
+
- >> iotx_report_devinfo
+
- >> _sign_get_clientid
+
- >> IOT_Sign_MQTT
+
- >> IOT_Ioctl
+
- >> iotx_mqtt_offline_subscribe
+
- >> HAL_GetFirmwareVersion
+
- >> LITE_syslog_routine
+
- >> writeCString
+
- >> MQTTstrlen
+
- >> iotx_net_init
+
- >> infra_strtok
+
- >> MQTTPacket_equals
+
- >> MQTTPublish
+
- >> _iotx_generate_sign_string
+
+
+memcmp (Thumb, 26 bytes, Stack size 12 bytes, memcmp.o(.text))
+
[Stack]
- Max Depth = 12
- Call Chain = memcmp
+
+
[Called By]- >> iotx_mqtt_offline_subscribe
+
- >> infra_strtok
+
- >> MQTTPacket_equals
+
+
+strncmp (Thumb, 30 bytes, Stack size 12 bytes, strncmp.o(.text))
+
[Stack]
- Max Depth = 12
- Call Chain = strncmp
+
+
[Called By]- >> at_is_echo_expect
+
- >> at_event_do_get
+
- >> iotx_mc_check_handle_is_identical_ex
+
+
+__0sscanf (Thumb, 48 bytes, Stack size 72 bytes, __0sscanf.o(.text))
+
[Stack]
- Max Depth = 216
- Call Chain = __0sscanf ⇒ __vfscanf_char ⇒ __vfscanf ⇒ _scanf_string
+
+
[Calls]
+
[Called By]- >> esp8266_parse_domain
+
+
+_scanf_string (Thumb, 224 bytes, Stack size 56 bytes, _scanf_str.o(.text))
+
[Stack]
- Max Depth = 56
- Call Chain = _scanf_string
+
+
[Called By]
+
+__aeabi_ddiv (Thumb, 222 bytes, Stack size 32 bytes, ddiv.o(.text), UNUSED)
+
[Calls]
+
[Called By]
+
+__aeabi_uidiv (Thumb, 0 bytes, Stack size 12 bytes, uidiv.o(.text), UNUSED)
+
+
__aeabi_uidivmod (Thumb, 44 bytes, Stack size 12 bytes, uidiv.o(.text), UNUSED)
+
[Called By]
+
+__aeabi_llsr (Thumb, 32 bytes, Stack size 0 bytes, llushr.o(.text))
+
[Called By]
- >> __aeabi_uldivmod
+
- >> _double_epilogue
+
- >> __aeabi_d2ulz
+
+
+_ll_ushift_r (Thumb, 0 bytes, Stack size 0 bytes, llushr.o(.text), UNUSED)
+
+
__vfscanf_char (Thumb, 20 bytes, Stack size 0 bytes, scanf_char.o(.text))
+
[Stack]
- Max Depth = 144
- Call Chain = __vfscanf_char ⇒ __vfscanf ⇒ _scanf_string
+
+
[Calls]
+
[Called By]
+
+_sgetc (Thumb, 30 bytes, Stack size 0 bytes, _sgetc.o(.text))
+
[Address Reference Count : 1]
+_sbackspace (Thumb, 34 bytes, Stack size 0 bytes, _sgetc.o(.text))
+
[Address Reference Count : 1]
+__I$use$fp (Thumb, 0 bytes, Stack size 8 bytes, iusefp.o(.text), UNUSED)
+
+
_double_round (Thumb, 30 bytes, Stack size 8 bytes, depilogue.o(.text), UNUSED)
+
[Called By]
- >> __aeabi_ddiv
+
- >> _double_epilogue
+
- >> __aeabi_dadd
+
+
+_double_epilogue (Thumb, 156 bytes, Stack size 32 bytes, depilogue.o(.text), UNUSED)
+
[Calls]
- >> __aeabi_llsl
+
- >> __aeabi_llsr
+
- >> _double_round
+
+
[Called By]- >> __aeabi_dmul
+
- >> __aeabi_dadd
+
+
+__aeabi_dadd (Thumb, 322 bytes, Stack size 48 bytes, dadd.o(.text), UNUSED)
+
[Calls]
- >> __aeabi_llsl
+
- >> __aeabi_lasr
+
- >> _double_epilogue
+
- >> _double_round
+
+
[Called By]- >> __aeabi_drsub
+
- >> __aeabi_dsub
+
- >> _fp_digits
+
+
+__aeabi_dsub (Thumb, 6 bytes, Stack size 0 bytes, dadd.o(.text), UNUSED)
+
[Calls]
+
+__aeabi_drsub (Thumb, 6 bytes, Stack size 0 bytes, dadd.o(.text), UNUSED)
+
[Calls]
+
+__aeabi_dmul (Thumb, 228 bytes, Stack size 48 bytes, dmul.o(.text), UNUSED)
+
[Calls]
+
[Called By]
+
+__aeabi_d2ulz (Thumb, 48 bytes, Stack size 0 bytes, dfixul.o(.text), UNUSED)
+
[Calls]
- >> __aeabi_llsl
+
- >> __aeabi_llsr
+
+
[Called By]
+
+__aeabi_cdrcmple (Thumb, 48 bytes, Stack size 0 bytes, cdrcmple.o(.text), UNUSED)
+
[Called By]
+
+__scatterload (Thumb, 28 bytes, Stack size 0 bytes, init.o(.text))
+
[Calls]
- >> __main_after_scatterload
+
+
[Called By]
+
+__scatterload_rt2 (Thumb, 0 bytes, Stack size 0 bytes, init.o(.text), UNUSED)
+
+
__aeabi_lasr (Thumb, 36 bytes, Stack size 0 bytes, llsshr.o(.text), UNUSED)
+
[Called By]
+
+_ll_sshift_r (Thumb, 0 bytes, Stack size 0 bytes, llsshr.o(.text), UNUSED)
+
+
isspace (Thumb, 10 bytes, Stack size 0 bytes, isspace_c.o(.text))
+
[Calls]
+
[Address Reference Count : 1]
+__vfscanf (Thumb, 808 bytes, Stack size 88 bytes, _scanf.o(.text))
+
[Stack]
- Max Depth = 144
- Call Chain = __vfscanf ⇒ _scanf_string
+
+
[Calls]
+
[Called By]
+
+__ctype_lookup (Thumb, 34 bytes, Stack size 0 bytes, ctype_c.o(.text))
+
[Called By]
+
+__decompress (Thumb, 0 bytes, Stack size unknown bytes, __dczerorl2.o(.text), UNUSED)
+
+
__decompress1 (Thumb, 86 bytes, Stack size unknown bytes, __dczerorl2.o(.text), UNUSED)
+
+
BusFault_Handler (Thumb, 4 bytes, Stack size 0 bytes, stm32l4xx_it_module.o(i.BusFault_Handler))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+DHT11_Init (Thumb, 48 bytes, Stack size 8 bytes, dht11_bus.o(i.DHT11_Init))
+
[Stack]
- Max Depth = 52
- Call Chain = DHT11_Init ⇒ DHT11_Mode_Out_PP ⇒ HAL_GPIO_Init
+
+
[Calls]- >> HAL_GPIO_WritePin
+
- >> DHT11_Mode_Out_PP
+
+
[Called By]
+
+DebugMon_Handler (Thumb, 2 bytes, Stack size 0 bytes, stm32l4xx_it_module.o(i.DebugMon_Handler))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+EXTI1_IRQHandler (Thumb, 10 bytes, Stack size 8 bytes, stm32l4xx_it_module.o(i.EXTI1_IRQHandler))
+
[Stack]
- Max Depth = 16
- Call Chain = EXTI1_IRQHandler ⇒ HAL_GPIO_EXTI_IRQHandler
+
+
[Calls]- >> HAL_GPIO_EXTI_IRQHandler
+
+
[Address Reference Count : 1]- startup_stm32l431xx.o(RESET)
+
+EXTI2_IRQHandler (Thumb, 10 bytes, Stack size 8 bytes, stm32l4xx_it_module.o(i.EXTI2_IRQHandler))
+
[Stack]
- Max Depth = 16
- Call Chain = EXTI2_IRQHandler ⇒ HAL_GPIO_EXTI_IRQHandler
+
+
[Calls]- >> HAL_GPIO_EXTI_IRQHandler
+
+
[Address Reference Count : 1]- startup_stm32l431xx.o(RESET)
+
+EXTI3_IRQHandler (Thumb, 10 bytes, Stack size 8 bytes, stm32l4xx_it_module.o(i.EXTI3_IRQHandler))
+
[Stack]
- Max Depth = 16
- Call Chain = EXTI3_IRQHandler ⇒ HAL_GPIO_EXTI_IRQHandler
+
+
[Calls]- >> HAL_GPIO_EXTI_IRQHandler
+
+
[Address Reference Count : 1]- startup_stm32l431xx.o(RESET)
+
+Error_Handler (Thumb, 2 bytes, Stack size 0 bytes, mcu_init.o(i.Error_Handler))
+
[Called By]
- >> MX_USART1_UART_Init
+
- >> MX_LPUART1_UART_Init
+
- >> MX_USART3_UART_Init
+
- >> MX_USART2_UART_Init
+
- >> SystemClock_Config
+
+
+HAL_DMA_Abort_IT (Thumb, 92 bytes, Stack size 16 bytes, stm32l4xx_hal_dma.o(i.HAL_DMA_Abort_IT))
+
[Stack]
- Max Depth = 16
- Call Chain = HAL_DMA_Abort_IT
+
+
[Called By]
+
+HAL_Delay (Thumb, 32 bytes, Stack size 16 bytes, stm32l4xx_hal.o(i.HAL_Delay))
+
[Stack]
- Max Depth = 16
- Call Chain = HAL_Delay
+
+
[Calls]
+
[Called By]
+
+HAL_Free (Thumb, 12 bytes, Stack size 8 bytes, osal_os.o(i.HAL_Free))
+
[Stack]
- Max Depth = 112 + Unknown Stack Size
+
- Call Chain = HAL_Free ⇒ tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]
+
[Called By]- >> example_subscribe
+
- >> example_publish
+
- >> iotx_report_devinfo
+
- >> HAL_MutexDestroy
+
+
+HAL_GPIO_DeInit (Thumb, 256 bytes, Stack size 20 bytes, stm32l4xx_hal_gpio.o(i.HAL_GPIO_DeInit))
+
[Stack]
- Max Depth = 20
- Call Chain = HAL_GPIO_DeInit
+
+
[Called By]
+
+HAL_GPIO_EXTI_Callback (Thumb, 2 bytes, Stack size 0 bytes, stm32l4xx_hal_gpio.o(i.HAL_GPIO_EXTI_Callback))
+
[Called By]
- >> HAL_GPIO_EXTI_IRQHandler
+
+
+HAL_GPIO_EXTI_IRQHandler (Thumb, 24 bytes, Stack size 8 bytes, stm32l4xx_hal_gpio.o(i.HAL_GPIO_EXTI_IRQHandler))
+
[Stack]
- Max Depth = 8
- Call Chain = HAL_GPIO_EXTI_IRQHandler
+
+
[Calls]- >> HAL_GPIO_EXTI_Callback
+
+
[Called By]- >> EXTI3_IRQHandler
+
- >> EXTI2_IRQHandler
+
- >> EXTI1_IRQHandler
+
+
+HAL_GPIO_Init (Thumb, 428 bytes, Stack size 20 bytes, stm32l4xx_hal_gpio.o(i.HAL_GPIO_Init))
+
[Stack]
- Max Depth = 20
- Call Chain = HAL_GPIO_Init
+
+
[Called By]- >> HAL_UART_MspInit
+
- >> MX_GPIO_Init
+
- >> DHT11_Mode_Out_PP
+
+
+HAL_GPIO_WritePin (Thumb, 10 bytes, Stack size 0 bytes, stm32l4xx_hal_gpio.o(i.HAL_GPIO_WritePin))
+
[Called By]
- >> DHT11_Init
+
- >> MX_GPIO_Init
+
- >> Write_IIC_Byte
+
- >> IIC_Wait_Ack
+
- >> IIC_Stop
+
- >> IIC_Start
+
+
+HAL_GetDeviceName (Thumb, 38 bytes, Stack size 16 bytes, osal_os.o(i.HAL_GetDeviceName))
+
[Stack]
- Max Depth = 24
- Call Chain = HAL_GetDeviceName ⇒ strncpy
+
+
[Calls]- >> strlen
+
- >> strncpy
+
- >> __aeabi_memclr
+
+
[Called By]- >> IOT_MQTT_Construct
+
- >> mqtt_basic_thread
+
- >> iotx_report_firmware_version
+
- >> iotx_report_devinfo
+
+
+HAL_GetDeviceSecret (Thumb, 34 bytes, Stack size 16 bytes, osal_os.o(i.HAL_GetDeviceSecret))
+
[Stack]
- Max Depth = 24
- Call Chain = HAL_GetDeviceSecret ⇒ strncpy
+
+
[Calls]- >> strlen
+
- >> strncpy
+
- >> __aeabi_memclr
+
+
[Called By]- >> IOT_MQTT_Construct
+
- >> mqtt_basic_thread
+
+
+HAL_GetFirmwareVersion (Thumb, 44 bytes, Stack size 16 bytes, osal_os.o(i.HAL_GetFirmwareVersion))
+
[Stack]
- Max Depth = 24
- Call Chain = HAL_GetFirmwareVersion ⇒ strncpy
+
+
[Calls]- >> strlen
+
- >> strncpy
+
- >> __aeabi_memclr
+
+
[Called By]- >> iotx_report_firmware_version
+
+
+HAL_GetProductKey (Thumb, 34 bytes, Stack size 16 bytes, osal_os.o(i.HAL_GetProductKey))
+
[Stack]
- Max Depth = 24
- Call Chain = HAL_GetProductKey ⇒ strncpy
+
+
[Calls]- >> strlen
+
- >> strncpy
+
- >> __aeabi_memclr
+
+
[Called By]- >> IOT_MQTT_Construct
+
- >> mqtt_basic_thread
+
- >> iotx_report_firmware_version
+
- >> iotx_report_devinfo
+
+
+HAL_GetTick (Thumb, 6 bytes, Stack size 0 bytes, stm32l4xx_hal.o(i.HAL_GetTick))
+
[Called By]
- >> HAL_UART_Transmit
+
- >> HAL_RCC_OscConfig
+
- >> HAL_RCC_ClockConfig
+
- >> HAL_RCCEx_PeriphCLKConfig
+
- >> HAL_Delay
+
- >> UART_WaitOnFlagUntilTimeout
+
- >> UART_CheckIdleState
+
- >> RCCEx_PLLSAI1_Config
+
+
+HAL_IncTick (Thumb, 12 bytes, Stack size 0 bytes, stm32l4xx_hal.o(i.HAL_IncTick))
+
[Called By]
+
+HAL_Init (Thumb, 30 bytes, Stack size 8 bytes, stm32l4xx_hal.o(i.HAL_Init))
+
[Stack]
- Max Depth = 72
- Call Chain = HAL_Init ⇒ HAL_InitTick ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority
+
+
[Calls]- >> HAL_MspInit
+
- >> HAL_InitTick
+
- >> HAL_NVIC_SetPriorityGrouping
+
+
[Called By]
+
+HAL_InitTick (Thumb, 44 bytes, Stack size 16 bytes, stm32l4xx_hal.o(i.HAL_InitTick))
+
[Stack]
- Max Depth = 64
- Call Chain = HAL_InitTick ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority
+
+
[Calls]- >> HAL_NVIC_SetPriority
+
- >> HAL_SYSTICK_Config
+
+
[Called By]- >> HAL_RCC_OscConfig
+
- >> HAL_RCC_ClockConfig
+
- >> HAL_Init
+
+
+HAL_Malloc (Thumb, 12 bytes, Stack size 8 bytes, osal_os.o(i.HAL_Malloc))
+
[Stack]
- Max Depth = 136 + Unknown Stack Size
+
- Call Chain = HAL_Malloc ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next
+
+
[Calls]
+
[Called By]- >> example_subscribe
+
- >> example_publish
+
- >> iotx_report_devinfo
+
- >> HAL_MutexCreate
+
+
+HAL_MspInit (Thumb, 58 bytes, Stack size 8 bytes, stm32l4xx_hal_msp.o(i.HAL_MspInit))
+
[Stack]
- Max Depth = 8
- Call Chain = HAL_MspInit
+
+
[Called By]
+
+HAL_MutexCreate (Thumb, 20 bytes, Stack size 8 bytes, osal_os.o(i.HAL_MutexCreate))
+
[Stack]
- Max Depth = 144 + Unknown Stack Size
+
- Call Chain = HAL_MutexCreate ⇒ HAL_Malloc ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next
+
+
[Calls]- >> HAL_Malloc
+
- >> tos_mutex_create
+
+
[Called By]- >> iotx_mc_init
+
- >> _offline_subs_list_init
+
+
+HAL_MutexDestroy (Thumb, 32 bytes, Stack size 16 bytes, osal_os.o(i.HAL_MutexDestroy))
+
[Stack]
- Max Depth = 128 + Unknown Stack Size
+
- Call Chain = HAL_MutexDestroy ⇒ HAL_Free ⇒ tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]- >> HAL_Printf
+
- >> HAL_Free
+
- >> tos_mutex_destroy
+
+
[Called By]- >> iotx_mc_init
+
- >> wrapper_mqtt_release
+
- >> _offline_subs_list_deinit
+
+
+HAL_MutexLock (Thumb, 24 bytes, Stack size 16 bytes, osal_os.o(i.HAL_MutexLock))
+
[Stack]
- Max Depth = 152 + Unknown Stack Size
+
- Call Chain = HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> HAL_Printf
+
- >> tos_mutex_pend
+
+
[Called By]- >> iotx_mc_wait_CONNACK
+
- >> iotx_mc_set_client_state
+
- >> iotx_mc_read_packet
+
- >> iotx_mc_keepalive_sub
+
- >> iotx_mc_get_next_packetid
+
- >> iotx_mc_get_client_state
+
- >> iotx_mc_deliver_message
+
- >> iotx_mc_cycle
+
- >> _iotx_mqtt_event_handle_sub
+
- >> MQTTSubscribe
+
- >> MQTTRePublish
+
- >> MQTTPuback
+
- >> MQTTPubInfoProc
+
- >> MQTTKeepalive
+
- >> MQTTDisconnect
+
- >> wrapper_mqtt_yield
+
- >> iotx_mqtt_offline_subscribe
+
- >> iotx_mqtt_deal_offline_subs
+
- >> _mqtt_cycle
+
- >> MQTTPublish
+
- >> MQTTConnect
+
+
+HAL_MutexUnlock (Thumb, 24 bytes, Stack size 16 bytes, osal_os.o(i.HAL_MutexUnlock))
+
[Stack]
- Max Depth = 128 + Unknown Stack Size
+
- Call Chain = HAL_MutexUnlock ⇒ tos_mutex_post ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz
+
+
[Calls]- >> HAL_Printf
+
- >> tos_mutex_post
+
+
[Called By]- >> iotx_mc_wait_CONNACK
+
- >> iotx_mc_set_client_state
+
- >> iotx_mc_read_packet
+
- >> iotx_mc_keepalive_sub
+
- >> iotx_mc_get_next_packetid
+
- >> iotx_mc_get_client_state
+
- >> iotx_mc_deliver_message
+
- >> iotx_mc_cycle
+
- >> _iotx_mqtt_event_handle_sub
+
- >> MQTTSubscribe
+
- >> MQTTRePublish
+
- >> MQTTPuback
+
- >> MQTTPubInfoProc
+
- >> MQTTKeepalive
+
- >> MQTTDisconnect
+
- >> wrapper_mqtt_yield
+
- >> iotx_mqtt_offline_subscribe
+
- >> iotx_mqtt_deal_offline_subs
+
- >> _mqtt_cycle
+
- >> MQTTPublish
+
- >> MQTTConnect
+
+
+HAL_NVIC_DisableIRQ (Thumb, 62 bytes, Stack size 8 bytes, stm32l4xx_hal_cortex.o(i.HAL_NVIC_DisableIRQ))
+
[Stack]
- Max Depth = 8
- Call Chain = HAL_NVIC_DisableIRQ
+
+
[Called By]
+
+HAL_NVIC_EnableIRQ (Thumb, 32 bytes, Stack size 0 bytes, stm32l4xx_hal_cortex.o(i.HAL_NVIC_EnableIRQ))
+
[Called By]
- >> HAL_UART_MspInit
+
- >> MX_GPIO_Init
+
+
+HAL_NVIC_SetPriority (Thumb, 124 bytes, Stack size 40 bytes, stm32l4xx_hal_cortex.o(i.HAL_NVIC_SetPriority))
+
[Stack]
- Max Depth = 48
- Call Chain = HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority
+
+
[Calls]- >> __NVIC_SetPriority
+
- >> __NVIC_GetPriorityGrouping
+
+
[Called By]- >> HAL_UART_MspInit
+
- >> MX_GPIO_Init
+
- >> HAL_InitTick
+
+
+HAL_NVIC_SetPriorityGrouping (Thumb, 32 bytes, Stack size 0 bytes, stm32l4xx_hal_cortex.o(i.HAL_NVIC_SetPriorityGrouping))
+
[Called By]
+
+HAL_PWREx_ControlVoltageScaling (Thumb, 128 bytes, Stack size 0 bytes, stm32l4xx_hal_pwr_ex.o(i.HAL_PWREx_ControlVoltageScaling))
+
[Called By]
+
+HAL_PWREx_GetVoltageRange (Thumb, 10 bytes, Stack size 0 bytes, stm32l4xx_hal_pwr_ex.o(i.HAL_PWREx_GetVoltageRange))
+
[Called By]
- >> RCC_SetFlashLatencyFromMSIRange
+
+
+HAL_PWR_EnableBkUpAccess (Thumb, 14 bytes, Stack size 0 bytes, stm32l4xx_hal_pwr.o(i.HAL_PWR_EnableBkUpAccess))
+
[Called By]
+
+HAL_Printf (Thumb, 26 bytes, Stack size 24 bytes, osal_os.o(i.HAL_Printf))
+
[Stack]
- Max Depth = 24
- Call Chain = HAL_Printf
+
+
[Calls]
+
[Called By]- >> mqtt_basic_thread
+
- >> example_subscribe
+
- >> example_publish
+
- >> example_message_arrive
+
- >> example_event_handle
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
- >> HAL_MutexDestroy
+
- >> LITE_syslog_routine
+
+
+HAL_RCCEx_EnableMSIPLLMode (Thumb, 14 bytes, Stack size 0 bytes, stm32l4xx_hal_rcc_ex.o(i.HAL_RCCEx_EnableMSIPLLMode))
+
[Called By]
+
+HAL_RCCEx_PeriphCLKConfig (Thumb, 894 bytes, Stack size 32 bytes, stm32l4xx_hal_rcc_ex.o(i.HAL_RCCEx_PeriphCLKConfig))
+
[Stack]
- Max Depth = 56
- Call Chain = HAL_RCCEx_PeriphCLKConfig ⇒ RCCEx_PLLSAI1_Config
+
+
[Calls]- >> HAL_GetTick
+
- >> RCCEx_PLLSAI1_Config
+
+
[Called By]
+
+HAL_RCC_ClockConfig (Thumb, 358 bytes, Stack size 24 bytes, stm32l4xx_hal_rcc.o(i.HAL_RCC_ClockConfig))
+
[Stack]
- Max Depth = 88
- Call Chain = HAL_RCC_ClockConfig ⇒ HAL_InitTick ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority
+
+
[Calls]- >> HAL_InitTick
+
- >> HAL_RCC_GetSysClockFreq
+
- >> HAL_GetTick
+
+
[Called By]
+
+HAL_RCC_GetHCLKFreq (Thumb, 6 bytes, Stack size 0 bytes, stm32l4xx_hal_rcc.o(i.HAL_RCC_GetHCLKFreq))
+
[Called By]
- >> HAL_RCC_GetPCLK2Freq
+
- >> HAL_RCC_GetPCLK1Freq
+
+
+HAL_RCC_GetPCLK1Freq (Thumb, 26 bytes, Stack size 4 bytes, stm32l4xx_hal_rcc.o(i.HAL_RCC_GetPCLK1Freq))
+
[Stack]
- Max Depth = 4
- Call Chain = HAL_RCC_GetPCLK1Freq
+
+
[Calls]
+
[Called By]
+
+HAL_RCC_GetPCLK2Freq (Thumb, 26 bytes, Stack size 4 bytes, stm32l4xx_hal_rcc.o(i.HAL_RCC_GetPCLK2Freq))
+
[Stack]
- Max Depth = 4
- Call Chain = HAL_RCC_GetPCLK2Freq
+
+
[Calls]
+
[Called By]
+
+HAL_RCC_GetSysClockFreq (Thumb, 266 bytes, Stack size 24 bytes, stm32l4xx_hal_rcc.o(i.HAL_RCC_GetSysClockFreq))
+
[Stack]
- Max Depth = 24
- Call Chain = HAL_RCC_GetSysClockFreq
+
+
[Called By]- >> HAL_RCC_OscConfig
+
- >> HAL_RCC_ClockConfig
+
- >> UART_SetConfig
+
+
+HAL_RCC_OscConfig (Thumb, 1660 bytes, Stack size 32 bytes, stm32l4xx_hal_rcc.o(i.HAL_RCC_OscConfig))
+
[Stack]
- Max Depth = 96
- Call Chain = HAL_RCC_OscConfig ⇒ HAL_InitTick ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority
+
+
[Calls]- >> RCC_SetFlashLatencyFromMSIRange
+
- >> HAL_InitTick
+
- >> HAL_RCC_GetSysClockFreq
+
- >> HAL_GetTick
+
+
[Called By]
+
+HAL_SYSTICK_Config (Thumb, 52 bytes, Stack size 16 bytes, stm32l4xx_hal_cortex.o(i.HAL_SYSTICK_Config))
+
[Stack]
- Max Depth = 24
- Call Chain = HAL_SYSTICK_Config ⇒ __NVIC_SetPriority
+
+
[Calls]
+
[Called By]
+
+HAL_SleepMs (Thumb, 18 bytes, Stack size 8 bytes, osal_os.o(i.HAL_SleepMs))
+
[Stack]
- Max Depth = 144 + Unknown Stack Size
+
- Call Chain = HAL_SleepMs ⇒ tos_sleep_hmsm ⇒ tos_task_delay ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]
+
[Called By]- >> iotx_mc_handle_reconnect
+
- >> _mqtt_connect
+
- >> wrapper_mqtt_release
+
- >> wrapper_mqtt_connect
+
- >> _mqtt_cycle
+
+
+HAL_Snprintf (Thumb, 38 bytes, Stack size 40 bytes, osal_os.o(i.HAL_Snprintf))
+
[Stack]
- Max Depth = 64
- Call Chain = HAL_Snprintf ⇒ vsnprintf
+
+
[Calls]
+
[Called By]- >> example_subscribe
+
- >> example_publish
+
- >> iotx_report_firmware_version
+
- >> iotx_report_devinfo
+
+
+HAL_TCP_Destroy (Thumb, 14 bytes, Stack size 8 bytes, osal_tcp_module.o(i.HAL_TCP_Destroy))
+
[Stack]
- Max Depth = 16
- Call Chain = HAL_TCP_Destroy ⇒ tos_sal_module_close
+
+
[Calls]- >> tos_sal_module_close
+
+
[Called By]
+
+HAL_TCP_Establish (Thumb, 126 bytes, Stack size 32 bytes, osal_tcp_module.o(i.HAL_TCP_Establish))
+
[Stack]
- Max Depth = 64
- Call Chain = HAL_TCP_Establish ⇒ __2snprintf
+
+
[Calls]- >> tos_sal_module_init
+
- >> tos_sal_module_connect
+
- >> __2snprintf
+
- >> __2printf
+
+
[Called By]
+
+HAL_TCP_Read (Thumb, 28 bytes, Stack size 24 bytes, osal_tcp_module.o(i.HAL_TCP_Read))
+
[Stack]
- Max Depth = 48
- Call Chain = HAL_TCP_Read ⇒ tos_sal_module_recv_timeout
+
+
[Calls]- >> tos_sal_module_recv_timeout
+
+
[Called By]
+
+HAL_TCP_Write (Thumb, 26 bytes, Stack size 24 bytes, osal_tcp_module.o(i.HAL_TCP_Write))
+
[Stack]
- Max Depth = 40
- Call Chain = HAL_TCP_Write ⇒ tos_sal_module_send
+
+
[Calls]
+
[Called By]
+
+HAL_UARTEx_WakeupCallback (Thumb, 2 bytes, Stack size 0 bytes, stm32l4xx_hal_uart_ex.o(i.HAL_UARTEx_WakeupCallback))
+
[Called By]
+
+HAL_UART_DeInit (Thumb, 72 bytes, Stack size 8 bytes, stm32l4xx_hal_uart.o(i.HAL_UART_DeInit))
+
[Stack]
- Max Depth = 36
- Call Chain = HAL_UART_DeInit ⇒ HAL_UART_MspDeInit ⇒ HAL_GPIO_DeInit
+
+
[Calls]
+
[Called By]
+
+HAL_UART_ErrorCallback (Thumb, 2 bytes, Stack size 0 bytes, stm32l4xx_hal_uart.o(i.HAL_UART_ErrorCallback))
+
[Called By]
- >> HAL_UART_IRQHandler
+
- >> UART_DMAAbortOnError
+
+
+HAL_UART_IRQHandler (Thumb, 392 bytes, Stack size 24 bytes, stm32l4xx_hal_uart.o(i.HAL_UART_IRQHandler))
+
[Stack]
- Max Depth = 40
- Call Chain = HAL_UART_IRQHandler ⇒ HAL_DMA_Abort_IT
+
+
[Calls]- >> HAL_UART_ErrorCallback
+
- >> HAL_UARTEx_WakeupCallback
+
- >> HAL_DMA_Abort_IT
+
- >> UART_EndTransmit_IT
+
- >> UART_EndRxTransfer
+
+
[Called By]- >> USART3_IRQHandler
+
- >> USART2_IRQHandler
+
- >> LPUART1_IRQHandler
+
+
+HAL_UART_Init (Thumb, 120 bytes, Stack size 8 bytes, stm32l4xx_hal_uart.o(i.HAL_UART_Init))
+
[Stack]
- Max Depth = 88
- Call Chain = HAL_UART_Init ⇒ HAL_UART_MspInit ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority
+
+
[Calls]- >> HAL_UART_MspInit
+
- >> UART_SetConfig
+
- >> UART_CheckIdleState
+
- >> UART_AdvFeatureConfig
+
+
[Called By]- >> MX_USART1_UART_Init
+
- >> MX_LPUART1_UART_Init
+
- >> MX_USART3_UART_Init
+
- >> MX_USART2_UART_Init
+
+
+HAL_UART_MspDeInit (Thumb, 114 bytes, Stack size 8 bytes, usart.o(i.HAL_UART_MspDeInit))
+
[Stack]
- Max Depth = 28
- Call Chain = HAL_UART_MspDeInit ⇒ HAL_GPIO_DeInit
+
+
[Calls]- >> HAL_NVIC_DisableIRQ
+
- >> HAL_GPIO_DeInit
+
+
[Called By]- >> HAL_UART_DeInit
+
- >> tos_hal_uart_deinit
+
+
+HAL_UART_MspInit (Thumb, 342 bytes, Stack size 32 bytes, usart.o(i.HAL_UART_MspInit))
+
[Stack]
- Max Depth = 80
- Call Chain = HAL_UART_MspInit ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority
+
+
[Calls]- >> HAL_NVIC_SetPriority
+
- >> HAL_NVIC_EnableIRQ
+
- >> HAL_GPIO_Init
+
- >> __aeabi_memclr4
+
+
[Called By]
+
+HAL_UART_Receive_IT (Thumb, 214 bytes, Stack size 8 bytes, stm32l4xx_hal_uart.o(i.HAL_UART_Receive_IT))
+
[Stack]
- Max Depth = 8
- Call Chain = HAL_UART_Receive_IT
+
+
[Called By]- >> MX_LPUART1_UART_Init
+
- >> HAL_UART_RxCpltCallback
+
+
+HAL_UART_RxCpltCallback (Thumb, 32 bytes, Stack size 8 bytes, stm32l4xx_it_module.o(i.HAL_UART_RxCpltCallback))
+
[Stack]
- Max Depth = 136 + Unknown Stack Size
+
- Call Chain = HAL_UART_RxCpltCallback ⇒ tos_at_uart_write_byte ⇒ tos_sem_post ⇒ sem_do_post ⇒ pend_wakeup ⇒ pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]- >> HAL_UART_Receive_IT
+
- >> tos_at_uart_write_byte
+
+
[Called By]- >> UART_RxISR_8BIT
+
- >> UART_RxISR_16BIT
+
+
+HAL_UART_Transmit (Thumb, 200 bytes, Stack size 32 bytes, stm32l4xx_hal_uart.o(i.HAL_UART_Transmit))
+
[Stack]
- Max Depth = 56
- Call Chain = HAL_UART_Transmit ⇒ UART_WaitOnFlagUntilTimeout
+
+
[Calls]- >> HAL_GetTick
+
- >> UART_WaitOnFlagUntilTimeout
+
+
[Called By]- >> fputc
+
- >> tos_hal_uart_write
+
+
+HAL_UART_TxCpltCallback (Thumb, 2 bytes, Stack size 0 bytes, stm32l4xx_hal_uart.o(i.HAL_UART_TxCpltCallback))
+
[Called By]
+
+HAL_UptimeMs (Thumb, 8 bytes, Stack size 8 bytes, osal_timer.o(i.HAL_UptimeMs))
+
[Stack]
- Max Depth = 32 + Unknown Stack Size
+
- Call Chain = HAL_UptimeMs ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save
+
+
[Calls]
+
[Called By]- >> utils_time_spend
+
- >> utils_time_is_expired
+
- >> utils_time_countdown_ms
+
- >> iotx_time_start
+
- >> iotx_time_left
+
+
+HAL_Vsnprintf (Thumb, 24 bytes, Stack size 32 bytes, osal_os.o(i.HAL_Vsnprintf))
+
[Stack]
- Max Depth = 56
- Call Chain = HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]
+
[Called By]
+
+HardFault_Handler (Thumb, 4 bytes, Stack size 0 bytes, stm32l4xx_it_module.o(i.HardFault_Handler))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+IIC_Start (Thumb, 48 bytes, Stack size 8 bytes, oled.o(i.IIC_Start))
+
[Stack]
- Max Depth = 8
- Call Chain = IIC_Start
+
+
[Calls]
+
[Called By]- >> Write_IIC_Data
+
- >> Write_IIC_Command
+
+
+IIC_Stop (Thumb, 36 bytes, Stack size 8 bytes, oled.o(i.IIC_Stop))
+
[Stack]
- Max Depth = 8
- Call Chain = IIC_Stop
+
+
[Calls]
+
[Called By]- >> Write_IIC_Data
+
- >> Write_IIC_Command
+
+
+IIC_Wait_Ack (Thumb, 28 bytes, Stack size 8 bytes, oled.o(i.IIC_Wait_Ack))
+
[Stack]
- Max Depth = 8
- Call Chain = IIC_Wait_Ack
+
+
[Calls]
+
[Called By]- >> Write_IIC_Data
+
- >> Write_IIC_Command
+
+
+IOT_Ioctl (Thumb, 312 bytes, Stack size 24 bytes, infra_compat.o(i.IOT_Ioctl))
+
[Stack]
- Max Depth = 32
- Call Chain = IOT_Ioctl ⇒ __aeabi_memcpy
+
+
[Calls]- >> strlen
+
- >> __aeabi_memclr4
+
- >> __aeabi_memclr
+
- >> __aeabi_memcpy
+
+
[Called By]
+
+IOT_MQTT_Construct (Thumb, 1534 bytes, Stack size 360 bytes, mqtt_api.o(i.IOT_MQTT_Construct))
+
[Stack]
- Max Depth = 1416 + Unknown Stack Size
+
- Call Chain = IOT_MQTT_Construct ⇒ IOT_Sign_MQTT ⇒ _iotx_generate_sign_string ⇒ utils_hmac_sha256 ⇒ utils_sha256_finish ⇒ utils_sha256_update ⇒ utils_sha256_process
+
+
[Calls]- >> HAL_GetProductKey
+
- >> HAL_GetDeviceSecret
+
- >> HAL_GetDeviceName
+
- >> wrapper_mqtt_release
+
- >> wrapper_mqtt_init
+
- >> wrapper_mqtt_connect
+
- >> iotx_event_callback
+
- >> _sign_get_clientid
+
- >> LITE_syslog
+
- >> IOT_Sign_MQTT
+
- >> IOT_Ioctl
+
- >> iotx_mqtt_report_funcs
+
- >> strlen
+
- >> strstr
+
- >> __aeabi_memclr4
+
- >> __aeabi_memcpy4
+
- >> __aeabi_memcpy
+
+
[Called By]
+
+IOT_MQTT_Destroy (Thumb, 66 bytes, Stack size 16 bytes, mqtt_api.o(i.IOT_MQTT_Destroy))
+
[Stack]
- Max Depth = 232 + Unknown Stack Size
+
- Call Chain = IOT_MQTT_Destroy ⇒ wrapper_mqtt_release ⇒ iotx_mc_disconnect ⇒ MQTTDisconnect ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> wrapper_mqtt_release
+
- >> LITE_syslog
+
+
[Called By]
+
+IOT_MQTT_Publish_Simple (Thumb, 154 bytes, Stack size 56 bytes, mqtt_api.o(i.IOT_MQTT_Publish_Simple))
+
[Stack]
- Max Depth = 336 + Unknown Stack Size
+
- Call Chain = IOT_MQTT_Publish_Simple ⇒ wrapper_mqtt_publish ⇒ iotx_mc_check_topic ⇒ iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> wrapper_mqtt_publish
+
- >> LITE_syslog
+
- >> strlen
+
- >> __aeabi_memclr4
+
+
[Called By]
+
[Address Reference Count : 1]- mqtt_api.o(i.iotx_mqtt_report_funcs)
+
+IOT_MQTT_Subscribe (Thumb, 144 bytes, Stack size 48 bytes, mqtt_api.o(i.IOT_MQTT_Subscribe))
+
[Stack]
- Max Depth = 352 + Unknown Stack Size
+
- Call Chain = IOT_MQTT_Subscribe ⇒ wrapper_mqtt_subscribe ⇒ iotx_mc_check_topic ⇒ iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> wrapper_mqtt_subscribe
+
- >> LITE_syslog
+
- >> iotx_mqtt_offline_subscribe
+
- >> strlen
+
+
[Called By]
+
+IOT_MQTT_Yield (Thumb, 28 bytes, Stack size 16 bytes, mqtt_api.o(i.IOT_MQTT_Yield))
+
[Stack]
- Max Depth = 968 + Unknown Stack Size
+
- Call Chain = IOT_MQTT_Yield ⇒ wrapper_mqtt_yield ⇒ iotx_mc_keepalive ⇒ iotx_mc_handle_reconnect ⇒ iotx_mc_attempt_reconnect ⇒ wrapper_mqtt_connect ⇒ _mqtt_connect ⇒ iotx_mc_wait_CONNACK ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]
+
[Called By]
+
+IOT_Sign_MQTT (Thumb, 498 bytes, Stack size 96 bytes, dev_sign_mqtt.o(i.IOT_Sign_MQTT))
+
[Stack]
- Max Depth = 1056
- Call Chain = IOT_Sign_MQTT ⇒ _iotx_generate_sign_string ⇒ utils_hmac_sha256 ⇒ utils_sha256_finish ⇒ utils_sha256_update ⇒ utils_sha256_process
+
+
[Calls]- >> _sign_get_clientid
+
- >> _iotx_generate_sign_string
+
- >> strlen
+
- >> __aeabi_memclr4
+
- >> __aeabi_memclr
+
- >> __aeabi_memcpy
+
+
[Called By]
+
+LITE_get_loglevel (Thumb, 6 bytes, Stack size 0 bytes, infra_log.o(i.LITE_get_loglevel))
+
[Called By]
+
+LITE_syslog (Thumb, 40 bytes, Stack size 32 bytes, infra_log.o(i.LITE_syslog))
+
[Stack]
- Max Depth = 128
- Call Chain = LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]
+
[Called By]- >> IOT_MQTT_Subscribe
+
- >> IOT_MQTT_Publish_Simple
+
- >> IOT_MQTT_Destroy
+
- >> IOT_MQTT_Construct
+
- >> iotx_mc_wait_CONNACK
+
- >> iotx_mc_set_connect_params
+
- >> iotx_mc_read_packet
+
- >> iotx_mc_push_pubInfo_to
+
- >> iotx_mc_keepalive_sub
+
- >> iotx_mc_keepalive
+
- >> iotx_mc_init
+
- >> iotx_mc_handle_recv_SUBACK
+
- >> iotx_mc_handle_recv_PUBLISH
+
- >> iotx_mc_handle_recv_CONNACK
+
- >> iotx_mc_handle_reconnect
+
- >> iotx_mc_disconnect
+
- >> iotx_mc_deliver_message
+
- >> iotx_mc_cycle
+
- >> iotx_mc_check_topic
+
- >> iotx_mc_check_rule
+
- >> iotx_mc_attempt_reconnect
+
- >> _mqtt_connect
+
- >> _iotx_mqtt_event_handle_sub
+
- >> MQTTSubscribe
+
- >> MQTTKeepalive
+
- >> wrapper_mqtt_yield
+
- >> wrapper_mqtt_subscribe
+
- >> wrapper_mqtt_release
+
- >> wrapper_mqtt_publish
+
- >> wrapper_mqtt_init
+
- >> wrapper_mqtt_connect
+
- >> iotx_report_firmware_version
+
- >> iotx_report_devinfo
+
- >> iotx_mqtt_report_funcs
+
- >> utils_net_write
+
- >> utils_net_read
+
- >> iotx_net_disconnect
+
- >> iotx_net_connect
+
- >> disconnect_tcp
+
- >> connect_tcp
+
- >> iotx_net_init
+
- >> _mqtt_cycle
+
- >> MQTTPublish
+
- >> MQTTConnect
+
+
+LITE_syslog_routine (Thumb, 182 bytes, Stack size 40 bytes, infra_log.o(i.LITE_syslog_routine))
+
[Stack]
- Max Depth = 96
- Call Chain = LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> HAL_Printf
+
- >> HAL_Vsnprintf
+
- >> LITE_get_loglevel
+
- >> strlen
+
- >> __aeabi_memclr
+
+
[Called By]
+
+LPUART1_IRQHandler (Thumb, 18 bytes, Stack size 8 bytes, stm32l4xx_it_module.o(i.LPUART1_IRQHandler))
+
[Stack]
- Max Depth = 48 + Unknown Stack Size
+
- Call Chain = LPUART1_IRQHandler ⇒ HAL_UART_IRQHandler ⇒ HAL_DMA_Abort_IT
+
+
[Calls]- >> tos_knl_irq_leave
+
- >> tos_knl_irq_enter
+
- >> HAL_UART_IRQHandler
+
+
[Address Reference Count : 1]- startup_stm32l431xx.o(RESET)
+
+MQTTConnect (Thumb, 208 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.MQTTConnect))
+
[Stack]
- Max Depth = 184 + Unknown Stack Size
+
- Call Chain = MQTTConnect ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_send_packet
+
- >> _reset_send_buffer
+
- >> _get_connect_length
+
- >> _alloc_send_buffer
+
- >> LITE_syslog
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
- >> utils_time_countdown_ms
+
- >> iotx_time_init
+
- >> MQTTSerialize_connect
+
+
[Called By]
+
+MQTTDeserialize_ack (Thumb, 108 bytes, Stack size 48 bytes, mqttdeserializepublish.o(i.MQTTDeserialize_ack))
+
[Stack]
- Max Depth = 96
- Call Chain = MQTTDeserialize_ack ⇒ MQTTPacket_decodeBuf ⇒ MQTTPacket_decode
+
+
[Calls]- >> readInt
+
- >> readChar
+
- >> MQTTPacket_decodeBuf
+
+
[Called By]- >> iotx_mc_handle_recv_PUBACK
+
- >> MQTTDeserialize_unsuback
+
+
+MQTTDeserialize_connack (Thumb, 118 bytes, Stack size 48 bytes, mqttconnectclient.o(i.MQTTDeserialize_connack))
+
[Stack]
- Max Depth = 96
- Call Chain = MQTTDeserialize_connack ⇒ MQTTPacket_decodeBuf ⇒ MQTTPacket_decode
+
+
[Calls]- >> readChar
+
- >> MQTTPacket_decodeBuf
+
+
[Called By]- >> iotx_mc_handle_recv_CONNACK
+
+
+MQTTDeserialize_publish (Thumb, 174 bytes, Stack size 56 bytes, mqttdeserializepublish.o(i.MQTTDeserialize_publish))
+
[Stack]
- Max Depth = 104
- Call Chain = MQTTDeserialize_publish ⇒ MQTTPacket_decodeBuf ⇒ MQTTPacket_decode
+
+
[Calls]- >> readMQTTLenString
+
- >> readInt
+
- >> readChar
+
- >> MQTTPacket_decodeBuf
+
+
[Called By]- >> iotx_mc_handle_recv_PUBLISH
+
+
+MQTTDeserialize_suback (Thumb, 146 bytes, Stack size 48 bytes, mqttsubscribeclient.o(i.MQTTDeserialize_suback))
+
[Stack]
- Max Depth = 96
- Call Chain = MQTTDeserialize_suback ⇒ MQTTPacket_decodeBuf ⇒ MQTTPacket_decode
+
+
[Calls]- >> readInt
+
- >> readChar
+
- >> MQTTPacket_decodeBuf
+
+
[Called By]- >> iotx_mc_handle_recv_SUBACK
+
+
+MQTTDeserialize_unsuback (Thumb, 46 bytes, Stack size 32 bytes, mqttunsubscribeclient.o(i.MQTTDeserialize_unsuback))
+
[Stack]
- Max Depth = 128
- Call Chain = MQTTDeserialize_unsuback ⇒ MQTTDeserialize_ack ⇒ MQTTPacket_decodeBuf ⇒ MQTTPacket_decode
+
+
[Calls]
+
[Called By]- >> iotx_mc_handle_recv_UNSUBACK
+
+
+MQTTPacket_decode (Thumb, 88 bytes, Stack size 32 bytes, mqttpacket.o(i.MQTTPacket_decode))
+
[Stack]
- Max Depth = 32
- Call Chain = MQTTPacket_decode
+
+
[Called By]- >> MQTTPacket_decodeBuf
+
+
+MQTTPacket_decodeBuf (Thumb, 20 bytes, Stack size 16 bytes, mqttpacket.o(i.MQTTPacket_decodeBuf))
+
[Stack]
- Max Depth = 48
- Call Chain = MQTTPacket_decodeBuf ⇒ MQTTPacket_decode
+
+
[Calls]
+
[Called By]- >> MQTTDeserialize_suback
+
- >> MQTTDeserialize_publish
+
- >> MQTTDeserialize_connack
+
- >> MQTTDeserialize_ack
+
+
+MQTTPacket_encode (Thumb, 54 bytes, Stack size 12 bytes, mqttpacket.o(i.MQTTPacket_encode))
+
[Stack]
- Max Depth = 12
- Call Chain = MQTTPacket_encode
+
+
[Called By]- >> iotx_mc_read_packet
+
- >> MQTTSerialize_zero
+
- >> MQTTSerialize_subscribe
+
- >> MQTTSerialize_publish
+
- >> MQTTSerialize_connect
+
- >> MQTTSerialize_ack
+
+
+MQTTPacket_equals (Thumb, 66 bytes, Stack size 24 bytes, mqttpacket.o(i.MQTTPacket_equals))
+
[Stack]
- Max Depth = 36
- Call Chain = MQTTPacket_equals ⇒ memcmp
+
+
[Calls]
+
[Called By]- >> iotx_mc_deliver_message
+
+
+MQTTPacket_len (Thumb, 34 bytes, Stack size 0 bytes, mqttpacket.o(i.MQTTPacket_len))
+
[Called By]
- >> MQTTSerialize_subscribe
+
- >> MQTTSerialize_publish
+
- >> MQTTSerialize_connect
+
+
+MQTTPublish (Thumb, 398 bytes, Stack size 72 bytes, iotx_mqtt_client.o(i.MQTTPublish))
+
[Stack]
- Max Depth = 240 + Unknown Stack Size
+
- Call Chain = MQTTPublish ⇒ iotx_mc_push_pubInfo_to ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> iotx_mc_send_packet
+
- >> iotx_mc_push_pubInfo_to
+
- >> _reset_send_buffer
+
- >> _alloc_send_buffer
+
- >> LITE_syslog
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
- >> utils_time_countdown_ms
+
- >> iotx_time_init
+
- >> MQTTSerialize_publish
+
- >> strlen
+
- >> __aeabi_memclr4
+
+
[Called By]- >> wrapper_mqtt_publish
+
+
+MQTTSerialize_ack (Thumb, 144 bytes, Stack size 40 bytes, mqttserializepublish.o(i.MQTTSerialize_ack))
+
[Stack]
- Max Depth = 52
- Call Chain = MQTTSerialize_ack ⇒ MQTTPacket_encode
+
+
[Calls]- >> writeInt
+
- >> writeChar
+
- >> MQTTPacket_encode
+
+
[Called By]
+
+MQTTSerialize_connect (Thumb, 370 bytes, Stack size 40 bytes, mqttconnectclient.o(i.MQTTSerialize_connect))
+
[Stack]
- Max Depth = 88
- Call Chain = MQTTSerialize_connect ⇒ writeMQTTString ⇒ writeCString ⇒ writeInt
+
+
[Calls]- >> writeMQTTString
+
- >> writeInt
+
- >> writeChar
+
- >> writeCString
+
- >> MQTTPacket_len
+
- >> MQTTSerialize_connectLength
+
- >> MQTTPacket_encode
+
+
[Called By]
+
+MQTTSerialize_connectLength (Thumb, 118 bytes, Stack size 16 bytes, mqttconnectclient.o(i.MQTTSerialize_connectLength))
+
[Stack]
- Max Depth = 40
- Call Chain = MQTTSerialize_connectLength ⇒ MQTTstrlen
+
+
[Calls]
+
[Called By]- >> MQTTSerialize_connect
+
+
+MQTTSerialize_disconnect (Thumb, 18 bytes, Stack size 16 bytes, mqttconnectclient.o(i.MQTTSerialize_disconnect))
+
[Stack]
- Max Depth = 60
- Call Chain = MQTTSerialize_disconnect ⇒ MQTTSerialize_zero ⇒ MQTTPacket_encode
+
+
[Calls]
+
[Called By]
+
+MQTTSerialize_pingreq (Thumb, 18 bytes, Stack size 16 bytes, mqttconnectclient.o(i.MQTTSerialize_pingreq))
+
[Stack]
- Max Depth = 60
- Call Chain = MQTTSerialize_pingreq ⇒ MQTTSerialize_zero ⇒ MQTTPacket_encode
+
+
[Calls]
+
[Called By]
+
+MQTTSerialize_publish (Thumb, 208 bytes, Stack size 64 bytes, mqttserializepublish.o(i.MQTTSerialize_publish))
+
[Stack]
- Max Depth = 120
- Call Chain = MQTTSerialize_publish ⇒ MQTTSerialize_publishLength ⇒ MQTTstrlen
+
+
[Calls]- >> MQTTSerialize_publishLength
+
- >> writeMQTTString
+
- >> writeInt
+
- >> writeChar
+
- >> MQTTPacket_len
+
- >> MQTTPacket_encode
+
- >> __aeabi_memcpy
+
+
[Called By]
+
+MQTTSerialize_publishLength (Thumb, 34 bytes, Stack size 32 bytes, mqttserializepublish.o(i.MQTTSerialize_publishLength))
+
[Stack]
- Max Depth = 56
- Call Chain = MQTTSerialize_publishLength ⇒ MQTTstrlen
+
+
[Calls]
+
[Called By]- >> MQTTSerialize_publish
+
+
+MQTTSerialize_subscribe (Thumb, 192 bytes, Stack size 56 bytes, mqttsubscribeclient.o(i.MQTTSerialize_subscribe))
+
[Stack]
- Max Depth = 104
- Call Chain = MQTTSerialize_subscribe ⇒ MQTTSerialize_subscribeLength ⇒ MQTTstrlen
+
+
[Calls]- >> MQTTSerialize_subscribeLength
+
- >> writeMQTTString
+
- >> writeInt
+
- >> writeChar
+
- >> MQTTPacket_len
+
- >> MQTTPacket_encode
+
+
[Called By]
+
+MQTTSerialize_subscribeLength (Thumb, 46 bytes, Stack size 24 bytes, mqttsubscribeclient.o(i.MQTTSerialize_subscribeLength))
+
[Stack]
- Max Depth = 48
- Call Chain = MQTTSerialize_subscribeLength ⇒ MQTTstrlen
+
+
[Calls]
+
[Called By]- >> MQTTSerialize_subscribe
+
+
+MQTTSerialize_zero (Thumb, 84 bytes, Stack size 32 bytes, mqttconnectclient.o(i.MQTTSerialize_zero))
+
[Stack]
- Max Depth = 44
- Call Chain = MQTTSerialize_zero ⇒ MQTTPacket_encode
+
+
[Calls]- >> writeChar
+
- >> MQTTPacket_encode
+
+
[Called By]- >> MQTTSerialize_pingreq
+
- >> MQTTSerialize_disconnect
+
+
+MQTTstrlen (Thumb, 24 bytes, Stack size 24 bytes, mqttpacket.o(i.MQTTstrlen))
+
[Stack]
- Max Depth = 24
- Call Chain = MQTTstrlen
+
+
[Calls]
+
[Called By]- >> MQTTSerialize_subscribeLength
+
- >> MQTTSerialize_publishLength
+
- >> MQTTSerialize_connectLength
+
+
+MX_GPIO_Init (Thumb, 316 bytes, Stack size 32 bytes, gpio.o(i.MX_GPIO_Init))
+
[Stack]
- Max Depth = 80
- Call Chain = MX_GPIO_Init ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority
+
+
[Calls]- >> HAL_NVIC_SetPriority
+
- >> HAL_NVIC_EnableIRQ
+
- >> HAL_GPIO_WritePin
+
- >> HAL_GPIO_Init
+
- >> __aeabi_memclr4
+
+
[Called By]
+
+MX_LPUART1_UART_Init (Thumb, 64 bytes, Stack size 8 bytes, usart.o(i.MX_LPUART1_UART_Init))
+
[Stack]
- Max Depth = 96
- Call Chain = MX_LPUART1_UART_Init ⇒ HAL_UART_Init ⇒ HAL_UART_MspInit ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority
+
+
[Calls]- >> HAL_UART_Receive_IT
+
- >> HAL_UART_Init
+
- >> Error_Handler
+
+
[Called By]
+
+MX_USART1_UART_Init (Thumb, 56 bytes, Stack size 8 bytes, usart.o(i.MX_USART1_UART_Init))
+
[Stack]
- Max Depth = 96
- Call Chain = MX_USART1_UART_Init ⇒ HAL_UART_Init ⇒ HAL_UART_MspInit ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority
+
+
[Calls]- >> HAL_UART_Init
+
- >> Error_Handler
+
+
[Called By]
+
+MX_USART2_UART_Init (Thumb, 56 bytes, Stack size 8 bytes, usart.o(i.MX_USART2_UART_Init))
+
[Stack]
- Max Depth = 96
- Call Chain = MX_USART2_UART_Init ⇒ HAL_UART_Init ⇒ HAL_UART_MspInit ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority
+
+
[Calls]- >> HAL_UART_Init
+
- >> Error_Handler
+
+
[Called By]- >> board_init
+
- >> tos_hal_uart_init
+
+
+MX_USART3_UART_Init (Thumb, 56 bytes, Stack size 8 bytes, usart.o(i.MX_USART3_UART_Init))
+
[Stack]
- Max Depth = 96
- Call Chain = MX_USART3_UART_Init ⇒ HAL_UART_Init ⇒ HAL_UART_MspInit ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority
+
+
[Calls]- >> HAL_UART_Init
+
- >> Error_Handler
+
+
[Called By]- >> board_init
+
- >> tos_hal_uart_init
+
+
+MemManage_Handler (Thumb, 4 bytes, Stack size 0 bytes, stm32l4xx_it_module.o(i.MemManage_Handler))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+NMI_Handler (Thumb, 2 bytes, Stack size 0 bytes, stm32l4xx_it_module.o(i.NMI_Handler))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+OLED_Clear (Thumb, 62 bytes, Stack size 16 bytes, oled.o(i.OLED_Clear))
+
[Stack]
- Max Depth = 64
- Call Chain = OLED_Clear ⇒ OLED_WR_Byte ⇒ Write_IIC_Data ⇒ Write_IIC_Byte
+
+
[Calls]
+
[Called By]- >> OLED_Init
+
- >> board_init
+
+
+OLED_Init (Thumb, 198 bytes, Stack size 8 bytes, oled.o(i.OLED_Init))
+
[Stack]
- Max Depth = 72
- Call Chain = OLED_Init ⇒ OLED_Clear ⇒ OLED_WR_Byte ⇒ Write_IIC_Data ⇒ Write_IIC_Byte
+
+
[Calls]- >> OLED_Clear
+
- >> HAL_Delay
+
- >> OLED_WR_Byte
+
+
[Called By]
+
+OLED_Set_Pos (Thumb, 40 bytes, Stack size 16 bytes, oled.o(i.OLED_Set_Pos))
+
[Stack]
- Max Depth = 64
- Call Chain = OLED_Set_Pos ⇒ OLED_WR_Byte ⇒ Write_IIC_Data ⇒ Write_IIC_Byte
+
+
[Calls]
+
[Called By]- >> OLED_ShowChinese
+
- >> OLED_ShowChar
+
+
+OLED_ShowChar (Thumb, 154 bytes, Stack size 32 bytes, oled.o(i.OLED_ShowChar))
+
[Stack]
- Max Depth = 96
- Call Chain = OLED_ShowChar ⇒ OLED_Set_Pos ⇒ OLED_WR_Byte ⇒ Write_IIC_Data ⇒ Write_IIC_Byte
+
+
[Calls]- >> OLED_WR_Byte
+
- >> OLED_Set_Pos
+
+
[Called By]
+
+OLED_ShowChinese (Thumb, 98 bytes, Stack size 24 bytes, oled.o(i.OLED_ShowChinese))
+
[Stack]
- Max Depth = 88
- Call Chain = OLED_ShowChinese ⇒ OLED_Set_Pos ⇒ OLED_WR_Byte ⇒ Write_IIC_Data ⇒ Write_IIC_Byte
+
+
[Calls]- >> OLED_WR_Byte
+
- >> OLED_Set_Pos
+
+
[Called By]
+
+OLED_ShowString (Thumb, 58 bytes, Stack size 24 bytes, oled.o(i.OLED_ShowString))
+
[Stack]
- Max Depth = 120
- Call Chain = OLED_ShowString ⇒ OLED_ShowChar ⇒ OLED_Set_Pos ⇒ OLED_WR_Byte ⇒ Write_IIC_Data ⇒ Write_IIC_Byte
+
+
[Calls]
+
[Called By]
+
+OLED_WR_Byte (Thumb, 24 bytes, Stack size 16 bytes, oled.o(i.OLED_WR_Byte))
+
[Stack]
- Max Depth = 48
- Call Chain = OLED_WR_Byte ⇒ Write_IIC_Data ⇒ Write_IIC_Byte
+
+
[Calls]- >> Write_IIC_Data
+
- >> Write_IIC_Command
+
+
[Called By]- >> OLED_ShowChinese
+
- >> OLED_Init
+
- >> OLED_Clear
+
- >> OLED_ShowChar
+
- >> OLED_Set_Pos
+
+
+SVC_Handler (Thumb, 2 bytes, Stack size 0 bytes, stm32l4xx_it_module.o(i.SVC_Handler))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+SysTick_Handler (Thumb, 26 bytes, Stack size 8 bytes, stm32l4xx_it_module.o(i.SysTick_Handler))
+
[Stack]
- Max Depth = 104 + Unknown Stack Size
+
- Call Chain = SysTick_Handler ⇒ tos_tick_handler ⇒ tick_update ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]- >> tos_tick_handler
+
- >> tos_knl_is_running
+
- >> tos_knl_irq_leave
+
- >> tos_knl_irq_enter
+
- >> HAL_IncTick
+
+
[Address Reference Count : 1]- startup_stm32l431xx.o(RESET)
+
+SystemClock_Config (Thumb, 214 bytes, Stack size 184 bytes, mcu_init.o(i.SystemClock_Config))
+
[Stack]
- Max Depth = 280
- Call Chain = SystemClock_Config ⇒ HAL_RCC_OscConfig ⇒ HAL_InitTick ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority
+
+
[Calls]- >> HAL_RCC_OscConfig
+
- >> HAL_RCC_ClockConfig
+
- >> HAL_RCCEx_PeriphCLKConfig
+
- >> HAL_RCCEx_EnableMSIPLLMode
+
- >> HAL_PWR_EnableBkUpAccess
+
- >> HAL_PWREx_ControlVoltageScaling
+
- >> Error_Handler
+
- >> __aeabi_memclr4
+
+
[Called By]
+
+SystemInit (Thumb, 68 bytes, Stack size 0 bytes, system_stm32l4xx.o(i.SystemInit))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(.text)
+
+UART_AdvFeatureConfig (Thumb, 248 bytes, Stack size 0 bytes, stm32l4xx_hal_uart.o(i.UART_AdvFeatureConfig))
+
[Called By]
+
+UART_CheckIdleState (Thumb, 116 bytes, Stack size 16 bytes, stm32l4xx_hal_uart.o(i.UART_CheckIdleState))
+
[Stack]
- Max Depth = 40
- Call Chain = UART_CheckIdleState ⇒ UART_WaitOnFlagUntilTimeout
+
+
[Calls]- >> HAL_GetTick
+
- >> UART_WaitOnFlagUntilTimeout
+
+
[Called By]
+
+UART_SetConfig (Thumb, 1000 bytes, Stack size 40 bytes, stm32l4xx_hal_uart.o(i.UART_SetConfig))
+
[Stack]
- Max Depth = 80
- Call Chain = UART_SetConfig ⇒ __aeabi_uldivmod
+
+
[Calls]- >> HAL_RCC_GetSysClockFreq
+
- >> HAL_RCC_GetPCLK2Freq
+
- >> HAL_RCC_GetPCLK1Freq
+
- >> __aeabi_uldivmod
+
+
[Called By]
+
+UART_WaitOnFlagUntilTimeout (Thumb, 108 bytes, Stack size 24 bytes, stm32l4xx_hal_uart.o(i.UART_WaitOnFlagUntilTimeout))
+
[Stack]
- Max Depth = 24
- Call Chain = UART_WaitOnFlagUntilTimeout
+
+
[Calls]
+
[Called By]- >> HAL_UART_Transmit
+
- >> UART_CheckIdleState
+
+
+USART2_IRQHandler (Thumb, 10 bytes, Stack size 8 bytes, stm32l4xx_it_module.o(i.USART2_IRQHandler))
+
[Stack]
- Max Depth = 48
- Call Chain = USART2_IRQHandler ⇒ HAL_UART_IRQHandler ⇒ HAL_DMA_Abort_IT
+
+
[Calls]
+
[Address Reference Count : 1]- startup_stm32l431xx.o(RESET)
+
+USART3_IRQHandler (Thumb, 10 bytes, Stack size 8 bytes, stm32l4xx_it_module.o(i.USART3_IRQHandler))
+
[Stack]
- Max Depth = 48
- Call Chain = USART3_IRQHandler ⇒ HAL_UART_IRQHandler ⇒ HAL_DMA_Abort_IT
+
+
[Calls]
+
[Address Reference Count : 1]- startup_stm32l431xx.o(RESET)
+
+UsageFault_Handler (Thumb, 4 bytes, Stack size 0 bytes, stm32l4xx_it_module.o(i.UsageFault_Handler))
+
[Address Reference Count : 1]
- startup_stm32l431xx.o(RESET)
+
+Write_IIC_Byte (Thumb, 96 bytes, Stack size 24 bytes, oled.o(i.Write_IIC_Byte))
+
[Stack]
- Max Depth = 24
- Call Chain = Write_IIC_Byte
+
+
[Calls]
+
[Called By]- >> Write_IIC_Data
+
- >> Write_IIC_Command
+
+
+Write_IIC_Command (Thumb, 44 bytes, Stack size 8 bytes, oled.o(i.Write_IIC_Command))
+
[Stack]
- Max Depth = 32
- Call Chain = Write_IIC_Command ⇒ Write_IIC_Byte
+
+
[Calls]- >> Write_IIC_Byte
+
- >> IIC_Wait_Ack
+
- >> IIC_Stop
+
- >> IIC_Start
+
+
[Called By]
+
+Write_IIC_Data (Thumb, 44 bytes, Stack size 8 bytes, oled.o(i.Write_IIC_Data))
+
[Stack]
- Max Depth = 32
- Call Chain = Write_IIC_Data ⇒ Write_IIC_Byte
+
+
[Calls]- >> Write_IIC_Byte
+
- >> IIC_Wait_Ack
+
- >> IIC_Stop
+
- >> IIC_Start
+
+
[Called By]
+
+__0printf (Thumb, 22 bytes, Stack size 24 bytes, printfa.o(i.__0printf), UNUSED)
+
[Calls]
+
+__1printf (Thumb, 0 bytes, Stack size 24 bytes, printfa.o(i.__0printf), UNUSED)
+
+
__2printf (Thumb, 0 bytes, Stack size 24 bytes, printfa.o(i.__0printf))
+
[Stack]
- Max Depth = 24
- Call Chain = __2printf
+
+
[Called By]- >> main
+
- >> application_entry
+
- >> at_parser
+
- >> at_cmd_do_exec
+
- >> esp8266_reconnect_init
+
- >> esp8266_parse_domain
+
- >> esp8266_init
+
- >> HAL_TCP_Establish
+
+
+__c89printf (Thumb, 0 bytes, Stack size 24 bytes, printfa.o(i.__0printf), UNUSED)
+
+
printf (Thumb, 0 bytes, Stack size 24 bytes, printfa.o(i.__0printf), UNUSED)
+
+
__0snprintf (Thumb, 44 bytes, Stack size 32 bytes, printfa.o(i.__0snprintf), UNUSED)
+
[Calls]
+
+__1snprintf (Thumb, 0 bytes, Stack size 32 bytes, printfa.o(i.__0snprintf), UNUSED)
+
+
__2snprintf (Thumb, 0 bytes, Stack size 32 bytes, printfa.o(i.__0snprintf))
+
[Stack]
- Max Depth = 32
- Call Chain = __2snprintf
+
+
[Called By]
+
+__c89snprintf (Thumb, 0 bytes, Stack size 32 bytes, printfa.o(i.__0snprintf), UNUSED)
+
+
snprintf (Thumb, 0 bytes, Stack size 32 bytes, printfa.o(i.__0snprintf), UNUSED)
+
+
__0vprintf (Thumb, 8 bytes, Stack size 0 bytes, printfa.o(i.__0vprintf), UNUSED)
+
[Calls]
+
+__1vprintf (Thumb, 0 bytes, Stack size 0 bytes, printfa.o(i.__0vprintf), UNUSED)
+
+
__2vprintf (Thumb, 0 bytes, Stack size 0 bytes, printfa.o(i.__0vprintf), UNUSED)
+
+
__c89vprintf (Thumb, 0 bytes, Stack size 0 bytes, printfa.o(i.__0vprintf), UNUSED)
+
+
vprintf (Thumb, 0 bytes, Stack size 0 bytes, printfa.o(i.__0vprintf))
+
[Called By]
+
+__0vsnprintf (Thumb, 40 bytes, Stack size 24 bytes, printfa.o(i.__0vsnprintf), UNUSED)
+
[Calls]
+
+__1vsnprintf (Thumb, 0 bytes, Stack size 24 bytes, printfa.o(i.__0vsnprintf), UNUSED)
+
+
__2vsnprintf (Thumb, 0 bytes, Stack size 24 bytes, printfa.o(i.__0vsnprintf), UNUSED)
+
+
__c89vsnprintf (Thumb, 0 bytes, Stack size 24 bytes, printfa.o(i.__0vsnprintf), UNUSED)
+
+
vsnprintf (Thumb, 0 bytes, Stack size 24 bytes, printfa.o(i.__0vsnprintf))
+
[Stack]
- Max Depth = 24
- Call Chain = vsnprintf
+
+
[Called By]- >> HAL_Snprintf
+
- >> at_cmd_do_exec
+
- >> HAL_Vsnprintf
+
+
+__scatterload_copy (Thumb, 14 bytes, Stack size unknown bytes, handlers.o(i.__scatterload_copy), UNUSED)
+
+
__scatterload_null (Thumb, 2 bytes, Stack size unknown bytes, handlers.o(i.__scatterload_null), UNUSED)
+
+
__scatterload_zeroinit (Thumb, 14 bytes, Stack size unknown bytes, handlers.o(i.__scatterload_zeroinit), UNUSED)
+
+
_iotx_generate_sign_string (Thumb, 340 bytes, Stack size 320 bytes, dev_sign_mqtt.o(i._iotx_generate_sign_string))
+
[Stack]
- Max Depth = 960
- Call Chain = _iotx_generate_sign_string ⇒ utils_hmac_sha256 ⇒ utils_sha256_finish ⇒ utils_sha256_update ⇒ utils_sha256_process
+
+
[Calls]- >> utils_hmac_sha256
+
- >> _hex2str
+
- >> strlen
+
- >> __aeabi_memclr4
+
- >> __aeabi_memcpy4
+
- >> __aeabi_memcpy
+
+
[Called By]
+
+_mqtt_cycle (Thumb, 122 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i._mqtt_cycle))
+
[Stack]
- Max Depth = 784 + Unknown Stack Size
+
- Call Chain = _mqtt_cycle ⇒ iotx_mc_cycle ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_cycle
+
- >> MQTTPubInfoProc
+
- >> LITE_syslog
+
- >> HAL_SleepMs
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
- >> utils_time_is_expired
+
- >> utils_time_countdown_ms
+
- >> iotx_time_left
+
- >> iotx_time_init
+
+
[Called By]
+
+_sign_get_clientid (Thumb, 330 bytes, Stack size 32 bytes, dev_sign_mqtt.o(i._sign_get_clientid))
+
[Stack]
- Max Depth = 40
- Call Chain = _sign_get_clientid ⇒ __aeabi_memcpy
+
+
[Calls]- >> strlen
+
- >> __aeabi_memclr
+
- >> __aeabi_memcpy
+
+
[Called By]- >> IOT_MQTT_Construct
+
- >> IOT_Sign_MQTT
+
+
+application_entry (Thumb, 38 bytes, Stack size 0 bytes, aliyun_iotkit_csdk_mqtt.o(i.application_entry))
+
[Stack]
- Max Depth = 1496 + Unknown Stack Size
+
- Call Chain = application_entry ⇒ mqtt_basic_thread ⇒ IOT_MQTT_Construct ⇒ IOT_Sign_MQTT ⇒ _iotx_generate_sign_string ⇒ utils_hmac_sha256 ⇒ utils_sha256_finish ⇒ utils_sha256_update ⇒ utils_sha256_process
+
+
[Calls]- >> tos_task_delay
+
- >> esp8266_sal_init
+
- >> esp8266_join_ap
+
- >> mqtt_basic_thread
+
- >> __2printf
+
+
[Address Reference Count : 1]
+at_delay (Thumb, 38 bytes, Stack size 24 bytes, tos_at_utils.o(i.at_delay))
+
[Stack]
- Max Depth = 48 + Unknown Stack Size
+
- Call Chain = at_delay ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save
+
+
[Calls]
+
[Called By]
+
+at_timer_countdown (Thumb, 30 bytes, Stack size 16 bytes, tos_at_utils.o(i.at_timer_countdown))
+
[Stack]
- Max Depth = 40 + Unknown Stack Size
+
- Call Chain = at_timer_countdown ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save
+
+
[Calls]
+
[Called By]- >> tos_at_channel_read_timed
+
+
+at_timer_init (Thumb, 14 bytes, Stack size 0 bytes, tos_at_utils.o(i.at_timer_init))
+
[Called By]
+
+at_timer_is_expired (Thumb, 40 bytes, Stack size 16 bytes, tos_at_utils.o(i.at_timer_is_expired))
+
[Stack]
- Max Depth = 40 + Unknown Stack Size
+
- Call Chain = at_timer_is_expired ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save
+
+
[Calls]
+
[Called By]- >> at_timer_remain
+
- >> tos_at_channel_read_timed
+
+
+at_timer_remain (Thumb, 40 bytes, Stack size 16 bytes, tos_at_utils.o(i.at_timer_remain))
+
[Stack]
- Max Depth = 56 + Unknown Stack Size
+
- Call Chain = at_timer_remain ⇒ at_timer_is_expired ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_systick_get
+
- >> at_timer_is_expired
+
+
[Called By]- >> tos_at_channel_read_timed
+
+
+board_init (Thumb, 110 bytes, Stack size 8 bytes, mcu_init.o(i.board_init))
+
[Stack]
- Max Depth = 288
- Call Chain = board_init ⇒ SystemClock_Config ⇒ HAL_RCC_OscConfig ⇒ HAL_InitTick ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority
+
+
[Calls]- >> OLED_ShowString
+
- >> OLED_ShowChinese
+
- >> OLED_Init
+
- >> OLED_Clear
+
- >> MX_USART3_UART_Init
+
- >> MX_USART2_UART_Init
+
- >> HAL_Init
+
- >> DHT11_Init
+
- >> SystemClock_Config
+
- >> MX_GPIO_Init
+
+
[Called By]
+
+bufchar (Thumb, 36 bytes, Stack size 8 bytes, mqttpacket.o(i.bufchar))
+
[Stack]
- Max Depth = 8
- Call Chain = bufchar
+
+
[Address Reference Count : 1]- mqttpacket.o(i.MQTTPacket_decodeBuf)
+
+cpu_context_switch (Thumb, 8 bytes, Stack size 8 bytes, tos_cpu.o(i.cpu_context_switch))
+
[Stack]
- Max Depth = 8 + Unknown Stack Size
+
- Call Chain = cpu_context_switch
+
+
[Calls]
+
[Called By]
+
+cpu_init (Thumb, 30 bytes, Stack size 8 bytes, tos_cpu.o(i.cpu_init))
+
[Stack]
- Max Depth = 48
- Call Chain = cpu_init ⇒ __aeabi_uldivmod
+
+
[Calls]- >> cpu_systick_init
+
- >> __aeabi_uldivmod
+
+
[Called By]
+
+cpu_irq_context_switch (Thumb, 8 bytes, Stack size 8 bytes, tos_cpu.o(i.cpu_irq_context_switch))
+
[Stack]
- Max Depth = 8 + Unknown Stack Size
+
- Call Chain = cpu_irq_context_switch
+
+
[Calls]- >> port_irq_context_switch
+
+
[Called By]
+
+cpu_sched_start (Thumb, 4 bytes, Stack size 0 bytes, tos_cpu.o(i.cpu_sched_start))
+
[Calls]
+
[Called By]
+
+cpu_systick_init (Thumb, 18 bytes, Stack size 8 bytes, tos_cpu.o(i.cpu_systick_init))
+
[Stack]
- Max Depth = 32
- Call Chain = cpu_systick_init ⇒ port_systick_config ⇒ __NVIC_SetPriority
+
+
[Calls]- >> port_systick_priority_set
+
- >> port_systick_config
+
+
[Called By]
+
+cpu_task_stk_init (Thumb, 216 bytes, Stack size 20 bytes, tos_cpu.o(i.cpu_task_stk_init))
+
[Stack]
- Max Depth = 20
- Call Chain = cpu_task_stk_init
+
+
[Called By]
+
+esp8266_join_ap (Thumb, 68 bytes, Stack size 64 bytes, esp8266.o(i.esp8266_join_ap))
+
[Stack]
- Max Depth = 296 + Unknown Stack Size
+
- Call Chain = esp8266_join_ap ⇒ tos_at_cmd_exec_until ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_at_cmd_exec_until
+
- >> tos_at_echo_create
+
+
[Called By]
+
+esp8266_sal_init (Thumb, 52 bytes, Stack size 8 bytes, esp8266.o(i.esp8266_sal_init))
+
[Stack]
- Max Depth = 184 + Unknown Stack Size
+
- Call Chain = esp8266_sal_init ⇒ tos_at_init ⇒ at_recv_cache_init ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next
+
+
[Calls]- >> tos_sal_module_register
+
- >> tos_sal_module_init
+
- >> tos_at_init
+
+
[Called By]
+
+example_event_handle (Thumb, 40 bytes, Stack size 16 bytes, mqtt_example.o(i.example_event_handle))
+
[Stack]
- Max Depth = 40
- Call Chain = example_event_handle ⇒ HAL_Printf
+
+
[Calls]
+
[Address Reference Count : 1]- mqtt_example.o(i.mqtt_basic_thread)
+
+example_message_arrive (Thumb, 148 bytes, Stack size 24 bytes, mqtt_example.o(i.example_message_arrive))
+
[Stack]
- Max Depth = 48
- Call Chain = example_message_arrive ⇒ HAL_Printf
+
+
[Calls]
+
[Address Reference Count : 1]- mqtt_example.o(i.example_subscribe)
+
+example_publish (Thumb, 192 bytes, Stack size 40 bytes, mqtt_example.o(i.example_publish))
+
[Stack]
- Max Depth = 376 + Unknown Stack Size
+
- Call Chain = example_publish ⇒ IOT_MQTT_Publish_Simple ⇒ wrapper_mqtt_publish ⇒ iotx_mc_check_topic ⇒ iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> IOT_MQTT_Publish_Simple
+
- >> HAL_Snprintf
+
- >> HAL_Printf
+
- >> HAL_Malloc
+
- >> HAL_Free
+
- >> strlen
+
- >> __aeabi_memclr
+
+
[Called By]
+
+example_subscribe (Thumb, 186 bytes, Stack size 32 bytes, mqtt_example.o(i.example_subscribe))
+
[Stack]
- Max Depth = 384 + Unknown Stack Size
+
- Call Chain = example_subscribe ⇒ IOT_MQTT_Subscribe ⇒ wrapper_mqtt_subscribe ⇒ iotx_mc_check_topic ⇒ iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> IOT_MQTT_Subscribe
+
- >> HAL_Snprintf
+
- >> HAL_Printf
+
- >> HAL_Malloc
+
- >> HAL_Free
+
- >> strlen
+
- >> __aeabi_memclr
+
+
[Called By]
+
+fputc (Thumb, 42 bytes, Stack size 16 bytes, mcu_init.o(i.fputc))
+
[Stack]
- Max Depth = 72
- Call Chain = fputc ⇒ HAL_UART_Transmit ⇒ UART_WaitOnFlagUntilTimeout
+
+
[Calls]
+
[Address Reference Count : 2]- printfa.o(i.__0printf)
+
- printfa.o(i.__0vprintf)
+
+infra_strtok (Thumb, 258 bytes, Stack size 24 bytes, infra_string.o(i.infra_strtok))
+
[Stack]
- Max Depth = 36
- Call Chain = infra_strtok ⇒ memcmp
+
+
[Calls]- >> memcmp
+
- >> strlen
+
- >> __aeabi_memclr
+
+
[Called By]
+
+iotx_event_callback (Thumb, 24 bytes, Stack size 0 bytes, infra_compat.o(i.iotx_event_callback))
+
[Called By]
+
+iotx_net_connect (Thumb, 46 bytes, Stack size 16 bytes, infra_net.o(i.iotx_net_connect))
+
[Stack]
- Max Depth = 160
- Call Chain = iotx_net_connect ⇒ connect_tcp ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> LITE_syslog
+
- >> connect_tcp
+
+
[Address Reference Count : 1]- infra_net.o(i.iotx_net_init)
+
+iotx_net_disconnect (Thumb, 46 bytes, Stack size 16 bytes, infra_net.o(i.iotx_net_disconnect))
+
[Stack]
- Max Depth = 160
- Call Chain = iotx_net_disconnect ⇒ disconnect_tcp ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> LITE_syslog
+
- >> disconnect_tcp
+
+
[Address Reference Count : 1]- infra_net.o(i.iotx_net_init)
+
+iotx_net_init (Thumb, 86 bytes, Stack size 32 bytes, infra_net.o(i.iotx_net_init))
+
[Stack]
- Max Depth = 160
- Call Chain = iotx_net_init ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> LITE_syslog
+
- >> strlen
+
+
[Called By]
+
+iotx_report_devinfo (Thumb, 376 bytes, Stack size 232 bytes, infra_report.o(i.iotx_report_devinfo))
+
[Stack]
- Max Depth = 368 + Unknown Stack Size
+
- Call Chain = iotx_report_devinfo ⇒ HAL_Malloc ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next
+
+
[Calls]- >> HAL_Snprintf
+
- >> HAL_Malloc
+
- >> HAL_GetProductKey
+
- >> HAL_GetDeviceName
+
- >> HAL_Free
+
- >> LITE_syslog
+
- >> iotx_report_id
+
- >> strlen
+
- >> __aeabi_memclr4
+
- >> __aeabi_memclr
+
+
[Called By]- >> iotx_mqtt_report_funcs
+
+
+iotx_report_firmware_version (Thumb, 346 bytes, Stack size 328 bytes, infra_report.o(i.iotx_report_firmware_version))
+
[Stack]
- Max Depth = 456
- Call Chain = iotx_report_firmware_version ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> HAL_Snprintf
+
- >> HAL_GetProductKey
+
- >> HAL_GetDeviceName
+
- >> LITE_syslog
+
- >> HAL_GetFirmwareVersion
+
- >> iotx_report_id
+
- >> strlen
+
- >> __aeabi_memclr4
+
+
[Called By]- >> iotx_mqtt_report_funcs
+
+
+iotx_report_id (Thumb, 16 bytes, Stack size 0 bytes, infra_report.o(i.iotx_report_id))
+
[Called By]
- >> iotx_report_firmware_version
+
- >> iotx_report_devinfo
+
+
+iotx_report_mid (Thumb, 6 bytes, Stack size 0 bytes, infra_report.o(i.iotx_report_mid))
+
[Called By]
- >> iotx_mqtt_report_funcs
+
+
+iotx_set_report_func (Thumb, 6 bytes, Stack size 0 bytes, infra_report.o(i.iotx_set_report_func))
+
[Called By]
- >> iotx_mqtt_report_funcs
+
+
+iotx_time_init (Thumb, 12 bytes, Stack size 0 bytes, infra_timer.o(i.iotx_time_init))
+
[Called By]
- >> iotx_mc_wait_CONNACK
+
- >> iotx_mc_init
+
- >> MQTTSubscribe
+
- >> MQTTRePublish
+
- >> MQTTPuback
+
- >> MQTTKeepalive
+
- >> MQTTDisconnect
+
- >> _mqtt_cycle
+
- >> MQTTPublish
+
- >> MQTTConnect
+
+
+iotx_time_left (Thumb, 36 bytes, Stack size 16 bytes, infra_timer.o(i.iotx_time_left))
+
[Stack]
- Max Depth = 64 + Unknown Stack Size
+
- Call Chain = iotx_time_left ⇒ utils_time_is_expired ⇒ HAL_UptimeMs ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> HAL_UptimeMs
+
- >> utils_time_is_expired
+
+
[Called By]- >> iotx_mc_send_packet
+
- >> iotx_mc_read_packet
+
- >> _mqtt_cycle
+
+
+iotx_time_start (Thumb, 18 bytes, Stack size 8 bytes, infra_timer.o(i.iotx_time_start))
+
[Stack]
- Max Depth = 40 + Unknown Stack Size
+
- Call Chain = iotx_time_start ⇒ HAL_UptimeMs ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save
+
+
[Calls]
+
[Called By]- >> iotx_mc_push_pubInfo_to
+
- >> MQTTPubInfoProc
+
+
+knl_idle_init (Thumb, 38 bytes, Stack size 24 bytes, tos_sys.o(i.knl_idle_init))
+
[Stack]
- Max Depth = 96 + Unknown Stack Size
+
- Call Chain = knl_idle_init ⇒ tos_task_create ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]
+
[Called By]
+
+knl_is_idle (Thumb, 16 bytes, Stack size 0 bytes, tos_sys.o(i.knl_is_idle))
+
[Called By]
- >> task_do_destroy
+
- >> tos_task_create
+
+
+knl_is_inirq (Thumb, 14 bytes, Stack size 0 bytes, tos_sys.o(i.knl_is_inirq))
+
[Called By]
- >> tos_task_delay
+
- >> tos_knl_irq_leave
+
- >> tos_task_prio_change
+
- >> tos_mutex_post
+
- >> tos_mutex_pend_timed
+
- >> tos_mutex_destroy
+
- >> tos_mutex_create
+
- >> knl_sched
+
- >> tos_sem_pend
+
- >> tos_knl_sched_lock
+
- >> tos_task_yield
+
- >> tos_task_destroy
+
- >> tos_task_create
+
- >> tos_knl_sched_unlock
+
+
+knl_is_sched_locked (Thumb, 14 bytes, Stack size 0 bytes, tos_sys.o(i.knl_is_sched_locked))
+
[Called By]
- >> tos_task_delay
+
- >> tos_knl_irq_leave
+
- >> tos_mutex_pend_timed
+
- >> knl_sched
+
- >> tos_sem_pend
+
- >> tos_task_destroy
+
- >> tos_knl_sched_unlock
+
+
+knl_is_self (Thumb, 18 bytes, Stack size 0 bytes, tos_sys.o(i.knl_is_self))
+
[Called By]
- >> tos_knl_irq_leave
+
- >> tos_task_prio_change
+
- >> tos_mutex_post
+
- >> tos_mutex_pend_timed
+
- >> knl_sched
+
- >> tos_task_destroy
+
+
+knl_object_alloc_is_static (Thumb, 14 bytes, Stack size 0 bytes, tos_sys.o(i.knl_object_alloc_is_static))
+
[Called By]
- >> tos_ring_q_destroy
+
- >> tos_chr_fifo_destroy
+
- >> tos_task_destroy
+
+
+knl_object_alloc_reset (Thumb, 6 bytes, Stack size 0 bytes, tos_sys.o(i.knl_object_alloc_reset))
+
[Called By]
- >> tos_ring_q_destroy
+
- >> tos_chr_fifo_destroy
+
- >> task_reset
+
+
+knl_object_alloc_set_static (Thumb, 6 bytes, Stack size 0 bytes, tos_sys.o(i.knl_object_alloc_set_static))
+
[Called By]
- >> tos_ring_q_create
+
- >> tos_chr_fifo_create
+
- >> tos_task_create
+
+
+knl_object_deinit (Thumb, 6 bytes, Stack size 0 bytes, tos_sys.o(i.knl_object_deinit))
+
[Called By]
- >> tos_mutex_destroy
+
- >> tos_ring_q_destroy
+
- >> tos_chr_fifo_destroy
+
- >> tos_sem_destroy
+
- >> task_reset
+
+
+knl_object_init (Thumb, 4 bytes, Stack size 0 bytes, tos_sys.o(i.knl_object_init))
+
[Called By]
- >> tos_mutex_create
+
- >> tos_ring_q_create
+
- >> tos_chr_fifo_create
+
- >> tos_sem_create_max
+
- >> tos_task_create
+
+
+knl_object_verify (Thumb, 16 bytes, Stack size 0 bytes, tos_sys.o(i.knl_object_verify))
+
[Called By]
- >> tos_task_prio_change
+
- >> tos_mutex_post
+
- >> tos_mutex_pend_timed
+
- >> tos_mutex_destroy
+
- >> tos_ring_q_is_full
+
- >> tos_ring_q_is_empty
+
- >> tos_ring_q_enqueue
+
- >> tos_ring_q_destroy
+
- >> tos_ring_q_dequeue
+
- >> tos_chr_fifo_push_stream
+
- >> tos_chr_fifo_push
+
- >> tos_chr_fifo_pop_stream
+
- >> tos_chr_fifo_pop
+
- >> tos_chr_fifo_destroy
+
- >> tos_sem_pend
+
- >> tos_sem_destroy
+
- >> sem_do_post
+
- >> tos_task_destroy
+
+
+knl_sched (Thumb, 78 bytes, Stack size 8 bytes, tos_sys.o(i.knl_sched))
+
[Stack]
- Max Depth = 16 + Unknown Stack Size
+
- Call Chain = knl_sched ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> knl_is_self
+
- >> knl_is_sched_locked
+
- >> knl_is_inirq
+
- >> readyqueue_highest_ready_task_get
+
- >> cpu_context_switch
+
+
[Called By]- >> tos_task_delay
+
- >> tos_task_prio_change
+
- >> tos_mutex_post
+
- >> tos_mutex_pend_timed
+
- >> tos_mutex_destroy
+
- >> tos_sem_pend
+
- >> tos_sem_destroy
+
- >> sem_do_post
+
- >> tos_task_yield
+
- >> task_do_destroy
+
- >> tos_task_create
+
- >> tos_knl_sched_unlock
+
+
+main (Thumb, 32 bytes, Stack size 8 bytes, main.o(i.main))
+
[Stack]
- Max Depth = 296 + Unknown Stack Size
+
- Call Chain = main ⇒ board_init ⇒ SystemClock_Config ⇒ HAL_RCC_OscConfig ⇒ HAL_InitTick ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority
+
+
[Calls]- >> osThreadCreate
+
- >> osKernelStart
+
- >> osKernelInitialize
+
- >> board_init
+
- >> __2printf
+
+
[Address Reference Count : 1]- entry9a.o(.ARM.Collect$$$$0000000B)
+
+mmheap_init_with_pool (Thumb, 20 bytes, Stack size 16 bytes, tos_mmheap.o(i.mmheap_init_with_pool))
+
[Stack]
- Max Depth = 112 + Unknown Stack Size
+
- Call Chain = mmheap_init_with_pool ⇒ tos_mmheap_pool_add ⇒ blk_insert ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]- >> tos_mmheap_pool_add
+
- >> mmheap_ctl_init
+
+
[Called By]
+
+mqtt_basic_thread (Thumb, 176 bytes, Stack size 80 bytes, mqtt_example.o(i.mqtt_basic_thread))
+
[Stack]
- Max Depth = 1496 + Unknown Stack Size
+
- Call Chain = mqtt_basic_thread ⇒ IOT_MQTT_Construct ⇒ IOT_Sign_MQTT ⇒ _iotx_generate_sign_string ⇒ utils_hmac_sha256 ⇒ utils_sha256_finish ⇒ utils_sha256_update ⇒ utils_sha256_process
+
+
[Calls]- >> IOT_MQTT_Yield
+
- >> IOT_MQTT_Destroy
+
- >> IOT_MQTT_Construct
+
- >> HAL_Printf
+
- >> HAL_GetProductKey
+
- >> HAL_GetDeviceSecret
+
- >> HAL_GetDeviceName
+
- >> example_subscribe
+
- >> example_publish
+
- >> __aeabi_memclr4
+
+
[Called By]
+
+mutex_release (Thumb, 20 bytes, Stack size 8 bytes, tos_mutex.o(i.mutex_release))
+
[Stack]
- Max Depth = 88 + Unknown Stack Size
+
- Call Chain = mutex_release ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz
+
+
[Calls]- >> mutex_old_owner_release
+
- >> pend_wakeup_all
+
+
[Called By]
+
+osKernelInitialize (Thumb, 14 bytes, Stack size 8 bytes, cmsis_os.o(i.osKernelInitialize))
+
[Stack]
- Max Depth = 128 + Unknown Stack Size
+
- Call Chain = osKernelInitialize ⇒ tos_knl_init ⇒ mmheap_init_with_pool ⇒ tos_mmheap_pool_add ⇒ blk_insert ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]- >> errno_knl2cmsis
+
- >> tos_knl_init
+
+
[Called By]
+
+osKernelStart (Thumb, 14 bytes, Stack size 8 bytes, cmsis_os.o(i.osKernelStart))
+
[Stack]
- Max Depth = 16 + Unknown Stack Size
+
- Call Chain = osKernelStart ⇒ tos_knl_start
+
+
[Calls]- >> errno_knl2cmsis
+
- >> tos_knl_start
+
+
[Called By]
+
+osThreadCreate (Thumb, 66 bytes, Stack size 40 bytes, cmsis_os.o(i.osThreadCreate))
+
[Stack]
- Max Depth = 112 + Unknown Stack Size
+
- Call Chain = osThreadCreate ⇒ tos_task_create ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]- >> priority_cmsis2knl
+
- >> tos_task_create
+
+
[Called By]
+
+pend_highest_pending_prio_get (Thumb, 32 bytes, Stack size 16 bytes, tos_pend.o(i.pend_highest_pending_prio_get))
+
[Stack]
- Max Depth = 16
- Call Chain = pend_highest_pending_prio_get
+
+
[Calls]
+
[Called By]- >> tos_mutex_post
+
- >> task_highest_pending_prio_get
+
+
+pend_highest_pending_task_get (Thumb, 8 bytes, Stack size 0 bytes, tos_pend.o(i.pend_highest_pending_task_get))
+
[Called By]
+
+pend_is_nopending (Thumb, 12 bytes, Stack size 8 bytes, tos_pend.o(i.pend_is_nopending))
+
[Stack]
- Max Depth = 8
- Call Chain = pend_is_nopending
+
+
[Calls]
+
[Called By]- >> tos_mutex_post
+
- >> tos_mutex_destroy
+
- >> tos_sem_destroy
+
- >> sem_do_post
+
+
+pend_list_adjust (Thumb, 22 bytes, Stack size 8 bytes, tos_pend.o(i.pend_list_adjust))
+
[Stack]
- Max Depth = 24
- Call Chain = pend_list_adjust ⇒ pend_list_add
+
+
[Calls]- >> tos_list_del
+
- >> pend_list_add
+
+
[Called By]- >> tos_task_prio_change
+
+
+pend_list_remove (Thumb, 30 bytes, Stack size 8 bytes, tos_pend.o(i.pend_list_remove))
+
[Stack]
- Max Depth = 8
- Call Chain = pend_list_remove
+
+
[Calls]
+
[Called By]- >> pend_task_wakeup
+
- >> task_do_destroy
+
+
+pend_object_deinit (Thumb, 12 bytes, Stack size 8 bytes, tos_pend.o(i.pend_object_deinit))
+
[Stack]
- Max Depth = 8
- Call Chain = pend_object_deinit
+
+
[Calls]
+
[Called By]- >> tos_mutex_destroy
+
- >> tos_sem_destroy
+
+
+pend_object_init (Thumb, 12 bytes, Stack size 8 bytes, tos_pend.o(i.pend_object_init))
+
[Stack]
- Max Depth = 8
- Call Chain = pend_object_init
+
+
[Calls]
+
[Called By]- >> tos_mutex_create
+
- >> tos_sem_create_max
+
+
+pend_state2errno (Thumb, 46 bytes, Stack size 0 bytes, tos_pend.o(i.pend_state2errno))
+
[Called By]
- >> tos_mutex_pend_timed
+
- >> tos_sem_pend
+
+
+pend_task_block (Thumb, 60 bytes, Stack size 24 bytes, tos_pend.o(i.pend_task_block))
+
[Stack]
- Max Depth = 104 + Unknown Stack Size
+
- Call Chain = pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> pend_list_add
+
- >> tick_list_add
+
- >> readyqueue_remove
+
+
[Called By]- >> tos_mutex_pend_timed
+
- >> tos_sem_pend
+
+
+pend_task_wakeup (Thumb, 64 bytes, Stack size 16 bytes, tos_pend.o(i.pend_task_wakeup))
+
[Stack]
- Max Depth = 56 + Unknown Stack Size
+
- Call Chain = pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]- >> tick_list_remove
+
- >> readyqueue_add
+
- >> pend_list_remove
+
+
[Called By]- >> pend_wakeup_one
+
- >> pend_wakeup_all
+
- >> tick_update
+
+
+pend_wakeup (Thumb, 30 bytes, Stack size 16 bytes, tos_pend.o(i.pend_wakeup))
+
[Stack]
- Max Depth = 96 + Unknown Stack Size
+
- Call Chain = pend_wakeup ⇒ pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]- >> pend_wakeup_one
+
- >> pend_wakeup_all
+
+
[Called By]
+
+pend_wakeup_all (Thumb, 36 bytes, Stack size 24 bytes, tos_pend.o(i.pend_wakeup_all))
+
[Stack]
- Max Depth = 80 + Unknown Stack Size
+
- Call Chain = pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]
+
[Called By]- >> tos_mutex_destroy
+
- >> mutex_release
+
- >> tos_sem_destroy
+
- >> pend_wakeup
+
+
+pend_wakeup_one (Thumb, 20 bytes, Stack size 16 bytes, tos_pend.o(i.pend_wakeup_one))
+
[Stack]
- Max Depth = 72 + Unknown Stack Size
+
- Call Chain = pend_wakeup_one ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]
+
[Called By]- >> tos_mutex_post
+
- >> pend_wakeup
+
+
+port_systick_config (Thumb, 50 bytes, Stack size 16 bytes, port_c.o(i.port_systick_config))
+
[Stack]
- Max Depth = 24
- Call Chain = port_systick_config ⇒ __NVIC_SetPriority
+
+
[Calls]
+
[Called By]
+
+port_systick_priority_set (Thumb, 16 bytes, Stack size 8 bytes, port_c.o(i.port_systick_priority_set))
+
[Stack]
- Max Depth = 16
- Call Chain = port_systick_priority_set ⇒ __NVIC_SetPriority
+
+
[Calls]
+
[Called By]
+
+readChar (Thumb, 14 bytes, Stack size 0 bytes, mqttpacket.o(i.readChar))
+
[Called By]
- >> MQTTDeserialize_suback
+
- >> MQTTDeserialize_publish
+
- >> MQTTDeserialize_connack
+
- >> MQTTDeserialize_ack
+
+
+readInt (Thumb, 26 bytes, Stack size 12 bytes, mqttpacket.o(i.readInt))
+
[Stack]
- Max Depth = 12
- Call Chain = readInt
+
+
[Called By]- >> readMQTTLenString
+
- >> MQTTDeserialize_suback
+
- >> MQTTDeserialize_publish
+
- >> MQTTDeserialize_ack
+
+
+readMQTTLenString (Thumb, 58 bytes, Stack size 20 bytes, mqttpacket.o(i.readMQTTLenString))
+
[Stack]
- Max Depth = 32
- Call Chain = readMQTTLenString ⇒ readInt
+
+
[Calls]
+
[Called By]- >> MQTTDeserialize_publish
+
+
+readyqueue_add (Thumb, 32 bytes, Stack size 8 bytes, tos_sched.o(i.readyqueue_add))
+
[Stack]
- Max Depth = 40
- Call Chain = readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]- >> readyqueue_add_tail
+
- >> readyqueue_add_head
+
+
[Called By]
+
+readyqueue_add_head (Thumb, 48 bytes, Stack size 24 bytes, tos_sched.o(i.readyqueue_add_head))
+
[Stack]
- Max Depth = 24
- Call Chain = readyqueue_add_head
+
+
[Calls]- >> tos_list_empty
+
- >> readyqueue_prio_mark
+
- >> _list_add
+
+
[Called By]- >> tos_task_prio_change
+
- >> readyqueue_add
+
+
+readyqueue_add_tail (Thumb, 38 bytes, Stack size 16 bytes, tos_sched.o(i.readyqueue_add_tail))
+
[Stack]
- Max Depth = 32
- Call Chain = readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]- >> tos_list_empty
+
- >> tos_list_add_tail
+
- >> readyqueue_prio_mark
+
+
[Called By]- >> tos_task_prio_change
+
- >> readyqueue_add
+
- >> tos_task_yield
+
- >> tos_task_create
+
+
+readyqueue_highest_ready_task_get (Thumb, 18 bytes, Stack size 0 bytes, tos_sched.o(i.readyqueue_highest_ready_task_get))
+
[Called By]
- >> tos_knl_irq_leave
+
- >> knl_sched
+
- >> tos_knl_start
+
+
+readyqueue_init (Thumb, 60 bytes, Stack size 0 bytes, tos_sched.o(i.readyqueue_init))
+
[Called By]
+
+readyqueue_remove (Thumb, 94 bytes, Stack size 16 bytes, tos_sched.o(i.readyqueue_remove))
+
[Stack]
- Max Depth = 40 + Unknown Stack Size
+
- Call Chain = readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz
+
+
[Calls]- >> tos_list_empty
+
- >> readyqueue_prio_highest_get
+
- >> _list_del
+
+
[Called By]- >> tos_task_delay
+
- >> tos_task_prio_change
+
- >> pend_task_block
+
- >> tos_task_yield
+
- >> task_do_destroy
+
+
+task_free_all (Thumb, 66 bytes, Stack size 24 bytes, tos_task.o(i.task_free_all))
+
[Stack]
- Max Depth = 136 + Unknown Stack Size
+
- Call Chain = task_free_all ⇒ task_free ⇒ tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> tos_list_del
+
- >> task_free
+
+
[Called By]
+
+tick_list_add (Thumb, 72 bytes, Stack size 16 bytes, tos_tick.o(i.tick_list_add))
+
[Stack]
- Max Depth = 80 + Unknown Stack Size
+
- Call Chain = tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]
+
[Called By]- >> tos_task_delay
+
- >> pend_task_block
+
+
+tick_list_remove (Thumb, 24 bytes, Stack size 8 bytes, tos_tick.o(i.tick_list_remove))
+
[Stack]
- Max Depth = 32 + Unknown Stack Size
+
- Call Chain = tick_list_remove ⇒ tick_task_takeoff ⇒ tos_cpu_cpsr_save
+
+
[Calls]
+
[Called By]- >> pend_task_wakeup
+
- >> task_do_destroy
+
+
+tick_update (Thumb, 180 bytes, Stack size 32 bytes, tos_tick.o(i.tick_update))
+
[Stack]
- Max Depth = 88 + Unknown Stack Size
+
- Call Chain = tick_update ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> pend_task_wakeup
+
- >> tos_list_empty
+
+
[Called By]
+
+timer_init (Thumb, 4 bytes, Stack size 0 bytes, tos_timer.o(i.timer_init))
+
[Called By]
+
+timer_update (Thumb, 118 bytes, Stack size 16 bytes, tos_timer.o(i.timer_update))
+
[Stack]
- Max Depth = 48 + Unknown Stack Size
+
- Call Chain = timer_update ⇒ timer_takeoff ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_knl_sched_lock
+
- >> timer_takeoff
+
- >> timer_place
+
- >> tos_knl_sched_unlock
+
+
[Called By]
+
+tos_at_channel_alloc (Thumb, 76 bytes, Stack size 24 bytes, tos_at.o(i.tos_at_channel_alloc))
+
[Stack]
- Max Depth = 176 + Unknown Stack Size
+
- Call Chain = tos_at_channel_alloc ⇒ at_channel_construct ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next
+
+
[Calls]- >> at_channel_construct
+
+
[Called By]
+
+tos_at_channel_free (Thumb, 64 bytes, Stack size 16 bytes, tos_at.o(i.tos_at_channel_free))
+
[Stack]
- Max Depth = 120 + Unknown Stack Size
+
- Call Chain = tos_at_channel_free ⇒ tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]- >> tos_mmheap_free
+
- >> tos_mutex_destroy
+
- >> tos_chr_fifo_destroy
+
- >> at_channel_get
+
- >> __aeabi_memclr4
+
+
[Called By]- >> esp8266_connect
+
- >> esp8266_close
+
+
+tos_at_channel_is_working (Thumb, 34 bytes, Stack size 16 bytes, tos_at.o(i.tos_at_channel_is_working))
+
[Stack]
- Max Depth = 24
- Call Chain = tos_at_channel_is_working ⇒ at_channel_get
+
+
[Calls]
+
[Called By]- >> esp8266_sendto
+
- >> esp8266_send
+
+
+tos_at_channel_read_timed (Thumb, 170 bytes, Stack size 56 bytes, tos_at.o(i.tos_at_channel_read_timed))
+
[Stack]
- Max Depth = 184 + Unknown Stack Size
+
- Call Chain = tos_at_channel_read_timed ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_mutex_post
+
- >> tos_mutex_pend_timed
+
- >> tos_chr_fifo_pop_stream
+
- >> tos_millisec2tick
+
- >> at_timer_remain
+
- >> at_timer_is_expired
+
- >> at_timer_countdown
+
- >> at_channel_get
+
+
[Called By]- >> esp8266_recvfrom_timeout
+
- >> esp8266_recv_timeout
+
+
+tos_at_channel_set_broken (Thumb, 34 bytes, Stack size 16 bytes, tos_at.o(i.tos_at_channel_set_broken))
+
[Stack]
- Max Depth = 24
- Call Chain = tos_at_channel_set_broken ⇒ at_channel_get
+
+
[Calls]
+
[Called By]- >> esp8266_sendto
+
- >> esp8266_send
+
+
+tos_at_channel_write (Thumb, 72 bytes, Stack size 24 bytes, tos_at.o(i.tos_at_channel_write))
+
[Stack]
- Max Depth = 160 + Unknown Stack Size
+
- Call Chain = tos_at_channel_write ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_mutex_post
+
- >> tos_mutex_pend
+
- >> tos_chr_fifo_push_stream
+
- >> at_channel_get
+
+
[Called By]- >> esp8266_incoming_data_process
+
+
+tos_at_cmd_exec (Thumb, 86 bytes, Stack size 48 bytes, tos_at.o(i.tos_at_cmd_exec))
+
[Stack]
- Max Depth = 232 + Unknown Stack Size
+
- Call Chain = tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_task_delay
+
- >> tos_millisec2tick
+
- >> at_echo_attach
+
- >> at_cmd_do_exec
+
+
[Called By]- >> esp8266_sendto
+
- >> esp8266_send_mode_set
+
- >> esp8266_send
+
- >> esp8266_restore
+
- >> esp8266_parse_domain
+
- >> esp8266_net_mode_set
+
- >> esp8266_multilink_set
+
- >> esp8266_echo_close
+
- >> esp8266_close
+
+
+tos_at_cmd_exec_until (Thumb, 134 bytes, Stack size 48 bytes, tos_at.o(i.tos_at_cmd_exec_until))
+
[Stack]
- Max Depth = 232 + Unknown Stack Size
+
- Call Chain = tos_at_cmd_exec_until ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_sem_pend
+
- >> tos_sem_destroy
+
- >> tos_sem_create
+
- >> tos_millisec2tick
+
- >> at_echo_attach
+
- >> at_cmd_do_exec
+
+
[Called By]- >> esp8266_join_ap
+
- >> esp8266_connect
+
+
+tos_at_echo_create (Thumb, 52 bytes, Stack size 24 bytes, tos_at.o(i.tos_at_echo_create))
+
[Stack]
- Max Depth = 24
- Call Chain = tos_at_echo_create
+
+
[Calls]
+
[Called By]- >> esp8266_join_ap
+
- >> esp8266_sendto
+
- >> esp8266_send_mode_set
+
- >> esp8266_send
+
- >> esp8266_restore
+
- >> esp8266_parse_domain
+
- >> esp8266_net_mode_set
+
- >> esp8266_multilink_set
+
- >> esp8266_echo_close
+
- >> esp8266_connect
+
+
+tos_at_global_lock_pend (Thumb, 20 bytes, Stack size 8 bytes, tos_at.o(i.tos_at_global_lock_pend))
+
[Stack]
- Max Depth = 144 + Unknown Stack Size
+
- Call Chain = tos_at_global_lock_pend ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]
+
[Called By]- >> esp8266_sendto
+
- >> esp8266_send
+
+
+tos_at_global_lock_post (Thumb, 20 bytes, Stack size 8 bytes, tos_at.o(i.tos_at_global_lock_post))
+
[Stack]
- Max Depth = 120 + Unknown Stack Size
+
- Call Chain = tos_at_global_lock_post ⇒ tos_mutex_post ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz
+
+
[Calls]
+
[Called By]- >> esp8266_sendto
+
- >> esp8266_send
+
+
+tos_at_init (Thumb, 344 bytes, Stack size 40 bytes, tos_at.o(i.tos_at_init))
+
[Stack]
- Max Depth = 176 + Unknown Stack Size
+
- Call Chain = tos_at_init ⇒ at_recv_cache_init ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next
+
+
[Calls]- >> tos_mmheap_free
+
- >> tos_mmheap_alloc
+
- >> tos_mutex_destroy
+
- >> tos_mutex_create
+
- >> tos_chr_fifo_destroy
+
- >> tos_chr_fifo_create
+
- >> tos_sem_destroy
+
- >> tos_sem_create
+
- >> tos_task_destroy
+
- >> tos_task_create
+
- >> at_timer_init
+
- >> at_recv_cache_init
+
- >> at_recv_cache_deinit
+
- >> at_event_table_set
+
- >> at_channel_init
+
- >> tos_hal_uart_init
+
- >> tos_hal_uart_deinit
+
- >> __aeabi_memclr4
+
+
[Called By]
+
+tos_at_raw_data_send_until (Thumb, 118 bytes, Stack size 32 bytes, tos_at.o(i.tos_at_raw_data_send_until))
+
[Stack]
- Max Depth = 192 + Unknown Stack Size
+
- Call Chain = tos_at_raw_data_send_until ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_sem_pend
+
- >> tos_sem_destroy
+
- >> tos_sem_create
+
- >> tos_millisec2tick
+
- >> at_uart_send
+
- >> at_echo_attach
+
+
[Called By]- >> esp8266_sendto
+
- >> esp8266_send
+
+
+tos_at_uart_read (Thumb, 48 bytes, Stack size 24 bytes, tos_at.o(i.tos_at_uart_read))
+
[Stack]
- Max Depth = 184 + Unknown Stack Size
+
- Call Chain = tos_at_uart_read ⇒ at_uart_getchar ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]
+
[Called By]- >> esp8266_incoming_data_process
+
+
+tos_at_uart_write_byte (Thumb, 24 bytes, Stack size 8 bytes, tos_at.o(i.tos_at_uart_write_byte))
+
[Stack]
- Max Depth = 128 + Unknown Stack Size
+
- Call Chain = tos_at_uart_write_byte ⇒ tos_sem_post ⇒ sem_do_post ⇒ pend_wakeup ⇒ pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]- >> tos_chr_fifo_push
+
- >> tos_sem_post
+
+
[Called By]- >> HAL_UART_RxCpltCallback
+
+
+tos_chr_fifo_create (Thumb, 92 bytes, Stack size 24 bytes, tos_char_fifo.o(i.tos_chr_fifo_create))
+
[Stack]
- Max Depth = 48
- Call Chain = tos_chr_fifo_create ⇒ tos_ring_q_create
+
+
[Calls]- >> knl_object_init
+
- >> knl_object_alloc_set_static
+
- >> tos_ring_q_create
+
+
[Called By]- >> at_channel_construct
+
- >> tos_at_init
+
+
+tos_chr_fifo_destroy (Thumb, 90 bytes, Stack size 16 bytes, tos_char_fifo.o(i.tos_chr_fifo_destroy))
+
[Stack]
- Max Depth = 24
- Call Chain = tos_chr_fifo_destroy ⇒ tos_ring_q_destroy
+
+
[Calls]- >> knl_object_verify
+
- >> knl_object_deinit
+
- >> knl_object_alloc_reset
+
- >> knl_object_alloc_is_static
+
- >> tos_ring_q_destroy
+
+
[Called By]- >> tos_at_init
+
- >> tos_at_channel_free
+
+
+tos_chr_fifo_pop (Thumb, 60 bytes, Stack size 16 bytes, tos_char_fifo.o(i.tos_chr_fifo_pop))
+
[Stack]
- Max Depth = 72 + Unknown Stack Size
+
- Call Chain = tos_chr_fifo_pop ⇒ tos_ring_q_dequeue ⇒ tos_ring_q_is_empty ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> knl_object_verify
+
- >> tos_ring_q_dequeue
+
+
[Called By]
+
+tos_chr_fifo_pop_stream (Thumb, 122 bytes, Stack size 32 bytes, tos_char_fifo.o(i.tos_chr_fifo_pop_stream))
+
[Stack]
- Max Depth = 88 + Unknown Stack Size
+
- Call Chain = tos_chr_fifo_pop_stream ⇒ tos_ring_q_dequeue ⇒ tos_ring_q_is_empty ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> knl_object_verify
+
- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> tos_ring_q_dequeue
+
+
[Called By]- >> tos_at_channel_read_timed
+
+
+tos_chr_fifo_push (Thumb, 58 bytes, Stack size 16 bytes, tos_char_fifo.o(i.tos_chr_fifo_push))
+
[Stack]
- Max Depth = 64 + Unknown Stack Size
+
- Call Chain = tos_chr_fifo_push ⇒ tos_ring_q_enqueue ⇒ tos_ring_q_is_full ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> knl_object_verify
+
- >> tos_ring_q_enqueue
+
+
[Called By]- >> tos_at_uart_write_byte
+
+
+tos_chr_fifo_push_stream (Thumb, 116 bytes, Stack size 32 bytes, tos_char_fifo.o(i.tos_chr_fifo_push_stream))
+
[Stack]
- Max Depth = 80 + Unknown Stack Size
+
- Call Chain = tos_chr_fifo_push_stream ⇒ tos_ring_q_enqueue ⇒ tos_ring_q_is_full ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> knl_object_verify
+
- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> tos_ring_q_enqueue
+
+
[Called By]- >> tos_at_channel_write
+
+
+tos_cpu_clz (Thumb, 12 bytes, Stack size 8 bytes, tos_cpu.o(i.tos_cpu_clz))
+
[Stack]
- Max Depth = 8 + Unknown Stack Size
+
- Call Chain = tos_cpu_clz
+
+
[Calls]
+
[Called By]- >> generic_fls
+
- >> readyqueue_prio_highest_get
+
+
+tos_cpu_cpsr_restore (Thumb, 12 bytes, Stack size 8 bytes, tos_cpu.o(i.tos_cpu_cpsr_restore))
+
[Stack]
- Max Depth = 8 + Unknown Stack Size
+
- Call Chain = tos_cpu_cpsr_restore
+
+
[Calls]
+
[Called By]- >> tos_task_delay
+
- >> tos_knl_irq_leave
+
- >> tos_task_prio_change
+
- >> tos_mutex_post
+
- >> tos_mutex_pend_timed
+
- >> tos_mutex_destroy
+
- >> knl_sched
+
- >> tos_ring_q_is_full
+
- >> tos_ring_q_is_empty
+
- >> tos_ring_q_enqueue
+
- >> tos_ring_q_dequeue
+
- >> tos_chr_fifo_push_stream
+
- >> tos_chr_fifo_pop_stream
+
- >> tos_sem_pend
+
- >> tos_sem_destroy
+
- >> sem_do_post
+
- >> tos_knl_sched_lock
+
- >> timer_takeoff
+
- >> timer_place
+
- >> tos_systick_get
+
- >> tick_update
+
- >> tick_task_takeoff
+
- >> tick_task_place
+
- >> tos_task_yield
+
- >> task_do_destroy
+
- >> tos_task_create
+
- >> task_free_all
+
- >> tos_knl_sched_unlock
+
+
+tos_cpu_cpsr_save (Thumb, 8 bytes, Stack size 8 bytes, tos_cpu.o(i.tos_cpu_cpsr_save))
+
[Stack]
- Max Depth = 8 + Unknown Stack Size
+
- Call Chain = tos_cpu_cpsr_save
+
+
[Calls]
+
[Called By]- >> tos_task_delay
+
- >> tos_knl_irq_leave
+
- >> tos_task_prio_change
+
- >> tos_mutex_post
+
- >> tos_mutex_pend_timed
+
- >> tos_mutex_destroy
+
- >> knl_sched
+
- >> tos_ring_q_is_full
+
- >> tos_ring_q_is_empty
+
- >> tos_ring_q_enqueue
+
- >> tos_ring_q_dequeue
+
- >> tos_chr_fifo_push_stream
+
- >> tos_chr_fifo_pop_stream
+
- >> tos_sem_pend
+
- >> tos_sem_destroy
+
- >> sem_do_post
+
- >> tos_knl_sched_lock
+
- >> timer_takeoff
+
- >> timer_place
+
- >> tos_systick_get
+
- >> tick_update
+
- >> tick_task_takeoff
+
- >> tick_task_place
+
- >> tos_task_yield
+
- >> task_do_destroy
+
- >> tos_task_create
+
- >> task_free_all
+
- >> tos_knl_sched_unlock
+
+
+tos_hal_uart_deinit (Thumb, 50 bytes, Stack size 16 bytes, tos_hal_uart.o(i.tos_hal_uart_deinit))
+
[Stack]
- Max Depth = 52
- Call Chain = tos_hal_uart_deinit ⇒ HAL_UART_DeInit ⇒ HAL_UART_MspDeInit ⇒ HAL_GPIO_DeInit
+
+
[Calls]- >> HAL_UART_MspDeInit
+
- >> HAL_UART_DeInit
+
+
[Called By]
+
+tos_hal_uart_init (Thumb, 70 bytes, Stack size 16 bytes, tos_hal_uart.o(i.tos_hal_uart_init))
+
[Stack]
- Max Depth = 112
- Call Chain = tos_hal_uart_init ⇒ MX_USART1_UART_Init ⇒ HAL_UART_Init ⇒ HAL_UART_MspInit ⇒ HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority
+
+
[Calls]- >> MX_USART1_UART_Init
+
- >> MX_LPUART1_UART_Init
+
- >> MX_USART3_UART_Init
+
- >> MX_USART2_UART_Init
+
+
[Called By]
+
+tos_hal_uart_write (Thumb, 64 bytes, Stack size 32 bytes, tos_hal_uart.o(i.tos_hal_uart_write))
+
[Stack]
- Max Depth = 88
- Call Chain = tos_hal_uart_write ⇒ HAL_UART_Transmit ⇒ UART_WaitOnFlagUntilTimeout
+
+
[Calls]
+
[Called By]
+
+tos_knl_init (Thumb, 56 bytes, Stack size 8 bytes, tos_sys.o(i.tos_knl_init))
+
[Stack]
- Max Depth = 120 + Unknown Stack Size
+
- Call Chain = tos_knl_init ⇒ mmheap_init_with_pool ⇒ tos_mmheap_pool_add ⇒ blk_insert ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]- >> mmheap_init_with_pool
+
- >> readyqueue_init
+
- >> timer_init
+
- >> cpu_init
+
- >> knl_idle_init
+
+
[Called By]
+
+tos_knl_irq_enter (Thumb, 42 bytes, Stack size 4 bytes, tos_sys.o(i.tos_knl_irq_enter))
+
[Stack]
- Max Depth = 4
- Call Chain = tos_knl_irq_enter
+
+
[Calls]
+
[Called By]- >> SysTick_Handler
+
- >> LPUART1_IRQHandler
+
+
+tos_knl_irq_leave (Thumb, 134 bytes, Stack size 8 bytes, tos_sys.o(i.tos_knl_irq_leave))
+
[Stack]
- Max Depth = 16 + Unknown Stack Size
+
- Call Chain = tos_knl_irq_leave ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_knl_is_running
+
- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> knl_is_self
+
- >> knl_is_sched_locked
+
- >> knl_is_inirq
+
- >> readyqueue_highest_ready_task_get
+
- >> cpu_irq_context_switch
+
+
[Called By]- >> SysTick_Handler
+
- >> LPUART1_IRQHandler
+
+
+tos_knl_is_running (Thumb, 14 bytes, Stack size 0 bytes, tos_sys.o(i.tos_knl_is_running))
+
[Called By]
- >> tos_tick_handler
+
- >> tos_knl_irq_leave
+
- >> tos_knl_irq_enter
+
- >> SysTick_Handler
+
- >> tos_knl_sched_lock
+
- >> tos_task_create
+
- >> tos_knl_start
+
- >> tos_knl_sched_unlock
+
+
+tos_knl_sched_lock (Thumb, 88 bytes, Stack size 8 bytes, tos_sys.o(i.tos_knl_sched_lock))
+
[Stack]
- Max Depth = 16 + Unknown Stack Size
+
- Call Chain = tos_knl_sched_lock ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_knl_is_running
+
- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> knl_is_inirq
+
+
[Called By]
+
+tos_knl_sched_unlock (Thumb, 90 bytes, Stack size 8 bytes, tos_sys.o(i.tos_knl_sched_unlock))
+
[Stack]
- Max Depth = 24 + Unknown Stack Size
+
- Call Chain = tos_knl_sched_unlock ⇒ knl_sched ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_knl_is_running
+
- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> knl_sched
+
- >> knl_is_sched_locked
+
- >> knl_is_inirq
+
+
[Called By]
+
+tos_knl_start (Thumb, 44 bytes, Stack size 8 bytes, tos_sys.o(i.tos_knl_start))
+
[Stack]
- Max Depth = 8 + Unknown Stack Size
+
- Call Chain = tos_knl_start
+
+
[Calls]- >> tos_knl_is_running
+
- >> readyqueue_highest_ready_task_get
+
- >> cpu_sched_start
+
+
[Called By]
+
+tos_millisec2tick (Thumb, 28 bytes, Stack size 16 bytes, tos_time.o(i.tos_millisec2tick))
+
[Stack]
- Max Depth = 56
- Call Chain = tos_millisec2tick ⇒ __aeabi_uldivmod
+
+
[Calls]
+
[Called By]- >> tos_at_raw_data_send_until
+
- >> tos_at_cmd_exec_until
+
- >> tos_at_cmd_exec
+
- >> tos_at_channel_read_timed
+
+
+tos_mmheap_alloc (Thumb, 38 bytes, Stack size 16 bytes, tos_mmheap.o(i.tos_mmheap_alloc))
+
[Stack]
- Max Depth = 128 + Unknown Stack Size
+
- Call Chain = tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next
+
+
[Calls]- >> blk_prepare_used
+
- >> blk_locate_free
+
- >> adjust_request_size
+
+
[Called By]- >> HAL_Malloc
+
- >> at_recv_cache_init
+
- >> at_channel_construct
+
- >> tos_at_init
+
+
+tos_mmheap_free (Thumb, 48 bytes, Stack size 16 bytes, tos_mmheap.o(i.tos_mmheap_free))
+
[Stack]
- Max Depth = 104 + Unknown Stack Size
+
- Call Chain = tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]- >> blk_merge_prev
+
- >> blk_merge_next
+
- >> blk_mark_as_free
+
- >> blk_insert
+
+
[Called By]- >> HAL_Free
+
- >> task_free
+
- >> at_recv_cache_deinit
+
- >> at_channel_construct
+
- >> tos_at_init
+
- >> tos_at_channel_free
+
+
+tos_mmheap_pool_add (Thumb, 182 bytes, Stack size 24 bytes, tos_mmheap.o(i.tos_mmheap_pool_add))
+
[Stack]
- Max Depth = 96 + Unknown Stack Size
+
- Call Chain = tos_mmheap_pool_add ⇒ blk_insert ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]- >> offset_to_block
+
- >> mmheap_pool_is_exist
+
- >> blk_set_used
+
- >> blk_set_size
+
- >> blk_set_prev_used
+
- >> blk_set_prev_free
+
- >> blk_set_free
+
- >> blk_link_next
+
- >> blk_insert
+
+
[Called By]- >> mmheap_init_with_pool
+
+
+tos_mutex_create (Thumb, 88 bytes, Stack size 8 bytes, tos_mutex.o(i.tos_mutex_create))
+
[Stack]
- Max Depth = 16
- Call Chain = tos_mutex_create ⇒ pend_object_init
+
+
[Calls]- >> knl_object_init
+
- >> pend_object_init
+
- >> knl_is_inirq
+
+
[Called By]- >> at_channel_construct
+
- >> tos_at_init
+
- >> HAL_MutexCreate
+
+
+tos_mutex_destroy (Thumb, 138 bytes, Stack size 16 bytes, tos_mutex.o(i.tos_mutex_destroy))
+
[Stack]
- Max Depth = 96 + Unknown Stack Size
+
- Call Chain = tos_mutex_destroy ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz
+
+
[Calls]- >> knl_object_verify
+
- >> knl_object_deinit
+
- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> mutex_old_owner_release
+
- >> pend_wakeup_all
+
- >> pend_object_deinit
+
- >> pend_is_nopending
+
- >> knl_sched
+
- >> knl_is_inirq
+
+
[Called By]- >> tos_at_init
+
- >> tos_at_channel_free
+
- >> HAL_MutexDestroy
+
+
+tos_mutex_pend (Thumb, 18 bytes, Stack size 8 bytes, tos_mutex.o(i.tos_mutex_pend))
+
[Stack]
- Max Depth = 136 + Unknown Stack Size
+
- Call Chain = tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_mutex_pend_timed
+
+
[Called By]- >> at_uart_send
+
- >> at_uart_getchar
+
- >> at_cmd_do_exec
+
- >> tos_at_global_lock_pend
+
- >> tos_at_channel_write
+
- >> HAL_MutexLock
+
+
+tos_mutex_pend_timed (Thumb, 288 bytes, Stack size 24 bytes, tos_mutex.o(i.tos_mutex_pend_timed))
+
[Stack]
- Max Depth = 128 + Unknown Stack Size
+
- Call Chain = tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> knl_object_verify
+
- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> tos_task_prio_change
+
- >> knl_is_self
+
- >> mutex_fresh_owner_mark
+
- >> pend_task_block
+
- >> pend_state2errno
+
- >> knl_sched
+
- >> knl_is_sched_locked
+
- >> knl_is_inirq
+
+
[Called By]- >> tos_mutex_pend
+
- >> tos_at_channel_read_timed
+
+
+tos_mutex_post (Thumb, 238 bytes, Stack size 32 bytes, tos_mutex.o(i.tos_mutex_post))
+
[Stack]
- Max Depth = 112 + Unknown Stack Size
+
- Call Chain = tos_mutex_post ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz
+
+
[Calls]- >> knl_object_verify
+
- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> tos_task_prio_change
+
- >> pend_wakeup_one
+
- >> pend_highest_pending_task_get
+
- >> pend_highest_pending_prio_get
+
- >> knl_is_self
+
- >> mutex_old_owner_release
+
- >> mutex_fresh_owner_mark
+
- >> pend_is_nopending
+
- >> knl_sched
+
- >> knl_is_inirq
+
+
[Called By]- >> at_uart_send
+
- >> at_uart_getchar
+
- >> at_cmd_do_exec
+
- >> tos_at_global_lock_post
+
- >> tos_at_channel_write
+
- >> tos_at_channel_read_timed
+
- >> HAL_MutexUnlock
+
+
+tos_ring_q_create (Thumb, 88 bytes, Stack size 24 bytes, tos_ring_queue.o(i.tos_ring_q_create))
+
[Stack]
- Max Depth = 24
- Call Chain = tos_ring_q_create
+
+
[Calls]- >> knl_object_init
+
- >> knl_object_alloc_set_static
+
+
[Called By]
+
+tos_ring_q_dequeue (Thumb, 182 bytes, Stack size 32 bytes, tos_ring_queue.o(i.tos_ring_q_dequeue))
+
[Stack]
- Max Depth = 56 + Unknown Stack Size
+
- Call Chain = tos_ring_q_dequeue ⇒ tos_ring_q_is_empty ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> knl_object_verify
+
- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> tos_ring_q_is_empty
+
- >> __aeabi_memcpy
+
+
[Called By]- >> tos_chr_fifo_pop_stream
+
- >> tos_chr_fifo_pop
+
+
+tos_ring_q_destroy (Thumb, 90 bytes, Stack size 8 bytes, tos_ring_queue.o(i.tos_ring_q_destroy))
+
[Stack]
- Max Depth = 8
- Call Chain = tos_ring_q_destroy
+
+
[Calls]- >> knl_object_verify
+
- >> knl_object_deinit
+
- >> knl_object_alloc_reset
+
- >> knl_object_alloc_is_static
+
+
[Called By]- >> tos_chr_fifo_destroy
+
+
+tos_ring_q_enqueue (Thumb, 184 bytes, Stack size 24 bytes, tos_ring_queue.o(i.tos_ring_q_enqueue))
+
[Stack]
- Max Depth = 48 + Unknown Stack Size
+
- Call Chain = tos_ring_q_enqueue ⇒ tos_ring_q_is_full ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> knl_object_verify
+
- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> tos_ring_q_is_full
+
- >> __aeabi_memcpy
+
+
[Called By]- >> tos_chr_fifo_push_stream
+
- >> tos_chr_fifo_push
+
+
+tos_ring_q_is_empty (Thumb, 82 bytes, Stack size 16 bytes, tos_ring_queue.o(i.tos_ring_q_is_empty))
+
[Stack]
- Max Depth = 24 + Unknown Stack Size
+
- Call Chain = tos_ring_q_is_empty ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> knl_object_verify
+
- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
+
[Called By]
+
+tos_ring_q_is_full (Thumb, 86 bytes, Stack size 16 bytes, tos_ring_queue.o(i.tos_ring_q_is_full))
+
[Stack]
- Max Depth = 24 + Unknown Stack Size
+
- Call Chain = tos_ring_q_is_full ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> knl_object_verify
+
- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
+
[Called By]
+
+tos_sal_module_close (Thumb, 36 bytes, Stack size 8 bytes, sal_module_wrapper.o(i.tos_sal_module_close))
+
[Stack]
- Max Depth = 8
- Call Chain = tos_sal_module_close
+
+
[Called By]
+
+tos_sal_module_connect (Thumb, 44 bytes, Stack size 16 bytes, sal_module_wrapper.o(i.tos_sal_module_connect))
+
[Stack]
- Max Depth = 16
- Call Chain = tos_sal_module_connect
+
+
[Called By]
+
+tos_sal_module_init (Thumb, 32 bytes, Stack size 8 bytes, sal_module_wrapper.o(i.tos_sal_module_init))
+
[Stack]
- Max Depth = 8
- Call Chain = tos_sal_module_init
+
+
[Called By]- >> esp8266_sal_init
+
- >> HAL_TCP_Establish
+
+
+tos_sal_module_recv_timeout (Thumb, 54 bytes, Stack size 24 bytes, sal_module_wrapper.o(i.tos_sal_module_recv_timeout))
+
[Stack]
- Max Depth = 24
- Call Chain = tos_sal_module_recv_timeout
+
+
[Called By]
+
+tos_sal_module_register (Thumb, 22 bytes, Stack size 0 bytes, sal_module_wrapper.o(i.tos_sal_module_register))
+
[Called By]
+
+tos_sal_module_send (Thumb, 44 bytes, Stack size 16 bytes, sal_module_wrapper.o(i.tos_sal_module_send))
+
[Stack]
- Max Depth = 16
- Call Chain = tos_sal_module_send
+
+
[Called By]
+
+tos_sem_create (Thumb, 20 bytes, Stack size 16 bytes, tos_sem.o(i.tos_sem_create))
+
[Stack]
- Max Depth = 40
- Call Chain = tos_sem_create ⇒ tos_sem_create_max ⇒ pend_object_init
+
+
[Calls]
+
[Called By]- >> tos_at_raw_data_send_until
+
- >> tos_at_cmd_exec_until
+
- >> tos_at_init
+
+
+tos_sem_create_max (Thumb, 52 bytes, Stack size 16 bytes, tos_sem.o(i.tos_sem_create_max))
+
[Stack]
- Max Depth = 24
- Call Chain = tos_sem_create_max ⇒ pend_object_init
+
+
[Calls]- >> knl_object_init
+
- >> pend_object_init
+
+
[Called By]
+
+tos_sem_destroy (Thumb, 104 bytes, Stack size 16 bytes, tos_sem.o(i.tos_sem_destroy))
+
[Stack]
- Max Depth = 96 + Unknown Stack Size
+
- Call Chain = tos_sem_destroy ⇒ pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]- >> knl_object_verify
+
- >> knl_object_deinit
+
- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> pend_wakeup_all
+
- >> pend_object_deinit
+
- >> pend_is_nopending
+
- >> knl_sched
+
+
[Called By]- >> tos_at_raw_data_send_until
+
- >> tos_at_cmd_exec_until
+
- >> tos_at_init
+
+
+tos_sem_pend (Thumb, 206 bytes, Stack size 24 bytes, tos_sem.o(i.tos_sem_pend))
+
[Stack]
- Max Depth = 128 + Unknown Stack Size
+
- Call Chain = tos_sem_pend ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> knl_object_verify
+
- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> pend_task_block
+
- >> pend_state2errno
+
- >> knl_sched
+
- >> knl_is_sched_locked
+
- >> knl_is_inirq
+
+
[Called By]- >> at_uart_getchar
+
- >> tos_at_raw_data_send_until
+
- >> tos_at_cmd_exec_until
+
+
+tos_sem_post (Thumb, 14 bytes, Stack size 8 bytes, tos_sem.o(i.tos_sem_post))
+
[Stack]
- Max Depth = 120 + Unknown Stack Size
+
- Call Chain = tos_sem_post ⇒ sem_do_post ⇒ pend_wakeup ⇒ pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]
+
[Called By]- >> tos_at_uart_write_byte
+
- >> at_parser
+
+
+tos_sleep_hmsm (Thumb, 112 bytes, Stack size 40 bytes, tos_time.o(i.tos_sleep_hmsm))
+
[Stack]
- Max Depth = 136 + Unknown Stack Size
+
- Call Chain = tos_sleep_hmsm ⇒ tos_task_delay ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_task_delay
+
- >> __aeabi_uldivmod
+
+
[Called By]
+
+tos_systick_get (Thumb, 34 bytes, Stack size 16 bytes, tos_time.o(i.tos_systick_get))
+
[Stack]
- Max Depth = 24 + Unknown Stack Size
+
- Call Chain = tos_systick_get ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
+
[Called By]- >> at_timer_remain
+
- >> at_timer_is_expired
+
- >> at_timer_countdown
+
- >> at_delay
+
- >> HAL_UptimeMs
+
+
+tos_task_create (Thumb, 292 bytes, Stack size 40 bytes, tos_task.o(i.tos_task_create))
+
[Stack]
- Max Depth = 72 + Unknown Stack Size
+
- Call Chain = tos_task_create ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]- >> tos_knl_is_running
+
- >> knl_object_init
+
- >> knl_object_alloc_set_static
+
- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> knl_sched
+
- >> knl_is_inirq
+
- >> readyqueue_add_tail
+
- >> cpu_task_stk_init
+
- >> tos_list_add
+
- >> task_reset
+
- >> knl_is_idle
+
+
[Called By]- >> osThreadCreate
+
- >> knl_idle_init
+
- >> tos_at_init
+
+
+tos_task_delay (Thumb, 136 bytes, Stack size 16 bytes, tos_task.o(i.tos_task_delay))
+
[Stack]
- Max Depth = 96 + Unknown Stack Size
+
- Call Chain = tos_task_delay ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> knl_sched
+
- >> knl_is_sched_locked
+
- >> knl_is_inirq
+
- >> tick_list_add
+
- >> readyqueue_remove
+
- >> tos_task_yield
+
+
[Called By]- >> application_entry
+
- >> tos_sleep_hmsm
+
- >> tos_at_cmd_exec
+
+
+tos_task_destroy (Thumb, 106 bytes, Stack size 8 bytes, tos_task.o(i.tos_task_destroy))
+
[Stack]
- Max Depth = 128 + Unknown Stack Size
+
- Call Chain = tos_task_destroy ⇒ task_do_destroy ⇒ task_mutex_release ⇒ mutex_release ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz
+
+
[Calls]- >> knl_object_verify
+
- >> knl_object_alloc_is_static
+
- >> knl_is_self
+
- >> knl_is_sched_locked
+
- >> knl_is_inirq
+
- >> task_do_destroy
+
+
[Called By]- >> task_exit
+
- >> tos_at_init
+
+
+tos_task_prio_change (Thumb, 248 bytes, Stack size 24 bytes, tos_task.o(i.tos_task_prio_change))
+
[Stack]
- Max Depth = 64 + Unknown Stack Size
+
- Call Chain = tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz
+
+
[Calls]- >> knl_object_verify
+
- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> knl_is_self
+
- >> knl_sched
+
- >> knl_is_inirq
+
- >> readyqueue_add_tail
+
- >> readyqueue_add_head
+
- >> readyqueue_remove
+
- >> pend_list_adjust
+
- >> tos_list_empty
+
- >> task_state_is_ready
+
- >> task_highest_pending_prio_get
+
+
[Called By]- >> tos_mutex_post
+
- >> tos_mutex_pend_timed
+
- >> mutex_old_owner_release
+
+
+tos_task_yield (Thumb, 56 bytes, Stack size 8 bytes, tos_task.o(i.tos_task_yield))
+
[Stack]
- Max Depth = 48 + Unknown Stack Size
+
- Call Chain = tos_task_yield ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz
+
+
[Calls]- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> knl_sched
+
- >> knl_is_inirq
+
- >> readyqueue_add_tail
+
- >> readyqueue_remove
+
+
[Called By]
+
+tos_tick_handler (Thumb, 34 bytes, Stack size 8 bytes, tos_tick.o(i.tos_tick_handler))
+
[Stack]
- Max Depth = 96 + Unknown Stack Size
+
- Call Chain = tos_tick_handler ⇒ tick_update ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]- >> tos_knl_is_running
+
- >> timer_update
+
- >> tick_update
+
+
[Called By]
+
+utils_hmac_sha256 (Thumb, 194 bytes, Stack size 264 bytes, infra_sha256.o(i.utils_hmac_sha256))
+
[Stack]
- Max Depth = 640
- Call Chain = utils_hmac_sha256 ⇒ utils_sha256_finish ⇒ utils_sha256_update ⇒ utils_sha256_process
+
+
[Calls]- >> utils_sha256_update
+
- >> utils_sha256_starts
+
- >> utils_sha256_init
+
- >> utils_sha256_finish
+
- >> __aeabi_memclr4
+
- >> __aeabi_memcpy
+
+
[Called By]- >> _iotx_generate_sign_string
+
+
+utils_net_read (Thumb, 62 bytes, Stack size 32 bytes, infra_net.o(i.utils_net_read))
+
[Stack]
- Max Depth = 160
- Call Chain = utils_net_read ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> LITE_syslog
+
- >> read_tcp
+
+
[Address Reference Count : 1]- infra_net.o(i.iotx_net_init)
+
+utils_net_write (Thumb, 62 bytes, Stack size 32 bytes, infra_net.o(i.utils_net_write))
+
[Stack]
- Max Depth = 160
- Call Chain = utils_net_write ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> LITE_syslog
+
- >> write_tcp
+
+
[Address Reference Count : 1]- infra_net.o(i.iotx_net_init)
+
+utils_sha256_finish (Thumb, 350 bytes, Stack size 40 bytes, infra_sha256.o(i.utils_sha256_finish))
+
[Stack]
- Max Depth = 376
- Call Chain = utils_sha256_finish ⇒ utils_sha256_update ⇒ utils_sha256_process
+
+
[Calls]
+
[Called By]
+
+utils_sha256_init (Thumb, 14 bytes, Stack size 8 bytes, infra_sha256.o(i.utils_sha256_init))
+
[Stack]
- Max Depth = 8
- Call Chain = utils_sha256_init
+
+
[Calls]
+
[Called By]
+
+utils_sha256_process (Thumb, 444 bytes, Stack size 312 bytes, infra_sha256.o(i.utils_sha256_process))
+
[Stack]
- Max Depth = 312
- Call Chain = utils_sha256_process
+
+
[Called By]
+
+utils_sha256_starts (Thumb, 46 bytes, Stack size 0 bytes, infra_sha256.o(i.utils_sha256_starts))
+
[Called By]
+
+utils_sha256_update (Thumb, 124 bytes, Stack size 24 bytes, infra_sha256.o(i.utils_sha256_update))
+
[Stack]
- Max Depth = 336
- Call Chain = utils_sha256_update ⇒ utils_sha256_process
+
+
[Calls]- >> utils_sha256_process
+
- >> __aeabi_memcpy
+
+
[Called By]- >> utils_sha256_finish
+
- >> utils_hmac_sha256
+
+
+utils_time_countdown_ms (Thumb, 22 bytes, Stack size 16 bytes, infra_timer.o(i.utils_time_countdown_ms))
+
[Stack]
- Max Depth = 48 + Unknown Stack Size
+
- Call Chain = utils_time_countdown_ms ⇒ HAL_UptimeMs ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save
+
+
[Calls]
+
[Called By]- >> iotx_mc_wait_CONNACK
+
- >> iotx_mc_keepalive_sub
+
- >> iotx_mc_keepalive
+
- >> iotx_mc_handle_reconnect
+
- >> _mqtt_connect
+
- >> MQTTSubscribe
+
- >> MQTTRePublish
+
- >> MQTTPuback
+
- >> MQTTKeepalive
+
- >> MQTTDisconnect
+
- >> _mqtt_cycle
+
- >> MQTTPublish
+
- >> MQTTConnect
+
+
+utils_time_is_expired (Thumb, 36 bytes, Stack size 16 bytes, infra_timer.o(i.utils_time_is_expired))
+
[Stack]
- Max Depth = 48 + Unknown Stack Size
+
- Call Chain = utils_time_is_expired ⇒ HAL_UptimeMs ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save
+
+
[Calls]
+
[Called By]- >> iotx_mc_send_packet
+
- >> iotx_mc_keepalive_sub
+
- >> iotx_mc_handle_reconnect
+
- >> iotx_time_left
+
- >> _mqtt_cycle
+
+
+utils_time_spend (Thumb, 24 bytes, Stack size 16 bytes, infra_timer.o(i.utils_time_spend))
+
[Stack]
- Max Depth = 48 + Unknown Stack Size
+
- Call Chain = utils_time_spend ⇒ HAL_UptimeMs ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save
+
+
[Calls]
+
[Called By]
+
+wrapper_mqtt_check_state (Thumb, 28 bytes, Stack size 8 bytes, iotx_mqtt_client.o(i.wrapper_mqtt_check_state))
+
[Stack]
- Max Depth = 176 + Unknown Stack Size
+
- Call Chain = wrapper_mqtt_check_state ⇒ iotx_mc_get_client_state ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_get_client_state
+
+
[Called By]- >> iotx_mc_keepalive_sub
+
- >> iotx_mc_disconnect
+
- >> wrapper_mqtt_subscribe
+
- >> wrapper_mqtt_publish
+
+
+wrapper_mqtt_connect (Thumb, 202 bytes, Stack size 48 bytes, iotx_mqtt_client.o(i.wrapper_mqtt_connect))
+
[Stack]
- Max Depth = 848 + Unknown Stack Size
+
- Call Chain = wrapper_mqtt_connect ⇒ _mqtt_connect ⇒ iotx_mc_wait_CONNACK ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> _mqtt_connect
+
- >> LITE_syslog
+
- >> HAL_SleepMs
+
+
[Called By]- >> IOT_MQTT_Construct
+
- >> iotx_mc_attempt_reconnect
+
+
+wrapper_mqtt_init (Thumb, 152 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.wrapper_mqtt_init))
+
[Stack]
- Max Depth = 312 + Unknown Stack Size
+
- Call Chain = wrapper_mqtt_init ⇒ iotx_mc_init ⇒ iotx_mc_set_client_state ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_release
+
- >> iotx_mc_init
+
- >> LITE_syslog
+
+
[Called By]
+
+wrapper_mqtt_publish (Thumb, 232 bytes, Stack size 40 bytes, iotx_mqtt_client.o(i.wrapper_mqtt_publish))
+
[Stack]
- Max Depth = 280 + Unknown Stack Size
+
- Call Chain = wrapper_mqtt_publish ⇒ iotx_mc_check_topic ⇒ iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> iotx_mc_set_client_state
+
- >> iotx_mc_get_next_packetid
+
- >> iotx_mc_get_client_state
+
- >> iotx_mc_check_topic
+
- >> wrapper_mqtt_check_state
+
- >> LITE_syslog
+
- >> MQTTPublish
+
+
[Called By]- >> IOT_MQTT_Publish_Simple
+
+
+wrapper_mqtt_release (Thumb, 148 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.wrapper_mqtt_release))
+
[Stack]
- Max Depth = 216 + Unknown Stack Size
+
- Call Chain = wrapper_mqtt_release ⇒ iotx_mc_disconnect ⇒ MQTTDisconnect ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_set_client_state
+
- >> iotx_mc_pub_wait_list_deinit
+
- >> iotx_mc_disconnect
+
- >> LITE_syslog
+
- >> HAL_SleepMs
+
- >> HAL_MutexDestroy
+
- >> __aeabi_memclr4
+
+
[Called By]- >> IOT_MQTT_Destroy
+
- >> IOT_MQTT_Construct
+
+
+wrapper_mqtt_subscribe (Thumb, 256 bytes, Stack size 64 bytes, iotx_mqtt_client.o(i.wrapper_mqtt_subscribe))
+
[Stack]
- Max Depth = 304 + Unknown Stack Size
+
- Call Chain = wrapper_mqtt_subscribe ⇒ iotx_mc_check_topic ⇒ iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> iotx_mc_set_client_state
+
- >> iotx_mc_get_next_packetid
+
- >> iotx_mc_get_client_state
+
- >> iotx_mc_check_topic
+
- >> MQTTSubscribe
+
- >> wrapper_mqtt_check_state
+
- >> LITE_syslog
+
- >> strlen
+
+
[Called By]- >> IOT_MQTT_Subscribe
+
- >> iotx_mqtt_deal_offline_subs
+
+
+wrapper_mqtt_yield (Thumb, 88 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.wrapper_mqtt_yield))
+
[Stack]
- Max Depth = 952 + Unknown Stack Size
+
- Call Chain = wrapper_mqtt_yield ⇒ iotx_mc_keepalive ⇒ iotx_mc_handle_reconnect ⇒ iotx_mc_attempt_reconnect ⇒ wrapper_mqtt_connect ⇒ _mqtt_connect ⇒ iotx_mc_wait_CONNACK ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_keepalive
+
- >> LITE_syslog
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
- >> _mqtt_cycle
+
+
[Called By]
+
+writeCString (Thumb, 40 bytes, Stack size 16 bytes, mqttpacket.o(i.writeCString))
+
[Stack]
- Max Depth = 24
- Call Chain = writeCString ⇒ writeInt
+
+
[Calls]- >> writeInt
+
- >> strlen
+
- >> __aeabi_memcpy
+
+
[Called By]- >> writeMQTTString
+
- >> MQTTSerialize_connect
+
+
+writeChar (Thumb, 12 bytes, Stack size 0 bytes, mqttpacket.o(i.writeChar))
+
[Called By]
- >> MQTTSerialize_zero
+
- >> MQTTSerialize_subscribe
+
- >> MQTTSerialize_publish
+
- >> MQTTSerialize_connect
+
- >> MQTTSerialize_ack
+
+
+writeInt (Thumb, 48 bytes, Stack size 8 bytes, mqttpacket.o(i.writeInt))
+
[Stack]
- Max Depth = 8
- Call Chain = writeInt
+
+
[Called By]- >> writeMQTTString
+
- >> writeCString
+
- >> MQTTSerialize_subscribe
+
- >> MQTTSerialize_publish
+
- >> MQTTSerialize_connect
+
- >> MQTTSerialize_ack
+
+
+writeMQTTString (Thumb, 62 bytes, Stack size 24 bytes, mqttpacket.o(i.writeMQTTString))
+
[Stack]
- Max Depth = 48
- Call Chain = writeMQTTString ⇒ writeCString ⇒ writeInt
+
+
[Calls]- >> writeInt
+
- >> writeCString
+
- >> __aeabi_memcpy
+
+
[Called By]- >> MQTTSerialize_subscribe
+
- >> MQTTSerialize_publish
+
- >> MQTTSerialize_connect
+
+
+
+Local Symbols
+
+UART_DMAAbortOnError (Thumb, 24 bytes, Stack size 16 bytes, stm32l4xx_hal_uart.o(i.UART_DMAAbortOnError))
+
[Stack]
- Max Depth = 16
- Call Chain = UART_DMAAbortOnError
+
+
[Calls]- >> HAL_UART_ErrorCallback
+
+
[Address Reference Count : 1]- stm32l4xx_hal_uart.o(i.HAL_UART_IRQHandler)
+
+UART_EndRxTransfer (Thumb, 36 bytes, Stack size 0 bytes, stm32l4xx_hal_uart.o(i.UART_EndRxTransfer))
+
[Called By]
+
+UART_EndTransmit_IT (Thumb, 34 bytes, Stack size 8 bytes, stm32l4xx_hal_uart.o(i.UART_EndTransmit_IT))
+
[Stack]
- Max Depth = 8
- Call Chain = UART_EndTransmit_IT
+
+
[Calls]- >> HAL_UART_TxCpltCallback
+
+
[Called By]
+
+UART_RxISR_16BIT (Thumb, 108 bytes, Stack size 24 bytes, stm32l4xx_hal_uart.o(i.UART_RxISR_16BIT))
+
[Stack]
- Max Depth = 160 + Unknown Stack Size
+
- Call Chain = UART_RxISR_16BIT ⇒ HAL_UART_RxCpltCallback ⇒ tos_at_uart_write_byte ⇒ tos_sem_post ⇒ sem_do_post ⇒ pend_wakeup ⇒ pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]- >> HAL_UART_RxCpltCallback
+
+
[Address Reference Count : 1]- stm32l4xx_hal_uart.o(i.HAL_UART_Receive_IT)
+
+UART_RxISR_8BIT (Thumb, 102 bytes, Stack size 16 bytes, stm32l4xx_hal_uart.o(i.UART_RxISR_8BIT))
+
[Stack]
- Max Depth = 152 + Unknown Stack Size
+
- Call Chain = UART_RxISR_8BIT ⇒ HAL_UART_RxCpltCallback ⇒ tos_at_uart_write_byte ⇒ tos_sem_post ⇒ sem_do_post ⇒ pend_wakeup ⇒ pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]- >> HAL_UART_RxCpltCallback
+
+
[Address Reference Count : 1]- stm32l4xx_hal_uart.o(i.HAL_UART_Receive_IT)
+
+RCC_SetFlashLatencyFromMSIRange (Thumb, 148 bytes, Stack size 24 bytes, stm32l4xx_hal_rcc.o(i.RCC_SetFlashLatencyFromMSIRange))
+
[Stack]
- Max Depth = 24
- Call Chain = RCC_SetFlashLatencyFromMSIRange
+
+
[Calls]- >> HAL_PWREx_GetVoltageRange
+
+
[Called By]
+
+RCCEx_PLLSAI1_Config (Thumb, 376 bytes, Stack size 24 bytes, stm32l4xx_hal_rcc_ex.o(i.RCCEx_PLLSAI1_Config))
+
[Stack]
- Max Depth = 24
- Call Chain = RCCEx_PLLSAI1_Config
+
+
[Calls]
+
[Called By]- >> HAL_RCCEx_PeriphCLKConfig
+
+
+__NVIC_GetPriorityGrouping (Thumb, 10 bytes, Stack size 0 bytes, stm32l4xx_hal_cortex.o(i.__NVIC_GetPriorityGrouping))
+
[Called By]
- >> HAL_NVIC_SetPriority
+
+
+__NVIC_SetPriority (Thumb, 32 bytes, Stack size 8 bytes, stm32l4xx_hal_cortex.o(i.__NVIC_SetPriority))
+
[Stack]
- Max Depth = 8
- Call Chain = __NVIC_SetPriority
+
+
[Called By]- >> HAL_NVIC_SetPriority
+
- >> HAL_SYSTICK_Config
+
+
+DHT11_Mode_Out_PP (Thumb, 30 bytes, Stack size 24 bytes, dht11_bus.o(i.DHT11_Mode_Out_PP))
+
[Stack]
- Max Depth = 44
- Call Chain = DHT11_Mode_Out_PP ⇒ HAL_GPIO_Init
+
+
[Calls]
+
[Called By]
+
+__ffs (Thumb, 20 bytes, Stack size 8 bytes, tos_mmheap.o(i.__ffs))
+
[Stack]
- Max Depth = 24 + Unknown Stack Size
+
- Call Chain = __ffs ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]
+
[Called By]
+
+__fls (Thumb, 14 bytes, Stack size 8 bytes, tos_mmheap.o(i.__fls))
+
[Stack]
- Max Depth = 24 + Unknown Stack Size
+
- Call Chain = __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]
+
[Called By]- >> mapping_search
+
- >> mapping_insert
+
+
+adjust_request_size (Thumb, 46 bytes, Stack size 8 bytes, tos_mmheap.o(i.adjust_request_size))
+
[Stack]
- Max Depth = 8
- Call Chain = adjust_request_size
+
+
[Called By]
+
+blk_absorb (Thumb, 30 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_absorb))
+
[Stack]
- Max Depth = 56
- Call Chain = blk_absorb ⇒ blk_link_next ⇒ blk_next
+
+
[Calls]- >> blk_size
+
- >> blk_link_next
+
+
[Called By]- >> blk_merge_prev
+
- >> blk_merge_next
+
+
+blk_can_split (Thumb, 28 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_can_split))
+
[Stack]
- Max Depth = 16
- Call Chain = blk_can_split
+
+
[Calls]
+
[Called By]
+
+blk_insert (Thumb, 32 bytes, Stack size 24 bytes, tos_mmheap.o(i.blk_insert))
+
[Stack]
- Max Depth = 72 + Unknown Stack Size
+
- Call Chain = blk_insert ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]- >> mapping_insert
+
- >> insert_free_block
+
- >> blk_size
+
+
[Called By]- >> tos_mmheap_free
+
- >> tos_mmheap_pool_add
+
- >> blk_trim_free
+
+
+blk_link_next (Thumb, 18 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_link_next))
+
[Stack]
- Max Depth = 40
- Call Chain = blk_link_next ⇒ blk_next
+
+
[Calls]
+
[Called By]- >> tos_mmheap_pool_add
+
- >> blk_trim_free
+
- >> blk_mark_as_free
+
- >> blk_absorb
+
+
+blk_locate_free (Thumb, 58 bytes, Stack size 24 bytes, tos_mmheap.o(i.blk_locate_free))
+
[Stack]
- Max Depth = 96 + Unknown Stack Size
+
- Call Chain = blk_locate_free ⇒ mapping_search ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]- >> remove_free_block
+
- >> mapping_search
+
- >> blk_search_suitable
+
+
[Called By]
+
+blk_mark_as_free (Thumb, 26 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_mark_as_free))
+
[Stack]
- Max Depth = 56
- Call Chain = blk_mark_as_free ⇒ blk_link_next ⇒ blk_next
+
+
[Calls]- >> blk_set_prev_free
+
- >> blk_set_free
+
- >> blk_link_next
+
+
[Called By]- >> tos_mmheap_free
+
- >> blk_split
+
+
+blk_mark_as_used (Thumb, 26 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_mark_as_used))
+
[Stack]
- Max Depth = 40
- Call Chain = blk_mark_as_used ⇒ blk_next
+
+
[Calls]- >> blk_set_used
+
- >> blk_set_prev_used
+
- >> blk_next
+
+
[Called By]
+
+blk_merge_next (Thumb, 42 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_merge_next))
+
[Stack]
- Max Depth = 88 + Unknown Stack Size
+
- Call Chain = blk_merge_next ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]- >> blk_remove
+
- >> blk_next
+
- >> blk_absorb
+
+
[Called By]
+
+blk_merge_prev (Thumb, 40 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_merge_prev))
+
[Stack]
- Max Depth = 88 + Unknown Stack Size
+
- Call Chain = blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]- >> blk_remove
+
- >> blk_absorb
+
+
[Called By]
+
+blk_next (Thumb, 36 bytes, Stack size 24 bytes, tos_mmheap.o(i.blk_next))
+
[Stack]
- Max Depth = 24
- Call Chain = blk_next
+
+
[Calls]- >> offset_to_block
+
- >> blk_to_ptr
+
- >> blk_size
+
+
[Called By]- >> blk_merge_next
+
- >> blk_mark_as_used
+
- >> blk_link_next
+
+
+blk_prepare_used (Thumb, 34 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_prepare_used))
+
[Stack]
- Max Depth = 112 + Unknown Stack Size
+
- Call Chain = blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next
+
+
[Calls]- >> blk_trim_free
+
- >> blk_to_ptr
+
- >> blk_mark_as_used
+
+
[Called By]
+
+blk_remove (Thumb, 32 bytes, Stack size 24 bytes, tos_mmheap.o(i.blk_remove))
+
[Stack]
- Max Depth = 72 + Unknown Stack Size
+
- Call Chain = blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]- >> remove_free_block
+
- >> mapping_insert
+
- >> blk_size
+
+
[Called By]- >> blk_merge_prev
+
- >> blk_merge_next
+
+
+blk_search_suitable (Thumb, 104 bytes, Stack size 32 bytes, tos_mmheap.o(i.blk_search_suitable))
+
[Stack]
- Max Depth = 56 + Unknown Stack Size
+
- Call Chain = blk_search_suitable ⇒ __ffs ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]
+
[Called By]
+
+blk_set_free (Thumb, 10 bytes, Stack size 0 bytes, tos_mmheap.o(i.blk_set_free))
+
[Called By]
- >> tos_mmheap_pool_add
+
- >> blk_mark_as_free
+
+
+blk_set_prev_free (Thumb, 10 bytes, Stack size 0 bytes, tos_mmheap.o(i.blk_set_prev_free))
+
[Called By]
- >> tos_mmheap_pool_add
+
- >> blk_trim_free
+
- >> blk_mark_as_free
+
+
+blk_set_prev_used (Thumb, 10 bytes, Stack size 0 bytes, tos_mmheap.o(i.blk_set_prev_used))
+
[Called By]
- >> tos_mmheap_pool_add
+
- >> blk_mark_as_used
+
+
+blk_set_size (Thumb, 12 bytes, Stack size 0 bytes, tos_mmheap.o(i.blk_set_size))
+
[Called By]
- >> tos_mmheap_pool_add
+
- >> blk_split
+
+
+blk_set_used (Thumb, 10 bytes, Stack size 0 bytes, tos_mmheap.o(i.blk_set_used))
+
[Called By]
- >> tos_mmheap_pool_add
+
- >> blk_mark_as_used
+
+
+blk_size (Thumb, 10 bytes, Stack size 0 bytes, tos_mmheap.o(i.blk_size))
+
[Called By]
- >> blk_split
+
- >> blk_remove
+
- >> blk_next
+
- >> blk_insert
+
- >> blk_can_split
+
- >> blk_absorb
+
+
+blk_split (Thumb, 62 bytes, Stack size 24 bytes, tos_mmheap.o(i.blk_split))
+
[Stack]
- Max Depth = 80
- Call Chain = blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next
+
+
[Calls]- >> offset_to_block
+
- >> blk_to_ptr
+
- >> blk_size
+
- >> blk_set_size
+
- >> blk_mark_as_free
+
+
[Called By]
+
+blk_to_ptr (Thumb, 8 bytes, Stack size 0 bytes, tos_mmheap.o(i.blk_to_ptr))
+
[Called By]
- >> blk_split
+
- >> blk_prepare_used
+
- >> blk_next
+
+
+blk_trim_free (Thumb, 46 bytes, Stack size 16 bytes, tos_mmheap.o(i.blk_trim_free))
+
[Stack]
- Max Depth = 96 + Unknown Stack Size
+
- Call Chain = blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next
+
+
[Calls]- >> blk_split
+
- >> blk_set_prev_free
+
- >> blk_link_next
+
- >> blk_insert
+
- >> blk_can_split
+
+
[Called By]
+
+generic_fls (Thumb, 16 bytes, Stack size 8 bytes, tos_mmheap.o(i.generic_fls))
+
[Stack]
- Max Depth = 16 + Unknown Stack Size
+
- Call Chain = generic_fls ⇒ tos_cpu_clz
+
+
[Calls]
+
[Called By]
+
+insert_free_block (Thumb, 74 bytes, Stack size 12 bytes, tos_mmheap.o(i.insert_free_block))
+
[Stack]
- Max Depth = 12
- Call Chain = insert_free_block
+
+
[Called By]
+
+mapping_insert (Thumb, 58 bytes, Stack size 24 bytes, tos_mmheap.o(i.mapping_insert))
+
[Stack]
- Max Depth = 48 + Unknown Stack Size
+
- Call Chain = mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]
+
[Called By]- >> mapping_search
+
- >> blk_remove
+
- >> blk_insert
+
+
+mapping_search (Thumb, 46 bytes, Stack size 24 bytes, tos_mmheap.o(i.mapping_search))
+
[Stack]
- Max Depth = 72 + Unknown Stack Size
+
- Call Chain = mapping_search ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]- >> mapping_insert
+
- >> __fls
+
+
[Called By]
+
+mmheap_ctl_init (Thumb, 88 bytes, Stack size 0 bytes, tos_mmheap.o(i.mmheap_ctl_init))
+
[Called By]
- >> mmheap_init_with_pool
+
+
+mmheap_pool_is_exist (Thumb, 38 bytes, Stack size 0 bytes, tos_mmheap.o(i.mmheap_pool_is_exist))
+
[Called By]
+
+offset_to_block (Thumb, 6 bytes, Stack size 0 bytes, tos_mmheap.o(i.offset_to_block))
+
[Called By]
- >> tos_mmheap_pool_add
+
- >> blk_split
+
- >> blk_next
+
+
+remove_free_block (Thumb, 92 bytes, Stack size 16 bytes, tos_mmheap.o(i.remove_free_block))
+
[Stack]
- Max Depth = 16
- Call Chain = remove_free_block
+
+
[Called By]- >> blk_remove
+
- >> blk_locate_free
+
+
+mutex_fresh_owner_mark (Thumb, 40 bytes, Stack size 8 bytes, tos_mutex.o(i.mutex_fresh_owner_mark))
+
[Stack]
- Max Depth = 8
- Call Chain = mutex_fresh_owner_mark
+
+
[Called By]- >> tos_mutex_post
+
- >> tos_mutex_pend_timed
+
+
+mutex_old_owner_release (Thumb, 74 bytes, Stack size 16 bytes, tos_mutex.o(i.mutex_old_owner_release))
+
[Stack]
- Max Depth = 80 + Unknown Stack Size
+
- Call Chain = mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz
+
+
[Calls]- >> tos_task_prio_change
+
+
[Called By]- >> tos_mutex_post
+
- >> tos_mutex_destroy
+
- >> mutex_release
+
+
+pend_list_add (Thumb, 68 bytes, Stack size 16 bytes, tos_pend.o(i.pend_list_add))
+
[Stack]
- Max Depth = 16
- Call Chain = pend_list_add
+
+
[Called By]- >> pend_task_block
+
- >> pend_list_adjust
+
+
+tos_list_del (Thumb, 12 bytes, Stack size 0 bytes, tos_pend.o(i.tos_list_del))
+
[Called By]
- >> pend_list_remove
+
- >> pend_list_adjust
+
+
+tos_list_empty (Thumb, 16 bytes, Stack size 0 bytes, tos_pend.o(i.tos_list_empty))
+
[Called By]
- >> pend_highest_pending_prio_get
+
- >> pend_is_nopending
+
+
+tos_list_init (Thumb, 6 bytes, Stack size 0 bytes, tos_pend.o(i.tos_list_init))
+
[Called By]
- >> pend_object_init
+
- >> pend_object_deinit
+
+
+_list_add (Thumb, 10 bytes, Stack size 0 bytes, tos_sched.o(i._list_add))
+
[Called By]
- >> readyqueue_add_head
+
- >> tos_list_add_tail
+
+
+_list_del (Thumb, 6 bytes, Stack size 0 bytes, tos_sched.o(i._list_del))
+
[Called By]
+
+readyqueue_prio_highest_get (Thumb, 36 bytes, Stack size 16 bytes, tos_sched.o(i.readyqueue_prio_highest_get))
+
[Stack]
- Max Depth = 24 + Unknown Stack Size
+
- Call Chain = readyqueue_prio_highest_get ⇒ tos_cpu_clz
+
+
[Calls]
+
[Called By]
+
+readyqueue_prio_mark (Thumb, 56 bytes, Stack size 0 bytes, tos_sched.o(i.readyqueue_prio_mark))
+
[Called By]
- >> readyqueue_add_tail
+
- >> readyqueue_add_head
+
+
+tos_list_add_tail (Thumb, 18 bytes, Stack size 16 bytes, tos_sched.o(i.tos_list_add_tail))
+
[Stack]
- Max Depth = 16
- Call Chain = tos_list_add_tail
+
+
[Calls]
+
[Called By]
+
+tos_list_empty (Thumb, 16 bytes, Stack size 0 bytes, tos_sched.o(i.tos_list_empty))
+
[Called By]
- >> readyqueue_add_tail
+
- >> readyqueue_add_head
+
- >> readyqueue_remove
+
+
+sem_do_post (Thumb, 140 bytes, Stack size 16 bytes, tos_sem.o(i.sem_do_post))
+
[Stack]
- Max Depth = 112 + Unknown Stack Size
+
- Call Chain = sem_do_post ⇒ pend_wakeup ⇒ pend_wakeup_all ⇒ pend_task_wakeup ⇒ readyqueue_add ⇒ readyqueue_add_tail ⇒ tos_list_add_tail
+
+
[Calls]- >> knl_object_verify
+
- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> pend_is_nopending
+
- >> knl_sched
+
- >> pend_wakeup
+
+
[Called By]
+
+knl_idle_entry (Thumb, 10 bytes, Stack size 0 bytes, tos_sys.o(i.knl_idle_entry))
+
[Stack]
- Max Depth = 136 + Unknown Stack Size
+
- Call Chain = knl_idle_entry ⇒ task_free_all ⇒ task_free ⇒ tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]
+
[Address Reference Count : 1]- tos_sys.o(i.knl_idle_init)
+
+task_do_destroy (Thumb, 132 bytes, Stack size 16 bytes, tos_task.o(i.task_do_destroy))
+
[Stack]
- Max Depth = 120 + Unknown Stack Size
+
- Call Chain = task_do_destroy ⇒ task_mutex_release ⇒ mutex_release ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz
+
+
[Calls]- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> knl_sched
+
- >> tick_list_remove
+
- >> readyqueue_remove
+
- >> pend_list_remove
+
- >> tos_list_empty
+
- >> tos_list_del
+
- >> task_state_is_ready
+
- >> task_reset
+
- >> task_mutex_release
+
- >> knl_is_idle
+
+
[Called By]
+
+task_exit (Thumb, 10 bytes, Stack size 8 bytes, tos_task.o(i.task_exit))
+
[Stack]
- Max Depth = 136 + Unknown Stack Size
+
- Call Chain = task_exit ⇒ tos_task_destroy ⇒ task_do_destroy ⇒ task_mutex_release ⇒ mutex_release ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz
+
+
[Calls]
+
[Address Reference Count : 1]- tos_task.o(i.tos_task_create)
+
+task_free (Thumb, 18 bytes, Stack size 8 bytes, tos_task.o(i.task_free))
+
[Stack]
- Max Depth = 112 + Unknown Stack Size
+
- Call Chain = task_free ⇒ tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]
+
[Called By]
+
+task_highest_pending_prio_get (Thumb, 48 bytes, Stack size 24 bytes, tos_task.o(i.task_highest_pending_prio_get))
+
[Stack]
- Max Depth = 40
- Call Chain = task_highest_pending_prio_get ⇒ pend_highest_pending_prio_get
+
+
[Calls]- >> pend_highest_pending_prio_get
+
+
[Called By]- >> tos_task_prio_change
+
+
+task_mutex_release (Thumb, 32 bytes, Stack size 16 bytes, tos_task.o(i.task_mutex_release))
+
[Stack]
- Max Depth = 104 + Unknown Stack Size
+
- Call Chain = task_mutex_release ⇒ mutex_release ⇒ mutex_old_owner_release ⇒ tos_task_prio_change ⇒ readyqueue_remove ⇒ readyqueue_prio_highest_get ⇒ tos_cpu_clz
+
+
[Calls]
+
[Called By]
+
+task_reset (Thumb, 78 bytes, Stack size 8 bytes, tos_task.o(i.task_reset))
+
[Stack]
- Max Depth = 8
- Call Chain = task_reset
+
+
[Calls]- >> knl_object_deinit
+
- >> knl_object_alloc_reset
+
- >> tos_list_init
+
+
[Called By]- >> task_do_destroy
+
- >> tos_task_create
+
+
+task_state_is_ready (Thumb, 14 bytes, Stack size 0 bytes, tos_task.o(i.task_state_is_ready))
+
[Called By]
- >> tos_task_prio_change
+
- >> task_do_destroy
+
+
+tos_list_add (Thumb, 14 bytes, Stack size 0 bytes, tos_task.o(i.tos_list_add))
+
[Called By]
+
+tos_list_del (Thumb, 12 bytes, Stack size 0 bytes, tos_task.o(i.tos_list_del))
+
[Called By]
- >> task_do_destroy
+
- >> task_free_all
+
+
+tos_list_empty (Thumb, 16 bytes, Stack size 0 bytes, tos_task.o(i.tos_list_empty))
+
[Called By]
- >> tos_task_prio_change
+
- >> task_do_destroy
+
+
+tos_list_init (Thumb, 6 bytes, Stack size 0 bytes, tos_task.o(i.tos_list_init))
+
[Called By]
+
+tick_task_place (Thumb, 184 bytes, Stack size 56 bytes, tos_tick.o(i.tick_task_place))
+
[Stack]
- Max Depth = 64 + Unknown Stack Size
+
- Call Chain = tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
+
[Called By]
+
+tick_task_takeoff (Thumb, 126 bytes, Stack size 16 bytes, tos_tick.o(i.tick_task_takeoff))
+
[Stack]
- Max Depth = 24 + Unknown Stack Size
+
- Call Chain = tick_task_takeoff ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
- >> tos_list_empty
+
+
[Called By]
+
+tos_list_empty (Thumb, 16 bytes, Stack size 0 bytes, tos_tick.o(i.tos_list_empty))
+
[Called By]
- >> tick_update
+
- >> tick_task_takeoff
+
+
+timer_place (Thumb, 130 bytes, Stack size 24 bytes, tos_timer.o(i.timer_place))
+
[Stack]
- Max Depth = 32 + Unknown Stack Size
+
- Call Chain = timer_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
+
[Called By]
+
+timer_takeoff (Thumb, 110 bytes, Stack size 24 bytes, tos_timer.o(i.timer_takeoff))
+
[Stack]
- Max Depth = 32 + Unknown Stack Size
+
- Call Chain = timer_takeoff ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_cpu_cpsr_save
+
- >> tos_cpu_cpsr_restore
+
+
[Called By]
+
+__NVIC_SetPriority (Thumb, 32 bytes, Stack size 8 bytes, port_c.o(i.__NVIC_SetPriority))
+
[Stack]
- Max Depth = 8
- Call Chain = __NVIC_SetPriority
+
+
[Called By]- >> port_systick_priority_set
+
- >> port_systick_config
+
+
+errno_knl2cmsis (Thumb, 12 bytes, Stack size 0 bytes, cmsis_os.o(i.errno_knl2cmsis))
+
[Called By]
- >> osKernelStart
+
- >> osKernelInitialize
+
+
+priority_cmsis2knl (Thumb, 18 bytes, Stack size 0 bytes, cmsis_os.o(i.priority_cmsis2knl))
+
[Called By]
+
+esp8266_close (Thumb, 28 bytes, Stack size 8 bytes, esp8266.o(i.esp8266_close))
+
[Stack]
- Max Depth = 240 + Unknown Stack Size
+
- Call Chain = esp8266_close ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_at_cmd_exec
+
- >> tos_at_channel_free
+
+
[Address Reference Count : 1]
+esp8266_connect (Thumb, 100 bytes, Stack size 80 bytes, esp8266.o(i.esp8266_connect))
+
[Stack]
- Max Depth = 376 + Unknown Stack Size
+
- Call Chain = esp8266_connect ⇒ esp8266_reconnect_init ⇒ esp8266_multilink_set ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_at_cmd_exec_until
+
- >> tos_at_channel_alloc
+
- >> esp8266_reconnect_init
+
- >> tos_at_echo_create
+
- >> tos_at_channel_free
+
+
[Address Reference Count : 1]
+esp8266_echo_close (Thumb, 48 bytes, Stack size 48 bytes, esp8266.o(i.esp8266_echo_close))
+
[Stack]
- Max Depth = 280 + Unknown Stack Size
+
- Call Chain = esp8266_echo_close ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_at_echo_create
+
- >> tos_at_cmd_exec
+
+
[Called By]- >> esp8266_reconnect_init
+
- >> esp8266_init
+
+
+esp8266_incoming_data_process (Thumb, 132 bytes, Stack size 16 bytes, esp8266.o(i.esp8266_incoming_data_process))
+
[Stack]
- Max Depth = 200 + Unknown Stack Size
+
- Call Chain = esp8266_incoming_data_process ⇒ tos_at_uart_read ⇒ at_uart_getchar ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_at_uart_read
+
- >> tos_at_channel_write
+
+
[Address Reference Count : 1]
+esp8266_init (Thumb, 114 bytes, Stack size 8 bytes, esp8266.o(i.esp8266_init))
+
[Stack]
- Max Depth = 304 + Unknown Stack Size
+
- Call Chain = esp8266_init ⇒ esp8266_net_mode_set ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> esp8266_send_mode_set
+
- >> esp8266_restore
+
- >> esp8266_net_mode_set
+
- >> esp8266_multilink_set
+
- >> esp8266_echo_close
+
- >> __2printf
+
+
[Address Reference Count : 1]
+esp8266_is_link_broken (Thumb, 32 bytes, Stack size 8 bytes, esp8266.o(i.esp8266_is_link_broken))
+
[Stack]
- Max Depth = 20
- Call Chain = esp8266_is_link_broken ⇒ strstr
+
+
[Calls]
+
[Called By]- >> esp8266_sendto
+
- >> esp8266_send
+
+
+esp8266_multilink_set (Thumb, 80 bytes, Stack size 56 bytes, esp8266.o(i.esp8266_multilink_set))
+
[Stack]
- Max Depth = 288 + Unknown Stack Size
+
- Call Chain = esp8266_multilink_set ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_at_echo_create
+
- >> tos_at_cmd_exec
+
+
[Called By]- >> esp8266_reconnect_init
+
- >> esp8266_init
+
+
+esp8266_net_mode_set (Thumb, 104 bytes, Stack size 64 bytes, esp8266.o(i.esp8266_net_mode_set))
+
[Stack]
- Max Depth = 296 + Unknown Stack Size
+
- Call Chain = esp8266_net_mode_set ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_at_echo_create
+
- >> tos_at_cmd_exec
+
+
[Called By]
+
+esp8266_parse_domain (Thumb, 102 bytes, Stack size 128 bytes, esp8266.o(i.esp8266_parse_domain))
+
[Stack]
- Max Depth = 424 + Unknown Stack Size
+
- Call Chain = esp8266_parse_domain ⇒ esp8266_reconnect_init ⇒ esp8266_multilink_set ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> esp8266_reconnect_init
+
- >> tos_at_echo_create
+
- >> tos_at_cmd_exec
+
- >> strstr
+
- >> __0sscanf
+
- >> __2printf
+
+
[Address Reference Count : 1]
+esp8266_reconnect_init (Thumb, 44 bytes, Stack size 8 bytes, esp8266.o(i.esp8266_reconnect_init))
+
[Stack]
- Max Depth = 296 + Unknown Stack Size
+
- Call Chain = esp8266_reconnect_init ⇒ esp8266_multilink_set ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> esp8266_multilink_set
+
- >> esp8266_echo_close
+
- >> __2printf
+
+
[Called By]- >> esp8266_parse_domain
+
- >> esp8266_connect
+
+
+esp8266_recv (Thumb, 24 bytes, Stack size 16 bytes, esp8266.o(i.esp8266_recv))
+
[Stack]
- Max Depth = 224 + Unknown Stack Size
+
- Call Chain = esp8266_recv ⇒ esp8266_recv_timeout ⇒ tos_at_channel_read_timed ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> esp8266_recv_timeout
+
+
[Address Reference Count : 1]
+esp8266_recv_timeout (Thumb, 28 bytes, Stack size 24 bytes, esp8266.o(i.esp8266_recv_timeout))
+
[Stack]
- Max Depth = 208 + Unknown Stack Size
+
- Call Chain = esp8266_recv_timeout ⇒ tos_at_channel_read_timed ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_at_channel_read_timed
+
+
[Called By]
+
[Address Reference Count : 1]
+esp8266_recvfrom (Thumb, 24 bytes, Stack size 16 bytes, esp8266.o(i.esp8266_recvfrom))
+
[Stack]
- Max Depth = 224 + Unknown Stack Size
+
- Call Chain = esp8266_recvfrom ⇒ esp8266_recvfrom_timeout ⇒ tos_at_channel_read_timed ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> esp8266_recvfrom_timeout
+
+
[Address Reference Count : 1]
+esp8266_recvfrom_timeout (Thumb, 28 bytes, Stack size 24 bytes, esp8266.o(i.esp8266_recvfrom_timeout))
+
[Stack]
- Max Depth = 208 + Unknown Stack Size
+
- Call Chain = esp8266_recvfrom_timeout ⇒ tos_at_channel_read_timed ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_at_channel_read_timed
+
+
[Called By]
+
[Address Reference Count : 1]
+esp8266_restore (Thumb, 60 bytes, Stack size 56 bytes, esp8266.o(i.esp8266_restore))
+
[Stack]
- Max Depth = 288 + Unknown Stack Size
+
- Call Chain = esp8266_restore ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_at_echo_create
+
- >> tos_at_cmd_exec
+
+
[Called By]
+
+esp8266_send (Thumb, 172 bytes, Stack size 128 bytes, esp8266.o(i.esp8266_send))
+
[Stack]
- Max Depth = 360 + Unknown Stack Size
+
- Call Chain = esp8266_send ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_at_raw_data_send_until
+
- >> tos_at_channel_set_broken
+
- >> tos_at_channel_is_working
+
- >> esp8266_is_link_broken
+
- >> tos_at_global_lock_post
+
- >> tos_at_global_lock_pend
+
- >> tos_at_echo_create
+
- >> tos_at_cmd_exec
+
+
[Address Reference Count : 1]
+esp8266_send_mode_set (Thumb, 72 bytes, Stack size 56 bytes, esp8266.o(i.esp8266_send_mode_set))
+
[Stack]
- Max Depth = 288 + Unknown Stack Size
+
- Call Chain = esp8266_send_mode_set ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_at_echo_create
+
- >> tos_at_cmd_exec
+
+
[Called By]
+
+esp8266_sendto (Thumb, 204 bytes, Stack size 144 bytes, esp8266.o(i.esp8266_sendto))
+
[Stack]
- Max Depth = 376 + Unknown Stack Size
+
- Call Chain = esp8266_sendto ⇒ tos_at_cmd_exec ⇒ at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_at_raw_data_send_until
+
- >> tos_at_channel_set_broken
+
- >> tos_at_channel_is_working
+
- >> esp8266_is_link_broken
+
- >> tos_at_global_lock_post
+
- >> tos_at_global_lock_pend
+
- >> tos_at_echo_create
+
- >> tos_at_cmd_exec
+
+
[Address Reference Count : 1]
+at_channel_construct (Thumb, 88 bytes, Stack size 24 bytes, tos_at.o(i.at_channel_construct))
+
[Stack]
- Max Depth = 152 + Unknown Stack Size
+
- Call Chain = at_channel_construct ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next
+
+
[Calls]- >> tos_mmheap_free
+
- >> tos_mmheap_alloc
+
- >> tos_mutex_create
+
- >> tos_chr_fifo_create
+
+
[Called By]- >> tos_at_channel_alloc
+
+
+at_channel_get (Thumb, 52 bytes, Stack size 8 bytes, tos_at.o(i.at_channel_get))
+
[Stack]
- Max Depth = 8
- Call Chain = at_channel_get
+
+
[Called By]- >> tos_at_channel_set_broken
+
- >> tos_at_channel_is_working
+
- >> tos_at_channel_write
+
- >> tos_at_channel_read_timed
+
- >> tos_at_channel_free
+
+
+at_channel_init (Thumb, 58 bytes, Stack size 8 bytes, tos_at.o(i.at_channel_init))
+
[Stack]
- Max Depth = 8
- Call Chain = at_channel_init
+
+
[Calls]
+
[Called By]
+
+at_cmd_do_exec (Thumb, 76 bytes, Stack size 24 bytes, tos_at.o(i.at_cmd_do_exec))
+
[Stack]
- Max Depth = 184 + Unknown Stack Size
+
- Call Chain = at_cmd_do_exec ⇒ at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_mutex_post
+
- >> tos_mutex_pend
+
- >> at_uart_send
+
- >> vsnprintf
+
- >> __2printf
+
+
[Called By]- >> tos_at_cmd_exec_until
+
- >> tos_at_cmd_exec
+
+
+at_echo_attach (Thumb, 20 bytes, Stack size 0 bytes, tos_at.o(i.at_echo_attach))
+
[Called By]
- >> tos_at_raw_data_send_until
+
- >> tos_at_cmd_exec_until
+
- >> tos_at_cmd_exec
+
+
+at_echo_buffer_copy (Thumb, 74 bytes, Stack size 32 bytes, tos_at.o(i.at_echo_buffer_copy))
+
[Stack]
- Max Depth = 40
- Call Chain = at_echo_buffer_copy ⇒ __aeabi_memcpy
+
+
[Calls]
+
[Called By]
+
+at_echo_status_set (Thumb, 56 bytes, Stack size 16 bytes, tos_at.o(i.at_echo_status_set))
+
[Stack]
- Max Depth = 28
- Call Chain = at_echo_status_set ⇒ strstr
+
+
[Calls]
+
[Called By]
+
+at_event_do_get (Thumb, 78 bytes, Stack size 32 bytes, tos_at.o(i.at_event_do_get))
+
[Stack]
- Max Depth = 44
- Call Chain = at_event_do_get ⇒ strncmp
+
+
[Calls]
+
[Called By]
+
+at_event_table_set (Thumb, 12 bytes, Stack size 0 bytes, tos_at.o(i.at_event_table_set))
+
[Called By]
+
+at_get_event (Thumb, 20 bytes, Stack size 16 bytes, tos_at.o(i.at_get_event))
+
[Stack]
- Max Depth = 60
- Call Chain = at_get_event ⇒ at_event_do_get ⇒ strncmp
+
+
[Calls]
+
[Called By]- >> at_uart_line_parse
+
- >> at_parser
+
+
+at_is_echo_expect (Thumb, 76 bytes, Stack size 32 bytes, tos_at.o(i.at_is_echo_expect))
+
[Stack]
- Max Depth = 44
- Call Chain = at_is_echo_expect ⇒ strncmp
+
+
[Calls]
+
[Called By]
+
+at_parser (Thumb, 114 bytes, Stack size 0 bytes, tos_at.o(i.at_parser))
+
[Stack]
- Max Depth = 184 + Unknown Stack Size
+
- Call Chain = at_parser ⇒ at_uart_line_parse ⇒ at_uart_getchar ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_sem_post
+
- >> at_uart_line_parse
+
- >> at_get_event
+
- >> at_echo_status_set
+
- >> at_echo_buffer_copy
+
- >> __2printf
+
+
[Address Reference Count : 1]- tos_at.o(i.tos_at_init)
+
+at_recv_cache_deinit (Thumb, 40 bytes, Stack size 8 bytes, tos_at.o(i.at_recv_cache_deinit))
+
[Stack]
- Max Depth = 112 + Unknown Stack Size
+
- Call Chain = at_recv_cache_deinit ⇒ tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]
+
[Called By]
+
+at_recv_cache_init (Thumb, 52 bytes, Stack size 8 bytes, tos_at.o(i.at_recv_cache_init))
+
[Stack]
- Max Depth = 136 + Unknown Stack Size
+
- Call Chain = at_recv_cache_init ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next
+
+
[Calls]
+
[Called By]
+
+at_uart_getchar (Thumb, 86 bytes, Stack size 24 bytes, tos_at.o(i.at_uart_getchar))
+
[Stack]
- Max Depth = 160 + Unknown Stack Size
+
- Call Chain = at_uart_getchar ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_mutex_post
+
- >> tos_mutex_pend
+
- >> tos_chr_fifo_pop
+
- >> tos_sem_pend
+
- >> at_delay
+
+
[Called By]- >> at_uart_line_parse
+
- >> tos_at_uart_read
+
+
+at_uart_line_parse (Thumb, 154 bytes, Stack size 24 bytes, tos_at.o(i.at_uart_line_parse))
+
[Stack]
- Max Depth = 184 + Unknown Stack Size
+
- Call Chain = at_uart_line_parse ⇒ at_uart_getchar ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> at_uart_getchar
+
- >> at_is_echo_expect
+
- >> at_get_event
+
- >> __aeabi_memclr
+
+
[Called By]
+
+at_uart_send (Thumb, 44 bytes, Stack size 24 bytes, tos_at.o(i.at_uart_send))
+
[Stack]
- Max Depth = 160 + Unknown Stack Size
+
- Call Chain = at_uart_send ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> tos_mutex_post
+
- >> tos_mutex_pend
+
- >> tos_hal_uart_write
+
+
[Called By]- >> at_cmd_do_exec
+
- >> tos_at_raw_data_send_until
+
+
+_offline_subs_list_deinit (Thumb, 30 bytes, Stack size 8 bytes, mqtt_api.o(i._offline_subs_list_deinit))
+
[Stack]
- Max Depth = 136 + Unknown Stack Size
+
- Call Chain = _offline_subs_list_deinit ⇒ HAL_MutexDestroy ⇒ HAL_Free ⇒ tos_mmheap_free ⇒ blk_merge_prev ⇒ blk_remove ⇒ mapping_insert ⇒ __fls ⇒ generic_fls ⇒ tos_cpu_clz
+
+
[Calls]- >> HAL_MutexDestroy
+
- >> __aeabi_memclr4
+
+
[Called By]- >> iotx_mqtt_deal_offline_subs
+
+
+_offline_subs_list_init (Thumb, 40 bytes, Stack size 8 bytes, mqtt_api.o(i._offline_subs_list_init))
+
[Stack]
- Max Depth = 152 + Unknown Stack Size
+
- Call Chain = _offline_subs_list_init ⇒ HAL_MutexCreate ⇒ HAL_Malloc ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next
+
+
[Calls]- >> HAL_MutexCreate
+
- >> __aeabi_memclr4
+
+
[Called By]- >> iotx_mqtt_offline_subscribe
+
+
+iotx_mqtt_deal_offline_subs (Thumb, 144 bytes, Stack size 24 bytes, mqtt_api.o(i.iotx_mqtt_deal_offline_subs))
+
[Stack]
- Max Depth = 328 + Unknown Stack Size
+
- Call Chain = iotx_mqtt_deal_offline_subs ⇒ wrapper_mqtt_subscribe ⇒ iotx_mc_check_topic ⇒ iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> wrapper_mqtt_subscribe
+
- >> _offline_subs_list_deinit
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
+
[Called By]- >> iotx_mqtt_report_funcs
+
+
+iotx_mqtt_offline_subscribe (Thumb, 362 bytes, Stack size 32 bytes, mqtt_api.o(i.iotx_mqtt_offline_subscribe))
+
[Stack]
- Max Depth = 184 + Unknown Stack Size
+
- Call Chain = iotx_mqtt_offline_subscribe ⇒ _offline_subs_list_init ⇒ HAL_MutexCreate ⇒ HAL_Malloc ⇒ tos_mmheap_alloc ⇒ blk_prepare_used ⇒ blk_trim_free ⇒ blk_split ⇒ blk_mark_as_free ⇒ blk_link_next ⇒ blk_next
+
+
[Calls]- >> _offline_subs_list_init
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
- >> memcmp
+
- >> strlen
+
- >> __aeabi_memclr4
+
- >> __aeabi_memcpy
+
+
[Called By]
+
+iotx_mqtt_report_funcs (Thumb, 100 bytes, Stack size 16 bytes, mqtt_api.o(i.iotx_mqtt_report_funcs))
+
[Stack]
- Max Depth = 472 + Unknown Stack Size
+
- Call Chain = iotx_mqtt_report_funcs ⇒ iotx_report_firmware_version ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> iotx_set_report_func
+
- >> iotx_report_mid
+
- >> iotx_report_firmware_version
+
- >> iotx_report_devinfo
+
- >> LITE_syslog
+
- >> iotx_mqtt_deal_offline_subs
+
+
[Called By]
+
+MQTTDisconnect (Thumb, 120 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.MQTTDisconnect))
+
[Stack]
- Max Depth = 176 + Unknown Stack Size
+
- Call Chain = MQTTDisconnect ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_send_packet
+
- >> _reset_send_buffer
+
- >> _alloc_send_buffer
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
- >> utils_time_countdown_ms
+
- >> iotx_time_init
+
- >> MQTTSerialize_disconnect
+
+
[Called By]
+
+MQTTKeepalive (Thumb, 226 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.MQTTKeepalive))
+
[Stack]
- Max Depth = 184 + Unknown Stack Size
+
- Call Chain = MQTTKeepalive ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_send_packet
+
- >> _reset_send_buffer
+
- >> _alloc_send_buffer
+
- >> LITE_syslog
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
- >> utils_time_countdown_ms
+
- >> iotx_time_init
+
- >> MQTTSerialize_pingreq
+
+
[Called By]- >> iotx_mc_keepalive_sub
+
+
+MQTTPubInfoProc (Thumb, 226 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.MQTTPubInfoProc))
+
[Stack]
- Max Depth = 200 + Unknown Stack Size
+
- Call Chain = MQTTPubInfoProc ⇒ MQTTRePublish ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_set_client_state
+
- >> iotx_mc_get_client_state
+
- >> MQTTRePublish
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
- >> utils_time_spend
+
- >> iotx_time_start
+
- >> __aeabi_memclr4
+
+
[Called By]
+
+MQTTPuback (Thumb, 206 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.MQTTPuback))
+
[Stack]
- Max Depth = 184 + Unknown Stack Size
+
- Call Chain = MQTTPuback ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_send_packet
+
- >> _reset_send_buffer
+
- >> _alloc_send_buffer
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
- >> utils_time_countdown_ms
+
- >> iotx_time_init
+
- >> MQTTSerialize_ack
+
+
[Called By]- >> iotx_mc_handle_recv_PUBLISH
+
+
+MQTTRePublish (Thumb, 76 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.MQTTRePublish))
+
[Stack]
- Max Depth = 176 + Unknown Stack Size
+
- Call Chain = MQTTRePublish ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_send_packet
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
- >> utils_time_countdown_ms
+
- >> iotx_time_init
+
+
[Called By]
+
+MQTTSubscribe (Thumb, 610 bytes, Stack size 80 bytes, iotx_mqtt_client.o(i.MQTTSubscribe))
+
[Stack]
- Max Depth = 232 + Unknown Stack Size
+
- Call Chain = MQTTSubscribe ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_send_packet
+
- >> iotx_mc_check_handle_is_identical
+
- >> _reset_send_buffer
+
- >> _alloc_send_buffer
+
- >> LITE_syslog
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
- >> utils_time_countdown_ms
+
- >> iotx_time_init
+
- >> MQTTSerialize_subscribe
+
- >> strlen
+
- >> __aeabi_memclr4
+
- >> __aeabi_memcpy
+
+
[Called By]- >> wrapper_mqtt_subscribe
+
+
+_alloc_recv_buffer (Thumb, 6 bytes, Stack size 0 bytes, iotx_mqtt_client.o(i._alloc_recv_buffer))
+
[Called By]
+
+_alloc_send_buffer (Thumb, 6 bytes, Stack size 0 bytes, iotx_mqtt_client.o(i._alloc_send_buffer))
+
[Called By]
- >> MQTTSubscribe
+
- >> MQTTPuback
+
- >> MQTTKeepalive
+
- >> MQTTDisconnect
+
- >> MQTTPublish
+
- >> MQTTConnect
+
+
+_get_connect_length (Thumb, 6 bytes, Stack size 0 bytes, iotx_mqtt_client.o(i._get_connect_length))
+
[Called By]
+
+_handle_event (Thumb, 46 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i._handle_event))
+
[Stack]
- Max Depth = 16
- Call Chain = _handle_event
+
+
[Called By]- >> iotx_mc_read_packet
+
- >> iotx_mc_handle_recv_UNSUBACK
+
- >> iotx_mc_handle_recv_SUBACK
+
- >> iotx_mc_handle_recv_PUBACK
+
- >> iotx_mc_deliver_message
+
+
+_iotx_mqtt_event_handle_sub (Thumb, 118 bytes, Stack size 40 bytes, iotx_mqtt_client.o(i._iotx_mqtt_event_handle_sub))
+
[Stack]
- Max Depth = 192 + Unknown Stack Size
+
- Call Chain = _iotx_mqtt_event_handle_sub ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> LITE_syslog
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
+
[Called By]- >> iotx_mc_handle_recv_SUBACK
+
+
+_mqtt_connect (Thumb, 396 bytes, Stack size 48 bytes, iotx_mqtt_client.o(i._mqtt_connect))
+
[Stack]
- Max Depth = 800 + Unknown Stack Size
+
- Call Chain = _mqtt_connect ⇒ iotx_mc_wait_CONNACK ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_wait_CONNACK
+
- >> iotx_mc_set_client_state
+
- >> LITE_syslog
+
- >> HAL_SleepMs
+
- >> utils_time_countdown_ms
+
- >> MQTTConnect
+
+
[Called By]- >> wrapper_mqtt_connect
+
+
+_reset_recv_buffer (Thumb, 6 bytes, Stack size 0 bytes, iotx_mqtt_client.o(i._reset_recv_buffer))
+
[Called By]
- >> iotx_mc_wait_CONNACK
+
- >> iotx_mc_cycle
+
+
+_reset_send_buffer (Thumb, 6 bytes, Stack size 0 bytes, iotx_mqtt_client.o(i._reset_send_buffer))
+
[Called By]
- >> MQTTSubscribe
+
- >> MQTTPuback
+
- >> MQTTKeepalive
+
- >> MQTTDisconnect
+
- >> MQTTPublish
+
- >> MQTTConnect
+
+
+iotx_mc_attempt_reconnect (Thumb, 116 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.iotx_mc_attempt_reconnect))
+
[Stack]
- Max Depth = 880 + Unknown Stack Size
+
- Call Chain = iotx_mc_attempt_reconnect ⇒ wrapper_mqtt_connect ⇒ _mqtt_connect ⇒ iotx_mc_wait_CONNACK ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> wrapper_mqtt_connect
+
- >> LITE_syslog
+
+
[Called By]- >> iotx_mc_handle_reconnect
+
+
+iotx_mc_check_handle_is_identical (Thumb, 48 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.iotx_mc_check_handle_is_identical))
+
[Stack]
- Max Depth = 44
- Call Chain = iotx_mc_check_handle_is_identical ⇒ iotx_mc_check_handle_is_identical_ex ⇒ strncmp
+
+
[Calls]- >> iotx_mc_check_handle_is_identical_ex
+
+
[Called By]
+
+iotx_mc_check_handle_is_identical_ex (Thumb, 82 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.iotx_mc_check_handle_is_identical_ex))
+
[Stack]
- Max Depth = 28
- Call Chain = iotx_mc_check_handle_is_identical_ex ⇒ strncmp
+
+
[Calls]
+
[Called By]- >> iotx_mc_check_handle_is_identical
+
+
+iotx_mc_check_rule (Thumb, 154 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.iotx_mc_check_rule))
+
[Stack]
- Max Depth = 152
- Call Chain = iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> LITE_syslog
+
- >> strlen
+
+
[Called By]
+
+iotx_mc_check_topic (Thumb, 228 bytes, Stack size 88 bytes, iotx_mqtt_client.o(i.iotx_mc_check_topic))
+
[Stack]
- Max Depth = 240
- Call Chain = iotx_mc_check_topic ⇒ iotx_mc_check_rule ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> iotx_mc_check_rule
+
- >> LITE_syslog
+
- >> infra_strtok
+
- >> strlen
+
- >> strncpy
+
- >> __aeabi_memclr4
+
+
[Called By]- >> wrapper_mqtt_subscribe
+
- >> wrapper_mqtt_publish
+
+
+iotx_mc_cycle (Thumb, 562 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.iotx_mc_cycle))
+
[Stack]
- Max Depth = 752 + Unknown Stack Size
+
- Call Chain = iotx_mc_cycle ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_set_client_state
+
- >> iotx_mc_read_packet
+
- >> iotx_mc_handle_recv_UNSUBACK
+
- >> iotx_mc_handle_recv_SUBACK
+
- >> iotx_mc_handle_recv_PUBLISH
+
- >> iotx_mc_handle_recv_PUBACK
+
- >> iotx_mc_get_client_state
+
- >> _reset_recv_buffer
+
- >> LITE_syslog
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
+
[Called By]
+
+iotx_mc_decode_packet (Thumb, 140 bytes, Stack size 40 bytes, iotx_mqtt_client.o(i.iotx_mc_decode_packet))
+
[Stack]
- Max Depth = 40
- Call Chain = iotx_mc_decode_packet
+
+
[Called By]
+
+iotx_mc_deliver_message (Thumb, 268 bytes, Stack size 40 bytes, iotx_mqtt_client.o(i.iotx_mc_deliver_message))
+
[Stack]
- Max Depth = 192 + Unknown Stack Size
+
- Call Chain = iotx_mc_deliver_message ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_is_topic_matched
+
- >> _handle_event
+
- >> LITE_syslog
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
- >> MQTTPacket_equals
+
+
[Called By]- >> iotx_mc_handle_recv_PUBLISH
+
+
+iotx_mc_disconnect (Thumb, 94 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.iotx_mc_disconnect))
+
[Stack]
- Max Depth = 200 + Unknown Stack Size
+
- Call Chain = iotx_mc_disconnect ⇒ MQTTDisconnect ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_set_client_state
+
- >> MQTTDisconnect
+
- >> wrapper_mqtt_check_state
+
- >> LITE_syslog
+
+
[Called By]- >> wrapper_mqtt_release
+
+
+iotx_mc_disconnect_callback (Thumb, 46 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.iotx_mc_disconnect_callback))
+
[Stack]
- Max Depth = 16
- Call Chain = iotx_mc_disconnect_callback
+
+
[Called By]
+
+iotx_mc_get_client_state (Thumb, 24 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.iotx_mc_get_client_state))
+
[Stack]
- Max Depth = 168 + Unknown Stack Size
+
- Call Chain = iotx_mc_get_client_state ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
+
[Called By]- >> iotx_mc_keepalive
+
- >> iotx_mc_cycle
+
- >> MQTTPubInfoProc
+
- >> wrapper_mqtt_subscribe
+
- >> wrapper_mqtt_publish
+
- >> wrapper_mqtt_check_state
+
+
+iotx_mc_get_next_packetid (Thumb, 50 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.iotx_mc_get_next_packetid))
+
[Stack]
- Max Depth = 168 + Unknown Stack Size
+
- Call Chain = iotx_mc_get_next_packetid ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
+
[Called By]- >> wrapper_mqtt_subscribe
+
- >> wrapper_mqtt_publish
+
+
+iotx_mc_handle_reconnect (Thumb, 196 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.iotx_mc_handle_reconnect))
+
[Stack]
- Max Depth = 904 + Unknown Stack Size
+
- Call Chain = iotx_mc_handle_reconnect ⇒ iotx_mc_attempt_reconnect ⇒ wrapper_mqtt_connect ⇒ _mqtt_connect ⇒ iotx_mc_wait_CONNACK ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_set_client_state
+
- >> iotx_mc_attempt_reconnect
+
- >> LITE_syslog
+
- >> HAL_SleepMs
+
- >> utils_time_is_expired
+
- >> utils_time_countdown_ms
+
+
[Called By]
+
+iotx_mc_handle_recv_CONNACK (Thumb, 126 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.iotx_mc_handle_recv_CONNACK))
+
[Stack]
- Max Depth = 152
- Call Chain = iotx_mc_handle_recv_CONNACK ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> LITE_syslog
+
- >> MQTTDeserialize_connack
+
+
[Called By]- >> iotx_mc_wait_CONNACK
+
+
+iotx_mc_handle_recv_PUBACK (Thumb, 98 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.iotx_mc_handle_recv_PUBACK))
+
[Stack]
- Max Depth = 128
- Call Chain = iotx_mc_handle_recv_PUBACK ⇒ MQTTDeserialize_ack ⇒ MQTTPacket_decodeBuf ⇒ MQTTPacket_decode
+
+
[Calls]- >> iotx_mc_mask_pubInfo_from
+
- >> _handle_event
+
- >> MQTTDeserialize_ack
+
+
[Called By]
+
+iotx_mc_handle_recv_PUBLISH (Thumb, 404 bytes, Stack size 72 bytes, iotx_mqtt_client.o(i.iotx_mc_handle_recv_PUBLISH))
+
[Stack]
- Max Depth = 264 + Unknown Stack Size
+
- Call Chain = iotx_mc_handle_recv_PUBLISH ⇒ iotx_mc_deliver_message ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_deliver_message
+
- >> MQTTPuback
+
- >> LITE_syslog
+
- >> MQTTDeserialize_publish
+
- >> __aeabi_memclr4
+
+
[Called By]
+
+iotx_mc_handle_recv_SUBACK (Thumb, 322 bytes, Stack size 80 bytes, iotx_mqtt_client.o(i.iotx_mc_handle_recv_SUBACK))
+
[Stack]
- Max Depth = 272 + Unknown Stack Size
+
- Call Chain = iotx_mc_handle_recv_SUBACK ⇒ _iotx_mqtt_event_handle_sub ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> _iotx_mqtt_event_handle_sub
+
- >> _handle_event
+
- >> LITE_syslog
+
- >> MQTTDeserialize_suback
+
+
[Called By]
+
+iotx_mc_handle_recv_UNSUBACK (Thumb, 76 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.iotx_mc_handle_recv_UNSUBACK))
+
[Stack]
- Max Depth = 152
- Call Chain = iotx_mc_handle_recv_UNSUBACK ⇒ MQTTDeserialize_unsuback ⇒ MQTTDeserialize_ack ⇒ MQTTPacket_decodeBuf ⇒ MQTTPacket_decode
+
+
[Calls]- >> _handle_event
+
- >> MQTTDeserialize_unsuback
+
+
[Called By]
+
+iotx_mc_init (Thumb, 452 bytes, Stack size 112 bytes, iotx_mqtt_client.o(i.iotx_mc_init))
+
[Stack]
- Max Depth = 280 + Unknown Stack Size
+
- Call Chain = iotx_mc_init ⇒ iotx_mc_set_client_state ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_set_connect_params
+
- >> iotx_mc_set_client_state
+
- >> iotx_mc_pub_wait_list_init
+
- >> LITE_syslog
+
- >> HAL_MutexDestroy
+
- >> HAL_MutexCreate
+
- >> iotx_time_init
+
- >> iotx_net_init
+
- >> __aeabi_memclr4
+
- >> __aeabi_memcpy4
+
+
[Called By]
+
+iotx_mc_is_topic_matched (Thumb, 126 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.iotx_mc_is_topic_matched))
+
[Stack]
- Max Depth = 16
- Call Chain = iotx_mc_is_topic_matched
+
+
[Called By]- >> iotx_mc_deliver_message
+
+
+iotx_mc_keepalive (Thumb, 206 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.iotx_mc_keepalive))
+
[Stack]
- Max Depth = 928 + Unknown Stack Size
+
- Call Chain = iotx_mc_keepalive ⇒ iotx_mc_handle_reconnect ⇒ iotx_mc_attempt_reconnect ⇒ wrapper_mqtt_connect ⇒ _mqtt_connect ⇒ iotx_mc_wait_CONNACK ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_set_client_state
+
- >> iotx_mc_reconnect_callback
+
- >> iotx_mc_keepalive_sub
+
- >> iotx_mc_handle_reconnect
+
- >> iotx_mc_get_client_state
+
- >> iotx_mc_disconnect_callback
+
- >> LITE_syslog
+
- >> utils_time_countdown_ms
+
+
[Called By]
+
+iotx_mc_keepalive_sub (Thumb, 148 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.iotx_mc_keepalive_sub))
+
[Stack]
- Max Depth = 208 + Unknown Stack Size
+
- Call Chain = iotx_mc_keepalive_sub ⇒ MQTTKeepalive ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_set_client_state
+
- >> MQTTKeepalive
+
- >> wrapper_mqtt_check_state
+
- >> LITE_syslog
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
- >> utils_time_is_expired
+
- >> utils_time_countdown_ms
+
+
[Called By]
+
+iotx_mc_mask_pubInfo_from (Thumb, 72 bytes, Stack size 12 bytes, iotx_mqtt_client.o(i.iotx_mc_mask_pubInfo_from))
+
[Stack]
- Max Depth = 12
- Call Chain = iotx_mc_mask_pubInfo_from
+
+
[Called By]- >> iotx_mc_handle_recv_PUBACK
+
+
+iotx_mc_pub_wait_list_deinit (Thumb, 18 bytes, Stack size 8 bytes, iotx_mqtt_client.o(i.iotx_mc_pub_wait_list_deinit))
+
[Stack]
- Max Depth = 8
- Call Chain = iotx_mc_pub_wait_list_deinit
+
+
[Calls]
+
[Called By]- >> wrapper_mqtt_release
+
+
+iotx_mc_pub_wait_list_init (Thumb, 18 bytes, Stack size 8 bytes, iotx_mqtt_client.o(i.iotx_mc_pub_wait_list_init))
+
[Stack]
- Max Depth = 8
- Call Chain = iotx_mc_pub_wait_list_init
+
+
[Calls]
+
[Called By]
+
+iotx_mc_push_pubInfo_to (Thumb, 286 bytes, Stack size 40 bytes, iotx_mqtt_client.o(i.iotx_mc_push_pubInfo_to))
+
[Stack]
- Max Depth = 168 + Unknown Stack Size
+
- Call Chain = iotx_mc_push_pubInfo_to ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> LITE_syslog
+
- >> iotx_time_start
+
- >> __aeabi_memcpy
+
+
[Called By]
+
+iotx_mc_read_packet (Thumb, 892 bytes, Stack size 568 bytes, iotx_mqtt_client.o(i.iotx_mc_read_packet))
+
[Stack]
- Max Depth = 720 + Unknown Stack Size
+
- Call Chain = iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_decode_packet
+
- >> _handle_event
+
- >> _alloc_recv_buffer
+
- >> LITE_syslog
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
- >> iotx_time_left
+
- >> MQTTPacket_encode
+
- >> __aeabi_memclr4
+
+
[Called By]- >> iotx_mc_wait_CONNACK
+
- >> iotx_mc_cycle
+
+
+iotx_mc_reconnect_callback (Thumb, 46 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.iotx_mc_reconnect_callback))
+
[Stack]
- Max Depth = 16
- Call Chain = iotx_mc_reconnect_callback
+
+
[Called By]
+
+iotx_mc_release (Thumb, 16 bytes, Stack size 8 bytes, iotx_mqtt_client.o(i.iotx_mc_release))
+
[Stack]
- Max Depth = 8
- Call Chain = iotx_mc_release
+
+
[Calls]
+
[Called By]
+
+iotx_mc_send_packet (Thumb, 126 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.iotx_mc_send_packet))
+
[Stack]
- Max Depth = 96 + Unknown Stack Size
+
- Call Chain = iotx_mc_send_packet ⇒ iotx_time_left ⇒ utils_time_is_expired ⇒ HAL_UptimeMs ⇒ tos_systick_get ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> utils_time_is_expired
+
- >> iotx_time_left
+
+
[Called By]- >> MQTTSubscribe
+
- >> MQTTRePublish
+
- >> MQTTPuback
+
- >> MQTTKeepalive
+
- >> MQTTDisconnect
+
- >> MQTTPublish
+
- >> MQTTConnect
+
+
+iotx_mc_set_client_state (Thumb, 24 bytes, Stack size 16 bytes, iotx_mqtt_client.o(i.iotx_mc_set_client_state))
+
[Stack]
- Max Depth = 168 + Unknown Stack Size
+
- Call Chain = iotx_mc_set_client_state ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
+
[Called By]- >> iotx_mc_keepalive_sub
+
- >> iotx_mc_keepalive
+
- >> iotx_mc_init
+
- >> iotx_mc_handle_reconnect
+
- >> iotx_mc_disconnect
+
- >> iotx_mc_cycle
+
- >> _mqtt_connect
+
- >> MQTTPubInfoProc
+
- >> wrapper_mqtt_subscribe
+
- >> wrapper_mqtt_release
+
- >> wrapper_mqtt_publish
+
+
+iotx_mc_set_connect_params (Thumb, 300 bytes, Stack size 24 bytes, iotx_mqtt_client.o(i.iotx_mc_set_connect_params))
+
[Stack]
- Max Depth = 152
- Call Chain = iotx_mc_set_connect_params ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]
+
[Called By]
+
+iotx_mc_wait_CONNACK (Thumb, 226 bytes, Stack size 32 bytes, iotx_mqtt_client.o(i.iotx_mc_wait_CONNACK))
+
[Stack]
- Max Depth = 752 + Unknown Stack Size
+
- Call Chain = iotx_mc_wait_CONNACK ⇒ iotx_mc_read_packet ⇒ HAL_MutexLock ⇒ tos_mutex_pend ⇒ tos_mutex_pend_timed ⇒ pend_task_block ⇒ tick_list_add ⇒ tick_task_place ⇒ tos_cpu_cpsr_save
+
+
[Calls]- >> iotx_mc_read_packet
+
- >> iotx_mc_handle_recv_CONNACK
+
- >> _reset_recv_buffer
+
- >> LITE_syslog
+
- >> HAL_MutexUnlock
+
- >> HAL_MutexLock
+
- >> utils_time_countdown_ms
+
- >> iotx_time_init
+
+
[Called By]
+
+connect_tcp (Thumb, 52 bytes, Stack size 16 bytes, infra_net.o(i.connect_tcp))
+
[Stack]
- Max Depth = 144
- Call Chain = connect_tcp ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> LITE_syslog
+
- >> HAL_TCP_Establish
+
+
[Called By]
+
+disconnect_tcp (Thumb, 48 bytes, Stack size 16 bytes, infra_net.o(i.disconnect_tcp))
+
[Stack]
- Max Depth = 144
- Call Chain = disconnect_tcp ⇒ LITE_syslog ⇒ LITE_syslog_routine ⇒ HAL_Vsnprintf ⇒ vsnprintf
+
+
[Calls]- >> LITE_syslog
+
- >> HAL_TCP_Destroy
+
+
[Called By]
+
+read_tcp (Thumb, 28 bytes, Stack size 24 bytes, infra_net.o(i.read_tcp))
+
[Stack]
- Max Depth = 72
- Call Chain = read_tcp ⇒ HAL_TCP_Read ⇒ tos_sal_module_recv_timeout
+
+
[Calls]
+
[Called By]
+
+write_tcp (Thumb, 28 bytes, Stack size 24 bytes, infra_net.o(i.write_tcp))
+
[Stack]
- Max Depth = 64
- Call Chain = write_tcp ⇒ HAL_TCP_Write ⇒ tos_sal_module_send
+
+
[Calls]
+
[Called By]
+
+_hex2str (Thumb, 58 bytes, Stack size 20 bytes, dev_sign_mqtt.o(i._hex2str))
+
[Stack]
- Max Depth = 20
- Call Chain = _hex2str
+
+
[Called By]- >> _iotx_generate_sign_string
+
+
+_fp_digits (Thumb, 366 bytes, Stack size 64 bytes, printfa.o(i._fp_digits), UNUSED)
+
[Calls]
- >> __aeabi_ddiv
+
- >> __aeabi_uldivmod
+
- >> __aeabi_dmul
+
- >> __aeabi_dadd
+
- >> __aeabi_d2ulz
+
- >> __aeabi_cdrcmple
+
+
[Called By]
+
+_printf_core (Thumb, 1744 bytes, Stack size 136 bytes, printfa.o(i._printf_core), UNUSED)
+
[Calls]
- >> __aeabi_uldivmod
+
- >> __aeabi_uidivmod
+
- >> _printf_pre_padding
+
- >> _printf_post_padding
+
- >> _fp_digits
+
+
[Called By]- >> __0vsnprintf
+
- >> __0vprintf
+
- >> __0snprintf
+
- >> __0printf
+
+
+_printf_post_padding (Thumb, 36 bytes, Stack size 24 bytes, printfa.o(i._printf_post_padding), UNUSED)
+
[Called By]
+
+_printf_pre_padding (Thumb, 46 bytes, Stack size 24 bytes, printfa.o(i._printf_pre_padding), UNUSED)
+
[Called By]
+
+_snputc (Thumb, 22 bytes, Stack size 0 bytes, printfa.o(i._snputc))
+
[Address Reference Count : 2]
- printfa.o(i.__0snprintf)
+
- printfa.o(i.__0vsnprintf)
+
+_scanf_char_input (Thumb, 12 bytes, Stack size 0 bytes, scanf_char.o(.text))
+
[Address Reference Count : 1]
+
+Undefined Global Symbols
+
diff --git a/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/obj/TencentOS_tiny.sct b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/obj/TencentOS_tiny.sct
new file mode 100644
index 00000000..66acf7f8
--- /dev/null
+++ b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/obj/TencentOS_tiny.sct
@@ -0,0 +1,16 @@
+; *************************************************************
+; *** Scatter-Loading Description File generated by uVision ***
+; *************************************************************
+
+LR_IROM1 0x08000000 0x00040000 { ; load region size_region
+ ER_IROM1 0x08000000 0x00040000 { ; load address = execution address
+ *.o (RESET, +First)
+ *(InRoot$$Sections)
+ .ANY (+RO)
+ .ANY (+XO)
+ }
+ RW_IRAM1 0x20000000 0x00010000 { ; RW data
+ .ANY (+RW +ZI)
+ }
+}
+
diff --git a/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/startup_stm32l431xx.s b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/startup_stm32l431xx.s
new file mode 100644
index 00000000..6a5c15a5
--- /dev/null
+++ b/board/TencentOS_tiny_EVB_MX_Plus/KEIL/aliyun_iotkit_csdk_mqtt/startup_stm32l431xx.s
@@ -0,0 +1,404 @@
+;********************** COPYRIGHT(c) 2017 STMicroelectronics ******************
+;* File Name : startup_stm32l431xx.s
+;* Author : MCD Application Team
+;* Description : STM32L431xx Ultra Low Power devices vector table for MDK-ARM toolchain.
+;* This module performs:
+;* - Set the initial SP
+;* - Set the initial PC == Reset_Handler
+;* - Set the vector table entries with the exceptions ISR address
+;* - Branches to __main in the C library (which eventually
+;* calls main()).
+;* After Reset the Cortex-M4 processor is in Thread mode,
+;* priority is Privileged, and the Stack is set to Main.
+;* <<< Use Configuration Wizard in Context Menu >>>
+;*******************************************************************************
+;*
+;* Redistribution and use in source and binary forms, with or without modification,
+;* are permitted provided that the following conditions are met:
+;* 1. Redistributions of source code must retain the above copyright notice,
+;* this list of conditions and the following disclaimer.
+;* 2. Redistributions in binary form must reproduce the above copyright notice,
+;* this list of conditions and the following disclaimer in the documentation
+;* and/or other materials provided with the distribution.
+;* 3. Neither the name of STMicroelectronics nor the names of its contributors
+;* may be used to endorse or promote products derived from this software
+;* without specific prior written permission.
+;*
+;* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+;* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+;* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+;* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+;* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+;* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+;* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+;* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+;* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+;* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+;*
+;*******************************************************************************
+;
+; Amount of memory (in bytes) allocated for Stack
+; Tailor this value to your application needs
+; Stack Configuration
+; Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
+;
+
+Stack_Size EQU 0x100
+
+ AREA STACK, NOINIT, READWRITE, ALIGN=3
+Stack_Mem SPACE Stack_Size
+__initial_sp
+
+
+; Heap Configuration
+; Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
+;
+
+Heap_Size EQU 0x100
+
+ AREA HEAP, NOINIT, READWRITE, ALIGN=3
+__heap_base
+Heap_Mem SPACE Heap_Size
+__heap_limit
+
+ PRESERVE8
+ THUMB
+
+
+; Vector Table Mapped to Address 0 at Reset
+ AREA RESET, DATA, READONLY
+ EXPORT __Vectors
+ EXPORT __Vectors_End
+ EXPORT __Vectors_Size
+
+__Vectors DCD __initial_sp ; Top of Stack
+ DCD Reset_Handler ; Reset Handler
+ DCD NMI_Handler ; NMI Handler
+ DCD HardFault_Handler ; Hard Fault Handler
+ DCD MemManage_Handler ; MPU Fault Handler
+ DCD BusFault_Handler ; Bus Fault Handler
+ DCD UsageFault_Handler ; Usage Fault Handler
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD SVC_Handler ; SVCall Handler
+ DCD DebugMon_Handler ; Debug Monitor Handler
+ DCD 0 ; Reserved
+ DCD PendSV_Handler ; PendSV Handler
+ DCD SysTick_Handler ; SysTick Handler
+
+ ; External Interrupts
+ DCD WWDG_IRQHandler ; Window WatchDog
+ DCD PVD_PVM_IRQHandler ; PVD/PVM1/PVM2/PVM3/PVM4 through EXTI Line detection
+ DCD TAMP_STAMP_IRQHandler ; Tamper and TimeStamps through the EXTI line
+ DCD RTC_WKUP_IRQHandler ; RTC Wakeup through the EXTI line
+ DCD FLASH_IRQHandler ; FLASH
+ DCD RCC_IRQHandler ; RCC
+ DCD EXTI0_IRQHandler ; EXTI Line0
+ DCD EXTI1_IRQHandler ; EXTI Line1
+ DCD EXTI2_IRQHandler ; EXTI Line2
+ DCD EXTI3_IRQHandler ; EXTI Line3
+ DCD EXTI4_IRQHandler ; EXTI Line4
+ DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1
+ DCD DMA1_Channel2_IRQHandler ; DMA1 Channel 2
+ DCD DMA1_Channel3_IRQHandler ; DMA1 Channel 3
+ DCD DMA1_Channel4_IRQHandler ; DMA1 Channel 4
+ DCD DMA1_Channel5_IRQHandler ; DMA1 Channel 5
+ DCD DMA1_Channel6_IRQHandler ; DMA1 Channel 6
+ DCD DMA1_Channel7_IRQHandler ; DMA1 Channel 7
+ DCD ADC1_IRQHandler ; ADC1
+ DCD CAN1_TX_IRQHandler ; CAN1 TX
+ DCD CAN1_RX0_IRQHandler ; CAN1 RX0
+ DCD CAN1_RX1_IRQHandler ; CAN1 RX1
+ DCD CAN1_SCE_IRQHandler ; CAN1 SCE
+ DCD EXTI9_5_IRQHandler ; External Line[9:5]s
+ DCD TIM1_BRK_TIM15_IRQHandler ; TIM1 Break and TIM15
+ DCD TIM1_UP_TIM16_IRQHandler ; TIM1 Update and TIM16
+ DCD TIM1_TRG_COM_IRQHandler ; TIM1 Trigger and Commutation
+ DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare
+ DCD TIM2_IRQHandler ; TIM2
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD I2C1_EV_IRQHandler ; I2C1 Event
+ DCD I2C1_ER_IRQHandler ; I2C1 Error
+ DCD I2C2_EV_IRQHandler ; I2C2 Event
+ DCD I2C2_ER_IRQHandler ; I2C2 Error
+ DCD SPI1_IRQHandler ; SPI1
+ DCD SPI2_IRQHandler ; SPI2
+ DCD USART1_IRQHandler ; USART1
+ DCD USART2_IRQHandler ; USART2
+ DCD USART3_IRQHandler ; USART3
+ DCD EXTI15_10_IRQHandler ; External Line[15:10]
+ DCD RTC_Alarm_IRQHandler ; RTC Alarm (A and B) through EXTI Line
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD SDMMC1_IRQHandler ; SDMMC1
+ DCD 0 ; Reserved
+ DCD SPI3_IRQHandler ; SPI3
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD TIM6_DAC_IRQHandler ; TIM6 and DAC1&2 underrun errors
+ DCD TIM7_IRQHandler ; TIM7
+ DCD DMA2_Channel1_IRQHandler ; DMA2 Channel 1
+ DCD DMA2_Channel2_IRQHandler ; DMA2 Channel 2
+ DCD DMA2_Channel3_IRQHandler ; DMA2 Channel 3
+ DCD DMA2_Channel4_IRQHandler ; DMA2 Channel 4
+ DCD DMA2_Channel5_IRQHandler ; DMA2 Channel 5
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD COMP_IRQHandler ; COMP Interrupt
+ DCD LPTIM1_IRQHandler ; LP TIM1 interrupt
+ DCD LPTIM2_IRQHandler ; LP TIM2 interrupt
+ DCD 0 ; Reserved
+ DCD DMA2_Channel6_IRQHandler ; DMA2 Channel 6
+ DCD DMA2_Channel7_IRQHandler ; DMA2 Channel 7
+ DCD LPUART1_IRQHandler ; LP UART1 interrupt
+ DCD QUADSPI_IRQHandler ; Quad SPI global interrupt
+ DCD I2C3_EV_IRQHandler ; I2C3 event
+ DCD I2C3_ER_IRQHandler ; I2C3 error
+ DCD SAI1_IRQHandler ; Serial Audio Interface 1 global interrupt
+ DCD 0 ; Reserved
+ DCD SWPMI1_IRQHandler ; Serial Wire Interface 1 global interrupt
+ DCD TSC_IRQHandler ; Touch Sense Controller global interrupt
+ DCD 0 ; Reserved
+ DCD 0 ; Reserved
+ DCD RNG_IRQHandler ; RNG global interrupt
+ DCD FPU_IRQHandler ; FPU
+ DCD CRS_IRQHandler ; CRS interrupt
+
+__Vectors_End
+
+__Vectors_Size EQU __Vectors_End - __Vectors
+
+ AREA |.text|, CODE, READONLY
+
+; Reset handler
+Reset_Handler PROC
+ EXPORT Reset_Handler [WEAK]
+ IMPORT SystemInit
+ IMPORT __main
+
+ LDR R0, =SystemInit
+ BLX R0
+ LDR R0, =__main
+ BX R0
+ ENDP
+
+; Dummy Exception Handlers (infinite loops which can be modified)
+
+NMI_Handler PROC
+ EXPORT NMI_Handler [WEAK]
+ B .
+ ENDP
+HardFault_Handler\
+ PROC
+ EXPORT HardFault_Handler [WEAK]
+ B .
+ ENDP
+MemManage_Handler\
+ PROC
+ EXPORT MemManage_Handler [WEAK]
+ B .
+ ENDP
+BusFault_Handler\
+ PROC
+ EXPORT BusFault_Handler [WEAK]
+ B .
+ ENDP
+UsageFault_Handler\
+ PROC
+ EXPORT UsageFault_Handler [WEAK]
+ B .
+ ENDP
+SVC_Handler PROC
+ EXPORT SVC_Handler [WEAK]
+ B .
+ ENDP
+DebugMon_Handler\
+ PROC
+ EXPORT DebugMon_Handler [WEAK]
+ B .
+ ENDP
+PendSV_Handler PROC
+ EXPORT PendSV_Handler [WEAK]
+ B .
+ ENDP
+SysTick_Handler PROC
+ EXPORT SysTick_Handler [WEAK]
+ B .
+ ENDP
+
+Default_Handler PROC
+
+ EXPORT WWDG_IRQHandler [WEAK]
+ EXPORT PVD_PVM_IRQHandler [WEAK]
+ EXPORT TAMP_STAMP_IRQHandler [WEAK]
+ EXPORT RTC_WKUP_IRQHandler [WEAK]
+ EXPORT FLASH_IRQHandler [WEAK]
+ EXPORT RCC_IRQHandler [WEAK]
+ EXPORT EXTI0_IRQHandler [WEAK]
+ EXPORT EXTI1_IRQHandler [WEAK]
+ EXPORT EXTI2_IRQHandler [WEAK]
+ EXPORT EXTI3_IRQHandler [WEAK]
+ EXPORT EXTI4_IRQHandler [WEAK]
+ EXPORT DMA1_Channel1_IRQHandler [WEAK]
+ EXPORT DMA1_Channel2_IRQHandler [WEAK]
+ EXPORT DMA1_Channel3_IRQHandler [WEAK]
+ EXPORT DMA1_Channel4_IRQHandler [WEAK]
+ EXPORT DMA1_Channel5_IRQHandler [WEAK]
+ EXPORT DMA1_Channel6_IRQHandler [WEAK]
+ EXPORT DMA1_Channel7_IRQHandler [WEAK]
+ EXPORT ADC1_IRQHandler [WEAK]
+ EXPORT CAN1_TX_IRQHandler [WEAK]
+ EXPORT CAN1_RX0_IRQHandler [WEAK]
+ EXPORT CAN1_RX1_IRQHandler [WEAK]
+ EXPORT CAN1_SCE_IRQHandler [WEAK]
+ EXPORT EXTI9_5_IRQHandler [WEAK]
+ EXPORT TIM1_BRK_TIM15_IRQHandler [WEAK]
+ EXPORT TIM1_UP_TIM16_IRQHandler [WEAK]
+ EXPORT TIM1_TRG_COM_IRQHandler [WEAK]
+ EXPORT TIM1_CC_IRQHandler [WEAK]
+ EXPORT TIM2_IRQHandler [WEAK]
+ EXPORT I2C1_EV_IRQHandler [WEAK]
+ EXPORT I2C1_ER_IRQHandler [WEAK]
+ EXPORT I2C2_EV_IRQHandler [WEAK]
+ EXPORT I2C2_ER_IRQHandler [WEAK]
+ EXPORT SPI1_IRQHandler [WEAK]
+ EXPORT SPI2_IRQHandler [WEAK]
+ EXPORT USART1_IRQHandler [WEAK]
+ EXPORT USART2_IRQHandler [WEAK]
+ EXPORT USART3_IRQHandler [WEAK]
+ EXPORT EXTI15_10_IRQHandler [WEAK]
+ EXPORT RTC_Alarm_IRQHandler [WEAK]
+ EXPORT SDMMC1_IRQHandler [WEAK]
+ EXPORT SPI3_IRQHandler [WEAK]
+ EXPORT TIM6_DAC_IRQHandler [WEAK]
+ EXPORT TIM7_IRQHandler [WEAK]
+ EXPORT DMA2_Channel1_IRQHandler [WEAK]
+ EXPORT DMA2_Channel2_IRQHandler [WEAK]
+ EXPORT DMA2_Channel3_IRQHandler [WEAK]
+ EXPORT DMA2_Channel4_IRQHandler [WEAK]
+ EXPORT DMA2_Channel5_IRQHandler [WEAK]
+ EXPORT COMP_IRQHandler [WEAK]
+ EXPORT LPTIM1_IRQHandler [WEAK]
+ EXPORT LPTIM2_IRQHandler [WEAK]
+ EXPORT DMA2_Channel6_IRQHandler [WEAK]
+ EXPORT DMA2_Channel7_IRQHandler [WEAK]
+ EXPORT LPUART1_IRQHandler [WEAK]
+ EXPORT QUADSPI_IRQHandler [WEAK]
+ EXPORT I2C3_EV_IRQHandler [WEAK]
+ EXPORT I2C3_ER_IRQHandler [WEAK]
+ EXPORT SAI1_IRQHandler [WEAK]
+ EXPORT SWPMI1_IRQHandler [WEAK]
+ EXPORT TSC_IRQHandler [WEAK]
+ EXPORT RNG_IRQHandler [WEAK]
+ EXPORT FPU_IRQHandler [WEAK]
+ EXPORT CRS_IRQHandler [WEAK]
+
+WWDG_IRQHandler
+PVD_PVM_IRQHandler
+TAMP_STAMP_IRQHandler
+RTC_WKUP_IRQHandler
+FLASH_IRQHandler
+RCC_IRQHandler
+EXTI0_IRQHandler
+EXTI1_IRQHandler
+EXTI2_IRQHandler
+EXTI3_IRQHandler
+EXTI4_IRQHandler
+DMA1_Channel1_IRQHandler
+DMA1_Channel2_IRQHandler
+DMA1_Channel3_IRQHandler
+DMA1_Channel4_IRQHandler
+DMA1_Channel5_IRQHandler
+DMA1_Channel6_IRQHandler
+DMA1_Channel7_IRQHandler
+ADC1_IRQHandler
+CAN1_TX_IRQHandler
+CAN1_RX0_IRQHandler
+CAN1_RX1_IRQHandler
+CAN1_SCE_IRQHandler
+EXTI9_5_IRQHandler
+TIM1_BRK_TIM15_IRQHandler
+TIM1_UP_TIM16_IRQHandler
+TIM1_TRG_COM_IRQHandler
+TIM1_CC_IRQHandler
+TIM2_IRQHandler
+I2C1_EV_IRQHandler
+I2C1_ER_IRQHandler
+I2C2_EV_IRQHandler
+I2C2_ER_IRQHandler
+SPI1_IRQHandler
+SPI2_IRQHandler
+USART1_IRQHandler
+USART2_IRQHandler
+USART3_IRQHandler
+EXTI15_10_IRQHandler
+RTC_Alarm_IRQHandler
+SDMMC1_IRQHandler
+SPI3_IRQHandler
+TIM6_DAC_IRQHandler
+TIM7_IRQHandler
+DMA2_Channel1_IRQHandler
+DMA2_Channel2_IRQHandler
+DMA2_Channel3_IRQHandler
+DMA2_Channel4_IRQHandler
+DMA2_Channel5_IRQHandler
+COMP_IRQHandler
+LPTIM1_IRQHandler
+LPTIM2_IRQHandler
+DMA2_Channel6_IRQHandler
+DMA2_Channel7_IRQHandler
+LPUART1_IRQHandler
+QUADSPI_IRQHandler
+I2C3_EV_IRQHandler
+I2C3_ER_IRQHandler
+SAI1_IRQHandler
+SWPMI1_IRQHandler
+TSC_IRQHandler
+RNG_IRQHandler
+FPU_IRQHandler
+CRS_IRQHandler
+
+ B .
+
+ ENDP
+
+ ALIGN
+
+;*******************************************************************************
+; User Stack and Heap initialization
+;*******************************************************************************
+ IF :DEF:__MICROLIB
+
+ EXPORT __initial_sp
+ EXPORT __heap_base
+ EXPORT __heap_limit
+
+ ELSE
+
+ IMPORT __use_two_region_memory
+ EXPORT __user_initial_stackheap
+
+__user_initial_stackheap
+
+ LDR R0, = Heap_Mem
+ LDR R1, =(Stack_Mem + Stack_Size)
+ LDR R2, = (Heap_Mem + Heap_Size)
+ LDR R3, = Stack_Mem
+ BX LR
+
+ ALIGN
+
+ ENDIF
+
+ END
+
+;************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE*****
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/.gitignore b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/.gitignore
new file mode 100644
index 00000000..32f060b5
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/.gitignore
@@ -0,0 +1,32 @@
+.settings/
+*.cproject
+*.project
+*.o
+*.d
+*.lo
+*.gcno
+*.gcda
+/INSTALL
+cscope.*
+*.swp
+*.swo
+ltmain.sh
+*.kv
+*.bak
+/Default/
+.O/
+.config
+output/
+ota.bin
+src/packages/*.git/hooks/*.sample
+vs_build/
+.vs/
+doc/html/
+compile.log
+CMakeLists.txt.user
+qt_build/
+.vscode/
+GPATH
+GRTAGS
+GTAGS
+iotx-sdk-c-test/
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/LICENSE b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/LICENSE
new file mode 100644
index 00000000..57bc88a1
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/LICENSE
@@ -0,0 +1,202 @@
+ 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/connectivity/iotkit-embedded-3.0.1/3rdparty/README.md b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/README.md
new file mode 100644
index 00000000..dbe1b157
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/README.md
@@ -0,0 +1,26 @@
+# 用户手册
+
+https://code.aliyun.com/edward.yangx/public-docs/wikis/user-guide/Linkkit_User_Manual
+
+# C-SDK 简介
+
+è®¾å¤‡åŽ‚å•†åœ¨è®¾å¤‡ä¸Šé›†æˆ `C-SDK` åŽ, å¯ä»¥å°†è®¾å¤‡å®‰å…¨çš„æŽ¥å…¥åˆ°é˜¿é‡Œäº‘IoT物è”网平å°, 从而使设备å¯ä»¥è¢«é˜¿é‡Œäº‘IoT物è”网平å°è¿›è¡Œç®¡ç†
+
+è®¾å¤‡éœ€è¦æ”¯æŒTCP/IPåè®®æ ˆæˆ–ä¸²å£é€šä¿¡, 以åŠC99æ ‡å‡†çš„C库æ‰èƒ½é›†æˆSDK, zigbee/433/KNXè¿™æ ·çš„éžIP设备需è¦é€šè¿‡ç½‘关设备接入到阿里云IoT物è”网平å°, 网关设备需è¦é›†æˆC-SDK
+
+
+# 快速开始
+
+用户å¯ä»¥é€šè¿‡[快速的体验C-SDK](https://code.aliyun.com/edward.yangx/public-docs/wikis/user-guide/linkkit/Quick_Start)感å—如何将设备连接到阿里云物è”网平å°, 并如何将设备的数æ®å‘é€åˆ°å¹³å°/以åŠå¦‚何从物è”ç½‘å¹³å°æŽ¥æ”¶æ•°æ®
+
+
+# ç§»æ¤è¯´æ˜Ž
+C-SDK与OS/ç¡¬ä»¶å¹³å°æ— å…³, 全部部分用C编写, 它定义了HAL层æ¥å¯¹æŽ¥ä¸Žç¡¬ä»¶ç›¸å…³çš„功能, å› æ¤åœ¨ä½¿ç”¨C-SDK时用户需è¦åŽ»å®žçŽ°ç›¸å…³çš„HAL函数
+
+ç›®å‰C-SDK已实现了在Linux/Windows/AliOS上HAL的实现, åŒæ—¶å¯¹äºŽä¸€äº›å¸¸è§çš„OS或者模组也进行了适é…, å¯ä»¥[访问æ¤å¤„](https://code.aliyun.com/edward.yangx/public-docs/wikis/user-guide/linkkit/Port_Guide/Porting_Overview)查看如何在相应平å°ä¸Šè¿›è¡ŒSDK的编译与集æˆ
+
+
+# 编程文档
+
+SDKæä¾›äº†ä¸€ç³»åˆ—çš„ç¼–ç¨‹æ–‡æ¡£æ¥æè¿°å¦‚ä½•ä½¿ç”¨SDKæä¾›çš„软件功能, 请[访问æ¤å¤„](https://code.aliyun.com/edward.yangx/public-docs/wikis/user-guide/Linkkit_User_Manual)进行了解
+
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/certs/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/certs/iot.mk
new file mode 100644
index 00000000..48d6a9c6
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/certs/iot.mk
@@ -0,0 +1 @@
+LIBA_TARGET := libiot_cert.a
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/certs/root_ca.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/certs/root_ca.c
new file mode 100644
index 00000000..4881a944
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/certs/root_ca.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include
+
+const char *iotx_ca_crt = \
+{
+ \
+ "-----BEGIN CERTIFICATE-----\r\n"
+ "MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\r\n" \
+ "A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\r\n" \
+ "b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw\r\n" \
+ "MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\r\n" \
+ "YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT\r\n" \
+ "aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ\r\n" \
+ "jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp\r\n" \
+ "xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp\r\n" \
+ "1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\r\n" \
+ "snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ\r\n" \
+ "U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8\r\n" \
+ "9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E\r\n" \
+ "BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B\r\n" \
+ "AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz\r\n" \
+ "yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE\r\n" \
+ "38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP\r\n" \
+ "AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad\r\n" \
+ "DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\r\n" \
+ "HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\r\n" \
+ "-----END CERTIFICATE-----"
+};
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/config.bat b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/config.bat
new file mode 100644
index 00000000..944b58ef
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/config.bat
@@ -0,0 +1,11 @@
+@echo off
+chcp 437
+
+set CONFIG_=FEATURE_
+
+.\tools\prebuilt\windows\kconfig-frontends-3.12.0-windows\kconfig-mconf.exe .\tools\Config.in
+
+if exist .config (
+ copy /y .config make.settings
+ del /F .config
+)
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/.gitignore b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/.gitignore
new file mode 100644
index 00000000..bf67d02e
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/.gitignore
@@ -0,0 +1,4 @@
+Makefile
+*.sln
+*.vcxproj
+mbedtls/check_config
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/aes.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/aes.h
new file mode 100644
index 00000000..115db985
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/aes.h
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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 Internal AES block encryption function
+ * (Only exposed to allow overriding it,
+ * see MBEDTLS_AES_ENCRYPT_ALT)
+ *
+ * \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 static inline void mbedtls_aes_encrypt(
+ mbedtls_aes_context *ctx,
+ const unsigned char input[16],
+ unsigned char output[16])
+{
+ mbedtls_internal_aes_encrypt(ctx, input, output);
+}
+
+/**
+ * \brief Internal AES block decryption function
+ * (Only exposed to allow overriding it,
+ * see MBEDTLS_AES_DECRYPT_ALT)
+ *
+ * \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 static inline void mbedtls_aes_decrypt(
+ mbedtls_aes_context *ctx,
+ const unsigned char input[16],
+ unsigned char output[16])
+{
+ mbedtls_internal_aes_decrypt(ctx, input, output);
+}
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/asn1.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/asn1.h
new file mode 100644
index 00000000..b561b49a
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/asn1.h
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/base64.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/base64.h
new file mode 100644
index 00000000..ef2cd0bd
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/base64.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/bignum.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/bignum.h
new file mode 100644
index 00000000..4781c6b7
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/bignum.h
@@ -0,0 +1,701 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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 )
+
+/*
+ * Define the base integer type, architecture-wise.
+ *
+ * 32-bit integers can be forced on 64-bit arches (eg. for testing purposes)
+ * by defining MBEDTLS_HAVE_INT32 and undefining MBEDTLS_HAVE_ASM
+ */
+#if ( ! defined(MBEDTLS_HAVE_INT32) && \
+ defined(_MSC_VER) && defined(_M_AMD64) )
+#define MBEDTLS_HAVE_INT64
+typedef int64_t mbedtls_mpi_sint;
+typedef uint64_t mbedtls_mpi_uint;
+#else
+#if ( ! defined(MBEDTLS_HAVE_INT32) && \
+ defined(__GNUC__) && ( \
+ defined(__amd64__) || defined(__x86_64__) || \
+ defined(__ppc64__) || defined(__powerpc64__) || \
+ defined(__ia64__) || defined(__alpha__) || \
+ (defined(__sparc__) && defined(__arch64__)) || \
+ defined(__s390x__) || defined(__mips64) ) )
+#define MBEDTLS_HAVE_INT64
+typedef int64_t mbedtls_mpi_sint;
+typedef uint64_t mbedtls_mpi_uint;
+/* mbedtls_t_udbl defined as 128-bit unsigned int */
+typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI)));
+#define MBEDTLS_HAVE_UDBL
+#else
+#define MBEDTLS_HAVE_INT32
+typedef int32_t mbedtls_mpi_sint;
+typedef uint32_t mbedtls_mpi_uint;
+typedef uint64_t mbedtls_t_udbl;
+#define MBEDTLS_HAVE_UDBL
+#endif /* !MBEDTLS_HAVE_INT32 && __GNUC__ && 64-bit platform */
+#endif /* !MBEDTLS_HAVE_INT32 && _MSC_VER && _M_AMD64 */
+
+#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 X from 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
+ */
+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 negative or nil
+ 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);
+
+/**
+ * \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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/bn_mul.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/bn_mul.h
new file mode 100644
index 00000000..30b487ae
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/bn_mul.h
@@ -0,0 +1,869 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+/*
+ * 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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/check_config.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/check_config.h
new file mode 100644
index 00000000..6d600fe9
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/check_config.h
@@ -0,0 +1,644 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+/*
+ * 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
+
+/*
+ * 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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/cipher.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/cipher.h
new file mode 100644
index 00000000..763ed439
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/cipher.h
@@ -0,0 +1,699 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/cipher_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/cipher_internal.h
new file mode 100644
index 00000000..db57b2e7
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/cipher_internal.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/config.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/config.h
new file mode 100644
index 00000000..cc1763c9
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/config.h
@@ -0,0 +1,2640 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#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_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
+
+/**
+ * \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: 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 and 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'). */
+
+/* \} 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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ctr_drbg.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ctr_drbg.h
new file mode 100644
index 00000000..7b78285d
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ctr_drbg.h
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/debug.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/debug.h
new file mode 100644
index 00000000..e62f6764
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/debug.h
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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"
+
+#define tls_info(...) log_info("tls", __VA_ARGS__)
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/des.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/des.h
new file mode 100644
index 00000000..a2ce8824
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/des.h
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ecp.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ecp.h
new file mode 100644
index 00000000..da8699c9
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ecp.h
@@ -0,0 +1,663 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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 index 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 index);
+
+/**
+ * \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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/entropy.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/entropy.h
new file mode 100644
index 00000000..1aa97f2a
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/entropy.h
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/entropy_poll.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/entropy_poll.h
new file mode 100644
index 00000000..85cdfee5
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/entropy_poll.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/error.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/error.h
new file mode 100644
index 00000000..09e0de79
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/error.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef MBEDTLS_ERROR_H
+#define MBEDTLS_ERROR_H
+
+#include
+#include "config.h"
+
+/**
+ * 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 19
+ * 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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md.h
new file mode 100644
index 00000000..c7c3b566
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md.h
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md5.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md5.h
new file mode 100644
index 00000000..1ef52a07
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md5.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md_internal.h
new file mode 100644
index 00000000..5f5ca6c8
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/md_internal.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/net.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/net.h
new file mode 100644
index 00000000..4ad82238
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/net.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/net_sockets.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/net_sockets.h
new file mode 100644
index 00000000..cf3eb9c8
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/net_sockets.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/oid.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/oid.h
new file mode 100644
index 00000000..e1f58de6
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/oid.h
@@ -0,0 +1,554 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pem.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pem.h
new file mode 100644
index 00000000..589fbf8f
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pem.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pk.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pk.h
new file mode 100644
index 00000000..a25e358f
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pk.h
@@ -0,0 +1,596 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pk_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pk_internal.h
new file mode 100644
index 00000000..f1868251
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/pk_internal.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/platform.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/platform.h
new file mode 100644
index 00000000..640094f0
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/platform.h
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* platform.h */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/rsa.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/rsa.h
new file mode 100644
index 00000000..4c9cee03
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/rsa.h
@@ -0,0 +1,635 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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 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_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 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_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 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_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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/sha1.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/sha1.h
new file mode 100644
index 00000000..3c247a63
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/sha1.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/sha256.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/sha256.h
new file mode 100644
index 00000000..38f1272c
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/sha256.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl.h
new file mode 100644
index 00000000..e3503412
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl.h
@@ -0,0 +1,2573 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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!
+ */
+
+/*
+ * !!!!! NOTE !!!!!
+ *
+ * Modification to value of MBEDTLS_SSL_MAX_CONTENT_LEN must be considered and verified carefully
+ *
+ * MBEDTLS_SSL_MAX_CONTENT_LEN >= 4096
+ *
+ * is mandantory to connect Aliyun Servers
+ *
+ * THIS DEFAULT CONFIGURATION IS CHANGED AT YOUR OWN RISK
+ *
+ * !!!!! NOTE !!!!!
+ */
+#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;
+#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 record_read; /*!< record is already present */
+
+ /*
+ * 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 x509parse_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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_ciphersuites.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_ciphersuites.h
new file mode 100644
index 00000000..9551b952
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_ciphersuites.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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 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 a 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);
+#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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ssl_ciphersuites.h */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_cookie.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_cookie.h
new file mode 100644
index 00000000..27768f61
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_cookie.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_internal.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_internal.h
new file mode 100644
index 00000000..3e97a1e7
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/ssl_internal.h
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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
+
+/*
+ * This structure contains the parameters only needed during handshake.
+ */
+struct mbedtls_ssl_handshake_params {
+ /*
+ * Handshake specific crypto variables
+ */
+ int sig_alg; /*!< Hash algorithm for signature */
+ int verify_sig_alg; /*!< Signature algorithm for verify */
+#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
+#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
+#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
+
+ /*
+ * 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 */
+
+
+/**
+ * \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);
+
+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);
+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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/timing.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/timing.h
new file mode 100644
index 00000000..776a6eba
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/timing.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509.h
new file mode 100644
index 00000000..7fa899b4
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509.h
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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. */
+/* \} 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 time 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 *time);
+
+/**
+ * \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 time 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 *time);
+
+/**
+ * \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 *time);
+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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509_crl.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509_crl.h
new file mode 100644
index 00000000..75172d9e
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509_crl.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509_crt.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509_crt.h
new file mode 100644
index 00000000..c7ea581f
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/include/mbedtls/x509_crt.h
@@ -0,0 +1,637 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#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 but a fatal error.
+ *
+ * \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 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(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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/iot.mk
new file mode 100644
index 00000000..5a90afd9
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/iot.mk
@@ -0,0 +1,6 @@
+LIBA_TARGET := libiot_tls.a
+
+HDR_REFS += src/infra
+
+CFLAGS := $(filter-out -Wdeclaration-after-statement,$(CFLAGS))
+CFLAGS := $(filter-out -ansi,$(CFLAGS))
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/.gitignore b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/.gitignore
new file mode 100644
index 00000000..3a63a63a
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/.gitignore
@@ -0,0 +1,4 @@
+*.o
+libmbed*
+*.sln
+*.vcxproj
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/Makefile b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/Makefile
new file mode 100644
index 00000000..28f92315
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/Makefile
@@ -0,0 +1,169 @@
+
+# Also see "include/mbedtls/config.h"
+
+CFLAGS ?= -O2
+WARNING_CFLAGS ?= -Wall -W -Wdeclaration-after-statement
+LDFLAGS ?=
+
+LOCAL_CFLAGS = $(WARNING_CFLAGS) -I../include -D_FILE_OFFSET_BITS=64
+LOCAL_LDFLAGS =
+
+ifdef DEBUG
+LOCAL_CFLAGS += -g3
+endif
+
+# MicroBlaze specific options:
+# CFLAGS += -mno-xl-soft-mul -mxl-barrel-shift
+
+# To compile on Plan9:
+# CFLAGS += -D_BSD_EXTENSION
+
+# if were running on Windows build for Windows
+ifdef WINDOWS
+WINDOWS_BUILD=1
+endif
+
+# To compile as a shared library:
+ifdef SHARED
+# all code is position-indep with mingw, avoid warning about useless flag
+ifndef WINDOWS_BUILD
+LOCAL_CFLAGS += -fPIC -fpic
+endif
+endif
+
+SOEXT_TLS=so.10
+SOEXT_X509=so.0
+SOEXT_CRYPTO=so.0
+
+DLEXT=so
+# OSX shared library extension:
+# DLEXT=dylib
+
+# Windows shared library extension:
+ifdef WINDOWS_BUILD
+DLEXT=dll
+endif
+
+OBJS_CRYPTO= aes.o aesni.o arc4.o \
+ asn1parse.o asn1write.o base64.o \
+ bignum.o blowfish.o camellia.o \
+ ccm.o cipher.o cipher_wrap.o \
+ cmac.o ctr_drbg.o des.o \
+ dhm.o ecdh.o ecdsa.o \
+ ecjpake.o ecp.o \
+ ecp_curves.o entropy.o entropy_poll.o \
+ error.o gcm.o havege.o \
+ hmac_drbg.o md.o md2.o \
+ md4.o md5.o md_wrap.o \
+ memory_buffer_alloc.o oid.o \
+ padlock.o pem.o pk.o \
+ pk_wrap.o pkcs12.o pkcs5.o \
+ pkparse.o pkwrite.o platform.o \
+ ripemd160.o rsa.o sha1.o \
+ sha256.o sha512.o threading.o \
+ timing.o version.o \
+ version_features.o xtea.o
+
+OBJS_X509= certs.o pkcs11.o x509.o \
+ x509_create.o x509_crl.o x509_crt.o \
+ x509_csr.o x509write_crt.o x509write_csr.o
+
+OBJS_TLS= debug.o net_sockets.o \
+ ssl_cache.o ssl_ciphersuites.o \
+ ssl_cli.o ssl_cookie.o \
+ ssl_srv.o ssl_ticket.o \
+ ssl_tls.o
+
+.SILENT:
+
+.PHONY: all static shared clean
+
+ifndef SHARED
+all: static
+else
+all: shared static
+endif
+
+static: libmbedcrypto.a libmbedx509.a libmbedtls.a
+
+shared: libmbedcrypto.$(DLEXT) libmbedx509.$(DLEXT) libmbedtls.$(DLEXT)
+
+# tls
+libmbedtls.a: $(OBJS_TLS)
+ echo " AR $@"
+ $(AR) -rc $@ $(OBJS_TLS)
+ echo " RL $@"
+ $(AR) -s $@
+
+libmbedtls.$(SOEXT_TLS): $(OBJS_TLS) libmbedx509.so
+ echo " LD $@"
+ $(CC) -shared -Wl,-soname,$@ -L. -lmbedcrypto -lmbedx509 $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_TLS)
+
+libmbedtls.so: libmbedtls.$(SOEXT_TLS)
+ echo " LN $@ -> $<"
+ ln -sf $< $@
+
+libmbedtls.dylib: $(OBJS_TLS)
+ echo " LD $@"
+ $(CC) -dynamiclib $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_TLS)
+
+libmbedtls.dll: $(OBJS_TLS) libmbedx509.dll
+ echo " LD $@"
+ $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_TLS) -lws2_32 -lwinmm -lgdi32 -L. -lmbedcrypto -lmbedx509 -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS)
+
+# x509
+libmbedx509.a: $(OBJS_X509)
+ echo " AR $@"
+ $(AR) -rc $@ $(OBJS_X509)
+ echo " RL $@"
+ $(AR) -s $@
+
+libmbedx509.$(SOEXT_X509): $(OBJS_X509) libmbedcrypto.so
+ echo " LD $@"
+ $(CC) -shared -Wl,-soname,$@ -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509)
+
+libmbedx509.so: libmbedx509.$(SOEXT_X509)
+ echo " LN $@ -> $<"
+ ln -sf $< $@
+
+libmbedx509.dylib: $(OBJS_X509)
+ echo " LD $@"
+ $(CC) -dynamiclib $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509)
+
+libmbedx509.dll: $(OBJS_X509) libmbedcrypto.dll
+ echo " LD $@"
+ $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_X509) -lws2_32 -lwinmm -lgdi32 -L. -lmbedcrypto -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS)
+
+# crypto
+libmbedcrypto.a: $(OBJS_CRYPTO)
+ echo " AR $@"
+ $(AR) -rc $@ $(OBJS_CRYPTO)
+ echo " RL $@"
+ $(AR) -s $@
+
+libmbedcrypto.$(SOEXT_CRYPTO): $(OBJS_CRYPTO)
+ echo " LD $@"
+ $(CC) -shared -Wl,-soname,$@ $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_CRYPTO)
+
+libmbedcrypto.so: libmbedcrypto.$(SOEXT_CRYPTO)
+ echo " LN $@ -> $<"
+ ln -sf $< $@
+
+libmbedcrypto.dylib: $(OBJS_CRYPTO)
+ echo " LD $@"
+ $(CC) -dynamiclib $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_CRYPTO)
+
+libmbedcrypto.dll: $(OBJS_CRYPTO)
+ echo " LD $@"
+ $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_CRYPTO) -lws2_32 -lwinmm -lgdi32 -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS)
+
+.c.o:
+ echo " CC $<"
+ $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -c $<
+
+clean:
+ifndef WINDOWS
+ rm -f *.o libmbed*
+else
+ del /Q /F *.o libmbed*
+endif
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/aes.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/aes.c
new file mode 100644
index 00000000..d944aa40
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/aes.c
@@ -0,0 +1,1481 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+/*
+ * 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
+#include "mbedtls/debug.h"
+#define mbedtls_printf tls_info
+#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 */
+
+/*
+ * 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 */
+
+/*
+ * 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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/asn1parse.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/asn1parse.c
new file mode 100644
index 00000000..8a1a55ea
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/asn1parse.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/base64.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/base64.c
new file mode 100644
index 00000000..b31531f2
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/base64.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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
+#include "mbedtls/debug.h"
+
+#define mbedtls_printf tls_info
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/bignum.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/bignum.c
new file mode 100644
index 00000000..da75c466
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/bignum.c
@@ -0,0 +1,2436 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+/*
+ * 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
+#include "mbedtls/debug.h"
+
+#define mbedtls_printf tls_info
+#define mbedtls_calloc calloc
+#define mbedtls_free free
+#endif
+
+/* 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 ) );
+ MBEDTLS_MPI_CHK( (X->p == NULL) );
+ 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( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; }
+ if( 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 ) );
+}
+
+/*
+ * 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 );
+}
+
+/*
+ * 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 );
+}
+
+/*
+ * 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 );
+}
+
+/*
+ * 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 )
+ {
+ 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 );
+}
+
+/*
+ * 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, 0 ) <= 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 */
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/cipher.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/cipher.c
new file mode 100644
index 00000000..70967d4e
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/cipher.c
@@ -0,0 +1,894 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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 )
+ {
+ 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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/cipher_wrap.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/cipher_wrap.c
new file mode 100644
index 00000000..2ff10638
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/cipher_wrap.c
@@ -0,0 +1,1433 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ctr_drbg.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ctr_drbg.c
new file mode 100644
index 00000000..6b282c24
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ctr_drbg.c
@@ -0,0 +1,583 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+/*
+ * 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
+#include "mbedtls/debug.h"
+
+#define mbedtls_printf tls_info
+#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 ||
+ len < 0)
+ 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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/debug.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/debug.c
new file mode 100644
index 00000000..a5e3062a
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/debug.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#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] = '\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)",
+ 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)",
+ 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", 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", 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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/entropy.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/entropy.c
new file mode 100644
index 00000000..97381dbb
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/entropy.c
@@ -0,0 +1,643 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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
+#include "mbedtls/debug.h"
+
+#define mbedtls_printf tls_info
+#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 index, ret = 0;
+
+#if defined(MBEDTLS_THREADING_C)
+ if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
+ return( ret );
+#endif
+
+ index = ctx->source_count;
+ if( index >= MBEDTLS_ENTROPY_MAX_SOURCES )
+ {
+ ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES;
+ goto exit;
+ }
+
+ ctx->source[index].f_source = f_source;
+ ctx->source[index].p_source = p_source;
+ ctx->source[index].threshold = threshold;
+ ctx->source[index].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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/entropy_poll.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/entropy_poll.c
new file mode 100644
index 00000000..33d114d2
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/entropy_poll.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/error.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/error.c
new file mode 100644
index 00000000..e2d84898
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/error.c
@@ -0,0 +1,693 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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" );
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/md.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/md.c
new file mode 100644
index 00000000..0034b10f
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/md.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/md_wrap.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/md_wrap.c
new file mode 100644
index 00000000..e3bfba01
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/md_wrap.c
@@ -0,0 +1,557 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/net_sockets.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/net_sockets.c
new file mode 100644
index 00000000..e035430b
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/net_sockets.c
@@ -0,0 +1,572 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_NET_C)
+
+#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
+ !defined(__APPLE__) && !defined(_WIN32)
+#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in config.h"
+#endif
+
+#if defined(MBEDTLS_PLATFORM_C)
+#include "mbedtls/platform.h"
+#else
+#include
+#endif
+
+#include "mbedtls/net_sockets.h"
+
+#include
+
+#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
+ !defined(EFI32)
+
+#ifdef _WIN32_WINNT
+#undef _WIN32_WINNT
+#endif
+/* Enables getaddrinfo() & Co */
+#define _WIN32_WINNT 0x0501
+#include
+
+#include
+#include
+
+#if defined(_MSC_VER)
+#if defined(_WIN32_WCE)
+#pragma comment( lib, "ws2.lib" )
+#else
+#pragma comment( lib, "ws2_32.lib" )
+#endif
+#endif /* _MSC_VER */
+
+#define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0)
+#define write(fd,buf,len) send(fd,(char*)buf,(int) len,0)
+#define close(fd) closesocket(fd)
+
+static int wsa_init_done = 0;
+
+#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
+
+/* Some MS functions want int and MSVC warns if we pass size_t,
+ * but the standard fucntions use socklen_t, so cast only for MSVC */
+#if defined(_MSC_VER)
+#define MSVC_INT_CAST (int)
+#else
+#define MSVC_INT_CAST
+#endif
+
+#include
+
+#include
+
+#include
+
+/*
+ * Prepare for using the sockets interface
+ */
+static int net_prepare( void )
+{
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+ !defined(EFI32)
+ WSADATA wsaData;
+
+ if( wsa_init_done == 0 )
+ {
+ if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
+ return( MBEDTLS_ERR_NET_SOCKET_FAILED );
+
+ wsa_init_done = 1;
+ }
+#else
+#if !defined(EFIX64) && !defined(EFI32)
+ signal( SIGPIPE, SIG_IGN );
+#endif
+#endif
+ return( 0 );
+}
+
+/*
+ * Initialize a context
+ */
+void mbedtls_net_init( mbedtls_net_context *ctx )
+{
+ ctx->fd = -1;
+}
+
+/*
+ * Initiate a TCP connection with host:port and the given protocol
+ */
+int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host,
+ const char *port, int proto )
+{
+ int ret;
+ struct addrinfo hints, *addr_list, *cur;
+
+ if( ( ret = net_prepare() ) != 0 )
+ return( ret );
+
+ /* Do name resolution with both IPv6 and IPv4 */
+ memset( &hints, 0, sizeof( hints ) );
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
+ hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
+
+ if( getaddrinfo( host, port, &hints, &addr_list ) != 0 )
+ return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
+
+ /* Try the sockaddrs until a connection succeeds */
+ ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
+ for( cur = addr_list; cur != NULL; cur = cur->ai_next )
+ {
+ ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
+ cur->ai_protocol );
+ if( ctx->fd < 0 )
+ {
+ ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
+ continue;
+ }
+
+ if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 )
+ {
+ ret = 0;
+ break;
+ }
+
+ close( ctx->fd );
+ ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
+ }
+
+ freeaddrinfo( addr_list );
+
+ return( ret );
+}
+
+/*
+ * Create a listening socket on bind_ip:port
+ */
+int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto )
+{
+ int n, ret;
+ struct addrinfo hints, *addr_list, *cur;
+
+ if( ( ret = net_prepare() ) != 0 )
+ return( ret );
+
+ /* Bind to IPv6 and/or IPv4, but only in the desired protocol */
+ memset( &hints, 0, sizeof( hints ) );
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
+ hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
+ if( bind_ip == NULL )
+ hints.ai_flags = AI_PASSIVE;
+
+ if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 )
+ return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
+
+ /* Try the sockaddrs until a binding succeeds */
+ ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
+ for( cur = addr_list; cur != NULL; cur = cur->ai_next )
+ {
+ ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
+ cur->ai_protocol );
+ if( ctx->fd < 0 )
+ {
+ ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
+ continue;
+ }
+
+ n = 1;
+ if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR,
+ (const char *) &n, sizeof( n ) ) != 0 )
+ {
+ close( ctx->fd );
+ ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
+ continue;
+ }
+
+ if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 )
+ {
+ close( ctx->fd );
+ ret = MBEDTLS_ERR_NET_BIND_FAILED;
+ continue;
+ }
+
+ /* Listen only makes sense for TCP */
+ if( proto == MBEDTLS_NET_PROTO_TCP )
+ {
+ if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 )
+ {
+ close( ctx->fd );
+ ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
+ continue;
+ }
+ }
+
+ /* Bind was successful */
+ ret = 0;
+ break;
+ }
+
+ freeaddrinfo( addr_list );
+
+ return( ret );
+
+}
+
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+ !defined(EFI32)
+/*
+ * Check if the requested operation would be blocking on a non-blocking socket
+ * and thus 'failed' with a negative return value.
+ */
+static int net_would_block( const mbedtls_net_context *ctx )
+{
+ ((void) ctx);
+ return( WSAGetLastError() == WSAEWOULDBLOCK );
+}
+#else
+/*
+ * Check if the requested operation would be blocking on a non-blocking socket
+ * and thus 'failed' with a negative return value.
+ *
+ * Note: on a blocking socket this function always returns 0!
+ */
+static int net_would_block( const mbedtls_net_context *ctx )
+{
+ /*
+ * Never return 'WOULD BLOCK' on a non-blocking socket
+ */
+ if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK )
+ return( 0 );
+
+ switch( errno )
+ {
+#if defined EAGAIN
+ case EAGAIN:
+#endif
+#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
+ case EWOULDBLOCK:
+#endif
+ return( 1 );
+ }
+ return( 0 );
+}
+#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
+
+/*
+ * Accept a connection from a remote client
+ */
+int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
+ mbedtls_net_context *client_ctx,
+ void *client_ip, size_t buf_size, size_t *ip_len )
+{
+ int ret;
+ int type;
+
+ struct sockaddr_storage client_addr;
+
+#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \
+ defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t)
+ socklen_t n = (socklen_t) sizeof( client_addr );
+ socklen_t type_len = (socklen_t) sizeof( type );
+#else
+ int n = (int) sizeof( client_addr );
+ int type_len = (int) sizeof( type );
+#endif
+
+ /* Is this a TCP or UDP socket? */
+ if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE,
+ (void *) &type, &type_len ) != 0 ||
+ ( type != SOCK_STREAM && type != SOCK_DGRAM ) )
+ {
+ return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
+ }
+
+ if( type == SOCK_STREAM )
+ {
+ /* TCP: actual accept() */
+ ret = client_ctx->fd = (int) accept( bind_ctx->fd,
+ (struct sockaddr *) &client_addr, &n );
+ }
+ else
+ {
+ /* UDP: wait for a message, but keep it in the queue */
+ char buf[1] = { 0 };
+
+ ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
+ (struct sockaddr *) &client_addr, &n );
+
+#if defined(_WIN32)
+ if( ret == SOCKET_ERROR &&
+ WSAGetLastError() == WSAEMSGSIZE )
+ {
+ /* We know buf is too small, thanks, just peeking here */
+ ret = 0;
+ }
+#endif
+ }
+
+ if( ret < 0 )
+ {
+ if( net_would_block( bind_ctx ) != 0 )
+ return( MBEDTLS_ERR_SSL_WANT_READ );
+
+ return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
+ }
+
+ /* UDP: hijack the listening socket to communicate with the client,
+ * then bind a new socket to accept new connections */
+ if( type != SOCK_STREAM )
+ {
+ struct sockaddr_storage local_addr;
+ int one = 1;
+
+ if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 )
+ return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
+
+ client_ctx->fd = bind_ctx->fd;
+ bind_ctx->fd = -1; /* In case we exit early */
+
+ n = sizeof( struct sockaddr_storage );
+ if( getsockname( client_ctx->fd,
+ (struct sockaddr *) &local_addr, &n ) != 0 ||
+ ( bind_ctx->fd = (int) socket( local_addr.ss_family,
+ SOCK_DGRAM, IPPROTO_UDP ) ) < 0 ||
+ setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,
+ (const char *) &one, sizeof( one ) ) != 0 )
+ {
+ return( MBEDTLS_ERR_NET_SOCKET_FAILED );
+ }
+
+ if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 )
+ {
+ return( MBEDTLS_ERR_NET_BIND_FAILED );
+ }
+ }
+
+ if( client_ip != NULL )
+ {
+ if( client_addr.ss_family == AF_INET )
+ {
+ struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
+ *ip_len = sizeof( addr4->sin_addr.s_addr );
+
+ if( buf_size < *ip_len )
+ return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
+
+ memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len );
+ }
+ else
+ {
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
+ *ip_len = sizeof( addr6->sin6_addr.s6_addr );
+
+ if( buf_size < *ip_len )
+ return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
+
+ memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len);
+ }
+ }
+
+ return( 0 );
+}
+
+/*
+ * Set the socket blocking or non-blocking
+ */
+int mbedtls_net_set_block( mbedtls_net_context *ctx )
+{
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+ !defined(EFI32)
+ u_long n = 0;
+ return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
+#else
+ return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) );
+#endif
+}
+
+int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
+{
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+ !defined(EFI32)
+ u_long n = 1;
+ return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
+#else
+ return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) );
+#endif
+}
+
+/*
+ * Portable usleep helper
+ */
+void mbedtls_net_usleep( unsigned long usec )
+{
+#if defined(_WIN32)
+ Sleep( ( usec + 999 ) / 1000 );
+#else
+ struct timeval tv;
+ tv.tv_sec = usec / 1000000;
+#if defined(__unix__) || defined(__unix) || \
+ ( defined(__APPLE__) && defined(__MACH__) )
+ tv.tv_usec = (suseconds_t) usec % 1000000;
+#else
+ tv.tv_usec = usec % 1000000;
+#endif
+ select( 0, NULL, NULL, NULL, &tv );
+#endif
+}
+
+/*
+ * Read at most 'len' characters
+ */
+int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
+{
+ int ret;
+ int fd = ((mbedtls_net_context *) ctx)->fd;
+
+ if( fd < 0 )
+ return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+
+ ret = (int) read( fd, buf, len );
+
+ if( ret < 0 )
+ {
+ if( net_would_block( ctx ) != 0 )
+ return( MBEDTLS_ERR_SSL_WANT_READ );
+
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+ !defined(EFI32)
+ if( WSAGetLastError() == WSAECONNRESET )
+ return( MBEDTLS_ERR_NET_CONN_RESET );
+#else
+ if( errno == EPIPE || errno == ECONNRESET )
+ return( MBEDTLS_ERR_NET_CONN_RESET );
+
+ if( errno == EINTR )
+ return( MBEDTLS_ERR_SSL_WANT_READ );
+#endif
+
+ return( MBEDTLS_ERR_NET_RECV_FAILED );
+ }
+
+ return( ret );
+}
+
+/*
+ * Read at most 'len' characters, blocking for at most 'timeout' ms
+ */
+int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
+ uint32_t timeout )
+{
+ int ret;
+ struct timeval tv;
+ fd_set read_fds;
+ int fd = ((mbedtls_net_context *) ctx)->fd;
+
+ if( fd < 0 )
+ return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+
+ FD_ZERO( &read_fds );
+ FD_SET( fd, &read_fds );
+
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = ( timeout % 1000 ) * 1000;
+
+ ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv );
+
+ /* Zero fds ready means we timed out */
+ if( ret == 0 )
+ return( MBEDTLS_ERR_SSL_TIMEOUT );
+
+ if( ret < 0 )
+ {
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+ !defined(EFI32)
+ if( WSAGetLastError() == WSAEINTR )
+ return( MBEDTLS_ERR_SSL_WANT_READ );
+#else
+ if( errno == EINTR )
+ return( MBEDTLS_ERR_SSL_WANT_READ );
+#endif
+
+ return( MBEDTLS_ERR_NET_RECV_FAILED );
+ }
+
+ /* This call will not block */
+ return( mbedtls_net_recv( ctx, buf, len ) );
+}
+
+/*
+ * Write at most 'len' characters
+ */
+int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
+{
+ int ret;
+ int fd = ((mbedtls_net_context *) ctx)->fd;
+
+ if( fd < 0 )
+ return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
+
+ ret = (int) write( fd, buf, len );
+
+ if( ret < 0 )
+ {
+ if( net_would_block( ctx ) != 0 )
+ return( MBEDTLS_ERR_SSL_WANT_WRITE );
+
+#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
+ !defined(EFI32)
+ if( WSAGetLastError() == WSAECONNRESET )
+ return( MBEDTLS_ERR_NET_CONN_RESET );
+#else
+ if( errno == EPIPE || errno == ECONNRESET )
+ return( MBEDTLS_ERR_NET_CONN_RESET );
+
+ if( errno == EINTR )
+ return( MBEDTLS_ERR_SSL_WANT_WRITE );
+#endif
+
+ return( MBEDTLS_ERR_NET_SEND_FAILED );
+ }
+
+ return( ret );
+}
+
+/*
+ * Gracefully close the connection
+ */
+void mbedtls_net_free( mbedtls_net_context *ctx )
+{
+ if( ctx->fd == -1 )
+ return;
+
+ shutdown( ctx->fd, 2 );
+ close( ctx->fd );
+
+ ctx->fd = -1;
+}
+
+#endif /* MBEDTLS_NET_C */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/oid.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/oid.c
new file mode 100644
index 00000000..ab461713
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/oid.c
@@ -0,0 +1,694 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pem.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pem.c
new file mode 100644
index 00000000..89f3b5a8
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pem.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pk.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pk.c
new file mode 100644
index 00000000..24ee3c51
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pk.c
@@ -0,0 +1,369 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pk_wrap.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pk_wrap.c
new file mode 100644
index 00000000..952349b1
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pk_wrap.c
@@ -0,0 +1,499 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pkparse.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pkparse.c
new file mode 100644
index 00000000..d4e7f9b6
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/pkparse.c
@@ -0,0 +1,1279 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/platform.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/platform.c
new file mode 100644
index 00000000..32523f5a
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/platform.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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 */
+
+#endif /* MBEDTLS_PLATFORM_C */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/rsa.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/rsa.c
new file mode 100644
index 00000000..0c983d69
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/rsa.c
@@ -0,0 +1,1846 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+/*
+ * 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, *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++;
+
+ 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
+ */
+ if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+ return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
+
+ if( asn1_len + 2 != len )
+ return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
+
+ if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
+ return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
+
+ if( asn1_len + 6 + hashlen != len )
+ return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
+
+ if( ( ret = mbedtls_asn1_get_tag( &p, end, &oid.len, MBEDTLS_ASN1_OID ) ) != 0 )
+ 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
+ */
+ if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_NULL ) ) != 0 )
+ return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
+
+ if( ( ret = mbedtls_asn1_get_tag( &p, end, &asn1_len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
+ return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
+
+ if( 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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/sha1.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/sha1.c
new file mode 100644
index 00000000..f6146f48
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/sha1.c
@@ -0,0 +1,436 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+/*
+ * 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
+#include "mbedtls/debug.h"
+
+#define mbedtls_printf tls_info
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/sha256.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/sha256.c
new file mode 100644
index 00000000..7c8e1399
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/sha256.c
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+/*
+ * 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
+#include "mbedtls/debug.h"
+
+#define mbedtls_printf tls_info
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_ciphersuites.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_ciphersuites.c
new file mode 100644
index 00000000..1648ca7c
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_ciphersuites.c
@@ -0,0 +1,1841 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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 );
+ }
+}
+#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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_cli.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_cli.c
new file mode 100644
index 00000000..e3415025
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_cli.c
@@ -0,0 +1,3391 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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++ )
+ {
+ info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
+#else
+ for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ )
+ {
+#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++ )
+ {
+ info = mbedtls_ecp_curve_info_from_grp_id( *grp_id );
+#else
+ for( info = mbedtls_ecp_curve_list(); info->grp_id != MBEDTLS_ECP_DP_NONE; info++ )
+ {
+#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 )
+{
+ int ret;
+
+#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" ) );
+
+ if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+ return( ret );
+
+ 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" ) );
+
+ if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+ return( ret );
+
+ 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 )
+ {
+ 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 )
+ {
+ 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 )
+ {
+ 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 )
+ {
+ 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 )
+ {
+ 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" ) );
+ 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" ) );
+ 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 );
+ 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 )
+ 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 )
+ return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
+
+ list_len = ( buf[0] << 8 ) | buf[1];
+ if( list_len != len - 2 )
+ return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO );
+
+ name_len = buf[2];
+ if( name_len != list_len - 1 )
+ 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 );
+ }
+ }
+
+ 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 )
+ {
+ 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" ) );
+ return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO );
+ }
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
+
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello 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" ) );
+ 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" ) );
+ 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" ) );
+ 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" ) );
+ 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 ) );
+ 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 ) );
+ 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 );
+ 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" ) );
+ 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" ) );
+ 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" ) );
+ 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" ) );
+ 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 )
+ {
+ if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+ return( ret );
+
+ 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 "
+ "that was not offered" ) );
+ 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 );
+ 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" ) );
+ 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 )
+ {
+ ssl->record_read = 1;
+ goto exit;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange 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" ) );
+ 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" ) );
+ 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" ) );
+ 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 );
+ 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_DHE_RSA_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
+ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+ if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ||
+ ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
+ ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA )
+ {
+ 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" ) );
+ 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" ) );
+ 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" ) );
+ 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 );
+ 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" ) );
+ 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" ) );
+ 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_DEBUG_RET( 1, "mbedtls_pk_verify", ret );
+ return( ret );
+ }
+ }
+#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED ||
+ MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED ||
+ MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
+
+exit:
+ ssl->state++;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server 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_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( 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 parse certificate request" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
+}
+#else
+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( 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 parse certificate request" ) );
+ ssl->state++;
+ return( 0 );
+ }
+
+ if( ssl->record_read == 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" ) );
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+
+ ssl->record_read = 1;
+ }
+
+ ssl->client_auth = 0;
+ ssl->state++;
+
+ if( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST )
+ ssl->client_auth++;
+
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request",
+ ssl->client_auth ? "a" : "no" ) );
+
+ if( ssl->client_auth == 0 )
+ goto exit;
+
+ ssl->record_read = 0;
+
+ /*
+ * 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" ) );
+ 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" ) );
+ 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" ) );
+ return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST );
+ }
+
+exit:
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) );
+
+ return( 0 );
+}
+#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 */
+
+static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl )
+{
+ int ret;
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) );
+
+ if( ssl->record_read == 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 server hello done message" ) );
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
+ }
+ }
+ ssl->record_read = 0;
+
+ 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" ) );
+ 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( 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 )
+ {
+ /*
+ * 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" ) );
+ 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" ) );
+ 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" ) );
+ 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" ) );
+ 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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_cookie.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_cookie.c
new file mode 100644
index 00000000..ee1b9f9c
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_cookie.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+/*
+ * 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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_tls.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_tls.c
new file mode 100644
index 00000000..38d967a8
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/ssl_tls.c
@@ -0,0 +1,7685 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+/*
+ * 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 ret;
+ 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" ) );
+
+ if( ( ret = mbedtls_ssl_send_alert_message( ssl,
+ MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ) ) != 0 )
+ {
+ return( ret );
+ }
+
+ 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" ) );
+
+ 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 );
+ }
+
+ if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE )
+ {
+ mbedtls_ssl_update_handshake_status( ssl );
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) );
+
+ return( 0 );
+}
+
+int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl )
+{
+ int ret;
+
+ if( ssl->in_hslen != 0 && ssl->in_hslen < ssl->in_msglen )
+ {
+ /*
+ * Get next Handshake message in the current record
+ */
+ 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 );
+
+ return( 0 );
+ }
+
+ ssl->in_hslen = 0;
+
+ /*
+ * Read the record header and parse it
+ */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+read_record_header:
+#endif
+
+ 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
+
+ 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" ) );
+
+ 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)
+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
+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;
+
+ 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_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" ) );
+
+ 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" ) );
+
+ 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" ) );
+ 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" ) );
+ 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" ) );
+ 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 ) ) );
+ 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" ) );
+ 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" ) );
+ return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
+ }
+
+ ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert,
+ ssl->in_msg + i, n );
+ if( 0 != ret && ( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND ) != ret )
+ {
+ 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" ) );
+ 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" ) );
+ 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;
+ }
+
+ if( ca_chain == NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) );
+ return( MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED );
+ }
+
+ /*
+ * 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 )
+ {
+ 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;
+ }
+
+ if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
+ ret = 0;
+ }
+
+ 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" ) );
+ 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" ) );
+ 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" ) );
+ 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 );
+ 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" ) );
+ 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" ) );
+ 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" ) );
+ 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;
+ handshake->sig_alg = MBEDTLS_SSL_HASH_SHA1;
+
+#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->record_read = 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, record_read = 0;
+ 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
+
+#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 )
+ {
+ ret = mbedtls_ssl_handshake( ssl );
+ if( ret == MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO )
+ {
+ record_read = 1;
+ }
+ else if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret );
+ return( ret );
+ }
+ }
+
+ 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( ! record_read )
+ {
+ 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" ) );
+
+#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 );
+ }
+
+ 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
+
+ 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 ) )
+ {
+ 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" alert
+ */
+ if( ( ret = mbedtls_ssl_send_fatal_handshake_failure( ssl ) ) != 0 )
+ return( ret );
+ }
+ 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
+ {
+ /* 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 )
+ {
+ record_read = 1;
+ }
+ else if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_start_renegotiation", ret );
+ return( ret );
+ }
+ }
+
+ /* If a non-handshake record was read during renego, fallthrough,
+ * else tell the user they should call mbedtls_ssl_read() again */
+ if( ! record_read )
+ 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
+ }
+
+ 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;
+ 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)
+ 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 );
+}
+
+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 ) */
+
+/*
+ * 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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/timing.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/timing.c
new file mode 100644
index 00000000..0a976b80
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/timing.c
@@ -0,0 +1,565 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#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
+#include "mbedtls/debug.h"
+#define mbedtls_printf tls_info
+#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;
+
+#if defined(_WIN32)
+#include
+#include
+
+#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
+ #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
+#else
+ #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
+#endif
+
+#ifndef _TIMEZONE_DEFINED
+struct timezone
+{
+ int tz_minuteswest; /* minutes W of Greenwich */
+ int tz_dsttime; /* type of dst correction */
+};
+#endif
+
+int mbedtls_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+ unsigned __int64 tmpres = 0;
+ FILETIME ft;
+ static int tzflag;
+
+ if (NULL != tv) {
+ GetSystemTimeAsFileTime(&ft);
+
+ tmpres |= ft.dwHighDateTime;
+ tmpres <<= 32;
+ tmpres |= ft.dwLowDateTime;
+
+ tmpres -= DELTA_EPOCH_IN_MICROSECS;
+ tmpres /= 10;
+ tv->tv_sec = (long)(tmpres / 1000000UL);
+ tv->tv_usec = (long)(tmpres % 1000000UL);
+ }
+
+ if (NULL != tz) {
+ if (!tzflag) {
+ _tzset();
+ tzflag++;
+ }
+
+ tz->tz_minuteswest = _timezone / 60;
+ tz->tz_dsttime = _daylight;
+ }
+
+ return 0;
+}
+#else
+#define mbedtls_gettimeofday gettimeofday
+#endif /* defined(_WIN32) */
+
+unsigned long mbedtls_timing_hardclock( void )
+{
+ struct timeval tv_cur;
+
+ if( hardclock_init == 0 )
+ {
+ mbedtls_gettimeofday( &tv_init, NULL );
+ hardclock_init = 1;
+ }
+
+ mbedtls_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;
+
+ mbedtls_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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/x509.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/x509.c
new file mode 100644
index 00000000..62ffca5e
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/x509.c
@@ -0,0 +1,1084 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+/*
+ * 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 *time)
+{
+ int ret = MBEDTLS_ERR_X509_INVALID_DATE;
+
+ CHECK_RANGE( 0, 9999, time->year );
+ CHECK_RANGE( 0, 23, time->hour );
+ CHECK_RANGE( 0, 59, time->min );
+ CHECK_RANGE( 0, 59, time->sec );
+
+ switch( time->mon )
+ {
+ case 1: case 3: case 5: case 7: case 8: case 10: case 12:
+ CHECK_RANGE( 1, 31, time->day );
+ break;
+ case 4: case 6: case 9: case 11:
+ CHECK_RANGE( 1, 30, time->day );
+ break;
+ case 2:
+ CHECK_RANGE( 1, 28 + (time->year % 4 == 0), time->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 *time )
+{
+ 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, &time->year ) );
+ if ( 2 == yearlen )
+ {
+ if ( time->year < 50 )
+ time->year += 100;
+
+ time->year += 1900;
+ }
+
+ CHECK( x509_parse_int( p, 2, &time->mon ) );
+ CHECK( x509_parse_int( p, 2, &time->day ) );
+ CHECK( x509_parse_int( p, 2, &time->hour ) );
+ CHECK( x509_parse_int( p, 2, &time->min ) );
+
+ /*
+ * Parse seconds if present
+ */
+ if ( len >= 2 )
+ {
+ CHECK( x509_parse_int( p, 2, &time->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( time ) );
+
+ return ( 0 );
+}
+
+/*
+ * Time ::= CHOICE {
+ * utcTime UTCTime,
+ * generalTime GeneralizedTime }
+ */
+int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end,
+ mbedtls_x509_time *time )
+{
+ 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, time );
+}
+
+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_SHA1_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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/x509_crt.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/x509_crt.c
new file mode 100644
index 00000000..f21c9889
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/mbedtls/library/x509_crt.c
@@ -0,0 +1,2389 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+/*
+ * 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 =
+{
+ /* Hashes from SHA-1 and above */
+ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) |
+ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_RIPEMD160 ) |
+ 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 );
+ }
+
+ crt->version++;
+
+ if( crt->version > 3 )
+ {
+ mbedtls_x509_crt_free( crt );
+ return( MBEDTLS_ERR_X509_UNKNOWN_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 )
+ return( MBEDTLS_ERR_X509_FILE_IO_ERROR );
+
+ 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;
+
+ 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_PTHREAD)
+ if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 )
+ {
+ closedir( dir );
+ return( ret );
+ }
+#endif
+
+ 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_PTHREAD)
+ if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 )
+ ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
+#endif
+
+#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 )
+ {
+ *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
+ return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED );
+ }
+
+ 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;
+
+ if( profile == NULL )
+ return( MBEDTLS_ERR_X509_BAD_INPUT_DATA );
+
+ *flags = 0;
+
+ 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 )
+ return( ret );
+ }
+ 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 )
+ return( ret );
+ }
+ else
+ {
+ ret = x509_crt_verify_top( crt, trust_ca, ca_crl, profile,
+ pathlen, selfsigned, flags, f_vrfy, p_vrfy );
+ if( ret != 0 )
+ 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/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/iot.mk
new file mode 100644
index 00000000..3b184824
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/iot.mk
@@ -0,0 +1,2 @@
+LIBA_TARGET := libiot_nghttp2.a
+HDR_REFS += src/infra
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2.h
new file mode 100644
index 00000000..8b96d25d
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2.h
@@ -0,0 +1,5363 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_H
+#define NGHTTP2_H
+
+
+#ifdef IOTX_HTTP2_DEBUG
+#define DEBUGBUILD
+#endif
+/* Define WIN32 when build target is Win32 API (borrowed from
+ libcurl) */
+#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
+#define WIN32
+#define ssize_t unsigned int
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#if defined(_MSC_VER) && (_MSC_VER < 1800)
+/* MSVC < 2013 does not have inttypes.h because it is not C99
+ compliant. See compiler macros and version number in
+ https://sourceforge.net/p/predef/wiki/Compilers/ */
+#include
+#else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
+#include
+#endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */
+#include
+#include
+
+#include
+
+#ifdef NGHTTP2_STATICLIB
+#define NGHTTP2_EXTERN
+#elif defined(WIN32__)
+#ifdef BUILDING_NGHTTP2
+#define NGHTTP2_EXTERN __declspec(dllexport)
+#else /* !BUILDING_NGHTTP2 */
+#define NGHTTP2_EXTERN __declspec(dllimport)
+#endif /* !BUILDING_NGHTTP2 */
+#else /* !defined(WIN32) */
+#ifdef BUILDING_NGHTTP2
+#define NGHTTP2_EXTERN __attribute__((visibility("default")))
+#else /* !BUILDING_NGHTTP2 */
+#define NGHTTP2_EXTERN
+#endif /* !BUILDING_NGHTTP2 */
+#endif /* !defined(WIN32) */
+
+/**
+ * @macro
+ *
+ * The protocol version identification string of this library
+ * supports. This identifier is used if HTTP/2 is used over TLS.
+ */
+#define NGHTTP2_PROTO_VERSION_ID "h2"
+/**
+ * @macro
+ *
+ * The length of :macro:`NGHTTP2_PROTO_VERSION_ID`.
+ */
+#define NGHTTP2_PROTO_VERSION_ID_LEN 2
+
+/**
+ * @macro
+ *
+ * The serialized form of ALPN protocol identifier this library
+ * supports. Notice that first byte is the length of following
+ * protocol identifier. This is the same wire format of `TLS ALPN
+ * extension `_. This is useful
+ * to process incoming ALPN tokens in wire format.
+ */
+#define NGHTTP2_PROTO_ALPN "\x2h2"
+
+/**
+ * @macro
+ *
+ * The length of :macro:`NGHTTP2_PROTO_ALPN`.
+ */
+#define NGHTTP2_PROTO_ALPN_LEN (sizeof(NGHTTP2_PROTO_ALPN) - 1)
+
+/**
+ * @macro
+ *
+ * The protocol version identification string of this library
+ * supports. This identifier is used if HTTP/2 is used over cleartext
+ * TCP.
+ */
+#define NGHTTP2_CLEARTEXT_PROTO_VERSION_ID "h2c"
+
+/**
+ * @macro
+ *
+ * The length of :macro:`NGHTTP2_CLEARTEXT_PROTO_VERSION_ID`.
+ */
+#define NGHTTP2_CLEARTEXT_PROTO_VERSION_ID_LEN 3
+
+struct nghttp2_session;
+/**
+ * @struct
+ *
+ * The primary structure to hold the resources needed for a HTTP/2
+ * session. The details of this structure are intentionally hidden
+ * from the public API.
+ */
+typedef struct nghttp2_session nghttp2_session;
+
+/**
+ * @macro
+ *
+ * The age of :type:`nghttp2_info`
+ */
+#define NGHTTP2_VERSION_AGE 1
+
+#ifndef HTTP2_RECV_BUFFER_LENGHT
+#define HTTP2_RECV_BUFFER_LENGHT 16384
+#endif
+/**
+ * @struct
+ *
+ * This struct is what `nghttp2_version()` returns. It holds
+ * information about the particular nghttp2 version.
+ */
+typedef struct {
+ /**
+ * Age of this struct. This instance of nghttp2 sets it to
+ * :macro:`NGHTTP2_VERSION_AGE` but a future version may bump it and
+ * add more struct fields at the bottom
+ */
+ int age;
+ /**
+ * the :macro:`NGHTTP2_VERSION_NUM` number (since age ==1)
+ */
+ int version_num;
+ /**
+ * points to the :macro:`NGHTTP2_VERSION` string (since age ==1)
+ */
+ const char *version_str;
+ /**
+ * points to the :macro:`NGHTTP2_PROTO_VERSION_ID` string this
+ * instance implements (since age ==1)
+ */
+ const char *proto_str;
+ /* -------- the above fields all exist when age == 1 */
+} nghttp2_info;
+
+/**
+ * @macro
+ *
+ * The default weight of stream dependency.
+ */
+#define NGHTTP2_DEFAULT_WEIGHT 16
+
+/**
+ * @macro
+ *
+ * The maximum weight of stream dependency.
+ */
+#define NGHTTP2_MAX_WEIGHT 256
+
+/**
+ * @macro
+ *
+ * The minimum weight of stream dependency.
+ */
+#define NGHTTP2_MIN_WEIGHT 1
+
+/**
+ * @macro
+ *
+ * The maximum window size
+ */
+#define NGHTTP2_MAX_WINDOW_SIZE ((int32_t)((1U << 31) - 1))
+
+/**
+ * @macro
+ *
+ * The initial window size for stream level flow control.
+ */
+#define NGHTTP2_INITIAL_WINDOW_SIZE ((1 << 24) - 1)
+/**
+ * @macro
+ *
+ * The initial window size for connection level flow control.
+ */
+#define NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE ((1 << 24) - 1)
+
+/**
+ * @macro
+ *
+ * The default header table size.
+ */
+#define NGHTTP2_DEFAULT_HEADER_TABLE_SIZE (1 << 12)
+
+/**
+ * @macro
+ *
+ * The client magic string, which is the first 24 bytes byte string of
+ * client connection preface.
+ */
+#define NGHTTP2_CLIENT_MAGIC "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
+
+/**
+ * @macro
+ *
+ * The length of :macro:`NGHTTP2_CLIENT_MAGIC`.
+ */
+#define NGHTTP2_CLIENT_MAGIC_LEN 24
+
+/**
+ * @enum
+ *
+ * Error codes used in this library. The code range is [-999, -500],
+ * inclusive. The following values are defined:
+ */
+typedef enum {
+ /**
+ * Invalid argument passed.
+ */
+ NGHTTP2_ERR_INVALID_ARGUMENT = -501,
+ /**
+ * Out of buffer space.
+ */
+ NGHTTP2_ERR_BUFFER_ERROR = -502,
+ /**
+ * The specified protocol version is not supported.
+ */
+ NGHTTP2_ERR_UNSUPPORTED_VERSION = -503,
+ /**
+ * Used as a return value from :type:`nghttp2_send_callback`,
+ * :type:`nghttp2_recv_callback` and
+ * :type:`nghttp2_send_data_callback` to indicate that the operation
+ * would block.
+ */
+ NGHTTP2_ERR_WOULDBLOCK = -504,
+ /**
+ * General protocol error
+ */
+ NGHTTP2_ERR_PROTO = -505,
+ /**
+ * The frame is invalid.
+ */
+ NGHTTP2_ERR_INVALID_FRAME = -506,
+ /**
+ * The peer performed a shutdown on the connection.
+ */
+ NGHTTP2_ERR_EOF = -507,
+ /**
+ * Used as a return value from
+ * :func:`nghttp2_data_source_read_callback` to indicate that data
+ * transfer is postponed. See
+ * :func:`nghttp2_data_source_read_callback` for details.
+ */
+ NGHTTP2_ERR_DEFERRED = -508,
+ /**
+ * Stream ID has reached the maximum value. Therefore no stream ID
+ * is available.
+ */
+ NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE = -509,
+ /**
+ * The stream is already closed; or the stream ID is invalid.
+ */
+ NGHTTP2_ERR_STREAM_CLOSED = -510,
+ /**
+ * RST_STREAM has been added to the outbound queue. The stream is
+ * in closing state.
+ */
+ NGHTTP2_ERR_STREAM_CLOSING = -511,
+ /**
+ * The transmission is not allowed for this stream (e.g., a frame
+ * with END_STREAM flag set has already sent).
+ */
+ NGHTTP2_ERR_STREAM_SHUT_WR = -512,
+ /**
+ * The stream ID is invalid.
+ */
+ NGHTTP2_ERR_INVALID_STREAM_ID = -513,
+ /**
+ * The state of the stream is not valid (e.g., DATA cannot be sent
+ * to the stream if response HEADERS has not been sent).
+ */
+ NGHTTP2_ERR_INVALID_STREAM_STATE = -514,
+ /**
+ * Another DATA frame has already been deferred.
+ */
+ NGHTTP2_ERR_DEFERRED_DATA_EXIST = -515,
+ /**
+ * Starting new stream is not allowed (e.g., GOAWAY has been sent
+ * and/or received).
+ */
+ NGHTTP2_ERR_START_STREAM_NOT_ALLOWED = -516,
+ /**
+ * GOAWAY has already been sent.
+ */
+ NGHTTP2_ERR_GOAWAY_ALREADY_SENT = -517,
+ /**
+ * The received frame contains the invalid header block (e.g., There
+ * are duplicate header names; or the header names are not encoded
+ * in US-ASCII character set and not lower cased; or the header name
+ * is zero-length string; or the header value contains multiple
+ * in-sequence NUL bytes).
+ */
+ NGHTTP2_ERR_INVALID_HEADER_BLOCK = -518,
+ /**
+ * Indicates that the context is not suitable to perform the
+ * requested operation.
+ */
+ NGHTTP2_ERR_INVALID_STATE = -519,
+ /**
+ * The user callback function failed due to the temporal error.
+ */
+ NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE = -521,
+ /**
+ * The length of the frame is invalid, either too large or too small.
+ */
+ NGHTTP2_ERR_FRAME_SIZE_ERROR = -522,
+ /**
+ * Header block inflate/deflate error.
+ */
+ NGHTTP2_ERR_HEADER_COMP = -523,
+ /**
+ * Flow control error
+ */
+ NGHTTP2_ERR_FLOW_CONTROL = -524,
+ /**
+ * Insufficient buffer size given to function.
+ */
+ NGHTTP2_ERR_INSUFF_BUFSIZE = -525,
+ /**
+ * Callback was paused by the application
+ */
+ NGHTTP2_ERR_PAUSE = -526,
+ /**
+ * There are too many in-flight SETTING frame and no more
+ * transmission of SETTINGS is allowed.
+ */
+ NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS = -527,
+ /**
+ * The server push is disabled.
+ */
+ NGHTTP2_ERR_PUSH_DISABLED = -528,
+ /**
+ * DATA or HEADERS frame for a given stream has been already
+ * submitted and has not been fully processed yet. Application
+ * should wait for the transmission of the previously submitted
+ * frame before submitting another.
+ */
+ NGHTTP2_ERR_DATA_EXIST = -529,
+ /**
+ * The current session is closing due to a connection error or
+ * `nghttp2_session_terminate_session()` is called.
+ */
+ NGHTTP2_ERR_SESSION_CLOSING = -530,
+ /**
+ * Invalid HTTP header field was received and stream is going to be
+ * closed.
+ */
+ NGHTTP2_ERR_HTTP_HEADER = -531,
+ /**
+ * Violation in HTTP messaging rule.
+ */
+ NGHTTP2_ERR_HTTP_MESSAGING = -532,
+ /**
+ * Stream was refused.
+ */
+ NGHTTP2_ERR_REFUSED_STREAM = -533,
+ /**
+ * Unexpected internal error, but recovered.
+ */
+ NGHTTP2_ERR_INTERNAL = -534,
+ /**
+ * Indicates that a processing was canceled.
+ */
+ NGHTTP2_ERR_CANCEL = -535,
+ /**
+ * When a local endpoint expects to receive SETTINGS frame, it
+ * receives an other type of frame.
+ */
+ NGHTTP2_ERR_SETTINGS_EXPECTED = -536,
+ /**
+ * The errors < :enum:`NGHTTP2_ERR_FATAL` mean that the library is
+ * under unexpected condition and processing was terminated (e.g.,
+ * out of memory). If application receives this error code, it must
+ * stop using that :type:`nghttp2_session` object and only allowed
+ * operation for that object is deallocate it using
+ * `nghttp2_session_del()`.
+ */
+ NGHTTP2_ERR_FATAL = -900,
+ /**
+ * Out of memory. This is a fatal error.
+ */
+ NGHTTP2_ERR_NOMEM = -901,
+ /**
+ * The user callback function failed. This is a fatal error.
+ */
+ NGHTTP2_ERR_CALLBACK_FAILURE = -902,
+ /**
+ * Invalid client magic (see :macro:`NGHTTP2_CLIENT_MAGIC`) was
+ * received and further processing is not possible.
+ */
+ NGHTTP2_ERR_BAD_CLIENT_MAGIC = -903,
+ /**
+ * Possible flooding by peer was detected in this HTTP/2 session.
+ * Flooding is measured by how many PING and SETTINGS frames with
+ * ACK flag set are queued for transmission. These frames are
+ * response for the peer initiated frames, and peer can cause memory
+ * exhaustion on server side to send these frames forever and does
+ * not read network.
+ */
+ NGHTTP2_ERR_FLOODED = -904
+} nghttp2_error;
+
+/**
+ * @struct
+ *
+ * The object representing single contiguous buffer.
+ */
+typedef struct {
+ /**
+ * The pointer to the buffer.
+ */
+ uint8_t *base;
+ /**
+ * The length of the buffer.
+ */
+ size_t len;
+} nghttp2_vec;
+
+struct nghttp2_rcbuf;
+
+/**
+ * @struct
+ *
+ * The object representing reference counted buffer. The details of
+ * this structure are intentionally hidden from the public API.
+ */
+typedef struct nghttp2_rcbuf nghttp2_rcbuf;
+
+/**
+ * @function
+ *
+ * Increments the reference count of |rcbuf| by 1.
+ */
+NGHTTP2_EXTERN void nghttp2_rcbuf_incref(nghttp2_rcbuf *rcbuf);
+
+/**
+ * @function
+ *
+ * Decrements the reference count of |rcbuf| by 1. If the reference
+ * count becomes zero, the object pointed by |rcbuf| will be freed.
+ * In this case, application must not use |rcbuf| again.
+ */
+NGHTTP2_EXTERN void nghttp2_rcbuf_decref(nghttp2_rcbuf *rcbuf);
+
+/**
+ * @function
+ *
+ * Returns the underlying buffer managed by |rcbuf|.
+ */
+NGHTTP2_EXTERN nghttp2_vec nghttp2_rcbuf_get_buf(nghttp2_rcbuf *rcbuf);
+
+/**
+ * @function
+ *
+ * Returns nonzero if the underlying buffer is statically allocated,
+ * and 0 otherwise. This can be useful for language bindings that wish
+ * to avoid creating duplicate strings for these buffers.
+ */
+NGHTTP2_EXTERN int nghttp2_rcbuf_is_static(const nghttp2_rcbuf *rcbuf);
+
+/**
+ * @enum
+ *
+ * The flags for header field name/value pair.
+ */
+typedef enum {
+ /**
+ * No flag set.
+ */
+ NGHTTP2_NV_FLAG_NONE = 0,
+ /**
+ * Indicates that this name/value pair must not be indexed ("Literal
+ * Header Field never Indexed" representation must be used in HPACK
+ * encoding). Other implementation calls this bit as "sensitive".
+ */
+ NGHTTP2_NV_FLAG_NO_INDEX = 0x01,
+ /**
+ * This flag is set solely by application. If this flag is set, the
+ * library does not make a copy of header field name. This could
+ * improve performance.
+ */
+ NGHTTP2_NV_FLAG_NO_COPY_NAME = 0x02,
+ /**
+ * This flag is set solely by application. If this flag is set, the
+ * library does not make a copy of header field value. This could
+ * improve performance.
+ */
+ NGHTTP2_NV_FLAG_NO_COPY_VALUE = 0x04
+} nghttp2_nv_flag;
+
+/**
+ * @struct
+ *
+ * The name/value pair, which mainly used to represent header fields.
+ */
+typedef struct {
+ /**
+ * The |name| byte string. If this struct is presented from library
+ * (e.g., :type:`nghttp2_on_frame_recv_callback`), |name| is
+ * guaranteed to be NULL-terminated. For some callbacks
+ * (:type:`nghttp2_before_frame_send_callback`,
+ * :type:`nghttp2_on_frame_send_callback`, and
+ * :type:`nghttp2_on_frame_not_send_callback`), it may not be
+ * NULL-terminated if header field is passed from application with
+ * the flag :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`). When application
+ * is constructing this struct, |name| is not required to be
+ * NULL-terminated.
+ */
+ uint8_t *name;
+ /**
+ * The |value| byte string. If this struct is presented from
+ * library (e.g., :type:`nghttp2_on_frame_recv_callback`), |value|
+ * is guaranteed to be NULL-terminated. For some callbacks
+ * (:type:`nghttp2_before_frame_send_callback`,
+ * :type:`nghttp2_on_frame_send_callback`, and
+ * :type:`nghttp2_on_frame_not_send_callback`), it may not be
+ * NULL-terminated if header field is passed from application with
+ * the flag :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE`). When
+ * application is constructing this struct, |value| is not required
+ * to be NULL-terminated.
+ */
+ uint8_t *value;
+ /**
+ * The length of the |name|, excluding terminating NULL.
+ */
+ size_t namelen;
+ /**
+ * The length of the |value|, excluding terminating NULL.
+ */
+ size_t valuelen;
+ /**
+ * Bitwise OR of one or more of :type:`nghttp2_nv_flag`.
+ */
+ uint8_t flags;
+} nghttp2_nv;
+
+/**
+ * @enum
+ *
+ * The frame types in HTTP/2 specification.
+ */
+typedef enum {
+ /**
+ * The DATA frame.
+ */
+ NGHTTP2_DATA = 0,
+ /**
+ * The HEADERS frame.
+ */
+ NGHTTP2_HEADERS = 0x01,
+ /**
+ * The PRIORITY frame.
+ */
+ NGHTTP2_PRIORITY = 0x02,
+ /**
+ * The RST_STREAM frame.
+ */
+ NGHTTP2_RST_STREAM = 0x03,
+ /**
+ * The SETTINGS frame.
+ */
+ NGHTTP2_SETTINGS = 0x04,
+ /**
+ * The PUSH_PROMISE frame.
+ */
+ NGHTTP2_PUSH_PROMISE = 0x05,
+ /**
+ * The PING frame.
+ */
+ NGHTTP2_PING = 0x06,
+ /**
+ * The GOAWAY frame.
+ */
+ NGHTTP2_GOAWAY = 0x07,
+ /**
+ * The WINDOW_UPDATE frame.
+ */
+ NGHTTP2_WINDOW_UPDATE = 0x08,
+ /**
+ * The CONTINUATION frame. This frame type won't be passed to any
+ * callbacks because the library processes this frame type and its
+ * preceding HEADERS/PUSH_PROMISE as a single frame.
+ */
+ NGHTTP2_CONTINUATION = 0x09,
+ /**
+ * The ALTSVC frame, which is defined in `RFC 7383
+ * `_.
+ */
+ NGHTTP2_ALTSVC = 0x0a
+} nghttp2_frame_type;
+
+/**
+ * @enum
+ *
+ * The flags for HTTP/2 frames. This enum defines all flags for all
+ * frames.
+ */
+typedef enum {
+ /**
+ * No flag set.
+ */
+ NGHTTP2_FLAG_NONE = 0,
+ /**
+ * The END_STREAM flag.
+ */
+ NGHTTP2_FLAG_END_STREAM = 0x01,
+ /**
+ * The END_HEADERS flag.
+ */
+ NGHTTP2_FLAG_END_HEADERS = 0x04,
+ /**
+ * The ACK flag.
+ */
+ NGHTTP2_FLAG_ACK = 0x01,
+ /**
+ * The PADDED flag.
+ */
+ NGHTTP2_FLAG_PADDED = 0x08,
+ /**
+ * The PRIORITY flag.
+ */
+ NGHTTP2_FLAG_PRIORITY = 0x20
+} nghttp2_flag;
+
+/**
+ * @enum
+ * The SETTINGS ID.
+ */
+typedef enum {
+ /**
+ * SETTINGS_HEADER_TABLE_SIZE
+ */
+ NGHTTP2_SETTINGS_HEADER_TABLE_SIZE = 0x01,
+ /**
+ * SETTINGS_ENABLE_PUSH
+ */
+ NGHTTP2_SETTINGS_ENABLE_PUSH = 0x02,
+ /**
+ * SETTINGS_MAX_CONCURRENT_STREAMS
+ */
+ NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS = 0x03,
+ /**
+ * SETTINGS_INITIAL_WINDOW_SIZE
+ */
+ NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE = 0x04,
+ /**
+ * SETTINGS_MAX_FRAME_SIZE
+ */
+ NGHTTP2_SETTINGS_MAX_FRAME_SIZE = 0x05,
+ /**
+ * SETTINGS_MAX_HEADER_LIST_SIZE
+ */
+ NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 0x06
+} nghttp2_settings_id;
+/* Note: If we add SETTINGS, update the capacity of
+ NGHTTP2_INBOUND_NUM_IV as well */
+
+/**
+ * @macro
+ *
+ * .. warning::
+ *
+ * Deprecated. The initial max concurrent streams is 0xffffffffu.
+ *
+ * Default maximum number of incoming concurrent streams. Use
+ * `nghttp2_submit_settings()` with
+ * :enum:`NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS` to change the
+ * maximum number of incoming concurrent streams.
+ *
+ * .. note::
+ *
+ * The maximum number of outgoing concurrent streams is 100 by
+ * default.
+ */
+#define NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS ((1U << 31) - 1)
+
+/**
+ * @enum
+ * The status codes for the RST_STREAM and GOAWAY frames.
+ */
+typedef enum {
+ /**
+ * No errors.
+ */
+ NGHTTP2_NO_ERROR = 0x00,
+ /**
+ * PROTOCOL_ERROR
+ */
+ NGHTTP2_PROTOCOL_ERROR = 0x01,
+ /**
+ * INTERNAL_ERROR
+ */
+ NGHTTP2_INTERNAL_ERROR = 0x02,
+ /**
+ * FLOW_CONTROL_ERROR
+ */
+ NGHTTP2_FLOW_CONTROL_ERROR = 0x03,
+ /**
+ * SETTINGS_TIMEOUT
+ */
+ NGHTTP2_SETTINGS_TIMEOUT = 0x04,
+ /**
+ * STREAM_CLOSED
+ */
+ NGHTTP2_STREAM_CLOSED = 0x05,
+ /**
+ * FRAME_SIZE_ERROR
+ */
+ NGHTTP2_FRAME_SIZE_ERROR = 0x06,
+ /**
+ * REFUSED_STREAM
+ */
+ NGHTTP2_REFUSED_STREAM = 0x07,
+ /**
+ * CANCEL
+ */
+ NGHTTP2_CANCEL = 0x08,
+ /**
+ * COMPRESSION_ERROR
+ */
+ NGHTTP2_COMPRESSION_ERROR = 0x09,
+ /**
+ * CONNECT_ERROR
+ */
+ NGHTTP2_CONNECT_ERROR = 0x0a,
+ /**
+ * ENHANCE_YOUR_CALM
+ */
+ NGHTTP2_ENHANCE_YOUR_CALM = 0x0b,
+ /**
+ * INADEQUATE_SECURITY
+ */
+ NGHTTP2_INADEQUATE_SECURITY = 0x0c,
+ /**
+ * HTTP_1_1_REQUIRED
+ */
+ NGHTTP2_HTTP_1_1_REQUIRED = 0x0d
+} nghttp2_error_code;
+
+/**
+ * @struct
+ * The frame header.
+ */
+typedef struct {
+ /**
+ * The length field of this frame, excluding frame header.
+ */
+ size_t length;
+ /**
+ * The stream identifier (aka, stream ID)
+ */
+ int32_t stream_id;
+ /**
+ * The type of this frame. See `nghttp2_frame_type`.
+ */
+ uint8_t type;
+ /**
+ * The flags.
+ */
+ uint8_t flags;
+ /**
+ * Reserved bit in frame header. Currently, this is always set to 0
+ * and application should not expect something useful in here.
+ */
+ uint8_t reserved;
+} nghttp2_frame_hd;
+
+/**
+ * @union
+ *
+ * This union represents the some kind of data source passed to
+ * :type:`nghttp2_data_source_read_callback`.
+ */
+typedef struct {
+ /**
+ * The integer field, suitable for a file descriptor.
+ */
+ int fd;
+ /**
+ * data length.
+ */
+ int len;
+ /**
+ * The pointer to an arbitrary object.
+ */
+ void *ptr;
+} nghttp2_data_source;
+
+/**
+ * @enum
+ *
+ * The flags used to set in |data_flags| output parameter in
+ * :type:`nghttp2_data_source_read_callback`.
+ */
+typedef enum {
+ /**
+ * No flag set.
+ */
+ NGHTTP2_DATA_FLAG_NONE = 0,
+ /**
+ * Indicates EOF was sensed.
+ */
+ NGHTTP2_DATA_FLAG_EOF = 0x01,
+ /**
+ * Indicates that END_STREAM flag must not be set even if
+ * NGHTTP2_DATA_FLAG_EOF is set. Usually this flag is used to send
+ * trailer fields with `nghttp2_submit_request()` or
+ * `nghttp2_submit_response()`.
+ */
+ NGHTTP2_DATA_FLAG_NO_END_STREAM = 0x02,
+ /**
+ * Indicates that application will send complete DATA frame in
+ * :type:`nghttp2_send_data_callback`.
+ */
+ NGHTTP2_DATA_FLAG_NO_COPY = 0x04
+} nghttp2_data_flag;
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when the library wants to read data from
+ * the |source|. The read data is sent in the stream |stream_id|.
+ * The implementation of this function must read at most |length|
+ * bytes of data from |source| (or possibly other places) and store
+ * them in |buf| and return number of data stored in |buf|. If EOF is
+ * reached, set :enum:`NGHTTP2_DATA_FLAG_EOF` flag in |*data_flags|.
+ *
+ * Sometime it is desirable to avoid copying data into |buf| and let
+ * application to send data directly. To achieve this, set
+ * :enum:`NGHTTP2_DATA_FLAG_NO_COPY` to |*data_flags| (and possibly
+ * other flags, just like when we do copy), and return the number of
+ * bytes to send without copying data into |buf|. The library, seeing
+ * :enum:`NGHTTP2_DATA_FLAG_NO_COPY`, will invoke
+ * :type:`nghttp2_send_data_callback`. The application must send
+ * complete DATA frame in that callback.
+ *
+ * If this callback is set by `nghttp2_submit_request()`,
+ * `nghttp2_submit_response()` or `nghttp2_submit_headers()` and
+ * `nghttp2_submit_data()` with flag parameter
+ * :enum:`NGHTTP2_FLAG_END_STREAM` set, and
+ * :enum:`NGHTTP2_DATA_FLAG_EOF` flag is set to |*data_flags|, DATA
+ * frame will have END_STREAM flag set. Usually, this is expected
+ * behaviour and all are fine. One exception is send trailer fields.
+ * You cannot send trailer fields after sending frame with END_STREAM
+ * set. To avoid this problem, one can set
+ * :enum:`NGHTTP2_DATA_FLAG_NO_END_STREAM` along with
+ * :enum:`NGHTTP2_DATA_FLAG_EOF` to signal the library not to set
+ * END_STREAM in DATA frame. Then application can use
+ * `nghttp2_submit_trailer()` to send trailer fields.
+ * `nghttp2_submit_trailer()` can be called inside this callback.
+ *
+ * If the application wants to postpone DATA frames (e.g.,
+ * asynchronous I/O, or reading data blocks for long time), it is
+ * achieved by returning :enum:`NGHTTP2_ERR_DEFERRED` without reading
+ * any data in this invocation. The library removes DATA frame from
+ * the outgoing queue temporarily. To move back deferred DATA frame
+ * to outgoing queue, call `nghttp2_session_resume_data()`.
+ *
+ * By default, |length| is limited to 16KiB at maximum. If peer
+ * allows larger frames, application can enlarge transmission buffer
+ * size. See :type:`nghttp2_data_source_read_length_callback` for
+ * more details.
+ *
+ * If the application just wants to return from
+ * `nghttp2_session_send()` or `nghttp2_session_mem_send()` without
+ * sending anything, return :enum:`NGHTTP2_ERR_PAUSE`.
+ *
+ * In case of error, there are 2 choices. Returning
+ * :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close the stream
+ * by issuing RST_STREAM with :enum:`NGHTTP2_INTERNAL_ERROR`. If a
+ * different error code is desirable, use
+ * `nghttp2_submit_rst_stream()` with a desired error code and then
+ * return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. Returning
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will signal the entire session
+ * failure.
+ */
+typedef ssize_t (*nghttp2_data_source_read_callback)(
+ nghttp2_session *session, int32_t stream_id, uint8_t *buf, size_t length,
+ uint32_t *data_flags, nghttp2_data_source *source, void *user_data);
+
+/**
+ * @struct
+ *
+ * This struct represents the data source and the way to read a chunk
+ * of data from it.
+ */
+typedef struct {
+ /**
+ * The data source.
+ */
+ nghttp2_data_source source;
+ /**
+ * The callback function to read a chunk of data from the |source|.
+ */
+ nghttp2_data_source_read_callback read_callback;
+} nghttp2_data_provider;
+
+/**
+ * @struct
+ *
+ * The DATA frame. The received data is delivered via
+ * :type:`nghttp2_on_data_chunk_recv_callback`.
+ */
+typedef struct {
+ nghttp2_frame_hd hd;
+ /**
+ * The length of the padding in this frame. This includes PAD_HIGH
+ * and PAD_LOW.
+ */
+ size_t padlen;
+} nghttp2_data;
+
+/**
+ * @enum
+ *
+ * The category of HEADERS, which indicates the role of the frame. In
+ * HTTP/2 spec, request, response, push response and other arbitrary
+ * headers (e.g., trailer fields) are all called just HEADERS. To
+ * give the application the role of incoming HEADERS frame, we define
+ * several categories.
+ */
+typedef enum {
+ /**
+ * The HEADERS frame is opening new stream, which is analogous to
+ * SYN_STREAM in SPDY.
+ */
+ NGHTTP2_HCAT_REQUEST = 0,
+ /**
+ * The HEADERS frame is the first response headers, which is
+ * analogous to SYN_REPLY in SPDY.
+ */
+ NGHTTP2_HCAT_RESPONSE = 1,
+ /**
+ * The HEADERS frame is the first headers sent against reserved
+ * stream.
+ */
+ NGHTTP2_HCAT_PUSH_RESPONSE = 2,
+ /**
+ * The HEADERS frame which does not apply for the above categories,
+ * which is analogous to HEADERS in SPDY. If non-final response
+ * (e.g., status 1xx) is used, final response HEADERS frame will be
+ * categorized here.
+ */
+ NGHTTP2_HCAT_HEADERS = 3
+} nghttp2_headers_category;
+
+/**
+ * @struct
+ *
+ * The structure to specify stream dependency.
+ */
+typedef struct {
+ /**
+ * The stream ID of the stream to depend on. Specifying 0 makes
+ * stream not depend any other stream.
+ */
+ int32_t stream_id;
+ /**
+ * The weight of this dependency.
+ */
+ int32_t weight;
+ /**
+ * nonzero means exclusive dependency
+ */
+ uint8_t exclusive;
+} nghttp2_priority_spec;
+
+/**
+ * @struct
+ *
+ * The HEADERS frame. It has the following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The length of the padding in this frame. This includes PAD_HIGH
+ * and PAD_LOW.
+ */
+ size_t padlen;
+ /**
+ * The priority specification
+ */
+ nghttp2_priority_spec pri_spec;
+ /**
+ * The name/value pairs.
+ */
+ nghttp2_nv *nva;
+ /**
+ * The number of name/value pairs in |nva|.
+ */
+ size_t nvlen;
+ /**
+ * The category of this HEADERS frame.
+ */
+ nghttp2_headers_category cat;
+} nghttp2_headers;
+
+/**
+ * @struct
+ *
+ * The PRIORITY frame. It has the following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The priority specification.
+ */
+ nghttp2_priority_spec pri_spec;
+} nghttp2_priority;
+
+/**
+ * @struct
+ *
+ * The RST_STREAM frame. It has the following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The error code. See :type:`nghttp2_error_code`.
+ */
+ uint32_t error_code;
+} nghttp2_rst_stream;
+
+/**
+ * @struct
+ *
+ * The SETTINGS ID/Value pair. It has the following members:
+ */
+typedef struct {
+ /**
+ * The SETTINGS ID. See :type:`nghttp2_settings_id`.
+ */
+ int32_t settings_id;
+ /**
+ * The value of this entry.
+ */
+ uint32_t value;
+} nghttp2_settings_entry;
+
+/**
+ * @struct
+ *
+ * The SETTINGS frame. It has the following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The number of SETTINGS ID/Value pairs in |iv|.
+ */
+ size_t niv;
+ /**
+ * The pointer to the array of SETTINGS ID/Value pair.
+ */
+ nghttp2_settings_entry *iv;
+} nghttp2_settings;
+
+/**
+ * @struct
+ *
+ * The PUSH_PROMISE frame. It has the following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The length of the padding in this frame. This includes PAD_HIGH
+ * and PAD_LOW.
+ */
+ size_t padlen;
+ /**
+ * The name/value pairs.
+ */
+ nghttp2_nv *nva;
+ /**
+ * The number of name/value pairs in |nva|.
+ */
+ size_t nvlen;
+ /**
+ * The promised stream ID
+ */
+ int32_t promised_stream_id;
+ /**
+ * Reserved bit. Currently this is always set to 0 and application
+ * should not expect something useful in here.
+ */
+ uint8_t reserved;
+} nghttp2_push_promise;
+
+/**
+ * @struct
+ *
+ * The PING frame. It has the following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The opaque data
+ */
+ uint8_t opaque_data[8];
+} nghttp2_ping;
+
+/**
+ * @struct
+ *
+ * The GOAWAY frame. It has the following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The last stream stream ID.
+ */
+ int32_t last_stream_id;
+ /**
+ * The error code. See :type:`nghttp2_error_code`.
+ */
+ uint32_t error_code;
+ /**
+ * The additional debug data
+ */
+ uint8_t *opaque_data;
+ /**
+ * The length of |opaque_data| member.
+ */
+ size_t opaque_data_len;
+ /**
+ * Reserved bit. Currently this is always set to 0 and application
+ * should not expect something useful in here.
+ */
+ uint8_t reserved;
+} nghttp2_goaway;
+
+/**
+ * @struct
+ *
+ * The WINDOW_UPDATE frame. It has the following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The window size increment.
+ */
+ int32_t window_size_increment;
+ /**
+ * Reserved bit. Currently this is always set to 0 and application
+ * should not expect something useful in here.
+ */
+ uint8_t reserved;
+} nghttp2_window_update;
+
+/**
+ * @struct
+ *
+ * The extension frame. It has following members:
+ */
+typedef struct {
+ /**
+ * The frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The pointer to extension payload. The exact pointer type is
+ * determined by hd.type.
+ *
+ * Currently, no extension is supported. This is a place holder for
+ * the future extensions.
+ */
+ void *payload;
+} nghttp2_extension;
+
+/**
+ * @union
+ *
+ * This union includes all frames to pass them to various function
+ * calls as nghttp2_frame type. The CONTINUATION frame is omitted
+ * from here because the library deals with it internally.
+ */
+typedef union {
+ /**
+ * The frame header, which is convenient to inspect frame header.
+ */
+ nghttp2_frame_hd hd;
+ /**
+ * The DATA frame.
+ */
+ nghttp2_data data;
+ /**
+ * The HEADERS frame.
+ */
+ nghttp2_headers headers;
+ /**
+ * The PRIORITY frame.
+ */
+ nghttp2_priority priority;
+ /**
+ * The RST_STREAM frame.
+ */
+ nghttp2_rst_stream rst_stream;
+ /**
+ * The SETTINGS frame.
+ */
+ nghttp2_settings settings;
+ /**
+ * The PUSH_PROMISE frame.
+ */
+ nghttp2_push_promise push_promise;
+ /**
+ * The PING frame.
+ */
+ nghttp2_ping ping;
+ /**
+ * The GOAWAY frame.
+ */
+ nghttp2_goaway goaway;
+ /**
+ * The WINDOW_UPDATE frame.
+ */
+ nghttp2_window_update window_update;
+ /**
+ * The extension frame.
+ */
+ nghttp2_extension ext;
+} nghttp2_frame;
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when |session| wants to send data to the
+ * remote peer. The implementation of this function must send at most
+ * |length| bytes of data stored in |data|. The |flags| is currently
+ * not used and always 0. It must return the number of bytes sent if
+ * it succeeds. If it cannot send any single byte without blocking,
+ * it must return :enum:`NGHTTP2_ERR_WOULDBLOCK`. For other errors,
+ * it must return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. The
+ * |user_data| pointer is the third argument passed in to the call to
+ * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
+ *
+ * This callback is required if the application uses
+ * `nghttp2_session_send()` to send data to the remote endpoint. If
+ * the application uses solely `nghttp2_session_mem_send()` instead,
+ * this callback function is unnecessary.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_send_callback()`.
+ *
+ * .. note::
+ *
+ * The |length| may be very small. If that is the case, and
+ * application disables Nagle algorithm (``TCP_NODELAY``), then just
+ * writing |data| to the network stack leads to very small packet,
+ * and it is very inefficient. An application should be responsible
+ * to buffer up small chunks of data as necessary to avoid this
+ * situation.
+ */
+typedef ssize_t (*nghttp2_send_callback)(nghttp2_session *session,
+ const uint8_t *data, size_t length,
+ int flags, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when :enum:`NGHTTP2_DATA_FLAG_NO_COPY` is
+ * used in :type:`nghttp2_data_source_read_callback` to send complete
+ * DATA frame.
+ *
+ * The |frame| is a DATA frame to send. The |framehd| is the
+ * serialized frame header (9 bytes). The |length| is the length of
+ * application data to send (this does not include padding). The
+ * |source| is the same pointer passed to
+ * :type:`nghttp2_data_source_read_callback`.
+ *
+ * The application first must send frame header |framehd| of length 9
+ * bytes. If ``frame->data.padlen > 0``, send 1 byte of value
+ * ``frame->data.padlen - 1``. Then send exactly |length| bytes of
+ * application data. Finally, if ``frame->data.padlen > 1``, send
+ * ``frame->data.padlen - 1`` bytes of zero as padding.
+ *
+ * The application has to send complete DATA frame in this callback.
+ * If all data were written successfully, return 0.
+ *
+ * If it cannot send any data at all, just return
+ * :enum:`NGHTTP2_ERR_WOULDBLOCK`; the library will call this callback
+ * with the same parameters later (It is recommended to send complete
+ * DATA frame at once in this function to deal with error; if partial
+ * frame data has already sent, it is impossible to send another data
+ * in that state, and all we can do is tear down connection). When
+ * data is fully processed, but application wants to make
+ * `nghttp2_session_mem_send()` or `nghttp2_session_send()` return
+ * immediately without processing next frames, return
+ * :enum:`NGHTTP2_ERR_PAUSE`. If application decided to reset this
+ * stream, return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`, then
+ * the library will send RST_STREAM with INTERNAL_ERROR as error code.
+ * The application can also return
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`, which will result in
+ * connection closure. Returning any other value is treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned.
+ */
+typedef int (*nghttp2_send_data_callback)(nghttp2_session *session,
+ nghttp2_frame *frame,
+ const uint8_t *framehd, size_t length,
+ nghttp2_data_source *source,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when |session| wants to receive data from
+ * the remote peer. The implementation of this function must read at
+ * most |length| bytes of data and store it in |buf|. The |flags| is
+ * currently not used and always 0. It must return the number of
+ * bytes written in |buf| if it succeeds. If it cannot read any
+ * single byte without blocking, it must return
+ * :enum:`NGHTTP2_ERR_WOULDBLOCK`. If it gets EOF before it reads any
+ * single byte, it must return :enum:`NGHTTP2_ERR_EOF`. For other
+ * errors, it must return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ * Returning 0 is treated as :enum:`NGHTTP2_ERR_WOULDBLOCK`. The
+ * |user_data| pointer is the third argument passed in to the call to
+ * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
+ *
+ * This callback is required if the application uses
+ * `nghttp2_session_recv()` to receive data from the remote endpoint.
+ * If the application uses solely `nghttp2_session_mem_recv()`
+ * instead, this callback function is unnecessary.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_recv_callback()`.
+ */
+typedef ssize_t (*nghttp2_recv_callback)(nghttp2_session *session, uint8_t *buf,
+ size_t length, int flags,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked by `nghttp2_session_recv()` and
+ * `nghttp2_session_mem_recv()` when a frame is received. The
+ * |user_data| pointer is the third argument passed in to the call to
+ * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
+ *
+ * If frame is HEADERS or PUSH_PROMISE, the ``nva`` and ``nvlen``
+ * member of their data structure are always ``NULL`` and 0
+ * respectively. The header name/value pairs are emitted via
+ * :type:`nghttp2_on_header_callback`.
+ *
+ * For HEADERS, PUSH_PROMISE and DATA frames, this callback may be
+ * called after stream is closed (see
+ * :type:`nghttp2_on_stream_close_callback`). The application should
+ * check that stream is still alive using its own stream management or
+ * :func:`nghttp2_session_get_stream_user_data()`.
+ *
+ * Only HEADERS and DATA frame can signal the end of incoming data.
+ * If ``frame->hd.flags & NGHTTP2_FLAG_END_STREAM`` is nonzero, the
+ * |frame| is the last frame from the remote peer in this stream.
+ *
+ * This callback won't be called for CONTINUATION frames.
+ * HEADERS/PUSH_PROMISE + CONTINUATIONs are treated as single frame.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * If nonzero value is returned, it is treated as fatal error and
+ * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_frame_recv_callback()`.
+ */
+typedef int (*nghttp2_on_frame_recv_callback)(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked by `nghttp2_session_recv()` and
+ * `nghttp2_session_mem_recv()` when an invalid non-DATA frame is
+ * received. The error is indicated by the |lib_error_code|, which is
+ * one of the values defined in :type:`nghttp2_error`. When this
+ * callback function is invoked, the library automatically submits
+ * either RST_STREAM or GOAWAY frame. The |user_data| pointer is the
+ * third argument passed in to the call to
+ * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
+ *
+ * If frame is HEADERS or PUSH_PROMISE, the ``nva`` and ``nvlen``
+ * member of their data structure are always ``NULL`` and 0
+ * respectively.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * If nonzero is returned, it is treated as fatal error and
+ * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_invalid_frame_recv_callback()`.
+ */
+typedef int (*nghttp2_on_invalid_frame_recv_callback)(
+ nghttp2_session *session, const nghttp2_frame *frame, int lib_error_code,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when a chunk of data in DATA frame is
+ * received. The |stream_id| is the stream ID this DATA frame belongs
+ * to. The |flags| is the flags of DATA frame which this data chunk
+ * is contained. ``(flags & NGHTTP2_FLAG_END_STREAM) != 0`` does not
+ * necessarily mean this chunk of data is the last one in the stream.
+ * You should use :type:`nghttp2_on_frame_recv_callback` to know all
+ * data frames are received. The |user_data| pointer is the third
+ * argument passed in to the call to `nghttp2_session_client_new()` or
+ * `nghttp2_session_server_new()`.
+ *
+ * If the application uses `nghttp2_session_mem_recv()`, it can return
+ * :enum:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()`
+ * return without processing further input bytes. The memory by
+ * pointed by the |data| is retained until
+ * `nghttp2_session_mem_recv()` or `nghttp2_session_recv()` is called.
+ * The application must retain the input bytes which was used to
+ * produce the |data| parameter, because it may refer to the memory
+ * region included in the input bytes.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * If nonzero is returned, it is treated as fatal error, and
+ * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_data_chunk_recv_callback()`.
+ */
+typedef int (*nghttp2_on_data_chunk_recv_callback)(nghttp2_session *session,
+ uint8_t flags,
+ int32_t stream_id,
+ const uint8_t *data,
+ size_t len, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked just before the non-DATA frame |frame| is
+ * sent. The |user_data| pointer is the third argument passed in to
+ * the call to `nghttp2_session_client_new()` or
+ * `nghttp2_session_server_new()`.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * It can also return :enum:`NGHTTP2_ERR_CANCEL` to cancel the
+ * transmission of the given frame.
+ *
+ * If there is a fatal error while executing this callback, the
+ * implementation should return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`,
+ * which makes `nghttp2_session_send()` and
+ * `nghttp2_session_mem_send()` functions immediately return
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * If the other value is returned, it is treated as if
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned. But the
+ * implementation should not rely on this since the library may define
+ * new return value to extend its capability.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_before_frame_send_callback()`.
+ */
+typedef int (*nghttp2_before_frame_send_callback)(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked after the frame |frame| is sent. The
+ * |user_data| pointer is the third argument passed in to the call to
+ * `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * If nonzero is returned, it is treated as fatal error and
+ * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_frame_send_callback()`.
+ */
+typedef int (*nghttp2_on_frame_send_callback)(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked after the non-DATA frame |frame| is not
+ * sent because of the error. The error is indicated by the
+ * |lib_error_code|, which is one of the values defined in
+ * :type:`nghttp2_error`. The |user_data| pointer is the third
+ * argument passed in to the call to `nghttp2_session_client_new()` or
+ * `nghttp2_session_server_new()`.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * If nonzero is returned, it is treated as fatal error and
+ * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * `nghttp2_session_get_stream_user_data()` can be used to get
+ * associated data.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_frame_not_send_callback()`.
+ */
+typedef int (*nghttp2_on_frame_not_send_callback)(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ int lib_error_code,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when the stream |stream_id| is closed.
+ * The reason of closure is indicated by the |error_code|. The
+ * |error_code| is usually one of :enum:`nghttp2_error_code`, but that
+ * is not guaranteed. The stream_user_data, which was specified in
+ * `nghttp2_submit_request()` or `nghttp2_submit_headers()`, is still
+ * available in this function. The |user_data| pointer is the third
+ * argument passed in to the call to `nghttp2_session_client_new()` or
+ * `nghttp2_session_server_new()`.
+ *
+ * This function is also called for a stream in reserved state.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * If nonzero is returned, it is treated as fatal error and
+ * `nghttp2_session_recv()`, `nghttp2_session_mem_recv()`,
+ * `nghttp2_session_send()`, and `nghttp2_session_mem_send()`
+ * functions immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_stream_close_callback()`.
+ */
+typedef int (*nghttp2_on_stream_close_callback)(nghttp2_session *session,
+ int32_t stream_id,
+ uint32_t error_code,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when the reception of header block in
+ * HEADERS or PUSH_PROMISE is started. Each header name/value pair
+ * will be emitted by :type:`nghttp2_on_header_callback`.
+ *
+ * The ``frame->hd.flags`` may not have
+ * :enum:`NGHTTP2_FLAG_END_HEADERS` flag set, which indicates that one
+ * or more CONTINUATION frames are involved. But the application does
+ * not need to care about that because the header name/value pairs are
+ * emitted transparently regardless of CONTINUATION frames.
+ *
+ * The server applications probably create an object to store
+ * information about new stream if ``frame->hd.type ==
+ * NGHTTP2_HEADERS`` and ``frame->headers.cat ==
+ * NGHTTP2_HCAT_REQUEST``. If |session| is configured as server side,
+ * ``frame->headers.cat`` is either ``NGHTTP2_HCAT_REQUEST``
+ * containing request headers or ``NGHTTP2_HCAT_HEADERS`` containing
+ * trailer fields and never get PUSH_PROMISE in this callback.
+ *
+ * For the client applications, ``frame->hd.type`` is either
+ * ``NGHTTP2_HEADERS`` or ``NGHTTP2_PUSH_PROMISE``. In case of
+ * ``NGHTTP2_HEADERS``, ``frame->headers.cat ==
+ * NGHTTP2_HCAT_RESPONSE`` means that it is the first response
+ * headers, but it may be non-final response which is indicated by 1xx
+ * status code. In this case, there may be zero or more HEADERS frame
+ * with ``frame->headers.cat == NGHTTP2_HCAT_HEADERS`` which has
+ * non-final response code and finally client gets exactly one HEADERS
+ * frame with ``frame->headers.cat == NGHTTP2_HCAT_HEADERS``
+ * containing final response headers (non-1xx status code). The
+ * trailer fields also has ``frame->headers.cat ==
+ * NGHTTP2_HCAT_HEADERS`` which does not contain any status code.
+ *
+ * Returning :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close
+ * the stream (promised stream if frame is PUSH_PROMISE) by issuing
+ * RST_STREAM with :enum:`NGHTTP2_INTERNAL_ERROR`. In this case,
+ * :type:`nghttp2_on_header_callback` and
+ * :type:`nghttp2_on_frame_recv_callback` will not be invoked. If a
+ * different error code is desirable, use
+ * `nghttp2_submit_rst_stream()` with a desired error code and then
+ * return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. Again, use
+ * ``frame->push_promise.promised_stream_id`` as stream_id parameter
+ * in `nghttp2_submit_rst_stream()` if frame is PUSH_PROMISE.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * It can return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` to
+ * reset the stream (promised stream if frame is PUSH_PROMISE). For
+ * critical errors, it must return
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the other value is
+ * returned, it is treated as if :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`
+ * is returned. If :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned,
+ * `nghttp2_session_mem_recv()` function will immediately return
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_begin_headers_callback()`.
+ */
+typedef int (*nghttp2_on_begin_headers_callback)(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when a header name/value pair is received
+ * for the |frame|. The |name| of length |namelen| is header name.
+ * The |value| of length |valuelen| is header value. The |flags| is
+ * bitwise OR of one or more of :type:`nghttp2_nv_flag`.
+ *
+ * If :enum:`NGHTTP2_NV_FLAG_NO_INDEX` is set in |flags|, the receiver
+ * must not index this name/value pair when forwarding it to the next
+ * hop. More specifically, "Literal Header Field never Indexed"
+ * representation must be used in HPACK encoding.
+ *
+ * When this callback is invoked, ``frame->hd.type`` is either
+ * :enum:`NGHTTP2_HEADERS` or :enum:`NGHTTP2_PUSH_PROMISE`. After all
+ * header name/value pairs are processed with this callback, and no
+ * error has been detected, :type:`nghttp2_on_frame_recv_callback`
+ * will be invoked. If there is an error in decompression,
+ * :type:`nghttp2_on_frame_recv_callback` for the |frame| will not be
+ * invoked.
+ *
+ * Both |name| and |value| are guaranteed to be NULL-terminated. The
+ * |namelen| and |valuelen| do not include terminal NULL. If
+ * `nghttp2_option_set_no_http_messaging()` is used with nonzero
+ * value, NULL character may be included in |name| or |value| before
+ * terminating NULL.
+ *
+ * Please note that unless `nghttp2_option_set_no_http_messaging()` is
+ * used, nghttp2 library does perform validation against the |name|
+ * and the |value| using `nghttp2_check_header_name()` and
+ * `nghttp2_check_header_value()`. In addition to this, nghttp2
+ * performs validation based on HTTP Messaging rule, which is briefly
+ * explained in :ref:`http-messaging` section.
+ *
+ * If the application uses `nghttp2_session_mem_recv()`, it can return
+ * :enum:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()`
+ * return without processing further input bytes. The memory pointed
+ * by |frame|, |name| and |value| parameters are retained until
+ * `nghttp2_session_mem_recv()` or `nghttp2_session_recv()` is called.
+ * The application must retain the input bytes which was used to
+ * produce these parameters, because it may refer to the memory region
+ * included in the input bytes.
+ *
+ * Returning :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close
+ * the stream (promised stream if frame is PUSH_PROMISE) by issuing
+ * RST_STREAM with :enum:`NGHTTP2_INTERNAL_ERROR`. In this case,
+ * :type:`nghttp2_on_header_callback` and
+ * :type:`nghttp2_on_frame_recv_callback` will not be invoked. If a
+ * different error code is desirable, use
+ * `nghttp2_submit_rst_stream()` with a desired error code and then
+ * return :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. Again, use
+ * ``frame->push_promise.promised_stream_id`` as stream_id parameter
+ * in `nghttp2_submit_rst_stream()` if frame is PUSH_PROMISE.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * It may return :enum:`NGHTTP2_ERR_PAUSE` or
+ * :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. For other critical
+ * failures, it must return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If
+ * the other nonzero value is returned, it is treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned,
+ * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_header_callback()`.
+ *
+ * .. warning::
+ *
+ * Application should properly limit the total buffer size to store
+ * incoming header fields. Without it, peer may send large number
+ * of header fields or large header fields to cause out of memory in
+ * local endpoint. Due to how HPACK works, peer can do this
+ * effectively without using much memory on their own.
+ */
+typedef int (*nghttp2_on_header_callback)(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ const uint8_t *name, size_t namelen,
+ const uint8_t *value, size_t valuelen,
+ uint8_t flags, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when a header name/value pair is received
+ * for the |frame|. The |name| is header name. The |value| is header
+ * value. The |flags| is bitwise OR of one or more of
+ * :type:`nghttp2_nv_flag`.
+ *
+ * This callback behaves like :type:`nghttp2_on_header_callback`,
+ * except that |name| and |value| are stored in reference counted
+ * buffer. If application wishes to keep these references without
+ * copying them, use `nghttp2_rcbuf_incref()` to increment their
+ * reference count. It is the application's responsibility to call
+ * `nghttp2_rcbuf_decref()` if they called `nghttp2_rcbuf_incref()` so
+ * as not to leak memory. If the |session| is created by
+ * `nghttp2_session_server_new3()` or `nghttp2_session_client_new3()`,
+ * the function to free memory is the one belongs to the mem
+ * parameter. As long as this free function alives, |name| and
+ * |value| can live after |session| was destroyed.
+ */
+typedef int (*nghttp2_on_header_callback2)(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ nghttp2_rcbuf *name,
+ nghttp2_rcbuf *value, uint8_t flags,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when a invalid header name/value pair is
+ * received for the |frame|.
+ *
+ * The parameter and behaviour are similar to
+ * :type:`nghttp2_on_header_callback`. The difference is that this
+ * callback is only invoked when a invalid header name/value pair is
+ * received which is treated as stream error if this callback is not
+ * set. Only invalid regular header field are passed to this
+ * callback. In other words, invalid pseudo header field is not
+ * passed to this callback. Also header fields which includes upper
+ * cased latter are also treated as error without passing them to this
+ * callback.
+ *
+ * This callback is only considered if HTTP messaging validation is
+ * turned on (which is on by default, see
+ * `nghttp2_option_set_no_http_messaging()`).
+ *
+ * With this callback, application inspects the incoming invalid
+ * field, and it also can reset stream from this callback by returning
+ * :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. By default, the
+ * error code is :enum:`NGHTTP2_PROTOCOL_ERROR`. To change the error
+ * code, call `nghttp2_submit_rst_stream()` with the error code of
+ * choice in addition to returning
+ * :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`.
+ *
+ * If 0 is returned, the header field is ignored, and the stream is
+ * not reset.
+ */
+typedef int (*nghttp2_on_invalid_header_callback)(
+ nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name,
+ size_t namelen, const uint8_t *value, size_t valuelen, uint8_t flags,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when a invalid header name/value pair is
+ * received for the |frame|.
+ *
+ * The parameter and behaviour are similar to
+ * :type:`nghttp2_on_header_callback2`. The difference is that this
+ * callback is only invoked when a invalid header name/value pair is
+ * received which is silently ignored if this callback is not set.
+ * Only invalid regular header field are passed to this callback. In
+ * other words, invalid pseudo header field is not passed to this
+ * callback. Also header fields which includes upper cased latter are
+ * also treated as error without passing them to this callback.
+ *
+ * This callback is only considered if HTTP messaging validation is
+ * turned on (which is on by default, see
+ * `nghttp2_option_set_no_http_messaging()`).
+ *
+ * With this callback, application inspects the incoming invalid
+ * field, and it also can reset stream from this callback by returning
+ * :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`. By default, the
+ * error code is :enum:`NGHTTP2_INTERNAL_ERROR`. To change the error
+ * code, call `nghttp2_submit_rst_stream()` with the error code of
+ * choice in addition to returning
+ * :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`.
+ */
+typedef int (*nghttp2_on_invalid_header_callback2)(
+ nghttp2_session *session, const nghttp2_frame *frame, nghttp2_rcbuf *name,
+ nghttp2_rcbuf *value, uint8_t flags, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when the library asks application how
+ * many padding bytes are required for the transmission of the
+ * |frame|. The application must choose the total length of payload
+ * including padded bytes in range [frame->hd.length, max_payloadlen],
+ * inclusive. Choosing number not in this range will be treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. Returning
+ * ``frame->hd.length`` means no padding is added. Returning
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will make
+ * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_select_padding_callback()`.
+ */
+typedef ssize_t (*nghttp2_select_padding_callback)(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ size_t max_payloadlen,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when library wants to get max length of
+ * data to send data to the remote peer. The implementation of this
+ * function should return a value in the following range. [1,
+ * min(|session_remote_window_size|, |stream_remote_window_size|,
+ * |remote_max_frame_size|)]. If a value greater than this range is
+ * returned than the max allow value will be used. Returning a value
+ * smaller than this range is treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. The |frame_type| is provided
+ * for future extensibility and identifies the type of frame (see
+ * :type:`nghttp2_frame_type`) for which to get the length for.
+ * Currently supported frame types are: :enum:`NGHTTP2_DATA`.
+ *
+ * This callback can be used to control the length in bytes for which
+ * :type:`nghttp2_data_source_read_callback` is allowed to send to the
+ * remote endpoint. This callback is optional. Returning
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` will signal the entire session
+ * failure.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_data_source_read_length_callback()`.
+ */
+typedef ssize_t (*nghttp2_data_source_read_length_callback)(
+ nghttp2_session *session, uint8_t frame_type, int32_t stream_id,
+ int32_t session_remote_window_size, int32_t stream_remote_window_size,
+ uint32_t remote_max_frame_size, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when a frame header is received. The
+ * |hd| points to received frame header.
+ *
+ * Unlike :type:`nghttp2_on_frame_recv_callback`, this callback will
+ * also be called when frame header of CONTINUATION frame is received.
+ *
+ * If both :type:`nghttp2_on_begin_frame_callback` and
+ * :type:`nghttp2_on_begin_headers_callback` are set and HEADERS or
+ * PUSH_PROMISE is received, :type:`nghttp2_on_begin_frame_callback`
+ * will be called first.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ * If nonzero value is returned, it is treated as fatal error and
+ * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ *
+ * To set this callback to :type:`nghttp2_session_callbacks`, use
+ * `nghttp2_session_callbacks_set_on_begin_frame_callback()`.
+ */
+typedef int (*nghttp2_on_begin_frame_callback)(nghttp2_session *session,
+ const nghttp2_frame_hd *hd,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when chunk of extension frame payload is
+ * received. The |hd| points to frame header. The received
+ * chunk is |data| of length |len|.
+ *
+ * The implementation of this function must return 0 if it succeeds.
+ *
+ * To abort processing this extension frame, return
+ * :enum:`NGHTTP2_ERR_CANCEL`.
+ *
+ * If fatal error occurred, application should return
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case,
+ * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the
+ * other values are returned, currently they are treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+typedef int (*nghttp2_on_extension_chunk_recv_callback)(
+ nghttp2_session *session, const nghttp2_frame_hd *hd, const uint8_t *data,
+ size_t len, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when library asks the application to
+ * unpack extension payload from its wire format. The extension
+ * payload has been passed to the application using
+ * :type:`nghttp2_on_extension_chunk_recv_callback`. The frame header
+ * is already unpacked by the library and provided as |hd|.
+ *
+ * To receive extension frames, the application must tell desired
+ * extension frame type to the library using
+ * `nghttp2_option_set_user_recv_extension_type()`.
+ *
+ * The implementation of this function may store the pointer to the
+ * created object as a result of unpacking in |*payload|, and returns
+ * 0. The pointer stored in |*payload| is opaque to the library, and
+ * the library does not own its pointer. |*payload| is initialized as
+ * ``NULL``. The |*payload| is available as ``frame->ext.payload`` in
+ * :type:`nghttp2_on_frame_recv_callback`. Therefore if application
+ * can free that memory inside :type:`nghttp2_on_frame_recv_callback`
+ * callback. Of course, application has a liberty not ot use
+ * |*payload|, and do its own mechanism to process extension frames.
+ *
+ * To abort processing this extension frame, return
+ * :enum:`NGHTTP2_ERR_CANCEL`.
+ *
+ * If fatal error occurred, application should return
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case,
+ * `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the
+ * other values are returned, currently they are treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+typedef int (*nghttp2_unpack_extension_callback)(nghttp2_session *session,
+ void **payload,
+ const nghttp2_frame_hd *hd,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when library asks the application to pack
+ * extension payload in its wire format. The frame header will be
+ * packed by library. Application must pack payload only.
+ * ``frame->ext.payload`` is the object passed to
+ * `nghttp2_submit_extension()` as payload parameter. Application
+ * must pack extension payload to the |buf| of its capacity |len|
+ * bytes. The |len| is at least 16KiB.
+ *
+ * The implementation of this function should return the number of
+ * bytes written into |buf| when it succeeds.
+ *
+ * To abort processing this extension frame, return
+ * :enum:`NGHTTP2_ERR_CANCEL`, and
+ * :type:`nghttp2_on_frame_not_send_callback` will be invoked.
+ *
+ * If fatal error occurred, application should return
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case,
+ * `nghttp2_session_send()` and `nghttp2_session_mem_send()` functions
+ * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the
+ * other values are returned, currently they are treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If the return value is
+ * strictly larger than |len|, it is treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
+ */
+typedef ssize_t (*nghttp2_pack_extension_callback)(nghttp2_session *session,
+ uint8_t *buf, size_t len,
+ const nghttp2_frame *frame,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when library provides the error message
+ * intended for human consumption. This callback is solely for
+ * debugging purpose. The |msg| is typically NULL-terminated string
+ * of length |len|. |len| does not include the sentinel NULL
+ * character.
+ *
+ * This function is deprecated. The new application should use
+ * :type:`nghttp2_error_callback2`.
+ *
+ * The format of error message may change between nghttp2 library
+ * versions. The application should not depend on the particular
+ * format.
+ *
+ * Normally, application should return 0 from this callback. If fatal
+ * error occurred while doing something in this callback, application
+ * should return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case,
+ * library will return immediately with return value
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. Currently, if nonzero value
+ * is returned from this callback, they are treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`, but application should not
+ * rely on this details.
+ */
+typedef int (*nghttp2_error_callback)(nghttp2_session *session, const char *msg,
+ size_t len, void *user_data);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when library provides the error code, and
+ * message. This callback is solely for debugging purpose.
+ * |lib_error_code| is one of error code defined in
+ * :enum:`nghttp2_error`. The |msg| is typically NULL-terminated
+ * string of length |len|, and intended for human consumption. |len|
+ * does not include the sentinel NULL character.
+ *
+ * The format of error message may change between nghttp2 library
+ * versions. The application should not depend on the particular
+ * format.
+ *
+ * Normally, application should return 0 from this callback. If fatal
+ * error occurred while doing something in this callback, application
+ * should return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case,
+ * library will return immediately with return value
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. Currently, if nonzero value
+ * is returned from this callback, they are treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`, but application should not
+ * rely on this details.
+ */
+typedef int (*nghttp2_error_callback2)(nghttp2_session *session,
+ int lib_error_code, const char *msg,
+ size_t len, void *user_data);
+
+struct nghttp2_session_callbacks;
+
+/**
+ * @struct
+ *
+ * Callback functions for :type:`nghttp2_session`. The details of
+ * this structure are intentionally hidden from the public API.
+ */
+typedef struct nghttp2_session_callbacks nghttp2_session_callbacks;
+
+/**
+ * @function
+ *
+ * Initializes |*callbacks_ptr| with NULL values.
+ *
+ * The initialized object can be used when initializing multiple
+ * :type:`nghttp2_session` objects.
+ *
+ * When the application finished using this object, it can use
+ * `nghttp2_session_callbacks_del()` to free its memory.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_callbacks_new(nghttp2_session_callbacks **callbacks_ptr);
+
+/**
+ * @function
+ *
+ * Frees any resources allocated for |callbacks|. If |callbacks| is
+ * ``NULL``, this function does nothing.
+ */
+NGHTTP2_EXTERN void
+nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when a session wants to send data to
+ * the remote peer. This callback is not necessary if the application
+ * uses solely `nghttp2_session_mem_send()` to serialize data to
+ * transmit.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_send_callback(
+ nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when the a session wants to receive
+ * data from the remote peer. This callback is not necessary if the
+ * application uses solely `nghttp2_session_mem_recv()` to process
+ * received data.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_recv_callback(
+ nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked by `nghttp2_session_recv()` and
+ * `nghttp2_session_mem_recv()` when a frame is received.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_frame_recv_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_frame_recv_callback on_frame_recv_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked by `nghttp2_session_recv()` and
+ * `nghttp2_session_mem_recv()` when an invalid non-DATA frame is
+ * received.
+ */
+NGHTTP2_EXTERN void
+nghttp2_session_callbacks_set_on_invalid_frame_recv_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when a chunk of data in DATA frame
+ * is received.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked before a non-DATA frame is sent.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_before_frame_send_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_before_frame_send_callback before_frame_send_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked after a frame is sent.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_frame_send_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_frame_send_callback on_frame_send_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when a non-DATA frame is not sent
+ * because of an error.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_frame_not_send_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_frame_not_send_callback on_frame_not_send_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when the stream is closed.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_stream_close_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_stream_close_callback on_stream_close_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when the reception of header block
+ * in HEADERS or PUSH_PROMISE is started.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_begin_headers_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_begin_headers_callback on_begin_headers_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when a header name/value pair is
+ * received. If both
+ * `nghttp2_session_callbacks_set_on_header_callback()` and
+ * `nghttp2_session_callbacks_set_on_header_callback2()` are used to
+ * set callbacks, the latter has the precedence.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_header_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_header_callback on_header_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when a header name/value pair is
+ * received.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_header_callback2(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_header_callback2 on_header_callback2);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when a invalid header name/value
+ * pair is received. If both
+ * `nghttp2_session_callbacks_set_on_invalid_header_callback()` and
+ * `nghttp2_session_callbacks_set_on_invalid_header_callback2()` are
+ * used to set callbacks, the latter takes the precedence.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_invalid_header_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_invalid_header_callback on_invalid_header_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when a invalid header name/value
+ * pair is received.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_invalid_header_callback2(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_invalid_header_callback2 on_invalid_header_callback2);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when the library asks application
+ * how many padding bytes are required for the transmission of the
+ * given frame.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_select_padding_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_select_padding_callback select_padding_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function determine the length allowed in
+ * :type:`nghttp2_data_source_read_callback`.
+ */
+NGHTTP2_EXTERN void
+nghttp2_session_callbacks_set_data_source_read_length_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_data_source_read_length_callback data_source_read_length_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when a frame header is received.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_begin_frame_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_begin_frame_callback on_begin_frame_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when
+ * :enum:`NGHTTP2_DATA_FLAG_NO_COPY` is used in
+ * :type:`nghttp2_data_source_read_callback` to avoid data copy.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_send_data_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_send_data_callback send_data_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when the library asks the
+ * application to pack extension frame payload in wire format.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_pack_extension_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_pack_extension_callback pack_extension_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when the library asks the
+ * application to unpack extension frame payload from wire format.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_unpack_extension_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_unpack_extension_callback unpack_extension_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when chunk of extension frame
+ * payload is received.
+ */
+NGHTTP2_EXTERN void
+nghttp2_session_callbacks_set_on_extension_chunk_recv_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when library tells error message to
+ * the application.
+ *
+ * This function is deprecated. The new application should use
+ * `nghttp2_session_callbacks_set_error_callback2()`.
+ *
+ * If both :type:`nghttp2_error_callback` and
+ * :type:`nghttp2_error_callback2` are set, the latter takes
+ * precedence.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_error_callback(
+ nghttp2_session_callbacks *cbs, nghttp2_error_callback error_callback);
+
+/**
+ * @function
+ *
+ * Sets callback function invoked when library tells error code, and
+ * message to the application.
+ *
+ * If both :type:`nghttp2_error_callback` and
+ * :type:`nghttp2_error_callback2` are set, the latter takes
+ * precedence.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_error_callback2(
+ nghttp2_session_callbacks *cbs, nghttp2_error_callback2 error_callback2);
+
+/**
+ * @functypedef
+ *
+ * Custom memory allocator to replace malloc(). The |mem_user_data|
+ * is the mem_user_data member of :type:`nghttp2_mem` structure.
+ */
+typedef void *(*nghttp2_malloc)(size_t size, void *mem_user_data);
+
+/**
+ * @functypedef
+ *
+ * Custom memory allocator to replace free(). The |mem_user_data| is
+ * the mem_user_data member of :type:`nghttp2_mem` structure.
+ */
+typedef void (*nghttp2_free)(void *ptr, void *mem_user_data);
+
+/**
+ * @functypedef
+ *
+ * Custom memory allocator to replace calloc(). The |mem_user_data|
+ * is the mem_user_data member of :type:`nghttp2_mem` structure.
+ */
+typedef void *(*nghttp2_calloc)(size_t nmemb, size_t size, void *mem_user_data);
+
+/**
+ * @functypedef
+ *
+ * Custom memory allocator to replace realloc(). The |mem_user_data|
+ * is the mem_user_data member of :type:`nghttp2_mem` structure.
+ */
+typedef void *(*nghttp2_realloc)(void *ptr, size_t size, void *mem_user_data);
+
+/**
+ * @struct
+ *
+ * Custom memory allocator functions and user defined pointer. The
+ * |mem_user_data| member is passed to each allocator function. This
+ * can be used, for example, to achieve per-session memory pool.
+ *
+ * In the following example code, ``my_malloc``, ``my_free``,
+ * ``my_calloc`` and ``my_realloc`` are the replacement of the
+ * standard allocators ``malloc``, ``free``, ``calloc`` and
+ * ``realloc`` respectively::
+ *
+ * void *my_malloc_cb(size_t size, void *mem_user_data) {
+ * return my_malloc(size);
+ * }
+ *
+ * void my_free_cb(void *ptr, void *mem_user_data) { my_free(ptr); }
+ *
+ * void *my_calloc_cb(size_t nmemb, size_t size, void *mem_user_data) {
+ * return my_calloc(nmemb, size);
+ * }
+ *
+ * void *my_realloc_cb(void *ptr, size_t size, void *mem_user_data) {
+ * return my_realloc(ptr, size);
+ * }
+ *
+ * void session_new() {
+ * nghttp2_session *session;
+ * nghttp2_session_callbacks *callbacks;
+ * nghttp2_mem mem = {NULL, my_malloc_cb, my_free_cb, my_calloc_cb,
+ * my_realloc_cb};
+ *
+ * ...
+ *
+ * nghttp2_session_client_new3(&session, callbacks, NULL, NULL, &mem);
+ *
+ * ...
+ * }
+ */
+typedef struct {
+ /**
+ * An arbitrary user supplied data. This is passed to each
+ * allocator function.
+ */
+ void *mem_user_data;
+ /**
+ * Custom allocator function to replace malloc().
+ */
+ nghttp2_malloc malloc;
+ /**
+ * Custom allocator function to replace free().
+ */
+ nghttp2_free free;
+ /**
+ * Custom allocator function to replace calloc().
+ */
+ nghttp2_calloc calloc;
+ /**
+ * Custom allocator function to replace realloc().
+ */
+ nghttp2_realloc realloc;
+} nghttp2_mem;
+
+struct nghttp2_option;
+
+/**
+ * @struct
+ *
+ * Configuration options for :type:`nghttp2_session`. The details of
+ * this structure are intentionally hidden from the public API.
+ */
+typedef struct nghttp2_option nghttp2_option;
+
+/**
+ * @function
+ *
+ * Initializes |*option_ptr| with default values.
+ *
+ * When the application finished using this object, it can use
+ * `nghttp2_option_del()` to free its memory.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_option_new(nghttp2_option **option_ptr);
+
+/**
+ * @function
+ *
+ * Frees any resources allocated for |option|. If |option| is
+ * ``NULL``, this function does nothing.
+ */
+NGHTTP2_EXTERN void nghttp2_option_del(nghttp2_option *option);
+
+/**
+ * @function
+ *
+ * This option prevents the library from sending WINDOW_UPDATE for a
+ * connection automatically. If this option is set to nonzero, the
+ * library won't send WINDOW_UPDATE for DATA until application calls
+ * `nghttp2_session_consume()` to indicate the consumed amount of
+ * data. Don't use `nghttp2_submit_window_update()` for this purpose.
+ * By default, this option is set to zero.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_no_auto_window_update(nghttp2_option *option, int val);
+
+/**
+ * @function
+ *
+ * This option sets the SETTINGS_MAX_CONCURRENT_STREAMS value of
+ * remote endpoint as if it is received in SETTINGS frame. Without
+ * specifying this option, before the local endpoint receives
+ * SETTINGS_MAX_CONCURRENT_STREAMS in SETTINGS frame from remote
+ * endpoint, SETTINGS_MAX_CONCURRENT_STREAMS is unlimited. This may
+ * cause problem if local endpoint submits lots of requests initially
+ * and sending them at once to the remote peer may lead to the
+ * rejection of some requests. Specifying this option to the sensible
+ * value, say 100, may avoid this kind of issue. This value will be
+ * overwritten if the local endpoint receives
+ * SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option,
+ uint32_t val);
+
+/**
+ * @function
+ *
+ * By default, nghttp2 library, if configured as server, requires
+ * first 24 bytes of client magic byte string (MAGIC). In most cases,
+ * this will simplify the implementation of server. But sometimes
+ * server may want to detect the application protocol based on first
+ * few bytes on clear text communication.
+ *
+ * If this option is used with nonzero |val|, nghttp2 library does not
+ * handle MAGIC. It still checks following SETTINGS frame. This
+ * means that applications should deal with MAGIC by themselves.
+ *
+ * If this option is not used or used with zero value, if MAGIC does
+ * not match :macro:`NGHTTP2_CLIENT_MAGIC`, `nghttp2_session_recv()`
+ * and `nghttp2_session_mem_recv()` will return error
+ * :enum:`NGHTTP2_ERR_BAD_CLIENT_MAGIC`, which is fatal error.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_no_recv_client_magic(nghttp2_option *option, int val);
+
+/**
+ * @function
+ *
+ * By default, nghttp2 library enforces subset of HTTP Messaging rules
+ * described in `HTTP/2 specification, section 8
+ * `_. See
+ * :ref:`http-messaging` section for details. For those applications
+ * who use nghttp2 library as non-HTTP use, give nonzero to |val| to
+ * disable this enforcement. Please note that disabling this feature
+ * does not change the fundamental client and server model of HTTP.
+ * That is, even if the validation is disabled, only client can send
+ * requests.
+ */
+NGHTTP2_EXTERN void nghttp2_option_set_no_http_messaging(nghttp2_option *option,
+ int val);
+
+/**
+ * @function
+ *
+ * RFC 7540 does not enforce any limit on the number of incoming
+ * reserved streams (in RFC 7540 terms, streams in reserved (remote)
+ * state). This only affects client side, since only server can push
+ * streams. Malicious server can push arbitrary number of streams,
+ * and make client's memory exhausted. This option can set the
+ * maximum number of such incoming streams to avoid possible memory
+ * exhaustion. If this option is set, and pushed streams are
+ * automatically closed on reception, without calling user provided
+ * callback, if they exceed the given limit. The default value is
+ * 200. If session is configured as server side, this option has no
+ * effect. Server can control the number of streams to push.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_max_reserved_remote_streams(nghttp2_option *option,
+ uint32_t val);
+
+/**
+ * @function
+ *
+ * Sets extension frame type the application is willing to handle with
+ * user defined callbacks (see
+ * :type:`nghttp2_on_extension_chunk_recv_callback` and
+ * :type:`nghttp2_unpack_extension_callback`). The |type| is
+ * extension frame type, and must be strictly greater than 0x9.
+ * Otherwise, this function does nothing. The application can call
+ * this function multiple times to set more than one frame type to
+ * receive. The application does not have to call this function if it
+ * just sends extension frames.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_user_recv_extension_type(nghttp2_option *option,
+ uint8_t type);
+
+/**
+ * @function
+ *
+ * Sets extension frame type the application is willing to receive
+ * using builtin handler. The |type| is the extension frame type to
+ * receive, and must be strictly greater than 0x9. Otherwise, this
+ * function does nothing. The application can call this function
+ * multiple times to set more than one frame type to receive. The
+ * application does not have to call this function if it just sends
+ * extension frames.
+ *
+ * If same frame type is passed to both
+ * `nghttp2_option_set_builtin_recv_extension_type()` and
+ * `nghttp2_option_set_user_recv_extension_type()`, the latter takes
+ * precedence.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_builtin_recv_extension_type(nghttp2_option *option,
+ uint8_t type);
+
+/**
+ * @function
+ *
+ * This option prevents the library from sending PING frame with ACK
+ * flag set automatically when PING frame without ACK flag set is
+ * received. If this option is set to nonzero, the library won't send
+ * PING frame with ACK flag set in the response for incoming PING
+ * frame. The application can send PING frame with ACK flag set using
+ * `nghttp2_submit_ping()` with :enum:`NGHTTP2_FLAG_ACK` as flags
+ * parameter.
+ */
+NGHTTP2_EXTERN void nghttp2_option_set_no_auto_ping_ack(nghttp2_option *option,
+ int val);
+
+/**
+ * @function
+ *
+ * This option sets the maximum length of header block (a set of
+ * header fields per one HEADERS frame) to send. The length of a
+ * given set of header fields is calculated using
+ * `nghttp2_hd_deflate_bound()`. The default value is 64KiB. If
+ * application attempts to send header fields larger than this limit,
+ * the transmission of the frame fails with error code
+ * :enum:`NGHTTP2_ERR_FRAME_SIZE_ERROR`.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_max_send_header_block_length(nghttp2_option *option,
+ size_t val);
+
+/**
+ * @function
+ *
+ * This option sets the maximum dynamic table size for deflating
+ * header fields. The default value is 4KiB. In HTTP/2, receiver of
+ * deflated header block can specify maximum dynamic table size. The
+ * actual maximum size is the minimum of the size receiver specified
+ * and this option value.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_max_deflate_dynamic_table_size(nghttp2_option *option,
+ size_t val);
+
+/**
+ * @function
+ *
+ * This option prevents the library from retaining closed streams to
+ * maintain the priority tree. If this option is set to nonzero,
+ * applications can discard closed stream completely to save memory.
+ */
+NGHTTP2_EXTERN void nghttp2_option_set_no_closed_streams(nghttp2_option *option,
+ int val);
+
+/**
+ * @function
+ *
+ * Initializes |*session_ptr| for client use. The all members of
+ * |callbacks| are copied to |*session_ptr|. Therefore |*session_ptr|
+ * does not store |callbacks|. The |user_data| is an arbitrary user
+ * supplied data, which will be passed to the callback functions.
+ *
+ * The :type:`nghttp2_send_callback` must be specified. If the
+ * application code uses `nghttp2_session_recv()`, the
+ * :type:`nghttp2_recv_callback` must be specified. The other members
+ * of |callbacks| can be ``NULL``.
+ *
+ * If this function fails, |*session_ptr| is left untouched.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_client_new(nghttp2_session **session_ptr,
+ const nghttp2_session_callbacks *callbacks,
+ void *user_data);
+
+/**
+ * @function
+ *
+ * Initializes |*session_ptr| for server use. The all members of
+ * |callbacks| are copied to |*session_ptr|. Therefore |*session_ptr|
+ * does not store |callbacks|. The |user_data| is an arbitrary user
+ * supplied data, which will be passed to the callback functions.
+ *
+ * The :type:`nghttp2_send_callback` must be specified. If the
+ * application code uses `nghttp2_session_recv()`, the
+ * :type:`nghttp2_recv_callback` must be specified. The other members
+ * of |callbacks| can be ``NULL``.
+ *
+ * If this function fails, |*session_ptr| is left untouched.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_server_new(nghttp2_session **session_ptr,
+ const nghttp2_session_callbacks *callbacks,
+ void *user_data);
+
+/**
+ * @function
+ *
+ * Like `nghttp2_session_client_new()`, but with additional options
+ * specified in the |option|.
+ *
+ * The |option| can be ``NULL`` and the call is equivalent to
+ * `nghttp2_session_client_new()`.
+ *
+ * This function does not take ownership |option|. The application is
+ * responsible for freeing |option| if it finishes using the object.
+ *
+ * The library code does not refer to |option| after this function
+ * returns.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_client_new2(nghttp2_session **session_ptr,
+ const nghttp2_session_callbacks *callbacks,
+ void *user_data, const nghttp2_option *option);
+
+/**
+ * @function
+ *
+ * Like `nghttp2_session_server_new()`, but with additional options
+ * specified in the |option|.
+ *
+ * The |option| can be ``NULL`` and the call is equivalent to
+ * `nghttp2_session_server_new()`.
+ *
+ * This function does not take ownership |option|. The application is
+ * responsible for freeing |option| if it finishes using the object.
+ *
+ * The library code does not refer to |option| after this function
+ * returns.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_server_new2(nghttp2_session **session_ptr,
+ const nghttp2_session_callbacks *callbacks,
+ void *user_data, const nghttp2_option *option);
+
+/**
+ * @function
+ *
+ * Like `nghttp2_session_client_new2()`, but with additional custom
+ * memory allocator specified in the |mem|.
+ *
+ * The |mem| can be ``NULL`` and the call is equivalent to
+ * `nghttp2_session_client_new2()`.
+ *
+ * This function does not take ownership |mem|. The application is
+ * responsible for freeing |mem|.
+ *
+ * The library code does not refer to |mem| pointer after this
+ * function returns, so the application can safely free it.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_session_client_new3(
+ nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks,
+ void *user_data, const nghttp2_option *option, nghttp2_mem *mem);
+
+/**
+ * @function
+ *
+ * Like `nghttp2_session_server_new2()`, but with additional custom
+ * memory allocator specified in the |mem|.
+ *
+ * The |mem| can be ``NULL`` and the call is equivalent to
+ * `nghttp2_session_server_new2()`.
+ *
+ * This function does not take ownership |mem|. The application is
+ * responsible for freeing |mem|.
+ *
+ * The library code does not refer to |mem| pointer after this
+ * function returns, so the application can safely free it.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_session_server_new3(
+ nghttp2_session **session_ptr, const nghttp2_session_callbacks *callbacks,
+ void *user_data, const nghttp2_option *option, nghttp2_mem *mem);
+
+/**
+ * @function
+ *
+ * Frees any resources allocated for |session|. If |session| is
+ * ``NULL``, this function does nothing.
+ */
+NGHTTP2_EXTERN void nghttp2_session_del(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Sends pending frames to the remote peer.
+ *
+ * This function retrieves the highest prioritized frame from the
+ * outbound queue and sends it to the remote peer. It does this as
+ * many as possible until the user callback
+ * :type:`nghttp2_send_callback` returns
+ * :enum:`NGHTTP2_ERR_WOULDBLOCK` or the outbound queue becomes empty.
+ * This function calls several callback functions which are passed
+ * when initializing the |session|. Here is the simple time chart
+ * which tells when each callback is invoked:
+ *
+ * 1. Get the next frame to send from outbound queue.
+ *
+ * 2. Prepare transmission of the frame.
+ *
+ * 3. If the control frame cannot be sent because some preconditions
+ * are not met (e.g., request HEADERS cannot be sent after GOAWAY),
+ * :type:`nghttp2_on_frame_not_send_callback` is invoked. Abort
+ * the following steps.
+ *
+ * 4. If the frame is HEADERS, PUSH_PROMISE or DATA,
+ * :type:`nghttp2_select_padding_callback` is invoked.
+ *
+ * 5. If the frame is request HEADERS, the stream is opened here.
+ *
+ * 6. :type:`nghttp2_before_frame_send_callback` is invoked.
+ *
+ * 7. If :enum:`NGHTTP2_ERR_CANCEL` is returned from
+ * :type:`nghttp2_before_frame_send_callback`, the current frame
+ * transmission is canceled, and
+ * :type:`nghttp2_on_frame_not_send_callback` is invoked. Abort
+ * the following steps.
+ *
+ * 8. :type:`nghttp2_send_callback` is invoked one or more times to
+ * send the frame.
+ *
+ * 9. :type:`nghttp2_on_frame_send_callback` is invoked.
+ *
+ * 10. If the transmission of the frame triggers closure of the
+ * stream, the stream is closed and
+ * :type:`nghttp2_on_stream_close_callback` is invoked.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`
+ * The callback function failed.
+ */
+NGHTTP2_EXTERN int nghttp2_session_send(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the serialized data to send.
+ *
+ * This function behaves like `nghttp2_session_send()` except that it
+ * does not use :type:`nghttp2_send_callback` to transmit data.
+ * Instead, it assigns the pointer to the serialized data to the
+ * |*data_ptr| and returns its length. The other callbacks are called
+ * in the same way as they are in `nghttp2_session_send()`.
+ *
+ * If no data is available to send, this function returns 0.
+ *
+ * This function may not return all serialized data in one invocation.
+ * To get all data, call this function repeatedly until it returns 0
+ * or one of negative error codes.
+ *
+ * The assigned |*data_ptr| is valid until the next call of
+ * `nghttp2_session_mem_send()` or `nghttp2_session_send()`.
+ *
+ * The caller must send all data before sending the next chunk of
+ * data.
+ *
+ * This function returns the length of the data pointed by the
+ * |*data_ptr| if it succeeds, or one of the following negative error
+ * codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ *
+ * .. note::
+ *
+ * This function may produce very small byte string. If that is the
+ * case, and application disables Nagle algorithm (``TCP_NODELAY``),
+ * then writing this small chunk leads to very small packet, and it
+ * is very inefficient. An application should be responsible to
+ * buffer up small chunks of data as necessary to avoid this
+ * situation.
+ */
+NGHTTP2_EXTERN ssize_t nghttp2_session_mem_send(nghttp2_session *session,
+ const uint8_t **data_ptr);
+
+/**
+ * @function
+ *
+ * Receives frames from the remote peer.
+ *
+ * This function receives as many frames as possible until the user
+ * callback :type:`nghttp2_recv_callback` returns
+ * :enum:`NGHTTP2_ERR_WOULDBLOCK`. This function calls several
+ * callback functions which are passed when initializing the
+ * |session|. Here is the simple time chart which tells when each
+ * callback is invoked:
+ *
+ * 1. :type:`nghttp2_recv_callback` is invoked one or more times to
+ * receive frame header.
+ *
+ * 2. When frame header is received,
+ * :type:`nghttp2_on_begin_frame_callback` is invoked.
+ *
+ * 3. If the frame is DATA frame:
+ *
+ * 1. :type:`nghttp2_recv_callback` is invoked to receive DATA
+ * payload. For each chunk of data,
+ * :type:`nghttp2_on_data_chunk_recv_callback` is invoked.
+ *
+ * 2. If one DATA frame is completely received,
+ * :type:`nghttp2_on_frame_recv_callback` is invoked. If the
+ * reception of the frame triggers the closure of the stream,
+ * :type:`nghttp2_on_stream_close_callback` is invoked.
+ *
+ * 4. If the frame is the control frame:
+ *
+ * 1. :type:`nghttp2_recv_callback` is invoked one or more times to
+ * receive whole frame.
+ *
+ * 2. If the received frame is valid, then following actions are
+ * taken. If the frame is either HEADERS or PUSH_PROMISE,
+ * :type:`nghttp2_on_begin_headers_callback` is invoked. Then
+ * :type:`nghttp2_on_header_callback` is invoked for each header
+ * name/value pair. For invalid header field,
+ * :type:`nghttp2_on_invalid_header_callback` is called. After
+ * all name/value pairs are emitted successfully,
+ * :type:`nghttp2_on_frame_recv_callback` is invoked. For other
+ * frames, :type:`nghttp2_on_frame_recv_callback` is invoked.
+ * If the reception of the frame triggers the closure of the
+ * stream, :type:`nghttp2_on_stream_close_callback` is invoked.
+ *
+ * 3. If the received frame is unpacked but is interpreted as
+ * invalid, :type:`nghttp2_on_invalid_frame_recv_callback` is
+ * invoked.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_EOF`
+ * The remote peer did shutdown on the connection.
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`
+ * The callback function failed.
+ * :enum:`NGHTTP2_ERR_BAD_CLIENT_MAGIC`
+ * Invalid client magic was detected. This error only returns
+ * when |session| was configured as server and
+ * `nghttp2_option_set_no_recv_client_magic()` is not used with
+ * nonzero value.
+ * :enum:`NGHTTP2_ERR_FLOODED`
+ * Flooding was detected in this HTTP/2 session, and it must be
+ * closed. This is most likely caused by misbehaviour of peer.
+ */
+NGHTTP2_EXTERN int nghttp2_session_recv(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Processes data |in| as an input from the remote endpoint. The
+ * |inlen| indicates the number of bytes in the |in|.
+ *
+ * This function behaves like `nghttp2_session_recv()` except that it
+ * does not use :type:`nghttp2_recv_callback` to receive data; the
+ * |in| is the only data for the invocation of this function. If all
+ * bytes are processed, this function returns. The other callbacks
+ * are called in the same way as they are in `nghttp2_session_recv()`.
+ *
+ * In the current implementation, this function always tries to
+ * processes all input data unless either an error occurs or
+ * :enum:`NGHTTP2_ERR_PAUSE` is returned from
+ * :type:`nghttp2_on_header_callback` or
+ * :type:`nghttp2_on_data_chunk_recv_callback`. If
+ * :enum:`NGHTTP2_ERR_PAUSE` is used, the return value includes the
+ * number of bytes which was used to produce the data or frame for the
+ * callback.
+ *
+ * This function returns the number of processed bytes, or one of the
+ * following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`
+ * The callback function failed.
+ * :enum:`NGHTTP2_ERR_BAD_CLIENT_MAGIC`
+ * Invalid client magic was detected. This error only returns
+ * when |session| was configured as server and
+ * `nghttp2_option_set_no_recv_client_magic()` is not used with
+ * nonzero value.
+ * :enum:`NGHTTP2_ERR_FLOODED`
+ * Flooding was detected in this HTTP/2 session, and it must be
+ * closed. This is most likely caused by misbehaviour of peer.
+ */
+NGHTTP2_EXTERN ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
+ const uint8_t *in,
+ size_t inlen);
+
+/**
+ * @function
+ *
+ * Puts back previously deferred DATA frame in the stream |stream_id|
+ * to the outbound queue.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The stream does not exist; or no deferred data exist.
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_session_resume_data(nghttp2_session *session,
+ int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Returns nonzero value if |session| wants to receive data from the
+ * remote peer.
+ *
+ * If both `nghttp2_session_want_read()` and
+ * `nghttp2_session_want_write()` return 0, the application should
+ * drop the connection.
+ */
+NGHTTP2_EXTERN int nghttp2_session_want_read(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns nonzero value if |session| wants to send data to the remote
+ * peer.
+ *
+ * If both `nghttp2_session_want_read()` and
+ * `nghttp2_session_want_write()` return 0, the application should
+ * drop the connection.
+ */
+NGHTTP2_EXTERN int nghttp2_session_want_write(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns stream_user_data for the stream |stream_id|. The
+ * stream_user_data is provided by `nghttp2_submit_request()`,
+ * `nghttp2_submit_headers()` or
+ * `nghttp2_session_set_stream_user_data()`. Unless it is set using
+ * `nghttp2_session_set_stream_user_data()`, if the stream is
+ * initiated by the remote endpoint, stream_user_data is always
+ * ``NULL``. If the stream does not exist, this function returns
+ * ``NULL``.
+ */
+NGHTTP2_EXTERN void *
+nghttp2_session_get_stream_user_data(nghttp2_session *session,
+ int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Sets the |stream_user_data| to the stream denoted by the
+ * |stream_id|. If a stream user data is already set to the stream,
+ * it is replaced with the |stream_user_data|. It is valid to specify
+ * ``NULL`` in the |stream_user_data|, which nullifies the associated
+ * data pointer.
+ *
+ * It is valid to set the |stream_user_data| to the stream reserved by
+ * PUSH_PROMISE frame.
+ *
+ * This function returns 0 if it succeeds, or one of following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The stream does not exist
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_set_stream_user_data(nghttp2_session *session,
+ int32_t stream_id, void *stream_user_data);
+
+/**
+ * @function
+ *
+ * Sets |user_data| to |session|, overwriting the existing user data
+ * specified in `nghttp2_session_client_new()`, or
+ * `nghttp2_session_server_new()`.
+ */
+NGHTTP2_EXTERN void nghttp2_session_set_user_data(nghttp2_session *session,
+ void *user_data);
+
+/**
+ * @function
+ *
+ * Returns the number of frames in the outbound queue. This does not
+ * include the deferred DATA frames.
+ */
+NGHTTP2_EXTERN size_t
+nghttp2_session_get_outbound_queue_size(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the number of DATA payload in bytes received without
+ * WINDOW_UPDATE transmission for the stream |stream_id|. The local
+ * (receive) window size can be adjusted by
+ * `nghttp2_submit_window_update()`. This function takes into account
+ * that and returns effective data length. In particular, if the
+ * local window size is reduced by submitting negative
+ * window_size_increment with `nghttp2_submit_window_update()`, this
+ * function returns the number of bytes less than actually received.
+ *
+ * This function returns -1 if it fails.
+ */
+NGHTTP2_EXTERN int32_t nghttp2_session_get_stream_effective_recv_data_length(
+ nghttp2_session *session, int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Returns the local (receive) window size for the stream |stream_id|.
+ * The local window size can be adjusted by
+ * `nghttp2_submit_window_update()`. This function takes into account
+ * that and returns effective window size.
+ *
+ * This function does not take into account the amount of received
+ * data from the remote endpoint. Use
+ * `nghttp2_session_get_stream_local_window_size()` to know the amount
+ * of data the remote endpoint can send without receiving stream level
+ * WINDOW_UPDATE frame. Note that each stream is still subject to the
+ * connection level flow control.
+ *
+ * This function returns -1 if it fails.
+ */
+NGHTTP2_EXTERN int32_t nghttp2_session_get_stream_effective_local_window_size(
+ nghttp2_session *session, int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Returns the amount of flow-controlled payload (e.g., DATA) that the
+ * remote endpoint can send without receiving stream level
+ * WINDOW_UPDATE frame. It is also subject to the connection level
+ * flow control. So the actual amount of data to send is
+ * min(`nghttp2_session_get_stream_local_window_size()`,
+ * `nghttp2_session_get_local_window_size()`).
+ *
+ * This function returns -1 if it fails.
+ */
+NGHTTP2_EXTERN int32_t nghttp2_session_get_stream_local_window_size(
+ nghttp2_session *session, int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Returns the number of DATA payload in bytes received without
+ * WINDOW_UPDATE transmission for a connection. The local (receive)
+ * window size can be adjusted by `nghttp2_submit_window_update()`.
+ * This function takes into account that and returns effective data
+ * length. In particular, if the local window size is reduced by
+ * submitting negative window_size_increment with
+ * `nghttp2_submit_window_update()`, this function returns the number
+ * of bytes less than actually received.
+ *
+ * This function returns -1 if it fails.
+ */
+NGHTTP2_EXTERN int32_t
+nghttp2_session_get_effective_recv_data_length(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the local (receive) window size for a connection. The
+ * local window size can be adjusted by
+ * `nghttp2_submit_window_update()`. This function takes into account
+ * that and returns effective window size.
+ *
+ * This function does not take into account the amount of received
+ * data from the remote endpoint. Use
+ * `nghttp2_session_get_local_window_size()` to know the amount of
+ * data the remote endpoint can send without receiving
+ * connection-level WINDOW_UPDATE frame. Note that each stream is
+ * still subject to the stream level flow control.
+ *
+ * This function returns -1 if it fails.
+ */
+NGHTTP2_EXTERN int32_t
+nghttp2_session_get_effective_local_window_size(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the amount of flow-controlled payload (e.g., DATA) that the
+ * remote endpoint can send without receiving connection level
+ * WINDOW_UPDATE frame. Note that each stream is still subject to the
+ * stream level flow control (see
+ * `nghttp2_session_get_stream_local_window_size()`).
+ *
+ * This function returns -1 if it fails.
+ */
+NGHTTP2_EXTERN int32_t
+nghttp2_session_get_local_window_size(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the remote window size for a given stream |stream_id|.
+ *
+ * This is the amount of flow-controlled payload (e.g., DATA) that the
+ * local endpoint can send without stream level WINDOW_UPDATE. There
+ * is also connection level flow control, so the effective size of
+ * payload that the local endpoint can actually send is
+ * min(`nghttp2_session_get_stream_remote_window_size()`,
+ * `nghttp2_session_get_remote_window_size()`).
+ *
+ * This function returns -1 if it fails.
+ */
+NGHTTP2_EXTERN int32_t nghttp2_session_get_stream_remote_window_size(
+ nghttp2_session *session, int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Returns the remote window size for a connection.
+ *
+ * This function always succeeds.
+ */
+NGHTTP2_EXTERN int32_t
+nghttp2_session_get_remote_window_size(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns 1 if local peer half closed the given stream |stream_id|.
+ * Returns 0 if it did not. Returns -1 if no such stream exists.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_get_stream_local_close(nghttp2_session *session,
+ int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Returns 1 if remote peer half closed the given stream |stream_id|.
+ * Returns 0 if it did not. Returns -1 if no such stream exists.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_get_stream_remote_close(nghttp2_session *session,
+ int32_t stream_id);
+
+/**
+ * @function
+ *
+ * Returns the current dynamic table size of HPACK inflater, including
+ * the overhead 32 bytes per entry described in RFC 7541.
+ */
+NGHTTP2_EXTERN size_t
+nghttp2_session_get_hd_inflate_dynamic_table_size(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the current dynamic table size of HPACK deflater including
+ * the overhead 32 bytes per entry described in RFC 7541.
+ */
+NGHTTP2_EXTERN size_t
+nghttp2_session_get_hd_deflate_dynamic_table_size(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Signals the session so that the connection should be terminated.
+ *
+ * The last stream ID is the minimum value between the stream ID of a
+ * stream for which :type:`nghttp2_on_frame_recv_callback` was called
+ * most recently and the last stream ID we have sent to the peer
+ * previously.
+ *
+ * The |error_code| is the error code of this GOAWAY frame. The
+ * pre-defined error code is one of :enum:`nghttp2_error_code`.
+ *
+ * After the transmission, both `nghttp2_session_want_read()` and
+ * `nghttp2_session_want_write()` return 0.
+ *
+ * This function should be called when the connection should be
+ * terminated after sending GOAWAY. If the remaining streams should
+ * be processed after GOAWAY, use `nghttp2_submit_goaway()` instead.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_session_terminate_session(nghttp2_session *session,
+ uint32_t error_code);
+
+/**
+ * @function
+ *
+ * Signals the session so that the connection should be terminated.
+ *
+ * This function behaves like `nghttp2_session_terminate_session()`,
+ * but the last stream ID can be specified by the application for fine
+ * grained control of stream. The HTTP/2 specification does not allow
+ * last_stream_id to be increased. So the actual value sent as
+ * last_stream_id is the minimum value between the given
+ * |last_stream_id| and the last_stream_id we have previously sent to
+ * the peer.
+ *
+ * The |last_stream_id| is peer's stream ID or 0. So if |session| is
+ * initialized as client, |last_stream_id| must be even or 0. If
+ * |session| is initialized as server, |last_stream_id| must be odd or
+ * 0.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |last_stream_id| is invalid.
+ */
+NGHTTP2_EXTERN int nghttp2_session_terminate_session2(nghttp2_session *session,
+ int32_t last_stream_id,
+ uint32_t error_code);
+
+/**
+ * @function
+ *
+ * Signals to the client that the server started graceful shutdown
+ * procedure.
+ *
+ * This function is only usable for server. If this function is
+ * called with client side session, this function returns
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`.
+ *
+ * To gracefully shutdown HTTP/2 session, server should call this
+ * function to send GOAWAY with last_stream_id (1u << 31) - 1. And
+ * after some delay (e.g., 1 RTT), send another GOAWAY with the stream
+ * ID that the server has some processing using
+ * `nghttp2_submit_goaway()`. See also
+ * `nghttp2_session_get_last_proc_stream_id()`.
+ *
+ * Unlike `nghttp2_submit_goaway()`, this function just sends GOAWAY
+ * and does nothing more. This is a mere indication to the client
+ * that session shutdown is imminent. The application should call
+ * `nghttp2_submit_goaway()` with appropriate last_stream_id after
+ * this call.
+ *
+ * If one or more GOAWAY frame have been already sent by either
+ * `nghttp2_submit_goaway()` or `nghttp2_session_terminate_session()`,
+ * this function has no effect.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`
+ * The |session| is initialized as client.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_shutdown_notice(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the value of SETTINGS |id| notified by a remote endpoint.
+ * The |id| must be one of values defined in
+ * :enum:`nghttp2_settings_id`.
+ */
+NGHTTP2_EXTERN uint32_t nghttp2_session_get_remote_settings(
+ nghttp2_session *session, nghttp2_settings_id id);
+
+/**
+ * @function
+ *
+ * Returns the value of SETTINGS |id| of local endpoint acknowledged
+ * by the remote endpoint. The |id| must be one of the values defined
+ * in :enum:`nghttp2_settings_id`.
+ */
+NGHTTP2_EXTERN uint32_t nghttp2_session_get_local_settings(
+ nghttp2_session *session, nghttp2_settings_id id);
+
+/**
+ * @function
+ *
+ * Tells the |session| that next stream ID is |next_stream_id|. The
+ * |next_stream_id| must be equal or greater than the value returned
+ * by `nghttp2_session_get_next_stream_id()`.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |next_stream_id| is strictly less than the value
+ * `nghttp2_session_get_next_stream_id()` returns; or
+ * |next_stream_id| is invalid (e.g., even integer for client, or
+ * odd integer for server).
+ */
+NGHTTP2_EXTERN int nghttp2_session_set_next_stream_id(nghttp2_session *session,
+ int32_t next_stream_id);
+
+/**
+ * @function
+ *
+ * Returns the next outgoing stream ID. Notice that return type is
+ * uint32_t. If we run out of stream ID for this session, this
+ * function returns 1 << 31.
+ */
+NGHTTP2_EXTERN uint32_t
+nghttp2_session_get_next_stream_id(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Tells the |session| that |size| bytes for a stream denoted by
+ * |stream_id| were consumed by application and are ready to
+ * WINDOW_UPDATE. The consumed bytes are counted towards both
+ * connection and stream level WINDOW_UPDATE (see
+ * `nghttp2_session_consume_connection()` and
+ * `nghttp2_session_consume_stream()` to update consumption
+ * independently). This function is intended to be used without
+ * automatic window update (see
+ * `nghttp2_option_set_no_auto_window_update()`).
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0.
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`
+ * Automatic WINDOW_UPDATE is not disabled.
+ */
+NGHTTP2_EXTERN int nghttp2_session_consume(nghttp2_session *session,
+ int32_t stream_id, size_t size);
+
+/**
+ * @function
+ *
+ * Like `nghttp2_session_consume()`, but this only tells library that
+ * |size| bytes were consumed only for connection level. Note that
+ * HTTP/2 maintains connection and stream level flow control windows
+ * independently.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`
+ * Automatic WINDOW_UPDATE is not disabled.
+ */
+NGHTTP2_EXTERN int nghttp2_session_consume_connection(nghttp2_session *session,
+ size_t size);
+
+/**
+ * @function
+ *
+ * Like `nghttp2_session_consume()`, but this only tells library that
+ * |size| bytes were consumed only for stream denoted by |stream_id|.
+ * Note that HTTP/2 maintains connection and stream level flow control
+ * windows independently.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0.
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`
+ * Automatic WINDOW_UPDATE is not disabled.
+ */
+NGHTTP2_EXTERN int nghttp2_session_consume_stream(nghttp2_session *session,
+ int32_t stream_id,
+ size_t size);
+
+/**
+ * @function
+ *
+ * Changes priority of existing stream denoted by |stream_id|. The
+ * new priority specification is |pri_spec|.
+ *
+ * The priority is changed silently and instantly, and no PRIORITY
+ * frame will be sent to notify the peer of this change. This
+ * function may be useful for server to change the priority of pushed
+ * stream.
+ *
+ * If |session| is initialized as server, and ``pri_spec->stream_id``
+ * points to the idle stream, the idle stream is created if it does
+ * not exist. The created idle stream will depend on root stream
+ * (stream 0) with weight 16.
+ *
+ * Otherwise, if stream denoted by ``pri_spec->stream_id`` is not
+ * found, we use default priority instead of given |pri_spec|. That
+ * is make stream depend on root stream with weight 16.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * Attempted to depend on itself; or no stream exist for the given
+ * |stream_id|; or |stream_id| is 0
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_change_stream_priority(nghttp2_session *session,
+ int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec);
+
+/**
+ * @function
+ *
+ * Creates idle stream with the given |stream_id|, and priority
+ * |pri_spec|.
+ *
+ * The stream creation is done without sending PRIORITY frame, which
+ * means that peer does not know about the existence of this idle
+ * stream in the local endpoint.
+ *
+ * RFC 7540 does not disallow the use of creation of idle stream with
+ * odd or even stream ID regardless of client or server. So this
+ * function can create odd or even stream ID regardless of client or
+ * server. But probably it is a bit safer to use the stream ID the
+ * local endpoint can initiate (in other words, use odd stream ID for
+ * client, and even stream ID for server), to avoid potential
+ * collision from peer's instruction. Also we can use
+ * `nghttp2_session_set_next_stream_id()` to avoid to open created
+ * idle streams accidentally if we follow this recommendation.
+ *
+ * If |session| is initialized as server, and ``pri_spec->stream_id``
+ * points to the idle stream, the idle stream is created if it does
+ * not exist. The created idle stream will depend on root stream
+ * (stream 0) with weight 16.
+ *
+ * Otherwise, if stream denoted by ``pri_spec->stream_id`` is not
+ * found, we use default priority instead of given |pri_spec|. That
+ * is make stream depend on root stream with weight 16.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * Attempted to depend on itself; or stream denoted by |stream_id|
+ * already exists; or |stream_id| cannot be used to create idle
+ * stream (in other words, local endpoint has already opened
+ * stream ID greater than or equal to the given stream ID; or
+ * |stream_id| is 0
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_create_idle_stream(nghttp2_session *session, int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec);
+
+/**
+ * @function
+ *
+ * Performs post-process of HTTP Upgrade request. This function can
+ * be called from both client and server, but the behavior is very
+ * different in each other.
+ *
+ * .. warning::
+ *
+ * This function is deprecated in favor of
+ * `nghttp2_session_upgrade2()`, because this function lacks the
+ * parameter to tell the library the request method used in the
+ * original HTTP request. This information is required for client
+ * to validate actual response body length against content-length
+ * header field (see `nghttp2_option_set_no_http_messaging()`). If
+ * HEAD is used in request, the length of response body must be 0
+ * regardless of value included in content-length header field.
+ *
+ * If called from client side, the |settings_payload| must be the
+ * value sent in ``HTTP2-Settings`` header field and must be decoded
+ * by base64url decoder. The |settings_payloadlen| is the length of
+ * |settings_payload|. The |settings_payload| is unpacked and its
+ * setting values will be submitted using `nghttp2_submit_settings()`.
+ * This means that the client application code does not need to submit
+ * SETTINGS by itself. The stream with stream ID=1 is opened and the
+ * |stream_user_data| is used for its stream_user_data. The opened
+ * stream becomes half-closed (local) state.
+ *
+ * If called from server side, the |settings_payload| must be the
+ * value received in ``HTTP2-Settings`` header field and must be
+ * decoded by base64url decoder. The |settings_payloadlen| is the
+ * length of |settings_payload|. It is treated as if the SETTINGS
+ * frame with that payload is received. Thus, callback functions for
+ * the reception of SETTINGS frame will be invoked. The stream with
+ * stream ID=1 is opened. The |stream_user_data| is ignored. The
+ * opened stream becomes half-closed (remote).
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |settings_payload| is badly formed.
+ * :enum:`NGHTTP2_ERR_PROTO`
+ * The stream ID 1 is already used or closed; or is not available.
+ */
+NGHTTP2_EXTERN int nghttp2_session_upgrade(nghttp2_session *session,
+ const uint8_t *settings_payload,
+ size_t settings_payloadlen,
+ void *stream_user_data);
+
+/**
+ * @function
+ *
+ * Performs post-process of HTTP Upgrade request. This function can
+ * be called from both client and server, but the behavior is very
+ * different in each other.
+ *
+ * If called from client side, the |settings_payload| must be the
+ * value sent in ``HTTP2-Settings`` header field and must be decoded
+ * by base64url decoder. The |settings_payloadlen| is the length of
+ * |settings_payload|. The |settings_payload| is unpacked and its
+ * setting values will be submitted using `nghttp2_submit_settings()`.
+ * This means that the client application code does not need to submit
+ * SETTINGS by itself. The stream with stream ID=1 is opened and the
+ * |stream_user_data| is used for its stream_user_data. The opened
+ * stream becomes half-closed (local) state.
+ *
+ * If called from server side, the |settings_payload| must be the
+ * value received in ``HTTP2-Settings`` header field and must be
+ * decoded by base64url decoder. The |settings_payloadlen| is the
+ * length of |settings_payload|. It is treated as if the SETTINGS
+ * frame with that payload is received. Thus, callback functions for
+ * the reception of SETTINGS frame will be invoked. The stream with
+ * stream ID=1 is opened. The |stream_user_data| is ignored. The
+ * opened stream becomes half-closed (remote).
+ *
+ * If the request method is HEAD, pass nonzero value to
+ * |head_request|. Otherwise, pass 0.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |settings_payload| is badly formed.
+ * :enum:`NGHTTP2_ERR_PROTO`
+ * The stream ID 1 is already used or closed; or is not available.
+ */
+NGHTTP2_EXTERN int nghttp2_session_upgrade2(nghttp2_session *session,
+ const uint8_t *settings_payload,
+ size_t settings_payloadlen,
+ int head_request,
+ void *stream_user_data);
+
+/**
+ * @function
+ *
+ * Serializes the SETTINGS values |iv| in the |buf|. The size of the
+ * |buf| is specified by |buflen|. The number of entries in the |iv|
+ * array is given by |niv|. The required space in |buf| for the |niv|
+ * entries is ``6*niv`` bytes and if the given buffer is too small, an
+ * error is returned. This function is used mainly for creating a
+ * SETTINGS payload to be sent with the ``HTTP2-Settings`` header
+ * field in an HTTP Upgrade request. The data written in |buf| is NOT
+ * base64url encoded and the application is responsible for encoding.
+ *
+ * This function returns the number of bytes written in |buf|, or one
+ * of the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |iv| contains duplicate settings ID or invalid value.
+ *
+ * :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`
+ * The provided |buflen| size is too small to hold the output.
+ */
+NGHTTP2_EXTERN ssize_t nghttp2_pack_settings_payload(
+ uint8_t *buf, size_t buflen, const nghttp2_settings_entry *iv, size_t niv);
+
+/**
+ * @function
+ *
+ * Returns string describing the |lib_error_code|. The
+ * |lib_error_code| must be one of the :enum:`nghttp2_error`.
+ */
+NGHTTP2_EXTERN const char *nghttp2_strerror(int lib_error_code);
+
+/**
+ * @function
+ *
+ * Returns string representation of HTTP/2 error code |error_code|
+ * (e.g., ``PROTOCOL_ERROR`` is returned if ``error_code ==
+ * NGHTTP2_PROTOCOL_ERROR``). If string representation is unknown for
+ * given |error_code|, this function returns string ``unknown``.
+ */
+NGHTTP2_EXTERN const char *nghttp2_http2_strerror(uint32_t error_code);
+
+/**
+ * @function
+ *
+ * Initializes |pri_spec| with the |stream_id| of the stream to depend
+ * on with |weight| and its exclusive flag. If |exclusive| is
+ * nonzero, exclusive flag is set.
+ *
+ * The |weight| must be in [:enum:`NGHTTP2_MIN_WEIGHT`,
+ * :enum:`NGHTTP2_MAX_WEIGHT`], inclusive.
+ */
+NGHTTP2_EXTERN void nghttp2_priority_spec_init(nghttp2_priority_spec *pri_spec,
+ int32_t stream_id,
+ int32_t weight, int exclusive);
+
+/**
+ * @function
+ *
+ * Initializes |pri_spec| with the default values. The default values
+ * are: stream_id = 0, weight = :macro:`NGHTTP2_DEFAULT_WEIGHT` and
+ * exclusive = 0.
+ */
+NGHTTP2_EXTERN void
+nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec);
+
+/**
+ * @function
+ *
+ * Returns nonzero if the |pri_spec| is filled with default values.
+ */
+NGHTTP2_EXTERN int
+nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec);
+
+/**
+ * @function
+ *
+ * Submits HEADERS frame and optionally one or more DATA frames.
+ *
+ * The |pri_spec| is priority specification of this request. ``NULL``
+ * means the default priority (see
+ * `nghttp2_priority_spec_default_init()`). To specify the priority,
+ * use `nghttp2_priority_spec_init()`. If |pri_spec| is not ``NULL``,
+ * this function will copy its data members.
+ *
+ * The ``pri_spec->weight`` must be in [:enum:`NGHTTP2_MIN_WEIGHT`,
+ * :enum:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` is
+ * strictly less than :enum:`NGHTTP2_MIN_WEIGHT`, it becomes
+ * :enum:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than
+ * :enum:`NGHTTP2_MAX_WEIGHT`, it becomes :enum:`NGHTTP2_MAX_WEIGHT`.
+ *
+ * The |nva| is an array of name/value pair :type:`nghttp2_nv` with
+ * |nvlen| elements. The application is responsible to include
+ * required pseudo-header fields (header field whose name starts with
+ * ":") in |nva| and must place pseudo-headers before regular header
+ * fields.
+ *
+ * This function creates copies of all name/value pairs in |nva|. It
+ * also lower-cases all names in |nva|. The order of elements in
+ * |nva| is preserved. For header fields with
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name
+ * and value are not copied respectively. With
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to
+ * pass header field name in lowercase. The application should
+ * maintain the references to them until
+ * :type:`nghttp2_on_frame_send_callback` or
+ * :type:`nghttp2_on_frame_not_send_callback` is called.
+ *
+ * HTTP/2 specification has requirement about header fields in the
+ * request HEADERS. See the specification for more details.
+ *
+ * If |data_prd| is not ``NULL``, it provides data which will be sent
+ * in subsequent DATA frames. In this case, a method that allows
+ * request message bodies
+ * (https://tools.ietf.org/html/rfc7231#section-4) must be specified
+ * with ``:method`` key in |nva| (e.g. ``POST``). This function does
+ * not take ownership of the |data_prd|. The function copies the
+ * members of the |data_prd|. If |data_prd| is ``NULL``, HEADERS have
+ * END_STREAM set. The |stream_user_data| is data associated to the
+ * stream opened by this request and can be an arbitrary pointer,
+ * which can be retrieved later by
+ * `nghttp2_session_get_stream_user_data()`.
+ *
+ * This function returns assigned stream ID if it succeeds, or one of
+ * the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE`
+ * No stream ID is available because maximum stream ID was
+ * reached.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * Trying to depend on itself (new stream ID equals
+ * ``pri_spec->stream_id``).
+ * :enum:`NGHTTP2_ERR_PROTO`
+ * The |session| is server session.
+ *
+ * .. warning::
+ *
+ * This function returns assigned stream ID if it succeeds. But
+ * that stream is not opened yet. The application must not submit
+ * frame to that stream ID before
+ * :type:`nghttp2_before_frame_send_callback` is called for this
+ * frame.
+ *
+ */
+NGHTTP2_EXTERN int32_t nghttp2_submit_request(
+ nghttp2_session *session, const nghttp2_priority_spec *pri_spec,
+ const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider *data_prd,
+ void *stream_user_data);
+
+/**
+ * @function
+ *
+ * Submits response HEADERS frame and optionally one or more DATA
+ * frames against the stream |stream_id|.
+ *
+ * The |nva| is an array of name/value pair :type:`nghttp2_nv` with
+ * |nvlen| elements. The application is responsible to include
+ * required pseudo-header fields (header field whose name starts with
+ * ":") in |nva| and must place pseudo-headers before regular header
+ * fields.
+ *
+ * This function creates copies of all name/value pairs in |nva|. It
+ * also lower-cases all names in |nva|. The order of elements in
+ * |nva| is preserved. For header fields with
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name
+ * and value are not copied respectively. With
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to
+ * pass header field name in lowercase. The application should
+ * maintain the references to them until
+ * :type:`nghttp2_on_frame_send_callback` or
+ * :type:`nghttp2_on_frame_not_send_callback` is called.
+ *
+ * HTTP/2 specification has requirement about header fields in the
+ * response HEADERS. See the specification for more details.
+ *
+ * If |data_prd| is not ``NULL``, it provides data which will be sent
+ * in subsequent DATA frames. This function does not take ownership
+ * of the |data_prd|. The function copies the members of the
+ * |data_prd|. If |data_prd| is ``NULL``, HEADERS will have
+ * END_STREAM flag set.
+ *
+ * This method can be used as normal HTTP response and push response.
+ * When pushing a resource using this function, the |session| must be
+ * configured using `nghttp2_session_server_new()` or its variants and
+ * the target stream denoted by the |stream_id| must be reserved using
+ * `nghttp2_submit_push_promise()`.
+ *
+ * To send non-final response headers (e.g., HTTP status 101), don't
+ * use this function because this function half-closes the outbound
+ * stream. Instead, use `nghttp2_submit_headers()` for this purpose.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0.
+ * :enum:`NGHTTP2_ERR_DATA_EXIST`
+ * DATA or HEADERS has been already submitted and not fully
+ * processed yet. Normally, this does not happen, but when
+ * application wrongly calls `nghttp2_submit_response()` twice,
+ * this may happen.
+ * :enum:`NGHTTP2_ERR_PROTO`
+ * The |session| is client session.
+ *
+ * .. warning::
+ *
+ * Calling this function twice for the same stream ID may lead to
+ * program crash. It is generally considered to a programming error
+ * to commit response twice.
+ */
+NGHTTP2_EXTERN int
+nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
+ const nghttp2_nv *nva, size_t nvlen,
+ const nghttp2_data_provider *data_prd);
+
+/**
+ * @function
+ *
+ * Submits trailer fields HEADERS against the stream |stream_id|.
+ *
+ * The |nva| is an array of name/value pair :type:`nghttp2_nv` with
+ * |nvlen| elements. The application must not include pseudo-header
+ * fields (headers whose names starts with ":") in |nva|.
+ *
+ * This function creates copies of all name/value pairs in |nva|. It
+ * also lower-cases all names in |nva|. The order of elements in
+ * |nva| is preserved. For header fields with
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name
+ * and value are not copied respectively. With
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to
+ * pass header field name in lowercase. The application should
+ * maintain the references to them until
+ * :type:`nghttp2_on_frame_send_callback` or
+ * :type:`nghttp2_on_frame_not_send_callback` is called.
+ *
+ * For server, trailer fields must follow response HEADERS or response
+ * DATA without END_STREAM flat set. The library does not enforce
+ * this requirement, and applications should do this for themselves.
+ * If `nghttp2_submit_trailer()` is called before any response HEADERS
+ * submission (usually by `nghttp2_submit_response()`), the content of
+ * |nva| will be sent as response headers, which will result in error.
+ *
+ * This function has the same effect with `nghttp2_submit_headers()`,
+ * with flags = :enum:`NGHTTP2_FLAG_END_STREAM` and both pri_spec and
+ * stream_user_data to NULL.
+ *
+ * To submit trailer fields after `nghttp2_submit_response()` is
+ * called, the application has to specify
+ * :type:`nghttp2_data_provider` to `nghttp2_submit_response()`.
+ * Inside of :type:`nghttp2_data_source_read_callback`, when setting
+ * :enum:`NGHTTP2_DATA_FLAG_EOF`, also set
+ * :enum:`NGHTTP2_DATA_FLAG_NO_END_STREAM`. After that, the
+ * application can send trailer fields using
+ * `nghttp2_submit_trailer()`. `nghttp2_submit_trailer()` can be used
+ * inside :type:`nghttp2_data_source_read_callback`.
+ *
+ * This function returns 0 if it succeeds and |stream_id| is -1.
+ * Otherwise, this function returns 0 if it succeeds, or one of the
+ * following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_trailer(nghttp2_session *session,
+ int32_t stream_id,
+ const nghttp2_nv *nva, size_t nvlen);
+
+/**
+ * @function
+ *
+ * Submits HEADERS frame. The |flags| is bitwise OR of the
+ * following values:
+ *
+ * * :enum:`NGHTTP2_FLAG_END_STREAM`
+ *
+ * If |flags| includes :enum:`NGHTTP2_FLAG_END_STREAM`, this frame has
+ * END_STREAM flag set.
+ *
+ * The library handles the CONTINUATION frame internally and it
+ * correctly sets END_HEADERS to the last sequence of the PUSH_PROMISE
+ * or CONTINUATION frame.
+ *
+ * If the |stream_id| is -1, this frame is assumed as request (i.e.,
+ * request HEADERS frame which opens new stream). In this case, the
+ * assigned stream ID will be returned. Otherwise, specify stream ID
+ * in |stream_id|.
+ *
+ * The |pri_spec| is priority specification of this request. ``NULL``
+ * means the default priority (see
+ * `nghttp2_priority_spec_default_init()`). To specify the priority,
+ * use `nghttp2_priority_spec_init()`. If |pri_spec| is not ``NULL``,
+ * this function will copy its data members.
+ *
+ * The ``pri_spec->weight`` must be in [:enum:`NGHTTP2_MIN_WEIGHT`,
+ * :enum:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` is
+ * strictly less than :enum:`NGHTTP2_MIN_WEIGHT`, it becomes
+ * :enum:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than
+ * :enum:`NGHTTP2_MAX_WEIGHT`, it becomes :enum:`NGHTTP2_MAX_WEIGHT`.
+ *
+ * The |nva| is an array of name/value pair :type:`nghttp2_nv` with
+ * |nvlen| elements. The application is responsible to include
+ * required pseudo-header fields (header field whose name starts with
+ * ":") in |nva| and must place pseudo-headers before regular header
+ * fields.
+ *
+ * This function creates copies of all name/value pairs in |nva|. It
+ * also lower-cases all names in |nva|. The order of elements in
+ * |nva| is preserved. For header fields with
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name
+ * and value are not copied respectively. With
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to
+ * pass header field name in lowercase. The application should
+ * maintain the references to them until
+ * :type:`nghttp2_on_frame_send_callback` or
+ * :type:`nghttp2_on_frame_not_send_callback` is called.
+ *
+ * The |stream_user_data| is a pointer to an arbitrary data which is
+ * associated to the stream this frame will open. Therefore it is
+ * only used if this frame opens streams, in other words, it changes
+ * stream state from idle or reserved to open.
+ *
+ * This function is low-level in a sense that the application code can
+ * specify flags directly. For usual HTTP request,
+ * `nghttp2_submit_request()` is useful. Likewise, for HTTP response,
+ * prefer `nghttp2_submit_response()`.
+ *
+ * This function returns newly assigned stream ID if it succeeds and
+ * |stream_id| is -1. Otherwise, this function returns 0 if it
+ * succeeds, or one of the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE`
+ * No stream ID is available because maximum stream ID was
+ * reached.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0; or trying to depend on itself (stream ID
+ * equals ``pri_spec->stream_id``).
+ * :enum:`NGHTTP2_ERR_DATA_EXIST`
+ * DATA or HEADERS has been already submitted and not fully
+ * processed yet. This happens if stream denoted by |stream_id|
+ * is in reserved state.
+ * :enum:`NGHTTP2_ERR_PROTO`
+ * The |stream_id| is -1, and |session| is server session.
+ *
+ * .. warning::
+ *
+ * This function returns assigned stream ID if it succeeds and
+ * |stream_id| is -1. But that stream is not opened yet. The
+ * application must not submit frame to that stream ID before
+ * :type:`nghttp2_before_frame_send_callback` is called for this
+ * frame.
+ *
+ */
+NGHTTP2_EXTERN int32_t nghttp2_submit_headers(
+ nghttp2_session *session, uint8_t flags, int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec, const nghttp2_nv *nva, size_t nvlen,
+ void *stream_user_data);
+
+/**
+ * @function
+ *
+ * Submits one or more DATA frames to the stream |stream_id|. The
+ * data to be sent are provided by |data_prd|. If |flags| contains
+ * :enum:`NGHTTP2_FLAG_END_STREAM`, the last DATA frame has END_STREAM
+ * flag set.
+ *
+ * This function does not take ownership of the |data_prd|. The
+ * function copies the members of the |data_prd|.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_DATA_EXIST`
+ * DATA or HEADERS has been already submitted and not fully
+ * processed yet.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0.
+ * :enum:`NGHTTP2_ERR_STREAM_CLOSED`
+ * The stream was already closed; or the |stream_id| is invalid.
+ *
+ * .. note::
+ *
+ * Currently, only one DATA or HEADERS is allowed for a stream at a
+ * time. Submitting these frames more than once before first DATA
+ * or HEADERS is finished results in :enum:`NGHTTP2_ERR_DATA_EXIST`
+ * error code. The earliest callback which tells that previous
+ * frame is done is :type:`nghttp2_on_frame_send_callback`. In side
+ * that callback, new data can be submitted using
+ * `nghttp2_submit_data()`. Of course, all data except for last one
+ * must not have :enum:`NGHTTP2_FLAG_END_STREAM` flag set in
+ * |flags|. This sounds a bit complicated, and we recommend to use
+ * `nghttp2_submit_request()` and `nghttp2_submit_response()` to
+ * avoid this cascading issue. The experience shows that for HTTP
+ * use, these two functions are enough to implement both client and
+ * server.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id,
+ const nghttp2_data_provider *data_prd);
+
+/**
+ * @function
+ *
+ * Submits PRIORITY frame to change the priority of stream |stream_id|
+ * to the priority specification |pri_spec|.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * The |pri_spec| is priority specification of this request. ``NULL``
+ * is not allowed for this function. To specify the priority, use
+ * `nghttp2_priority_spec_init()`. This function will copy its data
+ * members.
+ *
+ * The ``pri_spec->weight`` must be in [:enum:`NGHTTP2_MIN_WEIGHT`,
+ * :enum:`NGHTTP2_MAX_WEIGHT`], inclusive. If ``pri_spec->weight`` is
+ * strictly less than :enum:`NGHTTP2_MIN_WEIGHT`, it becomes
+ * :enum:`NGHTTP2_MIN_WEIGHT`. If it is strictly greater than
+ * :enum:`NGHTTP2_MAX_WEIGHT`, it becomes :enum:`NGHTTP2_MAX_WEIGHT`.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0; or the |pri_spec| is NULL; or trying to
+ * depend on itself.
+ */
+NGHTTP2_EXTERN int
+nghttp2_submit_priority(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec);
+
+/**
+ * @function
+ *
+ * Submits RST_STREAM frame to cancel/reject the stream |stream_id|
+ * with the error code |error_code|.
+ *
+ * The pre-defined error code is one of :enum:`nghttp2_error_code`.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_rst_stream(nghttp2_session *session,
+ uint8_t flags, int32_t stream_id,
+ uint32_t error_code);
+
+/**
+ * @function
+ *
+ * Stores local settings and submits SETTINGS frame. The |iv| is the
+ * pointer to the array of :type:`nghttp2_settings_entry`. The |niv|
+ * indicates the number of :type:`nghttp2_settings_entry`.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * This function does not take ownership of the |iv|. This function
+ * copies all the elements in the |iv|.
+ *
+ * While updating individual stream's local window size, if the window
+ * size becomes strictly larger than NGHTTP2_MAX_WINDOW_SIZE,
+ * RST_STREAM is issued against such a stream.
+ *
+ * SETTINGS with :enum:`NGHTTP2_FLAG_ACK` is automatically submitted
+ * by the library and application could not send it at its will.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |iv| contains invalid value (e.g., initial window size
+ * strictly greater than (1 << 31) - 1.
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_settings(nghttp2_session *session,
+ uint8_t flags,
+ const nghttp2_settings_entry *iv,
+ size_t niv);
+
+/**
+ * @function
+ *
+ * Submits PUSH_PROMISE frame.
+ *
+ * The |flags| is currently ignored. The library handles the
+ * CONTINUATION frame internally and it correctly sets END_HEADERS to
+ * the last sequence of the PUSH_PROMISE or CONTINUATION frame.
+ *
+ * The |stream_id| must be client initiated stream ID.
+ *
+ * The |nva| is an array of name/value pair :type:`nghttp2_nv` with
+ * |nvlen| elements. The application is responsible to include
+ * required pseudo-header fields (header field whose name starts with
+ * ":") in |nva| and must place pseudo-headers before regular header
+ * fields.
+ *
+ * This function creates copies of all name/value pairs in |nva|. It
+ * also lower-cases all names in |nva|. The order of elements in
+ * |nva| is preserved. For header fields with
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME` and
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE` are set, header field name
+ * and value are not copied respectively. With
+ * :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`, application is responsible to
+ * pass header field name in lowercase. The application should
+ * maintain the references to them until
+ * :type:`nghttp2_on_frame_send_callback` or
+ * :type:`nghttp2_on_frame_not_send_callback` is called.
+ *
+ * The |promised_stream_user_data| is a pointer to an arbitrary data
+ * which is associated to the promised stream this frame will open and
+ * make it in reserved state. It is available using
+ * `nghttp2_session_get_stream_user_data()`. The application can
+ * access it in :type:`nghttp2_before_frame_send_callback` and
+ * :type:`nghttp2_on_frame_send_callback` of this frame.
+ *
+ * The client side is not allowed to use this function.
+ *
+ * To submit response headers and data, use
+ * `nghttp2_submit_response()`.
+ *
+ * This function returns assigned promised stream ID if it succeeds,
+ * or one of the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_PROTO`
+ * This function was invoked when |session| is initialized as
+ * client.
+ * :enum:`NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE`
+ * No stream ID is available because maximum stream ID was
+ * reached.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is 0; The |stream_id| does not designate stream
+ * that peer initiated.
+ * :enum:`NGHTTP2_ERR_STREAM_CLOSED`
+ * The stream was already closed; or the |stream_id| is invalid.
+ *
+ * .. warning::
+ *
+ * This function returns assigned promised stream ID if it succeeds.
+ * As of 1.16.0, stream object for pushed resource is created when
+ * this function succeeds. In that case, the application can submit
+ * push response for the promised frame.
+ *
+ * In 1.15.0 or prior versions, pushed stream is not opened yet when
+ * this function succeeds. The application must not submit frame to
+ * that stream ID before :type:`nghttp2_before_frame_send_callback`
+ * is called for this frame.
+ *
+ */
+NGHTTP2_EXTERN int32_t nghttp2_submit_push_promise(
+ nghttp2_session *session, uint8_t flags, int32_t stream_id,
+ const nghttp2_nv *nva, size_t nvlen, void *promised_stream_user_data);
+
+/**
+ * @function
+ *
+ * Submits PING frame. You don't have to send PING back when you
+ * received PING frame. The library automatically submits PING frame
+ * in this case.
+ *
+ * The |flags| is bitwise OR of 0 or more of the following value.
+ *
+ * * :enum:`NGHTTP2_FLAG_ACK`
+ *
+ * Unless `nghttp2_option_set_no_auto_ping_ack()` is used, the |flags|
+ * should be :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * If the |opaque_data| is non ``NULL``, then it should point to the 8
+ * bytes array of memory to specify opaque data to send with PING
+ * frame. If the |opaque_data| is ``NULL``, zero-cleared 8 bytes will
+ * be sent as opaque data.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags,
+ const uint8_t *opaque_data);
+
+/**
+ * @function
+ *
+ * Submits GOAWAY frame with the last stream ID |last_stream_id| and
+ * the error code |error_code|.
+ *
+ * The pre-defined error code is one of :enum:`nghttp2_error_code`.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * The |last_stream_id| is peer's stream ID or 0. So if |session| is
+ * initialized as client, |last_stream_id| must be even or 0. If
+ * |session| is initialized as server, |last_stream_id| must be odd or
+ * 0.
+ *
+ * The HTTP/2 specification says last_stream_id must not be increased
+ * from the value previously sent. So the actual value sent as
+ * last_stream_id is the minimum value between the given
+ * |last_stream_id| and the last_stream_id previously sent to the
+ * peer.
+ *
+ * If the |opaque_data| is not ``NULL`` and |opaque_data_len| is not
+ * zero, those data will be sent as additional debug data. The
+ * library makes a copy of the memory region pointed by |opaque_data|
+ * with the length |opaque_data_len|, so the caller does not need to
+ * keep this memory after the return of this function. If the
+ * |opaque_data_len| is 0, the |opaque_data| could be ``NULL``.
+ *
+ * After successful transmission of GOAWAY, following things happen.
+ * All incoming streams having strictly more than |last_stream_id| are
+ * closed. All incoming HEADERS which starts new stream are simply
+ * ignored. After all active streams are handled, both
+ * `nghttp2_session_want_read()` and `nghttp2_session_want_write()`
+ * return 0 and the application can close session.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |opaque_data_len| is too large; the |last_stream_id| is
+ * invalid.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_goaway(nghttp2_session *session,
+ uint8_t flags, int32_t last_stream_id,
+ uint32_t error_code,
+ const uint8_t *opaque_data,
+ size_t opaque_data_len);
+
+/**
+ * @function
+ *
+ * Returns the last stream ID of a stream for which
+ * :type:`nghttp2_on_frame_recv_callback` was invoked most recently.
+ * The returned value can be used as last_stream_id parameter for
+ * `nghttp2_submit_goaway()` and
+ * `nghttp2_session_terminate_session2()`.
+ *
+ * This function always succeeds.
+ */
+NGHTTP2_EXTERN int32_t
+nghttp2_session_get_last_proc_stream_id(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns nonzero if new request can be sent from local endpoint.
+ *
+ * This function return 0 if request is not allowed for this session.
+ * There are several reasons why request is not allowed. Some of the
+ * reasons are: session is server; stream ID has been spent; GOAWAY
+ * has been sent or received.
+ *
+ * The application can call `nghttp2_submit_request()` without
+ * consulting this function. In that case, `nghttp2_submit_request()`
+ * may return error. Or, request is failed to sent, and
+ * :type:`nghttp2_on_stream_close_callback` is called.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_check_request_allowed(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns nonzero if |session| is initialized as server side session.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_check_server_session(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Submits WINDOW_UPDATE frame.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * The |stream_id| is the stream ID to send this WINDOW_UPDATE. To
+ * send connection level WINDOW_UPDATE, specify 0 to |stream_id|.
+ *
+ * If the |window_size_increment| is positive, the WINDOW_UPDATE with
+ * that value as window_size_increment is queued. If the
+ * |window_size_increment| is larger than the received bytes from the
+ * remote endpoint, the local window size is increased by that
+ * difference. If the sole purpose is to increase the local window
+ * size, consider to use `nghttp2_session_set_local_window_size()`.
+ *
+ * If the |window_size_increment| is negative, the local window size
+ * is decreased by -|window_size_increment|. If automatic
+ * WINDOW_UPDATE is enabled
+ * (`nghttp2_option_set_no_auto_window_update()`), and the library
+ * decided that the WINDOW_UPDATE should be submitted, then
+ * WINDOW_UPDATE is queued with the current received bytes count. If
+ * the sole purpose is to decrease the local window size, consider to
+ * use `nghttp2_session_set_local_window_size()`.
+ *
+ * If the |window_size_increment| is 0, the function does nothing and
+ * returns 0.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_FLOW_CONTROL`
+ * The local window size overflow or gets negative.
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_window_update(nghttp2_session *session,
+ uint8_t flags,
+ int32_t stream_id,
+ int32_t window_size_increment);
+
+/**
+ * @function
+ *
+ * Set local window size (local endpoints's window size) to the given
+ * |window_size| for the given stream denoted by |stream_id|. To
+ * change connection level window size, specify 0 to |stream_id|. To
+ * increase window size, this function may submit WINDOW_UPDATE frame
+ * to transmission queue.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * This sounds similar to `nghttp2_submit_window_update()`, but there
+ * are 2 differences. The first difference is that this function
+ * takes the absolute value of window size to set, rather than the
+ * delta. To change the window size, this may be easier to use since
+ * the application just declares the intended window size, rather than
+ * calculating delta. The second difference is that
+ * `nghttp2_submit_window_update()` affects the received bytes count
+ * which has not acked yet. By the specification of
+ * `nghttp2_submit_window_update()`, to strictly increase the local
+ * window size, we have to submit delta including all received bytes
+ * count, which might not be desirable in some cases. On the other
+ * hand, this function does not affect the received bytes count. It
+ * just sets the local window size to the given value.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The |stream_id| is negative.
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int
+nghttp2_session_set_local_window_size(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id, int32_t window_size);
+
+/**
+ * @function
+ *
+ * Submits extension frame.
+ *
+ * Application can pass arbitrary frame flags and stream ID in |flags|
+ * and |stream_id| respectively. The |payload| is opaque pointer, and
+ * it can be accessible though ``frame->ext.payload`` in
+ * :type:`nghttp2_pack_extension_callback`. The library will not own
+ * passed |payload| pointer.
+ *
+ * The application must set :type:`nghttp2_pack_extension_callback`
+ * using `nghttp2_session_callbacks_set_pack_extension_callback()`.
+ *
+ * The application should retain the memory pointed by |payload| until
+ * the transmission of extension frame is done (which is indicated by
+ * :type:`nghttp2_on_frame_send_callback`), or transmission fails
+ * (which is indicated by :type:`nghttp2_on_frame_not_send_callback`).
+ * If application does not touch this memory region after packing it
+ * into a wire format, application can free it inside
+ * :type:`nghttp2_pack_extension_callback`.
+ *
+ * The standard HTTP/2 frame cannot be sent with this function, so
+ * |type| must be strictly grater than 0x9. Otherwise, this function
+ * will fail with error code :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`
+ * If :type:`nghttp2_pack_extension_callback` is not set.
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * If |type| specifies standard HTTP/2 frame type. The frame
+ * types in the rage [0x0, 0x9], both inclusive, are standard
+ * HTTP/2 frame type, and cannot be sent using this function.
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory
+ */
+NGHTTP2_EXTERN int nghttp2_submit_extension(nghttp2_session *session,
+ uint8_t type, uint8_t flags,
+ int32_t stream_id, void *payload);
+
+/**
+ * @struct
+ *
+ * The payload of ALTSVC frame. ALTSVC frame is a non-critical
+ * extension to HTTP/2. If this frame is received, and
+ * `nghttp2_option_set_user_recv_extension_type()` is not set, and
+ * `nghttp2_option_set_builtin_recv_extension_type()` is set for
+ * :enum:`NGHTTP2_ALTSVC`, ``nghttp2_extension.payload`` will point to
+ * this struct.
+ *
+ * It has the following members:
+ */
+typedef struct {
+ /**
+ * The pointer to origin which this alternative service is
+ * associated with. This is not necessarily NULL-terminated.
+ */
+ uint8_t *origin;
+ /**
+ * The length of the |origin|.
+ */
+ size_t origin_len;
+ /**
+ * The pointer to Alt-Svc field value contained in ALTSVC frame.
+ * This is not necessarily NULL-terminated.
+ */
+ uint8_t *field_value;
+ /**
+ * The length of the |field_value|.
+ */
+ size_t field_value_len;
+} nghttp2_ext_altsvc;
+
+/**
+ * @function
+ *
+ * Submits ALTSVC frame.
+ *
+ * ALTSVC frame is a non-critical extension to HTTP/2, and defined in
+ * is defined in `RFC 7383
+ * `_.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * The |origin| points to the origin this alternative service is
+ * associated with. The |origin_len| is the length of the origin. If
+ * |stream_id| is 0, the origin must be specified. If |stream_id| is
+ * not zero, the origin must be empty (in other words, |origin_len|
+ * must be 0).
+ *
+ * The ALTSVC frame is only usable from server side. If this function
+ * is invoked with client side session, this function returns
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`
+ * The function is called from client side session
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The sum of |origin_len| and |field_value_len| is larger than
+ * 16382; or |origin_len| is 0 while |stream_id| is 0; or
+ * |origin_len| is not 0 while |stream_id| is not 0.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_altsvc(nghttp2_session *session,
+ uint8_t flags, int32_t stream_id,
+ const uint8_t *origin,
+ size_t origin_len,
+ const uint8_t *field_value,
+ size_t field_value_len);
+
+/**
+ * @function
+ *
+ * Compares ``lhs->name`` of length ``lhs->namelen`` bytes and
+ * ``rhs->name`` of length ``rhs->namelen`` bytes. Returns negative
+ * integer if ``lhs->name`` is found to be less than ``rhs->name``; or
+ * returns positive integer if ``lhs->name`` is found to be greater
+ * than ``rhs->name``; or returns 0 otherwise.
+ */
+NGHTTP2_EXTERN int nghttp2_nv_compare_name(const nghttp2_nv *lhs,
+ const nghttp2_nv *rhs);
+
+/**
+ * @function
+ *
+ * A helper function for dealing with NPN in client side or ALPN in
+ * server side. The |in| contains peer's protocol list in preferable
+ * order. The format of |in| is length-prefixed and not
+ * null-terminated. For example, ``h2`` and
+ * ``http/1.1`` stored in |in| like this::
+ *
+ * in[0] = 2
+ * in[1..2] = "h2"
+ * in[3] = 8
+ * in[4..11] = "http/1.1"
+ * inlen = 12
+ *
+ * The selection algorithm is as follows:
+ *
+ * 1. If peer's list contains HTTP/2 protocol the library supports,
+ * it is selected and returns 1. The following step is not taken.
+ *
+ * 2. If peer's list contains ``http/1.1``, this function selects
+ * ``http/1.1`` and returns 0. The following step is not taken.
+ *
+ * 3. This function selects nothing and returns -1 (So called
+ * non-overlap case). In this case, |out| and |outlen| are left
+ * untouched.
+ *
+ * Selecting ``h2`` means that ``h2`` is written into |*out| and its
+ * length (which is 2) is assigned to |*outlen|.
+ *
+ * For ALPN, refer to https://tools.ietf.org/html/rfc7301
+ *
+ * See http://technotes.googlecode.com/git/nextprotoneg.html for more
+ * details about NPN.
+ *
+ * For NPN, to use this method you should do something like::
+ *
+ * static int select_next_proto_cb(SSL* ssl,
+ * unsigned char **out,
+ * unsigned char *outlen,
+ * const unsigned char *in,
+ * unsigned int inlen,
+ * void *arg)
+ * {
+ * int rv;
+ * rv = nghttp2_select_next_protocol(out, outlen, in, inlen);
+ * if (rv == -1) {
+ * return SSL_TLSEXT_ERR_NOACK;
+ * }
+ * if (rv == 1) {
+ * ((MyType*)arg)->http2_selected = 1;
+ * }
+ * return SSL_TLSEXT_ERR_OK;
+ * }
+ * ...
+ * SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, my_obj);
+ *
+ */
+NGHTTP2_EXTERN int nghttp2_select_next_protocol(unsigned char **out,
+ unsigned char *outlen,
+ const unsigned char *in,
+ unsigned int inlen);
+
+/**
+ * @function
+ *
+ * Returns a pointer to a nghttp2_info struct with version information
+ * about the run-time library in use. The |least_version| argument
+ * can be set to a 24 bit numerical value for the least accepted
+ * version number and if the condition is not met, this function will
+ * return a ``NULL``. Pass in 0 to skip the version checking.
+ */
+NGHTTP2_EXTERN nghttp2_info *nghttp2_version(int least_version);
+
+/**
+ * @function
+ *
+ * Returns nonzero if the :type:`nghttp2_error` library error code
+ * |lib_error| is fatal.
+ */
+NGHTTP2_EXTERN int nghttp2_is_fatal(int lib_error_code);
+
+/**
+ * @function
+ *
+ * Returns nonzero if HTTP header field name |name| of length |len| is
+ * valid according to http://tools.ietf.org/html/rfc7230#section-3.2
+ *
+ * Because this is a header field name in HTTP2, the upper cased alphabet
+ * is treated as error.
+ */
+NGHTTP2_EXTERN int nghttp2_check_header_name(const uint8_t *name, size_t len);
+
+/**
+ * @function
+ *
+ * Returns nonzero if HTTP header field value |value| of length |len|
+ * is valid according to
+ * http://tools.ietf.org/html/rfc7230#section-3.2
+ */
+NGHTTP2_EXTERN int nghttp2_check_header_value(const uint8_t *value, size_t len);
+
+/* HPACK API */
+
+struct nghttp2_hd_deflater;
+
+/**
+ * @struct
+ *
+ * HPACK deflater object.
+ */
+typedef struct nghttp2_hd_deflater nghttp2_hd_deflater;
+
+/**
+ * @function
+ *
+ * Initializes |*deflater_ptr| for deflating name/values pairs.
+ *
+ * The |max_deflate_dynamic_table_size| is the upper bound of header
+ * table size the deflater will use.
+ *
+ * If this function fails, |*deflater_ptr| is left untouched.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int
+nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
+ size_t max_deflate_dynamic_table_size);
+
+/**
+ * @function
+ *
+ * Like `nghttp2_hd_deflate_new()`, but with additional custom memory
+ * allocator specified in the |mem|.
+ *
+ * The |mem| can be ``NULL`` and the call is equivalent to
+ * `nghttp2_hd_deflate_new()`.
+ *
+ * This function does not take ownership |mem|. The application is
+ * responsible for freeing |mem|.
+ *
+ * The library code does not refer to |mem| pointer after this
+ * function returns, so the application can safely free it.
+ */
+NGHTTP2_EXTERN int
+nghttp2_hd_deflate_new2(nghttp2_hd_deflater **deflater_ptr,
+ size_t max_deflate_dynamic_table_size,
+ nghttp2_mem *mem);
+
+/**
+ * @function
+ *
+ * Deallocates any resources allocated for |deflater|.
+ */
+NGHTTP2_EXTERN void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater);
+
+/**
+ * @function
+ *
+ * Changes header table size of the |deflater| to
+ * |settings_max_dynamic_table_size| bytes. This may trigger eviction
+ * in the dynamic table.
+ *
+ * The |settings_max_dynamic_table_size| should be the value received
+ * in SETTINGS_HEADER_TABLE_SIZE.
+ *
+ * The deflater never uses more memory than
+ * ``max_deflate_dynamic_table_size`` bytes specified in
+ * `nghttp2_hd_deflate_new()`. Therefore, if
+ * |settings_max_dynamic_table_size| >
+ * ``max_deflate_dynamic_table_size``, resulting maximum table size
+ * becomes ``max_deflate_dynamic_table_size``.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int
+nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
+ size_t settings_max_dynamic_table_size);
+
+/**
+ * @function
+ *
+ * Deflates the |nva|, which has the |nvlen| name/value pairs, into
+ * the |buf| of length |buflen|.
+ *
+ * If |buf| is not large enough to store the deflated header block,
+ * this function fails with :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`. The
+ * caller should use `nghttp2_hd_deflate_bound()` to know the upper
+ * bound of buffer size required to deflate given header name/value
+ * pairs.
+ *
+ * Once this function fails, subsequent call of this function always
+ * returns :enum:`NGHTTP2_ERR_HEADER_COMP`.
+ *
+ * After this function returns, it is safe to delete the |nva|.
+ *
+ * This function returns the number of bytes written to |buf| if it
+ * succeeds, or one of the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_HEADER_COMP`
+ * Deflation process has failed.
+ * :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`
+ * The provided |buflen| size is too small to hold the output.
+ */
+NGHTTP2_EXTERN ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
+ uint8_t *buf, size_t buflen,
+ const nghttp2_nv *nva,
+ size_t nvlen);
+
+/**
+ * @function
+ *
+ * Deflates the |nva|, which has the |nvlen| name/value pairs, into
+ * the |veclen| size of buf vector |vec|. The each size of buffer
+ * must be set in len field of :type:`nghttp2_vec`. If and only if
+ * one chunk is filled up completely, next chunk will be used. If
+ * |vec| is not large enough to store the deflated header block, this
+ * function fails with :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`. The caller
+ * should use `nghttp2_hd_deflate_bound()` to know the upper bound of
+ * buffer size required to deflate given header name/value pairs.
+ *
+ * Once this function fails, subsequent call of this function always
+ * returns :enum:`NGHTTP2_ERR_HEADER_COMP`.
+ *
+ * After this function returns, it is safe to delete the |nva|.
+ *
+ * This function returns the number of bytes written to |vec| if it
+ * succeeds, or one of the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_HEADER_COMP`
+ * Deflation process has failed.
+ * :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`
+ * The provided |buflen| size is too small to hold the output.
+ */
+NGHTTP2_EXTERN ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater,
+ const nghttp2_vec *vec,
+ size_t veclen,
+ const nghttp2_nv *nva,
+ size_t nvlen);
+
+/**
+ * @function
+ *
+ * Returns an upper bound on the compressed size after deflation of
+ * |nva| of length |nvlen|.
+ */
+NGHTTP2_EXTERN size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
+ const nghttp2_nv *nva,
+ size_t nvlen);
+
+/**
+ * @function
+ *
+ * Returns the number of entries that header table of |deflater|
+ * contains. This is the sum of the number of static table and
+ * dynamic table, so the return value is at least 61.
+ */
+NGHTTP2_EXTERN
+size_t nghttp2_hd_deflate_get_num_table_entries(nghttp2_hd_deflater *deflater);
+
+/**
+ * @function
+ *
+ * Returns the table entry denoted by |idx| from header table of
+ * |deflater|. The |idx| is 1-based, and idx=1 returns first entry of
+ * static table. idx=62 returns first entry of dynamic table if it
+ * exists. Specifying idx=0 is error, and this function returns NULL.
+ * If |idx| is strictly greater than the number of entries the tables
+ * contain, this function returns NULL.
+ */
+NGHTTP2_EXTERN
+const nghttp2_nv *
+nghttp2_hd_deflate_get_table_entry(nghttp2_hd_deflater *deflater, size_t idx);
+
+/**
+ * @function
+ *
+ * Returns the used dynamic table size, including the overhead 32
+ * bytes per entry described in RFC 7541.
+ */
+NGHTTP2_EXTERN
+size_t nghttp2_hd_deflate_get_dynamic_table_size(nghttp2_hd_deflater *deflater);
+
+/**
+ * @function
+ *
+ * Returns the maximum dynamic table size.
+ */
+NGHTTP2_EXTERN
+size_t
+nghttp2_hd_deflate_get_max_dynamic_table_size(nghttp2_hd_deflater *deflater);
+
+struct nghttp2_hd_inflater;
+
+/**
+ * @struct
+ *
+ * HPACK inflater object.
+ */
+typedef struct nghttp2_hd_inflater nghttp2_hd_inflater;
+
+/**
+ * @function
+ *
+ * Initializes |*inflater_ptr| for inflating name/values pairs.
+ *
+ * If this function fails, |*inflater_ptr| is left untouched.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+NGHTTP2_EXTERN int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr);
+
+/**
+ * @function
+ *
+ * Like `nghttp2_hd_inflate_new()`, but with additional custom memory
+ * allocator specified in the |mem|.
+ *
+ * The |mem| can be ``NULL`` and the call is equivalent to
+ * `nghttp2_hd_inflate_new()`.
+ *
+ * This function does not take ownership |mem|. The application is
+ * responsible for freeing |mem|.
+ *
+ * The library code does not refer to |mem| pointer after this
+ * function returns, so the application can safely free it.
+ */
+NGHTTP2_EXTERN int nghttp2_hd_inflate_new2(nghttp2_hd_inflater **inflater_ptr,
+ nghttp2_mem *mem);
+
+/**
+ * @function
+ *
+ * Deallocates any resources allocated for |inflater|.
+ */
+NGHTTP2_EXTERN void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater);
+
+/**
+ * @function
+ *
+ * Changes header table size in the |inflater|. This may trigger
+ * eviction in the dynamic table.
+ *
+ * The |settings_max_dynamic_table_size| should be the value
+ * transmitted in SETTINGS_HEADER_TABLE_SIZE.
+ *
+ * This function must not be called while header block is being
+ * inflated. In other words, this function must be called after
+ * initialization of |inflater|, but before calling
+ * `nghttp2_hd_inflate_hd2()`, or after
+ * `nghttp2_hd_inflate_end_headers()`. Otherwise,
+ * `NGHTTP2_ERR_INVALID_STATE` was returned.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`
+ * The function is called while header block is being inflated.
+ * Probably, application missed to call
+ * `nghttp2_hd_inflate_end_headers()`.
+ */
+NGHTTP2_EXTERN int
+nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
+ size_t settings_max_dynamic_table_size);
+
+/**
+ * @enum
+ *
+ * The flags for header inflation.
+ */
+typedef enum {
+ /**
+ * No flag set.
+ */
+ NGHTTP2_HD_INFLATE_NONE = 0,
+ /**
+ * Indicates all headers were inflated.
+ */
+ NGHTTP2_HD_INFLATE_FINAL = 0x01,
+ /**
+ * Indicates a header was emitted.
+ */
+ NGHTTP2_HD_INFLATE_EMIT = 0x02
+} nghttp2_hd_inflate_flag;
+
+/**
+ * @function
+ *
+ * .. warning::
+ *
+ * Deprecated. Use `nghttp2_hd_inflate_hd2()` instead.
+ *
+ * Inflates name/value block stored in |in| with length |inlen|. This
+ * function performs decompression. For each successful emission of
+ * header name/value pair, :enum:`NGHTTP2_HD_INFLATE_EMIT` is set in
+ * |*inflate_flags| and name/value pair is assigned to the |nv_out|
+ * and the function returns. The caller must not free the members of
+ * |nv_out|.
+ *
+ * The |nv_out| may include pointers to the memory region in the |in|.
+ * The caller must retain the |in| while the |nv_out| is used.
+ *
+ * The application should call this function repeatedly until the
+ * ``(*inflate_flags) & NGHTTP2_HD_INFLATE_FINAL`` is nonzero and
+ * return value is non-negative. This means the all input values are
+ * processed successfully. Then the application must call
+ * `nghttp2_hd_inflate_end_headers()` to prepare for the next header
+ * block input.
+ *
+ * The caller can feed complete compressed header block. It also can
+ * feed it in several chunks. The caller must set |in_final| to
+ * nonzero if the given input is the last block of the compressed
+ * header.
+ *
+ * This function returns the number of bytes processed if it succeeds,
+ * or one of the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_HEADER_COMP`
+ * Inflation process has failed.
+ * :enum:`NGHTTP2_ERR_BUFFER_ERROR`
+ * The header field name or value is too large.
+ *
+ * Example follows::
+ *
+ * int inflate_header_block(nghttp2_hd_inflater *hd_inflater,
+ * uint8_t *in, size_t inlen, int final)
+ * {
+ * ssize_t rv;
+ *
+ * for(;;) {
+ * nghttp2_nv nv;
+ * int inflate_flags = 0;
+ *
+ * rv = nghttp2_hd_inflate_hd(hd_inflater, &nv, &inflate_flags,
+ * in, inlen, final);
+ *
+ * if(rv < 0) {
+ * fprintf(stderr, "inflate failed with error code %zd", rv);
+ * return -1;
+ * }
+ *
+ * in += rv;
+ * inlen -= rv;
+ *
+ * if(inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
+ * fwrite(nv.name, nv.namelen, 1, stderr);
+ * fprintf(stderr, ": ");
+ * fwrite(nv.value, nv.valuelen, 1, stderr);
+ * fprintf(stderr, "\n");
+ * }
+ * if(inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
+ * nghttp2_hd_inflate_end_headers(hd_inflater);
+ * break;
+ * }
+ * if((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 &&
+ * inlen == 0) {
+ * break;
+ * }
+ * }
+ *
+ * return 0;
+ * }
+ *
+ */
+NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
+ nghttp2_nv *nv_out,
+ int *inflate_flags, uint8_t *in,
+ size_t inlen, int in_final);
+
+/**
+ * @function
+ *
+ * Inflates name/value block stored in |in| with length |inlen|. This
+ * function performs decompression. For each successful emission of
+ * header name/value pair, :enum:`NGHTTP2_HD_INFLATE_EMIT` is set in
+ * |*inflate_flags| and name/value pair is assigned to the |nv_out|
+ * and the function returns. The caller must not free the members of
+ * |nv_out|.
+ *
+ * The |nv_out| may include pointers to the memory region in the |in|.
+ * The caller must retain the |in| while the |nv_out| is used.
+ *
+ * The application should call this function repeatedly until the
+ * ``(*inflate_flags) & NGHTTP2_HD_INFLATE_FINAL`` is nonzero and
+ * return value is non-negative. If that happens, all given input
+ * data (|inlen| bytes) are processed successfully. Then the
+ * application must call `nghttp2_hd_inflate_end_headers()` to prepare
+ * for the next header block input.
+ *
+ * In other words, if |in_final| is nonzero, and this function returns
+ * |inlen|, you can assert that :enum:`NGHTTP2_HD_INFLATE_FINAL` is
+ * set in |*inflate_flags|.
+ *
+ * The caller can feed complete compressed header block. It also can
+ * feed it in several chunks. The caller must set |in_final| to
+ * nonzero if the given input is the last block of the compressed
+ * header.
+ *
+ * This function returns the number of bytes processed if it succeeds,
+ * or one of the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_HEADER_COMP`
+ * Inflation process has failed.
+ * :enum:`NGHTTP2_ERR_BUFFER_ERROR`
+ * The header field name or value is too large.
+ *
+ * Example follows::
+ *
+ * int inflate_header_block(nghttp2_hd_inflater *hd_inflater,
+ * uint8_t *in, size_t inlen, int final)
+ * {
+ * ssize_t rv;
+ *
+ * for(;;) {
+ * nghttp2_nv nv;
+ * int inflate_flags = 0;
+ *
+ * rv = nghttp2_hd_inflate_hd2(hd_inflater, &nv, &inflate_flags,
+ * in, inlen, final);
+ *
+ * if(rv < 0) {
+ * fprintf(stderr, "inflate failed with error code %zd", rv);
+ * return -1;
+ * }
+ *
+ * in += rv;
+ * inlen -= rv;
+ *
+ * if(inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
+ * fwrite(nv.name, nv.namelen, 1, stderr);
+ * fprintf(stderr, ": ");
+ * fwrite(nv.value, nv.valuelen, 1, stderr);
+ * fprintf(stderr, "\n");
+ * }
+ * if(inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
+ * nghttp2_hd_inflate_end_headers(hd_inflater);
+ * break;
+ * }
+ * if((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 &&
+ * inlen == 0) {
+ * break;
+ * }
+ * }
+ *
+ * return 0;
+ * }
+ *
+ */
+NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
+ nghttp2_nv *nv_out,
+ int *inflate_flags,
+ const uint8_t *in, size_t inlen,
+ int in_final);
+
+/**
+ * @function
+ *
+ * Signals the end of decompression for one header block.
+ *
+ * This function returns 0 if it succeeds. Currently this function
+ * always succeeds.
+ */
+NGHTTP2_EXTERN int
+nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater);
+
+/**
+ * @function
+ *
+ * Returns the number of entries that header table of |inflater|
+ * contains. This is the sum of the number of static table and
+ * dynamic table, so the return value is at least 61.
+ */
+NGHTTP2_EXTERN
+size_t nghttp2_hd_inflate_get_num_table_entries(nghttp2_hd_inflater *inflater);
+
+/**
+ * @function
+ *
+ * Returns the table entry denoted by |idx| from header table of
+ * |inflater|. The |idx| is 1-based, and idx=1 returns first entry of
+ * static table. idx=62 returns first entry of dynamic table if it
+ * exists. Specifying idx=0 is error, and this function returns NULL.
+ * If |idx| is strictly greater than the number of entries the tables
+ * contain, this function returns NULL.
+ */
+NGHTTP2_EXTERN
+const nghttp2_nv *
+nghttp2_hd_inflate_get_table_entry(nghttp2_hd_inflater *inflater, size_t idx);
+
+/**
+ * @function
+ *
+ * Returns the used dynamic table size, including the overhead 32
+ * bytes per entry described in RFC 7541.
+ */
+NGHTTP2_EXTERN
+size_t nghttp2_hd_inflate_get_dynamic_table_size(nghttp2_hd_inflater *inflater);
+
+/**
+ * @function
+ *
+ * Returns the maximum dynamic table size.
+ */
+NGHTTP2_EXTERN
+size_t
+nghttp2_hd_inflate_get_max_dynamic_table_size(nghttp2_hd_inflater *inflater);
+
+struct nghttp2_stream;
+
+/**
+ * @struct
+ *
+ * The structure to represent HTTP/2 stream. The details of this
+ * structure are intentionally hidden from the public API.
+ */
+typedef struct nghttp2_stream nghttp2_stream;
+
+/**
+ * @function
+ *
+ * Returns pointer to :type:`nghttp2_stream` object denoted by
+ * |stream_id|. If stream was not found, returns NULL.
+ *
+ * Returns imaginary root stream (see
+ * `nghttp2_session_get_root_stream()`) if 0 is given in |stream_id|.
+ *
+ * Unless |stream_id| == 0, the returned pointer is valid until next
+ * call of `nghttp2_session_send()`, `nghttp2_session_mem_send()`,
+ * `nghttp2_session_recv()`, and `nghttp2_session_mem_recv()`.
+ */
+NGHTTP2_EXTERN nghttp2_stream *
+nghttp2_session_find_stream(nghttp2_session *session, int32_t stream_id);
+
+/**
+ * @enum
+ *
+ * State of stream as described in RFC 7540.
+ */
+typedef enum {
+ /**
+ * idle state.
+ */
+ NGHTTP2_STREAM_STATE_IDLE = 1,
+ /**
+ * open state.
+ */
+ NGHTTP2_STREAM_STATE_OPEN,
+ /**
+ * reserved (local) state.
+ */
+ NGHTTP2_STREAM_STATE_RESERVED_LOCAL,
+ /**
+ * reserved (remote) state.
+ */
+ NGHTTP2_STREAM_STATE_RESERVED_REMOTE,
+ /**
+ * half closed (local) state.
+ */
+ NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL,
+ /**
+ * half closed (remote) state.
+ */
+ NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE,
+ /**
+ * closed state.
+ */
+ NGHTTP2_STREAM_STATE_CLOSED
+} nghttp2_stream_proto_state;
+
+/**
+ * @function
+ *
+ * Returns state of |stream|. The root stream retrieved by
+ * `nghttp2_session_get_root_stream()` will have stream state
+ * :enum:`NGHTTP2_STREAM_STATE_IDLE`.
+ */
+NGHTTP2_EXTERN nghttp2_stream_proto_state
+nghttp2_stream_get_state(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns root of dependency tree, which is imaginary stream with
+ * stream ID 0. The returned pointer is valid until |session| is
+ * freed by `nghttp2_session_del()`.
+ */
+NGHTTP2_EXTERN nghttp2_stream *
+nghttp2_session_get_root_stream(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the parent stream of |stream| in dependency tree. Returns
+ * NULL if there is no such stream.
+ */
+NGHTTP2_EXTERN nghttp2_stream *
+nghttp2_stream_get_parent(nghttp2_stream *stream);
+
+NGHTTP2_EXTERN int32_t nghttp2_stream_get_stream_id(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns the next sibling stream of |stream| in dependency tree.
+ * Returns NULL if there is no such stream.
+ */
+NGHTTP2_EXTERN nghttp2_stream *
+nghttp2_stream_get_next_sibling(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns the previous sibling stream of |stream| in dependency tree.
+ * Returns NULL if there is no such stream.
+ */
+NGHTTP2_EXTERN nghttp2_stream *
+nghttp2_stream_get_previous_sibling(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns the first child stream of |stream| in dependency tree.
+ * Returns NULL if there is no such stream.
+ */
+NGHTTP2_EXTERN nghttp2_stream *
+nghttp2_stream_get_first_child(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns dependency weight to the parent stream of |stream|.
+ */
+NGHTTP2_EXTERN int32_t nghttp2_stream_get_weight(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns the sum of the weight for |stream|'s children.
+ */
+NGHTTP2_EXTERN int32_t
+nghttp2_stream_get_sum_dependency_weight(nghttp2_stream *stream);
+
+/**
+ * @functypedef
+ *
+ * Callback function invoked when the library outputs debug logging.
+ * The function is called with arguments suitable for ``vfprintf(3)``
+ *
+ * The debug output is only enabled if the library is built with
+ * ``DEBUGBUILD`` macro defined.
+ */
+typedef void (*nghttp2_debug_vprintf_callback)(const char *format,
+ va_list args);
+
+/**
+ * @function
+ *
+ * Sets a debug output callback called by the library when built with
+ * ``DEBUGBUILD`` macro defined. If this option is not used, debug
+ * log is written into standard error output.
+ *
+ * For builds without ``DEBUGBUILD`` macro defined, this function is
+ * noop.
+ *
+ * Note that building with ``DEBUGBUILD`` may cause significant
+ * performance penalty to libnghttp2 because of extra processing. It
+ * should be used for debugging purpose only.
+ *
+ * .. Warning::
+ *
+ * Building with ``DEBUGBUILD`` may cause significant performance
+ * penalty to libnghttp2 because of extra processing. It should be
+ * used for debugging purpose only. We write this two times because
+ * this is important.
+ */
+NGHTTP2_EXTERN void nghttp2_set_debug_vprintf_callback(
+ nghttp2_debug_vprintf_callback debug_vprintf_callback);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NGHTTP2_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_buf.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_buf.c
new file mode 100644
index 00000000..b40d5672
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_buf.c
@@ -0,0 +1,506 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_buf.h"
+
+#include
+
+#include "nghttp2_helper.h"
+#include "nghttp2_debug.h"
+
+void nghttp2_buf_init(nghttp2_buf *buf) {
+ buf->begin = NULL;
+ buf->end = NULL;
+ buf->pos = NULL;
+ buf->last = NULL;
+ buf->mark = NULL;
+}
+
+int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial, nghttp2_mem *mem) {
+ nghttp2_buf_init(buf);
+ return nghttp2_buf_reserve(buf, initial, mem);
+}
+
+void nghttp2_buf_free(nghttp2_buf *buf, nghttp2_mem *mem) {
+ if (buf == NULL) {
+ return;
+ }
+
+ nghttp2_mem_free(mem, buf->begin);
+ buf->begin = NULL;
+}
+
+int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap, nghttp2_mem *mem) {
+ uint8_t *ptr;
+ size_t cap;
+
+ cap = nghttp2_buf_cap(buf);
+
+ if (cap >= new_cap) {
+ return 0;
+ }
+
+ new_cap = nghttp2_max(new_cap, cap * 2);
+
+ ptr = nghttp2_mem_realloc(mem, buf->begin, new_cap);
+ if (ptr == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ buf->pos = ptr + (buf->pos - buf->begin);
+ buf->last = ptr + (buf->last - buf->begin);
+ buf->mark = ptr + (buf->mark - buf->begin);
+ buf->begin = ptr;
+ buf->end = ptr + new_cap;
+
+ return 0;
+}
+
+void nghttp2_buf_reset(nghttp2_buf *buf) {
+ buf->pos = buf->last = buf->mark = buf->begin;
+}
+
+void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len) {
+ buf->begin = buf->pos = buf->last = buf->mark = begin;
+ buf->end = begin + len;
+}
+
+static int buf_chain_new(nghttp2_buf_chain **chain, size_t chunk_length,
+ nghttp2_mem *mem) {
+ int rv;
+
+ *chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain));
+ if (*chain == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ (*chain)->next = NULL;
+
+ rv = nghttp2_buf_init2(&(*chain)->buf, chunk_length, mem);
+ if (rv != 0) {
+ nghttp2_mem_free(mem, *chain);
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ return 0;
+}
+
+static void buf_chain_del(nghttp2_buf_chain *chain, nghttp2_mem *mem) {
+ nghttp2_buf_free(&chain->buf, mem);
+ nghttp2_mem_free(mem, chain);
+}
+
+int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, size_t max_chunk,
+ nghttp2_mem *mem) {
+ return nghttp2_bufs_init2(bufs, chunk_length, max_chunk, 0, mem);
+}
+
+int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length,
+ size_t max_chunk, size_t offset, nghttp2_mem *mem) {
+ return nghttp2_bufs_init3(bufs, chunk_length, max_chunk, max_chunk, offset,
+ mem);
+}
+
+int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length,
+ size_t max_chunk, size_t chunk_keep, size_t offset,
+ nghttp2_mem *mem) {
+ int rv;
+ nghttp2_buf_chain *chain;
+
+ if (chunk_keep == 0 || max_chunk < chunk_keep || chunk_length < offset) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ rv = buf_chain_new(&chain, chunk_length, mem);
+ if (rv != 0) {
+ return rv;
+ }
+
+ bufs->mem = mem;
+ bufs->offset = offset;
+
+ bufs->head = chain;
+ bufs->cur = bufs->head;
+
+ nghttp2_buf_shift_right(&bufs->cur->buf, offset);
+
+ bufs->chunk_length = chunk_length;
+ bufs->chunk_used = 1;
+ bufs->max_chunk = max_chunk;
+ bufs->chunk_keep = chunk_keep;
+
+ return 0;
+}
+
+int nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length) {
+ int rv;
+ nghttp2_buf_chain *chain;
+
+ if (chunk_length < bufs->offset) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ rv = buf_chain_new(&chain, chunk_length, bufs->mem);
+ if (rv != 0) {
+ return rv;
+ }
+
+ nghttp2_bufs_free(bufs);
+
+ bufs->head = chain;
+ bufs->cur = bufs->head;
+
+ nghttp2_buf_shift_right(&bufs->cur->buf, bufs->offset);
+
+ bufs->chunk_length = chunk_length;
+ bufs->chunk_used = 1;
+
+ return 0;
+}
+
+void nghttp2_bufs_free(nghttp2_bufs *bufs) {
+ nghttp2_buf_chain *chain, *next_chain;
+
+ if (bufs == NULL) {
+ return;
+ }
+
+ for (chain = bufs->head; chain;) {
+ next_chain = chain->next;
+
+ buf_chain_del(chain, bufs->mem);
+
+ chain = next_chain;
+ }
+
+ bufs->head = NULL;
+}
+
+int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
+ nghttp2_mem *mem) {
+ nghttp2_buf_chain *chain;
+
+ chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain));
+ if (chain == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ chain->next = NULL;
+
+ nghttp2_buf_wrap_init(&chain->buf, begin, len);
+
+ bufs->mem = mem;
+ bufs->offset = 0;
+
+ bufs->head = chain;
+ bufs->cur = bufs->head;
+
+ bufs->chunk_length = len;
+ bufs->chunk_used = 1;
+ bufs->max_chunk = 1;
+ bufs->chunk_keep = 1;
+
+ return 0;
+}
+
+int nghttp2_bufs_wrap_init2(nghttp2_bufs *bufs, const nghttp2_vec *vec,
+ size_t veclen, nghttp2_mem *mem) {
+ size_t i = 0;
+ nghttp2_buf_chain *cur_chain;
+ nghttp2_buf_chain *head_chain;
+ nghttp2_buf_chain **dst_chain = &head_chain;
+
+ if (veclen == 0) {
+ return nghttp2_bufs_wrap_init(bufs, NULL, 0, mem);
+ }
+
+ head_chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain) * veclen);
+ if (head_chain == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ for (i = 0; i < veclen; ++i) {
+ cur_chain = &head_chain[i];
+ cur_chain->next = NULL;
+ nghttp2_buf_wrap_init(&cur_chain->buf, vec[i].base, vec[i].len);
+
+ *dst_chain = cur_chain;
+ dst_chain = &cur_chain->next;
+ }
+
+ bufs->mem = mem;
+ bufs->offset = 0;
+
+ bufs->head = head_chain;
+ bufs->cur = bufs->head;
+
+ /* We don't use chunk_length since no allocation is expected. */
+ bufs->chunk_length = 0;
+ bufs->chunk_used = veclen;
+ bufs->max_chunk = veclen;
+ bufs->chunk_keep = veclen;
+
+ return 0;
+}
+
+void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs) {
+ if (bufs == NULL) {
+ return;
+ }
+
+ if (bufs->head) {
+ nghttp2_mem_free(bufs->mem, bufs->head);
+ }
+}
+
+void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs) {
+ nghttp2_buf_chain *ci;
+
+ for (ci = bufs->cur; ci; ci = ci->next) {
+ if (nghttp2_buf_len(&ci->buf) == 0) {
+ return;
+ } else {
+ bufs->cur = ci;
+ }
+ }
+}
+
+size_t nghttp2_bufs_len(nghttp2_bufs *bufs) {
+ nghttp2_buf_chain *ci;
+ size_t len;
+
+ len = 0;
+ for (ci = bufs->head; ci; ci = ci->next) {
+ len += nghttp2_buf_len(&ci->buf);
+ }
+
+ return len;
+}
+
+static int bufs_alloc_chain(nghttp2_bufs *bufs) {
+ int rv;
+ nghttp2_buf_chain *chain;
+
+ if (bufs->cur->next) {
+ bufs->cur = bufs->cur->next;
+
+ return 0;
+ }
+
+ if (bufs->max_chunk == bufs->chunk_used) {
+ return NGHTTP2_ERR_BUFFER_ERROR;
+ }
+
+ rv = buf_chain_new(&chain, bufs->chunk_length, bufs->mem);
+ if (rv != 0) {
+ return rv;
+ }
+
+ DEBUGF("new buffer %zu bytes allocated for bufs %p, used %zu\n",
+ bufs->chunk_length, bufs, bufs->chunk_used);
+
+ ++bufs->chunk_used;
+
+ bufs->cur->next = chain;
+ bufs->cur = chain;
+
+ nghttp2_buf_shift_right(&bufs->cur->buf, bufs->offset);
+
+ return 0;
+}
+
+int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len) {
+ int rv;
+ size_t nwrite;
+ nghttp2_buf *buf;
+ const uint8_t *p;
+
+ p = data;
+
+ while (len) {
+ buf = &bufs->cur->buf;
+
+ nwrite = nghttp2_min(nghttp2_buf_avail(buf), len);
+ if (nwrite == 0) {
+ rv = bufs_alloc_chain(bufs);
+ if (rv != 0) {
+ return rv;
+ }
+ continue;
+ }
+
+ buf->last = nghttp2_cpymem(buf->last, p, nwrite);
+ p += nwrite;
+ len -= nwrite;
+ }
+
+ return 0;
+}
+
+static int bufs_ensure_addb(nghttp2_bufs *bufs) {
+ int rv;
+ nghttp2_buf *buf;
+
+ buf = &bufs->cur->buf;
+
+ if (nghttp2_buf_avail(buf) > 0) {
+ return 0;
+ }
+
+ rv = bufs_alloc_chain(bufs);
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+}
+
+int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b) {
+ int rv;
+
+ rv = bufs_ensure_addb(bufs);
+ if (rv != 0) {
+ return rv;
+ }
+
+ *bufs->cur->buf.last++ = b;
+
+ return 0;
+}
+
+int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b) {
+ int rv;
+
+ rv = bufs_ensure_addb(bufs);
+ if (rv != 0) {
+ return rv;
+ }
+
+ *bufs->cur->buf.last = b;
+
+ return 0;
+}
+
+int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b) {
+ int rv;
+
+ rv = bufs_ensure_addb(bufs);
+ if (rv != 0) {
+ return rv;
+ }
+
+ *bufs->cur->buf.last++ |= b;
+
+ return 0;
+}
+
+int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b) {
+ int rv;
+
+ rv = bufs_ensure_addb(bufs);
+ if (rv != 0) {
+ return rv;
+ }
+
+ *bufs->cur->buf.last |= b;
+
+ return 0;
+}
+
+ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
+ size_t len;
+ nghttp2_buf_chain *chain;
+ nghttp2_buf *buf;
+ uint8_t *res;
+ nghttp2_buf resbuf;
+
+ len = 0;
+
+ for (chain = bufs->head; chain; chain = chain->next) {
+ len += nghttp2_buf_len(&chain->buf);
+ }
+
+ if (len == 0) {
+ res = NULL;
+ return 0;
+ }
+
+ res = nghttp2_mem_malloc(bufs->mem, len);
+ if (res == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ nghttp2_buf_wrap_init(&resbuf, res, len);
+
+ for (chain = bufs->head; chain; chain = chain->next) {
+ buf = &chain->buf;
+ resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf));
+ }
+
+ *out = res;
+
+ return (ssize_t)len;
+}
+
+size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out) {
+ size_t len;
+ nghttp2_buf_chain *chain;
+ nghttp2_buf *buf;
+ nghttp2_buf resbuf;
+
+ len = nghttp2_bufs_len(bufs);
+
+ nghttp2_buf_wrap_init(&resbuf, out, len);
+
+ for (chain = bufs->head; chain; chain = chain->next) {
+ buf = &chain->buf;
+ resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf));
+ }
+
+ return len;
+}
+
+void nghttp2_bufs_reset(nghttp2_bufs *bufs) {
+ nghttp2_buf_chain *chain, *ci;
+ size_t k;
+
+ k = bufs->chunk_keep;
+
+ for (ci = bufs->head; ci; ci = ci->next) {
+ nghttp2_buf_reset(&ci->buf);
+ nghttp2_buf_shift_right(&ci->buf, bufs->offset);
+
+ if (--k == 0) {
+ break;
+ }
+ }
+
+ if (ci) {
+ chain = ci->next;
+ ci->next = NULL;
+
+ for (ci = chain; ci;) {
+ chain = ci->next;
+
+ buf_chain_del(ci, bufs->mem);
+
+ ci = chain;
+ }
+
+ bufs->chunk_used = bufs->chunk_keep;
+ }
+
+ bufs->cur = bufs->head;
+}
+
+int nghttp2_bufs_advance(nghttp2_bufs *bufs) { return bufs_alloc_chain(bufs); }
+
+int nghttp2_bufs_next_present(nghttp2_bufs *bufs) {
+ nghttp2_buf_chain *chain;
+
+ chain = bufs->cur->next;
+
+ return chain && nghttp2_buf_len(&chain->buf);
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_buf.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_buf.h
new file mode 100644
index 00000000..7e33a528
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_buf.h
@@ -0,0 +1,393 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_BUF_H
+#define NGHTTP2_BUF_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+#include "nghttp2_int.h"
+#include "nghttp2_mem.h"
+
+typedef struct {
+ /* This points to the beginning of the buffer. The effective range
+ of buffer is [begin, end). */
+ uint8_t *begin;
+ /* This points to the memory one byte beyond the end of the
+ buffer. */
+ uint8_t *end;
+ /* The position indicator for effective start of the buffer. pos <=
+ last must be hold. */
+ uint8_t *pos;
+ /* The position indicator for effective one beyond of the end of the
+ buffer. last <= end must be hold. */
+ uint8_t *last;
+ /* Mark arbitrary position in buffer [begin, end) */
+ uint8_t *mark;
+} nghttp2_buf;
+
+#define nghttp2_buf_len(BUF) ((size_t)((BUF)->last - (BUF)->pos))
+#define nghttp2_buf_avail(BUF) ((size_t)((BUF)->end - (BUF)->last))
+#define nghttp2_buf_mark_avail(BUF) ((size_t)((BUF)->mark - (BUF)->last))
+#define nghttp2_buf_cap(BUF) ((size_t)((BUF)->end - (BUF)->begin))
+
+#define nghttp2_buf_pos_offset(BUF) ((size_t)((BUF)->pos - (BUF)->begin))
+#define nghttp2_buf_last_offset(BUF) ((size_t)((BUF)->last - (BUF)->begin))
+
+#define nghttp2_buf_shift_right(BUF, AMT) \
+ do { \
+ (BUF)->pos += AMT; \
+ (BUF)->last += AMT; \
+ } while (0)
+
+#define nghttp2_buf_shift_left(BUF, AMT) \
+ do { \
+ (BUF)->pos -= AMT; \
+ (BUF)->last -= AMT; \
+ } while (0)
+
+/*
+ * Initializes the |buf|. No memory is allocated in this function. Use
+ * nghttp2_buf_reserve() to allocate memory.
+ */
+void nghttp2_buf_init(nghttp2_buf *buf);
+
+/*
+ * Initializes the |buf| and allocates at least |initial| bytes of
+ * memory.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial, nghttp2_mem *mem);
+
+/*
+ * Frees buffer in |buf|.
+ */
+void nghttp2_buf_free(nghttp2_buf *buf, nghttp2_mem *mem);
+
+/*
+ * Extends buffer so that nghttp2_buf_cap() returns at least
+ * |new_cap|. If extensions took place, buffer pointers in |buf| will
+ * change.
+ *
+ * This function returns 0 if it succeeds, or one of the followings
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap, nghttp2_mem *mem);
+
+/*
+ * Resets pos, last, mark member of |buf| to buf->begin.
+ */
+void nghttp2_buf_reset(nghttp2_buf *buf);
+
+/*
+ * Initializes |buf| using supplied buffer |begin| of length
+ * |len|. Semantically, the application should not call *_reserve() or
+ * nghttp2_free() functions for |buf|.
+ */
+void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len);
+
+struct nghttp2_buf_chain;
+
+typedef struct nghttp2_buf_chain nghttp2_buf_chain;
+
+/* Chains 2 buffers */
+struct nghttp2_buf_chain {
+ /* Points to the subsequent buffer. NULL if there is no such
+ buffer. */
+ nghttp2_buf_chain *next;
+ nghttp2_buf buf;
+};
+
+typedef struct {
+ /* Points to the first buffer */
+ nghttp2_buf_chain *head;
+ /* Buffer pointer where write occurs. */
+ nghttp2_buf_chain *cur;
+ /* Memory allocator */
+ nghttp2_mem *mem;
+ /* The buffer capacity of each buf. This field may be 0 if
+ nghttp2_bufs is initialized by nghttp2_bufs_wrap_init* family
+ functions. */
+ size_t chunk_length;
+ /* The maximum number of nghttp2_buf_chain */
+ size_t max_chunk;
+ /* The number of nghttp2_buf_chain allocated */
+ size_t chunk_used;
+ /* The number of nghttp2_buf_chain to keep on reset */
+ size_t chunk_keep;
+ /* pos offset from begin in each buffers. On initialization and
+ reset, buf->pos and buf->last are positioned at buf->begin +
+ offset. */
+ size_t offset;
+} nghttp2_bufs;
+
+/*
+ * This is the same as calling nghttp2_bufs_init2 with the given
+ * arguments and offset = 0.
+ */
+int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, size_t max_chunk,
+ nghttp2_mem *mem);
+
+/*
+ * This is the same as calling nghttp2_bufs_init3 with the given
+ * arguments and chunk_keep = max_chunk.
+ */
+int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length,
+ size_t max_chunk, size_t offset, nghttp2_mem *mem);
+
+/*
+ * Initializes |bufs|. Each buffer size is given in the
+ * |chunk_length|. The maximum number of buffers is given in the
+ * |max_chunk|. On reset, first |chunk_keep| buffers are kept and
+ * remaining buffers are deleted. Each buffer will have bufs->pos and
+ * bufs->last shifted to left by |offset| bytes on creation and reset.
+ *
+ * This function allocates first buffer. bufs->head and bufs->cur
+ * will point to the first buffer after this call.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_INVALID_ARGUMENT
+ * chunk_keep is 0; or max_chunk < chunk_keep; or offset is too
+ * long.
+ */
+int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length,
+ size_t max_chunk, size_t chunk_keep, size_t offset,
+ nghttp2_mem *mem);
+
+/*
+ * Frees any related resources to the |bufs|.
+ */
+void nghttp2_bufs_free(nghttp2_bufs *bufs);
+
+/*
+ * Initializes |bufs| using supplied buffer |begin| of length |len|.
+ * The first buffer bufs->head uses buffer |begin|. The buffer size
+ * is fixed and no extra chunk buffer is allocated. In other
+ * words, max_chunk = chunk_keep = 1. To free the resource allocated
+ * for |bufs|, use nghttp2_bufs_wrap_free().
+ *
+ * Don't use the function which performs allocation, such as
+ * nghttp2_bufs_realloc().
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
+ nghttp2_mem *mem);
+
+/*
+ * Initializes |bufs| using supplied |veclen| size of buf vector
+ * |vec|. The number of buffers is fixed and no extra chunk buffer is
+ * allocated. In other words, max_chunk = chunk_keep = |in_len|. To
+ * free the resource allocated for |bufs|, use
+ * nghttp2_bufs_wrap_free().
+ *
+ * Don't use the function which performs allocation, such as
+ * nghttp2_bufs_realloc().
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_bufs_wrap_init2(nghttp2_bufs *bufs, const nghttp2_vec *vec,
+ size_t veclen, nghttp2_mem *mem);
+
+/*
+ * Frees any related resource to the |bufs|. This function does not
+ * free supplied buffer provided in nghttp2_bufs_wrap_init().
+ */
+void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs);
+
+/*
+ * Reallocates internal buffer using |chunk_length|. The max_chunk,
+ * chunk_keep and offset do not change. After successful allocation
+ * of new buffer, previous buffers are deallocated without copying
+ * anything into new buffers. chunk_used is reset to 1.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_INVALID_ARGUMENT
+ * chunk_length < offset
+ */
+int nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length);
+
+/*
+ * Appends the |data| of length |len| to the |bufs|. The write starts
+ * at bufs->cur->buf.last. A new buffers will be allocated to store
+ * all data.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_BUFFER_ERROR
+ * Out of buffer space.
+ */
+int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len);
+
+/*
+ * Appends a single byte |b| to the |bufs|. The write starts at
+ * bufs->cur->buf.last. A new buffers will be allocated to store all
+ * data.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_BUFFER_ERROR
+ * Out of buffer space.
+ */
+int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b);
+
+/*
+ * Behaves like nghttp2_bufs_addb(), but this does not update
+ * buf->last pointer.
+ */
+int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b);
+
+#define nghttp2_bufs_fast_addb(BUFS, B) \
+ do { \
+ *(BUFS)->cur->buf.last++ = B; \
+ } while (0)
+
+#define nghttp2_bufs_fast_addb_hold(BUFS, B) \
+ do { \
+ *(BUFS)->cur->buf.last = B; \
+ } while (0)
+
+/*
+ * Performs bitwise-OR of |b| at bufs->cur->buf.last. A new buffers
+ * will be allocated if necessary.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_BUFFER_ERROR
+ * Out of buffer space.
+ */
+int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b);
+
+/*
+ * Behaves like nghttp2_bufs_orb(), but does not update buf->last
+ * pointer.
+ */
+int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
+
+#define nghttp2_bufs_fast_orb(BUFS, B) \
+ do { \
+ uint8_t **p = &(BUFS)->cur->buf.last; \
+ **p = (uint8_t)(**p | (B)); \
+ ++(*p); \
+ } while (0)
+
+#define nghttp2_bufs_fast_orb_hold(BUFS, B) \
+ do { \
+ uint8_t *p = (BUFS)->cur->buf.last; \
+ *p = (uint8_t)(*p | (B)); \
+ } while (0)
+
+/*
+ * Copies all data stored in |bufs| to the contiguous buffer. This
+ * function allocates the contiguous memory to store all data in
+ * |bufs| and assigns it to |*out|.
+ *
+ * The contents of |bufs| is left unchanged.
+ *
+ * This function returns the length of copied data and assigns the
+ * pointer to copied data to |*out| if it succeeds, or one of the
+ * following negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out);
+
+/*
+ * Copies all data stored in |bufs| to |out|. This function assumes
+ * that the buffer space pointed by |out| has at least
+ * nghttp2_bufs(bufs) bytes.
+ *
+ * The contents of |bufs| is left unchanged.
+ *
+ * This function returns the length of copied data.
+ */
+size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out);
+
+/*
+ * Resets |bufs| and makes the buffers empty.
+ */
+void nghttp2_bufs_reset(nghttp2_bufs *bufs);
+
+/*
+ * Moves bufs->cur to bufs->cur->next. If resulting bufs->cur is
+ * NULL, this function allocates new buffers and bufs->cur points to
+ * it.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ * NGHTTP2_ERR_BUFFER_ERROR
+ * Out of buffer space.
+ */
+int nghttp2_bufs_advance(nghttp2_bufs *bufs);
+
+/* Sets bufs->cur to bufs->head */
+#define nghttp2_bufs_rewind(BUFS) \
+ do { \
+ (BUFS)->cur = (BUFS)->head; \
+ } while (0)
+
+/*
+ * Move bufs->cur, from the current position, using next member, to
+ * the last buf which has nghttp2_buf_len(buf) > 0 without seeing buf
+ * which satisfies nghttp2_buf_len(buf) == 0. If
+ * nghttp2_buf_len(&bufs->cur->buf) == 0 or bufs->cur->next is NULL,
+ * bufs->cur is unchanged.
+ */
+void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs);
+
+/*
+ * Returns nonzero if bufs->cur->next is not empty.
+ */
+int nghttp2_bufs_next_present(nghttp2_bufs *bufs);
+
+#define nghttp2_bufs_cur_avail(BUFS) nghttp2_buf_avail(&(BUFS)->cur->buf)
+
+/*
+ * Returns the total buffer length of |bufs|.
+ */
+size_t nghttp2_bufs_len(nghttp2_bufs *bufs);
+
+#endif /* NGHTTP2_BUF_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_callbacks.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_callbacks.c
new file mode 100644
index 00000000..a2f7e3fb
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_callbacks.c
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_callbacks.h"
+#include
+#include
+#ifdef INFRA_MEM_STATS
+#include "infra_mem_stats.h"
+#endif
+
+extern void *HAL_Malloc(uint32_t size);
+extern void *HAL_Realloc(void *ptr, uint32_t size);
+extern void HAL_Free(void *ptr);
+
+#if INFRA_MEM_STATS
+#define NGHTTP2_CB_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "nghttp2.cb")
+#define NGHTTP2_CB_FREE(ptr) LITE_free(ptr)
+#else
+#define NGHTTP2_CB_MALLOC(size) HAL_Malloc(size)
+#define NGHTTP2_CB_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+int nghttp2_session_callbacks_new(nghttp2_session_callbacks **callbacks_ptr) {
+ *callbacks_ptr = NGHTTP2_CB_MALLOC(sizeof(nghttp2_session_callbacks));
+
+ if (*callbacks_ptr == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ memset(*callbacks_ptr, 0, sizeof(nghttp2_session_callbacks));
+ return 0;
+}
+
+void nghttp2_session_callbacks_del(nghttp2_session_callbacks *callbacks) {
+ NGHTTP2_CB_FREE(callbacks);
+}
+
+void nghttp2_session_callbacks_set_send_callback(
+ nghttp2_session_callbacks *cbs, nghttp2_send_callback send_callback) {
+ cbs->send_callback = send_callback;
+}
+
+void nghttp2_session_callbacks_set_recv_callback(
+ nghttp2_session_callbacks *cbs, nghttp2_recv_callback recv_callback) {
+ cbs->recv_callback = recv_callback;
+}
+
+void nghttp2_session_callbacks_set_on_frame_recv_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_frame_recv_callback on_frame_recv_callback) {
+ cbs->on_frame_recv_callback = on_frame_recv_callback;
+}
+
+void nghttp2_session_callbacks_set_on_invalid_frame_recv_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback) {
+ cbs->on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
+}
+
+void nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback) {
+ cbs->on_data_chunk_recv_callback = on_data_chunk_recv_callback;
+}
+
+void nghttp2_session_callbacks_set_before_frame_send_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_before_frame_send_callback before_frame_send_callback) {
+ cbs->before_frame_send_callback = before_frame_send_callback;
+}
+
+void nghttp2_session_callbacks_set_on_frame_send_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_frame_send_callback on_frame_send_callback) {
+ cbs->on_frame_send_callback = on_frame_send_callback;
+}
+
+void nghttp2_session_callbacks_set_on_frame_not_send_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_frame_not_send_callback on_frame_not_send_callback) {
+ cbs->on_frame_not_send_callback = on_frame_not_send_callback;
+}
+
+void nghttp2_session_callbacks_set_on_stream_close_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_stream_close_callback on_stream_close_callback) {
+ cbs->on_stream_close_callback = on_stream_close_callback;
+}
+
+void nghttp2_session_callbacks_set_on_begin_headers_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_begin_headers_callback on_begin_headers_callback) {
+ cbs->on_begin_headers_callback = on_begin_headers_callback;
+}
+
+void nghttp2_session_callbacks_set_on_header_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_header_callback on_header_callback) {
+ cbs->on_header_callback = on_header_callback;
+}
+
+void nghttp2_session_callbacks_set_on_header_callback2(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_header_callback2 on_header_callback2) {
+ cbs->on_header_callback2 = on_header_callback2;
+}
+
+void nghttp2_session_callbacks_set_on_invalid_header_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_invalid_header_callback on_invalid_header_callback) {
+ cbs->on_invalid_header_callback = on_invalid_header_callback;
+}
+
+void nghttp2_session_callbacks_set_on_invalid_header_callback2(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_invalid_header_callback2 on_invalid_header_callback2) {
+ cbs->on_invalid_header_callback2 = on_invalid_header_callback2;
+}
+
+void nghttp2_session_callbacks_set_select_padding_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_select_padding_callback select_padding_callback) {
+ cbs->select_padding_callback = select_padding_callback;
+}
+
+void nghttp2_session_callbacks_set_data_source_read_length_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_data_source_read_length_callback data_source_read_length_callback) {
+ cbs->read_length_callback = data_source_read_length_callback;
+}
+
+void nghttp2_session_callbacks_set_on_begin_frame_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_begin_frame_callback on_begin_frame_callback) {
+ cbs->on_begin_frame_callback = on_begin_frame_callback;
+}
+
+void nghttp2_session_callbacks_set_send_data_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_send_data_callback send_data_callback) {
+ cbs->send_data_callback = send_data_callback;
+}
+
+void nghttp2_session_callbacks_set_pack_extension_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_pack_extension_callback pack_extension_callback) {
+ cbs->pack_extension_callback = pack_extension_callback;
+}
+
+void nghttp2_session_callbacks_set_unpack_extension_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_unpack_extension_callback unpack_extension_callback) {
+ cbs->unpack_extension_callback = unpack_extension_callback;
+}
+
+void nghttp2_session_callbacks_set_on_extension_chunk_recv_callback(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback) {
+ cbs->on_extension_chunk_recv_callback = on_extension_chunk_recv_callback;
+}
+
+void nghttp2_session_callbacks_set_error_callback(
+ nghttp2_session_callbacks *cbs, nghttp2_error_callback error_callback) {
+ cbs->error_callback = error_callback;
+}
+
+void nghttp2_session_callbacks_set_error_callback2(
+ nghttp2_session_callbacks *cbs, nghttp2_error_callback2 error_callback2) {
+ cbs->error_callback2 = error_callback2;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_callbacks.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_callbacks.h
new file mode 100644
index 00000000..542df190
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_callbacks.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_CALLBACKS_H
+#define NGHTTP2_CALLBACKS_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+/*
+ * Callback functions.
+ */
+struct nghttp2_session_callbacks {
+ /**
+ * Callback function invoked when the session wants to send data to
+ * the remote peer. This callback is not necessary if the
+ * application uses solely `nghttp2_session_mem_send()` to serialize
+ * data to transmit.
+ */
+ nghttp2_send_callback send_callback;
+ /**
+ * Callback function invoked when the session wants to receive data
+ * from the remote peer. This callback is not necessary if the
+ * application uses solely `nghttp2_session_mem_recv()` to process
+ * received data.
+ */
+ nghttp2_recv_callback recv_callback;
+ /**
+ * Callback function invoked by `nghttp2_session_recv()` when a
+ * frame is received.
+ */
+ nghttp2_on_frame_recv_callback on_frame_recv_callback;
+ /**
+ * Callback function invoked by `nghttp2_session_recv()` when an
+ * invalid non-DATA frame is received.
+ */
+ nghttp2_on_invalid_frame_recv_callback on_invalid_frame_recv_callback;
+ /**
+ * Callback function invoked when a chunk of data in DATA frame is
+ * received.
+ */
+ nghttp2_on_data_chunk_recv_callback on_data_chunk_recv_callback;
+ /**
+ * Callback function invoked before a non-DATA frame is sent.
+ */
+ nghttp2_before_frame_send_callback before_frame_send_callback;
+ /**
+ * Callback function invoked after a frame is sent.
+ */
+ nghttp2_on_frame_send_callback on_frame_send_callback;
+ /**
+ * The callback function invoked when a non-DATA frame is not sent
+ * because of an error.
+ */
+ nghttp2_on_frame_not_send_callback on_frame_not_send_callback;
+ /**
+ * Callback function invoked when the stream is closed.
+ */
+ nghttp2_on_stream_close_callback on_stream_close_callback;
+ /**
+ * Callback function invoked when the reception of header block in
+ * HEADERS or PUSH_PROMISE is started.
+ */
+ nghttp2_on_begin_headers_callback on_begin_headers_callback;
+ /**
+ * Callback function invoked when a header name/value pair is
+ * received.
+ */
+ nghttp2_on_header_callback on_header_callback;
+ nghttp2_on_header_callback2 on_header_callback2;
+ /**
+ * Callback function invoked when a invalid header name/value pair
+ * is received which is silently ignored if these callbacks are not
+ * set.
+ */
+ nghttp2_on_invalid_header_callback on_invalid_header_callback;
+ nghttp2_on_invalid_header_callback2 on_invalid_header_callback2;
+ /**
+ * Callback function invoked when the library asks application how
+ * many padding bytes are required for the transmission of the given
+ * frame.
+ */
+ nghttp2_select_padding_callback select_padding_callback;
+ /**
+ * The callback function used to determine the length allowed in
+ * `nghttp2_data_source_read_callback()`
+ */
+ nghttp2_data_source_read_length_callback read_length_callback;
+ /**
+ * Sets callback function invoked when a frame header is received.
+ */
+ nghttp2_on_begin_frame_callback on_begin_frame_callback;
+ nghttp2_send_data_callback send_data_callback;
+ nghttp2_pack_extension_callback pack_extension_callback;
+ nghttp2_unpack_extension_callback unpack_extension_callback;
+ nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback;
+ nghttp2_error_callback error_callback;
+ nghttp2_error_callback2 error_callback2;
+};
+
+#endif /* NGHTTP2_CALLBACKS_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_debug.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_debug.c
new file mode 100644
index 00000000..6533f989
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_debug.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_debug.h"
+
+#include
+
+#ifdef DEBUGBUILD
+
+static void nghttp2_default_debug_vfprintf_callback(const char *fmt,
+ va_list args) {
+ vfprintf(stderr, fmt, args);
+}
+
+static nghttp2_debug_vprintf_callback static_debug_vprintf_callback =
+ nghttp2_default_debug_vfprintf_callback;
+
+void nghttp2_debug_vprintf(const char *format, ...) {
+ if (static_debug_vprintf_callback) {
+ va_list args;
+ va_start(args, format);
+ static_debug_vprintf_callback(format, args);
+ va_end(args);
+ }
+}
+
+void nghttp2_set_debug_vprintf_callback(
+ nghttp2_debug_vprintf_callback debug_vprintf_callback) {
+ static_debug_vprintf_callback = debug_vprintf_callback;
+}
+
+#else /* !DEBUGBUILD */
+
+void nghttp2_set_debug_vprintf_callback(
+ nghttp2_debug_vprintf_callback debug_vprintf_callback) {
+ (void)debug_vprintf_callback;
+}
+
+#endif /* !DEBUGBUILD */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_debug.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_debug.h
new file mode 100644
index 00000000..6fed6ea0
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_debug.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_DEBUG_H
+#define NGHTTP2_DEBUG_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+#ifdef DEBUGBUILD
+#define DEBUGF(...) nghttp2_debug_vprintf(__VA_ARGS__)
+void nghttp2_debug_vprintf(const char *format, ...);
+#else
+#define DEBUGF(...) \
+ do { \
+ } while (0)
+#endif
+
+#endif /* NGHTTP2_DEBUG_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_frame.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_frame.c
new file mode 100644
index 00000000..76c919ec
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_frame.c
@@ -0,0 +1,977 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_frame.h"
+
+#include
+#include
+#include
+#include
+
+#include "nghttp2_helper.h"
+#include "nghttp2_net.h"
+#include "nghttp2_priority_spec.h"
+#include "nghttp2_debug.h"
+
+void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd) {
+ nghttp2_put_uint32be(&buf[0], (uint32_t)(hd->length << 8));
+ buf[3] = hd->type;
+ buf[4] = hd->flags;
+ nghttp2_put_uint32be(&buf[5], (uint32_t)hd->stream_id);
+ /* ignore hd->reserved for now */
+}
+
+void nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t *buf) {
+ hd->length = nghttp2_get_uint32(&buf[0]) >> 8;
+ hd->type = buf[3];
+ hd->flags = buf[4];
+ hd->stream_id = nghttp2_get_uint32(&buf[5]) & NGHTTP2_STREAM_ID_MASK;
+ hd->reserved = 0;
+}
+
+void nghttp2_frame_hd_init(nghttp2_frame_hd *hd, size_t length, uint8_t type,
+ uint8_t flags, int32_t stream_id) {
+ hd->length = length;
+ hd->type = type;
+ hd->flags = flags;
+ hd->stream_id = stream_id;
+ hd->reserved = 0;
+}
+
+void nghttp2_frame_headers_init(nghttp2_headers *frame, uint8_t flags,
+ int32_t stream_id, nghttp2_headers_category cat,
+ const nghttp2_priority_spec *pri_spec,
+ nghttp2_nv *nva, size_t nvlen) {
+ nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_HEADERS, flags, stream_id);
+ frame->padlen = 0;
+ frame->nva = nva;
+ frame->nvlen = nvlen;
+ frame->cat = cat;
+
+ if (pri_spec) {
+ frame->pri_spec = *pri_spec;
+ } else {
+ nghttp2_priority_spec_default_init(&frame->pri_spec);
+ }
+}
+
+void nghttp2_frame_headers_free(nghttp2_headers *frame, nghttp2_mem *mem) {
+ nghttp2_nv_array_del(frame->nva, mem);
+}
+
+void nghttp2_frame_priority_init(nghttp2_priority *frame, int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec) {
+ nghttp2_frame_hd_init(&frame->hd, NGHTTP2_PRIORITY_SPECLEN, NGHTTP2_PRIORITY,
+ NGHTTP2_FLAG_NONE, stream_id);
+ frame->pri_spec = *pri_spec;
+}
+
+void nghttp2_frame_priority_free(nghttp2_priority *frame) { (void)frame; }
+
+void nghttp2_frame_rst_stream_init(nghttp2_rst_stream *frame, int32_t stream_id,
+ uint32_t error_code) {
+ nghttp2_frame_hd_init(&frame->hd, 4, NGHTTP2_RST_STREAM, NGHTTP2_FLAG_NONE,
+ stream_id);
+ frame->error_code = error_code;
+}
+
+void nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame) { (void)frame; }
+
+void nghttp2_frame_settings_init(nghttp2_settings *frame, uint8_t flags,
+ nghttp2_settings_entry *iv, size_t niv) {
+ nghttp2_frame_hd_init(&frame->hd, niv * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH,
+ NGHTTP2_SETTINGS, flags, 0);
+ frame->niv = niv;
+ frame->iv = iv;
+}
+
+void nghttp2_frame_settings_free(nghttp2_settings *frame, nghttp2_mem *mem) {
+ nghttp2_mem_free(mem, frame->iv);
+}
+
+void nghttp2_frame_push_promise_init(nghttp2_push_promise *frame, uint8_t flags,
+ int32_t stream_id,
+ int32_t promised_stream_id,
+ nghttp2_nv *nva, size_t nvlen) {
+ nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_PUSH_PROMISE, flags, stream_id);
+ frame->padlen = 0;
+ frame->nva = nva;
+ frame->nvlen = nvlen;
+ frame->promised_stream_id = promised_stream_id;
+ frame->reserved = 0;
+}
+
+void nghttp2_frame_push_promise_free(nghttp2_push_promise *frame,
+ nghttp2_mem *mem) {
+ nghttp2_nv_array_del(frame->nva, mem);
+}
+
+void nghttp2_frame_ping_init(nghttp2_ping *frame, uint8_t flags,
+ const uint8_t *opaque_data) {
+ nghttp2_frame_hd_init(&frame->hd, 8, NGHTTP2_PING, flags, 0);
+ if (opaque_data) {
+ memcpy(frame->opaque_data, opaque_data, sizeof(frame->opaque_data));
+ } else {
+ memset(frame->opaque_data, 0, sizeof(frame->opaque_data));
+ }
+}
+
+void nghttp2_frame_ping_free(nghttp2_ping *frame) { (void)frame; }
+
+void nghttp2_frame_goaway_init(nghttp2_goaway *frame, int32_t last_stream_id,
+ uint32_t error_code, uint8_t *opaque_data,
+ size_t opaque_data_len) {
+ nghttp2_frame_hd_init(&frame->hd, 8 + opaque_data_len, NGHTTP2_GOAWAY,
+ NGHTTP2_FLAG_NONE, 0);
+ frame->last_stream_id = last_stream_id;
+ frame->error_code = error_code;
+ frame->opaque_data = opaque_data;
+ frame->opaque_data_len = opaque_data_len;
+ frame->reserved = 0;
+}
+
+void nghttp2_frame_goaway_free(nghttp2_goaway *frame, nghttp2_mem *mem) {
+ nghttp2_mem_free(mem, frame->opaque_data);
+}
+
+void nghttp2_frame_window_update_init(nghttp2_window_update *frame,
+ uint8_t flags, int32_t stream_id,
+ int32_t window_size_increment) {
+ nghttp2_frame_hd_init(&frame->hd, 4, NGHTTP2_WINDOW_UPDATE, flags, stream_id);
+ frame->window_size_increment = window_size_increment;
+ frame->reserved = 0;
+}
+
+void nghttp2_frame_window_update_free(nghttp2_window_update *frame) {
+ (void)frame;
+}
+
+size_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen) {
+ /* We have iframe->padlen == 0, but iframe->frame.hd.flags may have
+ NGHTTP2_FLAG_PADDED set. This happens when receiving
+ CONTINUATION frame, since we don't reset flags after HEADERS was
+ received. */
+ if (padlen == 0) {
+ return 0;
+ }
+ return padlen - ((frame->hd.flags & NGHTTP2_FLAG_PADDED) > 0);
+}
+
+void nghttp2_frame_data_init(nghttp2_data *frame, uint8_t flags,
+ int32_t stream_id) {
+ /* At this moment, the length of DATA frame is unknown */
+ nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_DATA, flags, stream_id);
+ frame->padlen = 0;
+}
+
+void nghttp2_frame_data_free(nghttp2_data *frame) { (void)frame; }
+
+void nghttp2_frame_extension_init(nghttp2_extension *frame, uint8_t type,
+ uint8_t flags, int32_t stream_id,
+ void *payload) {
+ nghttp2_frame_hd_init(&frame->hd, 0, type, flags, stream_id);
+ frame->payload = payload;
+}
+
+void nghttp2_frame_extension_free(nghttp2_extension *frame) { (void)frame; }
+
+void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id,
+ uint8_t *origin, size_t origin_len,
+ uint8_t *field_value, size_t field_value_len) {
+ nghttp2_ext_altsvc *altsvc;
+
+ nghttp2_frame_hd_init(&frame->hd, 2 + origin_len + field_value_len,
+ NGHTTP2_ALTSVC, NGHTTP2_FLAG_NONE, stream_id);
+
+ altsvc = frame->payload;
+ altsvc->origin = origin;
+ altsvc->origin_len = origin_len;
+ altsvc->field_value = field_value;
+ altsvc->field_value_len = field_value_len;
+}
+
+void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem) {
+ nghttp2_ext_altsvc *altsvc;
+
+ altsvc = frame->payload;
+ /* We use the same buffer for altsvc->origin and
+ altsvc->field_value. */
+ nghttp2_mem_free(mem, altsvc->origin);
+}
+
+size_t nghttp2_frame_priority_len(uint8_t flags) {
+ if (flags & NGHTTP2_FLAG_PRIORITY) {
+ return NGHTTP2_PRIORITY_SPECLEN;
+ }
+
+ return 0;
+}
+
+size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame) {
+ return nghttp2_frame_priority_len(frame->hd.flags);
+}
+
+/*
+ * Call this function after payload was serialized, but not before
+ * changing buf->pos and serializing frame header.
+ *
+ * This function assumes bufs->cur points to the last buf chain of the
+ * frame(s).
+ *
+ * This function serializes frame header for HEADERS/PUSH_PROMISE and
+ * handles their successive CONTINUATION frames.
+ *
+ * We don't process any padding here.
+ */
+static int frame_pack_headers_shared(nghttp2_bufs *bufs,
+ nghttp2_frame_hd *frame_hd) {
+ nghttp2_buf *buf;
+ nghttp2_buf_chain *ci, *ce;
+ nghttp2_frame_hd hd;
+
+ buf = &bufs->head->buf;
+
+ hd = *frame_hd;
+ hd.length = nghttp2_buf_len(buf);
+
+ DEBUGF("send: HEADERS/PUSH_PROMISE, payloadlen=%zu\n", hd.length);
+
+ /* We have multiple frame buffers, which means one or more
+ CONTINUATION frame is involved. Remove END_HEADERS flag from the
+ first frame. */
+ if (bufs->head != bufs->cur) {
+ hd.flags = (uint8_t)(hd.flags & ~NGHTTP2_FLAG_END_HEADERS);
+ }
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+ nghttp2_frame_pack_frame_hd(buf->pos, &hd);
+
+ if (bufs->head != bufs->cur) {
+ /* 2nd and later frames are CONTINUATION frames. */
+ hd.type = NGHTTP2_CONTINUATION;
+ /* We don't have no flags except for last CONTINUATION */
+ hd.flags = NGHTTP2_FLAG_NONE;
+
+ ce = bufs->cur;
+
+ for (ci = bufs->head->next; ci != ce; ci = ci->next) {
+ buf = &ci->buf;
+
+ hd.length = nghttp2_buf_len(buf);
+
+ DEBUGF("send: int CONTINUATION, payloadlen=%zu\n", hd.length);
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+ nghttp2_frame_pack_frame_hd(buf->pos, &hd);
+ }
+
+ buf = &ci->buf;
+ hd.length = nghttp2_buf_len(buf);
+ /* Set END_HEADERS flag for last CONTINUATION */
+ hd.flags = NGHTTP2_FLAG_END_HEADERS;
+
+ DEBUGF("send: last CONTINUATION, payloadlen=%zu\n", hd.length);
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+ nghttp2_frame_pack_frame_hd(buf->pos, &hd);
+ }
+
+ return 0;
+}
+
+int nghttp2_frame_pack_headers(nghttp2_bufs *bufs, nghttp2_headers *frame,
+ nghttp2_hd_deflater *deflater) {
+ size_t nv_offset;
+ int rv;
+ nghttp2_buf *buf;
+
+ assert(bufs->head == bufs->cur);
+
+ nv_offset = nghttp2_frame_headers_payload_nv_offset(frame);
+
+ buf = &bufs->cur->buf;
+
+ buf->pos += nv_offset;
+ buf->last = buf->pos;
+
+ /* This call will adjust buf->last to the correct position */
+ rv = nghttp2_hd_deflate_hd_bufs(deflater, bufs, frame->nva, frame->nvlen);
+
+ if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
+ rv = NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ buf->pos -= nv_offset;
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ if (frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
+ nghttp2_frame_pack_priority_spec(buf->pos, &frame->pri_spec);
+ }
+
+ frame->padlen = 0;
+ frame->hd.length = nghttp2_bufs_len(bufs);
+
+ return frame_pack_headers_shared(bufs, &frame->hd);
+}
+
+void nghttp2_frame_pack_priority_spec(uint8_t *buf,
+ const nghttp2_priority_spec *pri_spec) {
+ nghttp2_put_uint32be(buf, (uint32_t)pri_spec->stream_id);
+ if (pri_spec->exclusive) {
+ buf[0] |= 0x80;
+ }
+ buf[4] = (uint8_t)(pri_spec->weight - 1);
+}
+
+void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec,
+ const uint8_t *payload) {
+ int32_t dep_stream_id;
+ uint8_t exclusive;
+ int32_t weight;
+
+ dep_stream_id = nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
+ exclusive = (payload[0] & 0x80) > 0;
+ weight = payload[4] + 1;
+
+ nghttp2_priority_spec_init(pri_spec, dep_stream_id, weight, exclusive);
+}
+
+int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
+ const uint8_t *payload) {
+ if (frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
+ nghttp2_frame_unpack_priority_spec(&frame->pri_spec, payload);
+ } else {
+ nghttp2_priority_spec_default_init(&frame->pri_spec);
+ }
+
+ frame->nva = NULL;
+ frame->nvlen = 0;
+
+ return 0;
+}
+
+int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame) {
+ nghttp2_buf *buf;
+
+ assert(bufs->head == bufs->cur);
+
+ buf = &bufs->head->buf;
+
+ assert(nghttp2_buf_avail(buf) >= NGHTTP2_PRIORITY_SPECLEN);
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+
+ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
+
+ nghttp2_frame_pack_priority_spec(buf->last, &frame->pri_spec);
+
+ buf->last += NGHTTP2_PRIORITY_SPECLEN;
+
+ return 0;
+}
+
+void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
+ const uint8_t *payload) {
+ nghttp2_frame_unpack_priority_spec(&frame->pri_spec, payload);
+}
+
+int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
+ nghttp2_rst_stream *frame) {
+ nghttp2_buf *buf;
+
+ assert(bufs->head == bufs->cur);
+
+ buf = &bufs->head->buf;
+
+ assert(nghttp2_buf_avail(buf) >= 4);
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+
+ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
+
+ nghttp2_put_uint32be(buf->last, frame->error_code);
+ buf->last += 4;
+
+ return 0;
+}
+
+void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
+ const uint8_t *payload) {
+ frame->error_code = nghttp2_get_uint32(payload);
+}
+
+int nghttp2_frame_pack_settings(nghttp2_bufs *bufs, nghttp2_settings *frame) {
+ nghttp2_buf *buf;
+
+ assert(bufs->head == bufs->cur);
+
+ buf = &bufs->head->buf;
+
+ if (nghttp2_buf_avail(buf) < frame->hd.length) {
+ return NGHTTP2_ERR_FRAME_SIZE_ERROR;
+ }
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+
+ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
+
+ buf->last +=
+ nghttp2_frame_pack_settings_payload(buf->last, frame->iv, frame->niv);
+
+ return 0;
+}
+
+size_t nghttp2_frame_pack_settings_payload(uint8_t *buf,
+ const nghttp2_settings_entry *iv,
+ size_t niv) {
+ size_t i;
+ for (i = 0; i < niv; ++i, buf += NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) {
+ nghttp2_put_uint16be(buf, (uint16_t)iv[i].settings_id);
+ nghttp2_put_uint32be(buf + 2, iv[i].value);
+ }
+ return NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH * niv;
+}
+
+void nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame,
+ nghttp2_settings_entry *iv,
+ size_t niv) {
+ frame->iv = iv;
+ frame->niv = niv;
+}
+
+void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv,
+ const uint8_t *payload) {
+ iv->settings_id = nghttp2_get_uint16(&payload[0]);
+ iv->value = nghttp2_get_uint32(&payload[2]);
+}
+
+int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
+ size_t *niv_ptr,
+ const uint8_t *payload,
+ size_t payloadlen,
+ nghttp2_mem *mem) {
+ size_t i;
+
+ *niv_ptr = payloadlen / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH;
+
+ if (*niv_ptr == 0) {
+ *iv_ptr = NULL;
+
+ return 0;
+ }
+
+ *iv_ptr =
+ nghttp2_mem_malloc(mem, (*niv_ptr) * sizeof(nghttp2_settings_entry));
+
+ if (*iv_ptr == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ for (i = 0; i < *niv_ptr; ++i) {
+ size_t off = i * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH;
+ nghttp2_frame_unpack_settings_entry(&(*iv_ptr)[i], &payload[off]);
+ }
+
+ return 0;
+}
+
+int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
+ nghttp2_push_promise *frame,
+ nghttp2_hd_deflater *deflater) {
+ size_t nv_offset = 4;
+ int rv;
+ nghttp2_buf *buf;
+
+ assert(bufs->head == bufs->cur);
+
+ buf = &bufs->cur->buf;
+
+ buf->pos += nv_offset;
+ buf->last = buf->pos;
+
+ /* This call will adjust buf->last to the correct position */
+ rv = nghttp2_hd_deflate_hd_bufs(deflater, bufs, frame->nva, frame->nvlen);
+
+ if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
+ rv = NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ buf->pos -= nv_offset;
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ nghttp2_put_uint32be(buf->pos, (uint32_t)frame->promised_stream_id);
+
+ frame->padlen = 0;
+ frame->hd.length = nghttp2_bufs_len(bufs);
+
+ return frame_pack_headers_shared(bufs, &frame->hd);
+}
+
+int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
+ const uint8_t *payload) {
+ frame->promised_stream_id =
+ nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
+ frame->nva = NULL;
+ frame->nvlen = 0;
+ return 0;
+}
+
+int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame) {
+ nghttp2_buf *buf;
+
+ assert(bufs->head == bufs->cur);
+
+ buf = &bufs->head->buf;
+
+ assert(nghttp2_buf_avail(buf) >= 8);
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+
+ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
+
+ buf->last =
+ nghttp2_cpymem(buf->last, frame->opaque_data, sizeof(frame->opaque_data));
+
+ return 0;
+}
+
+void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
+ const uint8_t *payload) {
+ memcpy(frame->opaque_data, payload, sizeof(frame->opaque_data));
+}
+
+int nghttp2_frame_pack_goaway(nghttp2_bufs *bufs, nghttp2_goaway *frame) {
+ int rv;
+ nghttp2_buf *buf;
+
+ assert(bufs->head == bufs->cur);
+
+ buf = &bufs->head->buf;
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+
+ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
+
+ nghttp2_put_uint32be(buf->last, (uint32_t)frame->last_stream_id);
+ buf->last += 4;
+
+ nghttp2_put_uint32be(buf->last, frame->error_code);
+ buf->last += 4;
+
+ rv = nghttp2_bufs_add(bufs, frame->opaque_data, frame->opaque_data_len);
+
+ if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
+ return NGHTTP2_ERR_FRAME_SIZE_ERROR;
+ }
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+}
+
+void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
+ const uint8_t *payload,
+ uint8_t *var_gift_payload,
+ size_t var_gift_payloadlen) {
+ frame->last_stream_id = nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
+ frame->error_code = nghttp2_get_uint32(payload + 4);
+
+ frame->opaque_data = var_gift_payload;
+ frame->opaque_data_len = var_gift_payloadlen;
+}
+
+int nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame,
+ const uint8_t *payload,
+ size_t payloadlen, nghttp2_mem *mem) {
+ uint8_t *var_gift_payload;
+ size_t var_gift_payloadlen;
+
+ if (payloadlen > 8) {
+ var_gift_payloadlen = payloadlen - 8;
+ } else {
+ var_gift_payloadlen = 0;
+ }
+
+ payloadlen -= var_gift_payloadlen;
+
+ if (!var_gift_payloadlen) {
+ var_gift_payload = NULL;
+ } else {
+ var_gift_payload = nghttp2_mem_malloc(mem, var_gift_payloadlen);
+
+ if (var_gift_payload == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ memcpy(var_gift_payload, payload + 8, var_gift_payloadlen);
+ }
+
+ nghttp2_frame_unpack_goaway_payload(frame, payload, var_gift_payload,
+ var_gift_payloadlen);
+
+ return 0;
+}
+
+int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
+ nghttp2_window_update *frame) {
+ nghttp2_buf *buf;
+
+ assert(bufs->head == bufs->cur);
+
+ buf = &bufs->head->buf;
+
+ assert(nghttp2_buf_avail(buf) >= 4);
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+
+ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
+
+ nghttp2_put_uint32be(buf->last, (uint32_t)frame->window_size_increment);
+ buf->last += 4;
+
+ return 0;
+}
+
+void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
+ const uint8_t *payload) {
+ frame->window_size_increment =
+ nghttp2_get_uint32(payload) & NGHTTP2_WINDOW_SIZE_INCREMENT_MASK;
+}
+
+int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *frame) {
+ int rv;
+ nghttp2_buf *buf;
+ nghttp2_ext_altsvc *altsvc;
+
+ /* This is required with --disable-assert. */
+ (void)rv;
+
+ altsvc = frame->payload;
+
+ buf = &bufs->head->buf;
+
+ assert(nghttp2_buf_avail(buf) >=
+ 2 + altsvc->origin_len + altsvc->field_value_len);
+
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+
+ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
+
+ nghttp2_put_uint16be(buf->last, (uint16_t)altsvc->origin_len);
+ buf->last += 2;
+
+ rv = nghttp2_bufs_add(bufs, altsvc->origin, altsvc->origin_len);
+
+ assert(rv == 0);
+
+ rv = nghttp2_bufs_add(bufs, altsvc->field_value, altsvc->field_value_len);
+
+ assert(rv == 0);
+
+ return 0;
+}
+
+void nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame,
+ size_t origin_len, uint8_t *payload,
+ size_t payloadlen) {
+ nghttp2_ext_altsvc *altsvc;
+ uint8_t *p;
+
+ altsvc = frame->payload;
+ p = payload;
+
+ altsvc->origin = p;
+
+ p += origin_len;
+
+ altsvc->origin_len = origin_len;
+
+ altsvc->field_value = p;
+ altsvc->field_value_len = (size_t)(payload + payloadlen - p);
+}
+
+int nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame,
+ const uint8_t *payload,
+ size_t payloadlen, nghttp2_mem *mem) {
+ uint8_t *buf;
+ size_t origin_len;
+
+ if (payloadlen < 2) {
+ return NGHTTP2_FRAME_SIZE_ERROR;
+ }
+
+ origin_len = nghttp2_get_uint16(payload);
+
+ buf = nghttp2_mem_malloc(mem, payloadlen - 2);
+ if (!buf) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ nghttp2_cpymem(buf, payload + 2, payloadlen - 2);
+
+ nghttp2_frame_unpack_altsvc_payload(frame, origin_len, buf, payloadlen - 2);
+
+ return 0;
+}
+
+nghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
+ size_t niv, nghttp2_mem *mem) {
+ nghttp2_settings_entry *iv_copy;
+ size_t len = niv * sizeof(nghttp2_settings_entry);
+
+ if (len == 0) {
+ return NULL;
+ }
+
+ iv_copy = nghttp2_mem_malloc(mem, len);
+
+ if (iv_copy == NULL) {
+ return NULL;
+ }
+
+ memcpy(iv_copy, iv, len);
+
+ return iv_copy;
+}
+
+int nghttp2_nv_equal(const nghttp2_nv *a, const nghttp2_nv *b) {
+ return a->namelen == b->namelen && a->valuelen == b->valuelen &&
+ memcmp(a->name, b->name, a->namelen) == 0 &&
+ memcmp(a->value, b->value, a->valuelen) == 0;
+}
+
+void nghttp2_nv_array_del(nghttp2_nv *nva, nghttp2_mem *mem) {
+ nghttp2_mem_free(mem, nva);
+}
+
+static int bytes_compar(const uint8_t *a, size_t alen, const uint8_t *b,
+ size_t blen) {
+ int rv;
+
+ if (alen == blen) {
+ return memcmp(a, b, alen);
+ }
+
+ if (alen < blen) {
+ rv = memcmp(a, b, alen);
+
+ if (rv == 0) {
+ return -1;
+ }
+
+ return rv;
+ }
+
+ rv = memcmp(a, b, blen);
+
+ if (rv == 0) {
+ return 1;
+ }
+
+ return rv;
+}
+
+int nghttp2_nv_compare_name(const nghttp2_nv *lhs, const nghttp2_nv *rhs) {
+ return bytes_compar(lhs->name, lhs->namelen, rhs->name, rhs->namelen);
+}
+
+static int nv_compar(const void *lhs, const void *rhs) {
+ const nghttp2_nv *a = (const nghttp2_nv *)lhs;
+ const nghttp2_nv *b = (const nghttp2_nv *)rhs;
+ int rv;
+
+ rv = bytes_compar(a->name, a->namelen, b->name, b->namelen);
+
+ if (rv == 0) {
+ return bytes_compar(a->value, a->valuelen, b->value, b->valuelen);
+ }
+
+ return rv;
+}
+
+void nghttp2_nv_array_sort(nghttp2_nv *nva, size_t nvlen) {
+ qsort(nva, nvlen, sizeof(nghttp2_nv), nv_compar);
+}
+
+int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva,
+ size_t nvlen, nghttp2_mem *mem) {
+ size_t i;
+ uint8_t *data = NULL;
+ size_t buflen = 0;
+ nghttp2_nv *p;
+
+ if (nvlen == 0) {
+ *nva_ptr = NULL;
+
+ return 0;
+ }
+
+ for (i = 0; i < nvlen; ++i) {
+ /* + 1 for null-termination */
+ if ((nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_NAME) == 0) {
+ buflen += nva[i].namelen + 1;
+ }
+ if ((nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_VALUE) == 0) {
+ buflen += nva[i].valuelen + 1;
+ }
+ }
+
+ buflen += sizeof(nghttp2_nv) * nvlen;
+
+ *nva_ptr = nghttp2_mem_malloc(mem, buflen);
+
+ if (*nva_ptr == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ p = *nva_ptr;
+ data = (uint8_t *)(*nva_ptr) + sizeof(nghttp2_nv) * nvlen;
+
+ for (i = 0; i < nvlen; ++i) {
+ p->flags = nva[i].flags;
+
+ if (nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_NAME) {
+ p->name = nva[i].name;
+ p->namelen = nva[i].namelen;
+ } else {
+ if (nva[i].namelen) {
+ memcpy(data, nva[i].name, nva[i].namelen);
+ }
+ p->name = data;
+ p->namelen = nva[i].namelen;
+ data[p->namelen] = '\0';
+ nghttp2_downcase(p->name, p->namelen);
+ data += nva[i].namelen + 1;
+ }
+
+ if (nva[i].flags & NGHTTP2_NV_FLAG_NO_COPY_VALUE) {
+ p->value = nva[i].value;
+ p->valuelen = nva[i].valuelen;
+ } else {
+ if (nva[i].valuelen) {
+ memcpy(data, nva[i].value, nva[i].valuelen);
+ }
+ p->value = data;
+ p->valuelen = nva[i].valuelen;
+ data[p->valuelen] = '\0';
+ data += nva[i].valuelen + 1;
+ }
+
+ ++p;
+ }
+ return 0;
+}
+
+int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv) {
+ size_t i;
+ for (i = 0; i < niv; ++i) {
+ switch (iv[i].settings_id) {
+ case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
+ break;
+ case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
+ break;
+ case NGHTTP2_SETTINGS_ENABLE_PUSH:
+ if (iv[i].value != 0 && iv[i].value != 1) {
+ return 0;
+ }
+ break;
+ case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
+ if (iv[i].value > (uint32_t)NGHTTP2_MAX_WINDOW_SIZE) {
+ return 0;
+ }
+ break;
+ case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
+ if (iv[i].value < NGHTTP2_MAX_FRAME_SIZE_MIN ||
+ iv[i].value > NGHTTP2_MAX_FRAME_SIZE_MAX) {
+ return 0;
+ }
+ break;
+ case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
+ break;
+ }
+ }
+ return 1;
+}
+
+static void frame_set_pad(nghttp2_buf *buf, size_t padlen, int framehd_only) {
+ size_t trail_padlen;
+ size_t newlen;
+
+ DEBUGF("send: padlen=%zu, shift left 1 bytes\n", padlen);
+
+ memmove(buf->pos - 1, buf->pos, NGHTTP2_FRAME_HDLEN);
+
+ --buf->pos;
+
+ buf->pos[4] |= NGHTTP2_FLAG_PADDED;
+
+ newlen = (nghttp2_get_uint32(buf->pos) >> 8) + padlen;
+ nghttp2_put_uint32be(buf->pos, (uint32_t)((newlen << 8) + buf->pos[3]));
+
+ if (framehd_only) {
+ return;
+ }
+
+ trail_padlen = padlen - 1;
+ buf->pos[NGHTTP2_FRAME_HDLEN] = (uint8_t)trail_padlen;
+
+ /* zero out padding */
+ memset(buf->last, 0, trail_padlen);
+ /* extend buffers trail_padlen bytes, since we ate previous padlen -
+ trail_padlen byte(s) */
+ buf->last += trail_padlen;
+}
+
+int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
+ size_t padlen, int framehd_only) {
+ nghttp2_buf *buf;
+
+ if (padlen == 0) {
+ DEBUGF("send: padlen = 0, nothing to do\n");
+
+ return 0;
+ }
+
+ /*
+ * We have arranged bufs like this:
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | |Frame header | Frame payload... :
+ * +-+-----------------+-------------------------------------------+
+ * | |Frame header | Frame payload... :
+ * +-+-----------------+-------------------------------------------+
+ * | |Frame header | Frame payload... :
+ * +-+-----------------+-------------------------------------------+
+ *
+ * We arranged padding so that it is included in the first frame
+ * completely. For padded frame, we are going to adjust buf->pos of
+ * frame which includes padding and serialize (memmove) frame header
+ * in the correct position. Also extends buf->last to include
+ * padding.
+ */
+
+ buf = &bufs->head->buf;
+
+ assert(nghttp2_buf_avail(buf) >= padlen - 1);
+
+ frame_set_pad(buf, padlen, framehd_only);
+
+ hd->length += padlen;
+ hd->flags |= NGHTTP2_FLAG_PADDED;
+
+ DEBUGF("send: final payloadlen=%zu, padlen=%zu\n", hd->length, padlen);
+
+ return 0;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_frame.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_frame.h
new file mode 100644
index 00000000..07aeb8b7
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_frame.h
@@ -0,0 +1,556 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_FRAME_H
+#define NGHTTP2_FRAME_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+#include "nghttp2_hd.h"
+#include "nghttp2_buf.h"
+
+#define NGHTTP2_STREAM_ID_MASK ((1u << 31) - 1)
+#define NGHTTP2_PRI_GROUP_ID_MASK ((1u << 31) - 1)
+#define NGHTTP2_PRIORITY_MASK ((1u << 31) - 1)
+#define NGHTTP2_WINDOW_SIZE_INCREMENT_MASK ((1u << 31) - 1)
+#define NGHTTP2_SETTINGS_ID_MASK ((1 << 24) - 1)
+
+/* The number of bytes of frame header. */
+#define NGHTTP2_FRAME_HDLEN 9
+
+#define NGHTTP2_MAX_FRAME_SIZE_MAX ((1 << 24) - 1)
+#define NGHTTP2_MAX_FRAME_SIZE_MIN (1 << 14)
+
+#define NGHTTP2_MAX_PAYLOADLEN 16384
+/* The one frame buffer length for tranmission. We may use several of
+ them to support CONTINUATION. To account for Pad Length field, we
+ allocate extra 1 byte, which saves extra large memcopying. */
+#define NGHTTP2_FRAMEBUF_CHUNKLEN \
+ (NGHTTP2_FRAME_HDLEN + 1 + NGHTTP2_MAX_PAYLOADLEN)
+
+/* The default length of DATA frame payload. */
+#define NGHTTP2_DATA_PAYLOADLEN NGHTTP2_MAX_FRAME_SIZE_MIN
+
+/* Maximum headers block size to send, calculated using
+ nghttp2_hd_deflate_bound(). This is the default value, and can be
+ overridden by nghttp2_option_set_max_send_header_block_size(). */
+#define NGHTTP2_MAX_HEADERSLEN 65536
+
+/* The number of bytes for each SETTINGS entry */
+#define NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH 6
+
+/* Length of priority related fields in HEADERS/PRIORITY frames */
+#define NGHTTP2_PRIORITY_SPECLEN 5
+
+/* Maximum length of padding in bytes. */
+#define NGHTTP2_MAX_PADLEN 256
+
+/* Union of extension frame payload */
+typedef union {
+ nghttp2_ext_altsvc altsvc;
+} nghttp2_ext_frame_payload;
+
+void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd);
+
+void nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t *buf);
+
+/**
+ * Initializes frame header |hd| with given parameters. Reserved bit
+ * is set to 0.
+ */
+void nghttp2_frame_hd_init(nghttp2_frame_hd *hd, size_t length, uint8_t type,
+ uint8_t flags, int32_t stream_id);
+
+/**
+ * Returns the number of priority field depending on the |flags|. If
+ * |flags| has neither NGHTTP2_FLAG_PRIORITY_GROUP nor
+ * NGHTTP2_FLAG_PRIORITY_DEPENDENCY set, return 0.
+ */
+size_t nghttp2_frame_priority_len(uint8_t flags);
+
+/**
+ * Packs the |pri_spec| in |buf|. This function assumes |buf| has
+ * enough space for serialization.
+ */
+void nghttp2_frame_pack_priority_spec(uint8_t *buf,
+ const nghttp2_priority_spec *pri_spec);
+
+/**
+ * Unpacks the priority specification from payload |payload| of length
+ * |payloadlen| to |pri_spec|. The |flags| is used to determine what
+ * kind of priority specification is in |payload|. This function
+ * assumes the |payload| contains whole priority specification.
+ */
+void nghttp2_frame_unpack_priority_spec(nghttp2_priority_spec *pri_spec,
+ const uint8_t *payload);
+
+/*
+ * Returns the offset from the HEADERS frame payload where the
+ * compressed header block starts. The frame payload does not include
+ * frame header.
+ */
+size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame);
+
+/*
+ * Packs HEADERS frame |frame| in wire format and store it in |bufs|.
+ * This function expands |bufs| as necessary to store frame.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * frame->hd.length is assigned after length is determined during
+ * packing process. CONTINUATION frames are also serialized in this
+ * function. This function does not handle padding.
+ *
+ * This function returns 0 if it succeeds, or returns one of the
+ * following negative error codes:
+ *
+ * NGHTTP2_ERR_HEADER_COMP
+ * The deflate operation failed.
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_frame_pack_headers(nghttp2_bufs *bufs, nghttp2_headers *frame,
+ nghttp2_hd_deflater *deflater);
+
+/*
+ * Unpacks HEADERS frame byte sequence into |frame|. This function
+ * only unapcks bytes that come before name/value header block and
+ * after possible Pad Length field.
+ *
+ * This function always succeeds and returns 0.
+ */
+int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
+ const uint8_t *payload);
+
+/*
+ * Packs PRIORITY frame |frame| in wire format and store it in
+ * |bufs|.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * This function always succeeds and returns 0.
+ */
+int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame);
+
+/*
+ * Unpacks PRIORITY wire format into |frame|.
+ */
+void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
+ const uint8_t *payload);
+
+/*
+ * Packs RST_STREAM frame |frame| in wire frame format and store it in
+ * |bufs|.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * This function always succeeds and returns 0.
+ */
+int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
+ nghttp2_rst_stream *frame);
+
+/*
+ * Unpacks RST_STREAM frame byte sequence into |frame|.
+ */
+void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
+ const uint8_t *payload);
+
+/*
+ * Packs SETTINGS frame |frame| in wire format and store it in
+ * |bufs|.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * This function returns 0 if it succeeds, or returns one of the
+ * following negative error codes:
+ *
+ * NGHTTP2_ERR_FRAME_SIZE_ERROR
+ * The length of the frame is too large.
+ */
+int nghttp2_frame_pack_settings(nghttp2_bufs *bufs, nghttp2_settings *frame);
+
+/*
+ * Packs the |iv|, which includes |niv| entries, in the |buf|,
+ * assuming the |buf| has at least 8 * |niv| bytes.
+ *
+ * Returns the number of bytes written into the |buf|.
+ */
+size_t nghttp2_frame_pack_settings_payload(uint8_t *buf,
+ const nghttp2_settings_entry *iv,
+ size_t niv);
+
+void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv,
+ const uint8_t *payload);
+
+/*
+ * Initializes payload of frame->settings. The |frame| takes
+ * ownership of |iv|.
+ */
+void nghttp2_frame_unpack_settings_payload(nghttp2_settings *frame,
+ nghttp2_settings_entry *iv,
+ size_t niv);
+
+/*
+ * Unpacks SETTINGS payload into |*iv_ptr|. The number of entries are
+ * assigned to the |*niv_ptr|. This function allocates enough memory
+ * to store the result in |*iv_ptr|. The caller is responsible to free
+ * |*iv_ptr| after its use.
+ *
+ * This function returns 0 if it succeeds or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
+ size_t *niv_ptr,
+ const uint8_t *payload,
+ size_t payloadlen, nghttp2_mem *mem);
+
+/*
+ * Packs PUSH_PROMISE frame |frame| in wire format and store it in
+ * |bufs|. This function expands |bufs| as necessary to store
+ * frame.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * frame->hd.length is assigned after length is determined during
+ * packing process. CONTINUATION frames are also serialized in this
+ * function. This function does not handle padding.
+ *
+ * This function returns 0 if it succeeds, or returns one of the
+ * following negative error codes:
+ *
+ * NGHTTP2_ERR_HEADER_COMP
+ * The deflate operation failed.
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
+ nghttp2_push_promise *frame,
+ nghttp2_hd_deflater *deflater);
+
+/*
+ * Unpacks PUSH_PROMISE frame byte sequence into |frame|. This
+ * function only unapcks bytes that come before name/value header
+ * block and after possible Pad Length field.
+ *
+ * This function returns 0 if it succeeds or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_PROTO
+ * TODO END_HEADERS flag is not set
+ */
+int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
+ const uint8_t *payload);
+
+/*
+ * Packs PING frame |frame| in wire format and store it in
+ * |bufs|.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * This function always succeeds and returns 0.
+ */
+int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame);
+
+/*
+ * Unpacks PING wire format into |frame|.
+ */
+void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
+ const uint8_t *payload);
+
+/*
+ * Packs GOAWAY frame |frame| in wire format and store it in |bufs|.
+ * This function expands |bufs| as necessary to store frame.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * This function returns 0 if it succeeds or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_FRAME_SIZE_ERROR
+ * The length of the frame is too large.
+ */
+int nghttp2_frame_pack_goaway(nghttp2_bufs *bufs, nghttp2_goaway *frame);
+
+/*
+ * Unpacks GOAWAY wire format into |frame|. The |payload| of length
+ * |payloadlen| contains first 8 bytes of payload. The
+ * |var_gift_payload| of length |var_gift_payloadlen| contains
+ * remaining payload and its buffer is gifted to the function and then
+ * |frame|. The |var_gift_payloadlen| must be freed by
+ * nghttp2_frame_goaway_free().
+ */
+void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
+ const uint8_t *payload,
+ uint8_t *var_gift_payload,
+ size_t var_gift_payloadlen);
+
+/*
+ * Unpacks GOAWAY wire format into |frame|. This function only exists
+ * for unit test. After allocating buffer for debug data, this
+ * function internally calls nghttp2_frame_unpack_goaway_payload().
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_frame_unpack_goaway_payload2(nghttp2_goaway *frame,
+ const uint8_t *payload,
+ size_t payloadlen, nghttp2_mem *mem);
+
+/*
+ * Packs WINDOW_UPDATE frame |frame| in wire frame format and store it
+ * in |bufs|.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * This function always succeeds and returns 0.
+ */
+int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
+ nghttp2_window_update *frame);
+
+/*
+ * Unpacks WINDOW_UPDATE frame byte sequence into |frame|.
+ */
+void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
+ const uint8_t *payload);
+
+/*
+ * Packs ALTSVC frame |frame| in wire frame format and store it in
+ * |bufs|.
+ *
+ * The caller must make sure that nghttp2_bufs_reset(bufs) is called
+ * before calling this function.
+ *
+ * This function always succeeds and returns 0.
+ */
+int nghttp2_frame_pack_altsvc(nghttp2_bufs *bufs, nghttp2_extension *ext);
+
+/*
+ * Unpacks ALTSVC wire format into |frame|. The |payload| of
+ * |payloadlen| bytes contains frame payload. This function assumes
+ * that frame->payload points to the nghttp2_ext_altsvc object.
+ *
+ * This function always succeeds and returns 0.
+ */
+void nghttp2_frame_unpack_altsvc_payload(nghttp2_extension *frame,
+ size_t origin_len, uint8_t *payload,
+ size_t payloadlen);
+
+/*
+ * Unpacks ALTSVC wire format into |frame|. This function only exists
+ * for unit test. After allocating buffer for fields, this function
+ * internally calls nghttp2_frame_unpack_altsvc_payload().
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_FRAME_SIZE_ERROR
+ * The payload is too small.
+ */
+int nghttp2_frame_unpack_altsvc_payload2(nghttp2_extension *frame,
+ const uint8_t *payload,
+ size_t payloadlen, nghttp2_mem *mem);
+
+/*
+ * Initializes HEADERS frame |frame| with given values. |frame| takes
+ * ownership of |nva|, so caller must not free it. If |stream_id| is
+ * not assigned yet, it must be -1.
+ */
+void nghttp2_frame_headers_init(nghttp2_headers *frame, uint8_t flags,
+ int32_t stream_id, nghttp2_headers_category cat,
+ const nghttp2_priority_spec *pri_spec,
+ nghttp2_nv *nva, size_t nvlen);
+
+void nghttp2_frame_headers_free(nghttp2_headers *frame, nghttp2_mem *mem);
+
+void nghttp2_frame_priority_init(nghttp2_priority *frame, int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec);
+
+void nghttp2_frame_priority_free(nghttp2_priority *frame);
+
+void nghttp2_frame_rst_stream_init(nghttp2_rst_stream *frame, int32_t stream_id,
+ uint32_t error_code);
+
+void nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame);
+
+/*
+ * Initializes PUSH_PROMISE frame |frame| with given values. |frame|
+ * takes ownership of |nva|, so caller must not free it.
+ */
+void nghttp2_frame_push_promise_init(nghttp2_push_promise *frame, uint8_t flags,
+ int32_t stream_id,
+ int32_t promised_stream_id,
+ nghttp2_nv *nva, size_t nvlen);
+
+void nghttp2_frame_push_promise_free(nghttp2_push_promise *frame,
+ nghttp2_mem *mem);
+
+/*
+ * Initializes SETTINGS frame |frame| with given values. |frame| takes
+ * ownership of |iv|, so caller must not free it. The |flags| are
+ * bitwise-OR of one or more of nghttp2_settings_flag.
+ */
+void nghttp2_frame_settings_init(nghttp2_settings *frame, uint8_t flags,
+ nghttp2_settings_entry *iv, size_t niv);
+
+void nghttp2_frame_settings_free(nghttp2_settings *frame, nghttp2_mem *mem);
+
+/*
+ * Initializes PING frame |frame| with given values. If the
+ * |opqeue_data| is not NULL, it must point to 8 bytes memory region
+ * of data. The data pointed by |opaque_data| is copied. It can be
+ * NULL. In this case, 8 bytes NULL is used.
+ */
+void nghttp2_frame_ping_init(nghttp2_ping *frame, uint8_t flags,
+ const uint8_t *opque_data);
+
+void nghttp2_frame_ping_free(nghttp2_ping *frame);
+
+/*
+ * Initializes GOAWAY frame |frame| with given values. On success,
+ * this function takes ownership of |opaque_data|, so caller must not
+ * free it. If the |opaque_data_len| is 0, opaque_data could be NULL.
+ */
+void nghttp2_frame_goaway_init(nghttp2_goaway *frame, int32_t last_stream_id,
+ uint32_t error_code, uint8_t *opaque_data,
+ size_t opaque_data_len);
+
+void nghttp2_frame_goaway_free(nghttp2_goaway *frame, nghttp2_mem *mem);
+
+void nghttp2_frame_window_update_init(nghttp2_window_update *frame,
+ uint8_t flags, int32_t stream_id,
+ int32_t window_size_increment);
+
+void nghttp2_frame_window_update_free(nghttp2_window_update *frame);
+
+void nghttp2_frame_extension_init(nghttp2_extension *frame, uint8_t type,
+ uint8_t flags, int32_t stream_id,
+ void *payload);
+
+void nghttp2_frame_extension_free(nghttp2_extension *frame);
+
+/*
+ * Initializes ALTSVC frame |frame| with given values. This function
+ * assumes that frame->payload points to nghttp2_ext_altsvc object.
+ * Also |origin| and |field_value| are allocated in single buffer,
+ * starting |origin|. On success, this function takes ownership of
+ * |origin|, so caller must not free it.
+ */
+void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id,
+ uint8_t *origin, size_t origin_len,
+ uint8_t *field_value, size_t field_value_len);
+
+/*
+ * Frees up resources under |frame|. This function does not free
+ * nghttp2_ext_altsvc object pointed by frame->payload. This function
+ * only frees origin pointed by nghttp2_ext_altsvc.origin. Therefore,
+ * other fields must be allocated in the same buffer with origin.
+ */
+void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem);
+
+/*
+ * Returns the number of padding bytes after payload. The total
+ * padding length is given in the |padlen|. The returned value does
+ * not include the Pad Length field. If |padlen| is 0, this function
+ * returns 0, regardless of frame->hd.flags.
+ */
+size_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen);
+
+void nghttp2_frame_data_init(nghttp2_data *frame, uint8_t flags,
+ int32_t stream_id);
+
+void nghttp2_frame_data_free(nghttp2_data *frame);
+
+/*
+ * Makes copy of |iv| and return the copy. The |niv| is the number of
+ * entries in |iv|. This function returns the pointer to the copy if
+ * it succeeds, or NULL.
+ */
+nghttp2_settings_entry *nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
+ size_t niv, nghttp2_mem *mem);
+
+/*
+ * Sorts the |nva| in ascending order of name and value. If names are
+ * equivalent, sort them by value.
+ */
+void nghttp2_nv_array_sort(nghttp2_nv *nva, size_t nvlen);
+
+/*
+ * Copies name/value pairs from |nva|, which contains |nvlen| pairs,
+ * to |*nva_ptr|, which is dynamically allocated so that all items can
+ * be stored. The resultant name and value in nghttp2_nv are
+ * guaranteed to be NULL-terminated even if the input is not
+ * null-terminated.
+ *
+ * The |*nva_ptr| must be freed using nghttp2_nv_array_del().
+ *
+ * This function returns 0 if it succeeds or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_nv_array_copy(nghttp2_nv **nva_ptr, const nghttp2_nv *nva,
+ size_t nvlen, nghttp2_mem *mem);
+
+/*
+ * Returns nonzero if the name/value pair |a| equals to |b|. The name
+ * is compared in case-sensitive, because we ensure that this function
+ * is called after the name is lower-cased.
+ */
+int nghttp2_nv_equal(const nghttp2_nv *a, const nghttp2_nv *b);
+
+/*
+ * Frees |nva|.
+ */
+void nghttp2_nv_array_del(nghttp2_nv *nva, nghttp2_mem *mem);
+
+/*
+ * Checks that the |iv|, which includes |niv| entries, does not have
+ * invalid values.
+ *
+ * This function returns nonzero if it succeeds, or 0.
+ */
+int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
+
+/*
+ * Sets Pad Length field and flags and adjusts frame header position
+ * of each buffers in |bufs|. The number of padding is given in the
+ * |padlen| including Pad Length field. The |hd| is the frame header
+ * for the serialized data. This function fills zeros padding region
+ * unless framehd_only is nonzero.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_FRAME_SIZE_ERROR
+ * The length of the resulting frame is too large.
+ */
+int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
+ size_t padlen, int framehd_only);
+
+#endif /* NGHTTP2_FRAME_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd.c
new file mode 100644
index 00000000..d7e80a23
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd.c
@@ -0,0 +1,2317 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_hd.h"
+
+#include
+#include
+#include
+
+#include "nghttp2_helper.h"
+#include "nghttp2_int.h"
+#include "nghttp2_debug.h"
+
+/* Make scalar initialization form of nghttp2_hd_entry */
+#define MAKE_STATIC_ENT(N, V, T, H) \
+ { \
+ {NULL, NULL, (uint8_t *)(N), sizeof((N)) - 1, -1}, \
+ {NULL, NULL, (uint8_t *)(V), sizeof((V)) - 1, -1}, \
+ {(uint8_t *)(N), (uint8_t *)(V), sizeof((N)) - 1, sizeof((V)) - 1, 0}, \
+ T, H \
+ }
+
+/* Generated by mkstatictbl.py */
+/* 3rd parameter is nghttp2_token value for header field name. We use
+ first enum value if same header names are repeated (e.g.,
+ :status). */
+static nghttp2_hd_static_entry static_table[] = {
+ MAKE_STATIC_ENT(":authority", "", 0, 3153725150u),
+ MAKE_STATIC_ENT(":method", "GET", 1, 695666056u),
+ MAKE_STATIC_ENT(":method", "POST", 1, 695666056u),
+ MAKE_STATIC_ENT(":path", "/", 3, 3292848686u),
+ MAKE_STATIC_ENT(":path", "/index.html", 3, 3292848686u),
+ MAKE_STATIC_ENT(":scheme", "http", 5, 2510477674u),
+ MAKE_STATIC_ENT(":scheme", "https", 5, 2510477674u),
+ MAKE_STATIC_ENT(":status", "200", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "204", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "206", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "304", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "400", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "404", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "500", 7, 4000288983u),
+ MAKE_STATIC_ENT("accept-charset", "", 14, 3664010344u),
+ MAKE_STATIC_ENT("accept-encoding", "gzip, deflate", 15, 3379649177u),
+ MAKE_STATIC_ENT("accept-language", "", 16, 1979086614u),
+ MAKE_STATIC_ENT("accept-ranges", "", 17, 1713753958u),
+ MAKE_STATIC_ENT("accept", "", 18, 136609321u),
+ MAKE_STATIC_ENT("access-control-allow-origin", "", 19, 2710797292u),
+ MAKE_STATIC_ENT("age", "", 20, 742476188u),
+ MAKE_STATIC_ENT("allow", "", 21, 2930878514u),
+ MAKE_STATIC_ENT("authorization", "", 22, 2436257726u),
+ MAKE_STATIC_ENT("cache-control", "", 23, 1355326669u),
+ MAKE_STATIC_ENT("content-disposition", "", 24, 3889184348u),
+ MAKE_STATIC_ENT("content-encoding", "", 25, 65203592u),
+ MAKE_STATIC_ENT("content-language", "", 26, 24973587u),
+ MAKE_STATIC_ENT("content-length", "", 27, 1308181789u),
+ MAKE_STATIC_ENT("content-location", "", 28, 2302364718u),
+ MAKE_STATIC_ENT("content-range", "", 29, 3555523146u),
+ MAKE_STATIC_ENT("content-type", "", 30, 4244048277u),
+ MAKE_STATIC_ENT("cookie", "", 31, 2007449791u),
+ MAKE_STATIC_ENT("date", "", 32, 3564297305u),
+ MAKE_STATIC_ENT("etag", "", 33, 113792960u),
+ MAKE_STATIC_ENT("expect", "", 34, 2530896728u),
+ MAKE_STATIC_ENT("expires", "", 35, 1049544579u),
+ MAKE_STATIC_ENT("from", "", 36, 2513272949u),
+ MAKE_STATIC_ENT("host", "", 37, 2952701295u),
+ MAKE_STATIC_ENT("if-match", "", 38, 3597694698u),
+ MAKE_STATIC_ENT("if-modified-since", "", 39, 2213050793u),
+ MAKE_STATIC_ENT("if-none-match", "", 40, 2536202615u),
+ MAKE_STATIC_ENT("if-range", "", 41, 2340978238u),
+ MAKE_STATIC_ENT("if-unmodified-since", "", 42, 3794814858u),
+ MAKE_STATIC_ENT("last-modified", "", 43, 3226950251u),
+ MAKE_STATIC_ENT("link", "", 44, 232457833u),
+ MAKE_STATIC_ENT("location", "", 45, 200649126u),
+ MAKE_STATIC_ENT("max-forwards", "", 46, 1826162134u),
+ MAKE_STATIC_ENT("proxy-authenticate", "", 47, 2709445359u),
+ MAKE_STATIC_ENT("proxy-authorization", "", 48, 2686392507u),
+ MAKE_STATIC_ENT("range", "", 49, 4208725202u),
+ MAKE_STATIC_ENT("referer", "", 50, 3969579366u),
+ MAKE_STATIC_ENT("refresh", "", 51, 3572655668u),
+ MAKE_STATIC_ENT("retry-after", "", 52, 3336180598u),
+ MAKE_STATIC_ENT("server", "", 53, 1085029842u),
+ MAKE_STATIC_ENT("set-cookie", "", 54, 1848371000u),
+ MAKE_STATIC_ENT("strict-transport-security", "", 55, 4138147361u),
+ MAKE_STATIC_ENT("transfer-encoding", "", 56, 3719590988u),
+ MAKE_STATIC_ENT("user-agent", "", 57, 606444526u),
+ MAKE_STATIC_ENT("vary", "", 58, 1085005381u),
+ MAKE_STATIC_ENT("via", "", 59, 1762798611u),
+ MAKE_STATIC_ENT("www-authenticate", "", 60, 779865858u),
+};
+
+static int memeq(const void *s1, const void *s2, size_t n) {
+ return memcmp(s1, s2, n) == 0;
+}
+
+/*
+ * This function was generated by genlibtokenlookup.py. Inspired by
+ * h2o header lookup. https://github.com/h2o/h2o
+ */
+static int32_t lookup_token(const uint8_t *name, size_t namelen) {
+ switch (namelen) {
+ case 2:
+ switch (name[1]) {
+ case 'e':
+ if (memeq("t", name, 1)) {
+ return NGHTTP2_TOKEN_TE;
+ }
+ break;
+ }
+ break;
+ case 3:
+ switch (name[2]) {
+ case 'a':
+ if (memeq("vi", name, 2)) {
+ return NGHTTP2_TOKEN_VIA;
+ }
+ break;
+ case 'e':
+ if (memeq("ag", name, 2)) {
+ return NGHTTP2_TOKEN_AGE;
+ }
+ break;
+ }
+ break;
+ case 4:
+ switch (name[3]) {
+ case 'e':
+ if (memeq("dat", name, 3)) {
+ return NGHTTP2_TOKEN_DATE;
+ }
+ break;
+ case 'g':
+ if (memeq("eta", name, 3)) {
+ return NGHTTP2_TOKEN_ETAG;
+ }
+ break;
+ case 'k':
+ if (memeq("lin", name, 3)) {
+ return NGHTTP2_TOKEN_LINK;
+ }
+ break;
+ case 'm':
+ if (memeq("fro", name, 3)) {
+ return NGHTTP2_TOKEN_FROM;
+ }
+ break;
+ case 't':
+ if (memeq("hos", name, 3)) {
+ return NGHTTP2_TOKEN_HOST;
+ }
+ break;
+ case 'y':
+ if (memeq("var", name, 3)) {
+ return NGHTTP2_TOKEN_VARY;
+ }
+ break;
+ }
+ break;
+ case 5:
+ switch (name[4]) {
+ case 'e':
+ if (memeq("rang", name, 4)) {
+ return NGHTTP2_TOKEN_RANGE;
+ }
+ break;
+ case 'h':
+ if (memeq(":pat", name, 4)) {
+ return NGHTTP2_TOKEN__PATH;
+ }
+ break;
+ case 'w':
+ if (memeq("allo", name, 4)) {
+ return NGHTTP2_TOKEN_ALLOW;
+ }
+ break;
+ }
+ break;
+ case 6:
+ switch (name[5]) {
+ case 'e':
+ if (memeq("cooki", name, 5)) {
+ return NGHTTP2_TOKEN_COOKIE;
+ }
+ break;
+ case 'r':
+ if (memeq("serve", name, 5)) {
+ return NGHTTP2_TOKEN_SERVER;
+ }
+ break;
+ case 't':
+ if (memeq("accep", name, 5)) {
+ return NGHTTP2_TOKEN_ACCEPT;
+ }
+ if (memeq("expec", name, 5)) {
+ return NGHTTP2_TOKEN_EXPECT;
+ }
+ break;
+ }
+ break;
+ case 7:
+ switch (name[6]) {
+ case 'd':
+ if (memeq(":metho", name, 6)) {
+ return NGHTTP2_TOKEN__METHOD;
+ }
+ break;
+ case 'e':
+ if (memeq(":schem", name, 6)) {
+ return NGHTTP2_TOKEN__SCHEME;
+ }
+ if (memeq("upgrad", name, 6)) {
+ return NGHTTP2_TOKEN_UPGRADE;
+ }
+ break;
+ case 'h':
+ if (memeq("refres", name, 6)) {
+ return NGHTTP2_TOKEN_REFRESH;
+ }
+ break;
+ case 'r':
+ if (memeq("refere", name, 6)) {
+ return NGHTTP2_TOKEN_REFERER;
+ }
+ break;
+ case 's':
+ if (memeq(":statu", name, 6)) {
+ return NGHTTP2_TOKEN__STATUS;
+ }
+ if (memeq("expire", name, 6)) {
+ return NGHTTP2_TOKEN_EXPIRES;
+ }
+ break;
+ }
+ break;
+ case 8:
+ switch (name[7]) {
+ case 'e':
+ if (memeq("if-rang", name, 7)) {
+ return NGHTTP2_TOKEN_IF_RANGE;
+ }
+ break;
+ case 'h':
+ if (memeq("if-matc", name, 7)) {
+ return NGHTTP2_TOKEN_IF_MATCH;
+ }
+ break;
+ case 'n':
+ if (memeq("locatio", name, 7)) {
+ return NGHTTP2_TOKEN_LOCATION;
+ }
+ break;
+ }
+ break;
+ case 10:
+ switch (name[9]) {
+ case 'e':
+ if (memeq("keep-aliv", name, 9)) {
+ return NGHTTP2_TOKEN_KEEP_ALIVE;
+ }
+ if (memeq("set-cooki", name, 9)) {
+ return NGHTTP2_TOKEN_SET_COOKIE;
+ }
+ break;
+ case 'n':
+ if (memeq("connectio", name, 9)) {
+ return NGHTTP2_TOKEN_CONNECTION;
+ }
+ break;
+ case 't':
+ if (memeq("user-agen", name, 9)) {
+ return NGHTTP2_TOKEN_USER_AGENT;
+ }
+ break;
+ case 'y':
+ if (memeq(":authorit", name, 9)) {
+ return NGHTTP2_TOKEN__AUTHORITY;
+ }
+ break;
+ }
+ break;
+ case 11:
+ switch (name[10]) {
+ case 'r':
+ if (memeq("retry-afte", name, 10)) {
+ return NGHTTP2_TOKEN_RETRY_AFTER;
+ }
+ break;
+ }
+ break;
+ case 12:
+ switch (name[11]) {
+ case 'e':
+ if (memeq("content-typ", name, 11)) {
+ return NGHTTP2_TOKEN_CONTENT_TYPE;
+ }
+ break;
+ case 's':
+ if (memeq("max-forward", name, 11)) {
+ return NGHTTP2_TOKEN_MAX_FORWARDS;
+ }
+ break;
+ }
+ break;
+ case 13:
+ switch (name[12]) {
+ case 'd':
+ if (memeq("last-modifie", name, 12)) {
+ return NGHTTP2_TOKEN_LAST_MODIFIED;
+ }
+ break;
+ case 'e':
+ if (memeq("content-rang", name, 12)) {
+ return NGHTTP2_TOKEN_CONTENT_RANGE;
+ }
+ break;
+ case 'h':
+ if (memeq("if-none-matc", name, 12)) {
+ return NGHTTP2_TOKEN_IF_NONE_MATCH;
+ }
+ break;
+ case 'l':
+ if (memeq("cache-contro", name, 12)) {
+ return NGHTTP2_TOKEN_CACHE_CONTROL;
+ }
+ break;
+ case 'n':
+ if (memeq("authorizatio", name, 12)) {
+ return NGHTTP2_TOKEN_AUTHORIZATION;
+ }
+ break;
+ case 's':
+ if (memeq("accept-range", name, 12)) {
+ return NGHTTP2_TOKEN_ACCEPT_RANGES;
+ }
+ break;
+ }
+ break;
+ case 14:
+ switch (name[13]) {
+ case 'h':
+ if (memeq("content-lengt", name, 13)) {
+ return NGHTTP2_TOKEN_CONTENT_LENGTH;
+ }
+ break;
+ case 't':
+ if (memeq("accept-charse", name, 13)) {
+ return NGHTTP2_TOKEN_ACCEPT_CHARSET;
+ }
+ break;
+ }
+ break;
+ case 15:
+ switch (name[14]) {
+ case 'e':
+ if (memeq("accept-languag", name, 14)) {
+ return NGHTTP2_TOKEN_ACCEPT_LANGUAGE;
+ }
+ break;
+ case 'g':
+ if (memeq("accept-encodin", name, 14)) {
+ return NGHTTP2_TOKEN_ACCEPT_ENCODING;
+ }
+ break;
+ }
+ break;
+ case 16:
+ switch (name[15]) {
+ case 'e':
+ if (memeq("content-languag", name, 15)) {
+ return NGHTTP2_TOKEN_CONTENT_LANGUAGE;
+ }
+ if (memeq("www-authenticat", name, 15)) {
+ return NGHTTP2_TOKEN_WWW_AUTHENTICATE;
+ }
+ break;
+ case 'g':
+ if (memeq("content-encodin", name, 15)) {
+ return NGHTTP2_TOKEN_CONTENT_ENCODING;
+ }
+ break;
+ case 'n':
+ if (memeq("content-locatio", name, 15)) {
+ return NGHTTP2_TOKEN_CONTENT_LOCATION;
+ }
+ if (memeq("proxy-connectio", name, 15)) {
+ return NGHTTP2_TOKEN_PROXY_CONNECTION;
+ }
+ break;
+ }
+ break;
+ case 17:
+ switch (name[16]) {
+ case 'e':
+ if (memeq("if-modified-sinc", name, 16)) {
+ return NGHTTP2_TOKEN_IF_MODIFIED_SINCE;
+ }
+ break;
+ case 'g':
+ if (memeq("transfer-encodin", name, 16)) {
+ return NGHTTP2_TOKEN_TRANSFER_ENCODING;
+ }
+ break;
+ }
+ break;
+ case 18:
+ switch (name[17]) {
+ case 'e':
+ if (memeq("proxy-authenticat", name, 17)) {
+ return NGHTTP2_TOKEN_PROXY_AUTHENTICATE;
+ }
+ break;
+ }
+ break;
+ case 19:
+ switch (name[18]) {
+ case 'e':
+ if (memeq("if-unmodified-sinc", name, 18)) {
+ return NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE;
+ }
+ break;
+ case 'n':
+ if (memeq("content-dispositio", name, 18)) {
+ return NGHTTP2_TOKEN_CONTENT_DISPOSITION;
+ }
+ if (memeq("proxy-authorizatio", name, 18)) {
+ return NGHTTP2_TOKEN_PROXY_AUTHORIZATION;
+ }
+ break;
+ }
+ break;
+ case 25:
+ switch (name[24]) {
+ case 'y':
+ if (memeq("strict-transport-securit", name, 24)) {
+ return NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY;
+ }
+ break;
+ }
+ break;
+ case 27:
+ switch (name[26]) {
+ case 'n':
+ if (memeq("access-control-allow-origi", name, 26)) {
+ return NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN;
+ }
+ break;
+ }
+ break;
+ }
+ return -1;
+}
+
+void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv) {
+ ent->nv = *nv;
+ ent->cnv.name = nv->name->base;
+ ent->cnv.namelen = nv->name->len;
+ ent->cnv.value = nv->value->base;
+ ent->cnv.valuelen = nv->value->len;
+ ent->cnv.flags = nv->flags;
+ ent->next = NULL;
+ ent->hash = 0;
+
+ nghttp2_rcbuf_incref(ent->nv.name);
+ nghttp2_rcbuf_incref(ent->nv.value);
+}
+
+void nghttp2_hd_entry_free(nghttp2_hd_entry *ent) {
+ nghttp2_rcbuf_decref(ent->nv.value);
+ nghttp2_rcbuf_decref(ent->nv.name);
+}
+
+static int name_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
+ return a->name->len == b->namelen &&
+ memeq(a->name->base, b->name, b->namelen);
+}
+
+static int value_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
+ return a->value->len == b->valuelen &&
+ memeq(a->value->base, b->value, b->valuelen);
+}
+
+static uint32_t name_hash(const nghttp2_nv *nv) {
+ /* 32 bit FNV-1a: http://isthe.com/chongo/tech/comp/fnv/ */
+ uint32_t h = 2166136261u;
+ size_t i;
+
+ for (i = 0; i < nv->namelen; ++i) {
+ h ^= nv->name[i];
+ h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
+ }
+
+ return h;
+}
+
+static void hd_map_init(nghttp2_hd_map *map) {
+ memset(map, 0, sizeof(nghttp2_hd_map));
+}
+
+static void hd_map_insert(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
+ nghttp2_hd_entry **bucket;
+
+ bucket = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
+
+ if (*bucket == NULL) {
+ *bucket = ent;
+ return;
+ }
+
+ /* lower index is linked near the root */
+ ent->next = *bucket;
+ *bucket = ent;
+}
+
+static nghttp2_hd_entry *hd_map_find(nghttp2_hd_map *map, int *exact_match,
+ const nghttp2_nv *nv, int32_t token,
+ uint32_t hash, int name_only) {
+ nghttp2_hd_entry *p;
+ nghttp2_hd_entry *res = NULL;
+
+ *exact_match = 0;
+
+ for (p = map->table[hash & (HD_MAP_SIZE - 1)]; p; p = p->next) {
+ if (token != p->nv.token ||
+ (token == -1 && (hash != p->hash || !name_eq(&p->nv, nv)))) {
+ continue;
+ }
+ if (!res) {
+ res = p;
+ if (name_only) {
+ break;
+ }
+ }
+ if (value_eq(&p->nv, nv)) {
+ res = p;
+ *exact_match = 1;
+ break;
+ }
+ }
+
+ return res;
+}
+
+static void hd_map_remove(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
+ nghttp2_hd_entry **dst;
+
+ dst = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
+
+ for (; *dst; dst = &(*dst)->next) {
+ if (*dst != ent) {
+ continue;
+ }
+
+ *dst = ent->next;
+ ent->next = NULL;
+ return;
+ }
+}
+
+static int hd_ringbuf_init(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
+ nghttp2_mem *mem) {
+ size_t size;
+ for (size = 1; size < bufsize; size <<= 1)
+ ;
+ ringbuf->buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
+ if (ringbuf->buffer == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+ ringbuf->mask = size - 1;
+ ringbuf->first = 0;
+ ringbuf->len = 0;
+ return 0;
+}
+
+static nghttp2_hd_entry *hd_ringbuf_get(nghttp2_hd_ringbuf *ringbuf,
+ size_t idx) {
+ assert(idx < ringbuf->len);
+ return ringbuf->buffer[(ringbuf->first + idx) & ringbuf->mask];
+}
+
+static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
+ nghttp2_mem *mem) {
+ size_t i;
+ size_t size;
+ nghttp2_hd_entry **buffer;
+
+ if (ringbuf->mask + 1 >= bufsize) {
+ return 0;
+ }
+ for (size = 1; size < bufsize; size <<= 1)
+ ;
+ buffer = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size);
+ if (buffer == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+ for (i = 0; i < ringbuf->len; ++i) {
+ buffer[i] = hd_ringbuf_get(ringbuf, i);
+ }
+ nghttp2_mem_free(mem, ringbuf->buffer);
+ ringbuf->buffer = buffer;
+ ringbuf->mask = size - 1;
+ ringbuf->first = 0;
+ return 0;
+}
+
+static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) {
+ size_t i;
+ if (ringbuf == NULL) {
+ return;
+ }
+ for (i = 0; i < ringbuf->len; ++i) {
+ nghttp2_hd_entry *ent = hd_ringbuf_get(ringbuf, i);
+
+ nghttp2_hd_entry_free(ent);
+ nghttp2_mem_free(mem, ent);
+ }
+ nghttp2_mem_free(mem, ringbuf->buffer);
+}
+
+static int hd_ringbuf_push_front(nghttp2_hd_ringbuf *ringbuf,
+ nghttp2_hd_entry *ent, nghttp2_mem *mem) {
+ int rv;
+
+ rv = hd_ringbuf_reserve(ringbuf, ringbuf->len + 1, mem);
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ ringbuf->buffer[--ringbuf->first & ringbuf->mask] = ent;
+ ++ringbuf->len;
+
+ return 0;
+}
+
+static void hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf) {
+ assert(ringbuf->len > 0);
+ --ringbuf->len;
+}
+
+static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) {
+ int rv;
+ context->mem = mem;
+ context->bad = 0;
+ context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
+ rv = hd_ringbuf_init(
+ &context->hd_table,
+ context->hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD, mem);
+ if (rv != 0) {
+ return rv;
+ }
+
+ context->hd_table_bufsize = 0;
+ context->next_seq = 0;
+
+ return 0;
+}
+
+static void hd_context_free(nghttp2_hd_context *context) {
+ hd_ringbuf_free(&context->hd_table, context->mem);
+}
+
+int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem) {
+ return nghttp2_hd_deflate_init2(
+ deflater, NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE, mem);
+}
+
+int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
+ size_t max_deflate_dynamic_table_size,
+ nghttp2_mem *mem) {
+ int rv;
+ rv = hd_context_init(&deflater->ctx, mem);
+ if (rv != 0) {
+ return rv;
+ }
+
+ hd_map_init(&deflater->map);
+
+ if (max_deflate_dynamic_table_size < NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE) {
+ deflater->notify_table_size_change = 1;
+ deflater->ctx.hd_table_bufsize_max = max_deflate_dynamic_table_size;
+ } else {
+ deflater->notify_table_size_change = 0;
+ }
+
+ deflater->deflate_hd_table_bufsize_max = max_deflate_dynamic_table_size;
+ deflater->min_hd_table_bufsize_max = UINT32_MAX;
+
+ return 0;
+}
+
+int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
+ int rv;
+
+ rv = hd_context_init(&inflater->ctx, mem);
+ if (rv != 0) {
+ goto fail;
+ }
+
+ inflater->settings_hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
+ inflater->min_hd_table_bufsize_max = UINT32_MAX;
+
+ inflater->nv_name_keep = NULL;
+ inflater->nv_value_keep = NULL;
+
+ inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
+ inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
+
+ nghttp2_buf_init(&inflater->namebuf);
+ nghttp2_buf_init(&inflater->valuebuf);
+
+ inflater->namercbuf = NULL;
+ inflater->valuercbuf = NULL;
+
+ inflater->huffman_encoded = 0;
+ inflater->index = 0;
+ inflater->left = 0;
+ inflater->shift = 0;
+ inflater->index_required = 0;
+ inflater->no_index = 0;
+
+ return 0;
+
+fail:
+ return rv;
+}
+
+static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) {
+ nghttp2_rcbuf_decref(inflater->nv_value_keep);
+ nghttp2_rcbuf_decref(inflater->nv_name_keep);
+
+ inflater->nv_value_keep = NULL;
+ inflater->nv_name_keep = NULL;
+}
+
+void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
+ hd_context_free(&deflater->ctx);
+}
+
+void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) {
+ hd_inflate_keep_free(inflater);
+
+ nghttp2_rcbuf_decref(inflater->valuercbuf);
+ nghttp2_rcbuf_decref(inflater->namercbuf);
+
+ hd_context_free(&inflater->ctx);
+}
+
+static size_t entry_room(size_t namelen, size_t valuelen) {
+ return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen;
+}
+
+static void emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) {
+ DEBUGF("inflatehd: header emission: %s: %s\n", nv->name->base,
+ nv->value->base);
+ /* ent->ref may be 0. This happens if the encoder emits literal
+ block larger than header table capacity with indexing. */
+ *nv_out = *nv;
+}
+
+static size_t count_encoded_length(size_t n, size_t prefix) {
+ size_t k = (size_t)((1 << prefix) - 1);
+ size_t len = 0;
+
+ if (n < k) {
+ return 1;
+ }
+
+ n -= k;
+ ++len;
+
+ for (; n >= 128; n >>= 7, ++len)
+ ;
+
+ return len + 1;
+}
+
+static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) {
+ size_t k = (size_t)((1 << prefix) - 1);
+ uint8_t *begin = buf;
+
+ *buf = (uint8_t)(*buf & ~k);
+
+ if (n < k) {
+ *buf = (uint8_t)(*buf | n);
+ return 1;
+ }
+
+ *buf = (uint8_t)(*buf | k);
+ ++buf;
+
+ n -= k;
+
+ for (; n >= 128; n >>= 7) {
+ *buf++ = (uint8_t)((1 << 7) | (n & 0x7f));
+ }
+
+ *buf++ = (uint8_t)n;
+
+ return (size_t)(buf - begin);
+}
+
+/*
+ * Decodes |prefix| prefixed integer stored from |in|. The |last|
+ * represents the 1 beyond the last of the valid contiguous memory
+ * region from |in|. The decoded integer must be less than or equal
+ * to UINT32_MAX.
+ *
+ * If the |initial| is nonzero, it is used as a initial value, this
+ * function assumes the |in| starts with intermediate data.
+ *
+ * An entire integer is decoded successfully, decoded, the |*fin| is
+ * set to nonzero.
+ *
+ * This function stores the decoded integer in |*res| if it succeed,
+ * including partial decoding (in this case, number of shift to make
+ * in the next call will be stored in |*shift_ptr|) and returns number
+ * of bytes processed, or returns -1, indicating decoding error.
+ */
+static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
+ uint32_t initial, size_t shift, const uint8_t *in,
+ const uint8_t *last, size_t prefix) {
+ uint32_t k = (uint8_t)((1 << prefix) - 1);
+ uint32_t n = initial;
+ const uint8_t *start = in;
+
+ *shift_ptr = 0;
+ *fin = 0;
+
+ if (n == 0) {
+ if ((*in & k) != k) {
+ *res = (*in) & k;
+ *fin = 1;
+ return 1;
+ }
+
+ n = k;
+
+ if (++in == last) {
+ *res = n;
+ return (ssize_t)(in - start);
+ }
+ }
+
+ for (; in != last; ++in, shift += 7) {
+ uint32_t add = *in & 0x7f;
+
+ if (shift >= 32) {
+ DEBUGF("inflate: shift exponent overflow\n");
+ return -1;
+ }
+
+ if ((UINT32_MAX >> shift) < add) {
+ DEBUGF("inflate: integer overflow on shift\n");
+ return -1;
+ }
+
+ add <<= shift;
+
+ if (UINT32_MAX - add < n) {
+ DEBUGF("inflate: integer overflow on addition\n");
+ return -1;
+ }
+
+ n += add;
+
+ if ((*in & (1 << 7)) == 0) {
+ break;
+ }
+ }
+
+ *shift_ptr = shift;
+
+ if (in == last) {
+ *res = n;
+ return (ssize_t)(in - start);
+ }
+
+ *res = n;
+ *fin = 1;
+ return (ssize_t)(in + 1 - start);
+}
+
+static int emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
+ int rv;
+ uint8_t *bufp;
+ size_t blocklen;
+ uint8_t sb[16];
+
+ DEBUGF("deflatehd: emit table_size=%zu\n", table_size);
+
+ blocklen = count_encoded_length(table_size, 5);
+
+ if (sizeof(sb) < blocklen) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ bufp = sb;
+
+ *bufp = 0x20u;
+
+ encode_length(bufp, table_size, 5);
+
+ rv = nghttp2_bufs_add(bufs, sb, blocklen);
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+}
+
+static int emit_indexed_block(nghttp2_bufs *bufs, size_t idx) {
+ int rv;
+ size_t blocklen;
+ uint8_t sb[16];
+ uint8_t *bufp;
+
+ blocklen = count_encoded_length(idx + 1, 7);
+
+ DEBUGF("deflatehd: emit indexed index=%zu, %zu bytes\n", idx, blocklen);
+
+ if (sizeof(sb) < blocklen) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ bufp = sb;
+ *bufp = 0x80u;
+ encode_length(bufp, idx + 1, 7);
+
+ rv = nghttp2_bufs_add(bufs, sb, blocklen);
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+}
+
+static int emit_string(nghttp2_bufs *bufs, const uint8_t *str, size_t len) {
+ int rv;
+ uint8_t sb[16];
+ uint8_t *bufp;
+ size_t blocklen;
+ size_t enclen;
+ int huffman = 0;
+
+ enclen = nghttp2_hd_huff_encode_count(str, len);
+
+ if (enclen < len) {
+ huffman = 1;
+ } else {
+ enclen = len;
+ }
+
+ blocklen = count_encoded_length(enclen, 7);
+
+ DEBUGF("deflatehd: emit string str=%.*s, length=%zu, huffman=%d, "
+ "encoded_length=%zu\n",
+ (int)len, (const char *)str, len, huffman, enclen);
+
+ if (sizeof(sb) < blocklen) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ bufp = sb;
+ *bufp = huffman ? 1 << 7 : 0;
+ encode_length(bufp, enclen, 7);
+
+ rv = nghttp2_bufs_add(bufs, sb, blocklen);
+ if (rv != 0) {
+ return rv;
+ }
+
+ if (huffman) {
+ rv = nghttp2_hd_huff_encode(bufs, str, len);
+ } else {
+ assert(enclen == len);
+ rv = nghttp2_bufs_add(bufs, str, len);
+ }
+
+ return rv;
+}
+
+static uint8_t pack_first_byte(int indexing_mode) {
+ switch (indexing_mode) {
+ case NGHTTP2_HD_WITH_INDEXING:
+ return 0x40u;
+ case NGHTTP2_HD_WITHOUT_INDEXING:
+ return 0;
+ case NGHTTP2_HD_NEVER_INDEXING:
+ return 0x10u;
+ default:
+ assert(0);
+ }
+ /* This is required to compile with android NDK r10d +
+ --enable-werror */
+ return 0;
+}
+
+static int emit_indname_block(nghttp2_bufs *bufs, size_t idx,
+ const nghttp2_nv *nv, int indexing_mode) {
+ int rv;
+ uint8_t *bufp;
+ size_t blocklen;
+ uint8_t sb[16];
+ size_t prefixlen;
+
+ if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
+ prefixlen = 6;
+ } else {
+ prefixlen = 4;
+ }
+
+ DEBUGF("deflatehd: emit indname index=%zu, valuelen=%zu, indexing_mode=%d\n",
+ idx, nv->valuelen, indexing_mode);
+
+ blocklen = count_encoded_length(idx + 1, prefixlen);
+
+ if (sizeof(sb) < blocklen) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ bufp = sb;
+
+ *bufp = pack_first_byte(indexing_mode);
+
+ encode_length(bufp, idx + 1, prefixlen);
+
+ rv = nghttp2_bufs_add(bufs, sb, blocklen);
+ if (rv != 0) {
+ return rv;
+ }
+
+ rv = emit_string(bufs, nv->value, nv->valuelen);
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+}
+
+static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
+ int indexing_mode) {
+ int rv;
+
+ DEBUGF(
+ "deflatehd: emit newname namelen=%zu, valuelen=%zu, indexing_mode=%d\n",
+ nv->namelen, nv->valuelen, indexing_mode);
+
+ rv = nghttp2_bufs_addb(bufs, pack_first_byte(indexing_mode));
+ if (rv != 0) {
+ return rv;
+ }
+
+ rv = emit_string(bufs, nv->name, nv->namelen);
+ if (rv != 0) {
+ return rv;
+ }
+
+ rv = emit_string(bufs, nv->value, nv->valuelen);
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+}
+
+static int add_hd_table_incremental(nghttp2_hd_context *context,
+ nghttp2_hd_nv *nv, nghttp2_hd_map *map,
+ uint32_t hash) {
+ int rv;
+ nghttp2_hd_entry *new_ent;
+ size_t room;
+ nghttp2_mem *mem;
+
+ mem = context->mem;
+ room = entry_room(nv->name->len, nv->value->len);
+
+ while (context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
+ context->hd_table.len > 0) {
+
+ size_t idx = context->hd_table.len - 1;
+ nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
+
+ context->hd_table_bufsize -=
+ entry_room(ent->nv.name->len, ent->nv.value->len);
+
+ DEBUGF("hpack: remove item from header table: %s: %s\n",
+ (char *)ent->nv.name->base, (char *)ent->nv.value->base);
+
+ hd_ringbuf_pop_back(&context->hd_table);
+ if (map) {
+ hd_map_remove(map, ent);
+ }
+
+ nghttp2_hd_entry_free(ent);
+ nghttp2_mem_free(mem, ent);
+ }
+
+ if (room > context->hd_table_bufsize_max) {
+ /* The entry taking more than NGHTTP2_HD_MAX_BUFFER_SIZE is
+ immediately evicted. So we don't allocate memory for it. */
+ return 0;
+ }
+
+ new_ent = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry));
+ if (new_ent == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ nghttp2_hd_entry_init(new_ent, nv);
+
+ rv = hd_ringbuf_push_front(&context->hd_table, new_ent, mem);
+
+ if (rv != 0) {
+ nghttp2_hd_entry_free(new_ent);
+ nghttp2_mem_free(mem, new_ent);
+
+ return rv;
+ }
+
+ new_ent->seq = context->next_seq++;
+ new_ent->hash = hash;
+
+ if (map) {
+ hd_map_insert(map, new_ent);
+ }
+
+ context->hd_table_bufsize += room;
+
+ return 0;
+}
+
+typedef struct {
+ ssize_t index;
+ /* Nonzero if both name and value are matched. */
+ int name_value_match;
+} search_result;
+
+static search_result search_static_table(const nghttp2_nv *nv, int32_t token,
+ int name_only) {
+ search_result res = {token, 0};
+ int i;
+ nghttp2_hd_static_entry *ent;
+
+ if (name_only) {
+ return res;
+ }
+
+ for (i = token;
+ i <= NGHTTP2_TOKEN_WWW_AUTHENTICATE && static_table[i].token == token;
+ ++i) {
+ ent = &static_table[i];
+ if (ent->value.len == nv->valuelen &&
+ memcmp(ent->value.base, nv->value, nv->valuelen) == 0) {
+ res.index = i;
+ res.name_value_match = 1;
+ return res;
+ }
+ }
+ return res;
+}
+
+static search_result search_hd_table(nghttp2_hd_context *context,
+ const nghttp2_nv *nv, int32_t token,
+ int indexing_mode, nghttp2_hd_map *map,
+ uint32_t hash) {
+ search_result res = {-1, 0};
+ nghttp2_hd_entry *ent;
+ int exact_match;
+ int name_only = indexing_mode == NGHTTP2_HD_NEVER_INDEXING;
+
+ exact_match = 0;
+ ent = hd_map_find(map, &exact_match, nv, token, hash, name_only);
+
+ if (!exact_match && token >= 0 && token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
+ return search_static_table(nv, token, name_only);
+ }
+
+ if (ent == NULL) {
+ return res;
+ }
+
+ res.index =
+ (ssize_t)(context->next_seq - 1 - ent->seq + NGHTTP2_STATIC_TABLE_LENGTH);
+ res.name_value_match = exact_match;
+
+ return res;
+}
+
+static void hd_context_shrink_table_size(nghttp2_hd_context *context,
+ nghttp2_hd_map *map) {
+ nghttp2_mem *mem;
+
+ mem = context->mem;
+
+ while (context->hd_table_bufsize > context->hd_table_bufsize_max &&
+ context->hd_table.len > 0) {
+ size_t idx = context->hd_table.len - 1;
+ nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
+ context->hd_table_bufsize -=
+ entry_room(ent->nv.name->len, ent->nv.value->len);
+ hd_ringbuf_pop_back(&context->hd_table);
+ if (map) {
+ hd_map_remove(map, ent);
+ }
+
+ nghttp2_hd_entry_free(ent);
+ nghttp2_mem_free(mem, ent);
+ }
+}
+
+int nghttp2_hd_deflate_change_table_size(
+ nghttp2_hd_deflater *deflater, size_t settings_max_dynamic_table_size) {
+ size_t next_bufsize = nghttp2_min(settings_max_dynamic_table_size,
+ deflater->deflate_hd_table_bufsize_max);
+
+ deflater->ctx.hd_table_bufsize_max = next_bufsize;
+
+ deflater->min_hd_table_bufsize_max =
+ nghttp2_min(deflater->min_hd_table_bufsize_max, next_bufsize);
+
+ deflater->notify_table_size_change = 1;
+
+ hd_context_shrink_table_size(&deflater->ctx, &deflater->map);
+ return 0;
+}
+
+int nghttp2_hd_inflate_change_table_size(
+ nghttp2_hd_inflater *inflater, size_t settings_max_dynamic_table_size) {
+ switch (inflater->state) {
+ case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
+ case NGHTTP2_HD_STATE_INFLATE_START:
+ break;
+ default:
+ return NGHTTP2_ERR_INVALID_STATE;
+ }
+
+ /* It seems that encoder is not required to send dynamic table size
+ update if the table size is not changed after applying
+ SETTINGS_HEADER_TABLE_SIZE. RFC 7541 is ambiguous here, but this
+ is the intention of the editor. If new maximum table size is
+ strictly smaller than the current negotiated maximum size,
+ encoder must send dynamic table size update. In other cases, we
+ cannot expect it to do so. */
+ if (inflater->ctx.hd_table_bufsize_max > settings_max_dynamic_table_size) {
+ inflater->state = NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE;
+ /* Remember minimum value, and validate that encoder sends the
+ value less than or equal to this. */
+ inflater->min_hd_table_bufsize_max = settings_max_dynamic_table_size;
+ }
+
+ inflater->settings_hd_table_bufsize_max = settings_max_dynamic_table_size;
+
+ inflater->ctx.hd_table_bufsize_max = settings_max_dynamic_table_size;
+
+ hd_context_shrink_table_size(&inflater->ctx, NULL);
+ return 0;
+}
+
+#define INDEX_RANGE_VALID(context, idx) \
+ ((idx) < (context)->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH)
+
+static size_t get_max_index(nghttp2_hd_context *context) {
+ return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH;
+}
+
+nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) {
+ assert(INDEX_RANGE_VALID(context, idx));
+ if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
+ return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
+ ->nv;
+ } else {
+ nghttp2_hd_static_entry *ent = &static_table[idx];
+ nghttp2_hd_nv nv = {&ent->name, &ent->value, ent->token,
+ NGHTTP2_NV_FLAG_NONE};
+ return nv;
+ }
+}
+
+static const nghttp2_nv *nghttp2_hd_table_get2(nghttp2_hd_context *context,
+ size_t idx) {
+ assert(INDEX_RANGE_VALID(context, idx));
+ if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
+ return &hd_ringbuf_get(&context->hd_table,
+ idx - NGHTTP2_STATIC_TABLE_LENGTH)
+ ->cnv;
+ }
+
+ return &static_table[idx].cnv;
+}
+
+static int hd_deflate_decide_indexing(nghttp2_hd_deflater *deflater,
+ const nghttp2_nv *nv, int32_t token) {
+ if (token == NGHTTP2_TOKEN__PATH || token == NGHTTP2_TOKEN_AGE ||
+ token == NGHTTP2_TOKEN_CONTENT_LENGTH || token == NGHTTP2_TOKEN_ETAG ||
+ token == NGHTTP2_TOKEN_IF_MODIFIED_SINCE ||
+ token == NGHTTP2_TOKEN_IF_NONE_MATCH || token == NGHTTP2_TOKEN_LOCATION ||
+ token == NGHTTP2_TOKEN_SET_COOKIE ||
+ entry_room(nv->namelen, nv->valuelen) >
+ deflater->ctx.hd_table_bufsize_max * 3 / 4) {
+ return NGHTTP2_HD_WITHOUT_INDEXING;
+ }
+
+ return NGHTTP2_HD_WITH_INDEXING;
+}
+
+static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
+ const nghttp2_nv *nv) {
+ int rv;
+ search_result res;
+ ssize_t idx;
+ int indexing_mode;
+ int32_t token;
+ nghttp2_mem *mem;
+ uint32_t hash = 0;
+
+ DEBUGF("deflatehd: deflating %.*s: %.*s\n", (int)nv->namelen, nv->name,
+ (int)nv->valuelen, nv->value);
+
+ mem = deflater->ctx.mem;
+
+ token = lookup_token(nv->name, nv->namelen);
+ if (token == -1) {
+ hash = name_hash(nv);
+ } else if (token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
+ hash = static_table[token].hash;
+ }
+
+ /* Don't index authorization header field since it may contain low
+ entropy secret data (e.g., id/password). Also cookie header
+ field with less than 20 bytes value is also never indexed. This
+ is the same criteria used in Firefox codebase. */
+ indexing_mode =
+ token == NGHTTP2_TOKEN_AUTHORIZATION ||
+ (token == NGHTTP2_TOKEN_COOKIE && nv->valuelen < 20) ||
+ (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX)
+ ? NGHTTP2_HD_NEVER_INDEXING
+ : hd_deflate_decide_indexing(deflater, nv, token);
+
+ res = search_hd_table(&deflater->ctx, nv, token, indexing_mode,
+ &deflater->map, hash);
+
+ idx = res.index;
+
+ if (res.name_value_match) {
+
+ DEBUGF("deflatehd: name/value match index=%zd\n", idx);
+
+ rv = emit_indexed_block(bufs, (size_t)idx);
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+ }
+
+ if (res.index != -1) {
+ DEBUGF("deflatehd: name match index=%zd\n", res.index);
+ }
+
+ if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
+ nghttp2_hd_nv hd_nv;
+
+ if (idx != -1 && idx < (ssize_t)NGHTTP2_STATIC_TABLE_LENGTH) {
+ hd_nv.name = nghttp2_hd_table_get(&deflater->ctx, (size_t)idx).name;
+ nghttp2_rcbuf_incref(hd_nv.name);
+ } else {
+ rv = nghttp2_rcbuf_new2(&hd_nv.name, nv->name, nv->namelen, mem);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+
+ rv = nghttp2_rcbuf_new2(&hd_nv.value, nv->value, nv->valuelen, mem);
+
+ if (rv != 0) {
+ nghttp2_rcbuf_decref(hd_nv.name);
+ return rv;
+ }
+
+ hd_nv.token = token;
+ hd_nv.flags = NGHTTP2_NV_FLAG_NONE;
+
+ rv = add_hd_table_incremental(&deflater->ctx, &hd_nv, &deflater->map, hash);
+
+ nghttp2_rcbuf_decref(hd_nv.value);
+ nghttp2_rcbuf_decref(hd_nv.name);
+
+ if (rv != 0) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+ }
+ if (idx == -1) {
+ rv = emit_newname_block(bufs, nv, indexing_mode);
+ } else {
+ rv = emit_indname_block(bufs, (size_t)idx, nv, indexing_mode);
+ }
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+}
+
+int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
+ nghttp2_bufs *bufs, const nghttp2_nv *nv,
+ size_t nvlen) {
+ size_t i;
+ int rv = 0;
+
+ if (deflater->ctx.bad) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ if (deflater->notify_table_size_change) {
+ size_t min_hd_table_bufsize_max;
+
+ min_hd_table_bufsize_max = deflater->min_hd_table_bufsize_max;
+
+ deflater->notify_table_size_change = 0;
+ deflater->min_hd_table_bufsize_max = UINT32_MAX;
+
+ if (deflater->ctx.hd_table_bufsize_max > min_hd_table_bufsize_max) {
+
+ rv = emit_table_size(bufs, min_hd_table_bufsize_max);
+
+ if (rv != 0) {
+ goto fail;
+ }
+ }
+
+ rv = emit_table_size(bufs, deflater->ctx.hd_table_bufsize_max);
+
+ if (rv != 0) {
+ goto fail;
+ }
+ }
+
+ for (i = 0; i < nvlen; ++i) {
+ rv = deflate_nv(deflater, bufs, &nv[i]);
+ if (rv != 0) {
+ goto fail;
+ }
+ }
+
+ DEBUGF("deflatehd: all input name/value pairs were deflated\n");
+
+ return 0;
+fail:
+ DEBUGF("deflatehd: error return %d\n", rv);
+
+ deflater->ctx.bad = 1;
+ return rv;
+}
+
+ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
+ size_t buflen, const nghttp2_nv *nv,
+ size_t nvlen) {
+ nghttp2_bufs bufs;
+ int rv;
+ nghttp2_mem *mem;
+
+ mem = deflater->ctx.mem;
+
+ rv = nghttp2_bufs_wrap_init(&bufs, buf, buflen, mem);
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nv, nvlen);
+
+ buflen = nghttp2_bufs_len(&bufs);
+
+ nghttp2_bufs_wrap_free(&bufs);
+
+ if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
+ return NGHTTP2_ERR_INSUFF_BUFSIZE;
+ }
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ return (ssize_t)buflen;
+}
+
+ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater,
+ const nghttp2_vec *vec, size_t veclen,
+ const nghttp2_nv *nv, size_t nvlen) {
+ nghttp2_bufs bufs;
+ int rv;
+ nghttp2_mem *mem;
+ size_t buflen;
+
+ mem = deflater->ctx.mem;
+
+ rv = nghttp2_bufs_wrap_init2(&bufs, vec, veclen, mem);
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nv, nvlen);
+
+ buflen = nghttp2_bufs_len(&bufs);
+
+ nghttp2_bufs_wrap_free(&bufs);
+
+ if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
+ return NGHTTP2_ERR_INSUFF_BUFSIZE;
+ }
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ return (ssize_t)buflen;
+}
+
+size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
+ const nghttp2_nv *nva, size_t nvlen) {
+ size_t n = 0;
+ size_t i;
+ (void)deflater;
+
+ /* Possible Maximum Header Table Size Change. Encoding (1u << 31) -
+ 1 using 4 bit prefix requires 6 bytes. We may emit this at most
+ twice. */
+ n += 12;
+
+ /* Use Literal Header Field without indexing - New Name, since it is
+ most space consuming format. Also we choose the less one between
+ non-huffman and huffman, so using literal byte count is
+ sufficient for upper bound.
+
+ Encoding (1u << 31) - 1 using 7 bit prefix requires 6 bytes. We
+ need 2 of this for |nvlen| header fields. */
+ n += 6 * 2 * nvlen;
+
+ for (i = 0; i < nvlen; ++i) {
+ n += nva[i].namelen + nva[i].valuelen;
+ }
+
+ return n;
+}
+
+int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
+ size_t deflate_hd_table_bufsize_max) {
+ return nghttp2_hd_deflate_new2(deflater_ptr, deflate_hd_table_bufsize_max,
+ NULL);
+}
+
+int nghttp2_hd_deflate_new2(nghttp2_hd_deflater **deflater_ptr,
+ size_t deflate_hd_table_bufsize_max,
+ nghttp2_mem *mem) {
+ int rv;
+ nghttp2_hd_deflater *deflater;
+
+ if (mem == NULL) {
+ mem = nghttp2_mem_default();
+ }
+
+ deflater = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_deflater));
+
+ if (deflater == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ rv = nghttp2_hd_deflate_init2(deflater, deflate_hd_table_bufsize_max, mem);
+
+ if (rv != 0) {
+ nghttp2_mem_free(mem, deflater);
+
+ return rv;
+ }
+
+ *deflater_ptr = deflater;
+
+ return 0;
+}
+
+void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater) {
+ nghttp2_mem *mem;
+
+ mem = deflater->ctx.mem;
+
+ nghttp2_hd_deflate_free(deflater);
+
+ nghttp2_mem_free(mem, deflater);
+}
+
+static void hd_inflate_set_huffman_encoded(nghttp2_hd_inflater *inflater,
+ const uint8_t *in) {
+ inflater->huffman_encoded = (*in & (1 << 7)) != 0;
+}
+
+/*
+ * Decodes the integer from the range [in, last). The result is
+ * assigned to |inflater->left|. If the |inflater->left| is 0, then
+ * it performs variable integer decoding from scratch. Otherwise, it
+ * uses the |inflater->left| as the initial value and continues to
+ * decode assuming that [in, last) begins with intermediary sequence.
+ *
+ * This function returns the number of bytes read if it succeeds, or
+ * one of the following negative error codes:
+ *
+ * NGHTTP2_ERR_HEADER_COMP
+ * Integer decoding failed
+ */
+static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin,
+ const uint8_t *in, const uint8_t *last,
+ size_t prefix, size_t maxlen) {
+ ssize_t rv;
+ uint32_t out;
+
+ *rfin = 0;
+
+ rv = decode_length(&out, &inflater->shift, rfin, (uint32_t)inflater->left,
+ inflater->shift, in, last, prefix);
+
+ if (rv == -1) {
+ DEBUGF("inflatehd: integer decoding failed\n");
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ if (out > maxlen) {
+ DEBUGF("inflatehd: integer exceeded the maximum value %zu\n", maxlen);
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ inflater->left = out;
+
+ DEBUGF("inflatehd: decoded integer is %u\n", out);
+
+ return rv;
+}
+
+/*
+ * Reads |inflater->left| bytes from the range [in, last) and performs
+ * huffman decoding against them and pushes the result into the
+ * |buffer|.
+ *
+ * This function returns the number of bytes read if it succeeds, or
+ * one of the following negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ * NGHTTP2_ERR_HEADER_COMP
+ * Huffman decoding failed
+ */
+static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
+ nghttp2_buf *buf, const uint8_t *in,
+ const uint8_t *last) {
+ ssize_t readlen;
+ int fin = 0;
+ if ((size_t)(last - in) >= inflater->left) {
+ last = in + inflater->left;
+ fin = 1;
+ }
+ readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buf, in,
+ (size_t)(last - in), fin);
+
+ if (readlen < 0) {
+ DEBUGF("inflatehd: huffman decoding failed\n");
+ return readlen;
+ }
+ inflater->left -= (size_t)readlen;
+ return readlen;
+}
+
+/*
+ * Reads |inflater->left| bytes from the range [in, last) and copies
+ * them into the |buffer|.
+ *
+ * This function returns the number of bytes read if it succeeds, or
+ * one of the following negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ * NGHTTP2_ERR_HEADER_COMP
+ * Header decompression failed
+ */
+static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, nghttp2_buf *buf,
+ const uint8_t *in, const uint8_t *last) {
+ size_t len = nghttp2_min((size_t)(last - in), inflater->left);
+
+ buf->last = nghttp2_cpymem(buf->last, in, len);
+
+ inflater->left -= len;
+ return (ssize_t)len;
+}
+
+/*
+ * Finalize indexed header representation reception. The referenced
+ * header is always emitted, and |*nv_out| is filled with that value.
+ */
+static void hd_inflate_commit_indexed(nghttp2_hd_inflater *inflater,
+ nghttp2_hd_nv *nv_out) {
+ nghttp2_hd_nv nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
+
+ emit_header(nv_out, &nv);
+}
+
+/*
+ * Finalize literal header representation - new name- reception. If
+ * header is emitted, |*nv_out| is filled with that value and 0 is
+ * returned.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
+ nghttp2_hd_nv *nv_out) {
+ nghttp2_hd_nv nv;
+ int rv;
+
+ if (inflater->no_index) {
+ nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
+ } else {
+ nv.flags = NGHTTP2_NV_FLAG_NONE;
+ }
+
+ nv.name = inflater->namercbuf;
+ nv.value = inflater->valuercbuf;
+ nv.token = lookup_token(inflater->namercbuf->base, inflater->namercbuf->len);
+
+ if (inflater->index_required) {
+ rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
+
+ if (rv != 0) {
+ return rv;
+ }
+ }
+
+ emit_header(nv_out, &nv);
+
+ inflater->nv_name_keep = nv.name;
+ inflater->nv_value_keep = nv.value;
+
+ inflater->namercbuf = NULL;
+ inflater->valuercbuf = NULL;
+
+ return 0;
+}
+
+/*
+ * Finalize literal header representation - indexed name-
+ * reception. If header is emitted, |*nv_out| is filled with that
+ * value and 0 is returned.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
+ nghttp2_hd_nv *nv_out) {
+ nghttp2_hd_nv nv;
+ int rv;
+
+ nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
+
+ if (inflater->no_index) {
+ nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
+ } else {
+ nv.flags = NGHTTP2_NV_FLAG_NONE;
+ }
+
+ nghttp2_rcbuf_incref(nv.name);
+
+ nv.value = inflater->valuercbuf;
+
+ if (inflater->index_required) {
+ rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
+ if (rv != 0) {
+ nghttp2_rcbuf_decref(nv.name);
+ return NGHTTP2_ERR_NOMEM;
+ }
+ }
+
+ emit_header(nv_out, &nv);
+
+ inflater->nv_name_keep = nv.name;
+ inflater->nv_value_keep = nv.value;
+
+ inflater->valuercbuf = NULL;
+
+ return 0;
+}
+
+ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
+ int *inflate_flags, uint8_t *in, size_t inlen,
+ int in_final) {
+ return nghttp2_hd_inflate_hd2(inflater, nv_out, inflate_flags, in, inlen,
+ in_final);
+}
+
+ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
+ nghttp2_nv *nv_out, int *inflate_flags,
+ const uint8_t *in, size_t inlen, int in_final) {
+ ssize_t rv;
+ nghttp2_hd_nv hd_nv;
+
+ rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen,
+ in_final);
+
+ if (rv < 0) {
+ return rv;
+ }
+
+ if (*inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
+ nv_out->name = hd_nv.name->base;
+ nv_out->namelen = hd_nv.name->len;
+
+ nv_out->value = hd_nv.value->base;
+ nv_out->valuelen = hd_nv.value->len;
+
+ nv_out->flags = hd_nv.flags;
+ }
+
+ return rv;
+}
+
+ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
+ nghttp2_hd_nv *nv_out, int *inflate_flags,
+ const uint8_t *in, size_t inlen,
+ int in_final) {
+ ssize_t rv = 0;
+ const uint8_t *first = in;
+ const uint8_t *last = in + inlen;
+ int rfin = 0;
+ int busy = 0;
+ nghttp2_mem *mem;
+
+ mem = inflater->ctx.mem;
+
+ if (inflater->ctx.bad) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+
+ DEBUGF("inflatehd: start state=%d\n", inflater->state);
+ hd_inflate_keep_free(inflater);
+ *inflate_flags = NGHTTP2_HD_INFLATE_NONE;
+ for (; in != last || busy;) {
+ busy = 0;
+ switch (inflater->state) {
+ case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
+ if ((*in & 0xe0u) != 0x20u) {
+ DEBUGF("inflatehd: header table size change was expected, but saw "
+ "0x%02x as first byte",
+ *in);
+ rv = NGHTTP2_ERR_HEADER_COMP;
+ goto fail;
+ }
+ /* fall through */
+ case NGHTTP2_HD_STATE_INFLATE_START:
+ case NGHTTP2_HD_STATE_OPCODE:
+ if ((*in & 0xe0u) == 0x20u) {
+ DEBUGF("inflatehd: header table size change\n");
+ if (inflater->state == NGHTTP2_HD_STATE_OPCODE) {
+ DEBUGF("inflatehd: header table size change must appear at the head "
+ "of header block\n");
+ rv = NGHTTP2_ERR_HEADER_COMP;
+ goto fail;
+ }
+ inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
+ inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
+ } else if (*in & 0x80u) {
+ DEBUGF("inflatehd: indexed repr\n");
+ inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
+ inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
+ } else {
+ if (*in == 0x40u || *in == 0 || *in == 0x10u) {
+ DEBUGF("inflatehd: literal header repr - new name\n");
+ inflater->opcode = NGHTTP2_HD_OPCODE_NEWNAME;
+ inflater->state = NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN;
+ } else {
+ DEBUGF("inflatehd: literal header repr - indexed name\n");
+ inflater->opcode = NGHTTP2_HD_OPCODE_INDNAME;
+ inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
+ }
+ inflater->index_required = (*in & 0x40) != 0;
+ inflater->no_index = (*in & 0xf0u) == 0x10u;
+ DEBUGF("inflatehd: indexing required=%d, no_index=%d\n",
+ inflater->index_required, inflater->no_index);
+ if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
+ ++in;
+ }
+ }
+ inflater->left = 0;
+ inflater->shift = 0;
+ break;
+ case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
+ rfin = 0;
+ rv = hd_inflate_read_len(
+ inflater, &rfin, in, last, 5,
+ nghttp2_min(inflater->min_hd_table_bufsize_max,
+ inflater->settings_hd_table_bufsize_max));
+ if (rv < 0) {
+ goto fail;
+ }
+ in += rv;
+ if (!rfin) {
+ goto almost_ok;
+ }
+ DEBUGF("inflatehd: table_size=%zu\n", inflater->left);
+ inflater->min_hd_table_bufsize_max = UINT32_MAX;
+ inflater->ctx.hd_table_bufsize_max = inflater->left;
+ hd_context_shrink_table_size(&inflater->ctx, NULL);
+ inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
+ break;
+ case NGHTTP2_HD_STATE_READ_INDEX: {
+ size_t prefixlen;
+
+ if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
+ prefixlen = 7;
+ } else if (inflater->index_required) {
+ prefixlen = 6;
+ } else {
+ prefixlen = 4;
+ }
+
+ rfin = 0;
+ rv = hd_inflate_read_len(inflater, &rfin, in, last, prefixlen,
+ get_max_index(&inflater->ctx));
+ if (rv < 0) {
+ goto fail;
+ }
+
+ in += rv;
+
+ if (!rfin) {
+ goto almost_ok;
+ }
+
+ if (inflater->left == 0) {
+ rv = NGHTTP2_ERR_HEADER_COMP;
+ goto fail;
+ }
+
+ DEBUGF("inflatehd: index=%zu\n", inflater->left);
+ if (inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
+ inflater->index = inflater->left;
+ --inflater->index;
+
+ hd_inflate_commit_indexed(inflater, nv_out);
+
+ inflater->state = NGHTTP2_HD_STATE_OPCODE;
+ *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
+ return (ssize_t)(in - first);
+ } else {
+ inflater->index = inflater->left;
+ --inflater->index;
+
+ inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
+ }
+ break;
+ }
+ case NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN:
+ hd_inflate_set_huffman_encoded(inflater, in);
+ inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
+ inflater->left = 0;
+ inflater->shift = 0;
+ DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
+ /* Fall through */
+ case NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN:
+ rfin = 0;
+ rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
+ if (rv < 0) {
+ goto fail;
+ }
+ in += rv;
+ if (!rfin) {
+ DEBUGF("inflatehd: integer not fully decoded. current=%zu\n",
+ inflater->left);
+
+ goto almost_ok;
+ }
+
+ if (inflater->huffman_encoded) {
+ nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
+
+ inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
+
+ rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left * 2 + 1,
+ mem);
+ } else {
+ inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
+ rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem);
+ }
+
+ if (rv != 0) {
+ goto fail;
+ }
+
+ nghttp2_buf_wrap_init(&inflater->namebuf, inflater->namercbuf->base,
+ inflater->namercbuf->len);
+
+ break;
+ case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
+ rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last);
+ if (rv < 0) {
+ goto fail;
+ }
+
+ in += rv;
+
+ DEBUGF("inflatehd: %zd bytes read\n", rv);
+
+ if (inflater->left) {
+ DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
+
+ goto almost_ok;
+ }
+
+ *inflater->namebuf.last = '\0';
+ inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
+
+ inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
+
+ break;
+ case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
+ rv = hd_inflate_read(inflater, &inflater->namebuf, in, last);
+ if (rv < 0) {
+ goto fail;
+ }
+
+ in += rv;
+
+ DEBUGF("inflatehd: %zd bytes read\n", rv);
+ if (inflater->left) {
+ DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
+
+ goto almost_ok;
+ }
+
+ *inflater->namebuf.last = '\0';
+ inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
+
+ inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
+
+ break;
+ case NGHTTP2_HD_STATE_CHECK_VALUELEN:
+ hd_inflate_set_huffman_encoded(inflater, in);
+ inflater->state = NGHTTP2_HD_STATE_READ_VALUELEN;
+ inflater->left = 0;
+ inflater->shift = 0;
+ DEBUGF("inflatehd: huffman encoded=%d\n", inflater->huffman_encoded != 0);
+ /* Fall through */
+ case NGHTTP2_HD_STATE_READ_VALUELEN:
+ rfin = 0;
+ rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, NGHTTP2_HD_MAX_NV);
+ if (rv < 0) {
+ goto fail;
+ }
+
+ in += rv;
+
+ if (!rfin) {
+ goto almost_ok;
+ }
+
+ DEBUGF("inflatehd: valuelen=%zu\n", inflater->left);
+
+ if (inflater->huffman_encoded) {
+ nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
+
+ inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
+
+ rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left * 2 + 1,
+ mem);
+ } else {
+ inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
+
+ rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left + 1, mem);
+ }
+
+ if (rv != 0) {
+ goto fail;
+ }
+
+ nghttp2_buf_wrap_init(&inflater->valuebuf, inflater->valuercbuf->base,
+ inflater->valuercbuf->len);
+
+ busy = 1;
+
+ break;
+ case NGHTTP2_HD_STATE_READ_VALUEHUFF:
+ rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last);
+ if (rv < 0) {
+ goto fail;
+ }
+
+ in += rv;
+
+ DEBUGF("inflatehd: %zd bytes read\n", rv);
+
+ if (inflater->left) {
+ DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
+
+ goto almost_ok;
+ }
+
+ *inflater->valuebuf.last = '\0';
+ inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
+
+ if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
+ rv = hd_inflate_commit_newname(inflater, nv_out);
+ } else {
+ rv = hd_inflate_commit_indname(inflater, nv_out);
+ }
+
+ if (rv != 0) {
+ goto fail;
+ }
+
+ inflater->state = NGHTTP2_HD_STATE_OPCODE;
+ *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
+
+ return (ssize_t)(in - first);
+ case NGHTTP2_HD_STATE_READ_VALUE:
+ rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
+ if (rv < 0) {
+ DEBUGF("inflatehd: value read failure %zd: %s\n", rv,
+ nghttp2_strerror((int)rv));
+ goto fail;
+ }
+
+ in += rv;
+
+ DEBUGF("inflatehd: %zd bytes read\n", rv);
+
+ if (inflater->left) {
+ DEBUGF("inflatehd: still %zu bytes to go\n", inflater->left);
+ goto almost_ok;
+ }
+
+ *inflater->valuebuf.last = '\0';
+ inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
+
+ if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
+ rv = hd_inflate_commit_newname(inflater, nv_out);
+ } else {
+ rv = hd_inflate_commit_indname(inflater, nv_out);
+ }
+
+ if (rv != 0) {
+ goto fail;
+ }
+
+ inflater->state = NGHTTP2_HD_STATE_OPCODE;
+ *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
+
+ return (ssize_t)(in - first);
+ }
+ }
+
+ assert(in == last);
+
+ DEBUGF("inflatehd: all input bytes were processed\n");
+
+ if (in_final) {
+ DEBUGF("inflatehd: in_final set\n");
+
+ if (inflater->state != NGHTTP2_HD_STATE_OPCODE &&
+ inflater->state != NGHTTP2_HD_STATE_INFLATE_START) {
+ DEBUGF("inflatehd: unacceptable state=%d\n", inflater->state);
+ rv = NGHTTP2_ERR_HEADER_COMP;
+
+ goto fail;
+ }
+ *inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
+ }
+ return (ssize_t)(in - first);
+
+almost_ok:
+ if (in_final) {
+ DEBUGF("inflatehd: input ended prematurely\n");
+
+ rv = NGHTTP2_ERR_HEADER_COMP;
+
+ goto fail;
+ }
+ return (ssize_t)(in - first);
+
+fail:
+ DEBUGF("inflatehd: error return %zd\n", rv);
+
+ inflater->ctx.bad = 1;
+ return rv;
+}
+
+int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) {
+ hd_inflate_keep_free(inflater);
+ inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
+ return 0;
+}
+
+int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr) {
+ return nghttp2_hd_inflate_new2(inflater_ptr, NULL);
+}
+
+int nghttp2_hd_inflate_new2(nghttp2_hd_inflater **inflater_ptr,
+ nghttp2_mem *mem) {
+ int rv;
+ nghttp2_hd_inflater *inflater;
+
+ if (mem == NULL) {
+ mem = nghttp2_mem_default();
+ }
+
+ inflater = nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_inflater));
+
+ if (inflater == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ rv = nghttp2_hd_inflate_init(inflater, mem);
+
+ if (rv != 0) {
+ nghttp2_mem_free(mem, inflater);
+
+ return rv;
+ }
+
+ *inflater_ptr = inflater;
+
+ return 0;
+}
+
+void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater) {
+ nghttp2_mem *mem;
+
+ mem = inflater->ctx.mem;
+ nghttp2_hd_inflate_free(inflater);
+
+ nghttp2_mem_free(mem, inflater);
+}
+
+int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t idx,
+ nghttp2_nv *nv, int indexing_mode) {
+
+ return emit_indname_block(bufs, idx, nv, indexing_mode);
+}
+
+int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
+ int indexing_mode) {
+ return emit_newname_block(bufs, nv, indexing_mode);
+}
+
+int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size) {
+ return emit_table_size(bufs, table_size);
+}
+
+ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
+ uint32_t initial, size_t shift, uint8_t *in,
+ uint8_t *last, size_t prefix) {
+ return decode_length(res, shift_ptr, fin, initial, shift, in, last, prefix);
+}
+
+static const nghttp2_nv *hd_get_table_entry(nghttp2_hd_context *context,
+ size_t idx) {
+ if (idx == 0) {
+ return NULL;
+ }
+
+ --idx;
+
+ if (!INDEX_RANGE_VALID(context, idx)) {
+ return NULL;
+ }
+
+ return nghttp2_hd_table_get2(context, idx);
+}
+
+size_t nghttp2_hd_deflate_get_num_table_entries(nghttp2_hd_deflater *deflater) {
+ return get_max_index(&deflater->ctx);
+}
+
+const nghttp2_nv *
+nghttp2_hd_deflate_get_table_entry(nghttp2_hd_deflater *deflater, size_t idx) {
+ return hd_get_table_entry(&deflater->ctx, idx);
+}
+
+size_t
+nghttp2_hd_deflate_get_dynamic_table_size(nghttp2_hd_deflater *deflater) {
+ return deflater->ctx.hd_table_bufsize;
+}
+
+size_t
+nghttp2_hd_deflate_get_max_dynamic_table_size(nghttp2_hd_deflater *deflater) {
+ return deflater->ctx.hd_table_bufsize_max;
+}
+
+size_t nghttp2_hd_inflate_get_num_table_entries(nghttp2_hd_inflater *inflater) {
+ return get_max_index(&inflater->ctx);
+}
+
+const nghttp2_nv *
+nghttp2_hd_inflate_get_table_entry(nghttp2_hd_inflater *inflater, size_t idx) {
+ return hd_get_table_entry(&inflater->ctx, idx);
+}
+
+size_t
+nghttp2_hd_inflate_get_dynamic_table_size(nghttp2_hd_inflater *inflater) {
+ return inflater->ctx.hd_table_bufsize;
+}
+
+size_t
+nghttp2_hd_inflate_get_max_dynamic_table_size(nghttp2_hd_inflater *inflater) {
+ return inflater->ctx.hd_table_bufsize_max;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd.h
new file mode 100644
index 00000000..584dad39
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd.h
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_HD_H
+#define NGHTTP2_HD_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+#include "nghttp2_hd_huffman.h"
+#include "nghttp2_buf.h"
+#include "nghttp2_mem.h"
+#include "nghttp2_rcbuf.h"
+
+#define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE NGHTTP2_DEFAULT_HEADER_TABLE_SIZE
+#define NGHTTP2_HD_ENTRY_OVERHEAD 32
+
+/* The maximum length of one name/value pair. This is the sum of the
+ length of name and value. This is not specified by the spec. We
+ just chose the arbitrary size */
+#define NGHTTP2_HD_MAX_NV 65536
+
+/* Default size of maximum table buffer size for encoder. Even if
+ remote decoder notifies larger buffer size for its decoding,
+ encoder only uses the memory up to this value. */
+#define NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE (1 << 12)
+
+/* Exported for unit test */
+#define NGHTTP2_STATIC_TABLE_LENGTH 61
+
+/* Generated by genlibtokenlookup.py */
+typedef enum {
+ NGHTTP2_TOKEN__AUTHORITY = 0,
+ NGHTTP2_TOKEN__METHOD = 1,
+ NGHTTP2_TOKEN__PATH = 3,
+ NGHTTP2_TOKEN__SCHEME = 5,
+ NGHTTP2_TOKEN__STATUS = 7,
+ NGHTTP2_TOKEN_ACCEPT_CHARSET = 14,
+ NGHTTP2_TOKEN_ACCEPT_ENCODING = 15,
+ NGHTTP2_TOKEN_ACCEPT_LANGUAGE = 16,
+ NGHTTP2_TOKEN_ACCEPT_RANGES = 17,
+ NGHTTP2_TOKEN_ACCEPT = 18,
+ NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_ORIGIN = 19,
+ NGHTTP2_TOKEN_AGE = 20,
+ NGHTTP2_TOKEN_ALLOW = 21,
+ NGHTTP2_TOKEN_AUTHORIZATION = 22,
+ NGHTTP2_TOKEN_CACHE_CONTROL = 23,
+ NGHTTP2_TOKEN_CONTENT_DISPOSITION = 24,
+ NGHTTP2_TOKEN_CONTENT_ENCODING = 25,
+ NGHTTP2_TOKEN_CONTENT_LANGUAGE = 26,
+ NGHTTP2_TOKEN_CONTENT_LENGTH = 27,
+ NGHTTP2_TOKEN_CONTENT_LOCATION = 28,
+ NGHTTP2_TOKEN_CONTENT_RANGE = 29,
+ NGHTTP2_TOKEN_CONTENT_TYPE = 30,
+ NGHTTP2_TOKEN_COOKIE = 31,
+ NGHTTP2_TOKEN_DATE = 32,
+ NGHTTP2_TOKEN_ETAG = 33,
+ NGHTTP2_TOKEN_EXPECT = 34,
+ NGHTTP2_TOKEN_EXPIRES = 35,
+ NGHTTP2_TOKEN_FROM = 36,
+ NGHTTP2_TOKEN_HOST = 37,
+ NGHTTP2_TOKEN_IF_MATCH = 38,
+ NGHTTP2_TOKEN_IF_MODIFIED_SINCE = 39,
+ NGHTTP2_TOKEN_IF_NONE_MATCH = 40,
+ NGHTTP2_TOKEN_IF_RANGE = 41,
+ NGHTTP2_TOKEN_IF_UNMODIFIED_SINCE = 42,
+ NGHTTP2_TOKEN_LAST_MODIFIED = 43,
+ NGHTTP2_TOKEN_LINK = 44,
+ NGHTTP2_TOKEN_LOCATION = 45,
+ NGHTTP2_TOKEN_MAX_FORWARDS = 46,
+ NGHTTP2_TOKEN_PROXY_AUTHENTICATE = 47,
+ NGHTTP2_TOKEN_PROXY_AUTHORIZATION = 48,
+ NGHTTP2_TOKEN_RANGE = 49,
+ NGHTTP2_TOKEN_REFERER = 50,
+ NGHTTP2_TOKEN_REFRESH = 51,
+ NGHTTP2_TOKEN_RETRY_AFTER = 52,
+ NGHTTP2_TOKEN_SERVER = 53,
+ NGHTTP2_TOKEN_SET_COOKIE = 54,
+ NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY = 55,
+ NGHTTP2_TOKEN_TRANSFER_ENCODING = 56,
+ NGHTTP2_TOKEN_USER_AGENT = 57,
+ NGHTTP2_TOKEN_VARY = 58,
+ NGHTTP2_TOKEN_VIA = 59,
+ NGHTTP2_TOKEN_WWW_AUTHENTICATE = 60,
+ NGHTTP2_TOKEN_TE,
+ NGHTTP2_TOKEN_CONNECTION,
+ NGHTTP2_TOKEN_KEEP_ALIVE,
+ NGHTTP2_TOKEN_PROXY_CONNECTION,
+ NGHTTP2_TOKEN_UPGRADE,
+} nghttp2_token;
+
+struct nghttp2_hd_entry;
+typedef struct nghttp2_hd_entry nghttp2_hd_entry;
+
+typedef struct {
+ /* The buffer containing header field name. NULL-termination is
+ guaranteed. */
+ nghttp2_rcbuf *name;
+ /* The buffer containing header field value. NULL-termination is
+ guaranteed. */
+ nghttp2_rcbuf *value;
+ /* nghttp2_token value for name. It could be -1 if we have no token
+ for that header field name. */
+ int32_t token;
+ /* Bitwise OR of one or more of nghttp2_nv_flag. */
+ uint8_t flags;
+} nghttp2_hd_nv;
+
+struct nghttp2_hd_entry {
+ /* The header field name/value pair */
+ nghttp2_hd_nv nv;
+ /* This is solely for nghttp2_hd_{deflate,inflate}_get_table_entry
+ APIs to keep backward compatibility. */
+ nghttp2_nv cnv;
+ /* The next entry which shares same bucket in hash table. */
+ nghttp2_hd_entry *next;
+ /* The sequence number. We will increment it by one whenever we
+ store nghttp2_hd_entry to dynamic header table. */
+ uint32_t seq;
+ /* The hash value for header name (nv.name). */
+ uint32_t hash;
+};
+
+/* The entry used for static header table. */
+typedef struct {
+ nghttp2_rcbuf name;
+ nghttp2_rcbuf value;
+ nghttp2_nv cnv;
+ int32_t token;
+ uint32_t hash;
+} nghttp2_hd_static_entry;
+
+typedef struct {
+ nghttp2_hd_entry **buffer;
+ size_t mask;
+ size_t first;
+ size_t len;
+} nghttp2_hd_ringbuf;
+
+typedef enum {
+ NGHTTP2_HD_OPCODE_NONE,
+ NGHTTP2_HD_OPCODE_INDEXED,
+ NGHTTP2_HD_OPCODE_NEWNAME,
+ NGHTTP2_HD_OPCODE_INDNAME
+} nghttp2_hd_opcode;
+
+typedef enum {
+ NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE,
+ NGHTTP2_HD_STATE_INFLATE_START,
+ NGHTTP2_HD_STATE_OPCODE,
+ NGHTTP2_HD_STATE_READ_TABLE_SIZE,
+ NGHTTP2_HD_STATE_READ_INDEX,
+ NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN,
+ NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN,
+ NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF,
+ NGHTTP2_HD_STATE_NEWNAME_READ_NAME,
+ NGHTTP2_HD_STATE_CHECK_VALUELEN,
+ NGHTTP2_HD_STATE_READ_VALUELEN,
+ NGHTTP2_HD_STATE_READ_VALUEHUFF,
+ NGHTTP2_HD_STATE_READ_VALUE
+} nghttp2_hd_inflate_state;
+
+typedef enum {
+ NGHTTP2_HD_WITH_INDEXING,
+ NGHTTP2_HD_WITHOUT_INDEXING,
+ NGHTTP2_HD_NEVER_INDEXING
+} nghttp2_hd_indexing_mode;
+
+typedef struct {
+ /* dynamic header table */
+ nghttp2_hd_ringbuf hd_table;
+ /* Memory allocator */
+ nghttp2_mem *mem;
+ /* Abstract buffer size of hd_table as described in the spec. This
+ is the sum of length of name/value in hd_table +
+ NGHTTP2_HD_ENTRY_OVERHEAD bytes overhead per each entry. */
+ size_t hd_table_bufsize;
+ /* The effective header table size. */
+ size_t hd_table_bufsize_max;
+ /* Next sequence number for nghttp2_hd_entry */
+ uint32_t next_seq;
+ /* If inflate/deflate error occurred, this value is set to 1 and
+ further invocation of inflate/deflate will fail with
+ NGHTTP2_ERR_HEADER_COMP. */
+ uint8_t bad;
+} nghttp2_hd_context;
+
+#define HD_MAP_SIZE 128
+
+typedef struct {
+ nghttp2_hd_entry *table[HD_MAP_SIZE];
+} nghttp2_hd_map;
+
+struct nghttp2_hd_deflater {
+ nghttp2_hd_context ctx;
+ nghttp2_hd_map map;
+ /* The upper limit of the header table size the deflater accepts. */
+ size_t deflate_hd_table_bufsize_max;
+ /* Minimum header table size notified in the next context update */
+ size_t min_hd_table_bufsize_max;
+ /* If nonzero, send header table size using encoding context update
+ in the next deflate process */
+ uint8_t notify_table_size_change;
+};
+
+struct nghttp2_hd_inflater {
+ nghttp2_hd_context ctx;
+ /* Stores current state of huffman decoding */
+ nghttp2_hd_huff_decode_context huff_decode_ctx;
+ /* header buffer */
+ nghttp2_buf namebuf, valuebuf;
+ nghttp2_rcbuf *namercbuf, *valuercbuf;
+ /* Pointer to the name/value pair which are used in the current
+ header emission. */
+ nghttp2_rcbuf *nv_name_keep, *nv_value_keep;
+ /* The number of bytes to read */
+ size_t left;
+ /* The index in indexed repr or indexed name */
+ size_t index;
+ /* The maximum header table size the inflater supports. This is the
+ same value transmitted in SETTINGS_HEADER_TABLE_SIZE */
+ size_t settings_hd_table_bufsize_max;
+ /* Minimum header table size set by nghttp2_hd_inflate_change_table_size */
+ size_t min_hd_table_bufsize_max;
+ /* The number of next shift to decode integer */
+ size_t shift;
+ nghttp2_hd_opcode opcode;
+ nghttp2_hd_inflate_state state;
+ /* nonzero if string is huffman encoded */
+ uint8_t huffman_encoded;
+ /* nonzero if deflater requires that current entry is indexed */
+ uint8_t index_required;
+ /* nonzero if deflater requires that current entry must not be
+ indexed */
+ uint8_t no_index;
+};
+
+/*
+ * Initializes the |ent| members. The reference counts of nv->name
+ * and nv->value are increased by one for each.
+ */
+void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv);
+
+/*
+ * This function decreases the reference counts of nv->name and
+ * nv->value.
+ */
+void nghttp2_hd_entry_free(nghttp2_hd_entry *ent);
+
+/*
+ * Initializes |deflater| for deflating name/values pairs.
+ *
+ * The encoder only uses up to
+ * NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE bytes for header table
+ * even if the larger value is specified later in
+ * nghttp2_hd_change_table_size().
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem);
+
+/*
+ * Initializes |deflater| for deflating name/values pairs.
+ *
+ * The encoder only uses up to |max_deflate_dynamic_table_size| bytes
+ * for header table even if the larger value is specified later in
+ * nghttp2_hd_change_table_size().
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
+ size_t max_deflate_dynamic_table_size,
+ nghttp2_mem *mem);
+
+/*
+ * Deallocates any resources allocated for |deflater|.
+ */
+void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater);
+
+/*
+ * Deflates the |nva|, which has the |nvlen| name/value pairs, into
+ * the |bufs|.
+ *
+ * This function expands |bufs| as necessary to store the result. If
+ * buffers is full and the process still requires more space, this
+ * function fails and returns NGHTTP2_ERR_HEADER_COMP.
+ *
+ * After this function returns, it is safe to delete the |nva|.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_HEADER_COMP
+ * Deflation process has failed.
+ * NGHTTP2_ERR_BUFFER_ERROR
+ * Out of buffer space.
+ */
+int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
+ nghttp2_bufs *bufs, const nghttp2_nv *nva,
+ size_t nvlen);
+
+/*
+ * Initializes |inflater| for inflating name/values pairs.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ */
+int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem);
+
+/*
+ * Deallocates any resources allocated for |inflater|.
+ */
+void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater);
+
+/*
+ * Similar to nghttp2_hd_inflate_hd(), but this takes nghttp2_hd_nv
+ * instead of nghttp2_nv as output parameter |nv_out|. Other than
+ * that return values and semantics are the same as
+ * nghttp2_hd_inflate_hd().
+ */
+ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
+ nghttp2_hd_nv *nv_out, int *inflate_flags,
+ const uint8_t *in, size_t inlen, int in_final);
+
+/* For unittesting purpose */
+int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index,
+ nghttp2_nv *nv, int indexing_mode);
+
+/* For unittesting purpose */
+int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
+ int indexing_mode);
+
+/* For unittesting purpose */
+int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size);
+
+/* For unittesting purpose */
+nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t index);
+
+/* For unittesting purpose */
+ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *fin,
+ uint32_t initial, size_t shift, uint8_t *in,
+ uint8_t *last, size_t prefix);
+
+/* Huffman encoding/decoding functions */
+
+/*
+ * Counts the required bytes to encode |src| with length |len|.
+ *
+ * This function returns the number of required bytes to encode given
+ * data, including padding of prefix of terminal symbol code. This
+ * function always succeeds.
+ */
+size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len);
+
+/*
+ * Encodes the given data |src| with length |srclen| to the |bufs|.
+ * This function expands extra buffers in |bufs| if necessary.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_BUFFER_ERROR
+ * Out of buffer space.
+ */
+int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,
+ size_t srclen);
+
+void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
+
+/*
+ * Decodes the given data |src| with length |srclen|. The |ctx| must
+ * be initialized by nghttp2_hd_huff_decode_context_init(). The result
+ * will be written to |buf|. This function assumes that |buf| has the
+ * enough room to store the decoded byte string.
+ *
+ * The caller must set the |fin| to nonzero if the given input is the
+ * final block.
+ *
+ * This function returns the number of read bytes from the |in|.
+ *
+ * If this function fails, it returns one of the following negative
+ * return codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_HEADER_COMP
+ * Decoding process has failed.
+ */
+ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
+ nghttp2_buf *buf, const uint8_t *src,
+ size_t srclen, int fin);
+
+#endif /* NGHTTP2_HD_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd_huffman.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd_huffman.c
new file mode 100644
index 00000000..661668de
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd_huffman.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_hd_huffman.h"
+
+#include
+#include
+#include
+
+#include "nghttp2_hd.h"
+
+/*
+ * Encodes huffman code |sym| into |*dest_ptr|, whose least |rembits|
+ * bits are not filled yet. The |rembits| must be in range [1, 8],
+ * inclusive. At the end of the process, the |*dest_ptr| is updated
+ * and points where next output should be placed. The number of
+ * unfilled bits in the pointed location is returned.
+ */
+static ssize_t huff_encode_sym(nghttp2_bufs *bufs, size_t *avail_ptr,
+ size_t rembits, const nghttp2_huff_sym *sym) {
+ int rv;
+ size_t nbits = sym->nbits;
+ uint32_t code = sym->code;
+
+ /* We assume that sym->nbits <= 32 */
+ if (rembits > nbits) {
+ nghttp2_bufs_fast_orb_hold(bufs, (uint8_t)(code << (rembits - nbits)));
+ return (ssize_t)(rembits - nbits);
+ }
+
+ if (rembits == nbits) {
+ nghttp2_bufs_fast_orb(bufs, (uint8_t)code);
+ --*avail_ptr;
+ return 8;
+ }
+
+ nghttp2_bufs_fast_orb(bufs, (uint8_t)(code >> (nbits - rembits)));
+ --*avail_ptr;
+
+ nbits -= rembits;
+ if (nbits & 0x7) {
+ /* align code to MSB byte boundary */
+ code <<= 8 - (nbits & 0x7);
+ }
+
+ if (*avail_ptr < (nbits + 7) / 8) {
+ /* slow path */
+ if (nbits > 24) {
+ rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 24));
+ if (rv != 0) {
+ return rv;
+ }
+ nbits -= 8;
+ }
+ if (nbits > 16) {
+ rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 16));
+ if (rv != 0) {
+ return rv;
+ }
+ nbits -= 8;
+ }
+ if (nbits > 8) {
+ rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 8));
+ if (rv != 0) {
+ return rv;
+ }
+ nbits -= 8;
+ }
+ if (nbits == 8) {
+ rv = nghttp2_bufs_addb(bufs, (uint8_t)code);
+ if (rv != 0) {
+ return rv;
+ }
+ *avail_ptr = nghttp2_bufs_cur_avail(bufs);
+ return 8;
+ }
+
+ rv = nghttp2_bufs_addb_hold(bufs, (uint8_t)code);
+ if (rv != 0) {
+ return rv;
+ }
+ *avail_ptr = nghttp2_bufs_cur_avail(bufs);
+ return (ssize_t)(8 - nbits);
+ }
+
+ /* fast path, since most code is less than 8 */
+ if (nbits < 8) {
+ nghttp2_bufs_fast_addb_hold(bufs, (uint8_t)code);
+ *avail_ptr = nghttp2_bufs_cur_avail(bufs);
+ return (ssize_t)(8 - nbits);
+ }
+
+ /* handle longer code path */
+ if (nbits > 24) {
+ nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 24));
+ nbits -= 8;
+ }
+
+ if (nbits > 16) {
+ nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 16));
+ nbits -= 8;
+ }
+
+ if (nbits > 8) {
+ nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 8));
+ nbits -= 8;
+ }
+
+ if (nbits == 8) {
+ nghttp2_bufs_fast_addb(bufs, (uint8_t)code);
+ *avail_ptr = nghttp2_bufs_cur_avail(bufs);
+ return 8;
+ }
+
+ nghttp2_bufs_fast_addb_hold(bufs, (uint8_t)code);
+ *avail_ptr = nghttp2_bufs_cur_avail(bufs);
+ return (ssize_t)(8 - nbits);
+}
+
+size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len) {
+ size_t i;
+ size_t nbits = 0;
+
+ for (i = 0; i < len; ++i) {
+ nbits += huff_sym_table[src[i]].nbits;
+ }
+ /* pad the prefix of EOS (256) */
+ return (nbits + 7) / 8;
+}
+
+int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,
+ size_t srclen) {
+ int rv;
+ ssize_t rembits = 8;
+ size_t i;
+ size_t avail;
+
+ avail = nghttp2_bufs_cur_avail(bufs);
+
+ for (i = 0; i < srclen; ++i) {
+ const nghttp2_huff_sym *sym = &huff_sym_table[src[i]];
+ if (rembits == 8) {
+ if (avail) {
+ nghttp2_bufs_fast_addb_hold(bufs, 0);
+ } else {
+ rv = nghttp2_bufs_addb_hold(bufs, 0);
+ if (rv != 0) {
+ return rv;
+ }
+ avail = nghttp2_bufs_cur_avail(bufs);
+ }
+ }
+ rembits = huff_encode_sym(bufs, &avail, (size_t)rembits, sym);
+ if (rembits < 0) {
+ return (int)rembits;
+ }
+ }
+ /* 256 is special terminal symbol, pad with its prefix */
+ if (rembits < 8) {
+ /* if rembits < 8, we should have at least 1 buffer space
+ available */
+ const nghttp2_huff_sym *sym = &huff_sym_table[256];
+ assert(avail);
+ /* Caution we no longer adjust avail here */
+ nghttp2_bufs_fast_orb(
+ bufs, (uint8_t)(sym->code >> (sym->nbits - (size_t)rembits)));
+ }
+
+ return 0;
+}
+
+void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
+ ctx->state = 0;
+ ctx->accept = 1;
+}
+
+ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
+ nghttp2_buf *buf, const uint8_t *src,
+ size_t srclen, int final) {
+ size_t i;
+
+ /* We use the decoding algorithm described in
+ http://graphics.ics.uci.edu/pub/Prefix.pdf */
+ for (i = 0; i < srclen; ++i) {
+ const nghttp2_huff_decode *t;
+
+ t = &huff_decode_table[ctx->state][src[i] >> 4];
+ if (t->flags & NGHTTP2_HUFF_FAIL) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+ if (t->flags & NGHTTP2_HUFF_SYM) {
+ *buf->last++ = t->sym;
+ }
+
+ t = &huff_decode_table[t->state][src[i] & 0xf];
+ if (t->flags & NGHTTP2_HUFF_FAIL) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+ if (t->flags & NGHTTP2_HUFF_SYM) {
+ *buf->last++ = t->sym;
+ }
+
+ ctx->state = t->state;
+ ctx->accept = (t->flags & NGHTTP2_HUFF_ACCEPTED) != 0;
+ }
+ if (final && !ctx->accept) {
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+ return (ssize_t)i;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd_huffman.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd_huffman.h
new file mode 100644
index 00000000..979f6b12
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd_huffman.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_HD_HUFFMAN_H
+#define NGHTTP2_HD_HUFFMAN_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+typedef enum {
+ /* FSA accepts this state as the end of huffman encoding
+ sequence. */
+ NGHTTP2_HUFF_ACCEPTED = 1,
+ /* This state emits symbol */
+ NGHTTP2_HUFF_SYM = (1 << 1),
+ /* If state machine reaches this state, decoding fails. */
+ NGHTTP2_HUFF_FAIL = (1 << 2)
+} nghttp2_huff_decode_flag;
+
+typedef struct {
+ /* huffman decoding state, which is actually the node ID of internal
+ huffman tree. We have 257 leaf nodes, but they are identical to
+ root node other than emitting a symbol, so we have 256 internal
+ nodes [1..255], inclusive. */
+ uint8_t state;
+ /* bitwise OR of zero or more of the nghttp2_huff_decode_flag */
+ uint8_t flags;
+ /* symbol if NGHTTP2_HUFF_SYM flag set */
+ uint8_t sym;
+} nghttp2_huff_decode;
+
+typedef nghttp2_huff_decode huff_decode_table_type[16];
+
+typedef struct {
+ /* Current huffman decoding state. We stripped leaf nodes, so the
+ value range is [0..255], inclusive. */
+ uint8_t state;
+ /* nonzero if we can say that the decoding process succeeds at this
+ state */
+ uint8_t accept;
+} nghttp2_hd_huff_decode_context;
+
+typedef struct {
+ /* The number of bits in this code */
+ uint32_t nbits;
+ /* Huffman code aligned to LSB */
+ uint32_t code;
+} nghttp2_huff_sym;
+
+extern const nghttp2_huff_sym huff_sym_table[];
+extern const nghttp2_huff_decode huff_decode_table[][16];
+
+#endif /* NGHTTP2_HD_HUFFMAN_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd_huffman_data.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd_huffman_data.c
new file mode 100644
index 00000000..085b2e92
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_hd_huffman_data.c
@@ -0,0 +1,4942 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_hd_huffman.h"
+
+/* Generated by mkhufftbl.py */
+
+const nghttp2_huff_sym huff_sym_table[] = {
+ {13, 0x1ff8u}, {23, 0x7fffd8u}, {28, 0xfffffe2u}, {28, 0xfffffe3u},
+ {28, 0xfffffe4u}, {28, 0xfffffe5u}, {28, 0xfffffe6u}, {28, 0xfffffe7u},
+ {28, 0xfffffe8u}, {24, 0xffffeau}, {30, 0x3ffffffcu}, {28, 0xfffffe9u},
+ {28, 0xfffffeau}, {30, 0x3ffffffdu}, {28, 0xfffffebu}, {28, 0xfffffecu},
+ {28, 0xfffffedu}, {28, 0xfffffeeu}, {28, 0xfffffefu}, {28, 0xffffff0u},
+ {28, 0xffffff1u}, {28, 0xffffff2u}, {30, 0x3ffffffeu}, {28, 0xffffff3u},
+ {28, 0xffffff4u}, {28, 0xffffff5u}, {28, 0xffffff6u}, {28, 0xffffff7u},
+ {28, 0xffffff8u}, {28, 0xffffff9u}, {28, 0xffffffau}, {28, 0xffffffbu},
+ {6, 0x14u}, {10, 0x3f8u}, {10, 0x3f9u}, {12, 0xffau},
+ {13, 0x1ff9u}, {6, 0x15u}, {8, 0xf8u}, {11, 0x7fau},
+ {10, 0x3fau}, {10, 0x3fbu}, {8, 0xf9u}, {11, 0x7fbu},
+ {8, 0xfau}, {6, 0x16u}, {6, 0x17u}, {6, 0x18u},
+ {5, 0x0u}, {5, 0x1u}, {5, 0x2u}, {6, 0x19u},
+ {6, 0x1au}, {6, 0x1bu}, {6, 0x1cu}, {6, 0x1du},
+ {6, 0x1eu}, {6, 0x1fu}, {7, 0x5cu}, {8, 0xfbu},
+ {15, 0x7ffcu}, {6, 0x20u}, {12, 0xffbu}, {10, 0x3fcu},
+ {13, 0x1ffau}, {6, 0x21u}, {7, 0x5du}, {7, 0x5eu},
+ {7, 0x5fu}, {7, 0x60u}, {7, 0x61u}, {7, 0x62u},
+ {7, 0x63u}, {7, 0x64u}, {7, 0x65u}, {7, 0x66u},
+ {7, 0x67u}, {7, 0x68u}, {7, 0x69u}, {7, 0x6au},
+ {7, 0x6bu}, {7, 0x6cu}, {7, 0x6du}, {7, 0x6eu},
+ {7, 0x6fu}, {7, 0x70u}, {7, 0x71u}, {7, 0x72u},
+ {8, 0xfcu}, {7, 0x73u}, {8, 0xfdu}, {13, 0x1ffbu},
+ {19, 0x7fff0u}, {13, 0x1ffcu}, {14, 0x3ffcu}, {6, 0x22u},
+ {15, 0x7ffdu}, {5, 0x3u}, {6, 0x23u}, {5, 0x4u},
+ {6, 0x24u}, {5, 0x5u}, {6, 0x25u}, {6, 0x26u},
+ {6, 0x27u}, {5, 0x6u}, {7, 0x74u}, {7, 0x75u},
+ {6, 0x28u}, {6, 0x29u}, {6, 0x2au}, {5, 0x7u},
+ {6, 0x2bu}, {7, 0x76u}, {6, 0x2cu}, {5, 0x8u},
+ {5, 0x9u}, {6, 0x2du}, {7, 0x77u}, {7, 0x78u},
+ {7, 0x79u}, {7, 0x7au}, {7, 0x7bu}, {15, 0x7ffeu},
+ {11, 0x7fcu}, {14, 0x3ffdu}, {13, 0x1ffdu}, {28, 0xffffffcu},
+ {20, 0xfffe6u}, {22, 0x3fffd2u}, {20, 0xfffe7u}, {20, 0xfffe8u},
+ {22, 0x3fffd3u}, {22, 0x3fffd4u}, {22, 0x3fffd5u}, {23, 0x7fffd9u},
+ {22, 0x3fffd6u}, {23, 0x7fffdau}, {23, 0x7fffdbu}, {23, 0x7fffdcu},
+ {23, 0x7fffddu}, {23, 0x7fffdeu}, {24, 0xffffebu}, {23, 0x7fffdfu},
+ {24, 0xffffecu}, {24, 0xffffedu}, {22, 0x3fffd7u}, {23, 0x7fffe0u},
+ {24, 0xffffeeu}, {23, 0x7fffe1u}, {23, 0x7fffe2u}, {23, 0x7fffe3u},
+ {23, 0x7fffe4u}, {21, 0x1fffdcu}, {22, 0x3fffd8u}, {23, 0x7fffe5u},
+ {22, 0x3fffd9u}, {23, 0x7fffe6u}, {23, 0x7fffe7u}, {24, 0xffffefu},
+ {22, 0x3fffdau}, {21, 0x1fffddu}, {20, 0xfffe9u}, {22, 0x3fffdbu},
+ {22, 0x3fffdcu}, {23, 0x7fffe8u}, {23, 0x7fffe9u}, {21, 0x1fffdeu},
+ {23, 0x7fffeau}, {22, 0x3fffddu}, {22, 0x3fffdeu}, {24, 0xfffff0u},
+ {21, 0x1fffdfu}, {22, 0x3fffdfu}, {23, 0x7fffebu}, {23, 0x7fffecu},
+ {21, 0x1fffe0u}, {21, 0x1fffe1u}, {22, 0x3fffe0u}, {21, 0x1fffe2u},
+ {23, 0x7fffedu}, {22, 0x3fffe1u}, {23, 0x7fffeeu}, {23, 0x7fffefu},
+ {20, 0xfffeau}, {22, 0x3fffe2u}, {22, 0x3fffe3u}, {22, 0x3fffe4u},
+ {23, 0x7ffff0u}, {22, 0x3fffe5u}, {22, 0x3fffe6u}, {23, 0x7ffff1u},
+ {26, 0x3ffffe0u}, {26, 0x3ffffe1u}, {20, 0xfffebu}, {19, 0x7fff1u},
+ {22, 0x3fffe7u}, {23, 0x7ffff2u}, {22, 0x3fffe8u}, {25, 0x1ffffecu},
+ {26, 0x3ffffe2u}, {26, 0x3ffffe3u}, {26, 0x3ffffe4u}, {27, 0x7ffffdeu},
+ {27, 0x7ffffdfu}, {26, 0x3ffffe5u}, {24, 0xfffff1u}, {25, 0x1ffffedu},
+ {19, 0x7fff2u}, {21, 0x1fffe3u}, {26, 0x3ffffe6u}, {27, 0x7ffffe0u},
+ {27, 0x7ffffe1u}, {26, 0x3ffffe7u}, {27, 0x7ffffe2u}, {24, 0xfffff2u},
+ {21, 0x1fffe4u}, {21, 0x1fffe5u}, {26, 0x3ffffe8u}, {26, 0x3ffffe9u},
+ {28, 0xffffffdu}, {27, 0x7ffffe3u}, {27, 0x7ffffe4u}, {27, 0x7ffffe5u},
+ {20, 0xfffecu}, {24, 0xfffff3u}, {20, 0xfffedu}, {21, 0x1fffe6u},
+ {22, 0x3fffe9u}, {21, 0x1fffe7u}, {21, 0x1fffe8u}, {23, 0x7ffff3u},
+ {22, 0x3fffeau}, {22, 0x3fffebu}, {25, 0x1ffffeeu}, {25, 0x1ffffefu},
+ {24, 0xfffff4u}, {24, 0xfffff5u}, {26, 0x3ffffeau}, {23, 0x7ffff4u},
+ {26, 0x3ffffebu}, {27, 0x7ffffe6u}, {26, 0x3ffffecu}, {26, 0x3ffffedu},
+ {27, 0x7ffffe7u}, {27, 0x7ffffe8u}, {27, 0x7ffffe9u}, {27, 0x7ffffeau},
+ {27, 0x7ffffebu}, {28, 0xffffffeu}, {27, 0x7ffffecu}, {27, 0x7ffffedu},
+ {27, 0x7ffffeeu}, {27, 0x7ffffefu}, {27, 0x7fffff0u}, {26, 0x3ffffeeu},
+ {30, 0x3fffffffu}};
+
+const nghttp2_huff_decode huff_decode_table[][16] = {
+ /* 0 */
+ {
+ {4, 0x00, 0},
+ {5, 0x00, 0},
+ {7, 0x00, 0},
+ {8, 0x00, 0},
+ {11, 0x00, 0},
+ {12, 0x00, 0},
+ {16, 0x00, 0},
+ {19, 0x00, 0},
+ {25, 0x00, 0},
+ {28, 0x00, 0},
+ {32, 0x00, 0},
+ {35, 0x00, 0},
+ {42, 0x00, 0},
+ {49, 0x00, 0},
+ {57, 0x00, 0},
+ {64, 0x01, 0},
+ },
+ /* 1 */
+ {
+ {0, 0x03, 48},
+ {0, 0x03, 49},
+ {0, 0x03, 50},
+ {0, 0x03, 97},
+ {0, 0x03, 99},
+ {0, 0x03, 101},
+ {0, 0x03, 105},
+ {0, 0x03, 111},
+ {0, 0x03, 115},
+ {0, 0x03, 116},
+ {13, 0x00, 0},
+ {14, 0x00, 0},
+ {17, 0x00, 0},
+ {18, 0x00, 0},
+ {20, 0x00, 0},
+ {21, 0x00, 0},
+ },
+ /* 2 */
+ {
+ {1, 0x02, 48},
+ {22, 0x03, 48},
+ {1, 0x02, 49},
+ {22, 0x03, 49},
+ {1, 0x02, 50},
+ {22, 0x03, 50},
+ {1, 0x02, 97},
+ {22, 0x03, 97},
+ {1, 0x02, 99},
+ {22, 0x03, 99},
+ {1, 0x02, 101},
+ {22, 0x03, 101},
+ {1, 0x02, 105},
+ {22, 0x03, 105},
+ {1, 0x02, 111},
+ {22, 0x03, 111},
+ },
+ /* 3 */
+ {
+ {2, 0x02, 48},
+ {9, 0x02, 48},
+ {23, 0x02, 48},
+ {40, 0x03, 48},
+ {2, 0x02, 49},
+ {9, 0x02, 49},
+ {23, 0x02, 49},
+ {40, 0x03, 49},
+ {2, 0x02, 50},
+ {9, 0x02, 50},
+ {23, 0x02, 50},
+ {40, 0x03, 50},
+ {2, 0x02, 97},
+ {9, 0x02, 97},
+ {23, 0x02, 97},
+ {40, 0x03, 97},
+ },
+ /* 4 */
+ {
+ {3, 0x02, 48},
+ {6, 0x02, 48},
+ {10, 0x02, 48},
+ {15, 0x02, 48},
+ {24, 0x02, 48},
+ {31, 0x02, 48},
+ {41, 0x02, 48},
+ {56, 0x03, 48},
+ {3, 0x02, 49},
+ {6, 0x02, 49},
+ {10, 0x02, 49},
+ {15, 0x02, 49},
+ {24, 0x02, 49},
+ {31, 0x02, 49},
+ {41, 0x02, 49},
+ {56, 0x03, 49},
+ },
+ /* 5 */
+ {
+ {3, 0x02, 50},
+ {6, 0x02, 50},
+ {10, 0x02, 50},
+ {15, 0x02, 50},
+ {24, 0x02, 50},
+ {31, 0x02, 50},
+ {41, 0x02, 50},
+ {56, 0x03, 50},
+ {3, 0x02, 97},
+ {6, 0x02, 97},
+ {10, 0x02, 97},
+ {15, 0x02, 97},
+ {24, 0x02, 97},
+ {31, 0x02, 97},
+ {41, 0x02, 97},
+ {56, 0x03, 97},
+ },
+ /* 6 */
+ {
+ {2, 0x02, 99},
+ {9, 0x02, 99},
+ {23, 0x02, 99},
+ {40, 0x03, 99},
+ {2, 0x02, 101},
+ {9, 0x02, 101},
+ {23, 0x02, 101},
+ {40, 0x03, 101},
+ {2, 0x02, 105},
+ {9, 0x02, 105},
+ {23, 0x02, 105},
+ {40, 0x03, 105},
+ {2, 0x02, 111},
+ {9, 0x02, 111},
+ {23, 0x02, 111},
+ {40, 0x03, 111},
+ },
+ /* 7 */
+ {
+ {3, 0x02, 99},
+ {6, 0x02, 99},
+ {10, 0x02, 99},
+ {15, 0x02, 99},
+ {24, 0x02, 99},
+ {31, 0x02, 99},
+ {41, 0x02, 99},
+ {56, 0x03, 99},
+ {3, 0x02, 101},
+ {6, 0x02, 101},
+ {10, 0x02, 101},
+ {15, 0x02, 101},
+ {24, 0x02, 101},
+ {31, 0x02, 101},
+ {41, 0x02, 101},
+ {56, 0x03, 101},
+ },
+ /* 8 */
+ {
+ {3, 0x02, 105},
+ {6, 0x02, 105},
+ {10, 0x02, 105},
+ {15, 0x02, 105},
+ {24, 0x02, 105},
+ {31, 0x02, 105},
+ {41, 0x02, 105},
+ {56, 0x03, 105},
+ {3, 0x02, 111},
+ {6, 0x02, 111},
+ {10, 0x02, 111},
+ {15, 0x02, 111},
+ {24, 0x02, 111},
+ {31, 0x02, 111},
+ {41, 0x02, 111},
+ {56, 0x03, 111},
+ },
+ /* 9 */
+ {
+ {1, 0x02, 115},
+ {22, 0x03, 115},
+ {1, 0x02, 116},
+ {22, 0x03, 116},
+ {0, 0x03, 32},
+ {0, 0x03, 37},
+ {0, 0x03, 45},
+ {0, 0x03, 46},
+ {0, 0x03, 47},
+ {0, 0x03, 51},
+ {0, 0x03, 52},
+ {0, 0x03, 53},
+ {0, 0x03, 54},
+ {0, 0x03, 55},
+ {0, 0x03, 56},
+ {0, 0x03, 57},
+ },
+ /* 10 */
+ {
+ {2, 0x02, 115},
+ {9, 0x02, 115},
+ {23, 0x02, 115},
+ {40, 0x03, 115},
+ {2, 0x02, 116},
+ {9, 0x02, 116},
+ {23, 0x02, 116},
+ {40, 0x03, 116},
+ {1, 0x02, 32},
+ {22, 0x03, 32},
+ {1, 0x02, 37},
+ {22, 0x03, 37},
+ {1, 0x02, 45},
+ {22, 0x03, 45},
+ {1, 0x02, 46},
+ {22, 0x03, 46},
+ },
+ /* 11 */
+ {
+ {3, 0x02, 115},
+ {6, 0x02, 115},
+ {10, 0x02, 115},
+ {15, 0x02, 115},
+ {24, 0x02, 115},
+ {31, 0x02, 115},
+ {41, 0x02, 115},
+ {56, 0x03, 115},
+ {3, 0x02, 116},
+ {6, 0x02, 116},
+ {10, 0x02, 116},
+ {15, 0x02, 116},
+ {24, 0x02, 116},
+ {31, 0x02, 116},
+ {41, 0x02, 116},
+ {56, 0x03, 116},
+ },
+ /* 12 */
+ {
+ {2, 0x02, 32},
+ {9, 0x02, 32},
+ {23, 0x02, 32},
+ {40, 0x03, 32},
+ {2, 0x02, 37},
+ {9, 0x02, 37},
+ {23, 0x02, 37},
+ {40, 0x03, 37},
+ {2, 0x02, 45},
+ {9, 0x02, 45},
+ {23, 0x02, 45},
+ {40, 0x03, 45},
+ {2, 0x02, 46},
+ {9, 0x02, 46},
+ {23, 0x02, 46},
+ {40, 0x03, 46},
+ },
+ /* 13 */
+ {
+ {3, 0x02, 32},
+ {6, 0x02, 32},
+ {10, 0x02, 32},
+ {15, 0x02, 32},
+ {24, 0x02, 32},
+ {31, 0x02, 32},
+ {41, 0x02, 32},
+ {56, 0x03, 32},
+ {3, 0x02, 37},
+ {6, 0x02, 37},
+ {10, 0x02, 37},
+ {15, 0x02, 37},
+ {24, 0x02, 37},
+ {31, 0x02, 37},
+ {41, 0x02, 37},
+ {56, 0x03, 37},
+ },
+ /* 14 */
+ {
+ {3, 0x02, 45},
+ {6, 0x02, 45},
+ {10, 0x02, 45},
+ {15, 0x02, 45},
+ {24, 0x02, 45},
+ {31, 0x02, 45},
+ {41, 0x02, 45},
+ {56, 0x03, 45},
+ {3, 0x02, 46},
+ {6, 0x02, 46},
+ {10, 0x02, 46},
+ {15, 0x02, 46},
+ {24, 0x02, 46},
+ {31, 0x02, 46},
+ {41, 0x02, 46},
+ {56, 0x03, 46},
+ },
+ /* 15 */
+ {
+ {1, 0x02, 47},
+ {22, 0x03, 47},
+ {1, 0x02, 51},
+ {22, 0x03, 51},
+ {1, 0x02, 52},
+ {22, 0x03, 52},
+ {1, 0x02, 53},
+ {22, 0x03, 53},
+ {1, 0x02, 54},
+ {22, 0x03, 54},
+ {1, 0x02, 55},
+ {22, 0x03, 55},
+ {1, 0x02, 56},
+ {22, 0x03, 56},
+ {1, 0x02, 57},
+ {22, 0x03, 57},
+ },
+ /* 16 */
+ {
+ {2, 0x02, 47},
+ {9, 0x02, 47},
+ {23, 0x02, 47},
+ {40, 0x03, 47},
+ {2, 0x02, 51},
+ {9, 0x02, 51},
+ {23, 0x02, 51},
+ {40, 0x03, 51},
+ {2, 0x02, 52},
+ {9, 0x02, 52},
+ {23, 0x02, 52},
+ {40, 0x03, 52},
+ {2, 0x02, 53},
+ {9, 0x02, 53},
+ {23, 0x02, 53},
+ {40, 0x03, 53},
+ },
+ /* 17 */
+ {
+ {3, 0x02, 47},
+ {6, 0x02, 47},
+ {10, 0x02, 47},
+ {15, 0x02, 47},
+ {24, 0x02, 47},
+ {31, 0x02, 47},
+ {41, 0x02, 47},
+ {56, 0x03, 47},
+ {3, 0x02, 51},
+ {6, 0x02, 51},
+ {10, 0x02, 51},
+ {15, 0x02, 51},
+ {24, 0x02, 51},
+ {31, 0x02, 51},
+ {41, 0x02, 51},
+ {56, 0x03, 51},
+ },
+ /* 18 */
+ {
+ {3, 0x02, 52},
+ {6, 0x02, 52},
+ {10, 0x02, 52},
+ {15, 0x02, 52},
+ {24, 0x02, 52},
+ {31, 0x02, 52},
+ {41, 0x02, 52},
+ {56, 0x03, 52},
+ {3, 0x02, 53},
+ {6, 0x02, 53},
+ {10, 0x02, 53},
+ {15, 0x02, 53},
+ {24, 0x02, 53},
+ {31, 0x02, 53},
+ {41, 0x02, 53},
+ {56, 0x03, 53},
+ },
+ /* 19 */
+ {
+ {2, 0x02, 54},
+ {9, 0x02, 54},
+ {23, 0x02, 54},
+ {40, 0x03, 54},
+ {2, 0x02, 55},
+ {9, 0x02, 55},
+ {23, 0x02, 55},
+ {40, 0x03, 55},
+ {2, 0x02, 56},
+ {9, 0x02, 56},
+ {23, 0x02, 56},
+ {40, 0x03, 56},
+ {2, 0x02, 57},
+ {9, 0x02, 57},
+ {23, 0x02, 57},
+ {40, 0x03, 57},
+ },
+ /* 20 */
+ {
+ {3, 0x02, 54},
+ {6, 0x02, 54},
+ {10, 0x02, 54},
+ {15, 0x02, 54},
+ {24, 0x02, 54},
+ {31, 0x02, 54},
+ {41, 0x02, 54},
+ {56, 0x03, 54},
+ {3, 0x02, 55},
+ {6, 0x02, 55},
+ {10, 0x02, 55},
+ {15, 0x02, 55},
+ {24, 0x02, 55},
+ {31, 0x02, 55},
+ {41, 0x02, 55},
+ {56, 0x03, 55},
+ },
+ /* 21 */
+ {
+ {3, 0x02, 56},
+ {6, 0x02, 56},
+ {10, 0x02, 56},
+ {15, 0x02, 56},
+ {24, 0x02, 56},
+ {31, 0x02, 56},
+ {41, 0x02, 56},
+ {56, 0x03, 56},
+ {3, 0x02, 57},
+ {6, 0x02, 57},
+ {10, 0x02, 57},
+ {15, 0x02, 57},
+ {24, 0x02, 57},
+ {31, 0x02, 57},
+ {41, 0x02, 57},
+ {56, 0x03, 57},
+ },
+ /* 22 */
+ {
+ {26, 0x00, 0},
+ {27, 0x00, 0},
+ {29, 0x00, 0},
+ {30, 0x00, 0},
+ {33, 0x00, 0},
+ {34, 0x00, 0},
+ {36, 0x00, 0},
+ {37, 0x00, 0},
+ {43, 0x00, 0},
+ {46, 0x00, 0},
+ {50, 0x00, 0},
+ {53, 0x00, 0},
+ {58, 0x00, 0},
+ {61, 0x00, 0},
+ {65, 0x00, 0},
+ {68, 0x01, 0},
+ },
+ /* 23 */
+ {
+ {0, 0x03, 61},
+ {0, 0x03, 65},
+ {0, 0x03, 95},
+ {0, 0x03, 98},
+ {0, 0x03, 100},
+ {0, 0x03, 102},
+ {0, 0x03, 103},
+ {0, 0x03, 104},
+ {0, 0x03, 108},
+ {0, 0x03, 109},
+ {0, 0x03, 110},
+ {0, 0x03, 112},
+ {0, 0x03, 114},
+ {0, 0x03, 117},
+ {38, 0x00, 0},
+ {39, 0x00, 0},
+ },
+ /* 24 */
+ {
+ {1, 0x02, 61},
+ {22, 0x03, 61},
+ {1, 0x02, 65},
+ {22, 0x03, 65},
+ {1, 0x02, 95},
+ {22, 0x03, 95},
+ {1, 0x02, 98},
+ {22, 0x03, 98},
+ {1, 0x02, 100},
+ {22, 0x03, 100},
+ {1, 0x02, 102},
+ {22, 0x03, 102},
+ {1, 0x02, 103},
+ {22, 0x03, 103},
+ {1, 0x02, 104},
+ {22, 0x03, 104},
+ },
+ /* 25 */
+ {
+ {2, 0x02, 61},
+ {9, 0x02, 61},
+ {23, 0x02, 61},
+ {40, 0x03, 61},
+ {2, 0x02, 65},
+ {9, 0x02, 65},
+ {23, 0x02, 65},
+ {40, 0x03, 65},
+ {2, 0x02, 95},
+ {9, 0x02, 95},
+ {23, 0x02, 95},
+ {40, 0x03, 95},
+ {2, 0x02, 98},
+ {9, 0x02, 98},
+ {23, 0x02, 98},
+ {40, 0x03, 98},
+ },
+ /* 26 */
+ {
+ {3, 0x02, 61},
+ {6, 0x02, 61},
+ {10, 0x02, 61},
+ {15, 0x02, 61},
+ {24, 0x02, 61},
+ {31, 0x02, 61},
+ {41, 0x02, 61},
+ {56, 0x03, 61},
+ {3, 0x02, 65},
+ {6, 0x02, 65},
+ {10, 0x02, 65},
+ {15, 0x02, 65},
+ {24, 0x02, 65},
+ {31, 0x02, 65},
+ {41, 0x02, 65},
+ {56, 0x03, 65},
+ },
+ /* 27 */
+ {
+ {3, 0x02, 95},
+ {6, 0x02, 95},
+ {10, 0x02, 95},
+ {15, 0x02, 95},
+ {24, 0x02, 95},
+ {31, 0x02, 95},
+ {41, 0x02, 95},
+ {56, 0x03, 95},
+ {3, 0x02, 98},
+ {6, 0x02, 98},
+ {10, 0x02, 98},
+ {15, 0x02, 98},
+ {24, 0x02, 98},
+ {31, 0x02, 98},
+ {41, 0x02, 98},
+ {56, 0x03, 98},
+ },
+ /* 28 */
+ {
+ {2, 0x02, 100},
+ {9, 0x02, 100},
+ {23, 0x02, 100},
+ {40, 0x03, 100},
+ {2, 0x02, 102},
+ {9, 0x02, 102},
+ {23, 0x02, 102},
+ {40, 0x03, 102},
+ {2, 0x02, 103},
+ {9, 0x02, 103},
+ {23, 0x02, 103},
+ {40, 0x03, 103},
+ {2, 0x02, 104},
+ {9, 0x02, 104},
+ {23, 0x02, 104},
+ {40, 0x03, 104},
+ },
+ /* 29 */
+ {
+ {3, 0x02, 100},
+ {6, 0x02, 100},
+ {10, 0x02, 100},
+ {15, 0x02, 100},
+ {24, 0x02, 100},
+ {31, 0x02, 100},
+ {41, 0x02, 100},
+ {56, 0x03, 100},
+ {3, 0x02, 102},
+ {6, 0x02, 102},
+ {10, 0x02, 102},
+ {15, 0x02, 102},
+ {24, 0x02, 102},
+ {31, 0x02, 102},
+ {41, 0x02, 102},
+ {56, 0x03, 102},
+ },
+ /* 30 */
+ {
+ {3, 0x02, 103},
+ {6, 0x02, 103},
+ {10, 0x02, 103},
+ {15, 0x02, 103},
+ {24, 0x02, 103},
+ {31, 0x02, 103},
+ {41, 0x02, 103},
+ {56, 0x03, 103},
+ {3, 0x02, 104},
+ {6, 0x02, 104},
+ {10, 0x02, 104},
+ {15, 0x02, 104},
+ {24, 0x02, 104},
+ {31, 0x02, 104},
+ {41, 0x02, 104},
+ {56, 0x03, 104},
+ },
+ /* 31 */
+ {
+ {1, 0x02, 108},
+ {22, 0x03, 108},
+ {1, 0x02, 109},
+ {22, 0x03, 109},
+ {1, 0x02, 110},
+ {22, 0x03, 110},
+ {1, 0x02, 112},
+ {22, 0x03, 112},
+ {1, 0x02, 114},
+ {22, 0x03, 114},
+ {1, 0x02, 117},
+ {22, 0x03, 117},
+ {0, 0x03, 58},
+ {0, 0x03, 66},
+ {0, 0x03, 67},
+ {0, 0x03, 68},
+ },
+ /* 32 */
+ {
+ {2, 0x02, 108},
+ {9, 0x02, 108},
+ {23, 0x02, 108},
+ {40, 0x03, 108},
+ {2, 0x02, 109},
+ {9, 0x02, 109},
+ {23, 0x02, 109},
+ {40, 0x03, 109},
+ {2, 0x02, 110},
+ {9, 0x02, 110},
+ {23, 0x02, 110},
+ {40, 0x03, 110},
+ {2, 0x02, 112},
+ {9, 0x02, 112},
+ {23, 0x02, 112},
+ {40, 0x03, 112},
+ },
+ /* 33 */
+ {
+ {3, 0x02, 108},
+ {6, 0x02, 108},
+ {10, 0x02, 108},
+ {15, 0x02, 108},
+ {24, 0x02, 108},
+ {31, 0x02, 108},
+ {41, 0x02, 108},
+ {56, 0x03, 108},
+ {3, 0x02, 109},
+ {6, 0x02, 109},
+ {10, 0x02, 109},
+ {15, 0x02, 109},
+ {24, 0x02, 109},
+ {31, 0x02, 109},
+ {41, 0x02, 109},
+ {56, 0x03, 109},
+ },
+ /* 34 */
+ {
+ {3, 0x02, 110},
+ {6, 0x02, 110},
+ {10, 0x02, 110},
+ {15, 0x02, 110},
+ {24, 0x02, 110},
+ {31, 0x02, 110},
+ {41, 0x02, 110},
+ {56, 0x03, 110},
+ {3, 0x02, 112},
+ {6, 0x02, 112},
+ {10, 0x02, 112},
+ {15, 0x02, 112},
+ {24, 0x02, 112},
+ {31, 0x02, 112},
+ {41, 0x02, 112},
+ {56, 0x03, 112},
+ },
+ /* 35 */
+ {
+ {2, 0x02, 114},
+ {9, 0x02, 114},
+ {23, 0x02, 114},
+ {40, 0x03, 114},
+ {2, 0x02, 117},
+ {9, 0x02, 117},
+ {23, 0x02, 117},
+ {40, 0x03, 117},
+ {1, 0x02, 58},
+ {22, 0x03, 58},
+ {1, 0x02, 66},
+ {22, 0x03, 66},
+ {1, 0x02, 67},
+ {22, 0x03, 67},
+ {1, 0x02, 68},
+ {22, 0x03, 68},
+ },
+ /* 36 */
+ {
+ {3, 0x02, 114},
+ {6, 0x02, 114},
+ {10, 0x02, 114},
+ {15, 0x02, 114},
+ {24, 0x02, 114},
+ {31, 0x02, 114},
+ {41, 0x02, 114},
+ {56, 0x03, 114},
+ {3, 0x02, 117},
+ {6, 0x02, 117},
+ {10, 0x02, 117},
+ {15, 0x02, 117},
+ {24, 0x02, 117},
+ {31, 0x02, 117},
+ {41, 0x02, 117},
+ {56, 0x03, 117},
+ },
+ /* 37 */
+ {
+ {2, 0x02, 58},
+ {9, 0x02, 58},
+ {23, 0x02, 58},
+ {40, 0x03, 58},
+ {2, 0x02, 66},
+ {9, 0x02, 66},
+ {23, 0x02, 66},
+ {40, 0x03, 66},
+ {2, 0x02, 67},
+ {9, 0x02, 67},
+ {23, 0x02, 67},
+ {40, 0x03, 67},
+ {2, 0x02, 68},
+ {9, 0x02, 68},
+ {23, 0x02, 68},
+ {40, 0x03, 68},
+ },
+ /* 38 */
+ {
+ {3, 0x02, 58},
+ {6, 0x02, 58},
+ {10, 0x02, 58},
+ {15, 0x02, 58},
+ {24, 0x02, 58},
+ {31, 0x02, 58},
+ {41, 0x02, 58},
+ {56, 0x03, 58},
+ {3, 0x02, 66},
+ {6, 0x02, 66},
+ {10, 0x02, 66},
+ {15, 0x02, 66},
+ {24, 0x02, 66},
+ {31, 0x02, 66},
+ {41, 0x02, 66},
+ {56, 0x03, 66},
+ },
+ /* 39 */
+ {
+ {3, 0x02, 67},
+ {6, 0x02, 67},
+ {10, 0x02, 67},
+ {15, 0x02, 67},
+ {24, 0x02, 67},
+ {31, 0x02, 67},
+ {41, 0x02, 67},
+ {56, 0x03, 67},
+ {3, 0x02, 68},
+ {6, 0x02, 68},
+ {10, 0x02, 68},
+ {15, 0x02, 68},
+ {24, 0x02, 68},
+ {31, 0x02, 68},
+ {41, 0x02, 68},
+ {56, 0x03, 68},
+ },
+ /* 40 */
+ {
+ {44, 0x00, 0},
+ {45, 0x00, 0},
+ {47, 0x00, 0},
+ {48, 0x00, 0},
+ {51, 0x00, 0},
+ {52, 0x00, 0},
+ {54, 0x00, 0},
+ {55, 0x00, 0},
+ {59, 0x00, 0},
+ {60, 0x00, 0},
+ {62, 0x00, 0},
+ {63, 0x00, 0},
+ {66, 0x00, 0},
+ {67, 0x00, 0},
+ {69, 0x00, 0},
+ {72, 0x01, 0},
+ },
+ /* 41 */
+ {
+ {0, 0x03, 69},
+ {0, 0x03, 70},
+ {0, 0x03, 71},
+ {0, 0x03, 72},
+ {0, 0x03, 73},
+ {0, 0x03, 74},
+ {0, 0x03, 75},
+ {0, 0x03, 76},
+ {0, 0x03, 77},
+ {0, 0x03, 78},
+ {0, 0x03, 79},
+ {0, 0x03, 80},
+ {0, 0x03, 81},
+ {0, 0x03, 82},
+ {0, 0x03, 83},
+ {0, 0x03, 84},
+ },
+ /* 42 */
+ {
+ {1, 0x02, 69},
+ {22, 0x03, 69},
+ {1, 0x02, 70},
+ {22, 0x03, 70},
+ {1, 0x02, 71},
+ {22, 0x03, 71},
+ {1, 0x02, 72},
+ {22, 0x03, 72},
+ {1, 0x02, 73},
+ {22, 0x03, 73},
+ {1, 0x02, 74},
+ {22, 0x03, 74},
+ {1, 0x02, 75},
+ {22, 0x03, 75},
+ {1, 0x02, 76},
+ {22, 0x03, 76},
+ },
+ /* 43 */
+ {
+ {2, 0x02, 69},
+ {9, 0x02, 69},
+ {23, 0x02, 69},
+ {40, 0x03, 69},
+ {2, 0x02, 70},
+ {9, 0x02, 70},
+ {23, 0x02, 70},
+ {40, 0x03, 70},
+ {2, 0x02, 71},
+ {9, 0x02, 71},
+ {23, 0x02, 71},
+ {40, 0x03, 71},
+ {2, 0x02, 72},
+ {9, 0x02, 72},
+ {23, 0x02, 72},
+ {40, 0x03, 72},
+ },
+ /* 44 */
+ {
+ {3, 0x02, 69},
+ {6, 0x02, 69},
+ {10, 0x02, 69},
+ {15, 0x02, 69},
+ {24, 0x02, 69},
+ {31, 0x02, 69},
+ {41, 0x02, 69},
+ {56, 0x03, 69},
+ {3, 0x02, 70},
+ {6, 0x02, 70},
+ {10, 0x02, 70},
+ {15, 0x02, 70},
+ {24, 0x02, 70},
+ {31, 0x02, 70},
+ {41, 0x02, 70},
+ {56, 0x03, 70},
+ },
+ /* 45 */
+ {
+ {3, 0x02, 71},
+ {6, 0x02, 71},
+ {10, 0x02, 71},
+ {15, 0x02, 71},
+ {24, 0x02, 71},
+ {31, 0x02, 71},
+ {41, 0x02, 71},
+ {56, 0x03, 71},
+ {3, 0x02, 72},
+ {6, 0x02, 72},
+ {10, 0x02, 72},
+ {15, 0x02, 72},
+ {24, 0x02, 72},
+ {31, 0x02, 72},
+ {41, 0x02, 72},
+ {56, 0x03, 72},
+ },
+ /* 46 */
+ {
+ {2, 0x02, 73},
+ {9, 0x02, 73},
+ {23, 0x02, 73},
+ {40, 0x03, 73},
+ {2, 0x02, 74},
+ {9, 0x02, 74},
+ {23, 0x02, 74},
+ {40, 0x03, 74},
+ {2, 0x02, 75},
+ {9, 0x02, 75},
+ {23, 0x02, 75},
+ {40, 0x03, 75},
+ {2, 0x02, 76},
+ {9, 0x02, 76},
+ {23, 0x02, 76},
+ {40, 0x03, 76},
+ },
+ /* 47 */
+ {
+ {3, 0x02, 73},
+ {6, 0x02, 73},
+ {10, 0x02, 73},
+ {15, 0x02, 73},
+ {24, 0x02, 73},
+ {31, 0x02, 73},
+ {41, 0x02, 73},
+ {56, 0x03, 73},
+ {3, 0x02, 74},
+ {6, 0x02, 74},
+ {10, 0x02, 74},
+ {15, 0x02, 74},
+ {24, 0x02, 74},
+ {31, 0x02, 74},
+ {41, 0x02, 74},
+ {56, 0x03, 74},
+ },
+ /* 48 */
+ {
+ {3, 0x02, 75},
+ {6, 0x02, 75},
+ {10, 0x02, 75},
+ {15, 0x02, 75},
+ {24, 0x02, 75},
+ {31, 0x02, 75},
+ {41, 0x02, 75},
+ {56, 0x03, 75},
+ {3, 0x02, 76},
+ {6, 0x02, 76},
+ {10, 0x02, 76},
+ {15, 0x02, 76},
+ {24, 0x02, 76},
+ {31, 0x02, 76},
+ {41, 0x02, 76},
+ {56, 0x03, 76},
+ },
+ /* 49 */
+ {
+ {1, 0x02, 77},
+ {22, 0x03, 77},
+ {1, 0x02, 78},
+ {22, 0x03, 78},
+ {1, 0x02, 79},
+ {22, 0x03, 79},
+ {1, 0x02, 80},
+ {22, 0x03, 80},
+ {1, 0x02, 81},
+ {22, 0x03, 81},
+ {1, 0x02, 82},
+ {22, 0x03, 82},
+ {1, 0x02, 83},
+ {22, 0x03, 83},
+ {1, 0x02, 84},
+ {22, 0x03, 84},
+ },
+ /* 50 */
+ {
+ {2, 0x02, 77},
+ {9, 0x02, 77},
+ {23, 0x02, 77},
+ {40, 0x03, 77},
+ {2, 0x02, 78},
+ {9, 0x02, 78},
+ {23, 0x02, 78},
+ {40, 0x03, 78},
+ {2, 0x02, 79},
+ {9, 0x02, 79},
+ {23, 0x02, 79},
+ {40, 0x03, 79},
+ {2, 0x02, 80},
+ {9, 0x02, 80},
+ {23, 0x02, 80},
+ {40, 0x03, 80},
+ },
+ /* 51 */
+ {
+ {3, 0x02, 77},
+ {6, 0x02, 77},
+ {10, 0x02, 77},
+ {15, 0x02, 77},
+ {24, 0x02, 77},
+ {31, 0x02, 77},
+ {41, 0x02, 77},
+ {56, 0x03, 77},
+ {3, 0x02, 78},
+ {6, 0x02, 78},
+ {10, 0x02, 78},
+ {15, 0x02, 78},
+ {24, 0x02, 78},
+ {31, 0x02, 78},
+ {41, 0x02, 78},
+ {56, 0x03, 78},
+ },
+ /* 52 */
+ {
+ {3, 0x02, 79},
+ {6, 0x02, 79},
+ {10, 0x02, 79},
+ {15, 0x02, 79},
+ {24, 0x02, 79},
+ {31, 0x02, 79},
+ {41, 0x02, 79},
+ {56, 0x03, 79},
+ {3, 0x02, 80},
+ {6, 0x02, 80},
+ {10, 0x02, 80},
+ {15, 0x02, 80},
+ {24, 0x02, 80},
+ {31, 0x02, 80},
+ {41, 0x02, 80},
+ {56, 0x03, 80},
+ },
+ /* 53 */
+ {
+ {2, 0x02, 81},
+ {9, 0x02, 81},
+ {23, 0x02, 81},
+ {40, 0x03, 81},
+ {2, 0x02, 82},
+ {9, 0x02, 82},
+ {23, 0x02, 82},
+ {40, 0x03, 82},
+ {2, 0x02, 83},
+ {9, 0x02, 83},
+ {23, 0x02, 83},
+ {40, 0x03, 83},
+ {2, 0x02, 84},
+ {9, 0x02, 84},
+ {23, 0x02, 84},
+ {40, 0x03, 84},
+ },
+ /* 54 */
+ {
+ {3, 0x02, 81},
+ {6, 0x02, 81},
+ {10, 0x02, 81},
+ {15, 0x02, 81},
+ {24, 0x02, 81},
+ {31, 0x02, 81},
+ {41, 0x02, 81},
+ {56, 0x03, 81},
+ {3, 0x02, 82},
+ {6, 0x02, 82},
+ {10, 0x02, 82},
+ {15, 0x02, 82},
+ {24, 0x02, 82},
+ {31, 0x02, 82},
+ {41, 0x02, 82},
+ {56, 0x03, 82},
+ },
+ /* 55 */
+ {
+ {3, 0x02, 83},
+ {6, 0x02, 83},
+ {10, 0x02, 83},
+ {15, 0x02, 83},
+ {24, 0x02, 83},
+ {31, 0x02, 83},
+ {41, 0x02, 83},
+ {56, 0x03, 83},
+ {3, 0x02, 84},
+ {6, 0x02, 84},
+ {10, 0x02, 84},
+ {15, 0x02, 84},
+ {24, 0x02, 84},
+ {31, 0x02, 84},
+ {41, 0x02, 84},
+ {56, 0x03, 84},
+ },
+ /* 56 */
+ {
+ {0, 0x03, 85},
+ {0, 0x03, 86},
+ {0, 0x03, 87},
+ {0, 0x03, 89},
+ {0, 0x03, 106},
+ {0, 0x03, 107},
+ {0, 0x03, 113},
+ {0, 0x03, 118},
+ {0, 0x03, 119},
+ {0, 0x03, 120},
+ {0, 0x03, 121},
+ {0, 0x03, 122},
+ {70, 0x00, 0},
+ {71, 0x00, 0},
+ {73, 0x00, 0},
+ {74, 0x01, 0},
+ },
+ /* 57 */
+ {
+ {1, 0x02, 85},
+ {22, 0x03, 85},
+ {1, 0x02, 86},
+ {22, 0x03, 86},
+ {1, 0x02, 87},
+ {22, 0x03, 87},
+ {1, 0x02, 89},
+ {22, 0x03, 89},
+ {1, 0x02, 106},
+ {22, 0x03, 106},
+ {1, 0x02, 107},
+ {22, 0x03, 107},
+ {1, 0x02, 113},
+ {22, 0x03, 113},
+ {1, 0x02, 118},
+ {22, 0x03, 118},
+ },
+ /* 58 */
+ {
+ {2, 0x02, 85},
+ {9, 0x02, 85},
+ {23, 0x02, 85},
+ {40, 0x03, 85},
+ {2, 0x02, 86},
+ {9, 0x02, 86},
+ {23, 0x02, 86},
+ {40, 0x03, 86},
+ {2, 0x02, 87},
+ {9, 0x02, 87},
+ {23, 0x02, 87},
+ {40, 0x03, 87},
+ {2, 0x02, 89},
+ {9, 0x02, 89},
+ {23, 0x02, 89},
+ {40, 0x03, 89},
+ },
+ /* 59 */
+ {
+ {3, 0x02, 85},
+ {6, 0x02, 85},
+ {10, 0x02, 85},
+ {15, 0x02, 85},
+ {24, 0x02, 85},
+ {31, 0x02, 85},
+ {41, 0x02, 85},
+ {56, 0x03, 85},
+ {3, 0x02, 86},
+ {6, 0x02, 86},
+ {10, 0x02, 86},
+ {15, 0x02, 86},
+ {24, 0x02, 86},
+ {31, 0x02, 86},
+ {41, 0x02, 86},
+ {56, 0x03, 86},
+ },
+ /* 60 */
+ {
+ {3, 0x02, 87},
+ {6, 0x02, 87},
+ {10, 0x02, 87},
+ {15, 0x02, 87},
+ {24, 0x02, 87},
+ {31, 0x02, 87},
+ {41, 0x02, 87},
+ {56, 0x03, 87},
+ {3, 0x02, 89},
+ {6, 0x02, 89},
+ {10, 0x02, 89},
+ {15, 0x02, 89},
+ {24, 0x02, 89},
+ {31, 0x02, 89},
+ {41, 0x02, 89},
+ {56, 0x03, 89},
+ },
+ /* 61 */
+ {
+ {2, 0x02, 106},
+ {9, 0x02, 106},
+ {23, 0x02, 106},
+ {40, 0x03, 106},
+ {2, 0x02, 107},
+ {9, 0x02, 107},
+ {23, 0x02, 107},
+ {40, 0x03, 107},
+ {2, 0x02, 113},
+ {9, 0x02, 113},
+ {23, 0x02, 113},
+ {40, 0x03, 113},
+ {2, 0x02, 118},
+ {9, 0x02, 118},
+ {23, 0x02, 118},
+ {40, 0x03, 118},
+ },
+ /* 62 */
+ {
+ {3, 0x02, 106},
+ {6, 0x02, 106},
+ {10, 0x02, 106},
+ {15, 0x02, 106},
+ {24, 0x02, 106},
+ {31, 0x02, 106},
+ {41, 0x02, 106},
+ {56, 0x03, 106},
+ {3, 0x02, 107},
+ {6, 0x02, 107},
+ {10, 0x02, 107},
+ {15, 0x02, 107},
+ {24, 0x02, 107},
+ {31, 0x02, 107},
+ {41, 0x02, 107},
+ {56, 0x03, 107},
+ },
+ /* 63 */
+ {
+ {3, 0x02, 113},
+ {6, 0x02, 113},
+ {10, 0x02, 113},
+ {15, 0x02, 113},
+ {24, 0x02, 113},
+ {31, 0x02, 113},
+ {41, 0x02, 113},
+ {56, 0x03, 113},
+ {3, 0x02, 118},
+ {6, 0x02, 118},
+ {10, 0x02, 118},
+ {15, 0x02, 118},
+ {24, 0x02, 118},
+ {31, 0x02, 118},
+ {41, 0x02, 118},
+ {56, 0x03, 118},
+ },
+ /* 64 */
+ {
+ {1, 0x02, 119},
+ {22, 0x03, 119},
+ {1, 0x02, 120},
+ {22, 0x03, 120},
+ {1, 0x02, 121},
+ {22, 0x03, 121},
+ {1, 0x02, 122},
+ {22, 0x03, 122},
+ {0, 0x03, 38},
+ {0, 0x03, 42},
+ {0, 0x03, 44},
+ {0, 0x03, 59},
+ {0, 0x03, 88},
+ {0, 0x03, 90},
+ {75, 0x00, 0},
+ {78, 0x00, 0},
+ },
+ /* 65 */
+ {
+ {2, 0x02, 119},
+ {9, 0x02, 119},
+ {23, 0x02, 119},
+ {40, 0x03, 119},
+ {2, 0x02, 120},
+ {9, 0x02, 120},
+ {23, 0x02, 120},
+ {40, 0x03, 120},
+ {2, 0x02, 121},
+ {9, 0x02, 121},
+ {23, 0x02, 121},
+ {40, 0x03, 121},
+ {2, 0x02, 122},
+ {9, 0x02, 122},
+ {23, 0x02, 122},
+ {40, 0x03, 122},
+ },
+ /* 66 */
+ {
+ {3, 0x02, 119},
+ {6, 0x02, 119},
+ {10, 0x02, 119},
+ {15, 0x02, 119},
+ {24, 0x02, 119},
+ {31, 0x02, 119},
+ {41, 0x02, 119},
+ {56, 0x03, 119},
+ {3, 0x02, 120},
+ {6, 0x02, 120},
+ {10, 0x02, 120},
+ {15, 0x02, 120},
+ {24, 0x02, 120},
+ {31, 0x02, 120},
+ {41, 0x02, 120},
+ {56, 0x03, 120},
+ },
+ /* 67 */
+ {
+ {3, 0x02, 121},
+ {6, 0x02, 121},
+ {10, 0x02, 121},
+ {15, 0x02, 121},
+ {24, 0x02, 121},
+ {31, 0x02, 121},
+ {41, 0x02, 121},
+ {56, 0x03, 121},
+ {3, 0x02, 122},
+ {6, 0x02, 122},
+ {10, 0x02, 122},
+ {15, 0x02, 122},
+ {24, 0x02, 122},
+ {31, 0x02, 122},
+ {41, 0x02, 122},
+ {56, 0x03, 122},
+ },
+ /* 68 */
+ {
+ {1, 0x02, 38},
+ {22, 0x03, 38},
+ {1, 0x02, 42},
+ {22, 0x03, 42},
+ {1, 0x02, 44},
+ {22, 0x03, 44},
+ {1, 0x02, 59},
+ {22, 0x03, 59},
+ {1, 0x02, 88},
+ {22, 0x03, 88},
+ {1, 0x02, 90},
+ {22, 0x03, 90},
+ {76, 0x00, 0},
+ {77, 0x00, 0},
+ {79, 0x00, 0},
+ {81, 0x00, 0},
+ },
+ /* 69 */
+ {
+ {2, 0x02, 38},
+ {9, 0x02, 38},
+ {23, 0x02, 38},
+ {40, 0x03, 38},
+ {2, 0x02, 42},
+ {9, 0x02, 42},
+ {23, 0x02, 42},
+ {40, 0x03, 42},
+ {2, 0x02, 44},
+ {9, 0x02, 44},
+ {23, 0x02, 44},
+ {40, 0x03, 44},
+ {2, 0x02, 59},
+ {9, 0x02, 59},
+ {23, 0x02, 59},
+ {40, 0x03, 59},
+ },
+ /* 70 */
+ {
+ {3, 0x02, 38},
+ {6, 0x02, 38},
+ {10, 0x02, 38},
+ {15, 0x02, 38},
+ {24, 0x02, 38},
+ {31, 0x02, 38},
+ {41, 0x02, 38},
+ {56, 0x03, 38},
+ {3, 0x02, 42},
+ {6, 0x02, 42},
+ {10, 0x02, 42},
+ {15, 0x02, 42},
+ {24, 0x02, 42},
+ {31, 0x02, 42},
+ {41, 0x02, 42},
+ {56, 0x03, 42},
+ },
+ /* 71 */
+ {
+ {3, 0x02, 44},
+ {6, 0x02, 44},
+ {10, 0x02, 44},
+ {15, 0x02, 44},
+ {24, 0x02, 44},
+ {31, 0x02, 44},
+ {41, 0x02, 44},
+ {56, 0x03, 44},
+ {3, 0x02, 59},
+ {6, 0x02, 59},
+ {10, 0x02, 59},
+ {15, 0x02, 59},
+ {24, 0x02, 59},
+ {31, 0x02, 59},
+ {41, 0x02, 59},
+ {56, 0x03, 59},
+ },
+ /* 72 */
+ {
+ {2, 0x02, 88},
+ {9, 0x02, 88},
+ {23, 0x02, 88},
+ {40, 0x03, 88},
+ {2, 0x02, 90},
+ {9, 0x02, 90},
+ {23, 0x02, 90},
+ {40, 0x03, 90},
+ {0, 0x03, 33},
+ {0, 0x03, 34},
+ {0, 0x03, 40},
+ {0, 0x03, 41},
+ {0, 0x03, 63},
+ {80, 0x00, 0},
+ {82, 0x00, 0},
+ {84, 0x00, 0},
+ },
+ /* 73 */
+ {
+ {3, 0x02, 88},
+ {6, 0x02, 88},
+ {10, 0x02, 88},
+ {15, 0x02, 88},
+ {24, 0x02, 88},
+ {31, 0x02, 88},
+ {41, 0x02, 88},
+ {56, 0x03, 88},
+ {3, 0x02, 90},
+ {6, 0x02, 90},
+ {10, 0x02, 90},
+ {15, 0x02, 90},
+ {24, 0x02, 90},
+ {31, 0x02, 90},
+ {41, 0x02, 90},
+ {56, 0x03, 90},
+ },
+ /* 74 */
+ {
+ {1, 0x02, 33},
+ {22, 0x03, 33},
+ {1, 0x02, 34},
+ {22, 0x03, 34},
+ {1, 0x02, 40},
+ {22, 0x03, 40},
+ {1, 0x02, 41},
+ {22, 0x03, 41},
+ {1, 0x02, 63},
+ {22, 0x03, 63},
+ {0, 0x03, 39},
+ {0, 0x03, 43},
+ {0, 0x03, 124},
+ {83, 0x00, 0},
+ {85, 0x00, 0},
+ {88, 0x00, 0},
+ },
+ /* 75 */
+ {
+ {2, 0x02, 33},
+ {9, 0x02, 33},
+ {23, 0x02, 33},
+ {40, 0x03, 33},
+ {2, 0x02, 34},
+ {9, 0x02, 34},
+ {23, 0x02, 34},
+ {40, 0x03, 34},
+ {2, 0x02, 40},
+ {9, 0x02, 40},
+ {23, 0x02, 40},
+ {40, 0x03, 40},
+ {2, 0x02, 41},
+ {9, 0x02, 41},
+ {23, 0x02, 41},
+ {40, 0x03, 41},
+ },
+ /* 76 */
+ {
+ {3, 0x02, 33},
+ {6, 0x02, 33},
+ {10, 0x02, 33},
+ {15, 0x02, 33},
+ {24, 0x02, 33},
+ {31, 0x02, 33},
+ {41, 0x02, 33},
+ {56, 0x03, 33},
+ {3, 0x02, 34},
+ {6, 0x02, 34},
+ {10, 0x02, 34},
+ {15, 0x02, 34},
+ {24, 0x02, 34},
+ {31, 0x02, 34},
+ {41, 0x02, 34},
+ {56, 0x03, 34},
+ },
+ /* 77 */
+ {
+ {3, 0x02, 40},
+ {6, 0x02, 40},
+ {10, 0x02, 40},
+ {15, 0x02, 40},
+ {24, 0x02, 40},
+ {31, 0x02, 40},
+ {41, 0x02, 40},
+ {56, 0x03, 40},
+ {3, 0x02, 41},
+ {6, 0x02, 41},
+ {10, 0x02, 41},
+ {15, 0x02, 41},
+ {24, 0x02, 41},
+ {31, 0x02, 41},
+ {41, 0x02, 41},
+ {56, 0x03, 41},
+ },
+ /* 78 */
+ {
+ {2, 0x02, 63},
+ {9, 0x02, 63},
+ {23, 0x02, 63},
+ {40, 0x03, 63},
+ {1, 0x02, 39},
+ {22, 0x03, 39},
+ {1, 0x02, 43},
+ {22, 0x03, 43},
+ {1, 0x02, 124},
+ {22, 0x03, 124},
+ {0, 0x03, 35},
+ {0, 0x03, 62},
+ {86, 0x00, 0},
+ {87, 0x00, 0},
+ {89, 0x00, 0},
+ {90, 0x00, 0},
+ },
+ /* 79 */
+ {
+ {3, 0x02, 63},
+ {6, 0x02, 63},
+ {10, 0x02, 63},
+ {15, 0x02, 63},
+ {24, 0x02, 63},
+ {31, 0x02, 63},
+ {41, 0x02, 63},
+ {56, 0x03, 63},
+ {2, 0x02, 39},
+ {9, 0x02, 39},
+ {23, 0x02, 39},
+ {40, 0x03, 39},
+ {2, 0x02, 43},
+ {9, 0x02, 43},
+ {23, 0x02, 43},
+ {40, 0x03, 43},
+ },
+ /* 80 */
+ {
+ {3, 0x02, 39},
+ {6, 0x02, 39},
+ {10, 0x02, 39},
+ {15, 0x02, 39},
+ {24, 0x02, 39},
+ {31, 0x02, 39},
+ {41, 0x02, 39},
+ {56, 0x03, 39},
+ {3, 0x02, 43},
+ {6, 0x02, 43},
+ {10, 0x02, 43},
+ {15, 0x02, 43},
+ {24, 0x02, 43},
+ {31, 0x02, 43},
+ {41, 0x02, 43},
+ {56, 0x03, 43},
+ },
+ /* 81 */
+ {
+ {2, 0x02, 124},
+ {9, 0x02, 124},
+ {23, 0x02, 124},
+ {40, 0x03, 124},
+ {1, 0x02, 35},
+ {22, 0x03, 35},
+ {1, 0x02, 62},
+ {22, 0x03, 62},
+ {0, 0x03, 0},
+ {0, 0x03, 36},
+ {0, 0x03, 64},
+ {0, 0x03, 91},
+ {0, 0x03, 93},
+ {0, 0x03, 126},
+ {91, 0x00, 0},
+ {92, 0x00, 0},
+ },
+ /* 82 */
+ {
+ {3, 0x02, 124},
+ {6, 0x02, 124},
+ {10, 0x02, 124},
+ {15, 0x02, 124},
+ {24, 0x02, 124},
+ {31, 0x02, 124},
+ {41, 0x02, 124},
+ {56, 0x03, 124},
+ {2, 0x02, 35},
+ {9, 0x02, 35},
+ {23, 0x02, 35},
+ {40, 0x03, 35},
+ {2, 0x02, 62},
+ {9, 0x02, 62},
+ {23, 0x02, 62},
+ {40, 0x03, 62},
+ },
+ /* 83 */
+ {
+ {3, 0x02, 35},
+ {6, 0x02, 35},
+ {10, 0x02, 35},
+ {15, 0x02, 35},
+ {24, 0x02, 35},
+ {31, 0x02, 35},
+ {41, 0x02, 35},
+ {56, 0x03, 35},
+ {3, 0x02, 62},
+ {6, 0x02, 62},
+ {10, 0x02, 62},
+ {15, 0x02, 62},
+ {24, 0x02, 62},
+ {31, 0x02, 62},
+ {41, 0x02, 62},
+ {56, 0x03, 62},
+ },
+ /* 84 */
+ {
+ {1, 0x02, 0},
+ {22, 0x03, 0},
+ {1, 0x02, 36},
+ {22, 0x03, 36},
+ {1, 0x02, 64},
+ {22, 0x03, 64},
+ {1, 0x02, 91},
+ {22, 0x03, 91},
+ {1, 0x02, 93},
+ {22, 0x03, 93},
+ {1, 0x02, 126},
+ {22, 0x03, 126},
+ {0, 0x03, 94},
+ {0, 0x03, 125},
+ {93, 0x00, 0},
+ {94, 0x00, 0},
+ },
+ /* 85 */
+ {
+ {2, 0x02, 0},
+ {9, 0x02, 0},
+ {23, 0x02, 0},
+ {40, 0x03, 0},
+ {2, 0x02, 36},
+ {9, 0x02, 36},
+ {23, 0x02, 36},
+ {40, 0x03, 36},
+ {2, 0x02, 64},
+ {9, 0x02, 64},
+ {23, 0x02, 64},
+ {40, 0x03, 64},
+ {2, 0x02, 91},
+ {9, 0x02, 91},
+ {23, 0x02, 91},
+ {40, 0x03, 91},
+ },
+ /* 86 */
+ {
+ {3, 0x02, 0},
+ {6, 0x02, 0},
+ {10, 0x02, 0},
+ {15, 0x02, 0},
+ {24, 0x02, 0},
+ {31, 0x02, 0},
+ {41, 0x02, 0},
+ {56, 0x03, 0},
+ {3, 0x02, 36},
+ {6, 0x02, 36},
+ {10, 0x02, 36},
+ {15, 0x02, 36},
+ {24, 0x02, 36},
+ {31, 0x02, 36},
+ {41, 0x02, 36},
+ {56, 0x03, 36},
+ },
+ /* 87 */
+ {
+ {3, 0x02, 64},
+ {6, 0x02, 64},
+ {10, 0x02, 64},
+ {15, 0x02, 64},
+ {24, 0x02, 64},
+ {31, 0x02, 64},
+ {41, 0x02, 64},
+ {56, 0x03, 64},
+ {3, 0x02, 91},
+ {6, 0x02, 91},
+ {10, 0x02, 91},
+ {15, 0x02, 91},
+ {24, 0x02, 91},
+ {31, 0x02, 91},
+ {41, 0x02, 91},
+ {56, 0x03, 91},
+ },
+ /* 88 */
+ {
+ {2, 0x02, 93},
+ {9, 0x02, 93},
+ {23, 0x02, 93},
+ {40, 0x03, 93},
+ {2, 0x02, 126},
+ {9, 0x02, 126},
+ {23, 0x02, 126},
+ {40, 0x03, 126},
+ {1, 0x02, 94},
+ {22, 0x03, 94},
+ {1, 0x02, 125},
+ {22, 0x03, 125},
+ {0, 0x03, 60},
+ {0, 0x03, 96},
+ {0, 0x03, 123},
+ {95, 0x00, 0},
+ },
+ /* 89 */
+ {
+ {3, 0x02, 93},
+ {6, 0x02, 93},
+ {10, 0x02, 93},
+ {15, 0x02, 93},
+ {24, 0x02, 93},
+ {31, 0x02, 93},
+ {41, 0x02, 93},
+ {56, 0x03, 93},
+ {3, 0x02, 126},
+ {6, 0x02, 126},
+ {10, 0x02, 126},
+ {15, 0x02, 126},
+ {24, 0x02, 126},
+ {31, 0x02, 126},
+ {41, 0x02, 126},
+ {56, 0x03, 126},
+ },
+ /* 90 */
+ {
+ {2, 0x02, 94},
+ {9, 0x02, 94},
+ {23, 0x02, 94},
+ {40, 0x03, 94},
+ {2, 0x02, 125},
+ {9, 0x02, 125},
+ {23, 0x02, 125},
+ {40, 0x03, 125},
+ {1, 0x02, 60},
+ {22, 0x03, 60},
+ {1, 0x02, 96},
+ {22, 0x03, 96},
+ {1, 0x02, 123},
+ {22, 0x03, 123},
+ {96, 0x00, 0},
+ {110, 0x00, 0},
+ },
+ /* 91 */
+ {
+ {3, 0x02, 94},
+ {6, 0x02, 94},
+ {10, 0x02, 94},
+ {15, 0x02, 94},
+ {24, 0x02, 94},
+ {31, 0x02, 94},
+ {41, 0x02, 94},
+ {56, 0x03, 94},
+ {3, 0x02, 125},
+ {6, 0x02, 125},
+ {10, 0x02, 125},
+ {15, 0x02, 125},
+ {24, 0x02, 125},
+ {31, 0x02, 125},
+ {41, 0x02, 125},
+ {56, 0x03, 125},
+ },
+ /* 92 */
+ {
+ {2, 0x02, 60},
+ {9, 0x02, 60},
+ {23, 0x02, 60},
+ {40, 0x03, 60},
+ {2, 0x02, 96},
+ {9, 0x02, 96},
+ {23, 0x02, 96},
+ {40, 0x03, 96},
+ {2, 0x02, 123},
+ {9, 0x02, 123},
+ {23, 0x02, 123},
+ {40, 0x03, 123},
+ {97, 0x00, 0},
+ {101, 0x00, 0},
+ {111, 0x00, 0},
+ {133, 0x00, 0},
+ },
+ /* 93 */
+ {
+ {3, 0x02, 60},
+ {6, 0x02, 60},
+ {10, 0x02, 60},
+ {15, 0x02, 60},
+ {24, 0x02, 60},
+ {31, 0x02, 60},
+ {41, 0x02, 60},
+ {56, 0x03, 60},
+ {3, 0x02, 96},
+ {6, 0x02, 96},
+ {10, 0x02, 96},
+ {15, 0x02, 96},
+ {24, 0x02, 96},
+ {31, 0x02, 96},
+ {41, 0x02, 96},
+ {56, 0x03, 96},
+ },
+ /* 94 */
+ {
+ {3, 0x02, 123},
+ {6, 0x02, 123},
+ {10, 0x02, 123},
+ {15, 0x02, 123},
+ {24, 0x02, 123},
+ {31, 0x02, 123},
+ {41, 0x02, 123},
+ {56, 0x03, 123},
+ {98, 0x00, 0},
+ {99, 0x00, 0},
+ {102, 0x00, 0},
+ {105, 0x00, 0},
+ {112, 0x00, 0},
+ {119, 0x00, 0},
+ {134, 0x00, 0},
+ {153, 0x00, 0},
+ },
+ /* 95 */
+ {
+ {0, 0x03, 92},
+ {0, 0x03, 195},
+ {0, 0x03, 208},
+ {100, 0x00, 0},
+ {103, 0x00, 0},
+ {104, 0x00, 0},
+ {106, 0x00, 0},
+ {107, 0x00, 0},
+ {113, 0x00, 0},
+ {116, 0x00, 0},
+ {120, 0x00, 0},
+ {126, 0x00, 0},
+ {135, 0x00, 0},
+ {142, 0x00, 0},
+ {154, 0x00, 0},
+ {169, 0x00, 0},
+ },
+ /* 96 */
+ {
+ {1, 0x02, 92},
+ {22, 0x03, 92},
+ {1, 0x02, 195},
+ {22, 0x03, 195},
+ {1, 0x02, 208},
+ {22, 0x03, 208},
+ {0, 0x03, 128},
+ {0, 0x03, 130},
+ {0, 0x03, 131},
+ {0, 0x03, 162},
+ {0, 0x03, 184},
+ {0, 0x03, 194},
+ {0, 0x03, 224},
+ {0, 0x03, 226},
+ {108, 0x00, 0},
+ {109, 0x00, 0},
+ },
+ /* 97 */
+ {
+ {2, 0x02, 92},
+ {9, 0x02, 92},
+ {23, 0x02, 92},
+ {40, 0x03, 92},
+ {2, 0x02, 195},
+ {9, 0x02, 195},
+ {23, 0x02, 195},
+ {40, 0x03, 195},
+ {2, 0x02, 208},
+ {9, 0x02, 208},
+ {23, 0x02, 208},
+ {40, 0x03, 208},
+ {1, 0x02, 128},
+ {22, 0x03, 128},
+ {1, 0x02, 130},
+ {22, 0x03, 130},
+ },
+ /* 98 */
+ {
+ {3, 0x02, 92},
+ {6, 0x02, 92},
+ {10, 0x02, 92},
+ {15, 0x02, 92},
+ {24, 0x02, 92},
+ {31, 0x02, 92},
+ {41, 0x02, 92},
+ {56, 0x03, 92},
+ {3, 0x02, 195},
+ {6, 0x02, 195},
+ {10, 0x02, 195},
+ {15, 0x02, 195},
+ {24, 0x02, 195},
+ {31, 0x02, 195},
+ {41, 0x02, 195},
+ {56, 0x03, 195},
+ },
+ /* 99 */
+ {
+ {3, 0x02, 208},
+ {6, 0x02, 208},
+ {10, 0x02, 208},
+ {15, 0x02, 208},
+ {24, 0x02, 208},
+ {31, 0x02, 208},
+ {41, 0x02, 208},
+ {56, 0x03, 208},
+ {2, 0x02, 128},
+ {9, 0x02, 128},
+ {23, 0x02, 128},
+ {40, 0x03, 128},
+ {2, 0x02, 130},
+ {9, 0x02, 130},
+ {23, 0x02, 130},
+ {40, 0x03, 130},
+ },
+ /* 100 */
+ {
+ {3, 0x02, 128},
+ {6, 0x02, 128},
+ {10, 0x02, 128},
+ {15, 0x02, 128},
+ {24, 0x02, 128},
+ {31, 0x02, 128},
+ {41, 0x02, 128},
+ {56, 0x03, 128},
+ {3, 0x02, 130},
+ {6, 0x02, 130},
+ {10, 0x02, 130},
+ {15, 0x02, 130},
+ {24, 0x02, 130},
+ {31, 0x02, 130},
+ {41, 0x02, 130},
+ {56, 0x03, 130},
+ },
+ /* 101 */
+ {
+ {1, 0x02, 131},
+ {22, 0x03, 131},
+ {1, 0x02, 162},
+ {22, 0x03, 162},
+ {1, 0x02, 184},
+ {22, 0x03, 184},
+ {1, 0x02, 194},
+ {22, 0x03, 194},
+ {1, 0x02, 224},
+ {22, 0x03, 224},
+ {1, 0x02, 226},
+ {22, 0x03, 226},
+ {0, 0x03, 153},
+ {0, 0x03, 161},
+ {0, 0x03, 167},
+ {0, 0x03, 172},
+ },
+ /* 102 */
+ {
+ {2, 0x02, 131},
+ {9, 0x02, 131},
+ {23, 0x02, 131},
+ {40, 0x03, 131},
+ {2, 0x02, 162},
+ {9, 0x02, 162},
+ {23, 0x02, 162},
+ {40, 0x03, 162},
+ {2, 0x02, 184},
+ {9, 0x02, 184},
+ {23, 0x02, 184},
+ {40, 0x03, 184},
+ {2, 0x02, 194},
+ {9, 0x02, 194},
+ {23, 0x02, 194},
+ {40, 0x03, 194},
+ },
+ /* 103 */
+ {
+ {3, 0x02, 131},
+ {6, 0x02, 131},
+ {10, 0x02, 131},
+ {15, 0x02, 131},
+ {24, 0x02, 131},
+ {31, 0x02, 131},
+ {41, 0x02, 131},
+ {56, 0x03, 131},
+ {3, 0x02, 162},
+ {6, 0x02, 162},
+ {10, 0x02, 162},
+ {15, 0x02, 162},
+ {24, 0x02, 162},
+ {31, 0x02, 162},
+ {41, 0x02, 162},
+ {56, 0x03, 162},
+ },
+ /* 104 */
+ {
+ {3, 0x02, 184},
+ {6, 0x02, 184},
+ {10, 0x02, 184},
+ {15, 0x02, 184},
+ {24, 0x02, 184},
+ {31, 0x02, 184},
+ {41, 0x02, 184},
+ {56, 0x03, 184},
+ {3, 0x02, 194},
+ {6, 0x02, 194},
+ {10, 0x02, 194},
+ {15, 0x02, 194},
+ {24, 0x02, 194},
+ {31, 0x02, 194},
+ {41, 0x02, 194},
+ {56, 0x03, 194},
+ },
+ /* 105 */
+ {
+ {2, 0x02, 224},
+ {9, 0x02, 224},
+ {23, 0x02, 224},
+ {40, 0x03, 224},
+ {2, 0x02, 226},
+ {9, 0x02, 226},
+ {23, 0x02, 226},
+ {40, 0x03, 226},
+ {1, 0x02, 153},
+ {22, 0x03, 153},
+ {1, 0x02, 161},
+ {22, 0x03, 161},
+ {1, 0x02, 167},
+ {22, 0x03, 167},
+ {1, 0x02, 172},
+ {22, 0x03, 172},
+ },
+ /* 106 */
+ {
+ {3, 0x02, 224},
+ {6, 0x02, 224},
+ {10, 0x02, 224},
+ {15, 0x02, 224},
+ {24, 0x02, 224},
+ {31, 0x02, 224},
+ {41, 0x02, 224},
+ {56, 0x03, 224},
+ {3, 0x02, 226},
+ {6, 0x02, 226},
+ {10, 0x02, 226},
+ {15, 0x02, 226},
+ {24, 0x02, 226},
+ {31, 0x02, 226},
+ {41, 0x02, 226},
+ {56, 0x03, 226},
+ },
+ /* 107 */
+ {
+ {2, 0x02, 153},
+ {9, 0x02, 153},
+ {23, 0x02, 153},
+ {40, 0x03, 153},
+ {2, 0x02, 161},
+ {9, 0x02, 161},
+ {23, 0x02, 161},
+ {40, 0x03, 161},
+ {2, 0x02, 167},
+ {9, 0x02, 167},
+ {23, 0x02, 167},
+ {40, 0x03, 167},
+ {2, 0x02, 172},
+ {9, 0x02, 172},
+ {23, 0x02, 172},
+ {40, 0x03, 172},
+ },
+ /* 108 */
+ {
+ {3, 0x02, 153},
+ {6, 0x02, 153},
+ {10, 0x02, 153},
+ {15, 0x02, 153},
+ {24, 0x02, 153},
+ {31, 0x02, 153},
+ {41, 0x02, 153},
+ {56, 0x03, 153},
+ {3, 0x02, 161},
+ {6, 0x02, 161},
+ {10, 0x02, 161},
+ {15, 0x02, 161},
+ {24, 0x02, 161},
+ {31, 0x02, 161},
+ {41, 0x02, 161},
+ {56, 0x03, 161},
+ },
+ /* 109 */
+ {
+ {3, 0x02, 167},
+ {6, 0x02, 167},
+ {10, 0x02, 167},
+ {15, 0x02, 167},
+ {24, 0x02, 167},
+ {31, 0x02, 167},
+ {41, 0x02, 167},
+ {56, 0x03, 167},
+ {3, 0x02, 172},
+ {6, 0x02, 172},
+ {10, 0x02, 172},
+ {15, 0x02, 172},
+ {24, 0x02, 172},
+ {31, 0x02, 172},
+ {41, 0x02, 172},
+ {56, 0x03, 172},
+ },
+ /* 110 */
+ {
+ {114, 0x00, 0},
+ {115, 0x00, 0},
+ {117, 0x00, 0},
+ {118, 0x00, 0},
+ {121, 0x00, 0},
+ {123, 0x00, 0},
+ {127, 0x00, 0},
+ {130, 0x00, 0},
+ {136, 0x00, 0},
+ {139, 0x00, 0},
+ {143, 0x00, 0},
+ {146, 0x00, 0},
+ {155, 0x00, 0},
+ {162, 0x00, 0},
+ {170, 0x00, 0},
+ {180, 0x00, 0},
+ },
+ /* 111 */
+ {
+ {0, 0x03, 176},
+ {0, 0x03, 177},
+ {0, 0x03, 179},
+ {0, 0x03, 209},
+ {0, 0x03, 216},
+ {0, 0x03, 217},
+ {0, 0x03, 227},
+ {0, 0x03, 229},
+ {0, 0x03, 230},
+ {122, 0x00, 0},
+ {124, 0x00, 0},
+ {125, 0x00, 0},
+ {128, 0x00, 0},
+ {129, 0x00, 0},
+ {131, 0x00, 0},
+ {132, 0x00, 0},
+ },
+ /* 112 */
+ {
+ {1, 0x02, 176},
+ {22, 0x03, 176},
+ {1, 0x02, 177},
+ {22, 0x03, 177},
+ {1, 0x02, 179},
+ {22, 0x03, 179},
+ {1, 0x02, 209},
+ {22, 0x03, 209},
+ {1, 0x02, 216},
+ {22, 0x03, 216},
+ {1, 0x02, 217},
+ {22, 0x03, 217},
+ {1, 0x02, 227},
+ {22, 0x03, 227},
+ {1, 0x02, 229},
+ {22, 0x03, 229},
+ },
+ /* 113 */
+ {
+ {2, 0x02, 176},
+ {9, 0x02, 176},
+ {23, 0x02, 176},
+ {40, 0x03, 176},
+ {2, 0x02, 177},
+ {9, 0x02, 177},
+ {23, 0x02, 177},
+ {40, 0x03, 177},
+ {2, 0x02, 179},
+ {9, 0x02, 179},
+ {23, 0x02, 179},
+ {40, 0x03, 179},
+ {2, 0x02, 209},
+ {9, 0x02, 209},
+ {23, 0x02, 209},
+ {40, 0x03, 209},
+ },
+ /* 114 */
+ {
+ {3, 0x02, 176},
+ {6, 0x02, 176},
+ {10, 0x02, 176},
+ {15, 0x02, 176},
+ {24, 0x02, 176},
+ {31, 0x02, 176},
+ {41, 0x02, 176},
+ {56, 0x03, 176},
+ {3, 0x02, 177},
+ {6, 0x02, 177},
+ {10, 0x02, 177},
+ {15, 0x02, 177},
+ {24, 0x02, 177},
+ {31, 0x02, 177},
+ {41, 0x02, 177},
+ {56, 0x03, 177},
+ },
+ /* 115 */
+ {
+ {3, 0x02, 179},
+ {6, 0x02, 179},
+ {10, 0x02, 179},
+ {15, 0x02, 179},
+ {24, 0x02, 179},
+ {31, 0x02, 179},
+ {41, 0x02, 179},
+ {56, 0x03, 179},
+ {3, 0x02, 209},
+ {6, 0x02, 209},
+ {10, 0x02, 209},
+ {15, 0x02, 209},
+ {24, 0x02, 209},
+ {31, 0x02, 209},
+ {41, 0x02, 209},
+ {56, 0x03, 209},
+ },
+ /* 116 */
+ {
+ {2, 0x02, 216},
+ {9, 0x02, 216},
+ {23, 0x02, 216},
+ {40, 0x03, 216},
+ {2, 0x02, 217},
+ {9, 0x02, 217},
+ {23, 0x02, 217},
+ {40, 0x03, 217},
+ {2, 0x02, 227},
+ {9, 0x02, 227},
+ {23, 0x02, 227},
+ {40, 0x03, 227},
+ {2, 0x02, 229},
+ {9, 0x02, 229},
+ {23, 0x02, 229},
+ {40, 0x03, 229},
+ },
+ /* 117 */
+ {
+ {3, 0x02, 216},
+ {6, 0x02, 216},
+ {10, 0x02, 216},
+ {15, 0x02, 216},
+ {24, 0x02, 216},
+ {31, 0x02, 216},
+ {41, 0x02, 216},
+ {56, 0x03, 216},
+ {3, 0x02, 217},
+ {6, 0x02, 217},
+ {10, 0x02, 217},
+ {15, 0x02, 217},
+ {24, 0x02, 217},
+ {31, 0x02, 217},
+ {41, 0x02, 217},
+ {56, 0x03, 217},
+ },
+ /* 118 */
+ {
+ {3, 0x02, 227},
+ {6, 0x02, 227},
+ {10, 0x02, 227},
+ {15, 0x02, 227},
+ {24, 0x02, 227},
+ {31, 0x02, 227},
+ {41, 0x02, 227},
+ {56, 0x03, 227},
+ {3, 0x02, 229},
+ {6, 0x02, 229},
+ {10, 0x02, 229},
+ {15, 0x02, 229},
+ {24, 0x02, 229},
+ {31, 0x02, 229},
+ {41, 0x02, 229},
+ {56, 0x03, 229},
+ },
+ /* 119 */
+ {
+ {1, 0x02, 230},
+ {22, 0x03, 230},
+ {0, 0x03, 129},
+ {0, 0x03, 132},
+ {0, 0x03, 133},
+ {0, 0x03, 134},
+ {0, 0x03, 136},
+ {0, 0x03, 146},
+ {0, 0x03, 154},
+ {0, 0x03, 156},
+ {0, 0x03, 160},
+ {0, 0x03, 163},
+ {0, 0x03, 164},
+ {0, 0x03, 169},
+ {0, 0x03, 170},
+ {0, 0x03, 173},
+ },
+ /* 120 */
+ {
+ {2, 0x02, 230},
+ {9, 0x02, 230},
+ {23, 0x02, 230},
+ {40, 0x03, 230},
+ {1, 0x02, 129},
+ {22, 0x03, 129},
+ {1, 0x02, 132},
+ {22, 0x03, 132},
+ {1, 0x02, 133},
+ {22, 0x03, 133},
+ {1, 0x02, 134},
+ {22, 0x03, 134},
+ {1, 0x02, 136},
+ {22, 0x03, 136},
+ {1, 0x02, 146},
+ {22, 0x03, 146},
+ },
+ /* 121 */
+ {
+ {3, 0x02, 230},
+ {6, 0x02, 230},
+ {10, 0x02, 230},
+ {15, 0x02, 230},
+ {24, 0x02, 230},
+ {31, 0x02, 230},
+ {41, 0x02, 230},
+ {56, 0x03, 230},
+ {2, 0x02, 129},
+ {9, 0x02, 129},
+ {23, 0x02, 129},
+ {40, 0x03, 129},
+ {2, 0x02, 132},
+ {9, 0x02, 132},
+ {23, 0x02, 132},
+ {40, 0x03, 132},
+ },
+ /* 122 */
+ {
+ {3, 0x02, 129},
+ {6, 0x02, 129},
+ {10, 0x02, 129},
+ {15, 0x02, 129},
+ {24, 0x02, 129},
+ {31, 0x02, 129},
+ {41, 0x02, 129},
+ {56, 0x03, 129},
+ {3, 0x02, 132},
+ {6, 0x02, 132},
+ {10, 0x02, 132},
+ {15, 0x02, 132},
+ {24, 0x02, 132},
+ {31, 0x02, 132},
+ {41, 0x02, 132},
+ {56, 0x03, 132},
+ },
+ /* 123 */
+ {
+ {2, 0x02, 133},
+ {9, 0x02, 133},
+ {23, 0x02, 133},
+ {40, 0x03, 133},
+ {2, 0x02, 134},
+ {9, 0x02, 134},
+ {23, 0x02, 134},
+ {40, 0x03, 134},
+ {2, 0x02, 136},
+ {9, 0x02, 136},
+ {23, 0x02, 136},
+ {40, 0x03, 136},
+ {2, 0x02, 146},
+ {9, 0x02, 146},
+ {23, 0x02, 146},
+ {40, 0x03, 146},
+ },
+ /* 124 */
+ {
+ {3, 0x02, 133},
+ {6, 0x02, 133},
+ {10, 0x02, 133},
+ {15, 0x02, 133},
+ {24, 0x02, 133},
+ {31, 0x02, 133},
+ {41, 0x02, 133},
+ {56, 0x03, 133},
+ {3, 0x02, 134},
+ {6, 0x02, 134},
+ {10, 0x02, 134},
+ {15, 0x02, 134},
+ {24, 0x02, 134},
+ {31, 0x02, 134},
+ {41, 0x02, 134},
+ {56, 0x03, 134},
+ },
+ /* 125 */
+ {
+ {3, 0x02, 136},
+ {6, 0x02, 136},
+ {10, 0x02, 136},
+ {15, 0x02, 136},
+ {24, 0x02, 136},
+ {31, 0x02, 136},
+ {41, 0x02, 136},
+ {56, 0x03, 136},
+ {3, 0x02, 146},
+ {6, 0x02, 146},
+ {10, 0x02, 146},
+ {15, 0x02, 146},
+ {24, 0x02, 146},
+ {31, 0x02, 146},
+ {41, 0x02, 146},
+ {56, 0x03, 146},
+ },
+ /* 126 */
+ {
+ {1, 0x02, 154},
+ {22, 0x03, 154},
+ {1, 0x02, 156},
+ {22, 0x03, 156},
+ {1, 0x02, 160},
+ {22, 0x03, 160},
+ {1, 0x02, 163},
+ {22, 0x03, 163},
+ {1, 0x02, 164},
+ {22, 0x03, 164},
+ {1, 0x02, 169},
+ {22, 0x03, 169},
+ {1, 0x02, 170},
+ {22, 0x03, 170},
+ {1, 0x02, 173},
+ {22, 0x03, 173},
+ },
+ /* 127 */
+ {
+ {2, 0x02, 154},
+ {9, 0x02, 154},
+ {23, 0x02, 154},
+ {40, 0x03, 154},
+ {2, 0x02, 156},
+ {9, 0x02, 156},
+ {23, 0x02, 156},
+ {40, 0x03, 156},
+ {2, 0x02, 160},
+ {9, 0x02, 160},
+ {23, 0x02, 160},
+ {40, 0x03, 160},
+ {2, 0x02, 163},
+ {9, 0x02, 163},
+ {23, 0x02, 163},
+ {40, 0x03, 163},
+ },
+ /* 128 */
+ {
+ {3, 0x02, 154},
+ {6, 0x02, 154},
+ {10, 0x02, 154},
+ {15, 0x02, 154},
+ {24, 0x02, 154},
+ {31, 0x02, 154},
+ {41, 0x02, 154},
+ {56, 0x03, 154},
+ {3, 0x02, 156},
+ {6, 0x02, 156},
+ {10, 0x02, 156},
+ {15, 0x02, 156},
+ {24, 0x02, 156},
+ {31, 0x02, 156},
+ {41, 0x02, 156},
+ {56, 0x03, 156},
+ },
+ /* 129 */
+ {
+ {3, 0x02, 160},
+ {6, 0x02, 160},
+ {10, 0x02, 160},
+ {15, 0x02, 160},
+ {24, 0x02, 160},
+ {31, 0x02, 160},
+ {41, 0x02, 160},
+ {56, 0x03, 160},
+ {3, 0x02, 163},
+ {6, 0x02, 163},
+ {10, 0x02, 163},
+ {15, 0x02, 163},
+ {24, 0x02, 163},
+ {31, 0x02, 163},
+ {41, 0x02, 163},
+ {56, 0x03, 163},
+ },
+ /* 130 */
+ {
+ {2, 0x02, 164},
+ {9, 0x02, 164},
+ {23, 0x02, 164},
+ {40, 0x03, 164},
+ {2, 0x02, 169},
+ {9, 0x02, 169},
+ {23, 0x02, 169},
+ {40, 0x03, 169},
+ {2, 0x02, 170},
+ {9, 0x02, 170},
+ {23, 0x02, 170},
+ {40, 0x03, 170},
+ {2, 0x02, 173},
+ {9, 0x02, 173},
+ {23, 0x02, 173},
+ {40, 0x03, 173},
+ },
+ /* 131 */
+ {
+ {3, 0x02, 164},
+ {6, 0x02, 164},
+ {10, 0x02, 164},
+ {15, 0x02, 164},
+ {24, 0x02, 164},
+ {31, 0x02, 164},
+ {41, 0x02, 164},
+ {56, 0x03, 164},
+ {3, 0x02, 169},
+ {6, 0x02, 169},
+ {10, 0x02, 169},
+ {15, 0x02, 169},
+ {24, 0x02, 169},
+ {31, 0x02, 169},
+ {41, 0x02, 169},
+ {56, 0x03, 169},
+ },
+ /* 132 */
+ {
+ {3, 0x02, 170},
+ {6, 0x02, 170},
+ {10, 0x02, 170},
+ {15, 0x02, 170},
+ {24, 0x02, 170},
+ {31, 0x02, 170},
+ {41, 0x02, 170},
+ {56, 0x03, 170},
+ {3, 0x02, 173},
+ {6, 0x02, 173},
+ {10, 0x02, 173},
+ {15, 0x02, 173},
+ {24, 0x02, 173},
+ {31, 0x02, 173},
+ {41, 0x02, 173},
+ {56, 0x03, 173},
+ },
+ /* 133 */
+ {
+ {137, 0x00, 0},
+ {138, 0x00, 0},
+ {140, 0x00, 0},
+ {141, 0x00, 0},
+ {144, 0x00, 0},
+ {145, 0x00, 0},
+ {147, 0x00, 0},
+ {150, 0x00, 0},
+ {156, 0x00, 0},
+ {159, 0x00, 0},
+ {163, 0x00, 0},
+ {166, 0x00, 0},
+ {171, 0x00, 0},
+ {174, 0x00, 0},
+ {181, 0x00, 0},
+ {190, 0x00, 0},
+ },
+ /* 134 */
+ {
+ {0, 0x03, 178},
+ {0, 0x03, 181},
+ {0, 0x03, 185},
+ {0, 0x03, 186},
+ {0, 0x03, 187},
+ {0, 0x03, 189},
+ {0, 0x03, 190},
+ {0, 0x03, 196},
+ {0, 0x03, 198},
+ {0, 0x03, 228},
+ {0, 0x03, 232},
+ {0, 0x03, 233},
+ {148, 0x00, 0},
+ {149, 0x00, 0},
+ {151, 0x00, 0},
+ {152, 0x00, 0},
+ },
+ /* 135 */
+ {
+ {1, 0x02, 178},
+ {22, 0x03, 178},
+ {1, 0x02, 181},
+ {22, 0x03, 181},
+ {1, 0x02, 185},
+ {22, 0x03, 185},
+ {1, 0x02, 186},
+ {22, 0x03, 186},
+ {1, 0x02, 187},
+ {22, 0x03, 187},
+ {1, 0x02, 189},
+ {22, 0x03, 189},
+ {1, 0x02, 190},
+ {22, 0x03, 190},
+ {1, 0x02, 196},
+ {22, 0x03, 196},
+ },
+ /* 136 */
+ {
+ {2, 0x02, 178},
+ {9, 0x02, 178},
+ {23, 0x02, 178},
+ {40, 0x03, 178},
+ {2, 0x02, 181},
+ {9, 0x02, 181},
+ {23, 0x02, 181},
+ {40, 0x03, 181},
+ {2, 0x02, 185},
+ {9, 0x02, 185},
+ {23, 0x02, 185},
+ {40, 0x03, 185},
+ {2, 0x02, 186},
+ {9, 0x02, 186},
+ {23, 0x02, 186},
+ {40, 0x03, 186},
+ },
+ /* 137 */
+ {
+ {3, 0x02, 178},
+ {6, 0x02, 178},
+ {10, 0x02, 178},
+ {15, 0x02, 178},
+ {24, 0x02, 178},
+ {31, 0x02, 178},
+ {41, 0x02, 178},
+ {56, 0x03, 178},
+ {3, 0x02, 181},
+ {6, 0x02, 181},
+ {10, 0x02, 181},
+ {15, 0x02, 181},
+ {24, 0x02, 181},
+ {31, 0x02, 181},
+ {41, 0x02, 181},
+ {56, 0x03, 181},
+ },
+ /* 138 */
+ {
+ {3, 0x02, 185},
+ {6, 0x02, 185},
+ {10, 0x02, 185},
+ {15, 0x02, 185},
+ {24, 0x02, 185},
+ {31, 0x02, 185},
+ {41, 0x02, 185},
+ {56, 0x03, 185},
+ {3, 0x02, 186},
+ {6, 0x02, 186},
+ {10, 0x02, 186},
+ {15, 0x02, 186},
+ {24, 0x02, 186},
+ {31, 0x02, 186},
+ {41, 0x02, 186},
+ {56, 0x03, 186},
+ },
+ /* 139 */
+ {
+ {2, 0x02, 187},
+ {9, 0x02, 187},
+ {23, 0x02, 187},
+ {40, 0x03, 187},
+ {2, 0x02, 189},
+ {9, 0x02, 189},
+ {23, 0x02, 189},
+ {40, 0x03, 189},
+ {2, 0x02, 190},
+ {9, 0x02, 190},
+ {23, 0x02, 190},
+ {40, 0x03, 190},
+ {2, 0x02, 196},
+ {9, 0x02, 196},
+ {23, 0x02, 196},
+ {40, 0x03, 196},
+ },
+ /* 140 */
+ {
+ {3, 0x02, 187},
+ {6, 0x02, 187},
+ {10, 0x02, 187},
+ {15, 0x02, 187},
+ {24, 0x02, 187},
+ {31, 0x02, 187},
+ {41, 0x02, 187},
+ {56, 0x03, 187},
+ {3, 0x02, 189},
+ {6, 0x02, 189},
+ {10, 0x02, 189},
+ {15, 0x02, 189},
+ {24, 0x02, 189},
+ {31, 0x02, 189},
+ {41, 0x02, 189},
+ {56, 0x03, 189},
+ },
+ /* 141 */
+ {
+ {3, 0x02, 190},
+ {6, 0x02, 190},
+ {10, 0x02, 190},
+ {15, 0x02, 190},
+ {24, 0x02, 190},
+ {31, 0x02, 190},
+ {41, 0x02, 190},
+ {56, 0x03, 190},
+ {3, 0x02, 196},
+ {6, 0x02, 196},
+ {10, 0x02, 196},
+ {15, 0x02, 196},
+ {24, 0x02, 196},
+ {31, 0x02, 196},
+ {41, 0x02, 196},
+ {56, 0x03, 196},
+ },
+ /* 142 */
+ {
+ {1, 0x02, 198},
+ {22, 0x03, 198},
+ {1, 0x02, 228},
+ {22, 0x03, 228},
+ {1, 0x02, 232},
+ {22, 0x03, 232},
+ {1, 0x02, 233},
+ {22, 0x03, 233},
+ {0, 0x03, 1},
+ {0, 0x03, 135},
+ {0, 0x03, 137},
+ {0, 0x03, 138},
+ {0, 0x03, 139},
+ {0, 0x03, 140},
+ {0, 0x03, 141},
+ {0, 0x03, 143},
+ },
+ /* 143 */
+ {
+ {2, 0x02, 198},
+ {9, 0x02, 198},
+ {23, 0x02, 198},
+ {40, 0x03, 198},
+ {2, 0x02, 228},
+ {9, 0x02, 228},
+ {23, 0x02, 228},
+ {40, 0x03, 228},
+ {2, 0x02, 232},
+ {9, 0x02, 232},
+ {23, 0x02, 232},
+ {40, 0x03, 232},
+ {2, 0x02, 233},
+ {9, 0x02, 233},
+ {23, 0x02, 233},
+ {40, 0x03, 233},
+ },
+ /* 144 */
+ {
+ {3, 0x02, 198},
+ {6, 0x02, 198},
+ {10, 0x02, 198},
+ {15, 0x02, 198},
+ {24, 0x02, 198},
+ {31, 0x02, 198},
+ {41, 0x02, 198},
+ {56, 0x03, 198},
+ {3, 0x02, 228},
+ {6, 0x02, 228},
+ {10, 0x02, 228},
+ {15, 0x02, 228},
+ {24, 0x02, 228},
+ {31, 0x02, 228},
+ {41, 0x02, 228},
+ {56, 0x03, 228},
+ },
+ /* 145 */
+ {
+ {3, 0x02, 232},
+ {6, 0x02, 232},
+ {10, 0x02, 232},
+ {15, 0x02, 232},
+ {24, 0x02, 232},
+ {31, 0x02, 232},
+ {41, 0x02, 232},
+ {56, 0x03, 232},
+ {3, 0x02, 233},
+ {6, 0x02, 233},
+ {10, 0x02, 233},
+ {15, 0x02, 233},
+ {24, 0x02, 233},
+ {31, 0x02, 233},
+ {41, 0x02, 233},
+ {56, 0x03, 233},
+ },
+ /* 146 */
+ {
+ {1, 0x02, 1},
+ {22, 0x03, 1},
+ {1, 0x02, 135},
+ {22, 0x03, 135},
+ {1, 0x02, 137},
+ {22, 0x03, 137},
+ {1, 0x02, 138},
+ {22, 0x03, 138},
+ {1, 0x02, 139},
+ {22, 0x03, 139},
+ {1, 0x02, 140},
+ {22, 0x03, 140},
+ {1, 0x02, 141},
+ {22, 0x03, 141},
+ {1, 0x02, 143},
+ {22, 0x03, 143},
+ },
+ /* 147 */
+ {
+ {2, 0x02, 1},
+ {9, 0x02, 1},
+ {23, 0x02, 1},
+ {40, 0x03, 1},
+ {2, 0x02, 135},
+ {9, 0x02, 135},
+ {23, 0x02, 135},
+ {40, 0x03, 135},
+ {2, 0x02, 137},
+ {9, 0x02, 137},
+ {23, 0x02, 137},
+ {40, 0x03, 137},
+ {2, 0x02, 138},
+ {9, 0x02, 138},
+ {23, 0x02, 138},
+ {40, 0x03, 138},
+ },
+ /* 148 */
+ {
+ {3, 0x02, 1},
+ {6, 0x02, 1},
+ {10, 0x02, 1},
+ {15, 0x02, 1},
+ {24, 0x02, 1},
+ {31, 0x02, 1},
+ {41, 0x02, 1},
+ {56, 0x03, 1},
+ {3, 0x02, 135},
+ {6, 0x02, 135},
+ {10, 0x02, 135},
+ {15, 0x02, 135},
+ {24, 0x02, 135},
+ {31, 0x02, 135},
+ {41, 0x02, 135},
+ {56, 0x03, 135},
+ },
+ /* 149 */
+ {
+ {3, 0x02, 137},
+ {6, 0x02, 137},
+ {10, 0x02, 137},
+ {15, 0x02, 137},
+ {24, 0x02, 137},
+ {31, 0x02, 137},
+ {41, 0x02, 137},
+ {56, 0x03, 137},
+ {3, 0x02, 138},
+ {6, 0x02, 138},
+ {10, 0x02, 138},
+ {15, 0x02, 138},
+ {24, 0x02, 138},
+ {31, 0x02, 138},
+ {41, 0x02, 138},
+ {56, 0x03, 138},
+ },
+ /* 150 */
+ {
+ {2, 0x02, 139},
+ {9, 0x02, 139},
+ {23, 0x02, 139},
+ {40, 0x03, 139},
+ {2, 0x02, 140},
+ {9, 0x02, 140},
+ {23, 0x02, 140},
+ {40, 0x03, 140},
+ {2, 0x02, 141},
+ {9, 0x02, 141},
+ {23, 0x02, 141},
+ {40, 0x03, 141},
+ {2, 0x02, 143},
+ {9, 0x02, 143},
+ {23, 0x02, 143},
+ {40, 0x03, 143},
+ },
+ /* 151 */
+ {
+ {3, 0x02, 139},
+ {6, 0x02, 139},
+ {10, 0x02, 139},
+ {15, 0x02, 139},
+ {24, 0x02, 139},
+ {31, 0x02, 139},
+ {41, 0x02, 139},
+ {56, 0x03, 139},
+ {3, 0x02, 140},
+ {6, 0x02, 140},
+ {10, 0x02, 140},
+ {15, 0x02, 140},
+ {24, 0x02, 140},
+ {31, 0x02, 140},
+ {41, 0x02, 140},
+ {56, 0x03, 140},
+ },
+ /* 152 */
+ {
+ {3, 0x02, 141},
+ {6, 0x02, 141},
+ {10, 0x02, 141},
+ {15, 0x02, 141},
+ {24, 0x02, 141},
+ {31, 0x02, 141},
+ {41, 0x02, 141},
+ {56, 0x03, 141},
+ {3, 0x02, 143},
+ {6, 0x02, 143},
+ {10, 0x02, 143},
+ {15, 0x02, 143},
+ {24, 0x02, 143},
+ {31, 0x02, 143},
+ {41, 0x02, 143},
+ {56, 0x03, 143},
+ },
+ /* 153 */
+ {
+ {157, 0x00, 0},
+ {158, 0x00, 0},
+ {160, 0x00, 0},
+ {161, 0x00, 0},
+ {164, 0x00, 0},
+ {165, 0x00, 0},
+ {167, 0x00, 0},
+ {168, 0x00, 0},
+ {172, 0x00, 0},
+ {173, 0x00, 0},
+ {175, 0x00, 0},
+ {177, 0x00, 0},
+ {182, 0x00, 0},
+ {185, 0x00, 0},
+ {191, 0x00, 0},
+ {207, 0x00, 0},
+ },
+ /* 154 */
+ {
+ {0, 0x03, 147},
+ {0, 0x03, 149},
+ {0, 0x03, 150},
+ {0, 0x03, 151},
+ {0, 0x03, 152},
+ {0, 0x03, 155},
+ {0, 0x03, 157},
+ {0, 0x03, 158},
+ {0, 0x03, 165},
+ {0, 0x03, 166},
+ {0, 0x03, 168},
+ {0, 0x03, 174},
+ {0, 0x03, 175},
+ {0, 0x03, 180},
+ {0, 0x03, 182},
+ {0, 0x03, 183},
+ },
+ /* 155 */
+ {
+ {1, 0x02, 147},
+ {22, 0x03, 147},
+ {1, 0x02, 149},
+ {22, 0x03, 149},
+ {1, 0x02, 150},
+ {22, 0x03, 150},
+ {1, 0x02, 151},
+ {22, 0x03, 151},
+ {1, 0x02, 152},
+ {22, 0x03, 152},
+ {1, 0x02, 155},
+ {22, 0x03, 155},
+ {1, 0x02, 157},
+ {22, 0x03, 157},
+ {1, 0x02, 158},
+ {22, 0x03, 158},
+ },
+ /* 156 */
+ {
+ {2, 0x02, 147},
+ {9, 0x02, 147},
+ {23, 0x02, 147},
+ {40, 0x03, 147},
+ {2, 0x02, 149},
+ {9, 0x02, 149},
+ {23, 0x02, 149},
+ {40, 0x03, 149},
+ {2, 0x02, 150},
+ {9, 0x02, 150},
+ {23, 0x02, 150},
+ {40, 0x03, 150},
+ {2, 0x02, 151},
+ {9, 0x02, 151},
+ {23, 0x02, 151},
+ {40, 0x03, 151},
+ },
+ /* 157 */
+ {
+ {3, 0x02, 147},
+ {6, 0x02, 147},
+ {10, 0x02, 147},
+ {15, 0x02, 147},
+ {24, 0x02, 147},
+ {31, 0x02, 147},
+ {41, 0x02, 147},
+ {56, 0x03, 147},
+ {3, 0x02, 149},
+ {6, 0x02, 149},
+ {10, 0x02, 149},
+ {15, 0x02, 149},
+ {24, 0x02, 149},
+ {31, 0x02, 149},
+ {41, 0x02, 149},
+ {56, 0x03, 149},
+ },
+ /* 158 */
+ {
+ {3, 0x02, 150},
+ {6, 0x02, 150},
+ {10, 0x02, 150},
+ {15, 0x02, 150},
+ {24, 0x02, 150},
+ {31, 0x02, 150},
+ {41, 0x02, 150},
+ {56, 0x03, 150},
+ {3, 0x02, 151},
+ {6, 0x02, 151},
+ {10, 0x02, 151},
+ {15, 0x02, 151},
+ {24, 0x02, 151},
+ {31, 0x02, 151},
+ {41, 0x02, 151},
+ {56, 0x03, 151},
+ },
+ /* 159 */
+ {
+ {2, 0x02, 152},
+ {9, 0x02, 152},
+ {23, 0x02, 152},
+ {40, 0x03, 152},
+ {2, 0x02, 155},
+ {9, 0x02, 155},
+ {23, 0x02, 155},
+ {40, 0x03, 155},
+ {2, 0x02, 157},
+ {9, 0x02, 157},
+ {23, 0x02, 157},
+ {40, 0x03, 157},
+ {2, 0x02, 158},
+ {9, 0x02, 158},
+ {23, 0x02, 158},
+ {40, 0x03, 158},
+ },
+ /* 160 */
+ {
+ {3, 0x02, 152},
+ {6, 0x02, 152},
+ {10, 0x02, 152},
+ {15, 0x02, 152},
+ {24, 0x02, 152},
+ {31, 0x02, 152},
+ {41, 0x02, 152},
+ {56, 0x03, 152},
+ {3, 0x02, 155},
+ {6, 0x02, 155},
+ {10, 0x02, 155},
+ {15, 0x02, 155},
+ {24, 0x02, 155},
+ {31, 0x02, 155},
+ {41, 0x02, 155},
+ {56, 0x03, 155},
+ },
+ /* 161 */
+ {
+ {3, 0x02, 157},
+ {6, 0x02, 157},
+ {10, 0x02, 157},
+ {15, 0x02, 157},
+ {24, 0x02, 157},
+ {31, 0x02, 157},
+ {41, 0x02, 157},
+ {56, 0x03, 157},
+ {3, 0x02, 158},
+ {6, 0x02, 158},
+ {10, 0x02, 158},
+ {15, 0x02, 158},
+ {24, 0x02, 158},
+ {31, 0x02, 158},
+ {41, 0x02, 158},
+ {56, 0x03, 158},
+ },
+ /* 162 */
+ {
+ {1, 0x02, 165},
+ {22, 0x03, 165},
+ {1, 0x02, 166},
+ {22, 0x03, 166},
+ {1, 0x02, 168},
+ {22, 0x03, 168},
+ {1, 0x02, 174},
+ {22, 0x03, 174},
+ {1, 0x02, 175},
+ {22, 0x03, 175},
+ {1, 0x02, 180},
+ {22, 0x03, 180},
+ {1, 0x02, 182},
+ {22, 0x03, 182},
+ {1, 0x02, 183},
+ {22, 0x03, 183},
+ },
+ /* 163 */
+ {
+ {2, 0x02, 165},
+ {9, 0x02, 165},
+ {23, 0x02, 165},
+ {40, 0x03, 165},
+ {2, 0x02, 166},
+ {9, 0x02, 166},
+ {23, 0x02, 166},
+ {40, 0x03, 166},
+ {2, 0x02, 168},
+ {9, 0x02, 168},
+ {23, 0x02, 168},
+ {40, 0x03, 168},
+ {2, 0x02, 174},
+ {9, 0x02, 174},
+ {23, 0x02, 174},
+ {40, 0x03, 174},
+ },
+ /* 164 */
+ {
+ {3, 0x02, 165},
+ {6, 0x02, 165},
+ {10, 0x02, 165},
+ {15, 0x02, 165},
+ {24, 0x02, 165},
+ {31, 0x02, 165},
+ {41, 0x02, 165},
+ {56, 0x03, 165},
+ {3, 0x02, 166},
+ {6, 0x02, 166},
+ {10, 0x02, 166},
+ {15, 0x02, 166},
+ {24, 0x02, 166},
+ {31, 0x02, 166},
+ {41, 0x02, 166},
+ {56, 0x03, 166},
+ },
+ /* 165 */
+ {
+ {3, 0x02, 168},
+ {6, 0x02, 168},
+ {10, 0x02, 168},
+ {15, 0x02, 168},
+ {24, 0x02, 168},
+ {31, 0x02, 168},
+ {41, 0x02, 168},
+ {56, 0x03, 168},
+ {3, 0x02, 174},
+ {6, 0x02, 174},
+ {10, 0x02, 174},
+ {15, 0x02, 174},
+ {24, 0x02, 174},
+ {31, 0x02, 174},
+ {41, 0x02, 174},
+ {56, 0x03, 174},
+ },
+ /* 166 */
+ {
+ {2, 0x02, 175},
+ {9, 0x02, 175},
+ {23, 0x02, 175},
+ {40, 0x03, 175},
+ {2, 0x02, 180},
+ {9, 0x02, 180},
+ {23, 0x02, 180},
+ {40, 0x03, 180},
+ {2, 0x02, 182},
+ {9, 0x02, 182},
+ {23, 0x02, 182},
+ {40, 0x03, 182},
+ {2, 0x02, 183},
+ {9, 0x02, 183},
+ {23, 0x02, 183},
+ {40, 0x03, 183},
+ },
+ /* 167 */
+ {
+ {3, 0x02, 175},
+ {6, 0x02, 175},
+ {10, 0x02, 175},
+ {15, 0x02, 175},
+ {24, 0x02, 175},
+ {31, 0x02, 175},
+ {41, 0x02, 175},
+ {56, 0x03, 175},
+ {3, 0x02, 180},
+ {6, 0x02, 180},
+ {10, 0x02, 180},
+ {15, 0x02, 180},
+ {24, 0x02, 180},
+ {31, 0x02, 180},
+ {41, 0x02, 180},
+ {56, 0x03, 180},
+ },
+ /* 168 */
+ {
+ {3, 0x02, 182},
+ {6, 0x02, 182},
+ {10, 0x02, 182},
+ {15, 0x02, 182},
+ {24, 0x02, 182},
+ {31, 0x02, 182},
+ {41, 0x02, 182},
+ {56, 0x03, 182},
+ {3, 0x02, 183},
+ {6, 0x02, 183},
+ {10, 0x02, 183},
+ {15, 0x02, 183},
+ {24, 0x02, 183},
+ {31, 0x02, 183},
+ {41, 0x02, 183},
+ {56, 0x03, 183},
+ },
+ /* 169 */
+ {
+ {0, 0x03, 188},
+ {0, 0x03, 191},
+ {0, 0x03, 197},
+ {0, 0x03, 231},
+ {0, 0x03, 239},
+ {176, 0x00, 0},
+ {178, 0x00, 0},
+ {179, 0x00, 0},
+ {183, 0x00, 0},
+ {184, 0x00, 0},
+ {186, 0x00, 0},
+ {187, 0x00, 0},
+ {192, 0x00, 0},
+ {199, 0x00, 0},
+ {208, 0x00, 0},
+ {223, 0x00, 0},
+ },
+ /* 170 */
+ {
+ {1, 0x02, 188},
+ {22, 0x03, 188},
+ {1, 0x02, 191},
+ {22, 0x03, 191},
+ {1, 0x02, 197},
+ {22, 0x03, 197},
+ {1, 0x02, 231},
+ {22, 0x03, 231},
+ {1, 0x02, 239},
+ {22, 0x03, 239},
+ {0, 0x03, 9},
+ {0, 0x03, 142},
+ {0, 0x03, 144},
+ {0, 0x03, 145},
+ {0, 0x03, 148},
+ {0, 0x03, 159},
+ },
+ /* 171 */
+ {
+ {2, 0x02, 188},
+ {9, 0x02, 188},
+ {23, 0x02, 188},
+ {40, 0x03, 188},
+ {2, 0x02, 191},
+ {9, 0x02, 191},
+ {23, 0x02, 191},
+ {40, 0x03, 191},
+ {2, 0x02, 197},
+ {9, 0x02, 197},
+ {23, 0x02, 197},
+ {40, 0x03, 197},
+ {2, 0x02, 231},
+ {9, 0x02, 231},
+ {23, 0x02, 231},
+ {40, 0x03, 231},
+ },
+ /* 172 */
+ {
+ {3, 0x02, 188},
+ {6, 0x02, 188},
+ {10, 0x02, 188},
+ {15, 0x02, 188},
+ {24, 0x02, 188},
+ {31, 0x02, 188},
+ {41, 0x02, 188},
+ {56, 0x03, 188},
+ {3, 0x02, 191},
+ {6, 0x02, 191},
+ {10, 0x02, 191},
+ {15, 0x02, 191},
+ {24, 0x02, 191},
+ {31, 0x02, 191},
+ {41, 0x02, 191},
+ {56, 0x03, 191},
+ },
+ /* 173 */
+ {
+ {3, 0x02, 197},
+ {6, 0x02, 197},
+ {10, 0x02, 197},
+ {15, 0x02, 197},
+ {24, 0x02, 197},
+ {31, 0x02, 197},
+ {41, 0x02, 197},
+ {56, 0x03, 197},
+ {3, 0x02, 231},
+ {6, 0x02, 231},
+ {10, 0x02, 231},
+ {15, 0x02, 231},
+ {24, 0x02, 231},
+ {31, 0x02, 231},
+ {41, 0x02, 231},
+ {56, 0x03, 231},
+ },
+ /* 174 */
+ {
+ {2, 0x02, 239},
+ {9, 0x02, 239},
+ {23, 0x02, 239},
+ {40, 0x03, 239},
+ {1, 0x02, 9},
+ {22, 0x03, 9},
+ {1, 0x02, 142},
+ {22, 0x03, 142},
+ {1, 0x02, 144},
+ {22, 0x03, 144},
+ {1, 0x02, 145},
+ {22, 0x03, 145},
+ {1, 0x02, 148},
+ {22, 0x03, 148},
+ {1, 0x02, 159},
+ {22, 0x03, 159},
+ },
+ /* 175 */
+ {
+ {3, 0x02, 239},
+ {6, 0x02, 239},
+ {10, 0x02, 239},
+ {15, 0x02, 239},
+ {24, 0x02, 239},
+ {31, 0x02, 239},
+ {41, 0x02, 239},
+ {56, 0x03, 239},
+ {2, 0x02, 9},
+ {9, 0x02, 9},
+ {23, 0x02, 9},
+ {40, 0x03, 9},
+ {2, 0x02, 142},
+ {9, 0x02, 142},
+ {23, 0x02, 142},
+ {40, 0x03, 142},
+ },
+ /* 176 */
+ {
+ {3, 0x02, 9},
+ {6, 0x02, 9},
+ {10, 0x02, 9},
+ {15, 0x02, 9},
+ {24, 0x02, 9},
+ {31, 0x02, 9},
+ {41, 0x02, 9},
+ {56, 0x03, 9},
+ {3, 0x02, 142},
+ {6, 0x02, 142},
+ {10, 0x02, 142},
+ {15, 0x02, 142},
+ {24, 0x02, 142},
+ {31, 0x02, 142},
+ {41, 0x02, 142},
+ {56, 0x03, 142},
+ },
+ /* 177 */
+ {
+ {2, 0x02, 144},
+ {9, 0x02, 144},
+ {23, 0x02, 144},
+ {40, 0x03, 144},
+ {2, 0x02, 145},
+ {9, 0x02, 145},
+ {23, 0x02, 145},
+ {40, 0x03, 145},
+ {2, 0x02, 148},
+ {9, 0x02, 148},
+ {23, 0x02, 148},
+ {40, 0x03, 148},
+ {2, 0x02, 159},
+ {9, 0x02, 159},
+ {23, 0x02, 159},
+ {40, 0x03, 159},
+ },
+ /* 178 */
+ {
+ {3, 0x02, 144},
+ {6, 0x02, 144},
+ {10, 0x02, 144},
+ {15, 0x02, 144},
+ {24, 0x02, 144},
+ {31, 0x02, 144},
+ {41, 0x02, 144},
+ {56, 0x03, 144},
+ {3, 0x02, 145},
+ {6, 0x02, 145},
+ {10, 0x02, 145},
+ {15, 0x02, 145},
+ {24, 0x02, 145},
+ {31, 0x02, 145},
+ {41, 0x02, 145},
+ {56, 0x03, 145},
+ },
+ /* 179 */
+ {
+ {3, 0x02, 148},
+ {6, 0x02, 148},
+ {10, 0x02, 148},
+ {15, 0x02, 148},
+ {24, 0x02, 148},
+ {31, 0x02, 148},
+ {41, 0x02, 148},
+ {56, 0x03, 148},
+ {3, 0x02, 159},
+ {6, 0x02, 159},
+ {10, 0x02, 159},
+ {15, 0x02, 159},
+ {24, 0x02, 159},
+ {31, 0x02, 159},
+ {41, 0x02, 159},
+ {56, 0x03, 159},
+ },
+ /* 180 */
+ {
+ {0, 0x03, 171},
+ {0, 0x03, 206},
+ {0, 0x03, 215},
+ {0, 0x03, 225},
+ {0, 0x03, 236},
+ {0, 0x03, 237},
+ {188, 0x00, 0},
+ {189, 0x00, 0},
+ {193, 0x00, 0},
+ {196, 0x00, 0},
+ {200, 0x00, 0},
+ {203, 0x00, 0},
+ {209, 0x00, 0},
+ {216, 0x00, 0},
+ {224, 0x00, 0},
+ {238, 0x00, 0},
+ },
+ /* 181 */
+ {
+ {1, 0x02, 171},
+ {22, 0x03, 171},
+ {1, 0x02, 206},
+ {22, 0x03, 206},
+ {1, 0x02, 215},
+ {22, 0x03, 215},
+ {1, 0x02, 225},
+ {22, 0x03, 225},
+ {1, 0x02, 236},
+ {22, 0x03, 236},
+ {1, 0x02, 237},
+ {22, 0x03, 237},
+ {0, 0x03, 199},
+ {0, 0x03, 207},
+ {0, 0x03, 234},
+ {0, 0x03, 235},
+ },
+ /* 182 */
+ {
+ {2, 0x02, 171},
+ {9, 0x02, 171},
+ {23, 0x02, 171},
+ {40, 0x03, 171},
+ {2, 0x02, 206},
+ {9, 0x02, 206},
+ {23, 0x02, 206},
+ {40, 0x03, 206},
+ {2, 0x02, 215},
+ {9, 0x02, 215},
+ {23, 0x02, 215},
+ {40, 0x03, 215},
+ {2, 0x02, 225},
+ {9, 0x02, 225},
+ {23, 0x02, 225},
+ {40, 0x03, 225},
+ },
+ /* 183 */
+ {
+ {3, 0x02, 171},
+ {6, 0x02, 171},
+ {10, 0x02, 171},
+ {15, 0x02, 171},
+ {24, 0x02, 171},
+ {31, 0x02, 171},
+ {41, 0x02, 171},
+ {56, 0x03, 171},
+ {3, 0x02, 206},
+ {6, 0x02, 206},
+ {10, 0x02, 206},
+ {15, 0x02, 206},
+ {24, 0x02, 206},
+ {31, 0x02, 206},
+ {41, 0x02, 206},
+ {56, 0x03, 206},
+ },
+ /* 184 */
+ {
+ {3, 0x02, 215},
+ {6, 0x02, 215},
+ {10, 0x02, 215},
+ {15, 0x02, 215},
+ {24, 0x02, 215},
+ {31, 0x02, 215},
+ {41, 0x02, 215},
+ {56, 0x03, 215},
+ {3, 0x02, 225},
+ {6, 0x02, 225},
+ {10, 0x02, 225},
+ {15, 0x02, 225},
+ {24, 0x02, 225},
+ {31, 0x02, 225},
+ {41, 0x02, 225},
+ {56, 0x03, 225},
+ },
+ /* 185 */
+ {
+ {2, 0x02, 236},
+ {9, 0x02, 236},
+ {23, 0x02, 236},
+ {40, 0x03, 236},
+ {2, 0x02, 237},
+ {9, 0x02, 237},
+ {23, 0x02, 237},
+ {40, 0x03, 237},
+ {1, 0x02, 199},
+ {22, 0x03, 199},
+ {1, 0x02, 207},
+ {22, 0x03, 207},
+ {1, 0x02, 234},
+ {22, 0x03, 234},
+ {1, 0x02, 235},
+ {22, 0x03, 235},
+ },
+ /* 186 */
+ {
+ {3, 0x02, 236},
+ {6, 0x02, 236},
+ {10, 0x02, 236},
+ {15, 0x02, 236},
+ {24, 0x02, 236},
+ {31, 0x02, 236},
+ {41, 0x02, 236},
+ {56, 0x03, 236},
+ {3, 0x02, 237},
+ {6, 0x02, 237},
+ {10, 0x02, 237},
+ {15, 0x02, 237},
+ {24, 0x02, 237},
+ {31, 0x02, 237},
+ {41, 0x02, 237},
+ {56, 0x03, 237},
+ },
+ /* 187 */
+ {
+ {2, 0x02, 199},
+ {9, 0x02, 199},
+ {23, 0x02, 199},
+ {40, 0x03, 199},
+ {2, 0x02, 207},
+ {9, 0x02, 207},
+ {23, 0x02, 207},
+ {40, 0x03, 207},
+ {2, 0x02, 234},
+ {9, 0x02, 234},
+ {23, 0x02, 234},
+ {40, 0x03, 234},
+ {2, 0x02, 235},
+ {9, 0x02, 235},
+ {23, 0x02, 235},
+ {40, 0x03, 235},
+ },
+ /* 188 */
+ {
+ {3, 0x02, 199},
+ {6, 0x02, 199},
+ {10, 0x02, 199},
+ {15, 0x02, 199},
+ {24, 0x02, 199},
+ {31, 0x02, 199},
+ {41, 0x02, 199},
+ {56, 0x03, 199},
+ {3, 0x02, 207},
+ {6, 0x02, 207},
+ {10, 0x02, 207},
+ {15, 0x02, 207},
+ {24, 0x02, 207},
+ {31, 0x02, 207},
+ {41, 0x02, 207},
+ {56, 0x03, 207},
+ },
+ /* 189 */
+ {
+ {3, 0x02, 234},
+ {6, 0x02, 234},
+ {10, 0x02, 234},
+ {15, 0x02, 234},
+ {24, 0x02, 234},
+ {31, 0x02, 234},
+ {41, 0x02, 234},
+ {56, 0x03, 234},
+ {3, 0x02, 235},
+ {6, 0x02, 235},
+ {10, 0x02, 235},
+ {15, 0x02, 235},
+ {24, 0x02, 235},
+ {31, 0x02, 235},
+ {41, 0x02, 235},
+ {56, 0x03, 235},
+ },
+ /* 190 */
+ {
+ {194, 0x00, 0},
+ {195, 0x00, 0},
+ {197, 0x00, 0},
+ {198, 0x00, 0},
+ {201, 0x00, 0},
+ {202, 0x00, 0},
+ {204, 0x00, 0},
+ {205, 0x00, 0},
+ {210, 0x00, 0},
+ {213, 0x00, 0},
+ {217, 0x00, 0},
+ {220, 0x00, 0},
+ {225, 0x00, 0},
+ {231, 0x00, 0},
+ {239, 0x00, 0},
+ {246, 0x00, 0},
+ },
+ /* 191 */
+ {
+ {0, 0x03, 192},
+ {0, 0x03, 193},
+ {0, 0x03, 200},
+ {0, 0x03, 201},
+ {0, 0x03, 202},
+ {0, 0x03, 205},
+ {0, 0x03, 210},
+ {0, 0x03, 213},
+ {0, 0x03, 218},
+ {0, 0x03, 219},
+ {0, 0x03, 238},
+ {0, 0x03, 240},
+ {0, 0x03, 242},
+ {0, 0x03, 243},
+ {0, 0x03, 255},
+ {206, 0x00, 0},
+ },
+ /* 192 */
+ {
+ {1, 0x02, 192},
+ {22, 0x03, 192},
+ {1, 0x02, 193},
+ {22, 0x03, 193},
+ {1, 0x02, 200},
+ {22, 0x03, 200},
+ {1, 0x02, 201},
+ {22, 0x03, 201},
+ {1, 0x02, 202},
+ {22, 0x03, 202},
+ {1, 0x02, 205},
+ {22, 0x03, 205},
+ {1, 0x02, 210},
+ {22, 0x03, 210},
+ {1, 0x02, 213},
+ {22, 0x03, 213},
+ },
+ /* 193 */
+ {
+ {2, 0x02, 192},
+ {9, 0x02, 192},
+ {23, 0x02, 192},
+ {40, 0x03, 192},
+ {2, 0x02, 193},
+ {9, 0x02, 193},
+ {23, 0x02, 193},
+ {40, 0x03, 193},
+ {2, 0x02, 200},
+ {9, 0x02, 200},
+ {23, 0x02, 200},
+ {40, 0x03, 200},
+ {2, 0x02, 201},
+ {9, 0x02, 201},
+ {23, 0x02, 201},
+ {40, 0x03, 201},
+ },
+ /* 194 */
+ {
+ {3, 0x02, 192},
+ {6, 0x02, 192},
+ {10, 0x02, 192},
+ {15, 0x02, 192},
+ {24, 0x02, 192},
+ {31, 0x02, 192},
+ {41, 0x02, 192},
+ {56, 0x03, 192},
+ {3, 0x02, 193},
+ {6, 0x02, 193},
+ {10, 0x02, 193},
+ {15, 0x02, 193},
+ {24, 0x02, 193},
+ {31, 0x02, 193},
+ {41, 0x02, 193},
+ {56, 0x03, 193},
+ },
+ /* 195 */
+ {
+ {3, 0x02, 200},
+ {6, 0x02, 200},
+ {10, 0x02, 200},
+ {15, 0x02, 200},
+ {24, 0x02, 200},
+ {31, 0x02, 200},
+ {41, 0x02, 200},
+ {56, 0x03, 200},
+ {3, 0x02, 201},
+ {6, 0x02, 201},
+ {10, 0x02, 201},
+ {15, 0x02, 201},
+ {24, 0x02, 201},
+ {31, 0x02, 201},
+ {41, 0x02, 201},
+ {56, 0x03, 201},
+ },
+ /* 196 */
+ {
+ {2, 0x02, 202},
+ {9, 0x02, 202},
+ {23, 0x02, 202},
+ {40, 0x03, 202},
+ {2, 0x02, 205},
+ {9, 0x02, 205},
+ {23, 0x02, 205},
+ {40, 0x03, 205},
+ {2, 0x02, 210},
+ {9, 0x02, 210},
+ {23, 0x02, 210},
+ {40, 0x03, 210},
+ {2, 0x02, 213},
+ {9, 0x02, 213},
+ {23, 0x02, 213},
+ {40, 0x03, 213},
+ },
+ /* 197 */
+ {
+ {3, 0x02, 202},
+ {6, 0x02, 202},
+ {10, 0x02, 202},
+ {15, 0x02, 202},
+ {24, 0x02, 202},
+ {31, 0x02, 202},
+ {41, 0x02, 202},
+ {56, 0x03, 202},
+ {3, 0x02, 205},
+ {6, 0x02, 205},
+ {10, 0x02, 205},
+ {15, 0x02, 205},
+ {24, 0x02, 205},
+ {31, 0x02, 205},
+ {41, 0x02, 205},
+ {56, 0x03, 205},
+ },
+ /* 198 */
+ {
+ {3, 0x02, 210},
+ {6, 0x02, 210},
+ {10, 0x02, 210},
+ {15, 0x02, 210},
+ {24, 0x02, 210},
+ {31, 0x02, 210},
+ {41, 0x02, 210},
+ {56, 0x03, 210},
+ {3, 0x02, 213},
+ {6, 0x02, 213},
+ {10, 0x02, 213},
+ {15, 0x02, 213},
+ {24, 0x02, 213},
+ {31, 0x02, 213},
+ {41, 0x02, 213},
+ {56, 0x03, 213},
+ },
+ /* 199 */
+ {
+ {1, 0x02, 218},
+ {22, 0x03, 218},
+ {1, 0x02, 219},
+ {22, 0x03, 219},
+ {1, 0x02, 238},
+ {22, 0x03, 238},
+ {1, 0x02, 240},
+ {22, 0x03, 240},
+ {1, 0x02, 242},
+ {22, 0x03, 242},
+ {1, 0x02, 243},
+ {22, 0x03, 243},
+ {1, 0x02, 255},
+ {22, 0x03, 255},
+ {0, 0x03, 203},
+ {0, 0x03, 204},
+ },
+ /* 200 */
+ {
+ {2, 0x02, 218},
+ {9, 0x02, 218},
+ {23, 0x02, 218},
+ {40, 0x03, 218},
+ {2, 0x02, 219},
+ {9, 0x02, 219},
+ {23, 0x02, 219},
+ {40, 0x03, 219},
+ {2, 0x02, 238},
+ {9, 0x02, 238},
+ {23, 0x02, 238},
+ {40, 0x03, 238},
+ {2, 0x02, 240},
+ {9, 0x02, 240},
+ {23, 0x02, 240},
+ {40, 0x03, 240},
+ },
+ /* 201 */
+ {
+ {3, 0x02, 218},
+ {6, 0x02, 218},
+ {10, 0x02, 218},
+ {15, 0x02, 218},
+ {24, 0x02, 218},
+ {31, 0x02, 218},
+ {41, 0x02, 218},
+ {56, 0x03, 218},
+ {3, 0x02, 219},
+ {6, 0x02, 219},
+ {10, 0x02, 219},
+ {15, 0x02, 219},
+ {24, 0x02, 219},
+ {31, 0x02, 219},
+ {41, 0x02, 219},
+ {56, 0x03, 219},
+ },
+ /* 202 */
+ {
+ {3, 0x02, 238},
+ {6, 0x02, 238},
+ {10, 0x02, 238},
+ {15, 0x02, 238},
+ {24, 0x02, 238},
+ {31, 0x02, 238},
+ {41, 0x02, 238},
+ {56, 0x03, 238},
+ {3, 0x02, 240},
+ {6, 0x02, 240},
+ {10, 0x02, 240},
+ {15, 0x02, 240},
+ {24, 0x02, 240},
+ {31, 0x02, 240},
+ {41, 0x02, 240},
+ {56, 0x03, 240},
+ },
+ /* 203 */
+ {
+ {2, 0x02, 242},
+ {9, 0x02, 242},
+ {23, 0x02, 242},
+ {40, 0x03, 242},
+ {2, 0x02, 243},
+ {9, 0x02, 243},
+ {23, 0x02, 243},
+ {40, 0x03, 243},
+ {2, 0x02, 255},
+ {9, 0x02, 255},
+ {23, 0x02, 255},
+ {40, 0x03, 255},
+ {1, 0x02, 203},
+ {22, 0x03, 203},
+ {1, 0x02, 204},
+ {22, 0x03, 204},
+ },
+ /* 204 */
+ {
+ {3, 0x02, 242},
+ {6, 0x02, 242},
+ {10, 0x02, 242},
+ {15, 0x02, 242},
+ {24, 0x02, 242},
+ {31, 0x02, 242},
+ {41, 0x02, 242},
+ {56, 0x03, 242},
+ {3, 0x02, 243},
+ {6, 0x02, 243},
+ {10, 0x02, 243},
+ {15, 0x02, 243},
+ {24, 0x02, 243},
+ {31, 0x02, 243},
+ {41, 0x02, 243},
+ {56, 0x03, 243},
+ },
+ /* 205 */
+ {
+ {3, 0x02, 255},
+ {6, 0x02, 255},
+ {10, 0x02, 255},
+ {15, 0x02, 255},
+ {24, 0x02, 255},
+ {31, 0x02, 255},
+ {41, 0x02, 255},
+ {56, 0x03, 255},
+ {2, 0x02, 203},
+ {9, 0x02, 203},
+ {23, 0x02, 203},
+ {40, 0x03, 203},
+ {2, 0x02, 204},
+ {9, 0x02, 204},
+ {23, 0x02, 204},
+ {40, 0x03, 204},
+ },
+ /* 206 */
+ {
+ {3, 0x02, 203},
+ {6, 0x02, 203},
+ {10, 0x02, 203},
+ {15, 0x02, 203},
+ {24, 0x02, 203},
+ {31, 0x02, 203},
+ {41, 0x02, 203},
+ {56, 0x03, 203},
+ {3, 0x02, 204},
+ {6, 0x02, 204},
+ {10, 0x02, 204},
+ {15, 0x02, 204},
+ {24, 0x02, 204},
+ {31, 0x02, 204},
+ {41, 0x02, 204},
+ {56, 0x03, 204},
+ },
+ /* 207 */
+ {
+ {211, 0x00, 0},
+ {212, 0x00, 0},
+ {214, 0x00, 0},
+ {215, 0x00, 0},
+ {218, 0x00, 0},
+ {219, 0x00, 0},
+ {221, 0x00, 0},
+ {222, 0x00, 0},
+ {226, 0x00, 0},
+ {228, 0x00, 0},
+ {232, 0x00, 0},
+ {235, 0x00, 0},
+ {240, 0x00, 0},
+ {243, 0x00, 0},
+ {247, 0x00, 0},
+ {250, 0x00, 0},
+ },
+ /* 208 */
+ {
+ {0, 0x03, 211},
+ {0, 0x03, 212},
+ {0, 0x03, 214},
+ {0, 0x03, 221},
+ {0, 0x03, 222},
+ {0, 0x03, 223},
+ {0, 0x03, 241},
+ {0, 0x03, 244},
+ {0, 0x03, 245},
+ {0, 0x03, 246},
+ {0, 0x03, 247},
+ {0, 0x03, 248},
+ {0, 0x03, 250},
+ {0, 0x03, 251},
+ {0, 0x03, 252},
+ {0, 0x03, 253},
+ },
+ /* 209 */
+ {
+ {1, 0x02, 211},
+ {22, 0x03, 211},
+ {1, 0x02, 212},
+ {22, 0x03, 212},
+ {1, 0x02, 214},
+ {22, 0x03, 214},
+ {1, 0x02, 221},
+ {22, 0x03, 221},
+ {1, 0x02, 222},
+ {22, 0x03, 222},
+ {1, 0x02, 223},
+ {22, 0x03, 223},
+ {1, 0x02, 241},
+ {22, 0x03, 241},
+ {1, 0x02, 244},
+ {22, 0x03, 244},
+ },
+ /* 210 */
+ {
+ {2, 0x02, 211},
+ {9, 0x02, 211},
+ {23, 0x02, 211},
+ {40, 0x03, 211},
+ {2, 0x02, 212},
+ {9, 0x02, 212},
+ {23, 0x02, 212},
+ {40, 0x03, 212},
+ {2, 0x02, 214},
+ {9, 0x02, 214},
+ {23, 0x02, 214},
+ {40, 0x03, 214},
+ {2, 0x02, 221},
+ {9, 0x02, 221},
+ {23, 0x02, 221},
+ {40, 0x03, 221},
+ },
+ /* 211 */
+ {
+ {3, 0x02, 211},
+ {6, 0x02, 211},
+ {10, 0x02, 211},
+ {15, 0x02, 211},
+ {24, 0x02, 211},
+ {31, 0x02, 211},
+ {41, 0x02, 211},
+ {56, 0x03, 211},
+ {3, 0x02, 212},
+ {6, 0x02, 212},
+ {10, 0x02, 212},
+ {15, 0x02, 212},
+ {24, 0x02, 212},
+ {31, 0x02, 212},
+ {41, 0x02, 212},
+ {56, 0x03, 212},
+ },
+ /* 212 */
+ {
+ {3, 0x02, 214},
+ {6, 0x02, 214},
+ {10, 0x02, 214},
+ {15, 0x02, 214},
+ {24, 0x02, 214},
+ {31, 0x02, 214},
+ {41, 0x02, 214},
+ {56, 0x03, 214},
+ {3, 0x02, 221},
+ {6, 0x02, 221},
+ {10, 0x02, 221},
+ {15, 0x02, 221},
+ {24, 0x02, 221},
+ {31, 0x02, 221},
+ {41, 0x02, 221},
+ {56, 0x03, 221},
+ },
+ /* 213 */
+ {
+ {2, 0x02, 222},
+ {9, 0x02, 222},
+ {23, 0x02, 222},
+ {40, 0x03, 222},
+ {2, 0x02, 223},
+ {9, 0x02, 223},
+ {23, 0x02, 223},
+ {40, 0x03, 223},
+ {2, 0x02, 241},
+ {9, 0x02, 241},
+ {23, 0x02, 241},
+ {40, 0x03, 241},
+ {2, 0x02, 244},
+ {9, 0x02, 244},
+ {23, 0x02, 244},
+ {40, 0x03, 244},
+ },
+ /* 214 */
+ {
+ {3, 0x02, 222},
+ {6, 0x02, 222},
+ {10, 0x02, 222},
+ {15, 0x02, 222},
+ {24, 0x02, 222},
+ {31, 0x02, 222},
+ {41, 0x02, 222},
+ {56, 0x03, 222},
+ {3, 0x02, 223},
+ {6, 0x02, 223},
+ {10, 0x02, 223},
+ {15, 0x02, 223},
+ {24, 0x02, 223},
+ {31, 0x02, 223},
+ {41, 0x02, 223},
+ {56, 0x03, 223},
+ },
+ /* 215 */
+ {
+ {3, 0x02, 241},
+ {6, 0x02, 241},
+ {10, 0x02, 241},
+ {15, 0x02, 241},
+ {24, 0x02, 241},
+ {31, 0x02, 241},
+ {41, 0x02, 241},
+ {56, 0x03, 241},
+ {3, 0x02, 244},
+ {6, 0x02, 244},
+ {10, 0x02, 244},
+ {15, 0x02, 244},
+ {24, 0x02, 244},
+ {31, 0x02, 244},
+ {41, 0x02, 244},
+ {56, 0x03, 244},
+ },
+ /* 216 */
+ {
+ {1, 0x02, 245},
+ {22, 0x03, 245},
+ {1, 0x02, 246},
+ {22, 0x03, 246},
+ {1, 0x02, 247},
+ {22, 0x03, 247},
+ {1, 0x02, 248},
+ {22, 0x03, 248},
+ {1, 0x02, 250},
+ {22, 0x03, 250},
+ {1, 0x02, 251},
+ {22, 0x03, 251},
+ {1, 0x02, 252},
+ {22, 0x03, 252},
+ {1, 0x02, 253},
+ {22, 0x03, 253},
+ },
+ /* 217 */
+ {
+ {2, 0x02, 245},
+ {9, 0x02, 245},
+ {23, 0x02, 245},
+ {40, 0x03, 245},
+ {2, 0x02, 246},
+ {9, 0x02, 246},
+ {23, 0x02, 246},
+ {40, 0x03, 246},
+ {2, 0x02, 247},
+ {9, 0x02, 247},
+ {23, 0x02, 247},
+ {40, 0x03, 247},
+ {2, 0x02, 248},
+ {9, 0x02, 248},
+ {23, 0x02, 248},
+ {40, 0x03, 248},
+ },
+ /* 218 */
+ {
+ {3, 0x02, 245},
+ {6, 0x02, 245},
+ {10, 0x02, 245},
+ {15, 0x02, 245},
+ {24, 0x02, 245},
+ {31, 0x02, 245},
+ {41, 0x02, 245},
+ {56, 0x03, 245},
+ {3, 0x02, 246},
+ {6, 0x02, 246},
+ {10, 0x02, 246},
+ {15, 0x02, 246},
+ {24, 0x02, 246},
+ {31, 0x02, 246},
+ {41, 0x02, 246},
+ {56, 0x03, 246},
+ },
+ /* 219 */
+ {
+ {3, 0x02, 247},
+ {6, 0x02, 247},
+ {10, 0x02, 247},
+ {15, 0x02, 247},
+ {24, 0x02, 247},
+ {31, 0x02, 247},
+ {41, 0x02, 247},
+ {56, 0x03, 247},
+ {3, 0x02, 248},
+ {6, 0x02, 248},
+ {10, 0x02, 248},
+ {15, 0x02, 248},
+ {24, 0x02, 248},
+ {31, 0x02, 248},
+ {41, 0x02, 248},
+ {56, 0x03, 248},
+ },
+ /* 220 */
+ {
+ {2, 0x02, 250},
+ {9, 0x02, 250},
+ {23, 0x02, 250},
+ {40, 0x03, 250},
+ {2, 0x02, 251},
+ {9, 0x02, 251},
+ {23, 0x02, 251},
+ {40, 0x03, 251},
+ {2, 0x02, 252},
+ {9, 0x02, 252},
+ {23, 0x02, 252},
+ {40, 0x03, 252},
+ {2, 0x02, 253},
+ {9, 0x02, 253},
+ {23, 0x02, 253},
+ {40, 0x03, 253},
+ },
+ /* 221 */
+ {
+ {3, 0x02, 250},
+ {6, 0x02, 250},
+ {10, 0x02, 250},
+ {15, 0x02, 250},
+ {24, 0x02, 250},
+ {31, 0x02, 250},
+ {41, 0x02, 250},
+ {56, 0x03, 250},
+ {3, 0x02, 251},
+ {6, 0x02, 251},
+ {10, 0x02, 251},
+ {15, 0x02, 251},
+ {24, 0x02, 251},
+ {31, 0x02, 251},
+ {41, 0x02, 251},
+ {56, 0x03, 251},
+ },
+ /* 222 */
+ {
+ {3, 0x02, 252},
+ {6, 0x02, 252},
+ {10, 0x02, 252},
+ {15, 0x02, 252},
+ {24, 0x02, 252},
+ {31, 0x02, 252},
+ {41, 0x02, 252},
+ {56, 0x03, 252},
+ {3, 0x02, 253},
+ {6, 0x02, 253},
+ {10, 0x02, 253},
+ {15, 0x02, 253},
+ {24, 0x02, 253},
+ {31, 0x02, 253},
+ {41, 0x02, 253},
+ {56, 0x03, 253},
+ },
+ /* 223 */
+ {
+ {0, 0x03, 254},
+ {227, 0x00, 0},
+ {229, 0x00, 0},
+ {230, 0x00, 0},
+ {233, 0x00, 0},
+ {234, 0x00, 0},
+ {236, 0x00, 0},
+ {237, 0x00, 0},
+ {241, 0x00, 0},
+ {242, 0x00, 0},
+ {244, 0x00, 0},
+ {245, 0x00, 0},
+ {248, 0x00, 0},
+ {249, 0x00, 0},
+ {251, 0x00, 0},
+ {252, 0x00, 0},
+ },
+ /* 224 */
+ {
+ {1, 0x02, 254},
+ {22, 0x03, 254},
+ {0, 0x03, 2},
+ {0, 0x03, 3},
+ {0, 0x03, 4},
+ {0, 0x03, 5},
+ {0, 0x03, 6},
+ {0, 0x03, 7},
+ {0, 0x03, 8},
+ {0, 0x03, 11},
+ {0, 0x03, 12},
+ {0, 0x03, 14},
+ {0, 0x03, 15},
+ {0, 0x03, 16},
+ {0, 0x03, 17},
+ {0, 0x03, 18},
+ },
+ /* 225 */
+ {
+ {2, 0x02, 254},
+ {9, 0x02, 254},
+ {23, 0x02, 254},
+ {40, 0x03, 254},
+ {1, 0x02, 2},
+ {22, 0x03, 2},
+ {1, 0x02, 3},
+ {22, 0x03, 3},
+ {1, 0x02, 4},
+ {22, 0x03, 4},
+ {1, 0x02, 5},
+ {22, 0x03, 5},
+ {1, 0x02, 6},
+ {22, 0x03, 6},
+ {1, 0x02, 7},
+ {22, 0x03, 7},
+ },
+ /* 226 */
+ {
+ {3, 0x02, 254},
+ {6, 0x02, 254},
+ {10, 0x02, 254},
+ {15, 0x02, 254},
+ {24, 0x02, 254},
+ {31, 0x02, 254},
+ {41, 0x02, 254},
+ {56, 0x03, 254},
+ {2, 0x02, 2},
+ {9, 0x02, 2},
+ {23, 0x02, 2},
+ {40, 0x03, 2},
+ {2, 0x02, 3},
+ {9, 0x02, 3},
+ {23, 0x02, 3},
+ {40, 0x03, 3},
+ },
+ /* 227 */
+ {
+ {3, 0x02, 2},
+ {6, 0x02, 2},
+ {10, 0x02, 2},
+ {15, 0x02, 2},
+ {24, 0x02, 2},
+ {31, 0x02, 2},
+ {41, 0x02, 2},
+ {56, 0x03, 2},
+ {3, 0x02, 3},
+ {6, 0x02, 3},
+ {10, 0x02, 3},
+ {15, 0x02, 3},
+ {24, 0x02, 3},
+ {31, 0x02, 3},
+ {41, 0x02, 3},
+ {56, 0x03, 3},
+ },
+ /* 228 */
+ {
+ {2, 0x02, 4},
+ {9, 0x02, 4},
+ {23, 0x02, 4},
+ {40, 0x03, 4},
+ {2, 0x02, 5},
+ {9, 0x02, 5},
+ {23, 0x02, 5},
+ {40, 0x03, 5},
+ {2, 0x02, 6},
+ {9, 0x02, 6},
+ {23, 0x02, 6},
+ {40, 0x03, 6},
+ {2, 0x02, 7},
+ {9, 0x02, 7},
+ {23, 0x02, 7},
+ {40, 0x03, 7},
+ },
+ /* 229 */
+ {
+ {3, 0x02, 4},
+ {6, 0x02, 4},
+ {10, 0x02, 4},
+ {15, 0x02, 4},
+ {24, 0x02, 4},
+ {31, 0x02, 4},
+ {41, 0x02, 4},
+ {56, 0x03, 4},
+ {3, 0x02, 5},
+ {6, 0x02, 5},
+ {10, 0x02, 5},
+ {15, 0x02, 5},
+ {24, 0x02, 5},
+ {31, 0x02, 5},
+ {41, 0x02, 5},
+ {56, 0x03, 5},
+ },
+ /* 230 */
+ {
+ {3, 0x02, 6},
+ {6, 0x02, 6},
+ {10, 0x02, 6},
+ {15, 0x02, 6},
+ {24, 0x02, 6},
+ {31, 0x02, 6},
+ {41, 0x02, 6},
+ {56, 0x03, 6},
+ {3, 0x02, 7},
+ {6, 0x02, 7},
+ {10, 0x02, 7},
+ {15, 0x02, 7},
+ {24, 0x02, 7},
+ {31, 0x02, 7},
+ {41, 0x02, 7},
+ {56, 0x03, 7},
+ },
+ /* 231 */
+ {
+ {1, 0x02, 8},
+ {22, 0x03, 8},
+ {1, 0x02, 11},
+ {22, 0x03, 11},
+ {1, 0x02, 12},
+ {22, 0x03, 12},
+ {1, 0x02, 14},
+ {22, 0x03, 14},
+ {1, 0x02, 15},
+ {22, 0x03, 15},
+ {1, 0x02, 16},
+ {22, 0x03, 16},
+ {1, 0x02, 17},
+ {22, 0x03, 17},
+ {1, 0x02, 18},
+ {22, 0x03, 18},
+ },
+ /* 232 */
+ {
+ {2, 0x02, 8},
+ {9, 0x02, 8},
+ {23, 0x02, 8},
+ {40, 0x03, 8},
+ {2, 0x02, 11},
+ {9, 0x02, 11},
+ {23, 0x02, 11},
+ {40, 0x03, 11},
+ {2, 0x02, 12},
+ {9, 0x02, 12},
+ {23, 0x02, 12},
+ {40, 0x03, 12},
+ {2, 0x02, 14},
+ {9, 0x02, 14},
+ {23, 0x02, 14},
+ {40, 0x03, 14},
+ },
+ /* 233 */
+ {
+ {3, 0x02, 8},
+ {6, 0x02, 8},
+ {10, 0x02, 8},
+ {15, 0x02, 8},
+ {24, 0x02, 8},
+ {31, 0x02, 8},
+ {41, 0x02, 8},
+ {56, 0x03, 8},
+ {3, 0x02, 11},
+ {6, 0x02, 11},
+ {10, 0x02, 11},
+ {15, 0x02, 11},
+ {24, 0x02, 11},
+ {31, 0x02, 11},
+ {41, 0x02, 11},
+ {56, 0x03, 11},
+ },
+ /* 234 */
+ {
+ {3, 0x02, 12},
+ {6, 0x02, 12},
+ {10, 0x02, 12},
+ {15, 0x02, 12},
+ {24, 0x02, 12},
+ {31, 0x02, 12},
+ {41, 0x02, 12},
+ {56, 0x03, 12},
+ {3, 0x02, 14},
+ {6, 0x02, 14},
+ {10, 0x02, 14},
+ {15, 0x02, 14},
+ {24, 0x02, 14},
+ {31, 0x02, 14},
+ {41, 0x02, 14},
+ {56, 0x03, 14},
+ },
+ /* 235 */
+ {
+ {2, 0x02, 15},
+ {9, 0x02, 15},
+ {23, 0x02, 15},
+ {40, 0x03, 15},
+ {2, 0x02, 16},
+ {9, 0x02, 16},
+ {23, 0x02, 16},
+ {40, 0x03, 16},
+ {2, 0x02, 17},
+ {9, 0x02, 17},
+ {23, 0x02, 17},
+ {40, 0x03, 17},
+ {2, 0x02, 18},
+ {9, 0x02, 18},
+ {23, 0x02, 18},
+ {40, 0x03, 18},
+ },
+ /* 236 */
+ {
+ {3, 0x02, 15},
+ {6, 0x02, 15},
+ {10, 0x02, 15},
+ {15, 0x02, 15},
+ {24, 0x02, 15},
+ {31, 0x02, 15},
+ {41, 0x02, 15},
+ {56, 0x03, 15},
+ {3, 0x02, 16},
+ {6, 0x02, 16},
+ {10, 0x02, 16},
+ {15, 0x02, 16},
+ {24, 0x02, 16},
+ {31, 0x02, 16},
+ {41, 0x02, 16},
+ {56, 0x03, 16},
+ },
+ /* 237 */
+ {
+ {3, 0x02, 17},
+ {6, 0x02, 17},
+ {10, 0x02, 17},
+ {15, 0x02, 17},
+ {24, 0x02, 17},
+ {31, 0x02, 17},
+ {41, 0x02, 17},
+ {56, 0x03, 17},
+ {3, 0x02, 18},
+ {6, 0x02, 18},
+ {10, 0x02, 18},
+ {15, 0x02, 18},
+ {24, 0x02, 18},
+ {31, 0x02, 18},
+ {41, 0x02, 18},
+ {56, 0x03, 18},
+ },
+ /* 238 */
+ {
+ {0, 0x03, 19},
+ {0, 0x03, 20},
+ {0, 0x03, 21},
+ {0, 0x03, 23},
+ {0, 0x03, 24},
+ {0, 0x03, 25},
+ {0, 0x03, 26},
+ {0, 0x03, 27},
+ {0, 0x03, 28},
+ {0, 0x03, 29},
+ {0, 0x03, 30},
+ {0, 0x03, 31},
+ {0, 0x03, 127},
+ {0, 0x03, 220},
+ {0, 0x03, 249},
+ {253, 0x00, 0},
+ },
+ /* 239 */
+ {
+ {1, 0x02, 19},
+ {22, 0x03, 19},
+ {1, 0x02, 20},
+ {22, 0x03, 20},
+ {1, 0x02, 21},
+ {22, 0x03, 21},
+ {1, 0x02, 23},
+ {22, 0x03, 23},
+ {1, 0x02, 24},
+ {22, 0x03, 24},
+ {1, 0x02, 25},
+ {22, 0x03, 25},
+ {1, 0x02, 26},
+ {22, 0x03, 26},
+ {1, 0x02, 27},
+ {22, 0x03, 27},
+ },
+ /* 240 */
+ {
+ {2, 0x02, 19},
+ {9, 0x02, 19},
+ {23, 0x02, 19},
+ {40, 0x03, 19},
+ {2, 0x02, 20},
+ {9, 0x02, 20},
+ {23, 0x02, 20},
+ {40, 0x03, 20},
+ {2, 0x02, 21},
+ {9, 0x02, 21},
+ {23, 0x02, 21},
+ {40, 0x03, 21},
+ {2, 0x02, 23},
+ {9, 0x02, 23},
+ {23, 0x02, 23},
+ {40, 0x03, 23},
+ },
+ /* 241 */
+ {
+ {3, 0x02, 19},
+ {6, 0x02, 19},
+ {10, 0x02, 19},
+ {15, 0x02, 19},
+ {24, 0x02, 19},
+ {31, 0x02, 19},
+ {41, 0x02, 19},
+ {56, 0x03, 19},
+ {3, 0x02, 20},
+ {6, 0x02, 20},
+ {10, 0x02, 20},
+ {15, 0x02, 20},
+ {24, 0x02, 20},
+ {31, 0x02, 20},
+ {41, 0x02, 20},
+ {56, 0x03, 20},
+ },
+ /* 242 */
+ {
+ {3, 0x02, 21},
+ {6, 0x02, 21},
+ {10, 0x02, 21},
+ {15, 0x02, 21},
+ {24, 0x02, 21},
+ {31, 0x02, 21},
+ {41, 0x02, 21},
+ {56, 0x03, 21},
+ {3, 0x02, 23},
+ {6, 0x02, 23},
+ {10, 0x02, 23},
+ {15, 0x02, 23},
+ {24, 0x02, 23},
+ {31, 0x02, 23},
+ {41, 0x02, 23},
+ {56, 0x03, 23},
+ },
+ /* 243 */
+ {
+ {2, 0x02, 24},
+ {9, 0x02, 24},
+ {23, 0x02, 24},
+ {40, 0x03, 24},
+ {2, 0x02, 25},
+ {9, 0x02, 25},
+ {23, 0x02, 25},
+ {40, 0x03, 25},
+ {2, 0x02, 26},
+ {9, 0x02, 26},
+ {23, 0x02, 26},
+ {40, 0x03, 26},
+ {2, 0x02, 27},
+ {9, 0x02, 27},
+ {23, 0x02, 27},
+ {40, 0x03, 27},
+ },
+ /* 244 */
+ {
+ {3, 0x02, 24},
+ {6, 0x02, 24},
+ {10, 0x02, 24},
+ {15, 0x02, 24},
+ {24, 0x02, 24},
+ {31, 0x02, 24},
+ {41, 0x02, 24},
+ {56, 0x03, 24},
+ {3, 0x02, 25},
+ {6, 0x02, 25},
+ {10, 0x02, 25},
+ {15, 0x02, 25},
+ {24, 0x02, 25},
+ {31, 0x02, 25},
+ {41, 0x02, 25},
+ {56, 0x03, 25},
+ },
+ /* 245 */
+ {
+ {3, 0x02, 26},
+ {6, 0x02, 26},
+ {10, 0x02, 26},
+ {15, 0x02, 26},
+ {24, 0x02, 26},
+ {31, 0x02, 26},
+ {41, 0x02, 26},
+ {56, 0x03, 26},
+ {3, 0x02, 27},
+ {6, 0x02, 27},
+ {10, 0x02, 27},
+ {15, 0x02, 27},
+ {24, 0x02, 27},
+ {31, 0x02, 27},
+ {41, 0x02, 27},
+ {56, 0x03, 27},
+ },
+ /* 246 */
+ {
+ {1, 0x02, 28},
+ {22, 0x03, 28},
+ {1, 0x02, 29},
+ {22, 0x03, 29},
+ {1, 0x02, 30},
+ {22, 0x03, 30},
+ {1, 0x02, 31},
+ {22, 0x03, 31},
+ {1, 0x02, 127},
+ {22, 0x03, 127},
+ {1, 0x02, 220},
+ {22, 0x03, 220},
+ {1, 0x02, 249},
+ {22, 0x03, 249},
+ {254, 0x00, 0},
+ {255, 0x00, 0},
+ },
+ /* 247 */
+ {
+ {2, 0x02, 28},
+ {9, 0x02, 28},
+ {23, 0x02, 28},
+ {40, 0x03, 28},
+ {2, 0x02, 29},
+ {9, 0x02, 29},
+ {23, 0x02, 29},
+ {40, 0x03, 29},
+ {2, 0x02, 30},
+ {9, 0x02, 30},
+ {23, 0x02, 30},
+ {40, 0x03, 30},
+ {2, 0x02, 31},
+ {9, 0x02, 31},
+ {23, 0x02, 31},
+ {40, 0x03, 31},
+ },
+ /* 248 */
+ {
+ {3, 0x02, 28},
+ {6, 0x02, 28},
+ {10, 0x02, 28},
+ {15, 0x02, 28},
+ {24, 0x02, 28},
+ {31, 0x02, 28},
+ {41, 0x02, 28},
+ {56, 0x03, 28},
+ {3, 0x02, 29},
+ {6, 0x02, 29},
+ {10, 0x02, 29},
+ {15, 0x02, 29},
+ {24, 0x02, 29},
+ {31, 0x02, 29},
+ {41, 0x02, 29},
+ {56, 0x03, 29},
+ },
+ /* 249 */
+ {
+ {3, 0x02, 30},
+ {6, 0x02, 30},
+ {10, 0x02, 30},
+ {15, 0x02, 30},
+ {24, 0x02, 30},
+ {31, 0x02, 30},
+ {41, 0x02, 30},
+ {56, 0x03, 30},
+ {3, 0x02, 31},
+ {6, 0x02, 31},
+ {10, 0x02, 31},
+ {15, 0x02, 31},
+ {24, 0x02, 31},
+ {31, 0x02, 31},
+ {41, 0x02, 31},
+ {56, 0x03, 31},
+ },
+ /* 250 */
+ {
+ {2, 0x02, 127},
+ {9, 0x02, 127},
+ {23, 0x02, 127},
+ {40, 0x03, 127},
+ {2, 0x02, 220},
+ {9, 0x02, 220},
+ {23, 0x02, 220},
+ {40, 0x03, 220},
+ {2, 0x02, 249},
+ {9, 0x02, 249},
+ {23, 0x02, 249},
+ {40, 0x03, 249},
+ {0, 0x03, 10},
+ {0, 0x03, 13},
+ {0, 0x03, 22},
+ {0, 0x04, 0},
+ },
+ /* 251 */
+ {
+ {3, 0x02, 127},
+ {6, 0x02, 127},
+ {10, 0x02, 127},
+ {15, 0x02, 127},
+ {24, 0x02, 127},
+ {31, 0x02, 127},
+ {41, 0x02, 127},
+ {56, 0x03, 127},
+ {3, 0x02, 220},
+ {6, 0x02, 220},
+ {10, 0x02, 220},
+ {15, 0x02, 220},
+ {24, 0x02, 220},
+ {31, 0x02, 220},
+ {41, 0x02, 220},
+ {56, 0x03, 220},
+ },
+ /* 252 */
+ {
+ {3, 0x02, 249},
+ {6, 0x02, 249},
+ {10, 0x02, 249},
+ {15, 0x02, 249},
+ {24, 0x02, 249},
+ {31, 0x02, 249},
+ {41, 0x02, 249},
+ {56, 0x03, 249},
+ {1, 0x02, 10},
+ {22, 0x03, 10},
+ {1, 0x02, 13},
+ {22, 0x03, 13},
+ {1, 0x02, 22},
+ {22, 0x03, 22},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ },
+ /* 253 */
+ {
+ {2, 0x02, 10},
+ {9, 0x02, 10},
+ {23, 0x02, 10},
+ {40, 0x03, 10},
+ {2, 0x02, 13},
+ {9, 0x02, 13},
+ {23, 0x02, 13},
+ {40, 0x03, 13},
+ {2, 0x02, 22},
+ {9, 0x02, 22},
+ {23, 0x02, 22},
+ {40, 0x03, 22},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ },
+ /* 254 */
+ {
+ {3, 0x02, 10},
+ {6, 0x02, 10},
+ {10, 0x02, 10},
+ {15, 0x02, 10},
+ {24, 0x02, 10},
+ {31, 0x02, 10},
+ {41, 0x02, 10},
+ {56, 0x03, 10},
+ {3, 0x02, 13},
+ {6, 0x02, 13},
+ {10, 0x02, 13},
+ {15, 0x02, 13},
+ {24, 0x02, 13},
+ {31, 0x02, 13},
+ {41, 0x02, 13},
+ {56, 0x03, 13},
+ },
+ /* 255 */
+ {
+ {3, 0x02, 22},
+ {6, 0x02, 22},
+ {10, 0x02, 22},
+ {15, 0x02, 22},
+ {24, 0x02, 22},
+ {31, 0x02, 22},
+ {41, 0x02, 22},
+ {56, 0x03, 22},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ {0, 0x04, 0},
+ },
+};
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_helper.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_helper.c
new file mode 100644
index 00000000..8d80eb98
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_helper.c
@@ -0,0 +1,532 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_helper.h"
+
+#include
+#include
+
+#include "nghttp2_net.h"
+
+void nghttp2_put_uint16be(uint8_t *buf, uint16_t n) {
+ uint16_t x = nghttp2_htons(n);
+ memcpy(buf, &x, sizeof(uint16_t));
+}
+
+void nghttp2_put_uint32be(uint8_t *buf, uint32_t n) {
+ uint32_t x = nghttp2_htonl(n);
+ memcpy(buf, &x, sizeof(uint32_t));
+}
+
+uint16_t nghttp2_get_uint16(const uint8_t *data) {
+ uint16_t n;
+ memcpy(&n, data, sizeof(uint16_t));
+ return nghttp2_ntohs(n);
+}
+
+uint32_t nghttp2_get_uint32(const uint8_t *data) {
+ uint32_t n;
+ memcpy(&n, data, sizeof(uint32_t));
+ return nghttp2_ntohl(n);
+}
+
+/* Generated by gendowncasetbl.py */
+static const uint8_t DOWNCASE_TBL[] = {
+ 0 /* NUL */, 1 /* SOH */, 2 /* STX */, 3 /* ETX */,
+ 4 /* EOT */, 5 /* ENQ */, 6 /* ACK */, 7 /* BEL */,
+ 8 /* BS */, 9 /* HT */, 10 /* LF */, 11 /* VT */,
+ 12 /* FF */, 13 /* CR */, 14 /* SO */, 15 /* SI */,
+ 16 /* DLE */, 17 /* DC1 */, 18 /* DC2 */, 19 /* DC3 */,
+ 20 /* DC4 */, 21 /* NAK */, 22 /* SYN */, 23 /* ETB */,
+ 24 /* CAN */, 25 /* EM */, 26 /* SUB */, 27 /* ESC */,
+ 28 /* FS */, 29 /* GS */, 30 /* RS */, 31 /* US */,
+ 32 /* SPC */, 33 /* ! */, 34 /* " */, 35 /* # */,
+ 36 /* $ */, 37 /* % */, 38 /* & */, 39 /* ' */,
+ 40 /* ( */, 41 /* ) */, 42 /* * */, 43 /* + */,
+ 44 /* , */, 45 /* - */, 46 /* . */, 47 /* / */,
+ 48 /* 0 */, 49 /* 1 */, 50 /* 2 */, 51 /* 3 */,
+ 52 /* 4 */, 53 /* 5 */, 54 /* 6 */, 55 /* 7 */,
+ 56 /* 8 */, 57 /* 9 */, 58 /* : */, 59 /* ; */,
+ 60 /* < */, 61 /* = */, 62 /* > */, 63 /* ? */,
+ 64 /* @ */, 97 /* A */, 98 /* B */, 99 /* C */,
+ 100 /* D */, 101 /* E */, 102 /* F */, 103 /* G */,
+ 104 /* H */, 105 /* I */, 106 /* J */, 107 /* K */,
+ 108 /* L */, 109 /* M */, 110 /* N */, 111 /* O */,
+ 112 /* P */, 113 /* Q */, 114 /* R */, 115 /* S */,
+ 116 /* T */, 117 /* U */, 118 /* V */, 119 /* W */,
+ 120 /* X */, 121 /* Y */, 122 /* Z */, 91 /* [ */,
+ 92 /* \ */, 93 /* ] */, 94 /* ^ */, 95 /* _ */,
+ 96 /* ` */, 97 /* a */, 98 /* b */, 99 /* c */,
+ 100 /* d */, 101 /* e */, 102 /* f */, 103 /* g */,
+ 104 /* h */, 105 /* i */, 106 /* j */, 107 /* k */,
+ 108 /* l */, 109 /* m */, 110 /* n */, 111 /* o */,
+ 112 /* p */, 113 /* q */, 114 /* r */, 115 /* s */,
+ 116 /* t */, 117 /* u */, 118 /* v */, 119 /* w */,
+ 120 /* x */, 121 /* y */, 122 /* z */, 123 /* { */,
+ 124 /* | */, 125 /* } */, 126 /* ~ */, 127 /* DEL */,
+ 128 /* 0x80 */, 129 /* 0x81 */, 130 /* 0x82 */, 131 /* 0x83 */,
+ 132 /* 0x84 */, 133 /* 0x85 */, 134 /* 0x86 */, 135 /* 0x87 */,
+ 136 /* 0x88 */, 137 /* 0x89 */, 138 /* 0x8a */, 139 /* 0x8b */,
+ 140 /* 0x8c */, 141 /* 0x8d */, 142 /* 0x8e */, 143 /* 0x8f */,
+ 144 /* 0x90 */, 145 /* 0x91 */, 146 /* 0x92 */, 147 /* 0x93 */,
+ 148 /* 0x94 */, 149 /* 0x95 */, 150 /* 0x96 */, 151 /* 0x97 */,
+ 152 /* 0x98 */, 153 /* 0x99 */, 154 /* 0x9a */, 155 /* 0x9b */,
+ 156 /* 0x9c */, 157 /* 0x9d */, 158 /* 0x9e */, 159 /* 0x9f */,
+ 160 /* 0xa0 */, 161 /* 0xa1 */, 162 /* 0xa2 */, 163 /* 0xa3 */,
+ 164 /* 0xa4 */, 165 /* 0xa5 */, 166 /* 0xa6 */, 167 /* 0xa7 */,
+ 168 /* 0xa8 */, 169 /* 0xa9 */, 170 /* 0xaa */, 171 /* 0xab */,
+ 172 /* 0xac */, 173 /* 0xad */, 174 /* 0xae */, 175 /* 0xaf */,
+ 176 /* 0xb0 */, 177 /* 0xb1 */, 178 /* 0xb2 */, 179 /* 0xb3 */,
+ 180 /* 0xb4 */, 181 /* 0xb5 */, 182 /* 0xb6 */, 183 /* 0xb7 */,
+ 184 /* 0xb8 */, 185 /* 0xb9 */, 186 /* 0xba */, 187 /* 0xbb */,
+ 188 /* 0xbc */, 189 /* 0xbd */, 190 /* 0xbe */, 191 /* 0xbf */,
+ 192 /* 0xc0 */, 193 /* 0xc1 */, 194 /* 0xc2 */, 195 /* 0xc3 */,
+ 196 /* 0xc4 */, 197 /* 0xc5 */, 198 /* 0xc6 */, 199 /* 0xc7 */,
+ 200 /* 0xc8 */, 201 /* 0xc9 */, 202 /* 0xca */, 203 /* 0xcb */,
+ 204 /* 0xcc */, 205 /* 0xcd */, 206 /* 0xce */, 207 /* 0xcf */,
+ 208 /* 0xd0 */, 209 /* 0xd1 */, 210 /* 0xd2 */, 211 /* 0xd3 */,
+ 212 /* 0xd4 */, 213 /* 0xd5 */, 214 /* 0xd6 */, 215 /* 0xd7 */,
+ 216 /* 0xd8 */, 217 /* 0xd9 */, 218 /* 0xda */, 219 /* 0xdb */,
+ 220 /* 0xdc */, 221 /* 0xdd */, 222 /* 0xde */, 223 /* 0xdf */,
+ 224 /* 0xe0 */, 225 /* 0xe1 */, 226 /* 0xe2 */, 227 /* 0xe3 */,
+ 228 /* 0xe4 */, 229 /* 0xe5 */, 230 /* 0xe6 */, 231 /* 0xe7 */,
+ 232 /* 0xe8 */, 233 /* 0xe9 */, 234 /* 0xea */, 235 /* 0xeb */,
+ 236 /* 0xec */, 237 /* 0xed */, 238 /* 0xee */, 239 /* 0xef */,
+ 240 /* 0xf0 */, 241 /* 0xf1 */, 242 /* 0xf2 */, 243 /* 0xf3 */,
+ 244 /* 0xf4 */, 245 /* 0xf5 */, 246 /* 0xf6 */, 247 /* 0xf7 */,
+ 248 /* 0xf8 */, 249 /* 0xf9 */, 250 /* 0xfa */, 251 /* 0xfb */,
+ 252 /* 0xfc */, 253 /* 0xfd */, 254 /* 0xfe */, 255 /* 0xff */,
+};
+
+void nghttp2_downcase(uint8_t *s, size_t len) {
+ size_t i;
+ for (i = 0; i < len; ++i) {
+ s[i] = DOWNCASE_TBL[s[i]];
+ }
+}
+
+/*
+ * local_window_size
+ * ^ *
+ * | * recv_window_size
+ * | * * ^
+ * | * * |
+ * 0+++++++++
+ * | * * \
+ * | * * | This rage is hidden in flow control. But it must be
+ * v * * / kept in order to restore it when window size is enlarged.
+ * recv_reduction
+ * (+ for negative direction)
+ *
+ * recv_window_size could be negative if we decrease
+ * local_window_size more than recv_window_size:
+ *
+ * local_window_size
+ * ^ *
+ * | *
+ * | *
+ * 0++++++++
+ * | * ^ recv_window_size (negative)
+ * | * |
+ * v * *
+ * recv_reduction
+ */
+int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
+ int32_t *recv_window_size_ptr,
+ int32_t *recv_reduction_ptr,
+ int32_t *delta_ptr) {
+ if (*delta_ptr > 0) {
+ int32_t recv_reduction_delta;
+ int32_t delta;
+ int32_t new_recv_window_size =
+ nghttp2_max(0, *recv_window_size_ptr) - *delta_ptr;
+
+ if (new_recv_window_size >= 0) {
+ *recv_window_size_ptr = new_recv_window_size;
+ return 0;
+ }
+
+ delta = -new_recv_window_size;
+
+ /* The delta size is strictly more than received bytes. Increase
+ local_window_size by that difference |delta|. */
+ if (*local_window_size_ptr > NGHTTP2_MAX_WINDOW_SIZE - delta) {
+ return NGHTTP2_ERR_FLOW_CONTROL;
+ }
+ *local_window_size_ptr += delta;
+ /* If there is recv_reduction due to earlier window_size
+ reduction, we have to adjust it too. */
+ recv_reduction_delta = nghttp2_min(*recv_reduction_ptr, delta);
+ *recv_reduction_ptr -= recv_reduction_delta;
+ if (*recv_window_size_ptr < 0) {
+ *recv_window_size_ptr += recv_reduction_delta;
+ } else {
+ /* If *recv_window_size_ptr > 0, then those bytes are going to
+ be returned to the remote peer (by WINDOW_UPDATE with the
+ adjusted *delta_ptr), so it is effectively 0 now. We set to
+ *recv_reduction_delta, because caller does not take into
+ account it in *delta_ptr. */
+ *recv_window_size_ptr = recv_reduction_delta;
+ }
+ /* recv_reduction_delta must be paid from *delta_ptr, since it was
+ added in window size reduction (see below). */
+ *delta_ptr -= recv_reduction_delta;
+
+ return 0;
+ }
+
+ if (*local_window_size_ptr + *delta_ptr < 0 ||
+ *recv_window_size_ptr < INT32_MIN - *delta_ptr ||
+ *recv_reduction_ptr > INT32_MAX + *delta_ptr) {
+ return NGHTTP2_ERR_FLOW_CONTROL;
+ }
+ /* Decreasing local window size. Note that we achieve this without
+ noticing to the remote peer. To do this, we cut
+ recv_window_size by -delta. This means that we don't send
+ WINDOW_UPDATE for -delta bytes. */
+ *local_window_size_ptr += *delta_ptr;
+ *recv_window_size_ptr += *delta_ptr;
+ *recv_reduction_ptr -= *delta_ptr;
+ *delta_ptr = 0;
+
+ return 0;
+}
+
+int nghttp2_increase_local_window_size(int32_t *local_window_size_ptr,
+ int32_t *recv_window_size_ptr,
+ int32_t *recv_reduction_ptr,
+ int32_t *delta_ptr) {
+ int32_t recv_reduction_delta;
+ int32_t delta;
+
+ delta = *delta_ptr;
+
+ assert(delta >= 0);
+
+ /* The delta size is strictly more than received bytes. Increase
+ local_window_size by that difference |delta|. */
+ if (*local_window_size_ptr > NGHTTP2_MAX_WINDOW_SIZE - delta) {
+ return NGHTTP2_ERR_FLOW_CONTROL;
+ }
+
+ *local_window_size_ptr += delta;
+ /* If there is recv_reduction due to earlier window_size
+ reduction, we have to adjust it too. */
+ recv_reduction_delta = nghttp2_min(*recv_reduction_ptr, delta);
+ *recv_reduction_ptr -= recv_reduction_delta;
+
+ *recv_window_size_ptr += recv_reduction_delta;
+
+ /* recv_reduction_delta must be paid from *delta_ptr, since it was
+ added in window size reduction (see below). */
+ *delta_ptr -= recv_reduction_delta;
+
+ return 0;
+}
+
+int nghttp2_should_send_window_update(int32_t local_window_size,
+ int32_t recv_window_size) {
+ return recv_window_size > 0 && recv_window_size >= local_window_size / 2;
+}
+
+const char *nghttp2_strerror(int error_code) {
+ switch (error_code) {
+ case 0:
+ return "Success";
+ case NGHTTP2_ERR_INVALID_ARGUMENT:
+ return "Invalid argument";
+ case NGHTTP2_ERR_BUFFER_ERROR:
+ return "Out of buffer space";
+ case NGHTTP2_ERR_UNSUPPORTED_VERSION:
+ return "Unsupported SPDY version";
+ case NGHTTP2_ERR_WOULDBLOCK:
+ return "Operation would block";
+ case NGHTTP2_ERR_PROTO:
+ return "Protocol error";
+ case NGHTTP2_ERR_INVALID_FRAME:
+ return "Invalid frame octets";
+ case NGHTTP2_ERR_EOF:
+ return "EOF";
+ case NGHTTP2_ERR_DEFERRED:
+ return "Data transfer deferred";
+ case NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE:
+ return "No more Stream ID available";
+ case NGHTTP2_ERR_STREAM_CLOSED:
+ return "Stream was already closed or invalid";
+ case NGHTTP2_ERR_STREAM_CLOSING:
+ return "Stream is closing";
+ case NGHTTP2_ERR_STREAM_SHUT_WR:
+ return "The transmission is not allowed for this stream";
+ case NGHTTP2_ERR_INVALID_STREAM_ID:
+ return "Stream ID is invalid";
+ case NGHTTP2_ERR_INVALID_STREAM_STATE:
+ return "Invalid stream state";
+ case NGHTTP2_ERR_DEFERRED_DATA_EXIST:
+ return "Another DATA frame has already been deferred";
+ case NGHTTP2_ERR_START_STREAM_NOT_ALLOWED:
+ return "request HEADERS is not allowed";
+ case NGHTTP2_ERR_GOAWAY_ALREADY_SENT:
+ return "GOAWAY has already been sent";
+ case NGHTTP2_ERR_INVALID_HEADER_BLOCK:
+ return "Invalid header block";
+ case NGHTTP2_ERR_INVALID_STATE:
+ return "Invalid state";
+ case NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE:
+ return "The user callback function failed due to the temporal error";
+ case NGHTTP2_ERR_FRAME_SIZE_ERROR:
+ return "The length of the frame is invalid";
+ case NGHTTP2_ERR_HEADER_COMP:
+ return "Header compression/decompression error";
+ case NGHTTP2_ERR_FLOW_CONTROL:
+ return "Flow control error";
+ case NGHTTP2_ERR_INSUFF_BUFSIZE:
+ return "Insufficient buffer size given to function";
+ case NGHTTP2_ERR_PAUSE:
+ return "Callback was paused by the application";
+ case NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS:
+ return "Too many inflight SETTINGS";
+ case NGHTTP2_ERR_PUSH_DISABLED:
+ return "Server push is disabled by peer";
+ case NGHTTP2_ERR_DATA_EXIST:
+ return "DATA or HEADERS frame has already been submitted for the stream";
+ case NGHTTP2_ERR_SESSION_CLOSING:
+ return "The current session is closing";
+ case NGHTTP2_ERR_HTTP_HEADER:
+ return "Invalid HTTP header field was received";
+ case NGHTTP2_ERR_HTTP_MESSAGING:
+ return "Violation in HTTP messaging rule";
+ case NGHTTP2_ERR_REFUSED_STREAM:
+ return "Stream was refused";
+ case NGHTTP2_ERR_INTERNAL:
+ return "Internal error";
+ case NGHTTP2_ERR_CANCEL:
+ return "Cancel";
+ case NGHTTP2_ERR_SETTINGS_EXPECTED:
+ return "When a local endpoint expects to receive SETTINGS frame, it "
+ "receives an other type of frame";
+ case NGHTTP2_ERR_NOMEM:
+ return "Out of memory";
+ case NGHTTP2_ERR_CALLBACK_FAILURE:
+ return "The user callback function failed";
+ case NGHTTP2_ERR_BAD_CLIENT_MAGIC:
+ return "Received bad client magic byte string";
+ case NGHTTP2_ERR_FLOODED:
+ return "Flooding was detected in this HTTP/2 session, and it must be "
+ "closed";
+ default:
+ return "Unknown error code";
+ }
+}
+
+/* Generated by gennmchartbl.py */
+static int VALID_HD_NAME_CHARS[] = {
+ 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
+ 0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
+ 0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
+ 0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
+ 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
+ 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
+ 0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
+ 0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
+ 0 /* SPC */, 1 /* ! */, 0 /* " */, 1 /* # */,
+ 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
+ 0 /* ( */, 0 /* ) */, 1 /* * */, 1 /* + */,
+ 0 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
+ 1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
+ 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
+ 1 /* 8 */, 1 /* 9 */, 0 /* : */, 0 /* ; */,
+ 0 /* < */, 0 /* = */, 0 /* > */, 0 /* ? */,
+ 0 /* @ */, 0 /* A */, 0 /* B */, 0 /* C */,
+ 0 /* D */, 0 /* E */, 0 /* F */, 0 /* G */,
+ 0 /* H */, 0 /* I */, 0 /* J */, 0 /* K */,
+ 0 /* L */, 0 /* M */, 0 /* N */, 0 /* O */,
+ 0 /* P */, 0 /* Q */, 0 /* R */, 0 /* S */,
+ 0 /* T */, 0 /* U */, 0 /* V */, 0 /* W */,
+ 0 /* X */, 0 /* Y */, 0 /* Z */, 0 /* [ */,
+ 0 /* \ */, 0 /* ] */, 1 /* ^ */, 1 /* _ */,
+ 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
+ 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
+ 1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
+ 1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
+ 1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
+ 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
+ 1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
+ 1 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
+ 0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
+ 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
+ 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
+ 0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
+ 0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
+ 0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
+ 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
+ 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
+ 0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
+ 0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
+ 0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
+ 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
+ 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
+ 0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
+ 0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
+ 0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
+ 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
+ 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
+ 0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
+ 0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
+ 0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
+ 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
+ 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
+ 0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
+ 0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
+ 0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
+ 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
+ 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
+ 0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
+ 0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
+ 0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
+ 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
+};
+
+int nghttp2_check_header_name(const uint8_t *name, size_t len) {
+ const uint8_t *last;
+ if (len == 0) {
+ return 0;
+ }
+ if (*name == ':') {
+ if (len == 1) {
+ return 0;
+ }
+ ++name;
+ --len;
+ }
+ for (last = name + len; name != last; ++name) {
+ if (!VALID_HD_NAME_CHARS[*name]) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* Generated by genvchartbl.py */
+static int VALID_HD_VALUE_CHARS[] = {
+ 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
+ 0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
+ 0 /* BS */, 1 /* HT */, 0 /* LF */, 0 /* VT */,
+ 0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
+ 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
+ 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
+ 0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
+ 0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
+ 1 /* SPC */, 1 /* ! */, 1 /* " */, 1 /* # */,
+ 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
+ 1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
+ 1 /* , */, 1 /* - */, 1 /* . */, 1 /* / */,
+ 1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
+ 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
+ 1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
+ 1 /* < */, 1 /* = */, 1 /* > */, 1 /* ? */,
+ 1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
+ 1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
+ 1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
+ 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
+ 1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
+ 1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
+ 1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
+ 1 /* \ */, 1 /* ] */, 1 /* ^ */, 1 /* _ */,
+ 1 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
+ 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
+ 1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
+ 1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
+ 1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
+ 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
+ 1 /* x */, 1 /* y */, 1 /* z */, 1 /* { */,
+ 1 /* | */, 1 /* } */, 1 /* ~ */, 0 /* DEL */,
+ 1 /* 0x80 */, 1 /* 0x81 */, 1 /* 0x82 */, 1 /* 0x83 */,
+ 1 /* 0x84 */, 1 /* 0x85 */, 1 /* 0x86 */, 1 /* 0x87 */,
+ 1 /* 0x88 */, 1 /* 0x89 */, 1 /* 0x8a */, 1 /* 0x8b */,
+ 1 /* 0x8c */, 1 /* 0x8d */, 1 /* 0x8e */, 1 /* 0x8f */,
+ 1 /* 0x90 */, 1 /* 0x91 */, 1 /* 0x92 */, 1 /* 0x93 */,
+ 1 /* 0x94 */, 1 /* 0x95 */, 1 /* 0x96 */, 1 /* 0x97 */,
+ 1 /* 0x98 */, 1 /* 0x99 */, 1 /* 0x9a */, 1 /* 0x9b */,
+ 1 /* 0x9c */, 1 /* 0x9d */, 1 /* 0x9e */, 1 /* 0x9f */,
+ 1 /* 0xa0 */, 1 /* 0xa1 */, 1 /* 0xa2 */, 1 /* 0xa3 */,
+ 1 /* 0xa4 */, 1 /* 0xa5 */, 1 /* 0xa6 */, 1 /* 0xa7 */,
+ 1 /* 0xa8 */, 1 /* 0xa9 */, 1 /* 0xaa */, 1 /* 0xab */,
+ 1 /* 0xac */, 1 /* 0xad */, 1 /* 0xae */, 1 /* 0xaf */,
+ 1 /* 0xb0 */, 1 /* 0xb1 */, 1 /* 0xb2 */, 1 /* 0xb3 */,
+ 1 /* 0xb4 */, 1 /* 0xb5 */, 1 /* 0xb6 */, 1 /* 0xb7 */,
+ 1 /* 0xb8 */, 1 /* 0xb9 */, 1 /* 0xba */, 1 /* 0xbb */,
+ 1 /* 0xbc */, 1 /* 0xbd */, 1 /* 0xbe */, 1 /* 0xbf */,
+ 1 /* 0xc0 */, 1 /* 0xc1 */, 1 /* 0xc2 */, 1 /* 0xc3 */,
+ 1 /* 0xc4 */, 1 /* 0xc5 */, 1 /* 0xc6 */, 1 /* 0xc7 */,
+ 1 /* 0xc8 */, 1 /* 0xc9 */, 1 /* 0xca */, 1 /* 0xcb */,
+ 1 /* 0xcc */, 1 /* 0xcd */, 1 /* 0xce */, 1 /* 0xcf */,
+ 1 /* 0xd0 */, 1 /* 0xd1 */, 1 /* 0xd2 */, 1 /* 0xd3 */,
+ 1 /* 0xd4 */, 1 /* 0xd5 */, 1 /* 0xd6 */, 1 /* 0xd7 */,
+ 1 /* 0xd8 */, 1 /* 0xd9 */, 1 /* 0xda */, 1 /* 0xdb */,
+ 1 /* 0xdc */, 1 /* 0xdd */, 1 /* 0xde */, 1 /* 0xdf */,
+ 1 /* 0xe0 */, 1 /* 0xe1 */, 1 /* 0xe2 */, 1 /* 0xe3 */,
+ 1 /* 0xe4 */, 1 /* 0xe5 */, 1 /* 0xe6 */, 1 /* 0xe7 */,
+ 1 /* 0xe8 */, 1 /* 0xe9 */, 1 /* 0xea */, 1 /* 0xeb */,
+ 1 /* 0xec */, 1 /* 0xed */, 1 /* 0xee */, 1 /* 0xef */,
+ 1 /* 0xf0 */, 1 /* 0xf1 */, 1 /* 0xf2 */, 1 /* 0xf3 */,
+ 1 /* 0xf4 */, 1 /* 0xf5 */, 1 /* 0xf6 */, 1 /* 0xf7 */,
+ 1 /* 0xf8 */, 1 /* 0xf9 */, 1 /* 0xfa */, 1 /* 0xfb */,
+ 1 /* 0xfc */, 1 /* 0xfd */, 1 /* 0xfe */, 1 /* 0xff */
+};
+
+int nghttp2_check_header_value(const uint8_t *value, size_t len) {
+ const uint8_t *last;
+ for (last = value + len; value != last; ++value) {
+ if (!VALID_HD_VALUE_CHARS[*value]) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+uint8_t *nghttp2_cpymem(uint8_t *dest, const void *src, size_t len) {
+ if (len == 0) {
+ return dest;
+ }
+
+ memcpy(dest, src, len);
+
+ return dest + len;
+}
+
+const char *nghttp2_http2_strerror(uint32_t error_code) {
+ switch (error_code) {
+ case NGHTTP2_NO_ERROR:
+ return "NO_ERROR";
+ case NGHTTP2_PROTOCOL_ERROR:
+ return "PROTOCOL_ERROR";
+ case NGHTTP2_INTERNAL_ERROR:
+ return "INTERNAL_ERROR";
+ case NGHTTP2_FLOW_CONTROL_ERROR:
+ return "FLOW_CONTROL_ERROR";
+ case NGHTTP2_SETTINGS_TIMEOUT:
+ return "SETTINGS_TIMEOUT";
+ case NGHTTP2_STREAM_CLOSED:
+ return "STREAM_CLOSED";
+ case NGHTTP2_FRAME_SIZE_ERROR:
+ return "FRAME_SIZE_ERROR";
+ case NGHTTP2_REFUSED_STREAM:
+ return "REFUSED_STREAM";
+ case NGHTTP2_CANCEL:
+ return "CANCEL";
+ case NGHTTP2_COMPRESSION_ERROR:
+ return "COMPRESSION_ERROR";
+ case NGHTTP2_CONNECT_ERROR:
+ return "CONNECT_ERROR";
+ case NGHTTP2_ENHANCE_YOUR_CALM:
+ return "ENHANCE_YOUR_CALM";
+ case NGHTTP2_INADEQUATE_SECURITY:
+ return "INADEQUATE_SECURITY";
+ case NGHTTP2_HTTP_1_1_REQUIRED:
+ return "HTTP_1_1_REQUIRED";
+ default:
+ return "unknown";
+ }
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_helper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_helper.h
new file mode 100644
index 00000000..be85fd2f
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_helper.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_HELPER_H
+#define NGHTTP2_HELPER_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include
+#include
+
+#include "nghttp2.h"
+#include "nghttp2_mem.h"
+
+#define nghttp2_min(A, B) ((A) < (B) ? (A) : (B))
+#define nghttp2_max(A, B) ((A) > (B) ? (A) : (B))
+
+#define lstreq(A, B, N) ((sizeof((A)) - 1) == (N) && memcmp((A), (B), (N)) == 0)
+
+#define nghttp2_struct_of(ptr, type, member) \
+ ((type *)(void *)((char *)(ptr)-offsetof(type, member)))
+
+/*
+ * Copies 2 byte unsigned integer |n| in host byte order to |buf| in
+ * network byte order.
+ */
+void nghttp2_put_uint16be(uint8_t *buf, uint16_t n);
+
+/*
+ * Copies 4 byte unsigned integer |n| in host byte order to |buf| in
+ * network byte order.
+ */
+void nghttp2_put_uint32be(uint8_t *buf, uint32_t n);
+
+/*
+ * Retrieves 2 byte unsigned integer stored in |data| in network byte
+ * order and returns it in host byte order.
+ */
+uint16_t nghttp2_get_uint16(const uint8_t *data);
+
+/*
+ * Retrieves 4 byte unsigned integer stored in |data| in network byte
+ * order and returns it in host byte order.
+ */
+uint32_t nghttp2_get_uint32(const uint8_t *data);
+
+void nghttp2_downcase(uint8_t *s, size_t len);
+
+/*
+ * Adjusts |*local_window_size_ptr|, |*recv_window_size_ptr|,
+ * |*recv_reduction_ptr| with |*delta_ptr| which is the
+ * WINDOW_UPDATE's window_size_increment sent from local side. If
+ * |delta| is strictly larger than |*recv_window_size_ptr|,
+ * |*local_window_size_ptr| is increased by delta -
+ * *recv_window_size_ptr. If |delta| is negative,
+ * |*local_window_size_ptr| is decreased by delta.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_FLOW_CONTROL
+ * local_window_size overflow or gets negative.
+ */
+int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr,
+ int32_t *recv_window_size_ptr,
+ int32_t *recv_reduction_ptr,
+ int32_t *delta_ptr);
+
+/*
+ * This function works like nghttp2_adjust_local_window_size(). The
+ * difference is that this function assumes *delta_ptr >= 0, and
+ * *recv_window_size_ptr is not decreased by *delta_ptr.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_FLOW_CONTROL
+ * local_window_size overflow or gets negative.
+ */
+int nghttp2_increase_local_window_size(int32_t *local_window_size_ptr,
+ int32_t *recv_window_size_ptr,
+ int32_t *recv_reduction_ptr,
+ int32_t *delta_ptr);
+
+/*
+ * Returns non-zero if the function decided that WINDOW_UPDATE should
+ * be sent.
+ */
+int nghttp2_should_send_window_update(int32_t local_window_size,
+ int32_t recv_window_size);
+
+/*
+ * Copies the buffer |src| of length |len| to the destination pointed
+ * by the |dest|, assuming that the |dest| is at lest |len| bytes long
+ * . Returns dest + len.
+ */
+uint8_t *nghttp2_cpymem(uint8_t *dest, const void *src, size_t len);
+
+#endif /* NGHTTP2_HELPER_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_http.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_http.c
new file mode 100644
index 00000000..49caa100
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_http.c
@@ -0,0 +1,577 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_http.h"
+
+#include
+#include
+#include
+
+#include "nghttp2_hd.h"
+#include "nghttp2_helper.h"
+
+static uint8_t downcase(uint8_t c) {
+ return 'A' <= c && c <= 'Z' ? (uint8_t)(c - 'A' + 'a') : c;
+}
+
+static int memieq(const void *a, const void *b, size_t n) {
+ size_t i;
+ const uint8_t *aa = a, *bb = b;
+
+ for (i = 0; i < n; ++i) {
+ if (downcase(aa[i]) != downcase(bb[i])) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+#define lstrieq(A, B, N) ((sizeof((A)) - 1) == (N) && memieq((A), (B), (N)))
+
+static int64_t parse_uint(const uint8_t *s, size_t len) {
+ int64_t n = 0;
+ size_t i;
+ if (len == 0) {
+ return -1;
+ }
+ for (i = 0; i < len; ++i) {
+ if ('0' <= s[i] && s[i] <= '9') {
+ if (n > INT64_MAX / 10) {
+ return -1;
+ }
+ n *= 10;
+ if (n > INT64_MAX - (s[i] - '0')) {
+ return -1;
+ }
+ n += s[i] - '0';
+ continue;
+ }
+ return -1;
+ }
+ return n;
+}
+
+static int lws(const uint8_t *s, size_t n) {
+ size_t i;
+ for (i = 0; i < n; ++i) {
+ if (s[i] != ' ' && s[i] != '\t') {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int check_pseudo_header(nghttp2_stream *stream, const nghttp2_hd_nv *nv,
+ int flag) {
+ if (stream->http_flags & flag) {
+ return 0;
+ }
+ if (lws(nv->value->base, nv->value->len)) {
+ return 0;
+ }
+ stream->http_flags = (uint16_t)(stream->http_flags | flag);
+ return 1;
+}
+
+static int expect_response_body(nghttp2_stream *stream) {
+ return (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_HEAD) == 0 &&
+ stream->status_code / 100 != 1 && stream->status_code != 304 &&
+ stream->status_code != 204;
+}
+
+/* For "http" or "https" URIs, OPTIONS request may have "*" in :path
+ header field to represent system-wide OPTIONS request. Otherwise,
+ :path header field value must start with "/". This function must
+ be called after ":method" header field was received. This function
+ returns nonzero if path is valid.*/
+static int check_path(nghttp2_stream *stream) {
+ return (stream->http_flags & NGHTTP2_HTTP_FLAG_SCHEME_HTTP) == 0 ||
+ ((stream->http_flags & NGHTTP2_HTTP_FLAG_PATH_REGULAR) ||
+ ((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_OPTIONS) &&
+ (stream->http_flags & NGHTTP2_HTTP_FLAG_PATH_ASTERISK)));
+}
+
+static int http_request_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
+ int trailer) {
+ if (nv->name->base[0] == ':') {
+ if (trailer ||
+ (stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ }
+
+ switch (nv->token) {
+ case NGHTTP2_TOKEN__AUTHORITY:
+ if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__AUTHORITY)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ break;
+ case NGHTTP2_TOKEN__METHOD:
+ if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__METHOD)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ switch (nv->value->len) {
+ case 4:
+ if (lstreq("HEAD", nv->value->base, nv->value->len)) {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD;
+ }
+ break;
+ case 7:
+ switch (nv->value->base[6]) {
+ case 'T':
+ if (lstreq("CONNECT", nv->value->base, nv->value->len)) {
+ if (stream->stream_id % 2 == 0) {
+ /* we won't allow CONNECT for push */
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
+ if (stream->http_flags &
+ (NGHTTP2_HTTP_FLAG__PATH | NGHTTP2_HTTP_FLAG__SCHEME)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ }
+ break;
+ case 'S':
+ if (lstreq("OPTIONS", nv->value->base, nv->value->len)) {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_OPTIONS;
+ }
+ break;
+ }
+ break;
+ }
+ break;
+ case NGHTTP2_TOKEN__PATH:
+ if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__PATH)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ if (nv->value->base[0] == '/') {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_PATH_REGULAR;
+ } else if (nv->value->len == 1 && nv->value->base[0] == '*') {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_PATH_ASTERISK;
+ }
+ break;
+ case NGHTTP2_TOKEN__SCHEME:
+ if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__SCHEME)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ if ((nv->value->len == 4 && memieq("http", nv->value->base, 4)) ||
+ (nv->value->len == 5 && memieq("https", nv->value->base, 5))) {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_SCHEME_HTTP;
+ }
+ break;
+ case NGHTTP2_TOKEN_HOST:
+ if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG_HOST)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ break;
+ case NGHTTP2_TOKEN_CONTENT_LENGTH: {
+ if (stream->content_length != -1) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ stream->content_length = parse_uint(nv->value->base, nv->value->len);
+ if (stream->content_length == -1) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ break;
+ }
+ /* disallowed header fields */
+ case NGHTTP2_TOKEN_CONNECTION:
+ case NGHTTP2_TOKEN_KEEP_ALIVE:
+ case NGHTTP2_TOKEN_PROXY_CONNECTION:
+ case NGHTTP2_TOKEN_TRANSFER_ENCODING:
+ case NGHTTP2_TOKEN_UPGRADE:
+ return NGHTTP2_ERR_HTTP_HEADER;
+ case NGHTTP2_TOKEN_TE:
+ if (!lstrieq("trailers", nv->value->base, nv->value->len)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ break;
+ default:
+ if (nv->name->base[0] == ':') {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ }
+
+ if (nv->name->base[0] != ':') {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
+ }
+
+ return 0;
+}
+
+static int http_response_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
+ int trailer) {
+ if (nv->name->base[0] == ':') {
+ if (trailer ||
+ (stream->http_flags & NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ }
+
+ switch (nv->token) {
+ case NGHTTP2_TOKEN__STATUS: {
+ if (!check_pseudo_header(stream, nv, NGHTTP2_HTTP_FLAG__STATUS)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ if (nv->value->len != 3) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ stream->status_code = (int16_t)parse_uint(nv->value->base, nv->value->len);
+ if (stream->status_code == -1 || stream->status_code == 101) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ break;
+ }
+ case NGHTTP2_TOKEN_CONTENT_LENGTH: {
+ if (stream->status_code == 204) {
+ /* content-length header field in 204 response is prohibited by
+ RFC 7230. But some widely used servers send content-length:
+ 0. Until they get fixed, we ignore it. */
+ if (stream->content_length != -1) {
+ /* Found multiple content-length field */
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ if (!lstrieq("0", nv->value->base, nv->value->len)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ stream->content_length = 0;
+ return NGHTTP2_ERR_REMOVE_HTTP_HEADER;
+ }
+ if (stream->status_code / 100 == 1 ||
+ (stream->status_code == 200 &&
+ (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT))) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ if (stream->content_length != -1) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ stream->content_length = parse_uint(nv->value->base, nv->value->len);
+ if (stream->content_length == -1) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ break;
+ }
+ /* disallowed header fields */
+ case NGHTTP2_TOKEN_CONNECTION:
+ case NGHTTP2_TOKEN_KEEP_ALIVE:
+ case NGHTTP2_TOKEN_PROXY_CONNECTION:
+ case NGHTTP2_TOKEN_TRANSFER_ENCODING:
+ case NGHTTP2_TOKEN_UPGRADE:
+ return NGHTTP2_ERR_HTTP_HEADER;
+ case NGHTTP2_TOKEN_TE:
+ if (!lstrieq("trailers", nv->value->base, nv->value->len)) {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ break;
+ default:
+ if (nv->name->base[0] == ':') {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ }
+
+ if (nv->name->base[0] != ':') {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
+ }
+
+ return 0;
+}
+
+/* Generated by genauthroitychartbl.py */
+static char VALID_AUTHORITY_CHARS[] = {
+ 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */,
+ 0 /* EOT */, 0 /* ENQ */, 0 /* ACK */, 0 /* BEL */,
+ 0 /* BS */, 0 /* HT */, 0 /* LF */, 0 /* VT */,
+ 0 /* FF */, 0 /* CR */, 0 /* SO */, 0 /* SI */,
+ 0 /* DLE */, 0 /* DC1 */, 0 /* DC2 */, 0 /* DC3 */,
+ 0 /* DC4 */, 0 /* NAK */, 0 /* SYN */, 0 /* ETB */,
+ 0 /* CAN */, 0 /* EM */, 0 /* SUB */, 0 /* ESC */,
+ 0 /* FS */, 0 /* GS */, 0 /* RS */, 0 /* US */,
+ 0 /* SPC */, 1 /* ! */, 0 /* " */, 0 /* # */,
+ 1 /* $ */, 1 /* % */, 1 /* & */, 1 /* ' */,
+ 1 /* ( */, 1 /* ) */, 1 /* * */, 1 /* + */,
+ 1 /* , */, 1 /* - */, 1 /* . */, 0 /* / */,
+ 1 /* 0 */, 1 /* 1 */, 1 /* 2 */, 1 /* 3 */,
+ 1 /* 4 */, 1 /* 5 */, 1 /* 6 */, 1 /* 7 */,
+ 1 /* 8 */, 1 /* 9 */, 1 /* : */, 1 /* ; */,
+ 0 /* < */, 1 /* = */, 0 /* > */, 0 /* ? */,
+ 1 /* @ */, 1 /* A */, 1 /* B */, 1 /* C */,
+ 1 /* D */, 1 /* E */, 1 /* F */, 1 /* G */,
+ 1 /* H */, 1 /* I */, 1 /* J */, 1 /* K */,
+ 1 /* L */, 1 /* M */, 1 /* N */, 1 /* O */,
+ 1 /* P */, 1 /* Q */, 1 /* R */, 1 /* S */,
+ 1 /* T */, 1 /* U */, 1 /* V */, 1 /* W */,
+ 1 /* X */, 1 /* Y */, 1 /* Z */, 1 /* [ */,
+ 0 /* \ */, 1 /* ] */, 0 /* ^ */, 1 /* _ */,
+ 0 /* ` */, 1 /* a */, 1 /* b */, 1 /* c */,
+ 1 /* d */, 1 /* e */, 1 /* f */, 1 /* g */,
+ 1 /* h */, 1 /* i */, 1 /* j */, 1 /* k */,
+ 1 /* l */, 1 /* m */, 1 /* n */, 1 /* o */,
+ 1 /* p */, 1 /* q */, 1 /* r */, 1 /* s */,
+ 1 /* t */, 1 /* u */, 1 /* v */, 1 /* w */,
+ 1 /* x */, 1 /* y */, 1 /* z */, 0 /* { */,
+ 0 /* | */, 0 /* } */, 1 /* ~ */, 0 /* DEL */,
+ 0 /* 0x80 */, 0 /* 0x81 */, 0 /* 0x82 */, 0 /* 0x83 */,
+ 0 /* 0x84 */, 0 /* 0x85 */, 0 /* 0x86 */, 0 /* 0x87 */,
+ 0 /* 0x88 */, 0 /* 0x89 */, 0 /* 0x8a */, 0 /* 0x8b */,
+ 0 /* 0x8c */, 0 /* 0x8d */, 0 /* 0x8e */, 0 /* 0x8f */,
+ 0 /* 0x90 */, 0 /* 0x91 */, 0 /* 0x92 */, 0 /* 0x93 */,
+ 0 /* 0x94 */, 0 /* 0x95 */, 0 /* 0x96 */, 0 /* 0x97 */,
+ 0 /* 0x98 */, 0 /* 0x99 */, 0 /* 0x9a */, 0 /* 0x9b */,
+ 0 /* 0x9c */, 0 /* 0x9d */, 0 /* 0x9e */, 0 /* 0x9f */,
+ 0 /* 0xa0 */, 0 /* 0xa1 */, 0 /* 0xa2 */, 0 /* 0xa3 */,
+ 0 /* 0xa4 */, 0 /* 0xa5 */, 0 /* 0xa6 */, 0 /* 0xa7 */,
+ 0 /* 0xa8 */, 0 /* 0xa9 */, 0 /* 0xaa */, 0 /* 0xab */,
+ 0 /* 0xac */, 0 /* 0xad */, 0 /* 0xae */, 0 /* 0xaf */,
+ 0 /* 0xb0 */, 0 /* 0xb1 */, 0 /* 0xb2 */, 0 /* 0xb3 */,
+ 0 /* 0xb4 */, 0 /* 0xb5 */, 0 /* 0xb6 */, 0 /* 0xb7 */,
+ 0 /* 0xb8 */, 0 /* 0xb9 */, 0 /* 0xba */, 0 /* 0xbb */,
+ 0 /* 0xbc */, 0 /* 0xbd */, 0 /* 0xbe */, 0 /* 0xbf */,
+ 0 /* 0xc0 */, 0 /* 0xc1 */, 0 /* 0xc2 */, 0 /* 0xc3 */,
+ 0 /* 0xc4 */, 0 /* 0xc5 */, 0 /* 0xc6 */, 0 /* 0xc7 */,
+ 0 /* 0xc8 */, 0 /* 0xc9 */, 0 /* 0xca */, 0 /* 0xcb */,
+ 0 /* 0xcc */, 0 /* 0xcd */, 0 /* 0xce */, 0 /* 0xcf */,
+ 0 /* 0xd0 */, 0 /* 0xd1 */, 0 /* 0xd2 */, 0 /* 0xd3 */,
+ 0 /* 0xd4 */, 0 /* 0xd5 */, 0 /* 0xd6 */, 0 /* 0xd7 */,
+ 0 /* 0xd8 */, 0 /* 0xd9 */, 0 /* 0xda */, 0 /* 0xdb */,
+ 0 /* 0xdc */, 0 /* 0xdd */, 0 /* 0xde */, 0 /* 0xdf */,
+ 0 /* 0xe0 */, 0 /* 0xe1 */, 0 /* 0xe2 */, 0 /* 0xe3 */,
+ 0 /* 0xe4 */, 0 /* 0xe5 */, 0 /* 0xe6 */, 0 /* 0xe7 */,
+ 0 /* 0xe8 */, 0 /* 0xe9 */, 0 /* 0xea */, 0 /* 0xeb */,
+ 0 /* 0xec */, 0 /* 0xed */, 0 /* 0xee */, 0 /* 0xef */,
+ 0 /* 0xf0 */, 0 /* 0xf1 */, 0 /* 0xf2 */, 0 /* 0xf3 */,
+ 0 /* 0xf4 */, 0 /* 0xf5 */, 0 /* 0xf6 */, 0 /* 0xf7 */,
+ 0 /* 0xf8 */, 0 /* 0xf9 */, 0 /* 0xfa */, 0 /* 0xfb */,
+ 0 /* 0xfc */, 0 /* 0xfd */, 0 /* 0xfe */, 0 /* 0xff */
+};
+
+static int check_authority(const uint8_t *value, size_t len) {
+ const uint8_t *last;
+ for (last = value + len; value != last; ++value) {
+ if (!VALID_AUTHORITY_CHARS[*value]) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int check_scheme(const uint8_t *value, size_t len) {
+ const uint8_t *last;
+ if (len == 0) {
+ return 0;
+ }
+
+ if (!(('A' <= *value && *value <= 'Z') || ('a' <= *value && *value <= 'z'))) {
+ return 0;
+ }
+
+ last = value + len;
+ ++value;
+
+ for (; value != last; ++value) {
+ if (!(('A' <= *value && *value <= 'Z') ||
+ ('a' <= *value && *value <= 'z') ||
+ ('0' <= *value && *value <= '9') || *value == '+' || *value == '-' ||
+ *value == '.')) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
+ nghttp2_frame *frame, nghttp2_hd_nv *nv,
+ int trailer) {
+ int rv;
+
+ /* We are strict for pseudo header field. One bad character should
+ lead to fail. OTOH, we should be a bit forgiving for regular
+ headers, since existing public internet has so much illegal
+ headers floating around and if we kill the stream because of
+ this, we may disrupt many web sites and/or libraries. So we
+ become conservative here, and just ignore those illegal regular
+ headers. */
+ if (!nghttp2_check_header_name(nv->name->base, nv->name->len)) {
+ size_t i;
+ if (nv->name->len > 0 && nv->name->base[0] == ':') {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ /* header field name must be lower-cased without exception */
+ for (i = 0; i < nv->name->len; ++i) {
+ uint8_t c = nv->name->base[i];
+ if ('A' <= c && c <= 'Z') {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ }
+ /* When ignoring regular headers, we set this flag so that we
+ still enforce header field ordering rule for pseudo header
+ fields. */
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
+ return NGHTTP2_ERR_IGN_HTTP_HEADER;
+ }
+
+ if (nv->token == NGHTTP2_TOKEN__AUTHORITY ||
+ nv->token == NGHTTP2_TOKEN_HOST) {
+ rv = check_authority(nv->value->base, nv->value->len);
+ } else if (nv->token == NGHTTP2_TOKEN__SCHEME) {
+ rv = check_scheme(nv->value->base, nv->value->len);
+ } else {
+ rv = nghttp2_check_header_value(nv->value->base, nv->value->len);
+ }
+
+ if (rv == 0) {
+ assert(nv->name->len > 0);
+ if (nv->name->base[0] == ':') {
+ return NGHTTP2_ERR_HTTP_HEADER;
+ }
+ /* When ignoring regular headers, we set this flag so that we
+ still enforce header field ordering rule for pseudo header
+ fields. */
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED;
+ return NGHTTP2_ERR_IGN_HTTP_HEADER;
+ }
+
+ if (session->server || frame->hd.type == NGHTTP2_PUSH_PROMISE) {
+ return http_request_on_header(stream, nv, trailer);
+ }
+
+ return http_response_on_header(stream, nv, trailer);
+}
+
+int nghttp2_http_on_request_headers(nghttp2_stream *stream,
+ nghttp2_frame *frame) {
+ if (stream->http_flags & NGHTTP2_HTTP_FLAG_METH_CONNECT) {
+ if ((stream->http_flags & NGHTTP2_HTTP_FLAG__AUTHORITY) == 0) {
+ return -1;
+ }
+ stream->content_length = -1;
+ } else {
+ if ((stream->http_flags & NGHTTP2_HTTP_FLAG_REQ_HEADERS) !=
+ NGHTTP2_HTTP_FLAG_REQ_HEADERS ||
+ (stream->http_flags &
+ (NGHTTP2_HTTP_FLAG__AUTHORITY | NGHTTP2_HTTP_FLAG_HOST)) == 0) {
+ return -1;
+ }
+ if (!check_path(stream)) {
+ return -1;
+ }
+ }
+
+ if (frame->hd.type == NGHTTP2_PUSH_PROMISE) {
+ /* we are going to reuse data fields for upcoming response. Clear
+ them now, except for method flags. */
+ stream->http_flags &= NGHTTP2_HTTP_FLAG_METH_ALL;
+ stream->content_length = -1;
+ }
+
+ return 0;
+}
+
+int nghttp2_http_on_response_headers(nghttp2_stream *stream) {
+ if ((stream->http_flags & NGHTTP2_HTTP_FLAG__STATUS) == 0) {
+ return -1;
+ }
+
+ if (stream->status_code / 100 == 1) {
+ /* non-final response */
+ stream->http_flags =
+ (uint16_t)((stream->http_flags & NGHTTP2_HTTP_FLAG_METH_ALL) |
+ NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE);
+ stream->content_length = -1;
+ stream->status_code = -1;
+ return 0;
+ }
+
+ stream->http_flags =
+ (uint16_t)(stream->http_flags & ~NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE);
+
+ if (!expect_response_body(stream)) {
+ stream->content_length = 0;
+ } else if (stream->http_flags & (NGHTTP2_HTTP_FLAG_METH_CONNECT |
+ NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND)) {
+ stream->content_length = -1;
+ }
+
+ return 0;
+}
+
+int nghttp2_http_on_trailer_headers(nghttp2_stream *stream,
+ nghttp2_frame *frame) {
+ (void)stream;
+
+ if ((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int nghttp2_http_on_remote_end_stream(nghttp2_stream *stream) {
+ if (stream->http_flags & NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE) {
+ return -1;
+ }
+
+ if (stream->content_length != -1 &&
+ stream->content_length != stream->recv_content_length) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int nghttp2_http_on_data_chunk(nghttp2_stream *stream, size_t n) {
+ stream->recv_content_length += (int64_t)n;
+
+ if ((stream->http_flags & NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE) ||
+ (stream->content_length != -1 &&
+ stream->recv_content_length > stream->content_length)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+void nghttp2_http_record_request_method(nghttp2_stream *stream,
+ nghttp2_frame *frame) {
+ const nghttp2_nv *nva;
+ size_t nvlen;
+ size_t i;
+
+ switch (frame->hd.type) {
+ case NGHTTP2_HEADERS:
+ nva = frame->headers.nva;
+ nvlen = frame->headers.nvlen;
+ break;
+ case NGHTTP2_PUSH_PROMISE:
+ nva = frame->push_promise.nva;
+ nvlen = frame->push_promise.nvlen;
+ break;
+ default:
+ return;
+ }
+
+ /* TODO we should do this strictly. */
+ for (i = 0; i < nvlen; ++i) {
+ const nghttp2_nv *nv = &nva[i];
+ if (!(nv->namelen == 7 && nv->name[6] == 'd' &&
+ memcmp(":metho", nv->name, nv->namelen - 1) == 0)) {
+ continue;
+ }
+ if (lstreq("CONNECT", nv->value, nv->valuelen)) {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_CONNECT;
+ return;
+ }
+ if (lstreq("HEAD", nv->value, nv->valuelen)) {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD;
+ return;
+ }
+ return;
+ }
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_http.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_http.h
new file mode 100644
index 00000000..bde7023d
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_http.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_HTTP_H
+#define NGHTTP2_HTTP_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+#include "nghttp2_session.h"
+#include "nghttp2_stream.h"
+
+/*
+ * This function is called when HTTP header field |nv| in |frame| is
+ * received for |stream|. This function will validate |nv| against
+ * the current state of stream.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_HTTP_HEADER
+ * Invalid HTTP header field was received.
+ * NGHTTP2_ERR_IGN_HTTP_HEADER
+ * Invalid HTTP header field was received but it can be treated as
+ * if it was not received because of compatibility reasons.
+ */
+int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
+ nghttp2_frame *frame, nghttp2_hd_nv *nv,
+ int trailer);
+
+/*
+ * This function is called when request header is received. This
+ * function performs validation and returns 0 if it succeeds, or -1.
+ */
+int nghttp2_http_on_request_headers(nghttp2_stream *stream,
+ nghttp2_frame *frame);
+
+/*
+ * This function is called when response header is received. This
+ * function performs validation and returns 0 if it succeeds, or -1.
+ */
+int nghttp2_http_on_response_headers(nghttp2_stream *stream);
+
+/*
+ * This function is called trailer header (for both request and
+ * response) is received. This function performs validation and
+ * returns 0 if it succeeds, or -1.
+ */
+int nghttp2_http_on_trailer_headers(nghttp2_stream *stream,
+ nghttp2_frame *frame);
+
+/*
+ * This function is called when END_STREAM flag is seen in incoming
+ * frame. This function performs validation and returns 0 if it
+ * succeeds, or -1.
+ */
+int nghttp2_http_on_remote_end_stream(nghttp2_stream *stream);
+
+/*
+ * This function is called when chunk of data is received. This
+ * function performs validation and returns 0 if it succeeds, or -1.
+ */
+int nghttp2_http_on_data_chunk(nghttp2_stream *stream, size_t n);
+
+/*
+ * This function inspects header field in |frame| and records its
+ * method in stream->http_flags. If frame->hd.type is neither
+ * NGHTTP2_HEADERS nor NGHTTP2_PUSH_PROMISE, this function does
+ * nothing.
+ */
+void nghttp2_http_record_request_method(nghttp2_stream *stream,
+ nghttp2_frame *frame);
+
+#endif /* NGHTTP2_HTTP_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_int.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_int.h
new file mode 100644
index 00000000..56c071a4
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_int.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_INT_H
+#define NGHTTP2_INT_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+/* Macros, types and constants for internal use */
+
+/* "less" function, return nonzero if |lhs| is less than |rhs|. */
+typedef int (*nghttp2_less)(const void *lhs, const void *rhs);
+
+/* Internal error code. They must be in the range [-499, -100],
+ inclusive. */
+typedef enum {
+ NGHTTP2_ERR_CREDENTIAL_PENDING = -101,
+ NGHTTP2_ERR_IGN_HEADER_BLOCK = -103,
+ NGHTTP2_ERR_IGN_PAYLOAD = -104,
+ /*
+ * Invalid HTTP header field was received but it can be treated as
+ * if it was not received because of compatibility reasons.
+ */
+ NGHTTP2_ERR_IGN_HTTP_HEADER = -105,
+ /*
+ * Invalid HTTP header field was received, and it is ignored.
+ * Unlike NGHTTP2_ERR_IGN_HTTP_HEADER, this does not invoke
+ * nghttp2_on_invalid_header_callback.
+ */
+ NGHTTP2_ERR_REMOVE_HTTP_HEADER = -106
+} nghttp2_internal_error;
+
+#endif /* NGHTTP2_INT_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_map.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_map.c
new file mode 100644
index 00000000..9de8299a
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_map.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_map.h"
+
+#include
+
+#define INITIAL_TABLE_LENGTH 256
+
+int nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem) {
+ map->mem = mem;
+ map->tablelen = INITIAL_TABLE_LENGTH;
+ map->table =
+ nghttp2_mem_calloc(mem, map->tablelen, sizeof(nghttp2_map_entry *));
+ if (map->table == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ map->size = 0;
+
+ return 0;
+}
+
+void nghttp2_map_free(nghttp2_map *map) {
+ nghttp2_mem_free(map->mem, map->table);
+}
+
+void nghttp2_map_each_free(nghttp2_map *map,
+ int (*func)(nghttp2_map_entry *entry, void *ptr),
+ void *ptr) {
+ uint32_t i;
+ for (i = 0; i < map->tablelen; ++i) {
+ nghttp2_map_entry *entry;
+ for (entry = map->table[i]; entry;) {
+ nghttp2_map_entry *next = entry->next;
+ func(entry, ptr);
+ entry = next;
+ }
+ map->table[i] = NULL;
+ }
+}
+
+int nghttp2_map_each(nghttp2_map *map,
+ int (*func)(nghttp2_map_entry *entry, void *ptr),
+ void *ptr) {
+ int rv;
+ uint32_t i;
+ for (i = 0; i < map->tablelen; ++i) {
+ nghttp2_map_entry *entry;
+ for (entry = map->table[i]; entry; entry = entry->next) {
+ rv = func(entry, ptr);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+ }
+ return 0;
+}
+
+void nghttp2_map_entry_init(nghttp2_map_entry *entry, key_type key) {
+ entry->key = key;
+ entry->next = NULL;
+}
+
+/* Same hash function in android HashMap source code. */
+/* The |mod| must be power of 2 */
+static uint32_t hash(int32_t key, uint32_t mod) {
+ uint32_t h = (uint32_t)key;
+ h ^= (h >> 20) ^ (h >> 12);
+ h ^= (h >> 7) ^ (h >> 4);
+ return h & (mod - 1);
+}
+
+static int insert(nghttp2_map_entry **table, uint32_t tablelen,
+ nghttp2_map_entry *entry) {
+ uint32_t h = hash(entry->key, tablelen);
+ if (table[h] == NULL) {
+ table[h] = entry;
+ } else {
+ nghttp2_map_entry *p;
+ /* We won't allow duplicated key, so check it out. */
+ for (p = table[h]; p; p = p->next) {
+ if (p->key == entry->key) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+ }
+ entry->next = table[h];
+ table[h] = entry;
+ }
+ return 0;
+}
+
+/* new_tablelen must be power of 2 */
+static int resize(nghttp2_map *map, uint32_t new_tablelen) {
+ uint32_t i;
+ nghttp2_map_entry **new_table;
+
+ new_table =
+ nghttp2_mem_calloc(map->mem, new_tablelen, sizeof(nghttp2_map_entry *));
+ if (new_table == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ for (i = 0; i < map->tablelen; ++i) {
+ nghttp2_map_entry *entry;
+ for (entry = map->table[i]; entry;) {
+ nghttp2_map_entry *next = entry->next;
+ entry->next = NULL;
+ /* This function must succeed */
+ insert(new_table, new_tablelen, entry);
+ entry = next;
+ }
+ }
+ nghttp2_mem_free(map->mem, map->table);
+ map->tablelen = new_tablelen;
+ map->table = new_table;
+
+ return 0;
+}
+
+int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_entry *new_entry) {
+ int rv;
+ /* Load factor is 0.75 */
+ if ((map->size + 1) * 4 > map->tablelen * 3) {
+ rv = resize(map, map->tablelen * 2);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+ rv = insert(map->table, map->tablelen, new_entry);
+ if (rv != 0) {
+ return rv;
+ }
+ ++map->size;
+ return 0;
+}
+
+nghttp2_map_entry *nghttp2_map_find(nghttp2_map *map, key_type key) {
+ uint32_t h;
+ nghttp2_map_entry *entry;
+ h = hash(key, map->tablelen);
+ for (entry = map->table[h]; entry; entry = entry->next) {
+ if (entry->key == key) {
+ return entry;
+ }
+ }
+ return NULL;
+}
+
+int nghttp2_map_remove(nghttp2_map *map, key_type key) {
+ uint32_t h;
+ nghttp2_map_entry **dst;
+
+ h = hash(key, map->tablelen);
+
+ for (dst = &map->table[h]; *dst; dst = &(*dst)->next) {
+ if ((*dst)->key != key) {
+ continue;
+ }
+
+ *dst = (*dst)->next;
+ --map->size;
+ return 0;
+ }
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+}
+
+size_t nghttp2_map_size(nghttp2_map *map) { return map->size; }
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_map.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_map.h
new file mode 100644
index 00000000..48096a2d
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_map.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_MAP_H
+#define NGHTTP2_MAP_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+#include "nghttp2_int.h"
+#include "nghttp2_mem.h"
+
+/* Implementation of unordered map */
+
+typedef int32_t key_type;
+
+typedef struct nghttp2_map_entry {
+ struct nghttp2_map_entry *next;
+ key_type key;
+#if SIZEOF_INT_P == 4
+ /* we requires 8 bytes aligment */
+ int64_t pad;
+#endif
+} nghttp2_map_entry;
+
+typedef struct {
+ nghttp2_map_entry **table;
+ nghttp2_mem *mem;
+ size_t size;
+ uint32_t tablelen;
+} nghttp2_map;
+
+/*
+ * Initializes the map |map|.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_map_init(nghttp2_map *map, nghttp2_mem *mem);
+
+/*
+ * Deallocates any resources allocated for |map|. The stored entries
+ * are not freed by this function. Use nghttp2_map_each_free() to free
+ * each entries.
+ */
+void nghttp2_map_free(nghttp2_map *map);
+
+/*
+ * Deallocates each entries using |func| function and any resources
+ * allocated for |map|. The |func| function is responsible for freeing
+ * given the |entry| object. The |ptr| will be passed to the |func| as
+ * send argument. The return value of the |func| will be ignored.
+ */
+void nghttp2_map_each_free(nghttp2_map *map,
+ int (*func)(nghttp2_map_entry *entry, void *ptr),
+ void *ptr);
+
+/*
+ * Initializes the |entry| with the |key|. All entries to be inserted
+ * to the map must be initialized with this function.
+ */
+void nghttp2_map_entry_init(nghttp2_map_entry *entry, key_type key);
+
+/*
+ * Inserts the new |entry| with the key |entry->key| to the map |map|.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_INVALID_ARGUMENT
+ * The item associated by |key| already exists.
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_map_insert(nghttp2_map *map, nghttp2_map_entry *entry);
+
+/*
+ * Returns the entry associated by the key |key|. If there is no such
+ * entry, this function returns NULL.
+ */
+nghttp2_map_entry *nghttp2_map_find(nghttp2_map *map, key_type key);
+
+/*
+ * Removes the entry associated by the key |key| from the |map|. The
+ * removed entry is not freed by this function.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_INVALID_ARGUMENT
+ * The entry associated by |key| does not exist.
+ */
+int nghttp2_map_remove(nghttp2_map *map, key_type key);
+
+/*
+ * Returns the number of items stored in the map |map|.
+ */
+size_t nghttp2_map_size(nghttp2_map *map);
+
+/*
+ * Applies the function |func| to each entry in the |map| with the
+ * optional user supplied pointer |ptr|.
+ *
+ * If the |func| returns 0, this function calls the |func| with the
+ * next entry. If the |func| returns nonzero, it will not call the
+ * |func| for further entries and return the return value of the
+ * |func| immediately. Thus, this function returns 0 if all the
+ * invocations of the |func| return 0, or nonzero value which the last
+ * invocation of |func| returns.
+ *
+ * Don't use this function to free each entry. Use
+ * nghttp2_map_each_free() instead.
+ */
+int nghttp2_map_each(nghttp2_map *map,
+ int (*func)(nghttp2_map_entry *entry, void *ptr),
+ void *ptr);
+
+#endif /* NGHTTP2_MAP_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_mem.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_mem.c
new file mode 100644
index 00000000..5a669731
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_mem.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include
+#include "nghttp2_mem.h"
+#ifdef INFRA_MEM_STATS
+#include "infra_mem_stats.h"
+#endif
+
+extern void *HAL_Malloc(uint32_t size);
+extern void *HAL_Realloc(void *ptr, uint32_t size);
+extern void HAL_Free(void *ptr);
+
+
+static void *default_malloc(size_t size, void *mem_user_data)
+{
+ (void)mem_user_data;
+
+#ifdef INFRA_MEM_STATS
+ return LITE_malloc(size, MEM_MAGIC, "nghttp2");
+#else
+ return HAL_Malloc(size);
+#endif
+}
+
+static void default_free(void *ptr, void *mem_user_data)
+{
+ (void)mem_user_data;
+ if (ptr != NULL) {
+#ifdef INFRA_MEM_STATS
+ LITE_free(ptr);
+#else
+ HAL_Free((void *)ptr);
+ ptr = NULL;
+#endif
+ }
+}
+
+static void *default_calloc(size_t nmemb, size_t size, void *mem_user_data)
+{
+ /* (void)mem_user_data; */
+
+#ifdef INFRA_MEM_STATS
+ return LITE_calloc(nmemb, size, MEM_MAGIC, "nghttp2");
+#else
+ void *ptr = HAL_Malloc(nmemb * size);
+ if (ptr != NULL) {
+ memset(ptr, 0, nmemb * size);
+ }
+ return ptr;
+#endif
+}
+
+static void *default_realloc(void *ptr, size_t size, void *mem_user_data)
+{
+ (void)mem_user_data;
+
+#ifdef INFRA_MEM_STATS
+ return LITE_realloc(ptr, size, MEM_MAGIC, "nghttp2");
+#else
+ return HAL_Realloc(ptr, size);
+#endif
+}
+
+static nghttp2_mem mem_default = {NULL, default_malloc, default_free,
+ default_calloc, default_realloc
+ };
+
+nghttp2_mem *nghttp2_mem_default(void)
+{
+ return &mem_default;
+}
+
+void *nghttp2_mem_malloc(nghttp2_mem *mem, size_t size)
+{
+ return mem->malloc(size, mem->mem_user_data);
+}
+
+void nghttp2_mem_free(nghttp2_mem *mem, void *ptr)
+{
+ mem->free(ptr, mem->mem_user_data);
+}
+
+void nghttp2_mem_free2(nghttp2_free free_func, void *ptr, void *mem_user_data)
+{
+ free_func(ptr, mem_user_data);
+}
+
+void *nghttp2_mem_calloc(nghttp2_mem *mem, size_t nmemb, size_t size)
+{
+ return mem->calloc(nmemb, size, mem->mem_user_data);
+}
+
+void *nghttp2_mem_realloc(nghttp2_mem *mem, void *ptr, size_t size)
+{
+ return mem->realloc(ptr, size, mem->mem_user_data);
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_mem.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_mem.h
new file mode 100644
index 00000000..be33ac5d
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_mem.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_MEM_H
+#define NGHTTP2_MEM_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+#ifdef INFRA_MEM_STATS
+#include "infra_mem_stats.h"
+#endif
+
+/* The default, system standard memory allocator */
+nghttp2_mem *nghttp2_mem_default(void);
+
+/* Convenient wrapper functions to call allocator function in
+ |mem|. */
+void *nghttp2_mem_malloc(nghttp2_mem *mem, size_t size);
+void nghttp2_mem_free(nghttp2_mem *mem, void *ptr);
+void nghttp2_mem_free2(nghttp2_free free_func, void *ptr, void *mem_user_data);
+void *nghttp2_mem_calloc(nghttp2_mem *mem, size_t nmemb, size_t size);
+void *nghttp2_mem_realloc(nghttp2_mem *mem, void *ptr, size_t size);
+
+#endif /* NGHTTP2_MEM_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_net.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_net.c
new file mode 100644
index 00000000..c71af3e1
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_net.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include
+#include
+#include "nghttp2_net.h"
+
+#if IOT_BYTE_ORDER == LITTLE_ENDIAN
+ uint32_t nghttp2_htonl(uint32_t hostlong) {
+ uint32_t res;
+ unsigned char *p = (unsigned char *)&res;
+ *p++ = hostlong >> 24;
+ *p++ = (hostlong >> 16) & 0xffu;
+ *p++ = (hostlong >> 8) & 0xffu;
+ *p = hostlong & 0xffu;
+ return res;
+}
+
+uint16_t nghttp2_htons(uint16_t hostshort) {
+ uint16_t res;
+ unsigned char *p = (unsigned char *)&res;
+ *p++ = hostshort >> 8;
+ *p = hostshort & 0xffu;
+ return res;
+}
+
+uint32_t nghttp2_ntohl(uint32_t netlong) {
+ uint32_t res;
+ unsigned char *p = (unsigned char *)&netlong;
+ res = *p++ << 24;
+ res += *p++ << 16;
+ res += *p++ << 8;
+ res += *p;
+ return res;
+}
+
+uint16_t nghttp2_ntohs(uint16_t netshort) {
+ uint16_t res;
+ unsigned char *p = (unsigned char *)&netshort;
+ res = *p++ << 8;
+ res += *p;
+ return res;
+}
+#endif
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_net.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_net.h
new file mode 100644
index 00000000..b1adc401
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_net.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_NET_H
+#define NGHTTP2_NET_H
+
+#ifndef LITTLE_ENDIAN
+#define LITTLE_ENDIAN 1234
+#endif
+
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN 4321
+#endif
+
+#define IOT_BYTE_ORDER LITTLE_ENDIAN
+
+#if IOT_BYTE_ORDER == BIG_ENDIAN
+#define nghttp2_htonl(x) (x)
+#define nghttp2_htons(x) (x)
+#define nghttp2_ntohl(x) (x)
+#define nghttp2_ntohs(x) (x)
+#else
+/* Windows requires ws2_32 library for ntonl family functions. We
+ define inline functions for those function so that we don't have
+ dependeny on that lib. */
+
+#ifdef _MSC_VER
+#define STIN
+#else
+#define STIN
+#endif
+
+STIN uint32_t nghttp2_htonl(uint32_t hostlong);
+
+STIN uint16_t nghttp2_htons(uint16_t hostshort);
+
+STIN uint32_t nghttp2_ntohl(uint32_t netlong);
+
+STIN uint16_t nghttp2_ntohs(uint16_t netshort);
+
+#endif
+#endif /* NGHTTP2_NET_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_npn.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_npn.c
new file mode 100644
index 00000000..0527ec94
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_npn.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_npn.h"
+
+#include
+
+static int select_next_protocol(unsigned char **out, unsigned char *outlen,
+ const unsigned char *in, unsigned int inlen,
+ const char *key, unsigned int keylen) {
+ unsigned int i;
+ for (i = 0; i + keylen <= inlen; i += (unsigned int)(in[i] + 1)) {
+ if (memcmp(&in[i], key, keylen) == 0) {
+ *out = (unsigned char *)&in[i + 1];
+ *outlen = in[i];
+ return 0;
+ }
+ }
+ return -1;
+}
+
+#define NGHTTP2_HTTP_1_1_ALPN "\x8http/1.1"
+#define NGHTTP2_HTTP_1_1_ALPN_LEN (sizeof(NGHTTP2_HTTP_1_1_ALPN) - 1)
+
+int nghttp2_select_next_protocol(unsigned char **out, unsigned char *outlen,
+ const unsigned char *in, unsigned int inlen) {
+ if (select_next_protocol(out, outlen, in, inlen, NGHTTP2_PROTO_ALPN,
+ NGHTTP2_PROTO_ALPN_LEN) == 0) {
+ return 1;
+ }
+ if (select_next_protocol(out, outlen, in, inlen, NGHTTP2_HTTP_1_1_ALPN,
+ NGHTTP2_HTTP_1_1_ALPN_LEN) == 0) {
+ return 0;
+ }
+ return -1;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_npn.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_npn.h
new file mode 100644
index 00000000..c9fe50c9
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_npn.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_NPN_H
+#define NGHTTP2_NPN_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+#endif /* NGHTTP2_NPN_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_option.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_option.c
new file mode 100644
index 00000000..1d62f5b6
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_option.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include
+#include "nghttp2_option.h"
+#include "nghttp2_session.h"
+#ifdef INFRA_MEM_STATS
+#include "infra_mem_stats.h"
+#endif
+
+extern void *HAL_Malloc(uint32_t size);
+extern void *HAL_Realloc(void *ptr, uint32_t size);
+extern void HAL_Free(void *ptr);
+
+#if INFRA_MEM_STATS
+#define NGHTTP2_OPTION_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "nghttp2.option")
+#define NGHTTP2_OPTION_FREE(ptr) LITE_free(ptr)
+#else
+#define NGHTTP2_OPTION_MALLOC(size) HAL_Malloc(size)
+#define NGHTTP2_OPTION_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+int nghttp2_option_new(nghttp2_option **option_ptr) {
+ *option_ptr = NGHTTP2_OPTION_MALLOC(sizeof(nghttp2_option));
+
+ if (*option_ptr == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ memset(*option_ptr, 0, sizeof(nghttp2_option));
+ return 0;
+}
+
+void nghttp2_option_del(nghttp2_option *option) { NGHTTP2_OPTION_FREE(option); }
+
+void nghttp2_option_set_no_auto_window_update(nghttp2_option *option, int val) {
+ option->opt_set_mask |= NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE;
+ option->no_auto_window_update = val;
+}
+
+void nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option,
+ uint32_t val) {
+ option->opt_set_mask |= NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS;
+ option->peer_max_concurrent_streams = val;
+}
+
+void nghttp2_option_set_no_recv_client_magic(nghttp2_option *option, int val) {
+ option->opt_set_mask |= NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC;
+ option->no_recv_client_magic = val;
+}
+
+void nghttp2_option_set_no_http_messaging(nghttp2_option *option, int val) {
+ option->opt_set_mask |= NGHTTP2_OPT_NO_HTTP_MESSAGING;
+ option->no_http_messaging = val;
+}
+
+void nghttp2_option_set_max_reserved_remote_streams(nghttp2_option *option,
+ uint32_t val) {
+ option->opt_set_mask |= NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS;
+ option->max_reserved_remote_streams = val;
+}
+
+static void set_ext_type(uint8_t *ext_types, uint8_t type) {
+ ext_types[type / 8] = (uint8_t)(ext_types[type / 8] | (1 << (type & 0x7)));
+}
+
+void nghttp2_option_set_user_recv_extension_type(nghttp2_option *option,
+ uint8_t type) {
+ if (type < 10) {
+ return;
+ }
+
+ option->opt_set_mask |= NGHTTP2_OPT_USER_RECV_EXT_TYPES;
+ set_ext_type(option->user_recv_ext_types, type);
+}
+
+void nghttp2_option_set_builtin_recv_extension_type(nghttp2_option *option,
+ uint8_t type) {
+ switch (type) {
+ case NGHTTP2_ALTSVC:
+ option->opt_set_mask |= NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES;
+ option->builtin_recv_ext_types |= NGHTTP2_TYPEMASK_ALTSVC;
+ return;
+ default:
+ return;
+ }
+}
+
+void nghttp2_option_set_no_auto_ping_ack(nghttp2_option *option, int val) {
+ option->opt_set_mask |= NGHTTP2_OPT_NO_AUTO_PING_ACK;
+ option->no_auto_ping_ack = val;
+}
+
+void nghttp2_option_set_max_send_header_block_length(nghttp2_option *option,
+ size_t val) {
+ option->opt_set_mask |= NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH;
+ option->max_send_header_block_length = val;
+}
+
+void nghttp2_option_set_max_deflate_dynamic_table_size(nghttp2_option *option,
+ size_t val) {
+ option->opt_set_mask |= NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE;
+ option->max_deflate_dynamic_table_size = val;
+}
+
+void nghttp2_option_set_no_closed_streams(nghttp2_option *option, int val) {
+ option->opt_set_mask |= NGHTTP2_OPT_NO_CLOSED_STREAMS;
+ option->no_closed_streams = val;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_option.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_option.h
new file mode 100644
index 00000000..16b64e09
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_option.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_OPTION_H
+#define NGHTTP2_OPTION_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+/**
+ * Configuration options
+ */
+typedef enum {
+ /**
+ * This option prevents the library from sending WINDOW_UPDATE for a
+ * connection automatically. If this option is set to nonzero, the
+ * library won't send WINDOW_UPDATE for DATA until application calls
+ * nghttp2_session_consume() to indicate the amount of consumed
+ * DATA. By default, this option is set to zero.
+ */
+ NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE = 1,
+ /**
+ * This option sets the SETTINGS_MAX_CONCURRENT_STREAMS value of
+ * remote endpoint as if it is received in SETTINGS frame. Without
+ * specifying this option, before the local endpoint receives
+ * SETTINGS_MAX_CONCURRENT_STREAMS in SETTINGS frame from remote
+ * endpoint, SETTINGS_MAX_CONCURRENT_STREAMS is unlimited. This may
+ * cause problem if local endpoint submits lots of requests
+ * initially and sending them at once to the remote peer may lead to
+ * the rejection of some requests. Specifying this option to the
+ * sensible value, say 100, may avoid this kind of issue. This value
+ * will be overwritten if the local endpoint receives
+ * SETTINGS_MAX_CONCURRENT_STREAMS from the remote endpoint.
+ */
+ NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 1 << 1,
+ NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC = 1 << 2,
+ NGHTTP2_OPT_NO_HTTP_MESSAGING = 1 << 3,
+ NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS = 1 << 4,
+ NGHTTP2_OPT_USER_RECV_EXT_TYPES = 1 << 5,
+ NGHTTP2_OPT_NO_AUTO_PING_ACK = 1 << 6,
+ NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES = 1 << 7,
+ NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH = 1 << 8,
+ NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE = 1 << 9,
+ NGHTTP2_OPT_NO_CLOSED_STREAMS = 1 << 10,
+} nghttp2_option_flag;
+
+/**
+ * Struct to store option values for nghttp2_session.
+ */
+struct nghttp2_option {
+ /**
+ * NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH
+ */
+ size_t max_send_header_block_length;
+ /**
+ * NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE
+ */
+ size_t max_deflate_dynamic_table_size;
+ /**
+ * Bitwise OR of nghttp2_option_flag to determine that which fields
+ * are specified.
+ */
+ uint32_t opt_set_mask;
+ /**
+ * NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS
+ */
+ uint32_t peer_max_concurrent_streams;
+ /**
+ * NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS
+ */
+ uint32_t max_reserved_remote_streams;
+ /**
+ * NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES
+ */
+ uint32_t builtin_recv_ext_types;
+ /**
+ * NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE
+ */
+ int no_auto_window_update;
+ /**
+ * NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC
+ */
+ int no_recv_client_magic;
+ /**
+ * NGHTTP2_OPT_NO_HTTP_MESSAGING
+ */
+ int no_http_messaging;
+ /**
+ * NGHTTP2_OPT_NO_AUTO_PING_ACK
+ */
+ int no_auto_ping_ack;
+ /**
+ * NGHTTP2_OPT_NO_CLOSED_STREAMS
+ */
+ int no_closed_streams;
+ /**
+ * NGHTTP2_OPT_USER_RECV_EXT_TYPES
+ */
+ uint8_t user_recv_ext_types[32];
+};
+
+#endif /* NGHTTP2_OPTION_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_outbound_item.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_outbound_item.c
new file mode 100644
index 00000000..3d35983d
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_outbound_item.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_outbound_item.h"
+
+#include
+#include
+
+void nghttp2_outbound_item_init(nghttp2_outbound_item *item) {
+ item->cycle = 0;
+ item->qnext = NULL;
+ item->queued = 0;
+
+ memset(&item->aux_data, 0, sizeof(nghttp2_aux_data));
+}
+
+void nghttp2_outbound_item_free(nghttp2_outbound_item *item, nghttp2_mem *mem) {
+ nghttp2_frame *frame;
+
+ if (item == NULL) {
+ return;
+ }
+
+ frame = &item->frame;
+
+ switch (frame->hd.type) {
+ case NGHTTP2_DATA:
+ nghttp2_frame_data_free(&frame->data);
+ break;
+ case NGHTTP2_HEADERS:
+ nghttp2_frame_headers_free(&frame->headers, mem);
+ break;
+ case NGHTTP2_PRIORITY:
+ nghttp2_frame_priority_free(&frame->priority);
+ break;
+ case NGHTTP2_RST_STREAM:
+ nghttp2_frame_rst_stream_free(&frame->rst_stream);
+ break;
+ case NGHTTP2_SETTINGS:
+ nghttp2_frame_settings_free(&frame->settings, mem);
+ break;
+ case NGHTTP2_PUSH_PROMISE:
+ nghttp2_frame_push_promise_free(&frame->push_promise, mem);
+ break;
+ case NGHTTP2_PING:
+ nghttp2_frame_ping_free(&frame->ping);
+ break;
+ case NGHTTP2_GOAWAY:
+ nghttp2_frame_goaway_free(&frame->goaway, mem);
+ break;
+ case NGHTTP2_WINDOW_UPDATE:
+ nghttp2_frame_window_update_free(&frame->window_update);
+ break;
+ default: {
+ nghttp2_ext_aux_data *aux_data;
+
+ aux_data = &item->aux_data.ext;
+
+ if (aux_data->builtin == 0) {
+ nghttp2_frame_extension_free(&frame->ext);
+ break;
+ }
+
+ switch (frame->hd.type) {
+ case NGHTTP2_ALTSVC:
+ nghttp2_frame_altsvc_free(&frame->ext, mem);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ }
+}
+
+void nghttp2_outbound_queue_init(nghttp2_outbound_queue *q) {
+ q->head = q->tail = NULL;
+ q->n = 0;
+}
+
+void nghttp2_outbound_queue_push(nghttp2_outbound_queue *q,
+ nghttp2_outbound_item *item) {
+ if (q->tail) {
+ q->tail = q->tail->qnext = item;
+ } else {
+ q->head = q->tail = item;
+ }
+ ++q->n;
+}
+
+void nghttp2_outbound_queue_pop(nghttp2_outbound_queue *q) {
+ nghttp2_outbound_item *item;
+ if (!q->head) {
+ return;
+ }
+ item = q->head;
+ q->head = q->head->qnext;
+ item->qnext = NULL;
+ if (!q->head) {
+ q->tail = NULL;
+ }
+ --q->n;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_outbound_item.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_outbound_item.h
new file mode 100644
index 00000000..33918356
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_outbound_item.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_OUTBOUND_ITEM_H
+#define NGHTTP2_OUTBOUND_ITEM_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+#include "nghttp2_frame.h"
+#include "nghttp2_mem.h"
+
+/* struct used for HEADERS and PUSH_PROMISE frame */
+typedef struct {
+ nghttp2_data_provider data_prd;
+ void *stream_user_data;
+ /* error code when request HEADERS is canceled by RST_STREAM while
+ it is in queue. */
+ uint32_t error_code;
+ /* nonzero if request HEADERS is canceled. The error code is stored
+ in |error_code|. */
+ uint8_t canceled;
+} nghttp2_headers_aux_data;
+
+/* struct used for DATA frame */
+typedef struct {
+ /**
+ * The data to be sent for this DATA frame.
+ */
+ nghttp2_data_provider data_prd;
+ /**
+ * The flags of DATA frame. We use separate flags here and
+ * nghttp2_data frame. The latter contains flags actually sent to
+ * peer. This |flags| may contain NGHTTP2_FLAG_END_STREAM and only
+ * when |eof| becomes nonzero, flags in nghttp2_data has
+ * NGHTTP2_FLAG_END_STREAM set.
+ */
+ uint8_t flags;
+ /**
+ * The flag to indicate whether EOF was reached or not. Initially
+ * |eof| is 0. It becomes 1 after all data were read.
+ */
+ uint8_t eof;
+ /**
+ * The flag to indicate that NGHTTP2_DATA_FLAG_NO_COPY is used.
+ */
+ uint8_t no_copy;
+} nghttp2_data_aux_data;
+
+typedef enum {
+ NGHTTP2_GOAWAY_AUX_NONE = 0x0,
+ /* indicates that session should be terminated after the
+ transmission of this frame. */
+ NGHTTP2_GOAWAY_AUX_TERM_ON_SEND = 0x1,
+ /* indicates that this GOAWAY is just a notification for graceful
+ shutdown. No nghttp2_session.goaway_flags should be updated on
+ the reaction to this frame. */
+ NGHTTP2_GOAWAY_AUX_SHUTDOWN_NOTICE = 0x2
+} nghttp2_goaway_aux_flag;
+
+/* struct used for GOAWAY frame */
+typedef struct {
+ /* bitwise-OR of one or more of nghttp2_goaway_aux_flag. */
+ uint8_t flags;
+} nghttp2_goaway_aux_data;
+
+/* struct used for extension frame */
+typedef struct {
+ /* nonzero if this extension frame is serialized by library
+ function, instead of user-defined callbacks. */
+ uint8_t builtin;
+} nghttp2_ext_aux_data;
+
+/* Additional data which cannot be stored in nghttp2_frame struct */
+typedef union {
+ nghttp2_data_aux_data data;
+ nghttp2_headers_aux_data headers;
+ nghttp2_goaway_aux_data goaway;
+ nghttp2_ext_aux_data ext;
+} nghttp2_aux_data;
+
+struct nghttp2_outbound_item;
+typedef struct nghttp2_outbound_item nghttp2_outbound_item;
+
+struct nghttp2_outbound_item {
+ nghttp2_frame frame;
+ /* Storage for extension frame payload. frame->ext.payload points
+ to this structure to avoid frequent memory allocation. */
+ nghttp2_ext_frame_payload ext_frame_payload;
+ nghttp2_aux_data aux_data;
+ /* The priority used in priority comparion. Smaller is served
+ earlier. For PING, SETTINGS and non-DATA frames (excluding
+ response HEADERS frame) have dedicated cycle value defined above.
+ For DATA frame, cycle is computed by taking into account of
+ effective weight and frame payload length previously sent, so
+ that the amount of transmission is distributed across streams
+ proportional to effective weight (inside a tree). */
+ uint64_t cycle;
+ nghttp2_outbound_item *qnext;
+ /* nonzero if this object is queued, except for DATA or HEADERS
+ which are attached to stream as item. */
+ uint8_t queued;
+};
+
+/*
+ * Initializes |item|. No memory allocation is done in this function.
+ * Don't call nghttp2_outbound_item_free() until frame member is
+ * initialized.
+ */
+void nghttp2_outbound_item_init(nghttp2_outbound_item *item);
+
+/*
+ * Deallocates resource for |item|. If |item| is NULL, this function
+ * does nothing.
+ */
+void nghttp2_outbound_item_free(nghttp2_outbound_item *item, nghttp2_mem *mem);
+
+/*
+ * queue for nghttp2_outbound_item.
+ */
+typedef struct {
+ nghttp2_outbound_item *head, *tail;
+ /* number of items in this queue. */
+ size_t n;
+} nghttp2_outbound_queue;
+
+void nghttp2_outbound_queue_init(nghttp2_outbound_queue *q);
+
+/* Pushes |item| into |q| */
+void nghttp2_outbound_queue_push(nghttp2_outbound_queue *q,
+ nghttp2_outbound_item *item);
+
+/* Pops |item| at the top from |q|. If |q| is empty, nothing
+ happens. */
+void nghttp2_outbound_queue_pop(nghttp2_outbound_queue *q);
+
+/* Returns the top item. */
+#define nghttp2_outbound_queue_top(Q) ((Q)->head)
+
+/* Returns the size of the queue */
+#define nghttp2_outbound_queue_size(Q) ((Q)->n)
+
+#endif /* NGHTTP2_OUTBOUND_ITEM_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_pq.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_pq.c
new file mode 100644
index 00000000..79aa1562
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_pq.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_pq.h"
+
+#include
+#include
+
+#include "nghttp2_helper.h"
+
+int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_less less, nghttp2_mem *mem) {
+ pq->mem = mem;
+ pq->capacity = 0;
+ pq->q = NULL;
+ pq->length = 0;
+ pq->less = less;
+ return 0;
+}
+
+void nghttp2_pq_free(nghttp2_pq *pq) {
+ nghttp2_mem_free(pq->mem, pq->q);
+ pq->q = NULL;
+}
+
+static void swap(nghttp2_pq *pq, size_t i, size_t j) {
+ nghttp2_pq_entry *a = pq->q[i];
+ nghttp2_pq_entry *b = pq->q[j];
+
+ pq->q[i] = b;
+ b->index = i;
+ pq->q[j] = a;
+ a->index = j;
+}
+
+static void bubble_up(nghttp2_pq *pq, size_t index) {
+ size_t parent;
+ while (index != 0) {
+ parent = (index - 1) / 2;
+ if (!pq->less(pq->q[index], pq->q[parent])) {
+ return;
+ }
+ swap(pq, parent, index);
+ index = parent;
+ }
+}
+
+int nghttp2_pq_push(nghttp2_pq *pq, nghttp2_pq_entry *item) {
+ if (pq->capacity <= pq->length) {
+ void *nq;
+ size_t ncapacity;
+
+ ncapacity = nghttp2_max(4, (pq->capacity * 2));
+
+ nq = nghttp2_mem_realloc(pq->mem, pq->q,
+ ncapacity * sizeof(nghttp2_pq_entry *));
+ if (nq == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+ pq->capacity = ncapacity;
+ pq->q = nq;
+ }
+ pq->q[pq->length] = item;
+ item->index = pq->length;
+ ++pq->length;
+ bubble_up(pq, pq->length - 1);
+ return 0;
+}
+
+nghttp2_pq_entry *nghttp2_pq_top(nghttp2_pq *pq) {
+ if (pq->length == 0) {
+ return NULL;
+ } else {
+ return pq->q[0];
+ }
+}
+
+static void bubble_down(nghttp2_pq *pq, size_t index) {
+ size_t i, j, minindex;
+ for (;;) {
+ j = index * 2 + 1;
+ minindex = index;
+ for (i = 0; i < 2; ++i, ++j) {
+ if (j >= pq->length) {
+ break;
+ }
+ if (pq->less(pq->q[j], pq->q[minindex])) {
+ minindex = j;
+ }
+ }
+ if (minindex == index) {
+ return;
+ }
+ swap(pq, index, minindex);
+ index = minindex;
+ }
+}
+
+void nghttp2_pq_pop(nghttp2_pq *pq) {
+ if (pq->length > 0) {
+ pq->q[0] = pq->q[pq->length - 1];
+ pq->q[0]->index = 0;
+ --pq->length;
+ bubble_down(pq, 0);
+ }
+}
+
+void nghttp2_pq_remove(nghttp2_pq *pq, nghttp2_pq_entry *item) {
+ assert(pq->q[item->index] == item);
+
+ if (item->index == 0) {
+ nghttp2_pq_pop(pq);
+ return;
+ }
+
+ if (item->index == pq->length - 1) {
+ --pq->length;
+ return;
+ }
+
+ pq->q[item->index] = pq->q[pq->length - 1];
+ pq->q[item->index]->index = item->index;
+ --pq->length;
+
+ if (pq->less(item, pq->q[item->index])) {
+ bubble_down(pq, item->index);
+ } else {
+ bubble_up(pq, item->index);
+ }
+}
+
+int nghttp2_pq_empty(nghttp2_pq *pq) { return pq->length == 0; }
+
+size_t nghttp2_pq_size(nghttp2_pq *pq) { return pq->length; }
+
+void nghttp2_pq_update(nghttp2_pq *pq, nghttp2_pq_item_cb fun, void *arg) {
+ size_t i;
+ int rv = 0;
+ if (pq->length == 0) {
+ return;
+ }
+ for (i = 0; i < pq->length; ++i) {
+ rv |= (*fun)(pq->q[i], arg);
+ }
+ if (rv) {
+ for (i = pq->length; i > 0; --i) {
+ bubble_down(pq, i - 1);
+ }
+ }
+}
+
+int nghttp2_pq_each(nghttp2_pq *pq, nghttp2_pq_item_cb fun, void *arg) {
+ size_t i;
+
+ if (pq->length == 0) {
+ return 0;
+ }
+ for (i = 0; i < pq->length; ++i) {
+ if ((*fun)(pq->q[i], arg)) {
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_pq.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_pq.h
new file mode 100644
index 00000000..a527db13
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_pq.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_PQ_H
+#define NGHTTP2_PQ_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+#include "nghttp2_int.h"
+#include "nghttp2_mem.h"
+
+/* Implementation of priority queue */
+
+typedef struct {
+ size_t index;
+} nghttp2_pq_entry;
+
+typedef struct {
+ /* The pointer to the pointer to the item stored */
+ nghttp2_pq_entry **q;
+ /* Memory allocator */
+ nghttp2_mem *mem;
+ /* The number of items stored */
+ size_t length;
+ /* The maximum number of items this pq can store. This is
+ automatically extended when length is reached to this value. */
+ size_t capacity;
+ /* The less function between items */
+ nghttp2_less less;
+} nghttp2_pq;
+
+/*
+ * Initializes priority queue |pq| with compare function |cmp|.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_pq_init(nghttp2_pq *pq, nghttp2_less less, nghttp2_mem *mem);
+
+/*
+ * Deallocates any resources allocated for |pq|. The stored items are
+ * not freed by this function.
+ */
+void nghttp2_pq_free(nghttp2_pq *pq);
+
+/*
+ * Adds |item| to the priority queue |pq|.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_pq_push(nghttp2_pq *pq, nghttp2_pq_entry *item);
+
+/*
+ * Returns item at the top of the queue |pq|. If the queue is empty,
+ * this function returns NULL.
+ */
+nghttp2_pq_entry *nghttp2_pq_top(nghttp2_pq *pq);
+
+/*
+ * Pops item at the top of the queue |pq|. The popped item is not
+ * freed by this function.
+ */
+void nghttp2_pq_pop(nghttp2_pq *pq);
+
+/*
+ * Returns nonzero if the queue |pq| is empty.
+ */
+int nghttp2_pq_empty(nghttp2_pq *pq);
+
+/*
+ * Returns the number of items in the queue |pq|.
+ */
+size_t nghttp2_pq_size(nghttp2_pq *pq);
+
+typedef int (*nghttp2_pq_item_cb)(nghttp2_pq_entry *item, void *arg);
+
+/*
+ * Updates each item in |pq| using function |fun| and re-construct
+ * priority queue. The |fun| must return non-zero if it modifies the
+ * item in a way that it affects ordering in the priority queue. The
+ * |arg| is passed to the 2nd parameter of |fun|.
+ */
+void nghttp2_pq_update(nghttp2_pq *pq, nghttp2_pq_item_cb fun, void *arg);
+
+/*
+ * Applys |fun| to each item in |pq|. The |arg| is passed as arg
+ * parameter to callback function. This function must not change the
+ * ordering key. If the return value from callback is nonzero, this
+ * function returns 1 immediately without iterating remaining items.
+ * Otherwise this function returns 0.
+ */
+int nghttp2_pq_each(nghttp2_pq *pq, nghttp2_pq_item_cb fun, void *arg);
+
+/*
+ * Removes |item| from priority queue.
+ */
+void nghttp2_pq_remove(nghttp2_pq *pq, nghttp2_pq_entry *item);
+
+#endif /* NGHTTP2_PQ_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_priority_spec.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_priority_spec.c
new file mode 100644
index 00000000..b3d64e60
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_priority_spec.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_priority_spec.h"
+
+void nghttp2_priority_spec_init(nghttp2_priority_spec *pri_spec,
+ int32_t stream_id, int32_t weight,
+ int exclusive) {
+ pri_spec->stream_id = stream_id;
+ pri_spec->weight = weight;
+ pri_spec->exclusive = exclusive != 0;
+}
+
+void nghttp2_priority_spec_default_init(nghttp2_priority_spec *pri_spec) {
+ pri_spec->stream_id = 0;
+ pri_spec->weight = NGHTTP2_DEFAULT_WEIGHT;
+ pri_spec->exclusive = 0;
+}
+
+int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec) {
+ return pri_spec->stream_id == 0 &&
+ pri_spec->weight == NGHTTP2_DEFAULT_WEIGHT && pri_spec->exclusive == 0;
+}
+
+void nghttp2_priority_spec_normalize_weight(nghttp2_priority_spec *pri_spec) {
+ if (pri_spec->weight < NGHTTP2_MIN_WEIGHT) {
+ pri_spec->weight = NGHTTP2_MIN_WEIGHT;
+ } else if (pri_spec->weight > NGHTTP2_MAX_WEIGHT) {
+ pri_spec->weight = NGHTTP2_MAX_WEIGHT;
+ }
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_priority_spec.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_priority_spec.h
new file mode 100644
index 00000000..d5f99564
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_priority_spec.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_PRIORITY_SPEC_H
+#define NGHTTP2_PRIORITY_SPEC_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+/*
+ * This function normalizes pri_spec->weight if it is out of range.
+ * If pri_spec->weight is less than NGHTTP2_MIN_WEIGHT, it is set to
+ * NGHTTP2_MIN_WEIGHT. If pri_spec->weight is larger than
+ * NGHTTP2_MAX_WEIGHT, it is set to NGHTTP2_MAX_WEIGHT.
+ */
+void nghttp2_priority_spec_normalize_weight(nghttp2_priority_spec *pri_spec);
+
+#endif /* NGHTTP2_PRIORITY_SPEC_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_queue.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_queue.c
new file mode 100644
index 00000000..4c45dfe0
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_queue.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "nghttp2_queue.h"
+
+#include
+#include
+#ifdef INFRA_MEM_STATS
+#include "infra_mem_stats.h"
+#endif
+
+extern void *HAL_Malloc(uint32_t size);
+extern void *HAL_Realloc(void *ptr, uint32_t size);
+extern void HAL_Free(void *ptr);
+
+#if INFRA_MEM_STATS
+#define NGHTTP2_QUEUE_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "nghttp2.queue")
+#define NGHTTP2_QUEUE_FREE(ptr) LITE_free(ptr)
+#else
+#define NGHTTP2_QUEUE_MALLOC(size) HAL_Malloc(size)
+#define NGHTTP2_QUEUE_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+void nghttp2_queue_init(nghttp2_queue *queue) {
+ queue->front = queue->back = NULL;
+}
+
+void nghttp2_queue_free(nghttp2_queue *queue) {
+ if (!queue) {
+ return;
+ } else {
+ nghttp2_queue_cell *p = queue->front;
+ while (p) {
+ nghttp2_queue_cell *next = p->next;
+ NGHTTP2_QUEUE_FREE(p);
+ p = next;
+ }
+ }
+}
+
+int nghttp2_queue_push(nghttp2_queue *queue, void *data) {
+ nghttp2_queue_cell *new_cell =
+ (nghttp2_queue_cell *)NGHTTP2_QUEUE_MALLOC(sizeof(nghttp2_queue_cell));
+ if (!new_cell) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+ new_cell->data = data;
+ new_cell->next = NULL;
+ if (queue->back) {
+ queue->back->next = new_cell;
+ queue->back = new_cell;
+
+ } else {
+ queue->front = queue->back = new_cell;
+ }
+ return 0;
+}
+
+void nghttp2_queue_pop(nghttp2_queue *queue) {
+ nghttp2_queue_cell *front = queue->front;
+ assert(front);
+ queue->front = front->next;
+ if (front == queue->back) {
+ queue->back = NULL;
+ }
+ NGHTTP2_QUEUE_FREE(front);
+}
+
+void *nghttp2_queue_front(nghttp2_queue *queue) {
+ assert(queue->front);
+ return queue->front->data;
+}
+
+void *nghttp2_queue_back(nghttp2_queue *queue) {
+ assert(queue->back);
+ return queue->back->data;
+}
+
+int nghttp2_queue_empty(nghttp2_queue *queue) { return queue->front == NULL; }
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_queue.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_queue.h
new file mode 100644
index 00000000..3ffdc14a
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_queue.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_QUEUE_H
+#define NGHTTP2_QUEUE_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+typedef struct nghttp2_queue_cell {
+ void *data;
+ struct nghttp2_queue_cell *next;
+} nghttp2_queue_cell;
+
+typedef struct {
+ nghttp2_queue_cell *front, *back;
+} nghttp2_queue;
+
+void nghttp2_queue_init(nghttp2_queue *queue);
+void nghttp2_queue_free(nghttp2_queue *queue);
+int nghttp2_queue_push(nghttp2_queue *queue, void *data);
+void nghttp2_queue_pop(nghttp2_queue *queue);
+void *nghttp2_queue_front(nghttp2_queue *queue);
+void *nghttp2_queue_back(nghttp2_queue *queue);
+int nghttp2_queue_empty(nghttp2_queue *queue);
+
+#endif /* NGHTTP2_QUEUE_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_rcbuf.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_rcbuf.c
new file mode 100644
index 00000000..0fc440eb
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_rcbuf.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_rcbuf.h"
+
+#include
+#include
+
+#include "nghttp2_mem.h"
+#include "nghttp2_helper.h"
+
+int nghttp2_rcbuf_new(nghttp2_rcbuf **rcbuf_ptr, size_t size,
+ nghttp2_mem *mem) {
+ uint8_t *p;
+
+ p = nghttp2_mem_malloc(mem, sizeof(nghttp2_rcbuf) + size);
+ if (p == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ *rcbuf_ptr = (void *)p;
+
+ (*rcbuf_ptr)->mem_user_data = mem->mem_user_data;
+ (*rcbuf_ptr)->free = mem->free;
+ (*rcbuf_ptr)->base = p + sizeof(nghttp2_rcbuf);
+ (*rcbuf_ptr)->len = size;
+ (*rcbuf_ptr)->ref = 1;
+
+ return 0;
+}
+
+int nghttp2_rcbuf_new2(nghttp2_rcbuf **rcbuf_ptr, const uint8_t *src,
+ size_t srclen, nghttp2_mem *mem) {
+ int rv;
+
+ rv = nghttp2_rcbuf_new(rcbuf_ptr, srclen + 1, mem);
+ if (rv != 0) {
+ return rv;
+ }
+
+ (*rcbuf_ptr)->len = srclen;
+ *nghttp2_cpymem((*rcbuf_ptr)->base, src, srclen) = '\0';
+
+ return 0;
+}
+
+/*
+ * Frees |rcbuf| itself, regardless of its reference cout.
+ */
+void nghttp2_rcbuf_del(nghttp2_rcbuf *rcbuf) {
+ nghttp2_mem_free2(rcbuf->free, rcbuf, rcbuf->mem_user_data);
+}
+
+void nghttp2_rcbuf_incref(nghttp2_rcbuf *rcbuf) {
+ if (rcbuf->ref == -1) {
+ return;
+ }
+
+ ++rcbuf->ref;
+}
+
+void nghttp2_rcbuf_decref(nghttp2_rcbuf *rcbuf) {
+ if (rcbuf == NULL || rcbuf->ref == -1) {
+ return;
+ }
+
+ assert(rcbuf->ref > 0);
+
+ if (--rcbuf->ref == 0) {
+ nghttp2_rcbuf_del(rcbuf);
+ }
+}
+
+nghttp2_vec nghttp2_rcbuf_get_buf(nghttp2_rcbuf *rcbuf) {
+ nghttp2_vec res = {rcbuf->base, rcbuf->len};
+ return res;
+}
+
+int nghttp2_rcbuf_is_static(const nghttp2_rcbuf *rcbuf) {
+ return rcbuf->ref == -1;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_rcbuf.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_rcbuf.h
new file mode 100644
index 00000000..edb1c59b
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_rcbuf.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_RCBUF_H
+#define NGHTTP2_RCBUF_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+struct nghttp2_rcbuf {
+ /* custom memory allocator belongs to the mem parameter when
+ creating this object. */
+ void *mem_user_data;
+ nghttp2_free free;
+ /* The pointer to the underlying buffer */
+ uint8_t *base;
+ /* Size of buffer pointed by |base|. */
+ size_t len;
+ /* Reference count */
+ int32_t ref;
+};
+
+/*
+ * Allocates nghttp2_rcbuf object with |size| as initial buffer size.
+ * When the function succeeds, the reference count becomes 1.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM:
+ * Out of memory.
+ */
+int nghttp2_rcbuf_new(nghttp2_rcbuf **rcbuf_ptr, size_t size, nghttp2_mem *mem);
+
+/*
+ * Like nghttp2_rcbuf_new(), but initializes the buffer with |src| of
+ * length |srclen|. This function allocates additional byte at the
+ * end and puts '\0' into it, so that the resulting buffer could be
+ * used as NULL-terminated string. Still (*rcbuf_ptr)->len equals to
+ * |srclen|.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM:
+ * Out of memory.
+ */
+int nghttp2_rcbuf_new2(nghttp2_rcbuf **rcbuf_ptr, const uint8_t *src,
+ size_t srclen, nghttp2_mem *mem);
+
+/*
+ * Frees |rcbuf| itself, regardless of its reference cout.
+ */
+void nghttp2_rcbuf_del(nghttp2_rcbuf *rcbuf);
+
+#endif /* NGHTTP2_RCBUF_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_session.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_session.c
new file mode 100644
index 00000000..6299b0f5
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_session.c
@@ -0,0 +1,7504 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_session.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include "nghttp2_helper.h"
+#include "nghttp2_net.h"
+#include "nghttp2_priority_spec.h"
+#include "nghttp2_option.h"
+#include "nghttp2_http.h"
+#include "nghttp2_pq.h"
+#include "nghttp2_debug.h"
+
+extern int HAL_Vsnprintf(char *str, const int len, const char *format, va_list ap);
+
+/*
+ * Returns non-zero if the number of outgoing opened streams is larger
+ * than or equal to
+ * remote_settings.max_concurrent_streams.
+ */
+static int
+session_is_outgoing_concurrent_streams_max(nghttp2_session *session) {
+ return session->remote_settings.max_concurrent_streams <=
+ session->num_outgoing_streams;
+}
+
+/*
+ * Returns non-zero if the number of incoming opened streams is larger
+ * than or equal to
+ * local_settings.max_concurrent_streams.
+ */
+static int
+session_is_incoming_concurrent_streams_max(nghttp2_session *session) {
+ return session->local_settings.max_concurrent_streams <=
+ session->num_incoming_streams;
+}
+
+/*
+ * Returns non-zero if the number of incoming opened streams is larger
+ * than or equal to
+ * session->pending_local_max_concurrent_stream.
+ */
+static int
+session_is_incoming_concurrent_streams_pending_max(nghttp2_session *session) {
+ return session->pending_local_max_concurrent_stream <=
+ session->num_incoming_streams;
+}
+
+/*
+ * Returns non-zero if |lib_error| is non-fatal error.
+ */
+static int is_non_fatal(int lib_error_code) {
+ return lib_error_code < 0 && lib_error_code > NGHTTP2_ERR_FATAL;
+}
+
+int nghttp2_is_fatal(int lib_error_code) {
+ return lib_error_code < NGHTTP2_ERR_FATAL;
+}
+
+static int session_enforce_http_messaging(nghttp2_session *session) {
+ return (session->opt_flags & NGHTTP2_OPTMASK_NO_HTTP_MESSAGING) == 0;
+}
+
+/*
+ * Returns nonzero if |frame| is trailer headers.
+ */
+static int session_trailer_headers(nghttp2_session *session,
+ nghttp2_stream *stream,
+ nghttp2_frame *frame) {
+ if (!stream || frame->hd.type != NGHTTP2_HEADERS) {
+ return 0;
+ }
+ if (session->server) {
+ return frame->headers.cat == NGHTTP2_HCAT_HEADERS;
+ }
+
+ return frame->headers.cat == NGHTTP2_HCAT_HEADERS &&
+ (stream->http_flags & NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE) == 0;
+}
+
+/* Returns nonzero if the |stream| is in reserved(remote) state */
+static int state_reserved_remote(nghttp2_session *session,
+ nghttp2_stream *stream) {
+ return stream->state == NGHTTP2_STREAM_RESERVED &&
+ !nghttp2_session_is_my_stream_id(session, stream->stream_id);
+}
+
+/* Returns nonzero if the |stream| is in reserved(local) state */
+static int state_reserved_local(nghttp2_session *session,
+ nghttp2_stream *stream) {
+ return stream->state == NGHTTP2_STREAM_RESERVED &&
+ nghttp2_session_is_my_stream_id(session, stream->stream_id);
+}
+
+/*
+ * Checks whether received stream_id is valid. This function returns
+ * 1 if it succeeds, or 0.
+ */
+static int session_is_new_peer_stream_id(nghttp2_session *session,
+ int32_t stream_id) {
+ return stream_id != 0 &&
+ !nghttp2_session_is_my_stream_id(session, stream_id) &&
+ session->last_recv_stream_id < stream_id;
+}
+
+static int session_detect_idle_stream(nghttp2_session *session,
+ int32_t stream_id) {
+ /* Assume that stream object with stream_id does not exist */
+ if (nghttp2_session_is_my_stream_id(session, stream_id)) {
+ if (session->last_sent_stream_id < stream_id) {
+ return 1;
+ }
+ return 0;
+ }
+ if (session_is_new_peer_stream_id(session, stream_id)) {
+ return 1;
+ }
+ return 0;
+}
+
+static int check_ext_type_set(const uint8_t *ext_types, uint8_t type) {
+ return (ext_types[type / 8] & (1 << (type & 0x7))) > 0;
+}
+
+static int session_call_error_callback(nghttp2_session *session,
+ int lib_error_code, const char *fmt,
+ ...) {
+ size_t bufsize;
+ va_list ap;
+ char *buf;
+ int rv;
+ nghttp2_mem *mem;
+
+ if (!session->callbacks.error_callback &&
+ !session->callbacks.error_callback2) {
+ return 0;
+ }
+
+ mem = &session->mem;
+
+ va_start(ap, fmt);
+ rv = HAL_Vsnprintf(NULL, 0, fmt, ap);
+ va_end(ap);
+
+ if (rv < 0) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ bufsize = (size_t)(rv + 1);
+
+ buf = nghttp2_mem_malloc(mem, bufsize);
+ if (buf == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ va_start(ap, fmt);
+ rv = HAL_Vsnprintf(buf, bufsize, fmt, ap);
+ va_end(ap);
+
+ if (rv < 0) {
+ nghttp2_mem_free(mem, buf);
+ /* vsnprintf may return error because of various things we can
+ imagine, but typically we don't want to drop session just for
+ debug callback. */
+ DEBUGF("error_callback: vsnprintf failed. The template was %s\n", fmt);
+ return 0;
+ }
+
+ if (session->callbacks.error_callback2) {
+ rv = session->callbacks.error_callback2(session, lib_error_code, buf,
+ (size_t)rv, session->user_data);
+ } else {
+ rv = session->callbacks.error_callback(session, buf, (size_t)rv,
+ session->user_data);
+ }
+
+ nghttp2_mem_free(mem, buf);
+
+ if (rv != 0) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+static int session_terminate_session(nghttp2_session *session,
+ int32_t last_stream_id,
+ uint32_t error_code, const char *reason) {
+ int rv;
+ const uint8_t *debug_data;
+ size_t debug_datalen;
+
+ if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) {
+ return 0;
+ }
+
+ if (reason == NULL) {
+ debug_data = NULL;
+ debug_datalen = 0;
+ } else {
+ debug_data = (const uint8_t *)reason;
+ debug_datalen = strlen(reason);
+ }
+
+ rv = nghttp2_session_add_goaway(session, last_stream_id, error_code,
+ debug_data, debug_datalen,
+ NGHTTP2_GOAWAY_AUX_TERM_ON_SEND);
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ session->goaway_flags |= NGHTTP2_GOAWAY_TERM_ON_SEND;
+
+ return 0;
+}
+
+int nghttp2_session_terminate_session(nghttp2_session *session,
+ uint32_t error_code) {
+ return session_terminate_session(session, session->last_proc_stream_id,
+ error_code, NULL);
+}
+
+int nghttp2_session_terminate_session2(nghttp2_session *session,
+ int32_t last_stream_id,
+ uint32_t error_code) {
+ return session_terminate_session(session, last_stream_id, error_code, NULL);
+}
+
+int nghttp2_session_terminate_session_with_reason(nghttp2_session *session,
+ uint32_t error_code,
+ const char *reason) {
+ return session_terminate_session(session, session->last_proc_stream_id,
+ error_code, reason);
+}
+
+int nghttp2_session_is_my_stream_id(nghttp2_session *session,
+ int32_t stream_id) {
+ int rem;
+ if (stream_id == 0) {
+ return 0;
+ }
+ rem = stream_id & 0x1;
+ if (session->server) {
+ return rem == 0;
+ }
+ return rem == 1;
+}
+
+nghttp2_stream *nghttp2_session_get_stream(nghttp2_session *session,
+ int32_t stream_id) {
+ nghttp2_stream *stream;
+
+ stream = (nghttp2_stream *)nghttp2_map_find(&session->streams, stream_id);
+
+ if (stream == NULL || (stream->flags & NGHTTP2_STREAM_FLAG_CLOSED) ||
+ stream->state == NGHTTP2_STREAM_IDLE) {
+ return NULL;
+ }
+
+ return stream;
+}
+
+nghttp2_stream *nghttp2_session_get_stream_raw(nghttp2_session *session,
+ int32_t stream_id) {
+ return (nghttp2_stream *)nghttp2_map_find(&session->streams, stream_id);
+}
+
+static void session_inbound_frame_reset(nghttp2_session *session) {
+ nghttp2_inbound_frame *iframe = &session->iframe;
+ nghttp2_mem *mem = &session->mem;
+ /* A bit risky code, since if this function is called from
+ nghttp2_session_new(), we rely on the fact that
+ iframe->frame.hd.type is 0, so that no free is performed. */
+ switch (iframe->frame.hd.type) {
+ case NGHTTP2_DATA:
+ break;
+ case NGHTTP2_HEADERS:
+ nghttp2_frame_headers_free(&iframe->frame.headers, mem);
+ break;
+ case NGHTTP2_PRIORITY:
+ nghttp2_frame_priority_free(&iframe->frame.priority);
+ break;
+ case NGHTTP2_RST_STREAM:
+ nghttp2_frame_rst_stream_free(&iframe->frame.rst_stream);
+ break;
+ case NGHTTP2_SETTINGS:
+ nghttp2_frame_settings_free(&iframe->frame.settings, mem);
+
+ nghttp2_mem_free(mem, iframe->iv);
+
+ iframe->iv = NULL;
+ iframe->niv = 0;
+ iframe->max_niv = 0;
+
+ break;
+ case NGHTTP2_PUSH_PROMISE:
+ nghttp2_frame_push_promise_free(&iframe->frame.push_promise, mem);
+ break;
+ case NGHTTP2_PING:
+ nghttp2_frame_ping_free(&iframe->frame.ping);
+ break;
+ case NGHTTP2_GOAWAY:
+ nghttp2_frame_goaway_free(&iframe->frame.goaway, mem);
+ break;
+ case NGHTTP2_WINDOW_UPDATE:
+ nghttp2_frame_window_update_free(&iframe->frame.window_update);
+ break;
+ default:
+ /* extension frame */
+ if (check_ext_type_set(session->user_recv_ext_types,
+ iframe->frame.hd.type)) {
+ nghttp2_frame_extension_free(&iframe->frame.ext);
+ } else {
+ switch (iframe->frame.hd.type) {
+ case NGHTTP2_ALTSVC:
+ if ((session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ALTSVC) == 0) {
+ break;
+ }
+ nghttp2_frame_altsvc_free(&iframe->frame.ext, mem);
+ break;
+ }
+ }
+
+ break;
+ }
+
+ memset(&iframe->frame, 0, sizeof(nghttp2_frame));
+ memset(&iframe->ext_frame_payload, 0, sizeof(nghttp2_ext_frame_payload));
+
+ iframe->state = NGHTTP2_IB_READ_HEAD;
+
+ nghttp2_buf_wrap_init(&iframe->sbuf, iframe->raw_sbuf,
+ sizeof(iframe->raw_sbuf));
+ iframe->sbuf.mark += NGHTTP2_FRAME_HDLEN;
+
+ nghttp2_buf_free(&iframe->lbuf, mem);
+ nghttp2_buf_wrap_init(&iframe->lbuf, NULL, 0);
+
+ iframe->raw_lbuf = NULL;
+
+ iframe->payloadleft = 0;
+ iframe->padlen = 0;
+}
+
+static void init_settings(nghttp2_settings_storage *settings) {
+ settings->header_table_size = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
+ settings->enable_push = 1;
+ settings->max_concurrent_streams = NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS;
+ settings->initial_window_size = NGHTTP2_INITIAL_WINDOW_SIZE;
+ settings->max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MIN;
+ settings->max_header_list_size = UINT32_MAX;
+}
+
+static void active_outbound_item_reset(nghttp2_active_outbound_item *aob,
+ nghttp2_mem *mem) {
+ DEBUGF("send: reset nghttp2_active_outbound_item\n");
+ DEBUGF("send: aob->item = %p\n", aob->item);
+ nghttp2_outbound_item_free(aob->item, mem);
+ nghttp2_mem_free(mem, aob->item);
+ aob->item = NULL;
+ nghttp2_bufs_reset(&aob->framebufs);
+ aob->state = NGHTTP2_OB_POP_ITEM;
+}
+
+int nghttp2_enable_strict_preface = 1;
+
+static int session_new(nghttp2_session **session_ptr,
+ const nghttp2_session_callbacks *callbacks,
+ void *user_data, int server,
+ const nghttp2_option *option, nghttp2_mem *mem) {
+ int rv;
+ size_t nbuffer;
+ size_t max_deflate_dynamic_table_size =
+ NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE;
+
+ if (mem == NULL) {
+ mem = nghttp2_mem_default();
+ }
+
+ *session_ptr = nghttp2_mem_calloc(mem, 1, sizeof(nghttp2_session));
+ if (*session_ptr == NULL) {
+ rv = NGHTTP2_ERR_NOMEM;
+ goto fail_session;
+ }
+
+ (*session_ptr)->mem = *mem;
+ mem = &(*session_ptr)->mem;
+
+ /* next_stream_id is initialized in either
+ nghttp2_session_client_new2 or nghttp2_session_server_new2 */
+
+ nghttp2_stream_init(&(*session_ptr)->root, 0, NGHTTP2_STREAM_FLAG_NONE,
+ NGHTTP2_STREAM_IDLE, NGHTTP2_DEFAULT_WEIGHT, 0, 0, NULL,
+ mem);
+
+ (*session_ptr)->remote_window_size = NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
+ (*session_ptr)->recv_window_size = 0;
+ (*session_ptr)->consumed_size = 0;
+ (*session_ptr)->recv_reduction = 0;
+ (*session_ptr)->local_window_size = NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE;
+
+ (*session_ptr)->goaway_flags = NGHTTP2_GOAWAY_NONE;
+ (*session_ptr)->local_last_stream_id = (1u << 31) - 1;
+ (*session_ptr)->remote_last_stream_id = (1u << 31) - 1;
+
+ (*session_ptr)->pending_local_max_concurrent_stream =
+ NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS;
+ (*session_ptr)->pending_enable_push = 1;
+
+ if (server) {
+ (*session_ptr)->server = 1;
+ }
+
+ init_settings(&(*session_ptr)->remote_settings);
+ init_settings(&(*session_ptr)->local_settings);
+
+ (*session_ptr)->max_incoming_reserved_streams =
+ NGHTTP2_MAX_INCOMING_RESERVED_STREAMS;
+
+ /* Limit max outgoing concurrent streams to sensible value */
+ (*session_ptr)->remote_settings.max_concurrent_streams = 100;
+
+ (*session_ptr)->max_send_header_block_length = NGHTTP2_MAX_HEADERSLEN;
+
+ if (option) {
+ if ((option->opt_set_mask & NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE) &&
+ option->no_auto_window_update) {
+
+ (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE;
+ }
+
+ if (option->opt_set_mask & NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS) {
+
+ (*session_ptr)->remote_settings.max_concurrent_streams =
+ option->peer_max_concurrent_streams;
+ }
+
+ if (option->opt_set_mask & NGHTTP2_OPT_MAX_RESERVED_REMOTE_STREAMS) {
+
+ (*session_ptr)->max_incoming_reserved_streams =
+ option->max_reserved_remote_streams;
+ }
+
+ if ((option->opt_set_mask & NGHTTP2_OPT_NO_RECV_CLIENT_MAGIC) &&
+ option->no_recv_client_magic) {
+
+ (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC;
+ }
+
+ if ((option->opt_set_mask & NGHTTP2_OPT_NO_HTTP_MESSAGING) &&
+ option->no_http_messaging) {
+
+ (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_HTTP_MESSAGING;
+ }
+
+ if (option->opt_set_mask & NGHTTP2_OPT_USER_RECV_EXT_TYPES) {
+ memcpy((*session_ptr)->user_recv_ext_types, option->user_recv_ext_types,
+ sizeof((*session_ptr)->user_recv_ext_types));
+ }
+
+ if (option->opt_set_mask & NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES) {
+ (*session_ptr)->builtin_recv_ext_types = option->builtin_recv_ext_types;
+ }
+
+ if ((option->opt_set_mask & NGHTTP2_OPT_NO_AUTO_PING_ACK) &&
+ option->no_auto_ping_ack) {
+ (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_AUTO_PING_ACK;
+ }
+
+ if (option->opt_set_mask & NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH) {
+ (*session_ptr)->max_send_header_block_length =
+ option->max_send_header_block_length;
+ }
+
+ if (option->opt_set_mask & NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE) {
+ max_deflate_dynamic_table_size = option->max_deflate_dynamic_table_size;
+ }
+
+ if ((option->opt_set_mask & NGHTTP2_OPT_NO_CLOSED_STREAMS) &&
+ option->no_closed_streams) {
+ (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_CLOSED_STREAMS;
+ }
+ }
+
+ rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater,
+ max_deflate_dynamic_table_size, mem);
+ if (rv != 0) {
+ goto fail_hd_deflater;
+ }
+ rv = nghttp2_hd_inflate_init(&(*session_ptr)->hd_inflater, mem);
+ if (rv != 0) {
+ goto fail_hd_inflater;
+ }
+ rv = nghttp2_map_init(&(*session_ptr)->streams, mem);
+ if (rv != 0) {
+ goto fail_map;
+ }
+
+ nbuffer = ((*session_ptr)->max_send_header_block_length +
+ NGHTTP2_FRAMEBUF_CHUNKLEN - 1) /
+ NGHTTP2_FRAMEBUF_CHUNKLEN;
+
+ if (nbuffer == 0) {
+ nbuffer = 1;
+ }
+
+ /* 1 for Pad Field. */
+ rv = nghttp2_bufs_init3(&(*session_ptr)->aob.framebufs,
+ NGHTTP2_FRAMEBUF_CHUNKLEN, nbuffer, 1,
+ NGHTTP2_FRAME_HDLEN + 1, mem);
+ if (rv != 0) {
+ goto fail_aob_framebuf;
+ }
+
+ active_outbound_item_reset(&(*session_ptr)->aob, mem);
+
+ (*session_ptr)->callbacks = *callbacks;
+ (*session_ptr)->user_data = user_data;
+
+ session_inbound_frame_reset(*session_ptr);
+
+ if (nghttp2_enable_strict_preface) {
+ nghttp2_inbound_frame *iframe = &(*session_ptr)->iframe;
+
+ if (server && ((*session_ptr)->opt_flags &
+ NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC) == 0) {
+ iframe->state = NGHTTP2_IB_READ_CLIENT_MAGIC;
+ iframe->payloadleft = NGHTTP2_CLIENT_MAGIC_LEN;
+ } else {
+ iframe->state = NGHTTP2_IB_READ_FIRST_SETTINGS;
+ }
+
+ if (!server) {
+ (*session_ptr)->aob.state = NGHTTP2_OB_SEND_CLIENT_MAGIC;
+ nghttp2_bufs_add(&(*session_ptr)->aob.framebufs, NGHTTP2_CLIENT_MAGIC,
+ NGHTTP2_CLIENT_MAGIC_LEN);
+ }
+ }
+
+ return 0;
+
+fail_aob_framebuf:
+ nghttp2_map_free(&(*session_ptr)->streams);
+fail_map:
+ nghttp2_hd_inflate_free(&(*session_ptr)->hd_inflater);
+fail_hd_inflater:
+ nghttp2_hd_deflate_free(&(*session_ptr)->hd_deflater);
+fail_hd_deflater:
+ nghttp2_mem_free(mem, *session_ptr);
+fail_session:
+ return rv;
+}
+
+int nghttp2_session_client_new(nghttp2_session **session_ptr,
+ const nghttp2_session_callbacks *callbacks,
+ void *user_data) {
+ return nghttp2_session_client_new3(session_ptr, callbacks, user_data, NULL,
+ NULL);
+}
+
+int nghttp2_session_client_new2(nghttp2_session **session_ptr,
+ const nghttp2_session_callbacks *callbacks,
+ void *user_data, const nghttp2_option *option) {
+ return nghttp2_session_client_new3(session_ptr, callbacks, user_data, option,
+ NULL);
+}
+
+int nghttp2_session_client_new3(nghttp2_session **session_ptr,
+ const nghttp2_session_callbacks *callbacks,
+ void *user_data, const nghttp2_option *option,
+ nghttp2_mem *mem) {
+ int rv;
+ nghttp2_session *session;
+
+ rv = session_new(&session, callbacks, user_data, 0, option, mem);
+
+ if (rv != 0) {
+ return rv;
+ }
+ /* IDs for use in client */
+ session->next_stream_id = 1;
+
+ *session_ptr = session;
+
+ return 0;
+}
+
+int nghttp2_session_server_new(nghttp2_session **session_ptr,
+ const nghttp2_session_callbacks *callbacks,
+ void *user_data) {
+ return nghttp2_session_server_new3(session_ptr, callbacks, user_data, NULL,
+ NULL);
+}
+
+int nghttp2_session_server_new2(nghttp2_session **session_ptr,
+ const nghttp2_session_callbacks *callbacks,
+ void *user_data, const nghttp2_option *option) {
+ return nghttp2_session_server_new3(session_ptr, callbacks, user_data, option,
+ NULL);
+}
+
+int nghttp2_session_server_new3(nghttp2_session **session_ptr,
+ const nghttp2_session_callbacks *callbacks,
+ void *user_data, const nghttp2_option *option,
+ nghttp2_mem *mem) {
+ int rv;
+ nghttp2_session *session;
+
+ rv = session_new(&session, callbacks, user_data, 1, option, mem);
+
+ if (rv != 0) {
+ return rv;
+ }
+ /* IDs for use in client */
+ session->next_stream_id = 2;
+
+ *session_ptr = session;
+
+ return 0;
+}
+
+static int free_streams(nghttp2_map_entry *entry, void *ptr) {
+ nghttp2_session *session;
+ nghttp2_stream *stream;
+ nghttp2_outbound_item *item;
+ nghttp2_mem *mem;
+
+ session = (nghttp2_session *)ptr;
+ mem = &session->mem;
+ stream = (nghttp2_stream *)entry;
+ item = stream->item;
+
+ if (item && !item->queued && item != session->aob.item) {
+ nghttp2_outbound_item_free(item, mem);
+ nghttp2_mem_free(mem, item);
+ }
+
+ nghttp2_stream_free(stream);
+ nghttp2_mem_free(mem, stream);
+
+ return 0;
+}
+
+static void ob_q_free(nghttp2_outbound_queue *q, nghttp2_mem *mem) {
+ nghttp2_outbound_item *item, *next;
+ for (item = q->head; item;) {
+ next = item->qnext;
+ nghttp2_outbound_item_free(item, mem);
+ nghttp2_mem_free(mem, item);
+ item = next;
+ }
+}
+
+static int inflight_settings_new(nghttp2_inflight_settings **settings_ptr,
+ const nghttp2_settings_entry *iv, size_t niv,
+ nghttp2_mem *mem) {
+ *settings_ptr = nghttp2_mem_malloc(mem, sizeof(nghttp2_inflight_settings));
+ if (!*settings_ptr) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ if (niv > 0) {
+ (*settings_ptr)->iv = nghttp2_frame_iv_copy(iv, niv, mem);
+ if (!(*settings_ptr)->iv) {
+ nghttp2_mem_free(mem, *settings_ptr);
+ return NGHTTP2_ERR_NOMEM;
+ }
+ } else {
+ (*settings_ptr)->iv = NULL;
+ }
+
+ (*settings_ptr)->niv = niv;
+ (*settings_ptr)->next = NULL;
+
+ return 0;
+}
+
+static void inflight_settings_del(nghttp2_inflight_settings *settings,
+ nghttp2_mem *mem) {
+ if (!settings) {
+ return;
+ }
+
+ nghttp2_mem_free(mem, settings->iv);
+ nghttp2_mem_free(mem, settings);
+}
+
+void nghttp2_session_del(nghttp2_session *session) {
+ nghttp2_mem *mem;
+ nghttp2_inflight_settings *settings;
+
+ if (session == NULL) {
+ return;
+ }
+
+ mem = &session->mem;
+
+ for (settings = session->inflight_settings_head; settings;) {
+ nghttp2_inflight_settings *next = settings->next;
+ inflight_settings_del(settings, mem);
+ settings = next;
+ }
+
+ nghttp2_stream_free(&session->root);
+
+ /* Have to free streams first, so that we can check
+ stream->item->queued */
+ nghttp2_map_each_free(&session->streams, free_streams, session);
+ nghttp2_map_free(&session->streams);
+
+ ob_q_free(&session->ob_urgent, mem);
+ ob_q_free(&session->ob_reg, mem);
+ ob_q_free(&session->ob_syn, mem);
+
+ active_outbound_item_reset(&session->aob, mem);
+ session_inbound_frame_reset(session);
+ nghttp2_hd_deflate_free(&session->hd_deflater);
+ nghttp2_hd_inflate_free(&session->hd_inflater);
+ nghttp2_bufs_free(&session->aob.framebufs);
+ nghttp2_mem_free(mem, session);
+}
+
+int nghttp2_session_reprioritize_stream(
+ nghttp2_session *session, nghttp2_stream *stream,
+ const nghttp2_priority_spec *pri_spec_in) {
+ int rv;
+ nghttp2_stream *dep_stream = NULL;
+ nghttp2_priority_spec pri_spec_default;
+ const nghttp2_priority_spec *pri_spec = pri_spec_in;
+
+ assert(pri_spec->stream_id != stream->stream_id);
+
+ if (!nghttp2_stream_in_dep_tree(stream)) {
+ return 0;
+ }
+
+ if (pri_spec->stream_id != 0) {
+ dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id);
+
+ if (!dep_stream &&
+ session_detect_idle_stream(session, pri_spec->stream_id)) {
+
+ nghttp2_priority_spec_default_init(&pri_spec_default);
+
+ dep_stream = nghttp2_session_open_stream(
+ session, pri_spec->stream_id, NGHTTP2_FLAG_NONE, &pri_spec_default,
+ NGHTTP2_STREAM_IDLE, NULL);
+
+ if (dep_stream == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+ } else if (!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) {
+ nghttp2_priority_spec_default_init(&pri_spec_default);
+ pri_spec = &pri_spec_default;
+ }
+ }
+
+ if (pri_spec->stream_id == 0) {
+ dep_stream = &session->root;
+ } else if (nghttp2_stream_dep_find_ancestor(dep_stream, stream)) {
+ DEBUGF("stream: cycle detected, dep_stream(%p)=%d stream(%p)=%d\n",
+ dep_stream, dep_stream->stream_id, stream, stream->stream_id);
+
+ nghttp2_stream_dep_remove_subtree(dep_stream);
+ rv = nghttp2_stream_dep_add_subtree(stream->dep_prev, dep_stream);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+
+ assert(dep_stream);
+
+ if (dep_stream == stream->dep_prev && !pri_spec->exclusive) {
+ /* This is minor optimization when just weight is changed. */
+ nghttp2_stream_change_weight(stream, pri_spec->weight);
+
+ return 0;
+ }
+
+ nghttp2_stream_dep_remove_subtree(stream);
+
+ /* We have to update weight after removing stream from tree */
+ stream->weight = pri_spec->weight;
+
+ if (pri_spec->exclusive) {
+ rv = nghttp2_stream_dep_insert_subtree(dep_stream, stream);
+ } else {
+ rv = nghttp2_stream_dep_add_subtree(dep_stream, stream);
+ }
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+}
+
+int nghttp2_session_add_item(nghttp2_session *session,
+ nghttp2_outbound_item *item) {
+ /* TODO Return error if stream is not found for the frame requiring
+ stream presence. */
+ int rv = 0;
+ nghttp2_stream *stream;
+ nghttp2_frame *frame;
+
+ frame = &item->frame;
+ stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
+
+ switch (frame->hd.type) {
+ case NGHTTP2_DATA:
+ if (!stream) {
+ return NGHTTP2_ERR_STREAM_CLOSED;
+ }
+
+ if (stream->item) {
+ return NGHTTP2_ERR_DATA_EXIST;
+ }
+
+ rv = nghttp2_stream_attach_item(stream, item);
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ return 0;
+ case NGHTTP2_HEADERS:
+ /* We push request HEADERS and push response HEADERS to
+ dedicated queue because their transmission is affected by
+ SETTINGS_MAX_CONCURRENT_STREAMS */
+ /* TODO If 2 HEADERS are submitted for reserved stream, then
+ both of them are queued into ob_syn, which is not
+ desirable. */
+ if (frame->headers.cat == NGHTTP2_HCAT_REQUEST ||
+ (stream && stream->state == NGHTTP2_STREAM_RESERVED)) {
+ nghttp2_outbound_queue_push(&session->ob_syn, item);
+ item->queued = 1;
+ return 0;
+ ;
+ }
+
+ nghttp2_outbound_queue_push(&session->ob_reg, item);
+ item->queued = 1;
+ return 0;
+ case NGHTTP2_SETTINGS:
+ case NGHTTP2_PING:
+ nghttp2_outbound_queue_push(&session->ob_urgent, item);
+ item->queued = 1;
+ return 0;
+ case NGHTTP2_RST_STREAM:
+ if (stream) {
+ stream->state = NGHTTP2_STREAM_CLOSING;
+ }
+ nghttp2_outbound_queue_push(&session->ob_reg, item);
+ item->queued = 1;
+ return 0;
+ case NGHTTP2_PUSH_PROMISE: {
+ nghttp2_headers_aux_data *aux_data;
+ nghttp2_priority_spec pri_spec;
+
+ aux_data = &item->aux_data.headers;
+
+ if (!stream) {
+ return NGHTTP2_ERR_STREAM_CLOSED;
+ }
+
+ nghttp2_priority_spec_init(&pri_spec, stream->stream_id,
+ NGHTTP2_DEFAULT_WEIGHT, 0);
+
+ if (!nghttp2_session_open_stream(
+ session, frame->push_promise.promised_stream_id,
+ NGHTTP2_STREAM_FLAG_NONE, &pri_spec, NGHTTP2_STREAM_RESERVED,
+ aux_data->stream_user_data)) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ /* We don't have to call nghttp2_session_adjust_closed_stream()
+ here, since stream->stream_id is local stream_id, and it does
+ not affect closed stream count. */
+
+ nghttp2_outbound_queue_push(&session->ob_reg, item);
+ item->queued = 1;
+
+ return 0;
+ }
+ case NGHTTP2_WINDOW_UPDATE:
+ if (stream) {
+ stream->window_update_queued = 1;
+ } else if (frame->hd.stream_id == 0) {
+ session->window_update_queued = 1;
+ }
+ nghttp2_outbound_queue_push(&session->ob_reg, item);
+ item->queued = 1;
+ return 0;
+ default:
+ nghttp2_outbound_queue_push(&session->ob_reg, item);
+ item->queued = 1;
+ return 0;
+ }
+}
+
+int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id,
+ uint32_t error_code) {
+ int rv;
+ nghttp2_outbound_item *item;
+ nghttp2_frame *frame;
+ nghttp2_stream *stream;
+ nghttp2_mem *mem;
+
+ mem = &session->mem;
+ stream = nghttp2_session_get_stream(session, stream_id);
+ if (stream && stream->state == NGHTTP2_STREAM_CLOSING) {
+ return 0;
+ }
+
+ /* Cancel pending request HEADERS in ob_syn if this RST_STREAM
+ refers to that stream. */
+ if (!session->server && nghttp2_session_is_my_stream_id(session, stream_id) &&
+ nghttp2_outbound_queue_top(&session->ob_syn)) {
+ nghttp2_headers_aux_data *aux_data;
+ nghttp2_frame *headers_frame;
+
+ headers_frame = &nghttp2_outbound_queue_top(&session->ob_syn)->frame;
+ assert(headers_frame->hd.type == NGHTTP2_HEADERS);
+
+ if (headers_frame->hd.stream_id <= stream_id &&
+ (uint32_t)stream_id < session->next_stream_id) {
+
+ for (item = session->ob_syn.head; item; item = item->qnext) {
+ aux_data = &item->aux_data.headers;
+
+ if (item->frame.hd.stream_id < stream_id) {
+ continue;
+ }
+
+ /* stream_id in ob_syn queue must be strictly increasing. If
+ we found larger ID, then we can break here. */
+ if (item->frame.hd.stream_id > stream_id || aux_data->canceled) {
+ break;
+ }
+
+ aux_data->error_code = error_code;
+ aux_data->canceled = 1;
+
+ return 0;
+ }
+ }
+ }
+
+ item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
+ if (item == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ nghttp2_outbound_item_init(item);
+
+ frame = &item->frame;
+
+ nghttp2_frame_rst_stream_init(&frame->rst_stream, stream_id, error_code);
+ rv = nghttp2_session_add_item(session, item);
+ if (rv != 0) {
+ nghttp2_frame_rst_stream_free(&frame->rst_stream);
+ nghttp2_mem_free(mem, item);
+ return rv;
+ }
+ return 0;
+}
+
+nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session,
+ int32_t stream_id, uint8_t flags,
+ nghttp2_priority_spec *pri_spec_in,
+ nghttp2_stream_state initial_state,
+ void *stream_user_data) {
+ int rv;
+ nghttp2_stream *stream;
+ nghttp2_stream *dep_stream = NULL;
+ int stream_alloc = 0;
+ nghttp2_priority_spec pri_spec_default;
+ nghttp2_priority_spec *pri_spec = pri_spec_in;
+ nghttp2_mem *mem;
+
+ mem = &session->mem;
+ stream = nghttp2_session_get_stream_raw(session, stream_id);
+
+ if (stream) {
+ assert(stream->state == NGHTTP2_STREAM_IDLE);
+ assert(nghttp2_stream_in_dep_tree(stream));
+ nghttp2_session_detach_idle_stream(session, stream);
+ rv = nghttp2_stream_dep_remove(stream);
+ if (rv != 0) {
+ return NULL;
+ }
+ } else {
+ stream = nghttp2_mem_malloc(mem, sizeof(nghttp2_stream));
+ if (stream == NULL) {
+ return NULL;
+ }
+
+ stream_alloc = 1;
+ }
+
+ if (pri_spec->stream_id != 0) {
+ dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id);
+
+ if (!dep_stream &&
+ session_detect_idle_stream(session, pri_spec->stream_id)) {
+ /* Depends on idle stream, which does not exist in memory.
+ Assign default priority for it. */
+ nghttp2_priority_spec_default_init(&pri_spec_default);
+
+ dep_stream = nghttp2_session_open_stream(
+ session, pri_spec->stream_id, NGHTTP2_FLAG_NONE, &pri_spec_default,
+ NGHTTP2_STREAM_IDLE, NULL);
+
+ if (dep_stream == NULL) {
+ if (stream_alloc) {
+ nghttp2_mem_free(mem, stream);
+ }
+
+ return NULL;
+ }
+ } else if (!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) {
+ /* If dep_stream is not part of dependency tree, stream will get
+ default priority. This handles the case when
+ pri_spec->stream_id == stream_id. This happens because we
+ don't check pri_spec->stream_id against new stream ID in
+ nghttp2_submit_request. This also handles the case when idle
+ stream created by PRIORITY frame was opened. Somehow we
+ first remove the idle stream from dependency tree. This is
+ done to simplify code base, but ideally we should retain old
+ dependency. But I'm not sure this adds values. */
+ nghttp2_priority_spec_default_init(&pri_spec_default);
+ pri_spec = &pri_spec_default;
+ }
+ }
+
+ if (initial_state == NGHTTP2_STREAM_RESERVED) {
+ flags |= NGHTTP2_STREAM_FLAG_PUSH;
+ }
+
+ if (stream_alloc) {
+ nghttp2_stream_init(stream, stream_id, flags, initial_state,
+ pri_spec->weight,
+ (int32_t)session->remote_settings.initial_window_size,
+ (int32_t)session->local_settings.initial_window_size,
+ stream_user_data, mem);
+
+ rv = nghttp2_map_insert(&session->streams, &stream->map_entry);
+ if (rv != 0) {
+ nghttp2_stream_free(stream);
+ nghttp2_mem_free(mem, stream);
+ return NULL;
+ }
+ } else {
+ stream->flags = flags;
+ stream->state = initial_state;
+ stream->weight = pri_spec->weight;
+ stream->stream_user_data = stream_user_data;
+ }
+
+ switch (initial_state) {
+ case NGHTTP2_STREAM_RESERVED:
+ if (nghttp2_session_is_my_stream_id(session, stream_id)) {
+ /* reserved (local) */
+ nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
+ } else {
+ /* reserved (remote) */
+ nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
+ ++session->num_incoming_reserved_streams;
+ }
+ /* Reserved stream does not count in the concurrent streams
+ limit. That is one of the DOS vector. */
+ break;
+ case NGHTTP2_STREAM_IDLE:
+ /* Idle stream does not count toward the concurrent streams limit.
+ This is used as anchor node in dependency tree. */
+ nghttp2_session_keep_idle_stream(session, stream);
+ break;
+ default:
+ if (nghttp2_session_is_my_stream_id(session, stream_id)) {
+ ++session->num_outgoing_streams;
+ } else {
+ ++session->num_incoming_streams;
+ }
+ }
+
+ if (pri_spec->stream_id == 0) {
+ dep_stream = &session->root;
+ }
+
+ assert(dep_stream);
+
+ if (pri_spec->exclusive) {
+ rv = nghttp2_stream_dep_insert(dep_stream, stream);
+ if (rv != 0) {
+ return NULL;
+ }
+ } else {
+ nghttp2_stream_dep_add(dep_stream, stream);
+ }
+
+ return stream;
+}
+
+int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id,
+ uint32_t error_code) {
+ int rv;
+ nghttp2_stream *stream;
+ nghttp2_mem *mem;
+ int is_my_stream_id;
+
+ mem = &session->mem;
+ stream = nghttp2_session_get_stream(session, stream_id);
+
+ if (!stream) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ DEBUGF("stream: stream(%p)=%d close\n", stream, stream->stream_id);
+
+ if (stream->item) {
+ nghttp2_outbound_item *item;
+
+ item = stream->item;
+
+ rv = nghttp2_stream_detach_item(stream);
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ /* If item is queued, it will be deleted when it is popped
+ (nghttp2_session_prep_frame() will fail). If session->aob.item
+ points to this item, let active_outbound_item_reset()
+ free the item. */
+ if (!item->queued && item != session->aob.item) {
+ nghttp2_outbound_item_free(item, mem);
+ nghttp2_mem_free(mem, item);
+ }
+ }
+
+ /* We call on_stream_close_callback even if stream->state is
+ NGHTTP2_STREAM_INITIAL. This will happen while sending request
+ HEADERS, a local endpoint receives RST_STREAM for that stream. It
+ may be PROTOCOL_ERROR, but without notifying stream closure will
+ hang the stream in a local endpoint.
+ */
+
+ if (session->callbacks.on_stream_close_callback) {
+ if (session->callbacks.on_stream_close_callback(
+ session, stream_id, error_code, session->user_data) != 0) {
+
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+
+ is_my_stream_id = nghttp2_session_is_my_stream_id(session, stream_id);
+
+ /* pushed streams which is not opened yet is not counted toward max
+ concurrent limits */
+ if ((stream->flags & NGHTTP2_STREAM_FLAG_PUSH)) {
+ if (!is_my_stream_id) {
+ --session->num_incoming_reserved_streams;
+ }
+ } else {
+ if (is_my_stream_id) {
+ --session->num_outgoing_streams;
+ } else {
+ --session->num_incoming_streams;
+ }
+ }
+
+ /* Closes both directions just in case they are not closed yet */
+ stream->flags |= NGHTTP2_STREAM_FLAG_CLOSED;
+
+ if ((session->opt_flags & NGHTTP2_OPTMASK_NO_CLOSED_STREAMS) == 0 &&
+ session->server && !is_my_stream_id &&
+ nghttp2_stream_in_dep_tree(stream)) {
+ /* On server side, retain stream at most MAX_CONCURRENT_STREAMS
+ combined with the current active incoming streams to make
+ dependency tree work better. */
+ nghttp2_session_keep_closed_stream(session, stream);
+ } else {
+ rv = nghttp2_session_destroy_stream(session, stream);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+
+ return 0;
+}
+
+int nghttp2_session_destroy_stream(nghttp2_session *session,
+ nghttp2_stream *stream) {
+ nghttp2_mem *mem;
+ int rv;
+
+ DEBUGF("stream: destroy closed stream(%p)=%d\n", stream, stream->stream_id);
+
+ mem = &session->mem;
+
+ if (nghttp2_stream_in_dep_tree(stream)) {
+ rv = nghttp2_stream_dep_remove(stream);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+
+ nghttp2_map_remove(&session->streams, stream->stream_id);
+ nghttp2_stream_free(stream);
+ nghttp2_mem_free(mem, stream);
+
+ return 0;
+}
+
+void nghttp2_session_keep_closed_stream(nghttp2_session *session,
+ nghttp2_stream *stream) {
+ DEBUGF("stream: keep closed stream(%p)=%d, state=%d\n", stream,
+ stream->stream_id, stream->state);
+
+ if (session->closed_stream_tail) {
+ session->closed_stream_tail->closed_next = stream;
+ stream->closed_prev = session->closed_stream_tail;
+ } else {
+ session->closed_stream_head = stream;
+ }
+ session->closed_stream_tail = stream;
+
+ ++session->num_closed_streams;
+}
+
+void nghttp2_session_keep_idle_stream(nghttp2_session *session,
+ nghttp2_stream *stream) {
+ DEBUGF("stream: keep idle stream(%p)=%d, state=%d\n", stream,
+ stream->stream_id, stream->state);
+
+ if (session->idle_stream_tail) {
+ session->idle_stream_tail->closed_next = stream;
+ stream->closed_prev = session->idle_stream_tail;
+ } else {
+ session->idle_stream_head = stream;
+ }
+ session->idle_stream_tail = stream;
+
+ ++session->num_idle_streams;
+}
+
+void nghttp2_session_detach_idle_stream(nghttp2_session *session,
+ nghttp2_stream *stream) {
+ nghttp2_stream *prev_stream, *next_stream;
+
+ DEBUGF("stream: detach idle stream(%p)=%d, state=%d\n", stream,
+ stream->stream_id, stream->state);
+
+ prev_stream = stream->closed_prev;
+ next_stream = stream->closed_next;
+
+ if (prev_stream) {
+ prev_stream->closed_next = next_stream;
+ } else {
+ session->idle_stream_head = next_stream;
+ }
+
+ if (next_stream) {
+ next_stream->closed_prev = prev_stream;
+ } else {
+ session->idle_stream_tail = prev_stream;
+ }
+
+ stream->closed_prev = NULL;
+ stream->closed_next = NULL;
+
+ --session->num_idle_streams;
+}
+
+int nghttp2_session_adjust_closed_stream(nghttp2_session *session) {
+ size_t num_stream_max;
+ int rv;
+
+ if (session->local_settings.max_concurrent_streams ==
+ NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS) {
+ num_stream_max = session->pending_local_max_concurrent_stream;
+ } else {
+ num_stream_max = session->local_settings.max_concurrent_streams;
+ }
+
+ DEBUGF("stream: adjusting kept closed streams num_closed_streams=%zu, "
+ "num_incoming_streams=%zu, max_concurrent_streams=%zu\n",
+ session->num_closed_streams, session->num_incoming_streams,
+ num_stream_max);
+
+ while (session->num_closed_streams > 0 &&
+ session->num_closed_streams + session->num_incoming_streams >
+ num_stream_max) {
+ nghttp2_stream *head_stream;
+ nghttp2_stream *next;
+
+ head_stream = session->closed_stream_head;
+
+ assert(head_stream);
+
+ next = head_stream->closed_next;
+
+ rv = nghttp2_session_destroy_stream(session, head_stream);
+ if (rv != 0) {
+ return rv;
+ }
+
+ /* head_stream is now freed */
+
+ session->closed_stream_head = next;
+
+ if (session->closed_stream_head) {
+ session->closed_stream_head->closed_prev = NULL;
+ } else {
+ session->closed_stream_tail = NULL;
+ }
+
+ --session->num_closed_streams;
+ }
+
+ return 0;
+}
+
+int nghttp2_session_adjust_idle_stream(nghttp2_session *session) {
+ size_t max;
+ int rv;
+
+ /* Make minimum number of idle streams 16, and maximum 100, which
+ are arbitrary chosen numbers. */
+ max = nghttp2_min(
+ 100, nghttp2_max(
+ 16, nghttp2_min(session->local_settings.max_concurrent_streams,
+ session->pending_local_max_concurrent_stream)));
+
+ DEBUGF("stream: adjusting kept idle streams num_idle_streams=%zu, max=%zu\n",
+ session->num_idle_streams, max);
+
+ while (session->num_idle_streams > max) {
+ nghttp2_stream *head;
+ nghttp2_stream *next;
+
+ head = session->idle_stream_head;
+ assert(head);
+
+ next = head->closed_next;
+
+ rv = nghttp2_session_destroy_stream(session, head);
+ if (rv != 0) {
+ return rv;
+ }
+
+ /* head is now destroyed */
+
+ session->idle_stream_head = next;
+
+ if (session->idle_stream_head) {
+ session->idle_stream_head->closed_prev = NULL;
+ } else {
+ session->idle_stream_tail = NULL;
+ }
+
+ --session->num_idle_streams;
+ }
+
+ return 0;
+}
+
+/*
+ * Closes stream with stream ID |stream_id| if both transmission and
+ * reception of the stream were disallowed. The |error_code| indicates
+ * the reason of the closure.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_INVALID_ARGUMENT
+ * The stream is not found.
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * The callback function failed.
+ */
+int nghttp2_session_close_stream_if_shut_rdwr(nghttp2_session *session,
+ nghttp2_stream *stream) {
+ if ((stream->shut_flags & NGHTTP2_SHUT_RDWR) == NGHTTP2_SHUT_RDWR) {
+ return nghttp2_session_close_stream(session, stream->stream_id,
+ NGHTTP2_NO_ERROR);
+ }
+ return 0;
+}
+
+/*
+ * Returns nonzero if local endpoint allows reception of new stream
+ * from remote.
+ */
+static int session_allow_incoming_new_stream(nghttp2_session *session) {
+ return (session->goaway_flags &
+ (NGHTTP2_GOAWAY_TERM_ON_SEND | NGHTTP2_GOAWAY_SENT)) == 0;
+}
+
+/*
+ * This function returns nonzero if session is closing.
+ */
+static int session_is_closing(nghttp2_session *session) {
+ return (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) != 0 ||
+ (nghttp2_session_want_read(session) == 0 &&
+ nghttp2_session_want_write(session) == 0);
+}
+
+/*
+ * Check that we can send a frame to the |stream|. This function
+ * returns 0 if we can send a frame to the |frame|, or one of the
+ * following negative error codes:
+ *
+ * NGHTTP2_ERR_STREAM_CLOSED
+ * The stream is already closed.
+ * NGHTTP2_ERR_STREAM_SHUT_WR
+ * The stream is half-closed for transmission.
+ * NGHTTP2_ERR_SESSION_CLOSING
+ * This session is closing.
+ */
+static int session_predicate_for_stream_send(nghttp2_session *session,
+ nghttp2_stream *stream) {
+ if (stream == NULL) {
+ return NGHTTP2_ERR_STREAM_CLOSED;
+ }
+ if (session_is_closing(session)) {
+ return NGHTTP2_ERR_SESSION_CLOSING;
+ }
+ if (stream->shut_flags & NGHTTP2_SHUT_WR) {
+ return NGHTTP2_ERR_STREAM_SHUT_WR;
+ }
+ return 0;
+}
+
+int nghttp2_session_check_request_allowed(nghttp2_session *session) {
+ return !session->server && session->next_stream_id <= INT32_MAX &&
+ (session->goaway_flags & NGHTTP2_GOAWAY_RECV) == 0 &&
+ !session_is_closing(session);
+}
+
+/*
+ * This function checks request HEADERS frame, which opens stream, can
+ * be sent at this time.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_START_STREAM_NOT_ALLOWED
+ * New stream cannot be created because of GOAWAY: session is
+ * going down or received last_stream_id is strictly less than
+ * frame->hd.stream_id.
+ * NGHTTP2_ERR_STREAM_CLOSING
+ * request HEADERS was canceled by RST_STREAM while it is in queue.
+ */
+static int session_predicate_request_headers_send(nghttp2_session *session,
+ nghttp2_outbound_item *item) {
+ if (item->aux_data.headers.canceled) {
+ return NGHTTP2_ERR_STREAM_CLOSING;
+ }
+ /* If we are terminating session (NGHTTP2_GOAWAY_TERM_ON_SEND),
+ GOAWAY was received from peer, or session is about to close, new
+ request is not allowed. */
+ if ((session->goaway_flags & NGHTTP2_GOAWAY_RECV) ||
+ session_is_closing(session)) {
+ return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED;
+ }
+ return 0;
+}
+
+/*
+ * This function checks HEADERS, which is the first frame from the
+ * server, with the |stream| can be sent at this time. The |stream|
+ * can be NULL.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_STREAM_CLOSED
+ * The stream is already closed or does not exist.
+ * NGHTTP2_ERR_STREAM_SHUT_WR
+ * The transmission is not allowed for this stream (e.g., a frame
+ * with END_STREAM flag set has already sent)
+ * NGHTTP2_ERR_INVALID_STREAM_ID
+ * The stream ID is invalid.
+ * NGHTTP2_ERR_STREAM_CLOSING
+ * RST_STREAM was queued for this stream.
+ * NGHTTP2_ERR_INVALID_STREAM_STATE
+ * The state of the stream is not valid.
+ * NGHTTP2_ERR_SESSION_CLOSING
+ * This session is closing.
+ * NGHTTP2_ERR_PROTO
+ * Client side attempted to send response.
+ */
+static int session_predicate_response_headers_send(nghttp2_session *session,
+ nghttp2_stream *stream) {
+ int rv;
+ rv = session_predicate_for_stream_send(session, stream);
+ if (rv != 0) {
+ return rv;
+ }
+ assert(stream);
+ if (!session->server) {
+ return NGHTTP2_ERR_PROTO;
+ }
+ if (nghttp2_session_is_my_stream_id(session, stream->stream_id)) {
+ return NGHTTP2_ERR_INVALID_STREAM_ID;
+ }
+ switch (stream->state) {
+ case NGHTTP2_STREAM_OPENING:
+ return 0;
+ case NGHTTP2_STREAM_CLOSING:
+ return NGHTTP2_ERR_STREAM_CLOSING;
+ default:
+ return NGHTTP2_ERR_INVALID_STREAM_STATE;
+ }
+}
+
+/*
+ * This function checks HEADERS for reserved stream can be sent. The
+ * |stream| must be reserved state and the |session| is server side.
+ * The |stream| can be NULL.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * error codes:
+ *
+ * NGHTTP2_ERR_STREAM_CLOSED
+ * The stream is already closed.
+ * NGHTTP2_ERR_STREAM_SHUT_WR
+ * The stream is half-closed for transmission.
+ * NGHTTP2_ERR_PROTO
+ * The stream is not reserved state
+ * NGHTTP2_ERR_STREAM_CLOSED
+ * RST_STREAM was queued for this stream.
+ * NGHTTP2_ERR_SESSION_CLOSING
+ * This session is closing.
+ * NGHTTP2_ERR_START_STREAM_NOT_ALLOWED
+ * New stream cannot be created because GOAWAY is already sent or
+ * received.
+ * NGHTTP2_ERR_PROTO
+ * Client side attempted to send push response.
+ */
+static int
+session_predicate_push_response_headers_send(nghttp2_session *session,
+ nghttp2_stream *stream) {
+ int rv;
+ /* TODO Should disallow HEADERS if GOAWAY has already been issued? */
+ rv = session_predicate_for_stream_send(session, stream);
+ if (rv != 0) {
+ return rv;
+ }
+ assert(stream);
+ if (!session->server) {
+ return NGHTTP2_ERR_PROTO;
+ }
+ if (stream->state != NGHTTP2_STREAM_RESERVED) {
+ return NGHTTP2_ERR_PROTO;
+ }
+ if (session->goaway_flags & NGHTTP2_GOAWAY_RECV) {
+ return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED;
+ }
+ return 0;
+}
+
+/*
+ * This function checks HEADERS, which is neither stream-opening nor
+ * first response header, with the |stream| can be sent at this time.
+ * The |stream| can be NULL.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_STREAM_CLOSED
+ * The stream is already closed or does not exist.
+ * NGHTTP2_ERR_STREAM_SHUT_WR
+ * The transmission is not allowed for this stream (e.g., a frame
+ * with END_STREAM flag set has already sent)
+ * NGHTTP2_ERR_STREAM_CLOSING
+ * RST_STREAM was queued for this stream.
+ * NGHTTP2_ERR_INVALID_STREAM_STATE
+ * The state of the stream is not valid.
+ * NGHTTP2_ERR_SESSION_CLOSING
+ * This session is closing.
+ */
+static int session_predicate_headers_send(nghttp2_session *session,
+ nghttp2_stream *stream) {
+ int rv;
+ rv = session_predicate_for_stream_send(session, stream);
+ if (rv != 0) {
+ return rv;
+ }
+ assert(stream);
+
+ switch (stream->state) {
+ case NGHTTP2_STREAM_OPENED:
+ return 0;
+ case NGHTTP2_STREAM_CLOSING:
+ return NGHTTP2_ERR_STREAM_CLOSING;
+ default:
+ if (nghttp2_session_is_my_stream_id(session, stream->stream_id)) {
+ return 0;
+ }
+ return NGHTTP2_ERR_INVALID_STREAM_STATE;
+ }
+}
+
+/*
+ * This function checks PUSH_PROMISE frame |frame| with the |stream|
+ * can be sent at this time. The |stream| can be NULL.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_START_STREAM_NOT_ALLOWED
+ * New stream cannot be created because GOAWAY is already sent or
+ * received.
+ * NGHTTP2_ERR_PROTO
+ * The client side attempts to send PUSH_PROMISE, or the server
+ * sends PUSH_PROMISE for the stream not initiated by the client.
+ * NGHTTP2_ERR_STREAM_CLOSED
+ * The stream is already closed or does not exist.
+ * NGHTTP2_ERR_STREAM_CLOSING
+ * RST_STREAM was queued for this stream.
+ * NGHTTP2_ERR_STREAM_SHUT_WR
+ * The transmission is not allowed for this stream (e.g., a frame
+ * with END_STREAM flag set has already sent)
+ * NGHTTP2_ERR_PUSH_DISABLED
+ * The remote peer disabled reception of PUSH_PROMISE.
+ * NGHTTP2_ERR_SESSION_CLOSING
+ * This session is closing.
+ */
+static int session_predicate_push_promise_send(nghttp2_session *session,
+ nghttp2_stream *stream) {
+ int rv;
+
+ if (!session->server) {
+ return NGHTTP2_ERR_PROTO;
+ }
+
+ rv = session_predicate_for_stream_send(session, stream);
+ if (rv != 0) {
+ return rv;
+ }
+
+ assert(stream);
+
+ if (session->remote_settings.enable_push == 0) {
+ return NGHTTP2_ERR_PUSH_DISABLED;
+ }
+ if (stream->state == NGHTTP2_STREAM_CLOSING) {
+ return NGHTTP2_ERR_STREAM_CLOSING;
+ }
+ if (session->goaway_flags & NGHTTP2_GOAWAY_RECV) {
+ return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED;
+ }
+ return 0;
+}
+
+/*
+ * This function checks WINDOW_UPDATE with the stream ID |stream_id|
+ * can be sent at this time. Note that END_STREAM flag of the previous
+ * frame does not affect the transmission of the WINDOW_UPDATE frame.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_STREAM_CLOSED
+ * The stream is already closed or does not exist.
+ * NGHTTP2_ERR_STREAM_CLOSING
+ * RST_STREAM was queued for this stream.
+ * NGHTTP2_ERR_INVALID_STREAM_STATE
+ * The state of the stream is not valid.
+ * NGHTTP2_ERR_SESSION_CLOSING
+ * This session is closing.
+ */
+static int session_predicate_window_update_send(nghttp2_session *session,
+ int32_t stream_id) {
+ nghttp2_stream *stream;
+
+ if (session_is_closing(session)) {
+ return NGHTTP2_ERR_SESSION_CLOSING;
+ }
+
+ if (stream_id == 0) {
+ /* Connection-level window update */
+ return 0;
+ }
+ stream = nghttp2_session_get_stream(session, stream_id);
+ if (stream == NULL) {
+ return NGHTTP2_ERR_STREAM_CLOSED;
+ }
+ if (stream->state == NGHTTP2_STREAM_CLOSING) {
+ return NGHTTP2_ERR_STREAM_CLOSING;
+ }
+ if (state_reserved_local(session, stream)) {
+ return NGHTTP2_ERR_INVALID_STREAM_STATE;
+ }
+ return 0;
+}
+
+static int session_predicate_altsvc_send(nghttp2_session *session,
+ int32_t stream_id) {
+ nghttp2_stream *stream;
+
+ if (session_is_closing(session)) {
+ return NGHTTP2_ERR_SESSION_CLOSING;
+ }
+
+ if (stream_id == 0) {
+ return 0;
+ }
+
+ stream = nghttp2_session_get_stream(session, stream_id);
+ if (stream == NULL) {
+ return NGHTTP2_ERR_STREAM_CLOSED;
+ }
+ if (stream->state == NGHTTP2_STREAM_CLOSING) {
+ return NGHTTP2_ERR_STREAM_CLOSING;
+ }
+
+ return 0;
+}
+
+/* Take into account settings max frame size and both connection-level
+ flow control here */
+static ssize_t
+nghttp2_session_enforce_flow_control_limits(nghttp2_session *session,
+ nghttp2_stream *stream,
+ ssize_t requested_window_size) {
+ ssize_t window_size = 0;
+ window_size = nghttp2_min(nghttp2_min(nghttp2_min(requested_window_size,
+ stream->remote_window_size),
+ session->remote_window_size),
+ (int32_t)session->remote_settings.max_frame_size);
+ return window_size;
+}
+
+/*
+ * Returns the maximum length of next data read. If the
+ * connection-level and/or stream-wise flow control are enabled, the
+ * return value takes into account those current window sizes. The remote
+ * settings for max frame size is also taken into account.
+ */
+static size_t nghttp2_session_next_data_read(nghttp2_session *session,
+ nghttp2_stream *stream) {
+ ssize_t window_size;
+
+ window_size = nghttp2_session_enforce_flow_control_limits(
+ session, stream, NGHTTP2_DATA_PAYLOADLEN);
+
+ DEBUGF("send: available window=%zd\n", window_size);
+
+ return window_size > 0 ? (size_t)window_size : 0;
+}
+
+/*
+ * This function checks DATA with the |stream| can be sent at this
+ * time. The |stream| can be NULL.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_STREAM_CLOSED
+ * The stream is already closed or does not exist.
+ * NGHTTP2_ERR_STREAM_SHUT_WR
+ * The transmission is not allowed for this stream (e.g., a frame
+ * with END_STREAM flag set has already sent)
+ * NGHTTP2_ERR_STREAM_CLOSING
+ * RST_STREAM was queued for this stream.
+ * NGHTTP2_ERR_INVALID_STREAM_STATE
+ * The state of the stream is not valid.
+ * NGHTTP2_ERR_SESSION_CLOSING
+ * This session is closing.
+ */
+static int nghttp2_session_predicate_data_send(nghttp2_session *session,
+ nghttp2_stream *stream) {
+ int rv;
+ rv = session_predicate_for_stream_send(session, stream);
+ if (rv != 0) {
+ return rv;
+ }
+ assert(stream);
+ if (nghttp2_session_is_my_stream_id(session, stream->stream_id)) {
+ /* Request body data */
+ /* If stream->state is NGHTTP2_STREAM_CLOSING, RST_STREAM was
+ queued but not yet sent. In this case, we won't send DATA
+ frames. */
+ if (stream->state == NGHTTP2_STREAM_CLOSING) {
+ return NGHTTP2_ERR_STREAM_CLOSING;
+ }
+ if (stream->state == NGHTTP2_STREAM_RESERVED) {
+ return NGHTTP2_ERR_INVALID_STREAM_STATE;
+ }
+ return 0;
+ }
+ /* Response body data */
+ if (stream->state == NGHTTP2_STREAM_OPENED) {
+ return 0;
+ }
+ if (stream->state == NGHTTP2_STREAM_CLOSING) {
+ return NGHTTP2_ERR_STREAM_CLOSING;
+ }
+ return NGHTTP2_ERR_INVALID_STREAM_STATE;
+}
+
+static ssize_t session_call_select_padding(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ size_t max_payloadlen) {
+ ssize_t rv;
+
+ if (frame->hd.length >= max_payloadlen) {
+ return (ssize_t)frame->hd.length;
+ }
+
+ if (session->callbacks.select_padding_callback) {
+ size_t max_paddedlen;
+
+ max_paddedlen =
+ nghttp2_min(frame->hd.length + NGHTTP2_MAX_PADLEN, max_payloadlen);
+
+ rv = session->callbacks.select_padding_callback(
+ session, frame, max_paddedlen, session->user_data);
+ if (rv < (ssize_t)frame->hd.length || rv > (ssize_t)max_paddedlen) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ return rv;
+ }
+ return (ssize_t)frame->hd.length;
+}
+
+/* Add padding to HEADERS or PUSH_PROMISE. We use
+ frame->headers.padlen in this function to use the fact that
+ frame->push_promise has also padlen in the same position. */
+static int session_headers_add_pad(nghttp2_session *session,
+ nghttp2_frame *frame) {
+ int rv;
+ ssize_t padded_payloadlen;
+ nghttp2_active_outbound_item *aob;
+ nghttp2_bufs *framebufs;
+ size_t padlen;
+ size_t max_payloadlen;
+
+ aob = &session->aob;
+ framebufs = &aob->framebufs;
+
+ max_payloadlen = nghttp2_min(NGHTTP2_MAX_PAYLOADLEN,
+ frame->hd.length + NGHTTP2_MAX_PADLEN);
+
+ padded_payloadlen =
+ session_call_select_padding(session, frame, max_payloadlen);
+
+ if (nghttp2_is_fatal((int)padded_payloadlen)) {
+ return (int)padded_payloadlen;
+ }
+
+ padlen = (size_t)padded_payloadlen - frame->hd.length;
+
+ DEBUGF("send: padding selected: payloadlen=%zd, padlen=%zu\n",
+ padded_payloadlen, padlen);
+
+ rv = nghttp2_frame_add_pad(framebufs, &frame->hd, padlen, 0);
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ frame->headers.padlen = padlen;
+
+ return 0;
+}
+
+static size_t session_estimate_headers_payload(nghttp2_session *session,
+ const nghttp2_nv *nva,
+ size_t nvlen,
+ size_t additional) {
+ return nghttp2_hd_deflate_bound(&session->hd_deflater, nva, nvlen) +
+ additional;
+}
+
+static int session_pack_extension(nghttp2_session *session, nghttp2_bufs *bufs,
+ nghttp2_frame *frame) {
+ ssize_t rv;
+ nghttp2_buf *buf;
+ size_t buflen;
+ size_t framelen;
+
+ assert(session->callbacks.pack_extension_callback);
+
+ buf = &bufs->head->buf;
+ buflen = nghttp2_min(nghttp2_buf_avail(buf), NGHTTP2_MAX_PAYLOADLEN);
+
+ rv = session->callbacks.pack_extension_callback(session, buf->last, buflen,
+ frame, session->user_data);
+ if (rv == NGHTTP2_ERR_CANCEL) {
+ return (int)rv;
+ }
+
+ if (rv < 0 || (size_t)rv > buflen) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ framelen = (size_t)rv;
+
+ frame->hd.length = framelen;
+
+ assert(buf->pos == buf->last);
+ buf->last += framelen;
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+
+ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
+
+ return 0;
+}
+
+/*
+ * This function serializes frame for transmission.
+ *
+ * This function returns 0 if it succeeds, or one of negative error
+ * codes, including both fatal and non-fatal ones.
+ */
+static int session_prep_frame(nghttp2_session *session,
+ nghttp2_outbound_item *item) {
+ int rv;
+ nghttp2_frame *frame;
+ nghttp2_mem *mem;
+
+ mem = &session->mem;
+ frame = &item->frame;
+
+ switch (frame->hd.type) {
+ case NGHTTP2_DATA: {
+ size_t next_readmax;
+ nghttp2_stream *stream;
+
+ stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
+
+ if (stream) {
+ assert(stream->item == item);
+ }
+
+ rv = nghttp2_session_predicate_data_send(session, stream);
+ if (rv != 0) {
+ /* If stream was already closed, nghttp2_session_get_stream()
+ returns NULL, but item is still attached to the stream.
+ Search stream including closed again.*/
+ stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id);
+ if (stream) {
+ int rv2;
+
+ rv2 = nghttp2_stream_detach_item(stream);
+
+ if (nghttp2_is_fatal(rv2)) {
+ return rv2;
+ }
+ }
+
+ return rv;
+ }
+ /* Assuming stream is not NULL */
+ assert(stream);
+ next_readmax = nghttp2_session_next_data_read(session, stream);
+
+ if (next_readmax == 0) {
+
+ /* This must be true since we only pop DATA frame item from
+ queue when session->remote_window_size > 0 */
+ assert(session->remote_window_size > 0);
+
+ rv = nghttp2_stream_defer_item(stream,
+ NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ session->aob.item = NULL;
+ active_outbound_item_reset(&session->aob, mem);
+ return NGHTTP2_ERR_DEFERRED;
+ }
+
+ rv = nghttp2_session_pack_data(session, &session->aob.framebufs,
+ next_readmax, frame, &item->aux_data.data,
+ stream);
+ if (rv == NGHTTP2_ERR_PAUSE) {
+ return rv;
+ }
+ if (rv == NGHTTP2_ERR_DEFERRED) {
+ rv = nghttp2_stream_defer_item(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ session->aob.item = NULL;
+ active_outbound_item_reset(&session->aob, mem);
+ return NGHTTP2_ERR_DEFERRED;
+ }
+ if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
+ rv = nghttp2_stream_detach_item(stream);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ rv = nghttp2_session_add_rst_stream(session, frame->hd.stream_id,
+ NGHTTP2_INTERNAL_ERROR);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
+ if (rv != 0) {
+ int rv2;
+
+ rv2 = nghttp2_stream_detach_item(stream);
+
+ if (nghttp2_is_fatal(rv2)) {
+ return rv2;
+ }
+
+ return rv;
+ }
+ return 0;
+ }
+ case NGHTTP2_HEADERS: {
+ nghttp2_headers_aux_data *aux_data;
+ size_t estimated_payloadlen;
+
+ aux_data = &item->aux_data.headers;
+
+ if (frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
+ /* initial HEADERS, which opens stream */
+ nghttp2_stream *stream;
+
+ stream = nghttp2_session_open_stream(
+ session, frame->hd.stream_id, NGHTTP2_STREAM_FLAG_NONE,
+ &frame->headers.pri_spec, NGHTTP2_STREAM_INITIAL,
+ aux_data->stream_user_data);
+
+ if (stream == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ /* We don't call nghttp2_session_adjust_closed_stream() here,
+ since we don't keep closed stream in client side */
+
+ rv = session_predicate_request_headers_send(session, item);
+ if (rv != 0) {
+ return rv;
+ }
+
+ if (session_enforce_http_messaging(session)) {
+ nghttp2_http_record_request_method(stream, frame);
+ }
+ } else {
+ nghttp2_stream *stream;
+
+ stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
+
+ if (stream && stream->state == NGHTTP2_STREAM_RESERVED) {
+ rv = session_predicate_push_response_headers_send(session, stream);
+ if (rv == 0) {
+ frame->headers.cat = NGHTTP2_HCAT_PUSH_RESPONSE;
+
+ if (aux_data->stream_user_data) {
+ stream->stream_user_data = aux_data->stream_user_data;
+ }
+ }
+ } else if (session_predicate_response_headers_send(session, stream) ==
+ 0) {
+ frame->headers.cat = NGHTTP2_HCAT_RESPONSE;
+ rv = 0;
+ } else {
+ frame->headers.cat = NGHTTP2_HCAT_HEADERS;
+
+ rv = session_predicate_headers_send(session, stream);
+ }
+
+ if (rv != 0) {
+ return rv;
+ }
+ }
+
+ estimated_payloadlen = session_estimate_headers_payload(
+ session, frame->headers.nva, frame->headers.nvlen,
+ NGHTTP2_PRIORITY_SPECLEN);
+
+ if (estimated_payloadlen > session->max_send_header_block_length) {
+ return NGHTTP2_ERR_FRAME_SIZE_ERROR;
+ }
+
+ rv = nghttp2_frame_pack_headers(&session->aob.framebufs, &frame->headers,
+ &session->hd_deflater);
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ DEBUGF("send: before padding, HEADERS serialized in %zd bytes\n",
+ nghttp2_bufs_len(&session->aob.framebufs));
+
+ rv = session_headers_add_pad(session, frame);
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ DEBUGF("send: HEADERS finally serialized in %zd bytes\n",
+ nghttp2_bufs_len(&session->aob.framebufs));
+
+ if (frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
+ assert(session->last_sent_stream_id < frame->hd.stream_id);
+ session->last_sent_stream_id = frame->hd.stream_id;
+ }
+
+ return 0;
+ }
+ case NGHTTP2_PRIORITY: {
+ if (session_is_closing(session)) {
+ return NGHTTP2_ERR_SESSION_CLOSING;
+ }
+ /* PRIORITY frame can be sent at any time and to any stream
+ ID. */
+ nghttp2_frame_pack_priority(&session->aob.framebufs, &frame->priority);
+
+ /* Peer can send PRIORITY frame against idle stream to create
+ "anchor" in dependency tree. Only client can do this in
+ nghttp2. In nghttp2, only server retains non-active (closed
+ or idle) streams in memory, so we don't open stream here. */
+ return 0;
+ }
+ case NGHTTP2_RST_STREAM:
+ if (session_is_closing(session)) {
+ return NGHTTP2_ERR_SESSION_CLOSING;
+ }
+ nghttp2_frame_pack_rst_stream(&session->aob.framebufs, &frame->rst_stream);
+ return 0;
+ case NGHTTP2_SETTINGS: {
+ if (frame->hd.flags & NGHTTP2_FLAG_ACK) {
+ assert(session->obq_flood_counter_ > 0);
+ --session->obq_flood_counter_;
+ /* When session is about to close, don't send SETTINGS ACK.
+ We are required to send SETTINGS without ACK though; for
+ example, we have to send SETTINGS as a part of connection
+ preface. */
+ if (session_is_closing(session)) {
+ return NGHTTP2_ERR_SESSION_CLOSING;
+ }
+ }
+
+ rv = nghttp2_frame_pack_settings(&session->aob.framebufs, &frame->settings);
+ if (rv != 0) {
+ return rv;
+ }
+ return 0;
+ }
+ case NGHTTP2_PUSH_PROMISE: {
+ nghttp2_stream *stream;
+ size_t estimated_payloadlen;
+
+ /* stream could be NULL if associated stream was already
+ closed. */
+ stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
+
+ /* predicate should fail if stream is NULL. */
+ rv = session_predicate_push_promise_send(session, stream);
+ if (rv != 0) {
+ return rv;
+ }
+
+ assert(stream);
+
+ estimated_payloadlen = session_estimate_headers_payload(
+ session, frame->push_promise.nva, frame->push_promise.nvlen, 0);
+
+ if (estimated_payloadlen > session->max_send_header_block_length) {
+ return NGHTTP2_ERR_FRAME_SIZE_ERROR;
+ }
+
+ rv = nghttp2_frame_pack_push_promise(
+ &session->aob.framebufs, &frame->push_promise, &session->hd_deflater);
+ if (rv != 0) {
+ return rv;
+ }
+ rv = session_headers_add_pad(session, frame);
+ if (rv != 0) {
+ return rv;
+ }
+
+ assert(session->last_sent_stream_id + 2 <=
+ frame->push_promise.promised_stream_id);
+ session->last_sent_stream_id = frame->push_promise.promised_stream_id;
+
+ return 0;
+ }
+ case NGHTTP2_PING:
+ if (frame->hd.flags & NGHTTP2_FLAG_ACK) {
+ assert(session->obq_flood_counter_ > 0);
+ --session->obq_flood_counter_;
+ }
+ /* PING frame is allowed to be sent unless termination GOAWAY is
+ sent */
+ if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) {
+ return NGHTTP2_ERR_SESSION_CLOSING;
+ }
+ nghttp2_frame_pack_ping(&session->aob.framebufs, &frame->ping);
+ return 0;
+ case NGHTTP2_GOAWAY:
+ rv = nghttp2_frame_pack_goaway(&session->aob.framebufs, &frame->goaway);
+ if (rv != 0) {
+ return rv;
+ }
+ session->local_last_stream_id = frame->goaway.last_stream_id;
+
+ return 0;
+ case NGHTTP2_WINDOW_UPDATE:
+ rv = session_predicate_window_update_send(session, frame->hd.stream_id);
+ if (rv != 0) {
+ return rv;
+ }
+ nghttp2_frame_pack_window_update(&session->aob.framebufs,
+ &frame->window_update);
+ return 0;
+ case NGHTTP2_CONTINUATION:
+ /* We never handle CONTINUATION here. */
+ assert(0);
+ return 0;
+ default: {
+ nghttp2_ext_aux_data *aux_data;
+
+ /* extension frame */
+
+ aux_data = &item->aux_data.ext;
+
+ if (aux_data->builtin == 0) {
+ if (session_is_closing(session)) {
+ return NGHTTP2_ERR_SESSION_CLOSING;
+ }
+
+ return session_pack_extension(session, &session->aob.framebufs, frame);
+ }
+
+ switch (frame->hd.type) {
+ case NGHTTP2_ALTSVC:
+ rv = session_predicate_altsvc_send(session, frame->hd.stream_id);
+ if (rv != 0) {
+ return rv;
+ }
+
+ nghttp2_frame_pack_altsvc(&session->aob.framebufs, &frame->ext);
+
+ return 0;
+ default:
+ /* Unreachable here */
+ assert(0);
+ return 0;
+ }
+ }
+ }
+}
+
+nghttp2_outbound_item *
+nghttp2_session_get_next_ob_item(nghttp2_session *session) {
+ if (nghttp2_outbound_queue_top(&session->ob_urgent)) {
+ return nghttp2_outbound_queue_top(&session->ob_urgent);
+ }
+
+ if (nghttp2_outbound_queue_top(&session->ob_reg)) {
+ return nghttp2_outbound_queue_top(&session->ob_reg);
+ }
+
+ if (!session_is_outgoing_concurrent_streams_max(session)) {
+ if (nghttp2_outbound_queue_top(&session->ob_syn)) {
+ return nghttp2_outbound_queue_top(&session->ob_syn);
+ }
+ }
+
+ if (session->remote_window_size > 0) {
+ return nghttp2_stream_next_outbound_item(&session->root);
+ }
+
+ return NULL;
+}
+
+nghttp2_outbound_item *
+nghttp2_session_pop_next_ob_item(nghttp2_session *session) {
+ nghttp2_outbound_item *item;
+
+ item = nghttp2_outbound_queue_top(&session->ob_urgent);
+ if (item) {
+ nghttp2_outbound_queue_pop(&session->ob_urgent);
+ item->queued = 0;
+ return item;
+ }
+
+ item = nghttp2_outbound_queue_top(&session->ob_reg);
+ if (item) {
+ nghttp2_outbound_queue_pop(&session->ob_reg);
+ item->queued = 0;
+ return item;
+ }
+
+ if (!session_is_outgoing_concurrent_streams_max(session)) {
+ item = nghttp2_outbound_queue_top(&session->ob_syn);
+ if (item) {
+ nghttp2_outbound_queue_pop(&session->ob_syn);
+ item->queued = 0;
+ return item;
+ }
+ }
+
+ if (session->remote_window_size > 0) {
+ return nghttp2_stream_next_outbound_item(&session->root);
+ }
+
+ return NULL;
+}
+
+static int session_call_before_frame_send(nghttp2_session *session,
+ nghttp2_frame *frame) {
+ int rv;
+ if (session->callbacks.before_frame_send_callback) {
+ rv = session->callbacks.before_frame_send_callback(session, frame,
+ session->user_data);
+ if (rv == NGHTTP2_ERR_CANCEL) {
+ return rv;
+ }
+
+ if (rv != 0) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+ return 0;
+}
+
+static int session_call_on_frame_send(nghttp2_session *session,
+ nghttp2_frame *frame) {
+ int rv;
+ if (session->callbacks.on_frame_send_callback) {
+ rv = session->callbacks.on_frame_send_callback(session, frame,
+ session->user_data);
+ if (rv != 0) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+ return 0;
+}
+
+static int find_stream_on_goaway_func(nghttp2_map_entry *entry, void *ptr) {
+ nghttp2_close_stream_on_goaway_arg *arg;
+ nghttp2_stream *stream;
+
+ arg = (nghttp2_close_stream_on_goaway_arg *)ptr;
+ stream = (nghttp2_stream *)entry;
+
+ if (nghttp2_session_is_my_stream_id(arg->session, stream->stream_id)) {
+ if (arg->incoming) {
+ return 0;
+ }
+ } else if (!arg->incoming) {
+ return 0;
+ }
+
+ if (stream->state != NGHTTP2_STREAM_IDLE &&
+ (stream->flags & NGHTTP2_STREAM_FLAG_CLOSED) == 0 &&
+ stream->stream_id > arg->last_stream_id) {
+ /* We are collecting streams to close because we cannot call
+ nghttp2_session_close_stream() inside nghttp2_map_each().
+ Reuse closed_next member.. bad choice? */
+ assert(stream->closed_next == NULL);
+ assert(stream->closed_prev == NULL);
+
+ if (arg->head) {
+ stream->closed_next = arg->head;
+ arg->head = stream;
+ } else {
+ arg->head = stream;
+ }
+ }
+
+ return 0;
+}
+
+/* Closes non-idle and non-closed streams whose stream ID >
+ last_stream_id. If incoming is nonzero, we are going to close
+ incoming streams. Otherwise, close outgoing streams. */
+static int session_close_stream_on_goaway(nghttp2_session *session,
+ int32_t last_stream_id,
+ int incoming) {
+ int rv;
+ nghttp2_stream *stream, *next_stream;
+ nghttp2_close_stream_on_goaway_arg arg = {session, NULL, last_stream_id,
+ incoming};
+
+ rv = nghttp2_map_each(&session->streams, find_stream_on_goaway_func, &arg);
+ assert(rv == 0);
+
+ stream = arg.head;
+ while (stream) {
+ next_stream = stream->closed_next;
+ stream->closed_next = NULL;
+ rv = nghttp2_session_close_stream(session, stream->stream_id,
+ NGHTTP2_REFUSED_STREAM);
+
+ /* stream may be deleted here */
+
+ stream = next_stream;
+
+ if (nghttp2_is_fatal(rv)) {
+ /* Clean up closed_next member just in case */
+ while (stream) {
+ next_stream = stream->closed_next;
+ stream->closed_next = NULL;
+ stream = next_stream;
+ }
+ return rv;
+ }
+ }
+
+ return 0;
+}
+
+static void reschedule_stream(nghttp2_stream *stream) {
+ stream->last_writelen = stream->item->frame.hd.length;
+
+ nghttp2_stream_reschedule(stream);
+}
+
+static int session_update_stream_consumed_size(nghttp2_session *session,
+ nghttp2_stream *stream,
+ size_t delta_size);
+
+static int session_update_connection_consumed_size(nghttp2_session *session,
+ size_t delta_size);
+
+static int session_update_recv_connection_window_size(nghttp2_session *session,
+ size_t delta_size);
+
+static int session_update_recv_stream_window_size(nghttp2_session *session,
+ nghttp2_stream *stream,
+ size_t delta_size,
+ int send_window_update);
+
+/*
+ * Called after a frame is sent. This function runs
+ * on_frame_send_callback and handles stream closure upon END_STREAM
+ * or RST_STREAM. This function does not reset session->aob. It is a
+ * responsibility of session_after_frame_sent2.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * The callback function failed.
+ */
+static int session_after_frame_sent1(nghttp2_session *session) {
+ int rv;
+ nghttp2_active_outbound_item *aob = &session->aob;
+ nghttp2_outbound_item *item = aob->item;
+ nghttp2_bufs *framebufs = &aob->framebufs;
+ nghttp2_frame *frame;
+ nghttp2_stream *stream;
+
+ frame = &item->frame;
+
+ if (frame->hd.type == NGHTTP2_DATA) {
+ nghttp2_data_aux_data *aux_data;
+
+ aux_data = &item->aux_data.data;
+
+ stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
+ /* We update flow control window after a frame was completely
+ sent. This is possible because we choose payload length not to
+ exceed the window */
+ session->remote_window_size -= (int32_t)frame->hd.length;
+ if (stream) {
+ stream->remote_window_size -= (int32_t)frame->hd.length;
+ }
+
+ if (stream && aux_data->eof) {
+ rv = nghttp2_stream_detach_item(stream);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ /* Call on_frame_send_callback after
+ nghttp2_stream_detach_item(), so that application can issue
+ nghttp2_submit_data() in the callback. */
+ if (session->callbacks.on_frame_send_callback) {
+ rv = session_call_on_frame_send(session, frame);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+
+ if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
+ int stream_closed;
+
+ stream_closed =
+ (stream->shut_flags & NGHTTP2_SHUT_RDWR) == NGHTTP2_SHUT_RDWR;
+
+ nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
+
+ rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ /* stream may be NULL if it was closed */
+ if (stream_closed) {
+ stream = NULL;
+ }
+ }
+ return 0;
+ }
+
+ if (session->callbacks.on_frame_send_callback) {
+ rv = session_call_on_frame_send(session, frame);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+
+ return 0;
+ }
+
+ /* non-DATA frame */
+
+ if (frame->hd.type == NGHTTP2_HEADERS ||
+ frame->hd.type == NGHTTP2_PUSH_PROMISE) {
+ if (nghttp2_bufs_next_present(framebufs)) {
+ DEBUGF("send: CONTINUATION exists, just return\n");
+ return 0;
+ }
+ }
+ rv = session_call_on_frame_send(session, frame);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ switch (frame->hd.type) {
+ case NGHTTP2_HEADERS: {
+ nghttp2_headers_aux_data *aux_data;
+
+ stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
+ if (!stream) {
+ return 0;
+ }
+
+ switch (frame->headers.cat) {
+ case NGHTTP2_HCAT_REQUEST: {
+ stream->state = NGHTTP2_STREAM_OPENING;
+ if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
+ nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
+ }
+ rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ /* We assume aux_data is a pointer to nghttp2_headers_aux_data */
+ aux_data = &item->aux_data.headers;
+ if (aux_data->data_prd.read_callback) {
+ /* nghttp2_submit_data() makes a copy of aux_data->data_prd */
+ rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM,
+ frame->hd.stream_id, &aux_data->data_prd);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ /* TODO nghttp2_submit_data() may fail if stream has already
+ DATA frame item. We might have to handle it here. */
+ }
+ return 0;
+ }
+ case NGHTTP2_HCAT_PUSH_RESPONSE:
+ stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_PUSH);
+ ++session->num_outgoing_streams;
+ /* Fall through */
+ case NGHTTP2_HCAT_RESPONSE:
+ stream->state = NGHTTP2_STREAM_OPENED;
+ /* Fall through */
+ case NGHTTP2_HCAT_HEADERS:
+ if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
+ nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
+ }
+ rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ /* We assume aux_data is a pointer to nghttp2_headers_aux_data */
+ aux_data = &item->aux_data.headers;
+ if (aux_data->data_prd.read_callback) {
+ rv = nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM,
+ frame->hd.stream_id, &aux_data->data_prd);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ /* TODO nghttp2_submit_data() may fail if stream has already
+ DATA frame item. We might have to handle it here. */
+ }
+ return 0;
+ default:
+ /* Unreachable */
+ assert(0);
+ return 0;
+ }
+ }
+ case NGHTTP2_PRIORITY:
+ if (session->server) {
+ return 0;
+ ;
+ }
+
+ stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id);
+
+ if (!stream) {
+ if (!session_detect_idle_stream(session, frame->hd.stream_id)) {
+ return 0;
+ }
+
+ stream = nghttp2_session_open_stream(
+ session, frame->hd.stream_id, NGHTTP2_FLAG_NONE,
+ &frame->priority.pri_spec, NGHTTP2_STREAM_IDLE, NULL);
+ if (!stream) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+ } else {
+ rv = nghttp2_session_reprioritize_stream(session, stream,
+ &frame->priority.pri_spec);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+
+ rv = nghttp2_session_adjust_idle_stream(session);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ return 0;
+ case NGHTTP2_RST_STREAM:
+ rv = nghttp2_session_close_stream(session, frame->hd.stream_id,
+ frame->rst_stream.error_code);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ return 0;
+ case NGHTTP2_GOAWAY: {
+ nghttp2_goaway_aux_data *aux_data;
+
+ aux_data = &item->aux_data.goaway;
+
+ if ((aux_data->flags & NGHTTP2_GOAWAY_AUX_SHUTDOWN_NOTICE) == 0) {
+
+ if (aux_data->flags & NGHTTP2_GOAWAY_AUX_TERM_ON_SEND) {
+ session->goaway_flags |= NGHTTP2_GOAWAY_TERM_SENT;
+ }
+
+ session->goaway_flags |= NGHTTP2_GOAWAY_SENT;
+
+ rv = session_close_stream_on_goaway(session, frame->goaway.last_stream_id,
+ 1);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+
+ return 0;
+ }
+ case NGHTTP2_WINDOW_UPDATE:
+ if (frame->hd.stream_id == 0) {
+ session->window_update_queued = 0;
+ if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
+ rv = session_update_connection_consumed_size(session, 0);
+ } else {
+ rv = session_update_recv_connection_window_size(session, 0);
+ }
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ return 0;
+ }
+
+ stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
+ if (!stream) {
+ return 0;
+ }
+
+ stream->window_update_queued = 0;
+
+ /* We don't have to send WINDOW_UPDATE if END_STREAM from peer
+ is seen. */
+ if (stream->shut_flags & NGHTTP2_SHUT_RD) {
+ return 0;
+ }
+
+ if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
+ rv = session_update_stream_consumed_size(session, stream, 0);
+ } else {
+ rv = session_update_recv_stream_window_size(session, stream, 0, 1);
+ }
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+/*
+ * Called after a frame is sent and session_after_frame_sent1. This
+ * function is responsible to reset session->aob.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * The callback function failed.
+ */
+static int session_after_frame_sent2(nghttp2_session *session) {
+ int rv;
+ nghttp2_active_outbound_item *aob = &session->aob;
+ nghttp2_outbound_item *item = aob->item;
+ nghttp2_bufs *framebufs = &aob->framebufs;
+ nghttp2_frame *frame;
+ nghttp2_mem *mem;
+ nghttp2_stream *stream;
+ nghttp2_data_aux_data *aux_data;
+
+ mem = &session->mem;
+ frame = &item->frame;
+
+ if (frame->hd.type != NGHTTP2_DATA) {
+
+ if (frame->hd.type == NGHTTP2_HEADERS ||
+ frame->hd.type == NGHTTP2_PUSH_PROMISE) {
+
+ if (nghttp2_bufs_next_present(framebufs)) {
+ framebufs->cur = framebufs->cur->next;
+
+ DEBUGF("send: next CONTINUATION frame, %zu bytes\n",
+ nghttp2_buf_len(&framebufs->cur->buf));
+
+ return 0;
+ }
+ }
+
+ active_outbound_item_reset(&session->aob, mem);
+
+ return 0;
+ }
+
+ /* DATA frame */
+
+ aux_data = &item->aux_data.data;
+
+ /* On EOF, we have already detached data. Please note that
+ application may issue nghttp2_submit_data() in
+ on_frame_send_callback (call from session_after_frame_sent1),
+ which attach data to stream. We don't want to detach it. */
+ if (aux_data->eof) {
+ active_outbound_item_reset(aob, mem);
+
+ return 0;
+ }
+
+ /* Reset no_copy here because next write may not use this. */
+ aux_data->no_copy = 0;
+
+ stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
+
+ /* If session is closed or RST_STREAM was queued, we won't send
+ further data. */
+ if (nghttp2_session_predicate_data_send(session, stream) != 0) {
+ if (stream) {
+ rv = nghttp2_stream_detach_item(stream);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+
+ active_outbound_item_reset(aob, mem);
+
+ return 0;
+ }
+
+ aob->item = NULL;
+ active_outbound_item_reset(&session->aob, mem);
+
+ return 0;
+}
+
+static int session_call_send_data(nghttp2_session *session,
+ nghttp2_outbound_item *item,
+ nghttp2_bufs *framebufs) {
+ int rv;
+ nghttp2_buf *buf;
+ size_t length;
+ nghttp2_frame *frame;
+ nghttp2_data_aux_data *aux_data;
+
+ buf = &framebufs->cur->buf;
+ frame = &item->frame;
+ length = frame->hd.length - frame->data.padlen;
+ aux_data = &item->aux_data.data;
+
+ rv = session->callbacks.send_data_callback(session, frame, buf->pos, length,
+ &aux_data->data_prd.source,
+ session->user_data);
+
+ switch (rv) {
+ case 0:
+ case NGHTTP2_ERR_WOULDBLOCK:
+ case NGHTTP2_ERR_PAUSE:
+ case NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE:
+ return rv;
+ default:
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+}
+
+static ssize_t nghttp2_session_mem_send_internal(nghttp2_session *session,
+ const uint8_t **data_ptr,
+ int fast_cb) {
+ int rv;
+ nghttp2_active_outbound_item *aob;
+ nghttp2_bufs *framebufs;
+ nghttp2_mem *mem;
+
+ mem = &session->mem;
+ aob = &session->aob;
+ framebufs = &aob->framebufs;
+
+ /* We may have idle streams more than we expect (e.g.,
+ nghttp2_session_change_stream_priority() or
+ nghttp2_session_create_idle_stream()). Adjust them here. */
+ rv = nghttp2_session_adjust_idle_stream(session);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ for (;;) {
+ switch (aob->state) {
+ case NGHTTP2_OB_POP_ITEM: {
+ nghttp2_outbound_item *item;
+
+ item = nghttp2_session_pop_next_ob_item(session);
+ if (item == NULL) {
+ return 0;
+ }
+
+ rv = session_prep_frame(session, item);
+ if (rv == NGHTTP2_ERR_PAUSE) {
+ return 0;
+ }
+ if (rv == NGHTTP2_ERR_DEFERRED) {
+ DEBUGF("send: frame transmission deferred\n");
+ break;
+ }
+ if (rv < 0) {
+ int32_t opened_stream_id = 0;
+ uint32_t error_code = NGHTTP2_INTERNAL_ERROR;
+
+ DEBUGF("send: frame preparation failed with %s\n",
+ nghttp2_strerror(rv));
+ /* TODO If the error comes from compressor, the connection
+ must be closed. */
+ if (item->frame.hd.type != NGHTTP2_DATA &&
+ session->callbacks.on_frame_not_send_callback && is_non_fatal(rv)) {
+ nghttp2_frame *frame = &item->frame;
+ /* The library is responsible for the transmission of
+ WINDOW_UPDATE frame, so we don't call error callback for
+ it. */
+ if (frame->hd.type != NGHTTP2_WINDOW_UPDATE &&
+ session->callbacks.on_frame_not_send_callback(
+ session, frame, rv, session->user_data) != 0) {
+
+ nghttp2_outbound_item_free(item, mem);
+ nghttp2_mem_free(mem, item);
+
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+ /* We have to close stream opened by failed request HEADERS
+ or PUSH_PROMISE. */
+ switch (item->frame.hd.type) {
+ case NGHTTP2_HEADERS:
+ if (item->frame.headers.cat == NGHTTP2_HCAT_REQUEST) {
+ opened_stream_id = item->frame.hd.stream_id;
+ if (item->aux_data.headers.canceled) {
+ error_code = item->aux_data.headers.error_code;
+ } else {
+ /* Set error_code to REFUSED_STREAM so that application
+ can send request again. */
+ error_code = NGHTTP2_REFUSED_STREAM;
+ }
+ }
+ break;
+ case NGHTTP2_PUSH_PROMISE:
+ opened_stream_id = item->frame.push_promise.promised_stream_id;
+ break;
+ }
+ if (opened_stream_id) {
+ /* careful not to override rv */
+ int rv2;
+ rv2 = nghttp2_session_close_stream(session, opened_stream_id,
+ error_code);
+
+ if (nghttp2_is_fatal(rv2)) {
+ return rv2;
+ }
+ }
+
+ nghttp2_outbound_item_free(item, mem);
+ nghttp2_mem_free(mem, item);
+ active_outbound_item_reset(aob, mem);
+
+ if (rv == NGHTTP2_ERR_HEADER_COMP) {
+ /* If header compression error occurred, should terminiate
+ connection. */
+ rv = nghttp2_session_terminate_session(session,
+ NGHTTP2_INTERNAL_ERROR);
+ }
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ break;
+ }
+
+ aob->item = item;
+
+ nghttp2_bufs_rewind(framebufs);
+
+ if (item->frame.hd.type != NGHTTP2_DATA) {
+ nghttp2_frame *frame;
+
+ frame = &item->frame;
+
+ DEBUGF("send: next frame: payloadlen=%zu, type=%u, flags=0x%02x, "
+ "stream_id=%d\n",
+ frame->hd.length, frame->hd.type, frame->hd.flags,
+ frame->hd.stream_id);
+
+ rv = session_call_before_frame_send(session, frame);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ if (rv == NGHTTP2_ERR_CANCEL) {
+ int32_t opened_stream_id = 0;
+ uint32_t error_code = NGHTTP2_INTERNAL_ERROR;
+
+ if (session->callbacks.on_frame_not_send_callback) {
+ if (session->callbacks.on_frame_not_send_callback(
+ session, frame, rv, session->user_data) != 0) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+
+ /* We have to close stream opened by canceled request
+ HEADERS or PUSH_PROMISE. */
+ switch (item->frame.hd.type) {
+ case NGHTTP2_HEADERS:
+ if (item->frame.headers.cat == NGHTTP2_HCAT_REQUEST) {
+ opened_stream_id = item->frame.hd.stream_id;
+ /* We don't have to check
+ item->aux_data.headers.canceled since it has already
+ been checked. */
+ /* Set error_code to REFUSED_STREAM so that application
+ can send request again. */
+ error_code = NGHTTP2_REFUSED_STREAM;
+ }
+ break;
+ case NGHTTP2_PUSH_PROMISE:
+ opened_stream_id = item->frame.push_promise.promised_stream_id;
+ break;
+ }
+ if (opened_stream_id) {
+ /* careful not to override rv */
+ int rv2;
+ rv2 = nghttp2_session_close_stream(session, opened_stream_id,
+ error_code);
+
+ if (nghttp2_is_fatal(rv2)) {
+ return rv2;
+ }
+ }
+
+ active_outbound_item_reset(aob, mem);
+
+ break;
+ }
+ } else {
+ DEBUGF("send: next frame: DATA\n");
+
+ if (item->aux_data.data.no_copy) {
+ aob->state = NGHTTP2_OB_SEND_NO_COPY;
+ break;
+ }
+ }
+
+ DEBUGF("send: start transmitting frame type=%u, length=%zd\n",
+ framebufs->cur->buf.pos[3],
+ framebufs->cur->buf.last - framebufs->cur->buf.pos);
+
+ aob->state = NGHTTP2_OB_SEND_DATA;
+
+ break;
+ }
+ case NGHTTP2_OB_SEND_DATA: {
+ size_t datalen;
+ nghttp2_buf *buf;
+
+ buf = &framebufs->cur->buf;
+
+ if (buf->pos == buf->last) {
+ DEBUGF("send: end transmission of a frame\n");
+
+ /* Frame has completely sent */
+ if (fast_cb) {
+ rv = session_after_frame_sent2(session);
+ } else {
+ rv = session_after_frame_sent1(session);
+ if (rv < 0) {
+ /* FATAL */
+ assert(nghttp2_is_fatal(rv));
+ return rv;
+ }
+ rv = session_after_frame_sent2(session);
+ }
+ if (rv < 0) {
+ /* FATAL */
+ assert(nghttp2_is_fatal(rv));
+ return rv;
+ }
+ /* We have already adjusted the next state */
+ break;
+ }
+
+ *data_ptr = buf->pos;
+ datalen = nghttp2_buf_len(buf);
+
+ /* We increment the offset here. If send_callback does not send
+ everything, we will adjust it. */
+ buf->pos += datalen;
+
+ return (ssize_t)datalen;
+ }
+ case NGHTTP2_OB_SEND_NO_COPY: {
+ nghttp2_stream *stream;
+ nghttp2_frame *frame;
+ int pause;
+
+ DEBUGF("send: no copy DATA\n");
+
+ frame = &aob->item->frame;
+
+ stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
+ if (stream == NULL) {
+ DEBUGF("send: no copy DATA cancelled because stream was closed\n");
+
+ active_outbound_item_reset(aob, mem);
+
+ break;
+ }
+
+ rv = session_call_send_data(session, aob->item, framebufs);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
+ rv = nghttp2_stream_detach_item(stream);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ rv = nghttp2_session_add_rst_stream(session, frame->hd.stream_id,
+ NGHTTP2_INTERNAL_ERROR);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ active_outbound_item_reset(aob, mem);
+
+ break;
+ }
+
+ if (rv == NGHTTP2_ERR_WOULDBLOCK) {
+ return 0;
+ }
+
+ pause = (rv == NGHTTP2_ERR_PAUSE);
+
+ rv = session_after_frame_sent1(session);
+ if (rv < 0) {
+ assert(nghttp2_is_fatal(rv));
+ return rv;
+ }
+ rv = session_after_frame_sent2(session);
+ if (rv < 0) {
+ assert(nghttp2_is_fatal(rv));
+ return rv;
+ }
+
+ /* We have already adjusted the next state */
+
+ if (pause) {
+ return 0;
+ }
+
+ break;
+ }
+ case NGHTTP2_OB_SEND_CLIENT_MAGIC: {
+ size_t datalen;
+ nghttp2_buf *buf;
+
+ buf = &framebufs->cur->buf;
+
+ if (buf->pos == buf->last) {
+ DEBUGF("send: end transmission of client magic\n");
+ active_outbound_item_reset(aob, mem);
+ break;
+ }
+
+ *data_ptr = buf->pos;
+ datalen = nghttp2_buf_len(buf);
+
+ buf->pos += datalen;
+
+ return (ssize_t)datalen;
+ }
+ }
+ }
+}
+
+ssize_t nghttp2_session_mem_send(nghttp2_session *session,
+ const uint8_t **data_ptr) {
+ int rv;
+ ssize_t len;
+
+ *data_ptr = NULL;
+
+ len = nghttp2_session_mem_send_internal(session, data_ptr, 1);
+ if (len <= 0) {
+ return len;
+ }
+
+ if (session->aob.item) {
+ /* We have to call session_after_frame_sent1 here to handle stream
+ closure upon transmission of frames. Otherwise, END_STREAM may
+ be reached to client before we call nghttp2_session_mem_send
+ again and we may get exceeding number of incoming streams. */
+ rv = session_after_frame_sent1(session);
+ if (rv < 0) {
+ assert(nghttp2_is_fatal(rv));
+ return (ssize_t)rv;
+ }
+ }
+
+ return len;
+}
+
+int nghttp2_session_send(nghttp2_session *session) {
+ const uint8_t *data = NULL;
+ ssize_t datalen;
+ ssize_t sentlen;
+ nghttp2_bufs *framebufs;
+
+ framebufs = &session->aob.framebufs;
+
+ for (;;) {
+ datalen = nghttp2_session_mem_send_internal(session, &data, 0);
+ if (datalen <= 0) {
+ return (int)datalen;
+ }
+ sentlen = session->callbacks.send_callback(session, data, (size_t)datalen,
+ 0, session->user_data);
+ if (sentlen < 0) {
+ if (sentlen == NGHTTP2_ERR_WOULDBLOCK) {
+ /* Transmission canceled. Rewind the offset */
+ framebufs->cur->buf.pos -= datalen;
+
+ return 0;
+ }
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ /* Rewind the offset to the amount of unsent bytes */
+ framebufs->cur->buf.pos -= datalen - sentlen;
+ }
+}
+
+static ssize_t session_recv(nghttp2_session *session, uint8_t *buf,
+ size_t len) {
+ ssize_t rv;
+ rv = session->callbacks.recv_callback(session, buf, len, 0,
+ session->user_data);
+ if (rv > 0) {
+ if ((size_t)rv > len) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ } else if (rv < 0 && rv != NGHTTP2_ERR_WOULDBLOCK && rv != NGHTTP2_ERR_EOF) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ return rv;
+}
+
+static int session_call_on_begin_frame(nghttp2_session *session,
+ const nghttp2_frame_hd *hd) {
+ int rv;
+
+ if (session->callbacks.on_begin_frame_callback) {
+
+ rv = session->callbacks.on_begin_frame_callback(session, hd,
+ session->user_data);
+
+ if (rv != 0) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+
+ return 0;
+}
+
+static int session_call_on_frame_received(nghttp2_session *session,
+ nghttp2_frame *frame) {
+ int rv;
+ if (session->callbacks.on_frame_recv_callback) {
+ rv = session->callbacks.on_frame_recv_callback(session, frame,
+ session->user_data);
+ if (rv != 0) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+ return 0;
+}
+
+static int session_call_on_begin_headers(nghttp2_session *session,
+ nghttp2_frame *frame) {
+ int rv;
+ DEBUGF("recv: call on_begin_headers callback stream_id=%d\n",
+ frame->hd.stream_id);
+ if (session->callbacks.on_begin_headers_callback) {
+ rv = session->callbacks.on_begin_headers_callback(session, frame,
+ session->user_data);
+ if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
+ return rv;
+ }
+ if (rv != 0) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+ return 0;
+}
+
+static int session_call_on_header(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ const nghttp2_hd_nv *nv) {
+ int rv = 0;
+ if (session->callbacks.on_header_callback2) {
+ rv = session->callbacks.on_header_callback2(
+ session, frame, nv->name, nv->value, nv->flags, session->user_data);
+ } else if (session->callbacks.on_header_callback) {
+ rv = session->callbacks.on_header_callback(
+ session, frame, nv->name->base, nv->name->len, nv->value->base,
+ nv->value->len, nv->flags, session->user_data);
+ }
+
+ if (rv == NGHTTP2_ERR_PAUSE || rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
+ return rv;
+ }
+ if (rv != 0) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+static int session_call_on_invalid_header(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ const nghttp2_hd_nv *nv) {
+ int rv;
+ if (session->callbacks.on_invalid_header_callback2) {
+ rv = session->callbacks.on_invalid_header_callback2(
+ session, frame, nv->name, nv->value, nv->flags, session->user_data);
+ } else if (session->callbacks.on_invalid_header_callback) {
+ rv = session->callbacks.on_invalid_header_callback(
+ session, frame, nv->name->base, nv->name->len, nv->value->base,
+ nv->value->len, nv->flags, session->user_data);
+ } else {
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
+
+ if (rv == NGHTTP2_ERR_PAUSE || rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
+ return rv;
+ }
+ if (rv != 0) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+static int
+session_call_on_extension_chunk_recv_callback(nghttp2_session *session,
+ const uint8_t *data, size_t len) {
+ int rv;
+ nghttp2_inbound_frame *iframe = &session->iframe;
+ nghttp2_frame *frame = &iframe->frame;
+
+ if (session->callbacks.on_extension_chunk_recv_callback) {
+ rv = session->callbacks.on_extension_chunk_recv_callback(
+ session, &frame->hd, data, len, session->user_data);
+ if (rv == NGHTTP2_ERR_CANCEL) {
+ return rv;
+ }
+ if (rv != 0) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+
+ return 0;
+}
+
+static int session_call_unpack_extension_callback(nghttp2_session *session) {
+ int rv;
+ nghttp2_inbound_frame *iframe = &session->iframe;
+ nghttp2_frame *frame = &iframe->frame;
+ void *payload = NULL;
+
+ rv = session->callbacks.unpack_extension_callback(
+ session, &payload, &frame->hd, session->user_data);
+ if (rv == NGHTTP2_ERR_CANCEL) {
+ return rv;
+ }
+ if (rv != 0) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ frame->ext.payload = payload;
+
+ return 0;
+}
+
+/*
+ * Handles frame size error.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+static int session_handle_frame_size_error(nghttp2_session *session) {
+ /* TODO Currently no callback is called for this error, because we
+ call this callback before reading any payload */
+ return nghttp2_session_terminate_session(session, NGHTTP2_FRAME_SIZE_ERROR);
+}
+
+static uint32_t get_error_code_from_lib_error_code(int lib_error_code) {
+ switch (lib_error_code) {
+ case NGHTTP2_ERR_STREAM_CLOSED:
+ return NGHTTP2_STREAM_CLOSED;
+ case NGHTTP2_ERR_HEADER_COMP:
+ return NGHTTP2_COMPRESSION_ERROR;
+ case NGHTTP2_ERR_FRAME_SIZE_ERROR:
+ return NGHTTP2_FRAME_SIZE_ERROR;
+ case NGHTTP2_ERR_FLOW_CONTROL:
+ return NGHTTP2_FLOW_CONTROL_ERROR;
+ case NGHTTP2_ERR_REFUSED_STREAM:
+ return NGHTTP2_REFUSED_STREAM;
+ case NGHTTP2_ERR_PROTO:
+ case NGHTTP2_ERR_HTTP_HEADER:
+ case NGHTTP2_ERR_HTTP_MESSAGING:
+ return NGHTTP2_PROTOCOL_ERROR;
+ default:
+ return NGHTTP2_INTERNAL_ERROR;
+ }
+}
+
+/*
+ * Calls on_invalid_frame_recv_callback if it is set to |session|.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * User defined callback function fails.
+ */
+static int session_call_on_invalid_frame_recv_callback(nghttp2_session *session,
+ nghttp2_frame *frame,
+ int lib_error_code) {
+ if (session->callbacks.on_invalid_frame_recv_callback) {
+ if (session->callbacks.on_invalid_frame_recv_callback(
+ session, frame, lib_error_code, session->user_data) != 0) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+ return 0;
+}
+
+static int session_handle_invalid_stream2(nghttp2_session *session,
+ int32_t stream_id,
+ nghttp2_frame *frame,
+ int lib_error_code) {
+ int rv;
+ rv = nghttp2_session_add_rst_stream(
+ session, stream_id, get_error_code_from_lib_error_code(lib_error_code));
+ if (rv != 0) {
+ return rv;
+ }
+ if (session->callbacks.on_invalid_frame_recv_callback) {
+ if (session->callbacks.on_invalid_frame_recv_callback(
+ session, frame, lib_error_code, session->user_data) != 0) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+ return 0;
+}
+
+static int session_handle_invalid_stream(nghttp2_session *session,
+ nghttp2_frame *frame,
+ int lib_error_code) {
+ return session_handle_invalid_stream2(session, frame->hd.stream_id, frame,
+ lib_error_code);
+}
+
+static int session_inflate_handle_invalid_stream(nghttp2_session *session,
+ nghttp2_frame *frame,
+ int lib_error_code) {
+ int rv;
+ rv = session_handle_invalid_stream(session, frame, lib_error_code);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ return NGHTTP2_ERR_IGN_HEADER_BLOCK;
+}
+
+/*
+ * Handles invalid frame which causes connection error.
+ */
+static int session_handle_invalid_connection(nghttp2_session *session,
+ nghttp2_frame *frame,
+ int lib_error_code,
+ const char *reason) {
+ if (session->callbacks.on_invalid_frame_recv_callback) {
+ if (session->callbacks.on_invalid_frame_recv_callback(
+ session, frame, lib_error_code, session->user_data) != 0) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+ return nghttp2_session_terminate_session_with_reason(
+ session, get_error_code_from_lib_error_code(lib_error_code), reason);
+}
+
+static int session_inflate_handle_invalid_connection(nghttp2_session *session,
+ nghttp2_frame *frame,
+ int lib_error_code,
+ const char *reason) {
+ int rv;
+ rv =
+ session_handle_invalid_connection(session, frame, lib_error_code, reason);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ return NGHTTP2_ERR_IGN_HEADER_BLOCK;
+}
+
+/*
+ * Inflates header block in the memory pointed by |in| with |inlen|
+ * bytes. If this function returns NGHTTP2_ERR_PAUSE, the caller must
+ * call this function again, until it returns 0 or one of negative
+ * error code. If |call_header_cb| is zero, the on_header_callback
+ * are not invoked and the function never return NGHTTP2_ERR_PAUSE. If
+ * the given |in| is the last chunk of header block, the |final| must
+ * be nonzero. If header block is successfully processed (which is
+ * indicated by the return value 0, NGHTTP2_ERR_PAUSE or
+ * NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE), the number of processed
+ * input bytes is assigned to the |*readlen_ptr|.
+ *
+ * This function return 0 if it succeeds, or one of the negative error
+ * codes:
+ *
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * The callback function failed.
+ * NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE
+ * The callback returns this error code, indicating that this
+ * stream should be RST_STREAMed.
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_PAUSE
+ * The callback function returned NGHTTP2_ERR_PAUSE
+ * NGHTTP2_ERR_HEADER_COMP
+ * Header decompression failed
+ */
+static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
+ size_t *readlen_ptr, uint8_t *in, size_t inlen,
+ int final, int call_header_cb) {
+ ssize_t proclen;
+ int rv;
+ int inflate_flags;
+ nghttp2_hd_nv nv;
+ nghttp2_stream *stream;
+ nghttp2_stream *subject_stream;
+ int trailer = 0;
+
+ *readlen_ptr = 0;
+ stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
+
+ if (frame->hd.type == NGHTTP2_PUSH_PROMISE) {
+ subject_stream = nghttp2_session_get_stream(
+ session, frame->push_promise.promised_stream_id);
+ } else {
+ subject_stream = stream;
+ trailer = session_trailer_headers(session, stream, frame);
+ }
+
+ DEBUGF("recv: decoding header block %zu bytes\n", inlen);
+ for (;;) {
+ inflate_flags = 0;
+ proclen = nghttp2_hd_inflate_hd_nv(&session->hd_inflater, &nv,
+ &inflate_flags, in, inlen, final);
+ if (nghttp2_is_fatal((int)proclen)) {
+ return (int)proclen;
+ }
+ if (proclen < 0) {
+ if (session->iframe.state == NGHTTP2_IB_READ_HEADER_BLOCK) {
+ if (subject_stream && subject_stream->state != NGHTTP2_STREAM_CLOSING) {
+ /* Adding RST_STREAM here is very important. It prevents
+ from invoking subsequent callbacks for the same stream
+ ID. */
+ rv = nghttp2_session_add_rst_stream(
+ session, subject_stream->stream_id, NGHTTP2_COMPRESSION_ERROR);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+ }
+ rv =
+ nghttp2_session_terminate_session(session, NGHTTP2_COMPRESSION_ERROR);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ return NGHTTP2_ERR_HEADER_COMP;
+ }
+ in += proclen;
+ inlen -= (size_t)proclen;
+ *readlen_ptr += (size_t)proclen;
+
+ DEBUGF("recv: proclen=%zd\n", proclen);
+
+ if (call_header_cb && (inflate_flags & NGHTTP2_HD_INFLATE_EMIT)) {
+ rv = 0;
+ if (subject_stream && session_enforce_http_messaging(session)) {
+ rv = nghttp2_http_on_header(session, subject_stream, frame, &nv,
+ trailer);
+
+ if (rv == NGHTTP2_ERR_IGN_HTTP_HEADER) {
+ /* Don't overwrite rv here */
+ int rv2;
+
+ rv2 = session_call_on_invalid_header(session, frame, &nv);
+ if (rv2 == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
+ rv = NGHTTP2_ERR_HTTP_HEADER;
+ } else {
+ if (rv2 != 0) {
+ return rv2;
+ }
+
+ /* header is ignored */
+ DEBUGF("recv: HTTP ignored: type=%u, id=%d, header %.*s: %.*s\n",
+ frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
+ nv.name->base, (int)nv.value->len, nv.value->base);
+
+ rv2 = session_call_error_callback(
+ session, NGHTTP2_ERR_HTTP_HEADER,
+ "Ignoring received invalid HTTP header field: frame type: "
+ "%u, stream: %d, name: [%.*s], value: [%.*s]",
+ frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
+ nv.name->base, (int)nv.value->len, nv.value->base);
+
+ if (nghttp2_is_fatal(rv2)) {
+ return rv2;
+ }
+ }
+ }
+
+ if (rv == NGHTTP2_ERR_HTTP_HEADER) {
+ DEBUGF("recv: HTTP error: type=%u, id=%d, header %.*s: %.*s\n",
+ frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
+ nv.name->base, (int)nv.value->len, nv.value->base);
+
+ rv = session_call_error_callback(
+ session, NGHTTP2_ERR_HTTP_HEADER,
+ "Invalid HTTP header field was received: frame type: "
+ "%u, stream: %d, name: [%.*s], value: [%.*s]",
+ frame->hd.type, frame->hd.stream_id, (int)nv.name->len,
+ nv.name->base, (int)nv.value->len, nv.value->base);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ rv =
+ session_handle_invalid_stream2(session, subject_stream->stream_id,
+ frame, NGHTTP2_ERR_HTTP_HEADER);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
+ }
+ if (rv == 0) {
+ rv = session_call_on_header(session, frame, &nv);
+ /* This handles NGHTTP2_ERR_PAUSE and
+ NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE as well */
+ if (rv != 0) {
+ return rv;
+ }
+ }
+ }
+ if (inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
+ nghttp2_hd_inflate_end_headers(&session->hd_inflater);
+ break;
+ }
+ if ((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 && inlen == 0) {
+ break;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Call this function when HEADERS frame was completely received.
+ *
+ * This function returns 0 if it succeeds, or one of negative error
+ * codes:
+ *
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * The callback function failed.
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+static int session_end_stream_headers_received(nghttp2_session *session,
+ nghttp2_frame *frame,
+ nghttp2_stream *stream) {
+ int rv;
+ if ((frame->hd.flags & NGHTTP2_FLAG_END_STREAM) == 0) {
+ return 0;
+ }
+
+ nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
+ rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ return 0;
+}
+
+static int session_after_header_block_received(nghttp2_session *session) {
+ int rv = 0;
+ int call_cb = 1;
+ nghttp2_frame *frame = &session->iframe.frame;
+ nghttp2_stream *stream;
+
+ /* We don't call on_frame_recv_callback if stream has been closed
+ already or being closed. */
+ stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
+ if (!stream || stream->state == NGHTTP2_STREAM_CLOSING) {
+ return 0;
+ }
+
+ if (session_enforce_http_messaging(session)) {
+ if (frame->hd.type == NGHTTP2_PUSH_PROMISE) {
+ nghttp2_stream *subject_stream;
+
+ subject_stream = nghttp2_session_get_stream(
+ session, frame->push_promise.promised_stream_id);
+ if (subject_stream) {
+ rv = nghttp2_http_on_request_headers(subject_stream, frame);
+ }
+ } else {
+ assert(frame->hd.type == NGHTTP2_HEADERS);
+ switch (frame->headers.cat) {
+ case NGHTTP2_HCAT_REQUEST:
+ rv = nghttp2_http_on_request_headers(stream, frame);
+ break;
+ case NGHTTP2_HCAT_RESPONSE:
+ case NGHTTP2_HCAT_PUSH_RESPONSE:
+ rv = nghttp2_http_on_response_headers(stream);
+ break;
+ case NGHTTP2_HCAT_HEADERS:
+ if (stream->http_flags & NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE) {
+ assert(!session->server);
+ rv = nghttp2_http_on_response_headers(stream);
+ } else {
+ rv = nghttp2_http_on_trailer_headers(stream, frame);
+ }
+ break;
+ default:
+ assert(0);
+ }
+ if (rv == 0 && (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) {
+ rv = nghttp2_http_on_remote_end_stream(stream);
+ }
+ }
+ if (rv != 0) {
+ int32_t stream_id;
+
+ if (frame->hd.type == NGHTTP2_PUSH_PROMISE) {
+ stream_id = frame->push_promise.promised_stream_id;
+ } else {
+ stream_id = frame->hd.stream_id;
+ }
+
+ call_cb = 0;
+
+ rv = session_handle_invalid_stream2(session, stream_id, frame,
+ NGHTTP2_ERR_HTTP_MESSAGING);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+ }
+
+ if (call_cb) {
+ rv = session_call_on_frame_received(session, frame);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+
+ if (frame->hd.type != NGHTTP2_HEADERS) {
+ return 0;
+ }
+
+ return session_end_stream_headers_received(session, frame, stream);
+}
+
+int nghttp2_session_on_request_headers_received(nghttp2_session *session,
+ nghttp2_frame *frame) {
+ int rv = 0;
+ nghttp2_stream *stream;
+ if (frame->hd.stream_id == 0) {
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO, "request HEADERS: stream_id == 0");
+ }
+
+ /* If client receives idle stream from server, it is invalid
+ regardless stream ID is even or odd. This is because client is
+ not expected to receive request from server. */
+ if (!session->server) {
+ if (session_detect_idle_stream(session, frame->hd.stream_id)) {
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO,
+ "request HEADERS: client received request");
+ }
+
+ return NGHTTP2_ERR_IGN_HEADER_BLOCK;
+ }
+
+ assert(session->server);
+
+ if (!session_is_new_peer_stream_id(session, frame->hd.stream_id)) {
+ if (frame->hd.stream_id == 0 ||
+ nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) {
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO,
+ "request HEADERS: invalid stream_id");
+ }
+
+ /* RFC 7540 says if an endpoint receives a HEADERS with invalid
+ * stream ID (e.g, numerically smaller than previous), it MUST
+ * issue connection error with error code PROTOCOL_ERROR. It is a
+ * bit hard to detect this, since we cannot remember all streams
+ * we observed so far.
+ *
+ * You might imagine this is really easy. But no. HTTP/2 is
+ * asynchronous protocol, and usually client and server do not
+ * share the complete picture of open/closed stream status. For
+ * example, after server sends RST_STREAM for a stream, client may
+ * send trailer HEADERS for that stream. If naive server detects
+ * that, and issued connection error, then it is a bug of server
+ * implementation since client is not wrong if it did not get
+ * RST_STREAM when it issued trailer HEADERS.
+ *
+ * At the moment, we are very conservative here. We only use
+ * connection error if stream ID refers idle stream, or we are
+ * sure that stream is half-closed(remote) or closed. Otherwise
+ * we just ignore HEADERS for now.
+ */
+ stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id);
+ if (stream && (stream->shut_flags & NGHTTP2_SHUT_RD)) {
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_STREAM_CLOSED, "HEADERS: stream closed");
+ }
+
+ return NGHTTP2_ERR_IGN_HEADER_BLOCK;
+ }
+ session->last_recv_stream_id = frame->hd.stream_id;
+
+ if (session_is_incoming_concurrent_streams_max(session)) {
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO,
+ "request HEADERS: max concurrent streams exceeded");
+ }
+
+ if (!session_allow_incoming_new_stream(session)) {
+ /* We just ignore stream after GOAWAY was sent */
+ return NGHTTP2_ERR_IGN_HEADER_BLOCK;
+ }
+
+ if (frame->headers.pri_spec.stream_id == frame->hd.stream_id) {
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO, "request HEADERS: depend on itself");
+ }
+
+ if (session_is_incoming_concurrent_streams_pending_max(session)) {
+ return session_inflate_handle_invalid_stream(session, frame,
+ NGHTTP2_ERR_REFUSED_STREAM);
+ }
+
+ stream = nghttp2_session_open_stream(
+ session, frame->hd.stream_id, NGHTTP2_STREAM_FLAG_NONE,
+ &frame->headers.pri_spec, NGHTTP2_STREAM_OPENING, NULL);
+ if (!stream) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ rv = nghttp2_session_adjust_closed_stream(session);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ session->last_proc_stream_id = session->last_recv_stream_id;
+
+ rv = session_call_on_begin_headers(session, frame);
+ if (rv != 0) {
+ return rv;
+ }
+ return 0;
+}
+
+int nghttp2_session_on_response_headers_received(nghttp2_session *session,
+ nghttp2_frame *frame,
+ nghttp2_stream *stream) {
+ int rv;
+ /* This function is only called if stream->state ==
+ NGHTTP2_STREAM_OPENING and stream_id is local side initiated. */
+ assert(stream->state == NGHTTP2_STREAM_OPENING &&
+ nghttp2_session_is_my_stream_id(session, frame->hd.stream_id));
+ if (frame->hd.stream_id == 0) {
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO, "response HEADERS: stream_id == 0");
+ }
+ if (stream->shut_flags & NGHTTP2_SHUT_RD) {
+ /* half closed (remote): from the spec:
+
+ If an endpoint receives additional frames for a stream that is
+ in this state it MUST respond with a stream error (Section
+ 5.4.2) of type STREAM_CLOSED.
+
+ We go further, and make it connection error.
+ */
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_STREAM_CLOSED, "HEADERS: stream closed");
+ }
+ stream->state = NGHTTP2_STREAM_OPENED;
+ rv = session_call_on_begin_headers(session, frame);
+ if (rv != 0) {
+ return rv;
+ }
+ return 0;
+}
+
+int nghttp2_session_on_push_response_headers_received(nghttp2_session *session,
+ nghttp2_frame *frame,
+ nghttp2_stream *stream) {
+ int rv = 0;
+ assert(stream->state == NGHTTP2_STREAM_RESERVED);
+ if (frame->hd.stream_id == 0) {
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO,
+ "push response HEADERS: stream_id == 0");
+ }
+
+ if (session->server) {
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO,
+ "HEADERS: no HEADERS allowed from client in reserved state");
+ }
+
+ if (session_is_incoming_concurrent_streams_max(session)) {
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO,
+ "push response HEADERS: max concurrent streams exceeded");
+ }
+
+ if (!session_allow_incoming_new_stream(session)) {
+ /* We don't accept new stream after GOAWAY was sent. */
+ return NGHTTP2_ERR_IGN_HEADER_BLOCK;
+ }
+
+ if (session_is_incoming_concurrent_streams_pending_max(session)) {
+ return session_inflate_handle_invalid_stream(session, frame,
+ NGHTTP2_ERR_REFUSED_STREAM);
+ }
+
+ nghttp2_stream_promise_fulfilled(stream);
+ if (!nghttp2_session_is_my_stream_id(session, stream->stream_id)) {
+ --session->num_incoming_reserved_streams;
+ }
+ ++session->num_incoming_streams;
+ rv = session_call_on_begin_headers(session, frame);
+ if (rv != 0) {
+ return rv;
+ }
+ return 0;
+}
+
+int nghttp2_session_on_headers_received(nghttp2_session *session,
+ nghttp2_frame *frame,
+ nghttp2_stream *stream) {
+ int rv = 0;
+ if (frame->hd.stream_id == 0) {
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO, "HEADERS: stream_id == 0");
+ }
+ if ((stream->shut_flags & NGHTTP2_SHUT_RD)) {
+ /* half closed (remote): from the spec:
+
+ If an endpoint receives additional frames for a stream that is
+ in this state it MUST respond with a stream error (Section
+ 5.4.2) of type STREAM_CLOSED.
+
+ we go further, and make it connection error.
+ */
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_STREAM_CLOSED, "HEADERS: stream closed");
+ }
+ if (nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) {
+ if (stream->state == NGHTTP2_STREAM_OPENED) {
+ rv = session_call_on_begin_headers(session, frame);
+ if (rv != 0) {
+ return rv;
+ }
+ return 0;
+ }
+
+ return NGHTTP2_ERR_IGN_HEADER_BLOCK;
+ }
+ /* If this is remote peer initiated stream, it is OK unless it
+ has sent END_STREAM frame already. But if stream is in
+ NGHTTP2_STREAM_CLOSING, we discard the frame. This is a race
+ condition. */
+ if (stream->state != NGHTTP2_STREAM_CLOSING) {
+ rv = session_call_on_begin_headers(session, frame);
+ if (rv != 0) {
+ return rv;
+ }
+ return 0;
+ }
+ return NGHTTP2_ERR_IGN_HEADER_BLOCK;
+}
+
+static int session_process_headers_frame(nghttp2_session *session) {
+ int rv;
+ nghttp2_inbound_frame *iframe = &session->iframe;
+ nghttp2_frame *frame = &iframe->frame;
+ nghttp2_stream *stream;
+
+ rv = nghttp2_frame_unpack_headers_payload(&frame->headers, iframe->sbuf.pos);
+
+ if (rv != 0) {
+ return nghttp2_session_terminate_session_with_reason(
+ session, NGHTTP2_PROTOCOL_ERROR, "HEADERS: could not unpack");
+ }
+ stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
+ if (!stream) {
+ frame->headers.cat = NGHTTP2_HCAT_REQUEST;
+ return nghttp2_session_on_request_headers_received(session, frame);
+ }
+
+ if (stream->state == NGHTTP2_STREAM_RESERVED) {
+ frame->headers.cat = NGHTTP2_HCAT_PUSH_RESPONSE;
+ return nghttp2_session_on_push_response_headers_received(session, frame,
+ stream);
+ }
+
+ if (stream->state == NGHTTP2_STREAM_OPENING &&
+ nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) {
+ frame->headers.cat = NGHTTP2_HCAT_RESPONSE;
+ return nghttp2_session_on_response_headers_received(session, frame, stream);
+ }
+
+ frame->headers.cat = NGHTTP2_HCAT_HEADERS;
+ return nghttp2_session_on_headers_received(session, frame, stream);
+}
+
+int nghttp2_session_on_priority_received(nghttp2_session *session,
+ nghttp2_frame *frame) {
+ int rv;
+ nghttp2_stream *stream;
+
+ if (frame->hd.stream_id == 0) {
+ return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
+ "PRIORITY: stream_id == 0");
+ }
+
+ if (frame->priority.pri_spec.stream_id == frame->hd.stream_id) {
+ return nghttp2_session_terminate_session_with_reason(
+ session, NGHTTP2_PROTOCOL_ERROR, "depend on itself");
+ }
+
+ if (!session->server) {
+ /* Re-prioritization works only in server */
+ return session_call_on_frame_received(session, frame);
+ }
+
+ stream = nghttp2_session_get_stream_raw(session, frame->hd.stream_id);
+
+ if (!stream) {
+ /* PRIORITY against idle stream can create anchor node in
+ dependency tree. */
+ if (!session_detect_idle_stream(session, frame->hd.stream_id)) {
+ return 0;
+ }
+
+ stream = nghttp2_session_open_stream(
+ session, frame->hd.stream_id, NGHTTP2_STREAM_FLAG_NONE,
+ &frame->priority.pri_spec, NGHTTP2_STREAM_IDLE, NULL);
+
+ if (stream == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ rv = nghttp2_session_adjust_idle_stream(session);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ } else {
+ rv = nghttp2_session_reprioritize_stream(session, stream,
+ &frame->priority.pri_spec);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ rv = nghttp2_session_adjust_idle_stream(session);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+
+ return session_call_on_frame_received(session, frame);
+}
+
+static int session_process_priority_frame(nghttp2_session *session) {
+ nghttp2_inbound_frame *iframe = &session->iframe;
+ nghttp2_frame *frame = &iframe->frame;
+
+ nghttp2_frame_unpack_priority_payload(&frame->priority, iframe->sbuf.pos);
+
+ return nghttp2_session_on_priority_received(session, frame);
+}
+
+int nghttp2_session_on_rst_stream_received(nghttp2_session *session,
+ nghttp2_frame *frame) {
+ int rv;
+ nghttp2_stream *stream;
+ if (frame->hd.stream_id == 0) {
+ return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
+ "RST_STREAM: stream_id == 0");
+ }
+
+ if (session_detect_idle_stream(session, frame->hd.stream_id)) {
+ return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
+ "RST_STREAM: stream in idle");
+ }
+
+ stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
+ if (stream) {
+ /* We may use stream->shut_flags for strict error checking. */
+ nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
+ }
+
+ rv = session_call_on_frame_received(session, frame);
+ if (rv != 0) {
+ return rv;
+ }
+ rv = nghttp2_session_close_stream(session, frame->hd.stream_id,
+ frame->rst_stream.error_code);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ return 0;
+}
+
+static int session_process_rst_stream_frame(nghttp2_session *session) {
+ nghttp2_inbound_frame *iframe = &session->iframe;
+ nghttp2_frame *frame = &iframe->frame;
+
+ nghttp2_frame_unpack_rst_stream_payload(&frame->rst_stream, iframe->sbuf.pos);
+
+ return nghttp2_session_on_rst_stream_received(session, frame);
+}
+
+static int update_remote_initial_window_size_func(nghttp2_map_entry *entry,
+ void *ptr) {
+ int rv;
+ nghttp2_update_window_size_arg *arg;
+ nghttp2_stream *stream;
+
+ arg = (nghttp2_update_window_size_arg *)ptr;
+ stream = (nghttp2_stream *)entry;
+
+ rv = nghttp2_stream_update_remote_initial_window_size(
+ stream, arg->new_window_size, arg->old_window_size);
+ if (rv != 0) {
+ return nghttp2_session_add_rst_stream(arg->session, stream->stream_id,
+ NGHTTP2_FLOW_CONTROL_ERROR);
+ }
+
+ /* If window size gets positive, push deferred DATA frame to
+ outbound queue. */
+ if (stream->remote_window_size > 0 &&
+ nghttp2_stream_check_deferred_by_flow_control(stream)) {
+
+ rv = nghttp2_stream_resume_deferred_item(
+ stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Updates the remote initial window size of all active streams. If
+ * error occurs, all streams may not be updated.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+static int
+session_update_remote_initial_window_size(nghttp2_session *session,
+ int32_t new_initial_window_size) {
+ nghttp2_update_window_size_arg arg;
+
+ arg.session = session;
+ arg.new_window_size = new_initial_window_size;
+ arg.old_window_size = (int32_t)session->remote_settings.initial_window_size;
+
+ return nghttp2_map_each(&session->streams,
+ update_remote_initial_window_size_func, &arg);
+}
+
+static int update_local_initial_window_size_func(nghttp2_map_entry *entry,
+ void *ptr) {
+ int rv;
+ nghttp2_update_window_size_arg *arg;
+ nghttp2_stream *stream;
+ arg = (nghttp2_update_window_size_arg *)ptr;
+ stream = (nghttp2_stream *)entry;
+ rv = nghttp2_stream_update_local_initial_window_size(
+ stream, arg->new_window_size, arg->old_window_size);
+ if (rv != 0) {
+ return nghttp2_session_add_rst_stream(arg->session, stream->stream_id,
+ NGHTTP2_FLOW_CONTROL_ERROR);
+ }
+ if (!(arg->session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) &&
+ stream->window_update_queued == 0 &&
+ nghttp2_should_send_window_update(stream->local_window_size,
+ stream->recv_window_size)) {
+
+ rv = nghttp2_session_add_window_update(arg->session, NGHTTP2_FLAG_NONE,
+ stream->stream_id,
+ stream->recv_window_size);
+ if (rv != 0) {
+ return rv;
+ }
+
+ stream->recv_window_size = 0;
+ }
+ return 0;
+}
+
+/*
+ * Updates the local initial window size of all active streams. If
+ * error occurs, all streams may not be updated.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+static int
+session_update_local_initial_window_size(nghttp2_session *session,
+ int32_t new_initial_window_size,
+ int32_t old_initial_window_size) {
+ nghttp2_update_window_size_arg arg;
+ arg.session = session;
+ arg.new_window_size = new_initial_window_size;
+ arg.old_window_size = old_initial_window_size;
+ return nghttp2_map_each(&session->streams,
+ update_local_initial_window_size_func, &arg);
+}
+
+/*
+ * Apply SETTINGS values |iv| having |niv| elements to the local
+ * settings. We assumes that all values in |iv| is correct, since we
+ * validated them in nghttp2_session_add_settings() already.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_HEADER_COMP
+ * The header table size is out of range
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_session_update_local_settings(nghttp2_session *session,
+ nghttp2_settings_entry *iv,
+ size_t niv) {
+ int rv;
+ size_t i;
+ int32_t new_initial_window_size = -1;
+ uint32_t header_table_size = 0;
+ uint32_t min_header_table_size = UINT32_MAX;
+ uint8_t header_table_size_seen = 0;
+ /* For NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, use the value last
+ seen. For NGHTTP2_SETTINGS_HEADER_TABLE_SIZE, use both minimum
+ value and last seen value. */
+ for (i = 0; i < niv; ++i) {
+ switch (iv[i].settings_id) {
+ case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
+ header_table_size_seen = 1;
+ header_table_size = iv[i].value;
+ min_header_table_size = nghttp2_min(min_header_table_size, iv[i].value);
+ break;
+ case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
+ new_initial_window_size = (int32_t)iv[i].value;
+ break;
+ }
+ }
+ if (header_table_size_seen) {
+ if (min_header_table_size < header_table_size) {
+ rv = nghttp2_hd_inflate_change_table_size(&session->hd_inflater,
+ min_header_table_size);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+
+ rv = nghttp2_hd_inflate_change_table_size(&session->hd_inflater,
+ header_table_size);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+ if (new_initial_window_size != -1) {
+ rv = session_update_local_initial_window_size(
+ session, new_initial_window_size,
+ (int32_t)session->local_settings.initial_window_size);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+
+ for (i = 0; i < niv; ++i) {
+ switch (iv[i].settings_id) {
+ case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
+ session->local_settings.header_table_size = iv[i].value;
+ break;
+ case NGHTTP2_SETTINGS_ENABLE_PUSH:
+ session->local_settings.enable_push = iv[i].value;
+ break;
+ case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
+ session->local_settings.max_concurrent_streams = iv[i].value;
+ break;
+ case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
+ session->local_settings.initial_window_size = iv[i].value;
+ break;
+ case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
+ session->local_settings.max_frame_size = iv[i].value;
+ break;
+ case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
+ session->local_settings.max_header_list_size = iv[i].value;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int nghttp2_session_on_settings_received(nghttp2_session *session,
+ nghttp2_frame *frame, int noack) {
+ int rv;
+ size_t i;
+ nghttp2_mem *mem;
+ nghttp2_inflight_settings *settings;
+
+ mem = &session->mem;
+
+ if (frame->hd.stream_id != 0) {
+ return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
+ "SETTINGS: stream_id != 0");
+ }
+ if (frame->hd.flags & NGHTTP2_FLAG_ACK) {
+ if (frame->settings.niv != 0) {
+ return session_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_FRAME_SIZE_ERROR,
+ "SETTINGS: ACK and payload != 0");
+ }
+
+ settings = session->inflight_settings_head;
+
+ if (!settings) {
+ return session_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO, "SETTINGS: unexpected ACK");
+ }
+
+ rv = nghttp2_session_update_local_settings(session, settings->iv,
+ settings->niv);
+
+ session->inflight_settings_head = settings->next;
+
+ inflight_settings_del(settings, mem);
+
+ if (rv != 0) {
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ return session_handle_invalid_connection(session, frame, rv, NULL);
+ }
+ return session_call_on_frame_received(session, frame);
+ }
+
+ for (i = 0; i < frame->settings.niv; ++i) {
+ nghttp2_settings_entry *entry = &frame->settings.iv[i];
+
+ switch (entry->settings_id) {
+ case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
+
+ rv = nghttp2_hd_deflate_change_table_size(&session->hd_deflater,
+ entry->value);
+ if (rv != 0) {
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ } else {
+ return session_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_HEADER_COMP, NULL);
+ }
+ }
+
+ session->remote_settings.header_table_size = entry->value;
+
+ break;
+ case NGHTTP2_SETTINGS_ENABLE_PUSH:
+
+ if (entry->value != 0 && entry->value != 1) {
+ return session_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO,
+ "SETTINGS: invalid SETTINGS_ENBLE_PUSH");
+ }
+
+ if (!session->server && entry->value != 0) {
+ return session_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO,
+ "SETTINGS: server attempted to enable push");
+ }
+
+ session->remote_settings.enable_push = entry->value;
+
+ break;
+ case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
+
+ session->remote_settings.max_concurrent_streams = entry->value;
+
+ break;
+ case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
+
+ /* Update the initial window size of the all active streams */
+ /* Check that initial_window_size < (1u << 31) */
+ if (entry->value > NGHTTP2_MAX_WINDOW_SIZE) {
+ return session_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_FLOW_CONTROL,
+ "SETTINGS: too large SETTINGS_INITIAL_WINDOW_SIZE");
+ }
+
+ rv = session_update_remote_initial_window_size(session,
+ (int32_t)entry->value);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ if (rv != 0) {
+ return session_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_FLOW_CONTROL, NULL);
+ }
+
+ session->remote_settings.initial_window_size = entry->value;
+
+ break;
+ case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
+
+ if (entry->value < NGHTTP2_MAX_FRAME_SIZE_MIN ||
+ entry->value > NGHTTP2_MAX_FRAME_SIZE_MAX) {
+ return session_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO,
+ "SETTINGS: invalid SETTINGS_MAX_FRAME_SIZE");
+ }
+
+ session->remote_settings.max_frame_size = entry->value;
+
+ break;
+ case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
+
+ session->remote_settings.max_header_list_size = entry->value;
+
+ break;
+ }
+ }
+
+ if (!noack && !session_is_closing(session)) {
+ rv = nghttp2_session_add_settings(session, NGHTTP2_FLAG_ACK, NULL, 0);
+
+ if (rv != 0) {
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ return session_handle_invalid_connection(session, frame,
+ NGHTTP2_ERR_INTERNAL, NULL);
+ }
+ }
+
+ return session_call_on_frame_received(session, frame);
+}
+
+static int session_process_settings_frame(nghttp2_session *session) {
+ nghttp2_inbound_frame *iframe = &session->iframe;
+ nghttp2_frame *frame = &iframe->frame;
+ size_t i;
+ nghttp2_settings_entry min_header_size_entry;
+
+ if (iframe->max_niv) {
+ min_header_size_entry = iframe->iv[iframe->max_niv - 1];
+
+ if (min_header_size_entry.value < UINT32_MAX) {
+ /* If we have less value, then we must have
+ SETTINGS_HEADER_TABLE_SIZE in i < iframe->niv */
+ for (i = 0; i < iframe->niv; ++i) {
+ if (iframe->iv[i].settings_id == NGHTTP2_SETTINGS_HEADER_TABLE_SIZE) {
+ break;
+ }
+ }
+
+ assert(i < iframe->niv);
+
+ if (min_header_size_entry.value != iframe->iv[i].value) {
+ iframe->iv[iframe->niv++] = iframe->iv[i];
+ iframe->iv[i] = min_header_size_entry;
+ }
+ }
+ }
+
+ nghttp2_frame_unpack_settings_payload(&frame->settings, iframe->iv,
+ iframe->niv);
+
+ iframe->iv = NULL;
+ iframe->niv = 0;
+ iframe->max_niv = 0;
+
+ return nghttp2_session_on_settings_received(session, frame, 0 /* ACK */);
+}
+
+int nghttp2_session_on_push_promise_received(nghttp2_session *session,
+ nghttp2_frame *frame) {
+ int rv;
+ nghttp2_stream *stream;
+ nghttp2_stream *promised_stream;
+ nghttp2_priority_spec pri_spec;
+
+ if (frame->hd.stream_id == 0) {
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: stream_id == 0");
+ }
+ if (session->server || session->local_settings.enable_push == 0) {
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: push disabled");
+ }
+
+ if (!nghttp2_session_is_my_stream_id(session, frame->hd.stream_id)) {
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: invalid stream_id");
+ }
+
+ if (!session_allow_incoming_new_stream(session)) {
+ /* We just discard PUSH_PROMISE after GOAWAY was sent */
+ return NGHTTP2_ERR_IGN_HEADER_BLOCK;
+ }
+
+ if (!session_is_new_peer_stream_id(session,
+ frame->push_promise.promised_stream_id)) {
+ /* The spec says if an endpoint receives a PUSH_PROMISE with
+ illegal stream ID is subject to a connection error of type
+ PROTOCOL_ERROR. */
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO,
+ "PUSH_PROMISE: invalid promised_stream_id");
+ }
+
+ if (session_detect_idle_stream(session, frame->hd.stream_id)) {
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: stream in idle");
+ }
+
+ session->last_recv_stream_id = frame->push_promise.promised_stream_id;
+ stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
+ if (!stream || stream->state == NGHTTP2_STREAM_CLOSING ||
+ !session->pending_enable_push ||
+ session->num_incoming_reserved_streams >=
+ session->max_incoming_reserved_streams) {
+ /* Currently, client does not retain closed stream, so we don't
+ check NGHTTP2_SHUT_RD condition here. */
+
+ rv = nghttp2_session_add_rst_stream(
+ session, frame->push_promise.promised_stream_id, NGHTTP2_CANCEL);
+ if (rv != 0) {
+ return rv;
+ }
+ return NGHTTP2_ERR_IGN_HEADER_BLOCK;
+ }
+
+ if (stream->shut_flags & NGHTTP2_SHUT_RD) {
+ return session_inflate_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_STREAM_CLOSED,
+ "PUSH_PROMISE: stream closed");
+ }
+
+ nghttp2_priority_spec_init(&pri_spec, stream->stream_id,
+ NGHTTP2_DEFAULT_WEIGHT, 0);
+
+ promised_stream = nghttp2_session_open_stream(
+ session, frame->push_promise.promised_stream_id, NGHTTP2_STREAM_FLAG_NONE,
+ &pri_spec, NGHTTP2_STREAM_RESERVED, NULL);
+
+ if (!promised_stream) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ /* We don't call nghttp2_session_adjust_closed_stream(), since we
+ don't keep closed stream in client side */
+
+ session->last_proc_stream_id = session->last_recv_stream_id;
+ rv = session_call_on_begin_headers(session, frame);
+ if (rv != 0) {
+ return rv;
+ }
+ return 0;
+}
+
+static int session_process_push_promise_frame(nghttp2_session *session) {
+ int rv;
+ nghttp2_inbound_frame *iframe = &session->iframe;
+ nghttp2_frame *frame = &iframe->frame;
+
+ rv = nghttp2_frame_unpack_push_promise_payload(&frame->push_promise,
+ iframe->sbuf.pos);
+
+ if (rv != 0) {
+ return nghttp2_session_terminate_session_with_reason(
+ session, NGHTTP2_PROTOCOL_ERROR, "PUSH_PROMISE: could not unpack");
+ }
+
+ return nghttp2_session_on_push_promise_received(session, frame);
+}
+
+int nghttp2_session_on_ping_received(nghttp2_session *session,
+ nghttp2_frame *frame) {
+ int rv = 0;
+ if (frame->hd.stream_id != 0) {
+ return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
+ "PING: stream_id != 0");
+ }
+ if ((session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_PING_ACK) == 0 &&
+ (frame->hd.flags & NGHTTP2_FLAG_ACK) == 0 &&
+ !session_is_closing(session)) {
+ /* Peer sent ping, so ping it back */
+ rv = nghttp2_session_add_ping(session, NGHTTP2_FLAG_ACK,
+ frame->ping.opaque_data);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+ return session_call_on_frame_received(session, frame);
+}
+
+static int session_process_ping_frame(nghttp2_session *session) {
+ nghttp2_inbound_frame *iframe = &session->iframe;
+ nghttp2_frame *frame = &iframe->frame;
+
+ nghttp2_frame_unpack_ping_payload(&frame->ping, iframe->sbuf.pos);
+
+ return nghttp2_session_on_ping_received(session, frame);
+}
+
+int nghttp2_session_on_goaway_received(nghttp2_session *session,
+ nghttp2_frame *frame) {
+ int rv;
+
+ if (frame->hd.stream_id != 0) {
+ return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
+ "GOAWAY: stream_id != 0");
+ }
+ /* Spec says Endpoints MUST NOT increase the value they send in the
+ last stream identifier. */
+ if ((frame->goaway.last_stream_id > 0 &&
+ !nghttp2_session_is_my_stream_id(session,
+ frame->goaway.last_stream_id)) ||
+ session->remote_last_stream_id < frame->goaway.last_stream_id) {
+ return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
+ "GOAWAY: invalid last_stream_id");
+ }
+
+ session->goaway_flags |= NGHTTP2_GOAWAY_RECV;
+
+ session->remote_last_stream_id = frame->goaway.last_stream_id;
+
+ rv = session_call_on_frame_received(session, frame);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ return session_close_stream_on_goaway(session, frame->goaway.last_stream_id,
+ 0);
+}
+
+static int session_process_goaway_frame(nghttp2_session *session) {
+ nghttp2_inbound_frame *iframe = &session->iframe;
+ nghttp2_frame *frame = &iframe->frame;
+
+ nghttp2_frame_unpack_goaway_payload(&frame->goaway, iframe->sbuf.pos,
+ iframe->lbuf.pos,
+ nghttp2_buf_len(&iframe->lbuf));
+
+ nghttp2_buf_wrap_init(&iframe->lbuf, NULL, 0);
+
+ return nghttp2_session_on_goaway_received(session, frame);
+}
+
+static int
+session_on_connection_window_update_received(nghttp2_session *session,
+ nghttp2_frame *frame) {
+ /* Handle connection-level flow control */
+ if (frame->window_update.window_size_increment == 0) {
+ return session_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO,
+ "WINDOW_UPDATE: window_size_increment == 0");
+ }
+
+ if (NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment <
+ session->remote_window_size) {
+ return session_handle_invalid_connection(session, frame,
+ NGHTTP2_ERR_FLOW_CONTROL, NULL);
+ }
+ session->remote_window_size += frame->window_update.window_size_increment;
+
+ return session_call_on_frame_received(session, frame);
+}
+
+static int session_on_stream_window_update_received(nghttp2_session *session,
+ nghttp2_frame *frame) {
+ int rv;
+ nghttp2_stream *stream;
+
+ if (session_detect_idle_stream(session, frame->hd.stream_id)) {
+ return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO,
+ "WINDOW_UPDATE to idle stream");
+ }
+
+ stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
+ if (!stream) {
+ return 0;
+ }
+ if (state_reserved_remote(session, stream)) {
+ return session_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO, "WINDOW_UPADATE to reserved stream");
+ }
+ if (frame->window_update.window_size_increment == 0) {
+ return session_handle_invalid_connection(
+ session, frame, NGHTTP2_ERR_PROTO,
+ "WINDOW_UPDATE: window_size_increment == 0");
+ }
+ if (NGHTTP2_MAX_WINDOW_SIZE - frame->window_update.window_size_increment <
+ stream->remote_window_size) {
+ return session_handle_invalid_stream(session, frame,
+ NGHTTP2_ERR_FLOW_CONTROL);
+ }
+ stream->remote_window_size += frame->window_update.window_size_increment;
+
+ if (stream->remote_window_size > 0 &&
+ nghttp2_stream_check_deferred_by_flow_control(stream)) {
+
+ rv = nghttp2_stream_resume_deferred_item(
+ stream, NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+ return session_call_on_frame_received(session, frame);
+}
+
+int nghttp2_session_on_window_update_received(nghttp2_session *session,
+ nghttp2_frame *frame) {
+ if (frame->hd.stream_id == 0) {
+ return session_on_connection_window_update_received(session, frame);
+ } else {
+ return session_on_stream_window_update_received(session, frame);
+ }
+}
+
+static int session_process_window_update_frame(nghttp2_session *session) {
+ nghttp2_inbound_frame *iframe = &session->iframe;
+ nghttp2_frame *frame = &iframe->frame;
+
+ nghttp2_frame_unpack_window_update_payload(&frame->window_update,
+ iframe->sbuf.pos);
+
+ return nghttp2_session_on_window_update_received(session, frame);
+}
+
+int nghttp2_session_on_altsvc_received(nghttp2_session *session,
+ nghttp2_frame *frame) {
+ nghttp2_ext_altsvc *altsvc;
+ nghttp2_stream *stream;
+
+ altsvc = frame->ext.payload;
+
+ /* session->server case has been excluded */
+
+ if (frame->hd.stream_id == 0) {
+ if (altsvc->origin_len == 0) {
+ return session_call_on_invalid_frame_recv_callback(session, frame,
+ NGHTTP2_ERR_PROTO);
+ }
+ } else {
+ if (altsvc->origin_len > 0) {
+ return session_call_on_invalid_frame_recv_callback(session, frame,
+ NGHTTP2_ERR_PROTO);
+ }
+
+ stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
+ if (!stream) {
+ return 0;
+ }
+
+ if (stream->state == NGHTTP2_STREAM_CLOSING) {
+ return 0;
+ }
+ }
+
+ if (altsvc->field_value_len == 0) {
+ return session_call_on_invalid_frame_recv_callback(session, frame,
+ NGHTTP2_ERR_PROTO);
+ }
+
+ return session_call_on_frame_received(session, frame);
+}
+
+static int session_process_altsvc_frame(nghttp2_session *session) {
+ nghttp2_inbound_frame *iframe = &session->iframe;
+ nghttp2_frame *frame = &iframe->frame;
+
+ nghttp2_frame_unpack_altsvc_payload(
+ &frame->ext, nghttp2_get_uint16(iframe->sbuf.pos), iframe->lbuf.pos,
+ nghttp2_buf_len(&iframe->lbuf));
+
+ /* nghttp2_frame_unpack_altsvc_payload steals buffer from
+ iframe->lbuf */
+ nghttp2_buf_wrap_init(&iframe->lbuf, NULL, 0);
+
+ return nghttp2_session_on_altsvc_received(session, frame);
+}
+
+static int session_process_extension_frame(nghttp2_session *session) {
+ int rv;
+ nghttp2_inbound_frame *iframe = &session->iframe;
+ nghttp2_frame *frame = &iframe->frame;
+
+ rv = session_call_unpack_extension_callback(session);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ /* This handles the case where rv == NGHTTP2_ERR_CANCEL as well */
+ if (rv != 0) {
+ return 0;
+ }
+
+ return session_call_on_frame_received(session, frame);
+}
+
+int nghttp2_session_on_data_received(nghttp2_session *session,
+ nghttp2_frame *frame) {
+ int rv = 0;
+ int call_cb = 1;
+ nghttp2_stream *stream;
+
+ /* We don't call on_frame_recv_callback if stream has been closed
+ already or being closed. */
+ stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
+ if (!stream || stream->state == NGHTTP2_STREAM_CLOSING) {
+ /* This should be treated as stream error, but it results in lots
+ of RST_STREAM. So just ignore frame against nonexistent stream
+ for now. */
+ return 0;
+ }
+
+ if (session_enforce_http_messaging(session) &&
+ (frame->hd.flags & NGHTTP2_FLAG_END_STREAM)) {
+ if (nghttp2_http_on_remote_end_stream(stream) != 0) {
+ call_cb = 0;
+ rv = nghttp2_session_add_rst_stream(session, stream->stream_id,
+ NGHTTP2_PROTOCOL_ERROR);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+ }
+
+ if (call_cb) {
+ rv = session_call_on_frame_received(session, frame);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+
+ if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
+ nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
+ rv = nghttp2_session_close_stream_if_shut_rdwr(session, stream);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+ return 0;
+}
+
+/* For errors, this function only returns FATAL error. */
+static int session_process_data_frame(nghttp2_session *session) {
+ int rv;
+ nghttp2_frame *public_data_frame = &session->iframe.frame;
+ rv = nghttp2_session_on_data_received(session, public_data_frame);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ return 0;
+}
+
+/*
+ * Now we have SETTINGS synchronization, flow control error can be
+ * detected strictly. If DATA frame is received with length > 0 and
+ * current received window size + delta length is strictly larger than
+ * local window size, it is subject to FLOW_CONTROL_ERROR, so return
+ * -1. Note that local_window_size is calculated after SETTINGS ACK is
+ * received from peer, so peer must honor this limit. If the resulting
+ * recv_window_size is strictly larger than NGHTTP2_MAX_WINDOW_SIZE,
+ * return -1 too.
+ */
+static int adjust_recv_window_size(int32_t *recv_window_size_ptr, size_t delta,
+ int32_t local_window_size) {
+ if (*recv_window_size_ptr > local_window_size - (int32_t)delta ||
+ *recv_window_size_ptr > NGHTTP2_MAX_WINDOW_SIZE - (int32_t)delta) {
+ return -1;
+ }
+ *recv_window_size_ptr += (int32_t)delta;
+ return 0;
+}
+
+/*
+ * Accumulates received bytes |delta_size| for stream-level flow
+ * control and decides whether to send WINDOW_UPDATE to that stream.
+ * If NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE is set, WINDOW_UPDATE will not
+ * be sent.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+static int session_update_recv_stream_window_size(nghttp2_session *session,
+ nghttp2_stream *stream,
+ size_t delta_size,
+ int send_window_update) {
+ int rv;
+ rv = adjust_recv_window_size(&stream->recv_window_size, delta_size,
+ stream->local_window_size);
+ if (rv != 0) {
+ return nghttp2_session_add_rst_stream(session, stream->stream_id,
+ NGHTTP2_FLOW_CONTROL_ERROR);
+ }
+ /* We don't have to send WINDOW_UPDATE if the data received is the
+ last chunk in the incoming stream. */
+ /* We have to use local_settings here because it is the constraint
+ the remote endpoint should honor. */
+ if (send_window_update &&
+ !(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) &&
+ stream->window_update_queued == 0 &&
+ nghttp2_should_send_window_update(stream->local_window_size,
+ stream->recv_window_size)) {
+ rv = nghttp2_session_add_window_update(session, NGHTTP2_FLAG_NONE,
+ stream->stream_id,
+ stream->recv_window_size);
+ if (rv != 0) {
+ return rv;
+ }
+
+ stream->recv_window_size = 0;
+ }
+ return 0;
+}
+
+/*
+ * Accumulates received bytes |delta_size| for connection-level flow
+ * control and decides whether to send WINDOW_UPDATE to the
+ * connection. If NGHTTP2_OPT_NO_AUTO_WINDOW_UPDATE is set,
+ * WINDOW_UPDATE will not be sent.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+static int session_update_recv_connection_window_size(nghttp2_session *session,
+ size_t delta_size) {
+ int rv;
+ rv = adjust_recv_window_size(&session->recv_window_size, delta_size,
+ session->local_window_size);
+ if (rv != 0) {
+ return nghttp2_session_terminate_session(session,
+ NGHTTP2_FLOW_CONTROL_ERROR);
+ }
+ if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) &&
+ session->window_update_queued == 0 &&
+ nghttp2_should_send_window_update(session->local_window_size,
+ session->recv_window_size)) {
+ /* Use stream ID 0 to update connection-level flow control
+ window */
+ rv = nghttp2_session_add_window_update(session, NGHTTP2_FLAG_NONE, 0,
+ session->recv_window_size);
+ if (rv != 0) {
+ return rv;
+ }
+
+ session->recv_window_size = 0;
+ }
+ return 0;
+}
+
+static int session_update_consumed_size(nghttp2_session *session,
+ int32_t *consumed_size_ptr,
+ int32_t *recv_window_size_ptr,
+ uint8_t window_update_queued,
+ int32_t stream_id, size_t delta_size,
+ int32_t local_window_size) {
+ int32_t recv_size;
+ int rv;
+
+ if ((size_t)*consumed_size_ptr > NGHTTP2_MAX_WINDOW_SIZE - delta_size) {
+ return nghttp2_session_terminate_session(session,
+ NGHTTP2_FLOW_CONTROL_ERROR);
+ }
+
+ *consumed_size_ptr += (int32_t)delta_size;
+
+ if (window_update_queued == 0) {
+ /* recv_window_size may be smaller than consumed_size, because it
+ may be decreased by negative value with
+ nghttp2_submit_window_update(). */
+ recv_size = nghttp2_min(*consumed_size_ptr, *recv_window_size_ptr);
+
+ if (nghttp2_should_send_window_update(local_window_size, recv_size)) {
+ rv = nghttp2_session_add_window_update(session, NGHTTP2_FLAG_NONE,
+ stream_id, recv_size);
+
+ if (rv != 0) {
+ return rv;
+ }
+
+ *recv_window_size_ptr -= recv_size;
+ *consumed_size_ptr -= recv_size;
+ }
+ }
+
+ return 0;
+}
+
+static int session_update_stream_consumed_size(nghttp2_session *session,
+ nghttp2_stream *stream,
+ size_t delta_size) {
+ return session_update_consumed_size(
+ session, &stream->consumed_size, &stream->recv_window_size,
+ stream->window_update_queued, stream->stream_id, delta_size,
+ stream->local_window_size);
+}
+
+static int session_update_connection_consumed_size(nghttp2_session *session,
+ size_t delta_size) {
+ return session_update_consumed_size(
+ session, &session->consumed_size, &session->recv_window_size,
+ session->window_update_queued, 0, delta_size, session->local_window_size);
+}
+
+/*
+ * Checks that we can receive the DATA frame for stream, which is
+ * indicated by |session->iframe.frame.hd.stream_id|. If it is a
+ * connection error situation, GOAWAY frame will be issued by this
+ * function.
+ *
+ * If the DATA frame is allowed, returns 0.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_IGN_PAYLOAD
+ * The reception of DATA frame is connection error; or should be
+ * ignored.
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+static int session_on_data_received_fail_fast(nghttp2_session *session) {
+ int rv;
+ nghttp2_stream *stream;
+ nghttp2_inbound_frame *iframe;
+ int32_t stream_id;
+ const char *failure_reason;
+ uint32_t error_code = NGHTTP2_PROTOCOL_ERROR;
+
+ iframe = &session->iframe;
+ stream_id = iframe->frame.hd.stream_id;
+
+ if (stream_id == 0) {
+ /* The spec says that if a DATA frame is received whose stream ID
+ is 0, the recipient MUST respond with a connection error of
+ type PROTOCOL_ERROR. */
+ failure_reason = "DATA: stream_id == 0";
+ goto fail;
+ }
+
+ if (session_detect_idle_stream(session, stream_id)) {
+ failure_reason = "DATA: stream in idle";
+ error_code = NGHTTP2_PROTOCOL_ERROR;
+ goto fail;
+ }
+
+ stream = nghttp2_session_get_stream(session, stream_id);
+ if (!stream) {
+ stream = nghttp2_session_get_stream_raw(session, stream_id);
+ if (stream && (stream->shut_flags & NGHTTP2_SHUT_RD)) {
+ failure_reason = "DATA: stream closed";
+ error_code = NGHTTP2_STREAM_CLOSED;
+ goto fail;
+ }
+
+ return NGHTTP2_ERR_IGN_PAYLOAD;
+ }
+ if (stream->shut_flags & NGHTTP2_SHUT_RD) {
+ failure_reason = "DATA: stream in half-closed(remote)";
+ error_code = NGHTTP2_STREAM_CLOSED;
+ goto fail;
+ }
+
+ if (nghttp2_session_is_my_stream_id(session, stream_id)) {
+ if (stream->state == NGHTTP2_STREAM_CLOSING) {
+ return NGHTTP2_ERR_IGN_PAYLOAD;
+ }
+ if (stream->state != NGHTTP2_STREAM_OPENED) {
+ failure_reason = "DATA: stream not opened";
+ goto fail;
+ }
+ return 0;
+ }
+ if (stream->state == NGHTTP2_STREAM_RESERVED) {
+ failure_reason = "DATA: stream in reserved";
+ goto fail;
+ }
+ if (stream->state == NGHTTP2_STREAM_CLOSING) {
+ return NGHTTP2_ERR_IGN_PAYLOAD;
+ }
+ return 0;
+fail:
+ rv = nghttp2_session_terminate_session_with_reason(session, error_code,
+ failure_reason);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ return NGHTTP2_ERR_IGN_PAYLOAD;
+}
+
+static size_t inbound_frame_payload_readlen(nghttp2_inbound_frame *iframe,
+ const uint8_t *in,
+ const uint8_t *last) {
+ return nghttp2_min((size_t)(last - in), iframe->payloadleft);
+}
+
+/*
+ * Resets iframe->sbuf and advance its mark pointer by |left| bytes.
+ */
+static void inbound_frame_set_mark(nghttp2_inbound_frame *iframe, size_t left) {
+ nghttp2_buf_reset(&iframe->sbuf);
+ iframe->sbuf.mark += left;
+}
+
+static size_t inbound_frame_buf_read(nghttp2_inbound_frame *iframe,
+ const uint8_t *in, const uint8_t *last) {
+ size_t readlen;
+
+ readlen =
+ nghttp2_min((size_t)(last - in), nghttp2_buf_mark_avail(&iframe->sbuf));
+
+ iframe->sbuf.last = nghttp2_cpymem(iframe->sbuf.last, in, readlen);
+
+ return readlen;
+}
+
+/*
+ * Unpacks SETTINGS entry in iframe->sbuf.
+ */
+static void inbound_frame_set_settings_entry(nghttp2_inbound_frame *iframe) {
+ nghttp2_settings_entry iv;
+ nghttp2_settings_entry *min_header_table_size_entry;
+ size_t i;
+
+ nghttp2_frame_unpack_settings_entry(&iv, iframe->sbuf.pos);
+
+ switch (iv.settings_id) {
+ case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
+ case NGHTTP2_SETTINGS_ENABLE_PUSH:
+ case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
+ case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
+ case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
+ case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
+ break;
+ default:
+ DEBUGF("recv: unknown settings id=0x%02x\n", iv.settings_id);
+
+ iframe->iv[iframe->niv++] = iv;
+
+ return;
+ }
+
+ for (i = 0; i < iframe->niv; ++i) {
+ if (iframe->iv[i].settings_id == iv.settings_id) {
+ iframe->iv[i] = iv;
+ break;
+ }
+ }
+
+ if (i == iframe->niv) {
+ iframe->iv[iframe->niv++] = iv;
+ }
+
+ if (iv.settings_id == NGHTTP2_SETTINGS_HEADER_TABLE_SIZE) {
+ /* Keep track of minimum value of SETTINGS_HEADER_TABLE_SIZE */
+ min_header_table_size_entry = &iframe->iv[iframe->max_niv - 1];
+
+ if (iv.value < min_header_table_size_entry->value) {
+ min_header_table_size_entry->value = iv.value;
+ }
+ }
+}
+
+/*
+ * Checks PADDED flags and set iframe->sbuf to read them accordingly.
+ * If padding is set, this function returns 1. If no padding is set,
+ * this function returns 0. On error, returns -1.
+ */
+static int inbound_frame_handle_pad(nghttp2_inbound_frame *iframe,
+ nghttp2_frame_hd *hd) {
+ if (hd->flags & NGHTTP2_FLAG_PADDED) {
+ if (hd->length < 1) {
+ return -1;
+ }
+ inbound_frame_set_mark(iframe, 1);
+ return 1;
+ }
+ DEBUGF("recv: no padding in payload\n");
+ return 0;
+}
+
+/*
+ * Computes number of padding based on flags. This function returns
+ * the calculated length if it succeeds, or -1.
+ */
+static ssize_t inbound_frame_compute_pad(nghttp2_inbound_frame *iframe) {
+ size_t padlen;
+
+ /* 1 for Pad Length field */
+ padlen = (size_t)(iframe->sbuf.pos[0] + 1);
+
+ DEBUGF("recv: padlen=%zu\n", padlen);
+
+ /* We cannot use iframe->frame.hd.length because of CONTINUATION */
+ if (padlen - 1 > iframe->payloadleft) {
+ return -1;
+ }
+
+ iframe->padlen = padlen;
+
+ return (ssize_t)padlen;
+}
+
+/*
+ * This function returns the effective payload length in the data of
+ * length |readlen| when the remaning payload is |payloadleft|. The
+ * |payloadleft| does not include |readlen|. If padding was started
+ * strictly before this data chunk, this function returns -1.
+ */
+static ssize_t inbound_frame_effective_readlen(nghttp2_inbound_frame *iframe,
+ size_t payloadleft,
+ size_t readlen) {
+ size_t trail_padlen =
+ nghttp2_frame_trail_padlen(&iframe->frame, iframe->padlen);
+
+ if (trail_padlen > payloadleft) {
+ size_t padlen;
+ padlen = trail_padlen - payloadleft;
+ if (readlen < padlen) {
+ return -1;
+ }
+ return (ssize_t)(readlen - padlen);
+ }
+ return (ssize_t)(readlen);
+}
+
+ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
+ size_t inlen) {
+ const uint8_t *first = in, *last = in + inlen;
+ nghttp2_inbound_frame *iframe = &session->iframe;
+ size_t readlen;
+ ssize_t padlen;
+ int rv;
+ int busy = 0;
+ nghttp2_frame_hd cont_hd;
+ nghttp2_stream *stream;
+ size_t pri_fieldlen;
+ nghttp2_mem *mem;
+
+ mem = &session->mem;
+
+ /* We may have idle streams more than we expect (e.g.,
+ nghttp2_session_change_stream_priority() or
+ nghttp2_session_create_idle_stream()). Adjust them here. */
+ rv = nghttp2_session_adjust_idle_stream(session);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ if (!nghttp2_session_want_read(session)) {
+ return (ssize_t)inlen;
+ }
+
+ for (;;) {
+ switch (iframe->state) {
+ case NGHTTP2_IB_READ_CLIENT_MAGIC:
+ readlen = nghttp2_min(inlen, iframe->payloadleft);
+
+ if (memcmp(NGHTTP2_CLIENT_MAGIC + NGHTTP2_CLIENT_MAGIC_LEN -
+ iframe->payloadleft,
+ in, readlen) != 0) {
+ return NGHTTP2_ERR_BAD_CLIENT_MAGIC;
+ }
+
+ iframe->payloadleft -= readlen;
+ in += readlen;
+
+ if (iframe->payloadleft == 0) {
+ session_inbound_frame_reset(session);
+ iframe->state = NGHTTP2_IB_READ_FIRST_SETTINGS;
+ }
+
+ break;
+ case NGHTTP2_IB_READ_FIRST_SETTINGS:
+ DEBUGF("recv: [IB_READ_FIRST_SETTINGS]\n");
+
+ readlen = inbound_frame_buf_read(iframe, in, last);
+ in += readlen;
+
+ if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
+ return in - first;
+ }
+
+ if (iframe->sbuf.pos[3] != NGHTTP2_SETTINGS ||
+ (iframe->sbuf.pos[4] & NGHTTP2_FLAG_ACK)) {
+
+ iframe->state = NGHTTP2_IB_IGN_ALL;
+
+ rv = session_call_error_callback(
+ session, NGHTTP2_ERR_SETTINGS_EXPECTED,
+ "Remote peer returned unexpected data while we expected "
+ "SETTINGS frame. Perhaps, peer does not support HTTP/2 "
+ "properly.");
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ rv = nghttp2_session_terminate_session_with_reason(
+ session, NGHTTP2_PROTOCOL_ERROR, "SETTINGS expected");
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ return (ssize_t)inlen;
+ }
+
+ iframe->state = NGHTTP2_IB_READ_HEAD;
+
+ /* Fall through */
+ case NGHTTP2_IB_READ_HEAD: {
+ int on_begin_frame_called = 0;
+
+ DEBUGF("recv: [IB_READ_HEAD]\n");
+
+ readlen = inbound_frame_buf_read(iframe, in, last);
+ in += readlen;
+
+ if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
+ return in - first;
+ }
+
+ nghttp2_frame_unpack_frame_hd(&iframe->frame.hd, iframe->sbuf.pos);
+ iframe->payloadleft = iframe->frame.hd.length;
+
+ DEBUGF("recv: payloadlen=%zu, type=%u, flags=0x%02x, stream_id=%d\n",
+ iframe->frame.hd.length, iframe->frame.hd.type,
+ iframe->frame.hd.flags, iframe->frame.hd.stream_id);
+
+ if (iframe->frame.hd.length > session->local_settings.max_frame_size) {
+ DEBUGF("recv: length is too large %zu > %u\n", iframe->frame.hd.length,
+ session->local_settings.max_frame_size);
+
+ busy = 1;
+
+ iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
+
+ rv = nghttp2_session_terminate_session_with_reason(
+ session, NGHTTP2_FRAME_SIZE_ERROR, "too large frame size");
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ break;
+ }
+
+ switch (iframe->frame.hd.type) {
+ case NGHTTP2_DATA: {
+ DEBUGF("recv: DATA\n");
+
+ iframe->frame.hd.flags &=
+ (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PADDED);
+ /* Check stream is open. If it is not open or closing,
+ ignore payload. */
+ busy = 1;
+
+ rv = session_on_data_received_fail_fast(session);
+ if (rv == NGHTTP2_ERR_IGN_PAYLOAD) {
+ DEBUGF("recv: DATA not allowed stream_id=%d\n",
+ iframe->frame.hd.stream_id);
+ iframe->state = NGHTTP2_IB_IGN_DATA;
+ break;
+ }
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
+ if (rv < 0) {
+ iframe->state = NGHTTP2_IB_IGN_DATA;
+ rv = nghttp2_session_terminate_session_with_reason(
+ session, NGHTTP2_PROTOCOL_ERROR,
+ "DATA: insufficient padding space");
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ break;
+ }
+
+ if (rv == 1) {
+ iframe->state = NGHTTP2_IB_READ_PAD_DATA;
+ break;
+ }
+
+ iframe->state = NGHTTP2_IB_READ_DATA;
+ break;
+ }
+ case NGHTTP2_HEADERS:
+
+ DEBUGF("recv: HEADERS\n");
+
+ iframe->frame.hd.flags &=
+ (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS |
+ NGHTTP2_FLAG_PADDED | NGHTTP2_FLAG_PRIORITY);
+
+ rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
+ if (rv < 0) {
+ busy = 1;
+
+ iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
+
+ rv = nghttp2_session_terminate_session_with_reason(
+ session, NGHTTP2_PROTOCOL_ERROR,
+ "HEADERS: insufficient padding space");
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ break;
+ }
+
+ if (rv == 1) {
+ iframe->state = NGHTTP2_IB_READ_NBYTE;
+ break;
+ }
+
+ pri_fieldlen = nghttp2_frame_priority_len(iframe->frame.hd.flags);
+
+ if (pri_fieldlen > 0) {
+ if (iframe->payloadleft < pri_fieldlen) {
+ busy = 1;
+ iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
+ break;
+ }
+
+ iframe->state = NGHTTP2_IB_READ_NBYTE;
+
+ inbound_frame_set_mark(iframe, pri_fieldlen);
+
+ break;
+ }
+
+ /* Call on_begin_frame_callback here because
+ session_process_headers_frame() may call
+ on_begin_headers_callback */
+ rv = session_call_on_begin_frame(session, &iframe->frame.hd);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ on_begin_frame_called = 1;
+
+ rv = session_process_headers_frame(session);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ busy = 1;
+
+ if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
+ rv = nghttp2_session_add_rst_stream(
+ session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
+ break;
+ }
+
+ if (rv == NGHTTP2_ERR_IGN_HEADER_BLOCK) {
+ iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
+ break;
+ }
+
+ iframe->state = NGHTTP2_IB_READ_HEADER_BLOCK;
+
+ break;
+ case NGHTTP2_PRIORITY:
+ DEBUGF("recv: PRIORITY\n");
+
+ iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
+
+ if (iframe->payloadleft != NGHTTP2_PRIORITY_SPECLEN) {
+ busy = 1;
+
+ iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
+
+ break;
+ }
+
+ iframe->state = NGHTTP2_IB_READ_NBYTE;
+
+ inbound_frame_set_mark(iframe, NGHTTP2_PRIORITY_SPECLEN);
+
+ break;
+ case NGHTTP2_RST_STREAM:
+ case NGHTTP2_WINDOW_UPDATE:
+#ifdef DEBUGBUILD
+ switch (iframe->frame.hd.type) {
+ case NGHTTP2_RST_STREAM:
+ DEBUGF("recv: RST_STREAM\n");
+ break;
+ case NGHTTP2_WINDOW_UPDATE:
+ DEBUGF("recv: WINDOW_UPDATE\n");
+ break;
+ }
+#endif /* DEBUGBUILD */
+
+ iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
+
+ if (iframe->payloadleft != 4) {
+ busy = 1;
+ iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
+ break;
+ }
+
+ iframe->state = NGHTTP2_IB_READ_NBYTE;
+
+ inbound_frame_set_mark(iframe, 4);
+
+ break;
+ case NGHTTP2_SETTINGS:
+ DEBUGF("recv: SETTINGS\n");
+
+ iframe->frame.hd.flags &= NGHTTP2_FLAG_ACK;
+
+ if ((iframe->frame.hd.length % NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) ||
+ ((iframe->frame.hd.flags & NGHTTP2_FLAG_ACK) &&
+ iframe->payloadleft > 0)) {
+ busy = 1;
+ iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
+ break;
+ }
+
+ iframe->state = NGHTTP2_IB_READ_SETTINGS;
+
+ if (iframe->payloadleft) {
+ nghttp2_settings_entry *min_header_table_size_entry;
+
+ /* We allocate iv with additional one entry, to store the
+ minimum header table size. */
+ iframe->max_niv =
+ iframe->frame.hd.length / NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH + 1;
+
+ iframe->iv = nghttp2_mem_malloc(mem, sizeof(nghttp2_settings_entry) *
+ iframe->max_niv);
+
+ if (!iframe->iv) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ min_header_table_size_entry = &iframe->iv[iframe->max_niv - 1];
+ min_header_table_size_entry->settings_id =
+ NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
+ min_header_table_size_entry->value = UINT32_MAX;
+
+ inbound_frame_set_mark(iframe, NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH);
+ break;
+ }
+
+ busy = 1;
+
+ inbound_frame_set_mark(iframe, 0);
+
+ break;
+ case NGHTTP2_PUSH_PROMISE:
+ DEBUGF("recv: PUSH_PROMISE\n");
+
+ iframe->frame.hd.flags &=
+ (NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PADDED);
+
+ rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
+ if (rv < 0) {
+ busy = 1;
+ iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
+ rv = nghttp2_session_terminate_session_with_reason(
+ session, NGHTTP2_PROTOCOL_ERROR,
+ "PUSH_PROMISE: insufficient padding space");
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ break;
+ }
+
+ if (rv == 1) {
+ iframe->state = NGHTTP2_IB_READ_NBYTE;
+ break;
+ }
+
+ if (iframe->payloadleft < 4) {
+ busy = 1;
+ iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
+ break;
+ }
+
+ iframe->state = NGHTTP2_IB_READ_NBYTE;
+
+ inbound_frame_set_mark(iframe, 4);
+
+ break;
+ case NGHTTP2_PING:
+ DEBUGF("recv: PING\n");
+
+ iframe->frame.hd.flags &= NGHTTP2_FLAG_ACK;
+
+ if (iframe->payloadleft != 8) {
+ busy = 1;
+ iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
+ break;
+ }
+
+ iframe->state = NGHTTP2_IB_READ_NBYTE;
+ inbound_frame_set_mark(iframe, 8);
+
+ break;
+ case NGHTTP2_GOAWAY:
+ DEBUGF("recv: GOAWAY\n");
+
+ iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
+
+ if (iframe->payloadleft < 8) {
+ busy = 1;
+ iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
+ break;
+ }
+
+ iframe->state = NGHTTP2_IB_READ_NBYTE;
+ inbound_frame_set_mark(iframe, 8);
+
+ break;
+ case NGHTTP2_CONTINUATION:
+ DEBUGF("recv: unexpected CONTINUATION\n");
+
+ /* Receiving CONTINUATION in this state are subject to
+ connection error of type PROTOCOL_ERROR */
+ rv = nghttp2_session_terminate_session_with_reason(
+ session, NGHTTP2_PROTOCOL_ERROR, "CONTINUATION: unexpected");
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ busy = 1;
+
+ iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
+
+ break;
+ default:
+ DEBUGF("recv: extension frame\n");
+
+ if (check_ext_type_set(session->user_recv_ext_types,
+ iframe->frame.hd.type)) {
+ if (!session->callbacks.unpack_extension_callback) {
+ /* Silently ignore unknown frame type. */
+
+ busy = 1;
+
+ iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
+
+ break;
+ }
+
+ busy = 1;
+
+ iframe->state = NGHTTP2_IB_READ_EXTENSION_PAYLOAD;
+
+ break;
+ } else {
+ switch (iframe->frame.hd.type) {
+ case NGHTTP2_ALTSVC:
+ if ((session->builtin_recv_ext_types & NGHTTP2_TYPEMASK_ALTSVC) ==
+ 0) {
+ busy = 1;
+ iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
+ break;
+ }
+
+ DEBUGF("recv: ALTSVC\n");
+
+ iframe->frame.hd.flags = NGHTTP2_FLAG_NONE;
+ iframe->frame.ext.payload = &iframe->ext_frame_payload.altsvc;
+
+ if (session->server) {
+ busy = 1;
+ iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
+ break;
+ }
+
+ if (iframe->payloadleft < 2) {
+ busy = 1;
+ iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
+ break;
+ }
+
+ busy = 1;
+
+ iframe->state = NGHTTP2_IB_READ_NBYTE;
+ inbound_frame_set_mark(iframe, 2);
+
+ break;
+ default:
+ busy = 1;
+
+ iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
+
+ break;
+ }
+ }
+ }
+
+ if (!on_begin_frame_called) {
+ switch (iframe->state) {
+ case NGHTTP2_IB_IGN_HEADER_BLOCK:
+ case NGHTTP2_IB_IGN_PAYLOAD:
+ case NGHTTP2_IB_FRAME_SIZE_ERROR:
+ case NGHTTP2_IB_IGN_DATA:
+ break;
+ default:
+ rv = session_call_on_begin_frame(session, &iframe->frame.hd);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+ }
+
+ break;
+ }
+ case NGHTTP2_IB_READ_NBYTE:
+ DEBUGF("recv: [IB_READ_NBYTE]\n");
+
+ readlen = inbound_frame_buf_read(iframe, in, last);
+ in += readlen;
+ iframe->payloadleft -= readlen;
+
+ DEBUGF("recv: readlen=%zu, payloadleft=%zu, left=%zd\n", readlen,
+ iframe->payloadleft, nghttp2_buf_mark_avail(&iframe->sbuf));
+
+ if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
+ return in - first;
+ }
+
+ switch (iframe->frame.hd.type) {
+ case NGHTTP2_HEADERS:
+ if (iframe->padlen == 0 &&
+ (iframe->frame.hd.flags & NGHTTP2_FLAG_PADDED)) {
+ padlen = inbound_frame_compute_pad(iframe);
+ if (padlen < 0) {
+ busy = 1;
+ rv = nghttp2_session_terminate_session_with_reason(
+ session, NGHTTP2_PROTOCOL_ERROR, "HEADERS: invalid padding");
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
+ break;
+ }
+ iframe->frame.headers.padlen = (size_t)padlen;
+
+ pri_fieldlen = nghttp2_frame_priority_len(iframe->frame.hd.flags);
+
+ if (pri_fieldlen > 0) {
+ if (iframe->payloadleft < pri_fieldlen) {
+ busy = 1;
+ iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
+ break;
+ }
+ iframe->state = NGHTTP2_IB_READ_NBYTE;
+ inbound_frame_set_mark(iframe, pri_fieldlen);
+ break;
+ } else {
+ /* Truncate buffers used for padding spec */
+ inbound_frame_set_mark(iframe, 0);
+ }
+ }
+
+ rv = session_process_headers_frame(session);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ busy = 1;
+
+ if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
+ rv = nghttp2_session_add_rst_stream(
+ session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
+ break;
+ }
+
+ if (rv == NGHTTP2_ERR_IGN_HEADER_BLOCK) {
+ iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
+ break;
+ }
+
+ iframe->state = NGHTTP2_IB_READ_HEADER_BLOCK;
+
+ break;
+ case NGHTTP2_PRIORITY:
+ rv = session_process_priority_frame(session);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ session_inbound_frame_reset(session);
+
+ break;
+ case NGHTTP2_RST_STREAM:
+ rv = session_process_rst_stream_frame(session);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ session_inbound_frame_reset(session);
+
+ break;
+ case NGHTTP2_PUSH_PROMISE:
+ if (iframe->padlen == 0 &&
+ (iframe->frame.hd.flags & NGHTTP2_FLAG_PADDED)) {
+ padlen = inbound_frame_compute_pad(iframe);
+ if (padlen < 0) {
+ busy = 1;
+ rv = nghttp2_session_terminate_session_with_reason(
+ session, NGHTTP2_PROTOCOL_ERROR,
+ "PUSH_PROMISE: invalid padding");
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
+ break;
+ }
+
+ iframe->frame.push_promise.padlen = (size_t)padlen;
+
+ if (iframe->payloadleft < 4) {
+ busy = 1;
+ iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
+ break;
+ }
+
+ iframe->state = NGHTTP2_IB_READ_NBYTE;
+
+ inbound_frame_set_mark(iframe, 4);
+
+ break;
+ }
+
+ rv = session_process_push_promise_frame(session);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ busy = 1;
+
+ if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
+ rv = nghttp2_session_add_rst_stream(
+ session, iframe->frame.push_promise.promised_stream_id,
+ NGHTTP2_INTERNAL_ERROR);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
+ break;
+ }
+
+ if (rv == NGHTTP2_ERR_IGN_HEADER_BLOCK) {
+ iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
+ break;
+ }
+
+ iframe->state = NGHTTP2_IB_READ_HEADER_BLOCK;
+
+ break;
+ case NGHTTP2_PING:
+ rv = session_process_ping_frame(session);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ session_inbound_frame_reset(session);
+
+ break;
+ case NGHTTP2_GOAWAY: {
+ size_t debuglen;
+
+ /* 8 is Last-stream-ID + Error Code */
+ debuglen = iframe->frame.hd.length - 8;
+
+ if (debuglen > 0) {
+ iframe->raw_lbuf = nghttp2_mem_malloc(mem, debuglen);
+
+ if (iframe->raw_lbuf == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ nghttp2_buf_wrap_init(&iframe->lbuf, iframe->raw_lbuf, debuglen);
+ }
+
+ busy = 1;
+
+ iframe->state = NGHTTP2_IB_READ_GOAWAY_DEBUG;
+
+ break;
+ }
+ case NGHTTP2_WINDOW_UPDATE:
+ rv = session_process_window_update_frame(session);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ session_inbound_frame_reset(session);
+
+ break;
+ case NGHTTP2_ALTSVC: {
+ size_t origin_len;
+
+ origin_len = nghttp2_get_uint16(iframe->sbuf.pos);
+
+ DEBUGF("recv: origin_len=%zu\n", origin_len);
+
+ if (origin_len > iframe->payloadleft) {
+ busy = 1;
+ iframe->state = NGHTTP2_IB_FRAME_SIZE_ERROR;
+ break;
+ }
+
+ if (iframe->frame.hd.length > 2) {
+ iframe->raw_lbuf =
+ nghttp2_mem_malloc(mem, iframe->frame.hd.length - 2);
+
+ if (iframe->raw_lbuf == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ nghttp2_buf_wrap_init(&iframe->lbuf, iframe->raw_lbuf,
+ iframe->frame.hd.length);
+ }
+
+ busy = 1;
+
+ iframe->state = NGHTTP2_IB_READ_ALTSVC_PAYLOAD;
+
+ break;
+ }
+ default:
+ /* This is unknown frame */
+ session_inbound_frame_reset(session);
+
+ break;
+ }
+ break;
+ case NGHTTP2_IB_READ_HEADER_BLOCK:
+ case NGHTTP2_IB_IGN_HEADER_BLOCK: {
+ ssize_t data_readlen;
+ size_t trail_padlen;
+ int final;
+#ifdef DEBUGBUILD
+ if (iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK) {
+ DEBUGF("recv: [IB_READ_HEADER_BLOCK]\n");
+ } else {
+ DEBUGF("recv: [IB_IGN_HEADER_BLOCK]\n");
+ }
+#endif /* DEBUGBUILD */
+
+ readlen = inbound_frame_payload_readlen(iframe, in, last);
+
+ DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
+ iframe->payloadleft - readlen);
+
+ data_readlen = inbound_frame_effective_readlen(
+ iframe, iframe->payloadleft - readlen, readlen);
+ trail_padlen = nghttp2_frame_trail_padlen(&iframe->frame, iframe->padlen);
+
+ final = (iframe->frame.hd.flags & NGHTTP2_FLAG_END_HEADERS) &&
+ iframe->payloadleft - (size_t)data_readlen == trail_padlen;
+
+ if (data_readlen > 0 || (data_readlen == 0 && final)) {
+ size_t hd_proclen = 0;
+
+ DEBUGF("recv: block final=%d\n", final);
+
+ rv =
+ inflate_header_block(session, &iframe->frame, &hd_proclen,
+ (uint8_t *)in, (size_t)data_readlen, final,
+ iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ if (rv == NGHTTP2_ERR_PAUSE) {
+ in += hd_proclen;
+ iframe->payloadleft -= hd_proclen;
+
+ return in - first;
+ }
+
+ if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
+ /* The application says no more headers. We decompress the
+ rest of the header block but not invoke on_header_callback
+ and on_frame_recv_callback. */
+ in += hd_proclen;
+ iframe->payloadleft -= hd_proclen;
+
+ /* Use promised stream ID for PUSH_PROMISE */
+ rv = nghttp2_session_add_rst_stream(
+ session,
+ iframe->frame.hd.type == NGHTTP2_PUSH_PROMISE
+ ? iframe->frame.push_promise.promised_stream_id
+ : iframe->frame.hd.stream_id,
+ NGHTTP2_INTERNAL_ERROR);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ busy = 1;
+ iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
+ break;
+ }
+
+ in += readlen;
+ iframe->payloadleft -= readlen;
+
+ if (rv == NGHTTP2_ERR_HEADER_COMP) {
+ /* GOAWAY is already issued */
+ if (iframe->payloadleft == 0) {
+ session_inbound_frame_reset(session);
+ } else {
+ busy = 1;
+ iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
+ }
+ break;
+ }
+ } else {
+ in += readlen;
+ iframe->payloadleft -= readlen;
+ }
+
+ if (iframe->payloadleft) {
+ break;
+ }
+
+ if ((iframe->frame.hd.flags & NGHTTP2_FLAG_END_HEADERS) == 0) {
+
+ inbound_frame_set_mark(iframe, NGHTTP2_FRAME_HDLEN);
+
+ iframe->padlen = 0;
+
+ if (iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK) {
+ iframe->state = NGHTTP2_IB_EXPECT_CONTINUATION;
+ } else {
+ iframe->state = NGHTTP2_IB_IGN_CONTINUATION;
+ }
+ } else {
+ if (iframe->state == NGHTTP2_IB_READ_HEADER_BLOCK) {
+ rv = session_after_header_block_received(session);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+ session_inbound_frame_reset(session);
+ }
+ break;
+ }
+ case NGHTTP2_IB_IGN_PAYLOAD:
+ DEBUGF("recv: [IB_IGN_PAYLOAD]\n");
+
+ readlen = inbound_frame_payload_readlen(iframe, in, last);
+ iframe->payloadleft -= readlen;
+ in += readlen;
+
+ DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
+ iframe->payloadleft);
+
+ if (iframe->payloadleft) {
+ break;
+ }
+
+ switch (iframe->frame.hd.type) {
+ case NGHTTP2_HEADERS:
+ case NGHTTP2_PUSH_PROMISE:
+ case NGHTTP2_CONTINUATION:
+ /* Mark inflater bad so that we won't perform further decoding */
+ session->hd_inflater.ctx.bad = 1;
+ break;
+ default:
+ break;
+ }
+
+ session_inbound_frame_reset(session);
+
+ break;
+ case NGHTTP2_IB_FRAME_SIZE_ERROR:
+ DEBUGF("recv: [IB_FRAME_SIZE_ERROR]\n");
+
+ rv = session_handle_frame_size_error(session);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ busy = 1;
+
+ iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
+
+ break;
+ case NGHTTP2_IB_READ_SETTINGS:
+ DEBUGF("recv: [IB_READ_SETTINGS]\n");
+
+ readlen = inbound_frame_buf_read(iframe, in, last);
+ iframe->payloadleft -= readlen;
+ in += readlen;
+
+ DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
+ iframe->payloadleft);
+
+ if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
+ break;
+ }
+
+ if (readlen > 0) {
+ inbound_frame_set_settings_entry(iframe);
+ }
+ if (iframe->payloadleft) {
+ inbound_frame_set_mark(iframe, NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH);
+ break;
+ }
+
+ rv = session_process_settings_frame(session);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ session_inbound_frame_reset(session);
+
+ break;
+ case NGHTTP2_IB_READ_GOAWAY_DEBUG:
+ DEBUGF("recv: [IB_READ_GOAWAY_DEBUG]\n");
+
+ readlen = inbound_frame_payload_readlen(iframe, in, last);
+
+ if (readlen > 0) {
+ iframe->lbuf.last = nghttp2_cpymem(iframe->lbuf.last, in, readlen);
+
+ iframe->payloadleft -= readlen;
+ in += readlen;
+ }
+
+ DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
+ iframe->payloadleft);
+
+ if (iframe->payloadleft) {
+ assert(nghttp2_buf_avail(&iframe->lbuf) > 0);
+
+ break;
+ }
+
+ rv = session_process_goaway_frame(session);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ session_inbound_frame_reset(session);
+
+ break;
+ case NGHTTP2_IB_EXPECT_CONTINUATION:
+ case NGHTTP2_IB_IGN_CONTINUATION:
+#ifdef DEBUGBUILD
+ if (iframe->state == NGHTTP2_IB_EXPECT_CONTINUATION) {
+ fprintf(stderr, "recv: [IB_EXPECT_CONTINUATION]\n");
+ } else {
+ fprintf(stderr, "recv: [IB_IGN_CONTINUATION]\n");
+ }
+#endif /* DEBUGBUILD */
+
+ readlen = inbound_frame_buf_read(iframe, in, last);
+ in += readlen;
+
+ if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
+ return in - first;
+ }
+
+ nghttp2_frame_unpack_frame_hd(&cont_hd, iframe->sbuf.pos);
+ iframe->payloadleft = cont_hd.length;
+
+ DEBUGF("recv: payloadlen=%zu, type=%u, flags=0x%02x, stream_id=%d\n",
+ cont_hd.length, cont_hd.type, cont_hd.flags, cont_hd.stream_id);
+
+ if (cont_hd.type != NGHTTP2_CONTINUATION ||
+ cont_hd.stream_id != iframe->frame.hd.stream_id) {
+ DEBUGF("recv: expected stream_id=%d, type=%d, but got stream_id=%d, "
+ "type=%u\n",
+ iframe->frame.hd.stream_id, NGHTTP2_CONTINUATION,
+ cont_hd.stream_id, cont_hd.type);
+ rv = nghttp2_session_terminate_session_with_reason(
+ session, NGHTTP2_PROTOCOL_ERROR,
+ "unexpected non-CONTINUATION frame or stream_id is invalid");
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ busy = 1;
+
+ iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
+
+ break;
+ }
+
+ /* CONTINUATION won't bear NGHTTP2_PADDED flag */
+
+ iframe->frame.hd.flags = (uint8_t)(
+ iframe->frame.hd.flags | (cont_hd.flags & NGHTTP2_FLAG_END_HEADERS));
+ iframe->frame.hd.length += cont_hd.length;
+
+ busy = 1;
+
+ if (iframe->state == NGHTTP2_IB_EXPECT_CONTINUATION) {
+ iframe->state = NGHTTP2_IB_READ_HEADER_BLOCK;
+
+ rv = session_call_on_begin_frame(session, &cont_hd);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ } else {
+ iframe->state = NGHTTP2_IB_IGN_HEADER_BLOCK;
+ }
+
+ break;
+ case NGHTTP2_IB_READ_PAD_DATA:
+ DEBUGF("recv: [IB_READ_PAD_DATA]\n");
+
+ readlen = inbound_frame_buf_read(iframe, in, last);
+ in += readlen;
+ iframe->payloadleft -= readlen;
+
+ DEBUGF("recv: readlen=%zu, payloadleft=%zu, left=%zu\n", readlen,
+ iframe->payloadleft, nghttp2_buf_mark_avail(&iframe->sbuf));
+
+ if (nghttp2_buf_mark_avail(&iframe->sbuf)) {
+ return in - first;
+ }
+
+ /* Pad Length field is subject to flow control */
+ rv = session_update_recv_connection_window_size(session, readlen);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ /* Pad Length field is consumed immediately */
+ rv =
+ nghttp2_session_consume(session, iframe->frame.hd.stream_id, readlen);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ stream = nghttp2_session_get_stream(session, iframe->frame.hd.stream_id);
+ if (stream) {
+ rv = session_update_recv_stream_window_size(
+ session, stream, readlen,
+ iframe->payloadleft ||
+ (iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+
+ busy = 1;
+
+ padlen = inbound_frame_compute_pad(iframe);
+ if (padlen < 0) {
+ rv = nghttp2_session_terminate_session_with_reason(
+ session, NGHTTP2_PROTOCOL_ERROR, "DATA: invalid padding");
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ iframe->state = NGHTTP2_IB_IGN_DATA;
+ break;
+ }
+
+ iframe->frame.data.padlen = (size_t)padlen;
+
+ iframe->state = NGHTTP2_IB_READ_DATA;
+
+ break;
+ case NGHTTP2_IB_READ_DATA:
+ stream = nghttp2_session_get_stream(session, iframe->frame.hd.stream_id);
+
+ if (!stream) {
+ busy = 1;
+ iframe->state = NGHTTP2_IB_IGN_DATA;
+ break;
+ }
+
+ DEBUGF("recv: [IB_READ_DATA]\n");
+
+ readlen = inbound_frame_payload_readlen(iframe, in, last);
+ iframe->payloadleft -= readlen;
+ in += readlen;
+
+ DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
+ iframe->payloadleft);
+
+ if (readlen > 0) {
+ ssize_t data_readlen;
+
+ rv = session_update_recv_connection_window_size(session, readlen);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ rv = session_update_recv_stream_window_size(
+ session, stream, readlen,
+ iframe->payloadleft ||
+ (iframe->frame.hd.flags & NGHTTP2_FLAG_END_STREAM) == 0);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ data_readlen = inbound_frame_effective_readlen(
+ iframe, iframe->payloadleft, readlen);
+
+ if (data_readlen == -1) {
+ /* everything is padding */
+ data_readlen = 0;
+ }
+
+ padlen = (ssize_t)readlen - data_readlen;
+
+ if (padlen > 0) {
+ /* Padding is considered as "consumed" immediately */
+ rv = nghttp2_session_consume(session, iframe->frame.hd.stream_id,
+ (size_t)padlen);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+
+ DEBUGF("recv: data_readlen=%zd\n", data_readlen);
+
+ if (data_readlen > 0) {
+ if (session_enforce_http_messaging(session)) {
+ if (nghttp2_http_on_data_chunk(stream, (size_t)data_readlen) != 0) {
+ if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
+ /* Consume all data for connection immediately here */
+ rv = session_update_connection_consumed_size(
+ session, (size_t)data_readlen);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+
+ rv = nghttp2_session_add_rst_stream(
+ session, iframe->frame.hd.stream_id, NGHTTP2_PROTOCOL_ERROR);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ busy = 1;
+ iframe->state = NGHTTP2_IB_IGN_DATA;
+ break;
+ }
+ }
+ if (session->callbacks.on_data_chunk_recv_callback) {
+ rv = session->callbacks.on_data_chunk_recv_callback(
+ session, iframe->frame.hd.flags, iframe->frame.hd.stream_id,
+ in - readlen, (size_t)data_readlen, session->user_data);
+ if (rv == NGHTTP2_ERR_PAUSE) {
+ return in - first;
+ }
+
+ if (nghttp2_is_fatal(rv)) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+ }
+ }
+
+ if (iframe->payloadleft) {
+ break;
+ }
+
+ rv = session_process_data_frame(session);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ session_inbound_frame_reset(session);
+
+ break;
+ case NGHTTP2_IB_IGN_DATA:
+ DEBUGF("recv: [IB_IGN_DATA]\n");
+
+ readlen = inbound_frame_payload_readlen(iframe, in, last);
+ iframe->payloadleft -= readlen;
+ in += readlen;
+
+ DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
+ iframe->payloadleft);
+
+ if (readlen > 0) {
+ /* Update connection-level flow control window for ignored
+ DATA frame too */
+ rv = session_update_recv_connection_window_size(session, readlen);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
+
+ /* Ignored DATA is considered as "consumed" immediately. */
+ rv = session_update_connection_consumed_size(session, readlen);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+ }
+ }
+
+ if (iframe->payloadleft) {
+ break;
+ }
+
+ session_inbound_frame_reset(session);
+
+ break;
+ case NGHTTP2_IB_IGN_ALL:
+ return (ssize_t)inlen;
+ case NGHTTP2_IB_READ_EXTENSION_PAYLOAD:
+ DEBUGF("recv: [IB_READ_EXTENSION_PAYLOAD]\n");
+
+ readlen = inbound_frame_payload_readlen(iframe, in, last);
+ iframe->payloadleft -= readlen;
+ in += readlen;
+
+ DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
+ iframe->payloadleft);
+
+ if (readlen > 0) {
+ rv = session_call_on_extension_chunk_recv_callback(
+ session, in - readlen, readlen);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ if (rv != 0) {
+ busy = 1;
+
+ iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
+
+ break;
+ }
+ }
+
+ if (iframe->payloadleft > 0) {
+ break;
+ }
+
+ rv = session_process_extension_frame(session);
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ session_inbound_frame_reset(session);
+
+ break;
+ case NGHTTP2_IB_READ_ALTSVC_PAYLOAD:
+ DEBUGF("recv: [IB_READ_ALTSVC_PAYLOAD]\n");
+
+ readlen = inbound_frame_payload_readlen(iframe, in, last);
+
+ if (readlen > 0) {
+ iframe->lbuf.last = nghttp2_cpymem(iframe->lbuf.last, in, readlen);
+
+ iframe->payloadleft -= readlen;
+ in += readlen;
+ }
+
+ DEBUGF("recv: readlen=%zu, payloadleft=%zu\n", readlen,
+ iframe->payloadleft);
+
+ if (iframe->payloadleft) {
+ assert(nghttp2_buf_avail(&iframe->lbuf) > 0);
+
+ break;
+ }
+
+ rv = session_process_altsvc_frame(session);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ session_inbound_frame_reset(session);
+
+ break;
+ }
+
+ if (!busy && in == last) {
+ break;
+ }
+
+ busy = 0;
+ }
+
+ assert(in == last);
+
+ return in - first;
+}
+
+int nghttp2_session_recv(nghttp2_session *session) {
+ uint8_t buf[NGHTTP2_INBOUND_BUFFER_LENGTH];
+ while (1) {
+ ssize_t readlen;
+ readlen = session_recv(session, buf, sizeof(buf));
+ if (readlen > 0) {
+ ssize_t proclen = nghttp2_session_mem_recv(session, buf, (size_t)readlen);
+ if (proclen < 0) {
+ return (int)proclen;
+ }
+ assert(proclen == readlen);
+ } else if (readlen == 0 || readlen == NGHTTP2_ERR_WOULDBLOCK) {
+ return 0;
+ } else if (readlen == NGHTTP2_ERR_EOF) {
+ return NGHTTP2_ERR_EOF;
+ } else if (readlen < 0) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ }
+}
+
+/*
+ * Returns the number of active streams, which includes streams in
+ * reserved state.
+ */
+static size_t session_get_num_active_streams(nghttp2_session *session) {
+ return nghttp2_map_size(&session->streams) - session->num_closed_streams -
+ session->num_idle_streams;
+}
+
+int nghttp2_session_want_read(nghttp2_session *session) {
+ size_t num_active_streams;
+
+ /* If this flag is set, we don't want to read. The application
+ should drop the connection. */
+ if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_SENT) {
+ return 0;
+ }
+
+ num_active_streams = session_get_num_active_streams(session);
+
+ /* Unless termination GOAWAY is sent or received, we always want to
+ read incoming frames. */
+
+ if (num_active_streams > 0) {
+ return 1;
+ }
+
+ /* If there is no active streams and GOAWAY has been sent or
+ received, we are done with this session. */
+ return (session->goaway_flags &
+ (NGHTTP2_GOAWAY_SENT | NGHTTP2_GOAWAY_RECV)) == 0;
+}
+
+int nghttp2_session_want_write(nghttp2_session *session) {
+ /* If these flag is set, we don't want to write any data. The
+ application should drop the connection. */
+ if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_SENT) {
+ return 0;
+ }
+
+ /*
+ * Unless termination GOAWAY is sent or received, we want to write
+ * frames if there is pending ones. If pending frame is request/push
+ * response HEADERS and concurrent stream limit is reached, we don't
+ * want to write them.
+ */
+ return session->aob.item || nghttp2_outbound_queue_top(&session->ob_urgent) ||
+ nghttp2_outbound_queue_top(&session->ob_reg) ||
+ (!nghttp2_pq_empty(&session->root.obq) &&
+ session->remote_window_size > 0) ||
+ (nghttp2_outbound_queue_top(&session->ob_syn) &&
+ !session_is_outgoing_concurrent_streams_max(session));
+}
+
+int nghttp2_session_add_ping(nghttp2_session *session, uint8_t flags,
+ const uint8_t *opaque_data) {
+ int rv;
+ nghttp2_outbound_item *item;
+ nghttp2_frame *frame;
+ nghttp2_mem *mem;
+
+ mem = &session->mem;
+
+ if ((flags & NGHTTP2_FLAG_ACK) &&
+ session->obq_flood_counter_ >= NGHTTP2_MAX_OBQ_FLOOD_ITEM) {
+ return NGHTTP2_ERR_FLOODED;
+ }
+
+ item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
+ if (item == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ nghttp2_outbound_item_init(item);
+
+ frame = &item->frame;
+
+ nghttp2_frame_ping_init(&frame->ping, flags, opaque_data);
+
+ rv = nghttp2_session_add_item(session, item);
+
+ if (rv != 0) {
+ nghttp2_frame_ping_free(&frame->ping);
+ nghttp2_mem_free(mem, item);
+ return rv;
+ }
+
+ if (flags & NGHTTP2_FLAG_ACK) {
+ ++session->obq_flood_counter_;
+ }
+
+ return 0;
+}
+
+int nghttp2_session_add_goaway(nghttp2_session *session, int32_t last_stream_id,
+ uint32_t error_code, const uint8_t *opaque_data,
+ size_t opaque_data_len, uint8_t aux_flags) {
+ int rv;
+ nghttp2_outbound_item *item;
+ nghttp2_frame *frame;
+ uint8_t *opaque_data_copy = NULL;
+ nghttp2_goaway_aux_data *aux_data;
+ nghttp2_mem *mem;
+
+ mem = &session->mem;
+
+ if (nghttp2_session_is_my_stream_id(session, last_stream_id)) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ if (opaque_data_len) {
+ if (opaque_data_len + 8 > NGHTTP2_MAX_PAYLOADLEN) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+ opaque_data_copy = nghttp2_mem_malloc(mem, opaque_data_len);
+ if (opaque_data_copy == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+ memcpy(opaque_data_copy, opaque_data, opaque_data_len);
+ }
+
+ item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
+ if (item == NULL) {
+ nghttp2_mem_free(mem, opaque_data_copy);
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ nghttp2_outbound_item_init(item);
+
+ frame = &item->frame;
+
+ /* last_stream_id must not be increased from the value previously
+ sent */
+ last_stream_id = nghttp2_min(last_stream_id, session->local_last_stream_id);
+
+ nghttp2_frame_goaway_init(&frame->goaway, last_stream_id, error_code,
+ opaque_data_copy, opaque_data_len);
+
+ aux_data = &item->aux_data.goaway;
+ aux_data->flags = aux_flags;
+
+ rv = nghttp2_session_add_item(session, item);
+ if (rv != 0) {
+ nghttp2_frame_goaway_free(&frame->goaway, mem);
+ nghttp2_mem_free(mem, item);
+ return rv;
+ }
+ return 0;
+}
+
+int nghttp2_session_add_window_update(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id,
+ int32_t window_size_increment) {
+ int rv;
+ nghttp2_outbound_item *item;
+ nghttp2_frame *frame;
+ nghttp2_mem *mem;
+
+ mem = &session->mem;
+ item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
+ if (item == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ nghttp2_outbound_item_init(item);
+
+ frame = &item->frame;
+
+ nghttp2_frame_window_update_init(&frame->window_update, flags, stream_id,
+ window_size_increment);
+
+ rv = nghttp2_session_add_item(session, item);
+
+ if (rv != 0) {
+ nghttp2_frame_window_update_free(&frame->window_update);
+ nghttp2_mem_free(mem, item);
+ return rv;
+ }
+ return 0;
+}
+
+static void
+session_append_inflight_settings(nghttp2_session *session,
+ nghttp2_inflight_settings *settings) {
+ nghttp2_inflight_settings **i;
+
+ for (i = &session->inflight_settings_head; *i; i = &(*i)->next)
+ ;
+
+ *i = settings;
+}
+
+int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
+ const nghttp2_settings_entry *iv, size_t niv) {
+ nghttp2_outbound_item *item;
+ nghttp2_frame *frame;
+ nghttp2_settings_entry *iv_copy;
+ size_t i;
+ int rv;
+ nghttp2_mem *mem;
+ nghttp2_inflight_settings *inflight_settings = NULL;
+
+ mem = &session->mem;
+
+ if (flags & NGHTTP2_FLAG_ACK) {
+ if (niv != 0) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ if (session->obq_flood_counter_ >= NGHTTP2_MAX_OBQ_FLOOD_ITEM) {
+ return NGHTTP2_ERR_FLOODED;
+ }
+ }
+
+ if (!nghttp2_iv_check(iv, niv)) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
+ if (item == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ if (niv > 0) {
+ iv_copy = nghttp2_frame_iv_copy(iv, niv, mem);
+ if (iv_copy == NULL) {
+ nghttp2_mem_free(mem, item);
+ return NGHTTP2_ERR_NOMEM;
+ }
+ } else {
+ iv_copy = NULL;
+ }
+
+ if ((flags & NGHTTP2_FLAG_ACK) == 0) {
+ rv = inflight_settings_new(&inflight_settings, iv, niv, mem);
+ if (rv != 0) {
+ assert(nghttp2_is_fatal(rv));
+ nghttp2_mem_free(mem, iv_copy);
+ nghttp2_mem_free(mem, item);
+ return rv;
+ }
+ }
+
+ nghttp2_outbound_item_init(item);
+
+ frame = &item->frame;
+
+ nghttp2_frame_settings_init(&frame->settings, flags, iv_copy, niv);
+ rv = nghttp2_session_add_item(session, item);
+ if (rv != 0) {
+ /* The only expected error is fatal one */
+ assert(nghttp2_is_fatal(rv));
+
+ inflight_settings_del(inflight_settings, mem);
+
+ nghttp2_frame_settings_free(&frame->settings, mem);
+ nghttp2_mem_free(mem, item);
+
+ return rv;
+ }
+
+ if (flags & NGHTTP2_FLAG_ACK) {
+ ++session->obq_flood_counter_;
+ } else {
+ session_append_inflight_settings(session, inflight_settings);
+ }
+
+ /* Extract NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS and ENABLE_PUSH
+ here. We use it to refuse the incoming stream and PUSH_PROMISE
+ with RST_STREAM. */
+
+ for (i = niv; i > 0; --i) {
+ if (iv[i - 1].settings_id == NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS) {
+ session->pending_local_max_concurrent_stream = iv[i - 1].value;
+ break;
+ }
+ }
+
+ for (i = niv; i > 0; --i) {
+ if (iv[i - 1].settings_id == NGHTTP2_SETTINGS_ENABLE_PUSH) {
+ session->pending_enable_push = (uint8_t)iv[i - 1].value;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs,
+ size_t datamax, nghttp2_frame *frame,
+ nghttp2_data_aux_data *aux_data,
+ nghttp2_stream *stream) {
+ int rv;
+ uint32_t data_flags;
+ ssize_t payloadlen;
+ ssize_t padded_payloadlen;
+ nghttp2_buf *buf;
+ size_t max_payloadlen;
+
+ assert(bufs->head == bufs->cur);
+
+ buf = &bufs->cur->buf;
+
+ if (session->callbacks.read_length_callback) {
+
+ payloadlen = session->callbacks.read_length_callback(
+ session, frame->hd.type, stream->stream_id, session->remote_window_size,
+ stream->remote_window_size, session->remote_settings.max_frame_size,
+ session->user_data);
+
+ DEBUGF("send: read_length_callback=%zd\n", payloadlen);
+
+ payloadlen = nghttp2_session_enforce_flow_control_limits(session, stream,
+ payloadlen);
+
+ DEBUGF("send: read_length_callback after flow control=%zd\n", payloadlen);
+
+ if (payloadlen <= 0) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ if ((size_t)payloadlen > nghttp2_buf_avail(buf)) {
+ /* Resize the current buffer(s). The reason why we do +1 for
+ buffer size is for possible padding field. */
+ rv = nghttp2_bufs_realloc(&session->aob.framebufs,
+ (size_t)(NGHTTP2_FRAME_HDLEN + 1 + payloadlen));
+
+ if (rv != 0) {
+ DEBUGF("send: realloc buffer failed rv=%d", rv);
+ /* If reallocation failed, old buffers are still in tact. So
+ use safe limit. */
+ payloadlen = (ssize_t)datamax;
+
+ DEBUGF("send: use safe limit payloadlen=%zd", payloadlen);
+ } else {
+ assert(&session->aob.framebufs == bufs);
+
+ buf = &bufs->cur->buf;
+ }
+ }
+ datamax = (size_t)payloadlen;
+ }
+
+ /* Current max DATA length is less then buffer chunk size */
+ assert(nghttp2_buf_avail(buf) >= datamax);
+
+ data_flags = NGHTTP2_DATA_FLAG_NONE;
+ payloadlen = aux_data->data_prd.read_callback(
+ session, frame->hd.stream_id, buf->pos, datamax, &data_flags,
+ &aux_data->data_prd.source, session->user_data);
+
+ if (payloadlen == NGHTTP2_ERR_DEFERRED ||
+ payloadlen == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE ||
+ payloadlen == NGHTTP2_ERR_PAUSE) {
+ DEBUGF("send: DATA postponed due to %s\n",
+ nghttp2_strerror((int)payloadlen));
+
+ return (int)payloadlen;
+ }
+
+ if (payloadlen < 0 || datamax < (size_t)payloadlen) {
+ /* This is the error code when callback is failed. */
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+
+ buf->last = buf->pos + payloadlen;
+ buf->pos -= NGHTTP2_FRAME_HDLEN;
+
+ /* Clear flags, because this may contain previous flags of previous
+ DATA */
+ frame->hd.flags = NGHTTP2_FLAG_NONE;
+
+ if (data_flags & NGHTTP2_DATA_FLAG_EOF) {
+ aux_data->eof = 1;
+ /* If NGHTTP2_DATA_FLAG_NO_END_STREAM is set, don't set
+ NGHTTP2_FLAG_END_STREAM */
+ if ((aux_data->flags & NGHTTP2_FLAG_END_STREAM) &&
+ (data_flags & NGHTTP2_DATA_FLAG_NO_END_STREAM) == 0) {
+ frame->hd.flags |= NGHTTP2_FLAG_END_STREAM;
+ }
+ }
+
+ if (data_flags & NGHTTP2_DATA_FLAG_NO_COPY) {
+ if (session->callbacks.send_data_callback == NULL) {
+ DEBUGF("NGHTTP2_DATA_FLAG_NO_COPY requires send_data_callback set\n");
+
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
+ aux_data->no_copy = 1;
+ }
+
+ frame->hd.length = (size_t)payloadlen;
+ frame->data.padlen = 0;
+
+ max_payloadlen = nghttp2_min(datamax, frame->hd.length + NGHTTP2_MAX_PADLEN);
+
+ padded_payloadlen =
+ session_call_select_padding(session, frame, max_payloadlen);
+
+ if (nghttp2_is_fatal((int)padded_payloadlen)) {
+ return (int)padded_payloadlen;
+ }
+
+ frame->data.padlen = (size_t)(padded_payloadlen - payloadlen);
+
+ nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
+
+ rv = nghttp2_frame_add_pad(bufs, &frame->hd, frame->data.padlen,
+ aux_data->no_copy);
+ if (rv != 0) {
+ return rv;
+ }
+
+ reschedule_stream(stream);
+
+ if (frame->hd.length == 0 && (data_flags & NGHTTP2_DATA_FLAG_EOF) &&
+ (data_flags & NGHTTP2_DATA_FLAG_NO_END_STREAM)) {
+ /* DATA payload length is 0, and DATA frame does not bear
+ END_STREAM. In this case, there is no point to send 0 length
+ DATA frame. */
+ return NGHTTP2_ERR_CANCEL;
+ }
+
+ return 0;
+}
+
+void *nghttp2_session_get_stream_user_data(nghttp2_session *session,
+ int32_t stream_id) {
+ nghttp2_stream *stream;
+ stream = nghttp2_session_get_stream(session, stream_id);
+ if (stream) {
+ return stream->stream_user_data;
+ } else {
+ return NULL;
+ }
+}
+
+int nghttp2_session_set_stream_user_data(nghttp2_session *session,
+ int32_t stream_id,
+ void *stream_user_data) {
+ nghttp2_stream *stream;
+ stream = nghttp2_session_get_stream(session, stream_id);
+ if (!stream) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+ stream->stream_user_data = stream_user_data;
+ return 0;
+}
+
+int nghttp2_session_resume_data(nghttp2_session *session, int32_t stream_id) {
+ int rv;
+ nghttp2_stream *stream;
+ stream = nghttp2_session_get_stream(session, stream_id);
+ if (stream == NULL || !nghttp2_stream_check_deferred_item(stream)) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ rv = nghttp2_stream_resume_deferred_item(stream,
+ NGHTTP2_STREAM_FLAG_DEFERRED_USER);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ return 0;
+}
+
+size_t nghttp2_session_get_outbound_queue_size(nghttp2_session *session) {
+ return nghttp2_outbound_queue_size(&session->ob_urgent) +
+ nghttp2_outbound_queue_size(&session->ob_reg) +
+ nghttp2_outbound_queue_size(&session->ob_syn);
+ /* TODO account for item attached to stream */
+}
+
+int32_t
+nghttp2_session_get_stream_effective_recv_data_length(nghttp2_session *session,
+ int32_t stream_id) {
+ nghttp2_stream *stream;
+ stream = nghttp2_session_get_stream(session, stream_id);
+ if (stream == NULL) {
+ return -1;
+ }
+ return stream->recv_window_size < 0 ? 0 : stream->recv_window_size;
+}
+
+int32_t
+nghttp2_session_get_stream_effective_local_window_size(nghttp2_session *session,
+ int32_t stream_id) {
+ nghttp2_stream *stream;
+ stream = nghttp2_session_get_stream(session, stream_id);
+ if (stream == NULL) {
+ return -1;
+ }
+ return stream->local_window_size;
+}
+
+int32_t nghttp2_session_get_stream_local_window_size(nghttp2_session *session,
+ int32_t stream_id) {
+ nghttp2_stream *stream;
+ int32_t size;
+ stream = nghttp2_session_get_stream(session, stream_id);
+ if (stream == NULL) {
+ return -1;
+ }
+
+ size = stream->local_window_size - stream->recv_window_size;
+
+ /* size could be negative if local endpoint reduced
+ SETTINGS_INITIAL_WINDOW_SIZE */
+ if (size < 0) {
+ return 0;
+ }
+
+ return size;
+}
+
+int32_t
+nghttp2_session_get_effective_recv_data_length(nghttp2_session *session) {
+ return session->recv_window_size < 0 ? 0 : session->recv_window_size;
+}
+
+int32_t
+nghttp2_session_get_effective_local_window_size(nghttp2_session *session) {
+ return session->local_window_size;
+}
+
+int32_t nghttp2_session_get_local_window_size(nghttp2_session *session) {
+ return session->local_window_size - session->recv_window_size;
+}
+
+int32_t nghttp2_session_get_stream_remote_window_size(nghttp2_session *session,
+ int32_t stream_id) {
+ nghttp2_stream *stream;
+
+ stream = nghttp2_session_get_stream(session, stream_id);
+ if (stream == NULL) {
+ return -1;
+ }
+
+ /* stream->remote_window_size can be negative when
+ SETTINGS_INITIAL_WINDOW_SIZE is changed. */
+ return nghttp2_max(0, stream->remote_window_size);
+}
+
+int32_t nghttp2_session_get_remote_window_size(nghttp2_session *session) {
+ return session->remote_window_size;
+}
+
+uint32_t nghttp2_session_get_remote_settings(nghttp2_session *session,
+ nghttp2_settings_id id) {
+ switch (id) {
+ case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
+ return session->remote_settings.header_table_size;
+ case NGHTTP2_SETTINGS_ENABLE_PUSH:
+ return session->remote_settings.enable_push;
+ case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
+ return session->remote_settings.max_concurrent_streams;
+ case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
+ return session->remote_settings.initial_window_size;
+ case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
+ return session->remote_settings.max_frame_size;
+ case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
+ return session->remote_settings.max_header_list_size;
+ }
+
+ assert(0);
+ abort(); /* if NDEBUG is set */
+}
+
+uint32_t nghttp2_session_get_local_settings(nghttp2_session *session,
+ nghttp2_settings_id id) {
+ switch (id) {
+ case NGHTTP2_SETTINGS_HEADER_TABLE_SIZE:
+ return session->local_settings.header_table_size;
+ case NGHTTP2_SETTINGS_ENABLE_PUSH:
+ return session->local_settings.enable_push;
+ case NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS:
+ return session->local_settings.max_concurrent_streams;
+ case NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE:
+ return session->local_settings.initial_window_size;
+ case NGHTTP2_SETTINGS_MAX_FRAME_SIZE:
+ return session->local_settings.max_frame_size;
+ case NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE:
+ return session->local_settings.max_header_list_size;
+ }
+
+ assert(0);
+ abort(); /* if NDEBUG is set */
+}
+
+static int nghttp2_session_upgrade_internal(nghttp2_session *session,
+ const uint8_t *settings_payload,
+ size_t settings_payloadlen,
+ void *stream_user_data) {
+ nghttp2_stream *stream;
+ nghttp2_frame frame;
+ nghttp2_settings_entry *iv;
+ size_t niv;
+ int rv;
+ nghttp2_priority_spec pri_spec;
+ nghttp2_mem *mem;
+
+ mem = &session->mem;
+
+ if ((!session->server && session->next_stream_id != 1) ||
+ (session->server && session->last_recv_stream_id >= 1)) {
+ return NGHTTP2_ERR_PROTO;
+ }
+ if (settings_payloadlen % NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+ rv = nghttp2_frame_unpack_settings_payload2(&iv, &niv, settings_payload,
+ settings_payloadlen, mem);
+ if (rv != 0) {
+ return rv;
+ }
+
+ if (session->server) {
+ nghttp2_frame_hd_init(&frame.hd, settings_payloadlen, NGHTTP2_SETTINGS,
+ NGHTTP2_FLAG_NONE, 0);
+ frame.settings.iv = iv;
+ frame.settings.niv = niv;
+ rv = nghttp2_session_on_settings_received(session, &frame, 1 /* No ACK */);
+ } else {
+ rv = nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, niv);
+ }
+ nghttp2_mem_free(mem, iv);
+ if (rv != 0) {
+ return rv;
+ }
+
+ nghttp2_priority_spec_default_init(&pri_spec);
+
+ stream = nghttp2_session_open_stream(
+ session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec, NGHTTP2_STREAM_OPENING,
+ session->server ? NULL : stream_user_data);
+ if (stream == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ /* We don't call nghttp2_session_adjust_closed_stream(), since this
+ should be the first stream open. */
+
+ if (session->server) {
+ nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
+ session->last_recv_stream_id = 1;
+ session->last_proc_stream_id = 1;
+ } else {
+ nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
+ session->last_sent_stream_id = 1;
+ session->next_stream_id += 2;
+ }
+ return 0;
+}
+
+int nghttp2_session_upgrade(nghttp2_session *session,
+ const uint8_t *settings_payload,
+ size_t settings_payloadlen,
+ void *stream_user_data) {
+ int rv;
+ nghttp2_stream *stream;
+
+ rv = nghttp2_session_upgrade_internal(session, settings_payload,
+ settings_payloadlen, stream_user_data);
+ if (rv != 0) {
+ return rv;
+ }
+
+ stream = nghttp2_session_get_stream(session, 1);
+ assert(stream);
+
+ /* We have no information about request header fields when Upgrade
+ was happened. So we don't know the request method here. If
+ request method is HEAD, we have a trouble because we may have
+ nonzero content-length header field in response headers, and we
+ will going to check it against the actual DATA frames, but we may
+ get mismatch because HEAD response body must be empty. Because
+ of this reason, nghttp2_session_upgrade() was deprecated in favor
+ of nghttp2_session_upgrade2(), which has |head_request| parameter
+ to indicate that request method is HEAD or not. */
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND;
+ return 0;
+}
+
+int nghttp2_session_upgrade2(nghttp2_session *session,
+ const uint8_t *settings_payload,
+ size_t settings_payloadlen, int head_request,
+ void *stream_user_data) {
+ int rv;
+ nghttp2_stream *stream;
+
+ rv = nghttp2_session_upgrade_internal(session, settings_payload,
+ settings_payloadlen, stream_user_data);
+ if (rv != 0) {
+ return rv;
+ }
+
+ stream = nghttp2_session_get_stream(session, 1);
+ assert(stream);
+
+ if (head_request) {
+ stream->http_flags |= NGHTTP2_HTTP_FLAG_METH_HEAD;
+ }
+
+ return 0;
+}
+
+int nghttp2_session_get_stream_local_close(nghttp2_session *session,
+ int32_t stream_id) {
+ nghttp2_stream *stream;
+
+ stream = nghttp2_session_get_stream(session, stream_id);
+
+ if (!stream) {
+ return -1;
+ }
+
+ return (stream->shut_flags & NGHTTP2_SHUT_WR) != 0;
+}
+
+int nghttp2_session_get_stream_remote_close(nghttp2_session *session,
+ int32_t stream_id) {
+ nghttp2_stream *stream;
+
+ stream = nghttp2_session_get_stream(session, stream_id);
+
+ if (!stream) {
+ return -1;
+ }
+
+ return (stream->shut_flags & NGHTTP2_SHUT_RD) != 0;
+}
+
+int nghttp2_session_consume(nghttp2_session *session, int32_t stream_id,
+ size_t size) {
+ int rv;
+ nghttp2_stream *stream;
+
+ if (stream_id == 0) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) {
+ return NGHTTP2_ERR_INVALID_STATE;
+ }
+
+ rv = session_update_connection_consumed_size(session, size);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ stream = nghttp2_session_get_stream(session, stream_id);
+
+ if (!stream) {
+ return 0;
+ }
+
+ rv = session_update_stream_consumed_size(session, stream, size);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ return 0;
+}
+
+int nghttp2_session_consume_connection(nghttp2_session *session, size_t size) {
+ int rv;
+
+ if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) {
+ return NGHTTP2_ERR_INVALID_STATE;
+ }
+
+ rv = session_update_connection_consumed_size(session, size);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ return 0;
+}
+
+int nghttp2_session_consume_stream(nghttp2_session *session, int32_t stream_id,
+ size_t size) {
+ int rv;
+ nghttp2_stream *stream;
+
+ if (stream_id == 0) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ if (!(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE)) {
+ return NGHTTP2_ERR_INVALID_STATE;
+ }
+
+ stream = nghttp2_session_get_stream(session, stream_id);
+
+ if (!stream) {
+ return 0;
+ }
+
+ rv = session_update_stream_consumed_size(session, stream, size);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ return 0;
+}
+
+int nghttp2_session_set_next_stream_id(nghttp2_session *session,
+ int32_t next_stream_id) {
+ if (next_stream_id <= 0 ||
+ session->next_stream_id > (uint32_t)next_stream_id) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ if (session->server) {
+ if (next_stream_id % 2) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+ } else if (next_stream_id % 2 == 0) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ session->next_stream_id = (uint32_t)next_stream_id;
+ return 0;
+}
+
+uint32_t nghttp2_session_get_next_stream_id(nghttp2_session *session) {
+ return session->next_stream_id;
+}
+
+int32_t nghttp2_session_get_last_proc_stream_id(nghttp2_session *session) {
+ return session->last_proc_stream_id;
+}
+
+nghttp2_stream *nghttp2_session_find_stream(nghttp2_session *session,
+ int32_t stream_id) {
+ if (stream_id == 0) {
+ return &session->root;
+ }
+
+ return nghttp2_session_get_stream_raw(session, stream_id);
+}
+
+nghttp2_stream *nghttp2_session_get_root_stream(nghttp2_session *session) {
+ return &session->root;
+}
+
+int nghttp2_session_check_server_session(nghttp2_session *session) {
+ return session->server;
+}
+
+int nghttp2_session_change_stream_priority(
+ nghttp2_session *session, int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec) {
+ int rv;
+ nghttp2_stream *stream;
+ nghttp2_priority_spec pri_spec_copy;
+
+ if (stream_id == 0 || stream_id == pri_spec->stream_id) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ stream = nghttp2_session_get_stream_raw(session, stream_id);
+ if (!stream) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ pri_spec_copy = *pri_spec;
+ nghttp2_priority_spec_normalize_weight(&pri_spec_copy);
+
+ rv = nghttp2_session_reprioritize_stream(session, stream, &pri_spec_copy);
+
+ if (nghttp2_is_fatal(rv)) {
+ return rv;
+ }
+
+ /* We don't intentionally call nghttp2_session_adjust_idle_stream()
+ so that idle stream created by this function, and existing ones
+ are kept for application. We will adjust number of idle stream
+ in nghttp2_session_mem_send or nghttp2_session_mem_recv is
+ called. */
+ return 0;
+}
+
+int nghttp2_session_create_idle_stream(nghttp2_session *session,
+ int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec) {
+ nghttp2_stream *stream;
+ nghttp2_priority_spec pri_spec_copy;
+
+ if (stream_id == 0 || stream_id == pri_spec->stream_id ||
+ !session_detect_idle_stream(session, stream_id)) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ stream = nghttp2_session_get_stream_raw(session, stream_id);
+ if (stream) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ pri_spec_copy = *pri_spec;
+ nghttp2_priority_spec_normalize_weight(&pri_spec_copy);
+
+ stream =
+ nghttp2_session_open_stream(session, stream_id, NGHTTP2_STREAM_FLAG_NONE,
+ &pri_spec_copy, NGHTTP2_STREAM_IDLE, NULL);
+ if (!stream) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ /* We don't intentionally call nghttp2_session_adjust_idle_stream()
+ so that idle stream created by this function, and existing ones
+ are kept for application. We will adjust number of idle stream
+ in nghttp2_session_mem_send or nghttp2_session_mem_recv is
+ called. */
+ return 0;
+}
+
+size_t
+nghttp2_session_get_hd_inflate_dynamic_table_size(nghttp2_session *session) {
+ return nghttp2_hd_inflate_get_dynamic_table_size(&session->hd_inflater);
+}
+
+size_t
+nghttp2_session_get_hd_deflate_dynamic_table_size(nghttp2_session *session) {
+ return nghttp2_hd_deflate_get_dynamic_table_size(&session->hd_deflater);
+}
+
+void nghttp2_session_set_user_data(nghttp2_session *session, void *user_data) {
+ session->user_data = user_data;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_session.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_session.h
new file mode 100644
index 00000000..c67781f8
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_session.h
@@ -0,0 +1,860 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_SESSION_H
+#define NGHTTP2_SESSION_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+#include "nghttp2_map.h"
+#include "nghttp2_frame.h"
+#include "nghttp2_hd.h"
+#include "nghttp2_stream.h"
+#include "nghttp2_outbound_item.h"
+#include "nghttp2_int.h"
+#include "nghttp2_buf.h"
+#include "nghttp2_callbacks.h"
+#include "nghttp2_mem.h"
+
+/* The global variable for tests where we want to disable strict
+ preface handling. */
+extern int nghttp2_enable_strict_preface;
+
+/*
+ * Option flags.
+ */
+typedef enum {
+ NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE = 1 << 0,
+ NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC = 1 << 1,
+ NGHTTP2_OPTMASK_NO_HTTP_MESSAGING = 1 << 2,
+ NGHTTP2_OPTMASK_NO_AUTO_PING_ACK = 1 << 3,
+ NGHTTP2_OPTMASK_NO_CLOSED_STREAMS = 1 << 4
+} nghttp2_optmask;
+
+/*
+ * bitmask for built-in type to enable the default handling for that
+ * type of the frame.
+ */
+typedef enum {
+ NGHTTP2_TYPEMASK_NONE = 0,
+ NGHTTP2_TYPEMASK_ALTSVC = 1 << 0
+} nghttp2_typemask;
+
+typedef enum {
+ NGHTTP2_OB_POP_ITEM,
+ NGHTTP2_OB_SEND_DATA,
+ NGHTTP2_OB_SEND_NO_COPY,
+ NGHTTP2_OB_SEND_CLIENT_MAGIC
+} nghttp2_outbound_state;
+
+typedef struct {
+ nghttp2_outbound_item *item;
+ nghttp2_bufs framebufs;
+ nghttp2_outbound_state state;
+} nghttp2_active_outbound_item;
+
+/* Buffer length for inbound raw byte stream used in
+ nghttp2_session_recv(). */
+#define NGHTTP2_INBOUND_BUFFER_LENGTH HTTP2_RECV_BUFFER_LENGHT
+
+/* The default maximum number of incoming reserved streams */
+#define NGHTTP2_MAX_INCOMING_RESERVED_STREAMS 200
+
+/* Even if we have less SETTINGS_MAX_CONCURRENT_STREAMS than this
+ number, we keep NGHTTP2_MIN_IDLE_STREAMS streams in idle state */
+#define NGHTTP2_MIN_IDLE_STREAMS 16
+
+/* The maximum number of items in outbound queue, which is considered
+ as flooding caused by peer. All frames are not considered here.
+ We only consider PING + ACK and SETTINGS + ACK. This is because
+ they both are response to the frame initiated by peer and peer can
+ send as many of them as they want. If peer does not read network,
+ response frames are stacked up, which leads to memory exhaustion.
+ The value selected here is arbitrary, but safe value and if we have
+ these frames in this number, it is considered suspicious. */
+#define NGHTTP2_MAX_OBQ_FLOOD_ITEM 10000
+
+/* The default value of maximum number of concurrent streams. */
+#define NGHTTP2_DEFAULT_MAX_CONCURRENT_STREAMS 0xffffffffu
+
+/* Internal state when receiving incoming frame */
+typedef enum {
+ /* Receiving frame header */
+ NGHTTP2_IB_READ_CLIENT_MAGIC,
+ NGHTTP2_IB_READ_FIRST_SETTINGS,
+ NGHTTP2_IB_READ_HEAD,
+ NGHTTP2_IB_READ_NBYTE,
+ NGHTTP2_IB_READ_HEADER_BLOCK,
+ NGHTTP2_IB_IGN_HEADER_BLOCK,
+ NGHTTP2_IB_IGN_PAYLOAD,
+ NGHTTP2_IB_FRAME_SIZE_ERROR,
+ NGHTTP2_IB_READ_SETTINGS,
+ NGHTTP2_IB_READ_GOAWAY_DEBUG,
+ NGHTTP2_IB_EXPECT_CONTINUATION,
+ NGHTTP2_IB_IGN_CONTINUATION,
+ NGHTTP2_IB_READ_PAD_DATA,
+ NGHTTP2_IB_READ_DATA,
+ NGHTTP2_IB_IGN_DATA,
+ NGHTTP2_IB_IGN_ALL,
+ NGHTTP2_IB_READ_ALTSVC_PAYLOAD,
+ NGHTTP2_IB_READ_EXTENSION_PAYLOAD
+} nghttp2_inbound_state;
+
+typedef struct {
+ nghttp2_frame frame;
+ /* Storage for extension frame payload. frame->ext.payload points
+ to this structure to avoid frequent memory allocation. */
+ nghttp2_ext_frame_payload ext_frame_payload;
+ /* The received SETTINGS entry. For the standard settings entries,
+ we only keep the last seen value. For
+ SETTINGS_HEADER_TABLE_SIZE, we also keep minimum value in the
+ last index. */
+ nghttp2_settings_entry *iv;
+ /* buffer pointers to small buffer, raw_sbuf */
+ nghttp2_buf sbuf;
+ /* buffer pointers to large buffer, raw_lbuf */
+ nghttp2_buf lbuf;
+ /* Large buffer, malloced on demand */
+ uint8_t *raw_lbuf;
+ /* The number of entry filled in |iv| */
+ size_t niv;
+ /* The number of entries |iv| can store. */
+ size_t max_niv;
+ /* How many bytes we still need to receive for current frame */
+ size_t payloadleft;
+ /* padding length for the current frame */
+ size_t padlen;
+ nghttp2_inbound_state state;
+ /* Small buffer. Currently the largest contiguous chunk to buffer
+ is frame header. We buffer part of payload, but they are smaller
+ than frame header. */
+ uint8_t raw_sbuf[NGHTTP2_FRAME_HDLEN];
+} nghttp2_inbound_frame;
+
+typedef struct {
+ uint32_t header_table_size;
+ uint32_t enable_push;
+ uint32_t max_concurrent_streams;
+ uint32_t initial_window_size;
+ uint32_t max_frame_size;
+ uint32_t max_header_list_size;
+} nghttp2_settings_storage;
+
+typedef enum {
+ NGHTTP2_GOAWAY_NONE = 0,
+ /* Flag means that connection should be terminated after sending GOAWAY. */
+ NGHTTP2_GOAWAY_TERM_ON_SEND = 0x1,
+ /* Flag means GOAWAY to terminate session has been sent */
+ NGHTTP2_GOAWAY_TERM_SENT = 0x2,
+ /* Flag means GOAWAY was sent */
+ NGHTTP2_GOAWAY_SENT = 0x4,
+ /* Flag means GOAWAY was received */
+ NGHTTP2_GOAWAY_RECV = 0x8
+} nghttp2_goaway_flag;
+
+/* nghttp2_inflight_settings stores the SETTINGS entries which local
+ endpoint has sent to the remote endpoint, and has not received ACK
+ yet. */
+struct nghttp2_inflight_settings {
+ struct nghttp2_inflight_settings *next;
+ nghttp2_settings_entry *iv;
+ size_t niv;
+};
+
+typedef struct nghttp2_inflight_settings nghttp2_inflight_settings;
+
+struct nghttp2_session {
+ nghttp2_map /* */ streams;
+ /* root of dependency tree*/
+ nghttp2_stream root;
+ /* Queue for outbound urgent frames (PING and SETTINGS) */
+ nghttp2_outbound_queue ob_urgent;
+ /* Queue for non-DATA frames */
+ nghttp2_outbound_queue ob_reg;
+ /* Queue for outbound stream-creating HEADERS (request or push
+ response) frame, which are subject to
+ SETTINGS_MAX_CONCURRENT_STREAMS limit. */
+ nghttp2_outbound_queue ob_syn;
+ nghttp2_active_outbound_item aob;
+ nghttp2_inbound_frame iframe;
+ nghttp2_hd_deflater hd_deflater;
+ nghttp2_hd_inflater hd_inflater;
+ nghttp2_session_callbacks callbacks;
+ /* Memory allocator */
+ nghttp2_mem mem;
+ /* Base value when we schedule next DATA frame write. This is
+ updated when one frame was written. */
+ uint64_t last_cycle;
+ void *user_data;
+ /* Points to the latest incoming closed stream. NULL if there is no
+ closed stream. Only used when session is initialized as
+ server. */
+ nghttp2_stream *closed_stream_head;
+ /* Points to the oldest incoming closed stream. NULL if there is no
+ closed stream. Only used when session is initialized as
+ server. */
+ nghttp2_stream *closed_stream_tail;
+ /* Points to the latest idle stream. NULL if there is no idle
+ stream. Only used when session is initialized as server .*/
+ nghttp2_stream *idle_stream_head;
+ /* Points to the oldest idle stream. NULL if there is no idle
+ stream. Only used when session is initialized as erver. */
+ nghttp2_stream *idle_stream_tail;
+ /* Queue of In-flight SETTINGS values. SETTINGS bearing ACK is not
+ considered as in-flight. */
+ nghttp2_inflight_settings *inflight_settings_head;
+ /* The number of outgoing streams. This will be capped by
+ remote_settings.max_concurrent_streams. */
+ size_t num_outgoing_streams;
+ /* The number of incoming streams. This will be capped by
+ local_settings.max_concurrent_streams. */
+ size_t num_incoming_streams;
+ /* The number of incoming reserved streams. This is the number of
+ streams in reserved (remote) state. RFC 7540 does not limit this
+ number. nghttp2 offers
+ nghttp2_option_set_max_reserved_remote_streams() to achieve this.
+ If it is used, num_incoming_streams is capped by
+ max_incoming_reserved_streams. Client application should
+ consider to set this because without that server can send
+ arbitrary number of PUSH_PROMISE, and exhaust client's memory. */
+ size_t num_incoming_reserved_streams;
+ /* The maximum number of incoming reserved streams (reserved
+ (remote) state). RST_STREAM will be sent for the pushed stream
+ which exceeds this limit. */
+ size_t max_incoming_reserved_streams;
+ /* The number of closed streams still kept in |streams| hash. The
+ closed streams can be accessed through single linked list
+ |closed_stream_head|. The current implementation only keeps
+ incoming streams and session is initialized as server. */
+ size_t num_closed_streams;
+ /* The number of idle streams kept in |streams| hash. The idle
+ streams can be accessed through doubly linked list
+ |idle_stream_head|. The current implementation only keeps idle
+ streams if session is initialized as server. */
+ size_t num_idle_streams;
+ /* The number of bytes allocated for nvbuf */
+ size_t nvbuflen;
+ /* Counter for detecting flooding in outbound queue */
+ size_t obq_flood_counter_;
+ /* The maximum length of header block to send. Calculated by the
+ same way as nghttp2_hd_deflate_bound() does. */
+ size_t max_send_header_block_length;
+ /* Next Stream ID. Made unsigned int to detect >= (1 << 31). */
+ uint32_t next_stream_id;
+ /* The last stream ID this session initiated. For client session,
+ this is the last stream ID it has sent. For server session, it
+ is the last promised stream ID sent in PUSH_PROMISE. */
+ int32_t last_sent_stream_id;
+ /* The largest stream ID received so far */
+ int32_t last_recv_stream_id;
+ /* The largest stream ID which has been processed in some way. This
+ value will be used as last-stream-id when sending GOAWAY
+ frame. */
+ int32_t last_proc_stream_id;
+ /* Counter of unique ID of PING. Wraps when it exceeds
+ NGHTTP2_MAX_UNIQUE_ID */
+ uint32_t next_unique_id;
+ /* This is the last-stream-ID we have sent in GOAWAY */
+ int32_t local_last_stream_id;
+ /* This is the value in GOAWAY frame received from remote endpoint. */
+ int32_t remote_last_stream_id;
+ /* Current sender window size. This value is computed against the
+ current initial window size of remote endpoint. */
+ int32_t remote_window_size;
+ /* Keep track of the number of bytes received without
+ WINDOW_UPDATE. This could be negative after submitting negative
+ value to WINDOW_UPDATE. */
+ int32_t recv_window_size;
+ /* The number of bytes consumed by the application and now is
+ subject to WINDOW_UPDATE. This is only used when auto
+ WINDOW_UPDATE is turned off. */
+ int32_t consumed_size;
+ /* The amount of recv_window_size cut using submitting negative
+ value to WINDOW_UPDATE */
+ int32_t recv_reduction;
+ /* window size for local flow control. It is initially set to
+ NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE and could be
+ increased/decreased by submitting WINDOW_UPDATE. See
+ nghttp2_submit_window_update(). */
+ int32_t local_window_size;
+ /* Settings value received from the remote endpoint. We just use ID
+ as index. The index = 0 is unused. */
+ nghttp2_settings_storage remote_settings;
+ /* Settings value of the local endpoint. */
+ nghttp2_settings_storage local_settings;
+ /* Option flags. This is bitwise-OR of 0 or more of nghttp2_optmask. */
+ uint32_t opt_flags;
+ /* Unacked local SETTINGS_MAX_CONCURRENT_STREAMS value. We use this
+ to refuse the incoming stream if it exceeds this value. */
+ uint32_t pending_local_max_concurrent_stream;
+ /* The bitwise OR of zero or more of nghttp2_typemask to indicate
+ that the default handling of extension frame is enabled. */
+ uint32_t builtin_recv_ext_types;
+ /* Unacked local ENABLE_PUSH value. We use this to refuse
+ PUSH_PROMISE before SETTINGS ACK is received. */
+ uint8_t pending_enable_push;
+ /* Nonzero if the session is server side. */
+ uint8_t server;
+ /* Flags indicating GOAWAY is sent and/or received. The flags are
+ composed by bitwise OR-ing nghttp2_goaway_flag. */
+ uint8_t goaway_flags;
+ /* This flag is used to reduce excessive queuing of WINDOW_UPDATE to
+ this session. The nonzero does not necessarily mean
+ WINDOW_UPDATE is not queued. */
+ uint8_t window_update_queued;
+ /* Bitfield of extension frame types that application is willing to
+ receive. To designate the bit of given frame type i, use
+ user_recv_ext_types[i / 8] & (1 << (i & 0x7)). First 10 frame
+ types are standard frame types and not used in this bitfield. If
+ bit is set, it indicates that incoming frame with that type is
+ passed to user defined callbacks, otherwise they are ignored. */
+ uint8_t user_recv_ext_types[32];
+};
+
+/* Struct used when updating initial window size of each active
+ stream. */
+typedef struct {
+ nghttp2_session *session;
+ int32_t new_window_size, old_window_size;
+} nghttp2_update_window_size_arg;
+
+typedef struct {
+ nghttp2_session *session;
+ /* linked list of streams to close */
+ nghttp2_stream *head;
+ int32_t last_stream_id;
+ /* nonzero if GOAWAY is sent to peer, which means we are going to
+ close incoming streams. zero if GOAWAY is received from peer and
+ we are going to close outgoing streams. */
+ int incoming;
+} nghttp2_close_stream_on_goaway_arg;
+
+/* TODO stream timeout etc */
+
+/*
+ * Returns nonzero value if |stream_id| is initiated by local
+ * endpoint.
+ */
+int nghttp2_session_is_my_stream_id(nghttp2_session *session,
+ int32_t stream_id);
+
+/*
+ * Adds |item| to the outbound queue in |session|. When this function
+ * succeeds, it takes ownership of |item|. So caller must not free it
+ * on success.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_STREAM_CLOSED
+ * Stream already closed (DATA and PUSH_PROMISE frame only)
+ */
+int nghttp2_session_add_item(nghttp2_session *session,
+ nghttp2_outbound_item *item);
+
+/*
+ * Adds RST_STREAM frame for the stream |stream_id| with the error
+ * code |error_code|. This is a convenient function built on top of
+ * nghttp2_session_add_frame() to add RST_STREAM easily.
+ *
+ * This function simply returns 0 without adding RST_STREAM frame if
+ * given stream is in NGHTTP2_STREAM_CLOSING state, because multiple
+ * RST_STREAM for a stream is redundant.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_session_add_rst_stream(nghttp2_session *session, int32_t stream_id,
+ uint32_t error_code);
+
+/*
+ * Adds PING frame. This is a convenient functin built on top of
+ * nghttp2_session_add_frame() to add PING easily.
+ *
+ * If the |opaque_data| is not NULL, it must point to 8 bytes memory
+ * region of data. The data pointed by |opaque_data| is copied. It can
+ * be NULL. In this case, 8 bytes NULL is used.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_FLOODED
+ * There are too many items in outbound queue; this only happens
+ * if NGHTTP2_FLAG_ACK is set in |flags|
+ */
+int nghttp2_session_add_ping(nghttp2_session *session, uint8_t flags,
+ const uint8_t *opaque_data);
+
+/*
+ * Adds GOAWAY frame with the last-stream-ID |last_stream_id| and the
+ * error code |error_code|. This is a convenient function built on top
+ * of nghttp2_session_add_frame() to add GOAWAY easily. The
+ * |aux_flags| are bitwise-OR of one or more of
+ * nghttp2_goaway_aux_flag.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_INVALID_ARGUMENT
+ * The |opaque_data_len| is too large.
+ */
+int nghttp2_session_add_goaway(nghttp2_session *session, int32_t last_stream_id,
+ uint32_t error_code, const uint8_t *opaque_data,
+ size_t opaque_data_len, uint8_t aux_flags);
+
+/*
+ * Adds WINDOW_UPDATE frame with stream ID |stream_id| and
+ * window-size-increment |window_size_increment|. This is a convenient
+ * function built on top of nghttp2_session_add_frame() to add
+ * WINDOW_UPDATE easily.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ */
+int nghttp2_session_add_window_update(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id,
+ int32_t window_size_increment);
+
+/*
+ * Adds SETTINGS frame.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_FLOODED
+ * There are too many items in outbound queue; this only happens
+ * if NGHTTP2_FLAG_ACK is set in |flags|
+ */
+int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
+ const nghttp2_settings_entry *iv, size_t niv);
+
+/*
+ * Creates new stream in |session| with stream ID |stream_id|,
+ * priority |pri_spec| and flags |flags|. The |flags| is bitwise OR
+ * of nghttp2_stream_flag. Since this function is called when initial
+ * HEADERS is sent or received, these flags are taken from it. The
+ * state of stream is set to |initial_state|. The |stream_user_data|
+ * is a pointer to the arbitrary user supplied data to be associated
+ * to this stream.
+ *
+ * If |initial_state| is NGHTTP2_STREAM_RESERVED, this function sets
+ * NGHTTP2_STREAM_FLAG_PUSH flag set.
+ *
+ * This function returns a pointer to created new stream object, or
+ * NULL.
+ *
+ * This function adjusts neither the number of closed streams or idle
+ * streams. The caller should manually call
+ * nghttp2_session_adjust_closed_stream() or
+ * nghttp2_session_adjust_idle_stream() respectively.
+ */
+nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session,
+ int32_t stream_id, uint8_t flags,
+ nghttp2_priority_spec *pri_spec,
+ nghttp2_stream_state initial_state,
+ void *stream_user_data);
+
+/*
+ * Closes stream whose stream ID is |stream_id|. The reason of closure
+ * is indicated by the |error_code|. When closing the stream,
+ * on_stream_close_callback will be called.
+ *
+ * If the session is initialized as server and |stream| is incoming
+ * stream, stream is just marked closed and this function calls
+ * nghttp2_session_keep_closed_stream() with |stream|. Otherwise,
+ * |stream| will be deleted from memory.
+ *
+ * This function returns 0 if it succeeds, or one the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ * NGHTTP2_ERR_INVALID_ARGUMENT
+ * The specified stream does not exist.
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * The callback function failed.
+ */
+int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id,
+ uint32_t error_code);
+
+/*
+ * Deletes |stream| from memory. After this function returns, stream
+ * cannot be accessed.
+ *
+ * This function returns 0 if it succeeds, or one the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_session_destroy_stream(nghttp2_session *session,
+ nghttp2_stream *stream);
+
+/*
+ * Tries to keep incoming closed stream |stream|. Due to the
+ * limitation of maximum number of streams in memory, |stream| is not
+ * closed and just deleted from memory (see
+ * nghttp2_session_destroy_stream).
+ */
+void nghttp2_session_keep_closed_stream(nghttp2_session *session,
+ nghttp2_stream *stream);
+
+/*
+ * Appends |stream| to linked list |session->idle_stream_head|. We
+ * apply fixed limit for list size. To fit into that limit, one or
+ * more oldest streams are removed from list as necessary.
+ */
+void nghttp2_session_keep_idle_stream(nghttp2_session *session,
+ nghttp2_stream *stream);
+
+/*
+ * Detaches |stream| from idle streams linked list.
+ */
+void nghttp2_session_detach_idle_stream(nghttp2_session *session,
+ nghttp2_stream *stream);
+
+/*
+ * Deletes closed stream to ensure that number of incoming streams
+ * including active and closed is in the maximum number of allowed
+ * stream.
+ *
+ * This function returns 0 if it succeeds, or one the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_session_adjust_closed_stream(nghttp2_session *session);
+
+/*
+ * Deletes idle stream to ensure that number of idle streams is in
+ * certain limit.
+ *
+ * This function returns 0 if it succeeds, or one the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_session_adjust_idle_stream(nghttp2_session *session);
+
+/*
+ * If further receptions and transmissions over the stream |stream_id|
+ * are disallowed, close the stream with error code NGHTTP2_NO_ERROR.
+ *
+ * This function returns 0 if it
+ * succeeds, or one of the following negative error codes:
+ *
+ * NGHTTP2_ERR_INVALID_ARGUMENT
+ * The specified stream does not exist.
+ */
+int nghttp2_session_close_stream_if_shut_rdwr(nghttp2_session *session,
+ nghttp2_stream *stream);
+
+int nghttp2_session_on_request_headers_received(nghttp2_session *session,
+ nghttp2_frame *frame);
+
+int nghttp2_session_on_response_headers_received(nghttp2_session *session,
+ nghttp2_frame *frame,
+ nghttp2_stream *stream);
+
+int nghttp2_session_on_push_response_headers_received(nghttp2_session *session,
+ nghttp2_frame *frame,
+ nghttp2_stream *stream);
+
+/*
+ * Called when HEADERS is received, assuming |frame| is properly
+ * initialized. This function does first validate received frame and
+ * then open stream and call callback functions.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_IGN_HEADER_BLOCK
+ * Frame was rejected and header block must be decoded but
+ * result must be ignored.
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * The read_callback failed
+ */
+int nghttp2_session_on_headers_received(nghttp2_session *session,
+ nghttp2_frame *frame,
+ nghttp2_stream *stream);
+
+/*
+ * Called when PRIORITY is received, assuming |frame| is properly
+ * initialized.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * The read_callback failed
+ */
+int nghttp2_session_on_priority_received(nghttp2_session *session,
+ nghttp2_frame *frame);
+
+/*
+ * Called when RST_STREAM is received, assuming |frame| is properly
+ * initialized.
+ *
+ * This function returns 0 if it succeeds, or one the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * The read_callback failed
+ */
+int nghttp2_session_on_rst_stream_received(nghttp2_session *session,
+ nghttp2_frame *frame);
+
+/*
+ * Called when SETTINGS is received, assuming |frame| is properly
+ * initialized. If |noack| is non-zero, SETTINGS with ACK will not be
+ * submitted. If |frame| has NGHTTP2_FLAG_ACK flag set, no SETTINGS
+ * with ACK will not be submitted regardless of |noack|.
+ *
+ * This function returns 0 if it succeeds, or one the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * The read_callback failed
+ * NGHTTP2_ERR_FLOODED
+ * There are too many items in outbound queue, and this is most
+ * likely caused by misbehaviour of peer.
+ */
+int nghttp2_session_on_settings_received(nghttp2_session *session,
+ nghttp2_frame *frame, int noack);
+
+/*
+ * Called when PUSH_PROMISE is received, assuming |frame| is properly
+ * initialized.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_IGN_HEADER_BLOCK
+ * Frame was rejected and header block must be decoded but
+ * result must be ignored.
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * The read_callback failed
+ */
+int nghttp2_session_on_push_promise_received(nghttp2_session *session,
+ nghttp2_frame *frame);
+
+/*
+ * Called when PING is received, assuming |frame| is properly
+ * initialized.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * The callback function failed.
+ * NGHTTP2_ERR_FLOODED
+ * There are too many items in outbound queue, and this is most
+ * likely caused by misbehaviour of peer.
+ */
+int nghttp2_session_on_ping_received(nghttp2_session *session,
+ nghttp2_frame *frame);
+
+/*
+ * Called when GOAWAY is received, assuming |frame| is properly
+ * initialized.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * The callback function failed.
+ */
+int nghttp2_session_on_goaway_received(nghttp2_session *session,
+ nghttp2_frame *frame);
+
+/*
+ * Called when WINDOW_UPDATE is received, assuming |frame| is properly
+ * initialized.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * The callback function failed.
+ */
+int nghttp2_session_on_window_update_received(nghttp2_session *session,
+ nghttp2_frame *frame);
+
+/*
+ * Called when ALTSVC is received, assuming |frame| is properly
+ * initialized.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * The callback function failed.
+ */
+int nghttp2_session_on_altsvc_received(nghttp2_session *session,
+ nghttp2_frame *frame);
+
+/*
+ * Called when DATA is received, assuming |frame| is properly
+ * initialized.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * The callback function failed.
+ */
+int nghttp2_session_on_data_received(nghttp2_session *session,
+ nghttp2_frame *frame);
+
+/*
+ * Returns nghttp2_stream* object whose stream ID is |stream_id|. It
+ * could be NULL if such stream does not exist. This function returns
+ * NULL if stream is marked as closed.
+ */
+nghttp2_stream *nghttp2_session_get_stream(nghttp2_session *session,
+ int32_t stream_id);
+
+/*
+ * This function behaves like nghttp2_session_get_stream(), but it
+ * returns stream object even if it is marked as closed or in
+ * NGHTTP2_STREAM_IDLE state.
+ */
+nghttp2_stream *nghttp2_session_get_stream_raw(nghttp2_session *session,
+ int32_t stream_id);
+
+/*
+ * Packs DATA frame |frame| in wire frame format and stores it in
+ * |bufs|. Payload will be read using |aux_data->data_prd|. The
+ * length of payload is at most |datamax| bytes.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_DEFERRED
+ * The DATA frame is postponed.
+ * NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE
+ * The read_callback failed (stream error).
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_CALLBACK_FAILURE
+ * The read_callback failed (session error).
+ */
+int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs,
+ size_t datamax, nghttp2_frame *frame,
+ nghttp2_data_aux_data *aux_data,
+ nghttp2_stream *stream);
+
+/*
+ * Pops and returns next item to send. If there is no such item,
+ * returns NULL. This function takes into account max concurrent
+ * streams. That means if session->ob_syn has item and max concurrent
+ * streams is reached, the even if other queues contain items, then
+ * this function returns NULL.
+ */
+nghttp2_outbound_item *
+nghttp2_session_pop_next_ob_item(nghttp2_session *session);
+
+/*
+ * Returns next item to send. If there is no such item, this function
+ * returns NULL. This function takes into account max concurrent
+ * streams. That means if session->ob_syn has item and max concurrent
+ * streams is reached, the even if other queues contain items, then
+ * this function returns NULL.
+ */
+nghttp2_outbound_item *
+nghttp2_session_get_next_ob_item(nghttp2_session *session);
+
+/*
+ * Updates local settings with the |iv|. The number of elements in the
+ * array pointed by the |iv| is given by the |niv|. This function
+ * assumes that the all settings_id member in |iv| are in range 1 to
+ * NGHTTP2_SETTINGS_MAX, inclusive.
+ *
+ * While updating individual stream's local window size, if the window
+ * size becomes strictly larger than NGHTTP2_MAX_WINDOW_SIZE,
+ * RST_STREAM is issued against such a stream.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_session_update_local_settings(nghttp2_session *session,
+ nghttp2_settings_entry *iv,
+ size_t niv);
+
+/*
+ * Re-prioritize |stream|. The new priority specification is
+ * |pri_spec|. Caller must ensure that stream->hd.stream_id !=
+ * pri_spec->stream_id.
+ *
+ * This function does not adjust the number of idle streams. The
+ * caller should call nghttp2_session_adjust_idle_stream() later.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_session_reprioritize_stream(nghttp2_session *session,
+ nghttp2_stream *stream,
+ const nghttp2_priority_spec *pri_spec);
+
+/*
+ * Terminates current |session| with the |error_code|. The |reason|
+ * is NULL-terminated debug string.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory.
+ * NGHTTP2_ERR_INVALID_ARGUMENT
+ * The |reason| is too long.
+ */
+int nghttp2_session_terminate_session_with_reason(nghttp2_session *session,
+ uint32_t error_code,
+ const char *reason);
+
+#endif /* NGHTTP2_SESSION_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_stream.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_stream.c
new file mode 100644
index 00000000..e3d2b1e4
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_stream.c
@@ -0,0 +1,985 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_stream.h"
+
+#include
+#include
+
+#include "nghttp2_session.h"
+#include "nghttp2_helper.h"
+#include "nghttp2_debug.h"
+
+/* Maximum distance between any two stream's cycle in the same
+ prirority queue. Imagine stream A's cycle is A, and stream B's
+ cycle is B, and A < B. The cycle is unsigned 32 bit integer, it
+ may get overflow. Because of how we calculate the next cycle
+ value, if B - A is less than or equals to
+ NGHTTP2_MAX_CYCLE_DISTANCE, A and B are in the same scale, in other
+ words, B is really greater than or equal to A. Otherwise, A is a
+ result of overflow, and it is actually A > B if we consider that
+ fact. */
+#define NGHTTP2_MAX_CYCLE_DISTANCE (16384 * 256 + 255)
+
+static int stream_less(const void *lhsx, const void *rhsx) {
+ const nghttp2_stream *lhs, *rhs;
+
+ lhs = nghttp2_struct_of(lhsx, nghttp2_stream, pq_entry);
+ rhs = nghttp2_struct_of(rhsx, nghttp2_stream, pq_entry);
+
+ if (lhs->cycle == rhs->cycle) {
+ return lhs->seq < rhs->seq;
+ }
+
+ if (lhs->cycle < rhs->cycle) {
+ return rhs->cycle - lhs->cycle <= NGHTTP2_MAX_CYCLE_DISTANCE;
+ }
+
+ return lhs->cycle - rhs->cycle > NGHTTP2_MAX_CYCLE_DISTANCE;
+}
+
+void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
+ uint8_t flags, nghttp2_stream_state initial_state,
+ int32_t weight, int32_t remote_initial_window_size,
+ int32_t local_initial_window_size,
+ void *stream_user_data, nghttp2_mem *mem) {
+ nghttp2_map_entry_init(&stream->map_entry, (key_type)stream_id);
+ nghttp2_pq_init(&stream->obq, stream_less, mem);
+
+ stream->stream_id = stream_id;
+ stream->flags = flags;
+ stream->state = initial_state;
+ stream->shut_flags = NGHTTP2_SHUT_NONE;
+ stream->stream_user_data = stream_user_data;
+ stream->item = NULL;
+ stream->remote_window_size = remote_initial_window_size;
+ stream->local_window_size = local_initial_window_size;
+ stream->recv_window_size = 0;
+ stream->consumed_size = 0;
+ stream->recv_reduction = 0;
+ stream->window_update_queued = 0;
+
+ stream->dep_prev = NULL;
+ stream->dep_next = NULL;
+ stream->sib_prev = NULL;
+ stream->sib_next = NULL;
+
+ stream->closed_prev = NULL;
+ stream->closed_next = NULL;
+
+ stream->weight = weight;
+ stream->sum_dep_weight = 0;
+
+ stream->http_flags = NGHTTP2_HTTP_FLAG_NONE;
+ stream->content_length = -1;
+ stream->recv_content_length = 0;
+ stream->status_code = -1;
+
+ stream->queued = 0;
+ stream->descendant_last_cycle = 0;
+ stream->cycle = 0;
+ stream->pending_penalty = 0;
+ stream->descendant_next_seq = 0;
+ stream->seq = 0;
+ stream->last_writelen = 0;
+}
+
+void nghttp2_stream_free(nghttp2_stream *stream) {
+ nghttp2_pq_free(&stream->obq);
+ /* We don't free stream->item. If it is assigned to aob, then
+ active_outbound_item_reset() will delete it. Otherwise,
+ nghttp2_stream_close() or session_del() will delete it. */
+}
+
+void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag) {
+ stream->shut_flags = (uint8_t)(stream->shut_flags | flag);
+}
+
+/*
+ * Returns nonzero if |stream| is active. This function does not take
+ * into account its descendants.
+ */
+static int stream_active(nghttp2_stream *stream) {
+ return stream->item &&
+ (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0;
+}
+
+/*
+ * Returns nonzero if |stream| or one of its descendants is active
+ */
+static int stream_subtree_active(nghttp2_stream *stream) {
+ return stream_active(stream) || !nghttp2_pq_empty(&stream->obq);
+}
+
+/*
+ * Returns next cycle for |stream|.
+ */
+static void stream_next_cycle(nghttp2_stream *stream, uint32_t last_cycle) {
+ uint32_t penalty;
+
+ penalty = (uint32_t)stream->last_writelen * NGHTTP2_MAX_WEIGHT +
+ stream->pending_penalty;
+
+ stream->cycle = last_cycle + penalty / (uint32_t)stream->weight;
+ stream->pending_penalty = penalty % (uint32_t)stream->weight;
+}
+
+static int stream_obq_push(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
+ int rv;
+
+ for (; dep_stream && !stream->queued;
+ stream = dep_stream, dep_stream = dep_stream->dep_prev) {
+ stream_next_cycle(stream, dep_stream->descendant_last_cycle);
+ stream->seq = dep_stream->descendant_next_seq++;
+
+ DEBUGF("stream: stream=%d obq push cycle=%d\n", stream->stream_id,
+ stream->cycle);
+
+ DEBUGF("stream: push stream %d to stream %d\n", stream->stream_id,
+ dep_stream->stream_id);
+
+ rv = nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
+ if (rv != 0) {
+ return rv;
+ }
+ stream->queued = 1;
+ }
+
+ return 0;
+}
+
+/*
+ * Removes |stream| from parent's obq. If removal of |stream| makes
+ * parent's obq empty, and parent is not active, then parent is also
+ * removed. This process is repeated recursively.
+ */
+static void stream_obq_remove(nghttp2_stream *stream) {
+ nghttp2_stream *dep_stream;
+
+ dep_stream = stream->dep_prev;
+
+ if (!stream->queued) {
+ return;
+ }
+
+ for (; dep_stream; stream = dep_stream, dep_stream = dep_stream->dep_prev) {
+ DEBUGF("stream: remove stream %d from stream %d\n", stream->stream_id,
+ dep_stream->stream_id);
+
+ nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry);
+
+ assert(stream->queued);
+
+ stream->queued = 0;
+ stream->cycle = 0;
+ stream->pending_penalty = 0;
+ stream->descendant_last_cycle = 0;
+ stream->last_writelen = 0;
+
+ if (stream_subtree_active(dep_stream)) {
+ return;
+ }
+ }
+}
+
+/*
+ * Moves |stream| from |src|'s obq to |dest|'s obq. Removal from
+ * |src|'s obq is just done calling nghttp2_pq_remove(), so it does
+ * not recursively remove |src| and ancestors, like
+ * stream_obq_remove().
+ */
+static int stream_obq_move(nghttp2_stream *dest, nghttp2_stream *src,
+ nghttp2_stream *stream) {
+ if (!stream->queued) {
+ return 0;
+ }
+
+ DEBUGF("stream: remove stream %d from stream %d (move)\n", stream->stream_id,
+ src->stream_id);
+
+ nghttp2_pq_remove(&src->obq, &stream->pq_entry);
+ stream->queued = 0;
+
+ return stream_obq_push(dest, stream);
+}
+
+void nghttp2_stream_reschedule(nghttp2_stream *stream) {
+ nghttp2_stream *dep_stream;
+
+ assert(stream->queued);
+
+ dep_stream = stream->dep_prev;
+
+ for (; dep_stream; stream = dep_stream, dep_stream = dep_stream->dep_prev) {
+ nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry);
+
+ stream_next_cycle(stream, dep_stream->descendant_last_cycle);
+ stream->seq = dep_stream->descendant_next_seq++;
+
+ nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
+
+ DEBUGF("stream: stream=%d obq resched cycle=%d\n", stream->stream_id,
+ stream->cycle);
+
+ dep_stream->last_writelen = stream->last_writelen;
+ }
+}
+
+void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight) {
+ nghttp2_stream *dep_stream;
+ uint32_t last_cycle;
+ int32_t old_weight;
+ uint32_t wlen_penalty;
+
+ if (stream->weight == weight) {
+ return;
+ }
+
+ old_weight = stream->weight;
+ stream->weight = weight;
+
+ dep_stream = stream->dep_prev;
+
+ if (!dep_stream) {
+ return;
+ }
+
+ dep_stream->sum_dep_weight += weight - old_weight;
+
+ if (!stream->queued) {
+ return;
+ }
+
+ nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry);
+
+ wlen_penalty = (uint32_t)stream->last_writelen * NGHTTP2_MAX_WEIGHT;
+
+ /* Compute old stream->pending_penalty we used to calculate
+ stream->cycle */
+ stream->pending_penalty =
+ (uint32_t)((stream->pending_penalty + (uint32_t)old_weight -
+ (wlen_penalty % (uint32_t)old_weight)) %
+ (uint32_t)old_weight);
+
+ last_cycle = stream->cycle -
+ (wlen_penalty + stream->pending_penalty) / (uint32_t)old_weight;
+
+ /* Now we have old stream->pending_penalty and new stream->weight in
+ place */
+ stream_next_cycle(stream, last_cycle);
+
+ if (stream->cycle < dep_stream->descendant_last_cycle &&
+ (dep_stream->descendant_last_cycle - stream->cycle) <=
+ NGHTTP2_MAX_CYCLE_DISTANCE) {
+ stream->cycle = dep_stream->descendant_last_cycle;
+ }
+
+ /* Continue to use same stream->seq */
+
+ nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
+
+ DEBUGF("stream: stream=%d obq resched cycle=%d\n", stream->stream_id,
+ stream->cycle);
+}
+
+static nghttp2_stream *stream_last_sib(nghttp2_stream *stream) {
+ for (; stream->sib_next; stream = stream->sib_next)
+ ;
+
+ return stream;
+}
+
+int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
+ int32_t weight) {
+ weight = stream->weight * weight / stream->sum_dep_weight;
+
+ return nghttp2_max(1, weight);
+}
+
+#ifdef STREAM_DEP_DEBUG
+
+static void ensure_inactive(nghttp2_stream *stream) {
+ nghttp2_stream *si;
+
+ if (stream->queued) {
+ fprintf(stderr, "stream(%p)=%d, stream->queued = 1; want 0\n", stream,
+ stream->stream_id);
+ assert(0);
+ }
+
+ if (stream_active(stream)) {
+ fprintf(stderr, "stream(%p)=%d, stream_active(stream) = 1; want 0\n",
+ stream, stream->stream_id);
+ assert(0);
+ }
+
+ if (!nghttp2_pq_empty(&stream->obq)) {
+ fprintf(stderr, "stream(%p)=%d, nghttp2_pq_size() = %zu; want 0\n", stream,
+ stream->stream_id, nghttp2_pq_size(&stream->obq));
+ assert(0);
+ }
+
+ for (si = stream->dep_next; si; si = si->sib_next) {
+ ensure_inactive(si);
+ }
+}
+
+static void check_queued(nghttp2_stream *stream) {
+ nghttp2_stream *si;
+ int queued;
+
+ if (stream->queued) {
+ if (!stream_subtree_active(stream)) {
+ fprintf(stderr,
+ "stream(%p)=%d, stream->queued == 1, but "
+ "stream_active() == %d and nghttp2_pq_size(&stream->obq) = %zu\n",
+ stream, stream->stream_id, stream_active(stream),
+ nghttp2_pq_size(&stream->obq));
+ assert(0);
+ }
+ if (!stream_active(stream)) {
+ queued = 0;
+ for (si = stream->dep_next; si; si = si->sib_next) {
+ if (si->queued) {
+ ++queued;
+ }
+ }
+ if (queued == 0) {
+ fprintf(stderr,
+ "stream(%p)=%d, stream->queued == 1, and "
+ "!stream_active(), but no descendants is queued\n",
+ stream, stream->stream_id);
+ assert(0);
+ }
+ }
+
+ for (si = stream->dep_next; si; si = si->sib_next) {
+ check_queued(si);
+ }
+ } else {
+ if (stream_active(stream) || !nghttp2_pq_empty(&stream->obq)) {
+ fprintf(stderr,
+ "stream(%p) = %d, stream->queued == 0, but "
+ "stream_active(stream) == %d and "
+ "nghttp2_pq_size(&stream->obq) = %zu\n",
+ stream, stream->stream_id, stream_active(stream),
+ nghttp2_pq_size(&stream->obq));
+ assert(0);
+ }
+ for (si = stream->dep_next; si; si = si->sib_next) {
+ ensure_inactive(si);
+ }
+ }
+}
+
+static void check_sum_dep(nghttp2_stream *stream) {
+ nghttp2_stream *si;
+ int32_t n = 0;
+ for (si = stream->dep_next; si; si = si->sib_next) {
+ n += si->weight;
+ }
+ if (n != stream->sum_dep_weight) {
+ fprintf(stderr, "stream(%p)=%d, sum_dep_weight = %d; want %d\n", stream,
+ stream->stream_id, n, stream->sum_dep_weight);
+ assert(0);
+ }
+ for (si = stream->dep_next; si; si = si->sib_next) {
+ check_sum_dep(si);
+ }
+}
+
+static void check_dep_prev(nghttp2_stream *stream) {
+ nghttp2_stream *si;
+ for (si = stream->dep_next; si; si = si->sib_next) {
+ if (si->dep_prev != stream) {
+ fprintf(stderr, "si->dep_prev = %p; want %p\n", si->dep_prev, stream);
+ assert(0);
+ }
+ check_dep_prev(si);
+ }
+}
+
+#endif /* STREAM_DEP_DEBUG */
+
+#ifdef STREAM_DEP_DEBUG
+static void validate_tree(nghttp2_stream *stream) {
+ nghttp2_stream *si;
+
+ if (!stream) {
+ return;
+ }
+
+ for (; stream->dep_prev; stream = stream->dep_prev)
+ ;
+
+ assert(stream->stream_id == 0);
+ assert(!stream->queued);
+
+ fprintf(stderr, "checking...\n");
+ if (nghttp2_pq_empty(&stream->obq)) {
+ fprintf(stderr, "root obq empty\n");
+ for (si = stream->dep_next; si; si = si->sib_next) {
+ ensure_inactive(si);
+ }
+ } else {
+ for (si = stream->dep_next; si; si = si->sib_next) {
+ check_queued(si);
+ }
+ }
+
+ check_sum_dep(stream);
+ check_dep_prev(stream);
+}
+#else /* !STREAM_DEP_DEBUG */
+static void validate_tree(nghttp2_stream *stream) { (void)stream; }
+#endif /* !STREAM_DEP_DEBUG*/
+
+static int stream_update_dep_on_attach_item(nghttp2_stream *stream) {
+ int rv;
+
+ rv = stream_obq_push(stream->dep_prev, stream);
+ if (rv != 0) {
+ return rv;
+ }
+
+ validate_tree(stream);
+ return 0;
+}
+
+static int stream_update_dep_on_detach_item(nghttp2_stream *stream) {
+ if (nghttp2_pq_empty(&stream->obq)) {
+ stream_obq_remove(stream);
+ }
+
+ validate_tree(stream);
+
+ return 0;
+}
+
+int nghttp2_stream_attach_item(nghttp2_stream *stream,
+ nghttp2_outbound_item *item) {
+ int rv;
+
+ assert((stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) == 0);
+ assert(stream->item == NULL);
+
+ DEBUGF("stream: stream=%d attach item=%p\n", stream->stream_id, item);
+
+ stream->item = item;
+
+ rv = stream_update_dep_on_attach_item(stream);
+ if (rv != 0) {
+ /* This may relave stream->queued == 1, but stream->item == NULL.
+ But only consequence of this error is fatal one, and session
+ destruction. In that execution path, these inconsistency does
+ not matter. */
+ stream->item = NULL;
+ return rv;
+ }
+
+ return 0;
+}
+
+int nghttp2_stream_detach_item(nghttp2_stream *stream) {
+ DEBUGF("stream: stream=%d detach item=%p\n", stream->stream_id, stream->item);
+
+ stream->item = NULL;
+ stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_DEFERRED_ALL);
+
+ return stream_update_dep_on_detach_item(stream);
+}
+
+int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags) {
+ assert(stream->item);
+
+ DEBUGF("stream: stream=%d defer item=%p cause=%02x\n", stream->stream_id,
+ stream->item, flags);
+
+ stream->flags |= flags;
+
+ return stream_update_dep_on_detach_item(stream);
+}
+
+int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags) {
+ assert(stream->item);
+
+ DEBUGF("stream: stream=%d resume item=%p flags=%02x\n", stream->stream_id,
+ stream->item, flags);
+
+ stream->flags = (uint8_t)(stream->flags & ~flags);
+
+ if (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL) {
+ return 0;
+ }
+
+ return stream_update_dep_on_attach_item(stream);
+}
+
+int nghttp2_stream_check_deferred_item(nghttp2_stream *stream) {
+ return stream->item && (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_ALL);
+}
+
+int nghttp2_stream_check_deferred_by_flow_control(nghttp2_stream *stream) {
+ return stream->item &&
+ (stream->flags & NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL);
+}
+
+static int update_initial_window_size(int32_t *window_size_ptr,
+ int32_t new_initial_window_size,
+ int32_t old_initial_window_size) {
+ int64_t new_window_size = (int64_t)(*window_size_ptr) +
+ new_initial_window_size - old_initial_window_size;
+ if (INT32_MIN > new_window_size ||
+ new_window_size > NGHTTP2_MAX_WINDOW_SIZE) {
+ return -1;
+ }
+ *window_size_ptr = (int32_t)new_window_size;
+ return 0;
+}
+
+int nghttp2_stream_update_remote_initial_window_size(
+ nghttp2_stream *stream, int32_t new_initial_window_size,
+ int32_t old_initial_window_size) {
+ return update_initial_window_size(&stream->remote_window_size,
+ new_initial_window_size,
+ old_initial_window_size);
+}
+
+int nghttp2_stream_update_local_initial_window_size(
+ nghttp2_stream *stream, int32_t new_initial_window_size,
+ int32_t old_initial_window_size) {
+ return update_initial_window_size(&stream->local_window_size,
+ new_initial_window_size,
+ old_initial_window_size);
+}
+
+void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream) {
+ stream->state = NGHTTP2_STREAM_OPENED;
+ stream->flags = (uint8_t)(stream->flags & ~NGHTTP2_STREAM_FLAG_PUSH);
+}
+
+int nghttp2_stream_dep_find_ancestor(nghttp2_stream *stream,
+ nghttp2_stream *target) {
+ for (; stream; stream = stream->dep_prev) {
+ if (stream == target) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
+ nghttp2_stream *stream) {
+ nghttp2_stream *si;
+ int rv;
+
+ DEBUGF("stream: dep_insert dep_stream(%p)=%d, stream(%p)=%d\n", dep_stream,
+ dep_stream->stream_id, stream, stream->stream_id);
+
+ stream->sum_dep_weight = dep_stream->sum_dep_weight;
+ dep_stream->sum_dep_weight = stream->weight;
+
+ if (dep_stream->dep_next) {
+ for (si = dep_stream->dep_next; si; si = si->sib_next) {
+ si->dep_prev = stream;
+ if (si->queued) {
+ rv = stream_obq_move(stream, dep_stream, si);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+ }
+
+ if (stream_subtree_active(stream)) {
+ rv = stream_obq_push(dep_stream, stream);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+
+ stream->dep_next = dep_stream->dep_next;
+ }
+
+ dep_stream->dep_next = stream;
+ stream->dep_prev = dep_stream;
+
+ validate_tree(stream);
+
+ return 0;
+}
+
+static void set_dep_prev(nghttp2_stream *stream, nghttp2_stream *dep) {
+ for (; stream; stream = stream->sib_next) {
+ stream->dep_prev = dep;
+ }
+}
+
+static void link_dep(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
+ dep_stream->dep_next = stream;
+ if (stream) {
+ stream->dep_prev = dep_stream;
+ }
+}
+
+static void link_sib(nghttp2_stream *a, nghttp2_stream *b) {
+ a->sib_next = b;
+ if (b) {
+ b->sib_prev = a;
+ }
+}
+
+static void insert_link_dep(nghttp2_stream *dep_stream,
+ nghttp2_stream *stream) {
+ nghttp2_stream *sib_next;
+
+ assert(stream->sib_prev == NULL);
+
+ sib_next = dep_stream->dep_next;
+
+ link_sib(stream, sib_next);
+
+ link_dep(dep_stream, stream);
+}
+
+static void unlink_sib(nghttp2_stream *stream) {
+ nghttp2_stream *prev, *next, *dep_next;
+
+ prev = stream->sib_prev;
+ dep_next = stream->dep_next;
+
+ assert(prev);
+
+ if (dep_next) {
+ /*
+ * prev--stream(--sib_next--...)
+ * |
+ * dep_next
+ */
+
+ link_sib(prev, dep_next);
+
+ set_dep_prev(dep_next, stream->dep_prev);
+
+ if (stream->sib_next) {
+ link_sib(stream_last_sib(dep_next), stream->sib_next);
+ }
+ } else {
+ /*
+ * prev--stream(--sib_next--...)
+ */
+ next = stream->sib_next;
+
+ prev->sib_next = next;
+
+ if (next) {
+ next->sib_prev = prev;
+ }
+ }
+}
+
+static void unlink_dep(nghttp2_stream *stream) {
+ nghttp2_stream *prev, *next, *dep_next;
+
+ prev = stream->dep_prev;
+ dep_next = stream->dep_next;
+
+ assert(prev);
+
+ if (dep_next) {
+ /*
+ * prev
+ * |
+ * stream(--sib_next--...)
+ * |
+ * dep_next
+ */
+ link_dep(prev, dep_next);
+
+ set_dep_prev(dep_next, stream->dep_prev);
+
+ if (stream->sib_next) {
+ link_sib(stream_last_sib(dep_next), stream->sib_next);
+ }
+
+ } else if (stream->sib_next) {
+ /*
+ * prev
+ * |
+ * stream--sib_next
+ */
+ next = stream->sib_next;
+
+ next->sib_prev = NULL;
+
+ link_dep(prev, next);
+ } else {
+ prev->dep_next = NULL;
+ }
+}
+
+void nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
+ nghttp2_stream *stream) {
+ DEBUGF("stream: dep_add dep_stream(%p)=%d, stream(%p)=%d\n", dep_stream,
+ dep_stream->stream_id, stream, stream->stream_id);
+
+ dep_stream->sum_dep_weight += stream->weight;
+
+ if (dep_stream->dep_next == NULL) {
+ link_dep(dep_stream, stream);
+ } else {
+ insert_link_dep(dep_stream, stream);
+ }
+
+ validate_tree(stream);
+}
+
+int nghttp2_stream_dep_remove(nghttp2_stream *stream) {
+ nghttp2_stream *dep_prev, *si;
+ int32_t sum_dep_weight_delta;
+ int rv;
+
+ DEBUGF("stream: dep_remove stream(%p)=%d\n", stream, stream->stream_id);
+
+ /* Distribute weight of |stream| to direct descendants */
+ sum_dep_weight_delta = -stream->weight;
+
+ for (si = stream->dep_next; si; si = si->sib_next) {
+ si->weight = nghttp2_stream_dep_distributed_weight(stream, si->weight);
+
+ sum_dep_weight_delta += si->weight;
+
+ if (si->queued) {
+ rv = stream_obq_move(stream->dep_prev, stream, si);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+ }
+
+ assert(stream->dep_prev);
+
+ dep_prev = stream->dep_prev;
+
+ dep_prev->sum_dep_weight += sum_dep_weight_delta;
+
+ if (stream->queued) {
+ stream_obq_remove(stream);
+ }
+
+ if (stream->sib_prev) {
+ unlink_sib(stream);
+ } else {
+ unlink_dep(stream);
+ }
+
+ stream->sum_dep_weight = 0;
+
+ stream->dep_prev = NULL;
+ stream->dep_next = NULL;
+ stream->sib_prev = NULL;
+ stream->sib_next = NULL;
+
+ validate_tree(dep_prev);
+
+ return 0;
+}
+
+int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
+ nghttp2_stream *stream) {
+ nghttp2_stream *last_sib;
+ nghttp2_stream *dep_next;
+ nghttp2_stream *si;
+ int rv;
+
+ DEBUGF("stream: dep_insert_subtree dep_stream(%p)=%d stream(%p)=%d\n",
+ dep_stream, dep_stream->stream_id, stream, stream->stream_id);
+
+ stream->sum_dep_weight += dep_stream->sum_dep_weight;
+ dep_stream->sum_dep_weight = stream->weight;
+
+ if (dep_stream->dep_next) {
+ dep_next = dep_stream->dep_next;
+
+ link_dep(dep_stream, stream);
+
+ if (stream->dep_next) {
+ last_sib = stream_last_sib(stream->dep_next);
+
+ link_sib(last_sib, dep_next);
+ } else {
+ link_dep(stream, dep_next);
+ }
+
+ for (si = dep_next; si; si = si->sib_next) {
+ si->dep_prev = stream;
+ if (si->queued) {
+ rv = stream_obq_move(stream, dep_stream, si);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+ }
+ } else {
+ link_dep(dep_stream, stream);
+ }
+
+ if (stream_subtree_active(stream)) {
+ rv = stream_obq_push(dep_stream, stream);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+
+ validate_tree(dep_stream);
+
+ return 0;
+}
+
+int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
+ nghttp2_stream *stream) {
+ int rv;
+
+ DEBUGF("stream: dep_add_subtree dep_stream(%p)=%d stream(%p)=%d\n",
+ dep_stream, dep_stream->stream_id, stream, stream->stream_id);
+
+ dep_stream->sum_dep_weight += stream->weight;
+
+ if (dep_stream->dep_next) {
+ insert_link_dep(dep_stream, stream);
+ } else {
+ link_dep(dep_stream, stream);
+ }
+
+ if (stream_subtree_active(stream)) {
+ rv = stream_obq_push(dep_stream, stream);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+
+ validate_tree(dep_stream);
+
+ return 0;
+}
+
+void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream) {
+ nghttp2_stream *next, *dep_prev;
+
+ DEBUGF("stream: dep_remove_subtree stream(%p)=%d\n", stream,
+ stream->stream_id);
+
+ assert(stream->dep_prev);
+
+ dep_prev = stream->dep_prev;
+
+ if (stream->sib_prev) {
+ link_sib(stream->sib_prev, stream->sib_next);
+ } else {
+ next = stream->sib_next;
+
+ link_dep(dep_prev, next);
+
+ if (next) {
+ next->sib_prev = NULL;
+ }
+ }
+
+ dep_prev->sum_dep_weight -= stream->weight;
+
+ if (stream->queued) {
+ stream_obq_remove(stream);
+ }
+
+ validate_tree(dep_prev);
+
+ stream->sib_prev = NULL;
+ stream->sib_next = NULL;
+ stream->dep_prev = NULL;
+}
+
+int nghttp2_stream_in_dep_tree(nghttp2_stream *stream) {
+ return stream->dep_prev || stream->dep_next || stream->sib_prev ||
+ stream->sib_next;
+}
+
+nghttp2_outbound_item *
+nghttp2_stream_next_outbound_item(nghttp2_stream *stream) {
+ nghttp2_pq_entry *ent;
+ nghttp2_stream *si;
+
+ for (;;) {
+ if (stream_active(stream)) {
+ /* Update ascendant's descendant_last_cycle here, so that we can
+ assure that new stream is scheduled based on it. */
+ for (si = stream; si->dep_prev; si = si->dep_prev) {
+ si->dep_prev->descendant_last_cycle = si->cycle;
+ }
+ return stream->item;
+ }
+ ent = nghttp2_pq_top(&stream->obq);
+ if (!ent) {
+ return NULL;
+ }
+ stream = nghttp2_struct_of(ent, nghttp2_stream, pq_entry);
+ }
+}
+
+nghttp2_stream_proto_state nghttp2_stream_get_state(nghttp2_stream *stream) {
+ if (stream->flags & NGHTTP2_STREAM_FLAG_CLOSED) {
+ return NGHTTP2_STREAM_STATE_CLOSED;
+ }
+
+ if (stream->flags & NGHTTP2_STREAM_FLAG_PUSH) {
+ if (stream->shut_flags & NGHTTP2_SHUT_RD) {
+ return NGHTTP2_STREAM_STATE_RESERVED_LOCAL;
+ }
+
+ if (stream->shut_flags & NGHTTP2_SHUT_WR) {
+ return NGHTTP2_STREAM_STATE_RESERVED_REMOTE;
+ }
+ }
+
+ if (stream->shut_flags & NGHTTP2_SHUT_RD) {
+ return NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE;
+ }
+
+ if (stream->shut_flags & NGHTTP2_SHUT_WR) {
+ return NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL;
+ }
+
+ if (stream->state == NGHTTP2_STREAM_IDLE) {
+ return NGHTTP2_STREAM_STATE_IDLE;
+ }
+
+ return NGHTTP2_STREAM_STATE_OPEN;
+}
+
+nghttp2_stream *nghttp2_stream_get_parent(nghttp2_stream *stream) {
+ return stream->dep_prev;
+}
+
+nghttp2_stream *nghttp2_stream_get_next_sibling(nghttp2_stream *stream) {
+ return stream->sib_next;
+}
+
+nghttp2_stream *nghttp2_stream_get_previous_sibling(nghttp2_stream *stream) {
+ return stream->sib_prev;
+}
+
+nghttp2_stream *nghttp2_stream_get_first_child(nghttp2_stream *stream) {
+ return stream->dep_next;
+}
+
+int32_t nghttp2_stream_get_weight(nghttp2_stream *stream) {
+ return stream->weight;
+}
+
+int32_t nghttp2_stream_get_sum_dependency_weight(nghttp2_stream *stream) {
+ return stream->sum_dep_weight;
+}
+
+int32_t nghttp2_stream_get_stream_id(nghttp2_stream *stream) {
+ return stream->stream_id;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_stream.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_stream.h
new file mode 100644
index 00000000..7ff69281
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_stream.h
@@ -0,0 +1,417 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_STREAM_H
+#define NGHTTP2_STREAM_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+#include "nghttp2_outbound_item.h"
+#include "nghttp2_map.h"
+#include "nghttp2_pq.h"
+#include "nghttp2_int.h"
+
+/*
+ * If local peer is stream initiator:
+ * NGHTTP2_STREAM_OPENING : upon sending request HEADERS
+ * NGHTTP2_STREAM_OPENED : upon receiving response HEADERS
+ * NGHTTP2_STREAM_CLOSING : upon queuing RST_STREAM
+ *
+ * If remote peer is stream initiator:
+ * NGHTTP2_STREAM_OPENING : upon receiving request HEADERS
+ * NGHTTP2_STREAM_OPENED : upon sending response HEADERS
+ * NGHTTP2_STREAM_CLOSING : upon queuing RST_STREAM
+ */
+typedef enum {
+ /* Initial state */
+ NGHTTP2_STREAM_INITIAL,
+ /* For stream initiator: request HEADERS has been sent, but response
+ HEADERS has not been received yet. For receiver: request HEADERS
+ has been received, but it does not send response HEADERS yet. */
+ NGHTTP2_STREAM_OPENING,
+ /* For stream initiator: response HEADERS is received. For receiver:
+ response HEADERS is sent. */
+ NGHTTP2_STREAM_OPENED,
+ /* RST_STREAM is received, but somehow we need to keep stream in
+ memory. */
+ NGHTTP2_STREAM_CLOSING,
+ /* PUSH_PROMISE is received or sent */
+ NGHTTP2_STREAM_RESERVED,
+ /* Stream is created in this state if it is used as anchor in
+ dependency tree. */
+ NGHTTP2_STREAM_IDLE
+} nghttp2_stream_state;
+
+typedef enum {
+ NGHTTP2_SHUT_NONE = 0,
+ /* Indicates further receptions will be disallowed. */
+ NGHTTP2_SHUT_RD = 0x01,
+ /* Indicates further transmissions will be disallowed. */
+ NGHTTP2_SHUT_WR = 0x02,
+ /* Indicates both further receptions and transmissions will be
+ disallowed. */
+ NGHTTP2_SHUT_RDWR = NGHTTP2_SHUT_RD | NGHTTP2_SHUT_WR
+} nghttp2_shut_flag;
+
+typedef enum {
+ NGHTTP2_STREAM_FLAG_NONE = 0,
+ /* Indicates that this stream is pushed stream and not opened
+ yet. */
+ NGHTTP2_STREAM_FLAG_PUSH = 0x01,
+ /* Indicates that this stream was closed */
+ NGHTTP2_STREAM_FLAG_CLOSED = 0x02,
+ /* Indicates the item is deferred due to flow control. */
+ NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL = 0x04,
+ /* Indicates the item is deferred by user callback */
+ NGHTTP2_STREAM_FLAG_DEFERRED_USER = 0x08,
+ /* bitwise OR of NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and
+ NGHTTP2_STREAM_FLAG_DEFERRED_USER. */
+ NGHTTP2_STREAM_FLAG_DEFERRED_ALL = 0x0c
+
+} nghttp2_stream_flag;
+
+/* HTTP related flags to enforce HTTP semantics */
+typedef enum {
+ NGHTTP2_HTTP_FLAG_NONE = 0,
+ /* header field seen so far */
+ NGHTTP2_HTTP_FLAG__AUTHORITY = 1,
+ NGHTTP2_HTTP_FLAG__PATH = 1 << 1,
+ NGHTTP2_HTTP_FLAG__METHOD = 1 << 2,
+ NGHTTP2_HTTP_FLAG__SCHEME = 1 << 3,
+ /* host is not pseudo header, but we require either host or
+ :authority */
+ NGHTTP2_HTTP_FLAG_HOST = 1 << 4,
+ NGHTTP2_HTTP_FLAG__STATUS = 1 << 5,
+ /* required header fields for HTTP request except for CONNECT
+ method. */
+ NGHTTP2_HTTP_FLAG_REQ_HEADERS = NGHTTP2_HTTP_FLAG__METHOD |
+ NGHTTP2_HTTP_FLAG__PATH |
+ NGHTTP2_HTTP_FLAG__SCHEME,
+ NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED = 1 << 6,
+ /* HTTP method flags */
+ NGHTTP2_HTTP_FLAG_METH_CONNECT = 1 << 7,
+ NGHTTP2_HTTP_FLAG_METH_HEAD = 1 << 8,
+ NGHTTP2_HTTP_FLAG_METH_OPTIONS = 1 << 9,
+ NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND = 1 << 10,
+ NGHTTP2_HTTP_FLAG_METH_ALL = NGHTTP2_HTTP_FLAG_METH_CONNECT |
+ NGHTTP2_HTTP_FLAG_METH_HEAD |
+ NGHTTP2_HTTP_FLAG_METH_OPTIONS |
+ NGHTTP2_HTTP_FLAG_METH_UPGRADE_WORKAROUND,
+ /* :path category */
+ /* path starts with "/" */
+ NGHTTP2_HTTP_FLAG_PATH_REGULAR = 1 << 11,
+ /* path "*" */
+ NGHTTP2_HTTP_FLAG_PATH_ASTERISK = 1 << 12,
+ /* scheme */
+ /* "http" or "https" scheme */
+ NGHTTP2_HTTP_FLAG_SCHEME_HTTP = 1 << 13,
+ /* set if final response is expected */
+ NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE = 1 << 14
+} nghttp2_http_flag;
+
+struct nghttp2_stream {
+ /* Intrusive Map */
+ nghttp2_map_entry map_entry;
+ /* Entry for dep_prev->obq */
+ nghttp2_pq_entry pq_entry;
+ /* Priority Queue storing direct descendant (nghttp2_stream). Only
+ streams which itself has some data to send, or has a descendant
+ which has some data to sent. */
+ nghttp2_pq obq;
+ /* Content-Length of request/response body. -1 if unknown. */
+ int64_t content_length;
+ /* Received body so far */
+ int64_t recv_content_length;
+ /* Base last_cycle for direct descendent streams. */
+ uint32_t descendant_last_cycle;
+ /* Next scheduled time to sent item */
+ uint32_t cycle;
+ /* Next seq used for direct descendant streams */
+ uint64_t descendant_next_seq;
+ /* Secondary key for prioritization to break a tie for cycle. This
+ value is monotonically increased for single parent stream. */
+ uint64_t seq;
+ /* pointers to form dependency tree. If multiple streams depend on
+ a stream, only one stream (left most) has non-NULL dep_prev which
+ points to the stream it depends on. The remaining streams are
+ linked using sib_prev and sib_next. The stream which has
+ non-NULL dep_prev always NULL sib_prev. The right most stream
+ has NULL sib_next. If this stream is a root of dependency tree,
+ dep_prev and sib_prev are NULL. */
+ nghttp2_stream *dep_prev, *dep_next;
+ nghttp2_stream *sib_prev, *sib_next;
+ /* When stream is kept after closure, it may be kept in doubly
+ linked list pointed by nghttp2_session closed_stream_head.
+ closed_next points to the next stream object if it is the element
+ of the list. */
+ nghttp2_stream *closed_prev, *closed_next;
+ /* The arbitrary data provided by user for this stream. */
+ void *stream_user_data;
+ /* Item to send */
+ nghttp2_outbound_item *item;
+ /* Last written length of frame payload */
+ size_t last_writelen;
+ /* stream ID */
+ int32_t stream_id;
+ /* Current remote window size. This value is computed against the
+ current initial window size of remote endpoint. */
+ int32_t remote_window_size;
+ /* Keep track of the number of bytes received without
+ WINDOW_UPDATE. This could be negative after submitting negative
+ value to WINDOW_UPDATE */
+ int32_t recv_window_size;
+ /* The number of bytes consumed by the application and now is
+ subject to WINDOW_UPDATE. This is only used when auto
+ WINDOW_UPDATE is turned off. */
+ int32_t consumed_size;
+ /* The amount of recv_window_size cut using submitting negative
+ value to WINDOW_UPDATE */
+ int32_t recv_reduction;
+ /* window size for local flow control. It is initially set to
+ NGHTTP2_INITIAL_WINDOW_SIZE and could be increased/decreased by
+ submitting WINDOW_UPDATE. See nghttp2_submit_window_update(). */
+ int32_t local_window_size;
+ /* weight of this stream */
+ int32_t weight;
+ /* This is unpaid penalty (offset) when calculating cycle. */
+ uint32_t pending_penalty;
+ /* sum of weight of direct descendants */
+ int32_t sum_dep_weight;
+ nghttp2_stream_state state;
+ /* status code from remote server */
+ int16_t status_code;
+ /* Bitwise OR of zero or more nghttp2_http_flag values */
+ uint16_t http_flags;
+ /* This is bitwise-OR of 0 or more of nghttp2_stream_flag. */
+ uint8_t flags;
+ /* Bitwise OR of zero or more nghttp2_shut_flag values */
+ uint8_t shut_flags;
+ /* Nonzero if this stream has been queued to stream pointed by
+ dep_prev. We maintain the invariant that if a stream is queued,
+ then its ancestors, except for root, are also queued. This
+ invariant may break in fatal error condition. */
+ uint8_t queued;
+ /* This flag is used to reduce excessive queuing of WINDOW_UPDATE to
+ this stream. The nonzero does not necessarily mean WINDOW_UPDATE
+ is not queued. */
+ uint8_t window_update_queued;
+};
+
+void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
+ uint8_t flags, nghttp2_stream_state initial_state,
+ int32_t weight, int32_t remote_initial_window_size,
+ int32_t local_initial_window_size,
+ void *stream_user_data, nghttp2_mem *mem);
+
+void nghttp2_stream_free(nghttp2_stream *stream);
+
+/*
+ * Disallow either further receptions or transmissions, or both.
+ * |flag| is bitwise OR of one or more of nghttp2_shut_flag.
+ */
+void nghttp2_stream_shutdown(nghttp2_stream *stream, nghttp2_shut_flag flag);
+
+/*
+ * Defer |stream->item|. We won't call this function in the situation
+ * where |stream->item| == NULL. The |flags| is bitwise OR of zero or
+ * more of NGHTTP2_STREAM_FLAG_DEFERRED_USER and
+ * NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL. The |flags| indicates
+ * the reason of this action.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_stream_defer_item(nghttp2_stream *stream, uint8_t flags);
+
+/*
+ * Put back deferred data in this stream to active state. The |flags|
+ * are one or more of bitwise OR of the following values:
+ * NGHTTP2_STREAM_FLAG_DEFERRED_USER and
+ * NGHTTP2_STREAM_FLAG_DEFERRED_FLOW_CONTROL and given masks are
+ * cleared if they are set. So even if this function is called, if
+ * one of flag is still set, data does not become active.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_stream_resume_deferred_item(nghttp2_stream *stream, uint8_t flags);
+
+/*
+ * Returns nonzero if item is deferred by whatever reason.
+ */
+int nghttp2_stream_check_deferred_item(nghttp2_stream *stream);
+
+/*
+ * Returns nonzero if item is deferred by flow control.
+ */
+int nghttp2_stream_check_deferred_by_flow_control(nghttp2_stream *stream);
+
+/*
+ * Updates the remote window size with the new value
+ * |new_initial_window_size|. The |old_initial_window_size| is used to
+ * calculate the current window size.
+ *
+ * This function returns 0 if it succeeds or -1. The failure is due to
+ * overflow.
+ */
+int nghttp2_stream_update_remote_initial_window_size(
+ nghttp2_stream *stream, int32_t new_initial_window_size,
+ int32_t old_initial_window_size);
+
+/*
+ * Updates the local window size with the new value
+ * |new_initial_window_size|. The |old_initial_window_size| is used to
+ * calculate the current window size.
+ *
+ * This function returns 0 if it succeeds or -1. The failure is due to
+ * overflow.
+ */
+int nghttp2_stream_update_local_initial_window_size(
+ nghttp2_stream *stream, int32_t new_initial_window_size,
+ int32_t old_initial_window_size);
+
+/*
+ * Call this function if promised stream |stream| is replied with
+ * HEADERS. This function makes the state of the |stream| to
+ * NGHTTP2_STREAM_OPENED.
+ */
+void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream);
+
+/*
+ * Returns nonzero if |target| is an ancestor of |stream|.
+ */
+int nghttp2_stream_dep_find_ancestor(nghttp2_stream *stream,
+ nghttp2_stream *target);
+
+/*
+ * Computes distributed weight of a stream of the |weight| under the
+ * |stream| if |stream| is removed from a dependency tree.
+ */
+int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
+ int32_t weight);
+
+/*
+ * Makes the |stream| depend on the |dep_stream|. This dependency is
+ * exclusive. All existing direct descendants of |dep_stream| become
+ * the descendants of the |stream|. This function assumes
+ * |stream->item| is NULL.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
+ nghttp2_stream *stream);
+
+/*
+ * Makes the |stream| depend on the |dep_stream|. This dependency is
+ * not exclusive. This function assumes |stream->item| is NULL.
+ */
+void nghttp2_stream_dep_add(nghttp2_stream *dep_stream, nghttp2_stream *stream);
+
+/*
+ * Removes the |stream| from the current dependency tree. This
+ * function assumes |stream->item| is NULL.
+ */
+int nghttp2_stream_dep_remove(nghttp2_stream *stream);
+
+/*
+ * Attaches |item| to |stream|.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_stream_attach_item(nghttp2_stream *stream,
+ nghttp2_outbound_item *item);
+
+/*
+ * Detaches |stream->item|. This function does not free
+ * |stream->item|. The caller must free it.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_stream_detach_item(nghttp2_stream *stream);
+
+/*
+ * Makes the |stream| depend on the |dep_stream|. This dependency is
+ * exclusive.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
+ nghttp2_stream *stream);
+
+/*
+ * Makes the |stream| depend on the |dep_stream|. This dependency is
+ * not exclusive.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
+ nghttp2_stream *stream);
+
+/*
+ * Removes subtree whose root stream is |stream|. The
+ * effective_weight of streams in removed subtree is not updated.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM
+ * Out of memory
+ */
+void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream);
+
+/*
+ * Returns nonzero if |stream| is in any dependency tree.
+ */
+int nghttp2_stream_in_dep_tree(nghttp2_stream *stream);
+
+/*
+ * Schedules transmission of |stream|'s item, assuming stream->item is
+ * attached, and stream->last_writelen was updated.
+ */
+void nghttp2_stream_reschedule(nghttp2_stream *stream);
+
+/*
+ * Changes |stream|'s weight to |weight|. If |stream| is queued, it
+ * will be rescheduled based on new weight.
+ */
+void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight);
+
+/*
+ * Returns a stream which has highest priority, updating
+ * descendant_last_cycle of selected stream's ancestors.
+ */
+nghttp2_outbound_item *
+nghttp2_stream_next_outbound_item(nghttp2_stream *stream);
+
+#endif /* NGHTTP2_STREAM */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_submit.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_submit.c
new file mode 100644
index 00000000..dedf86e8
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_submit.c
@@ -0,0 +1,712 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include "nghttp2_submit.h"
+
+#include
+#include
+
+#include "nghttp2_session.h"
+#include "nghttp2_frame.h"
+#include "nghttp2_helper.h"
+#include "nghttp2_priority_spec.h"
+
+/*
+ * Detects the dependency error, that is stream attempted to depend on
+ * itself. If |stream_id| is -1, we use session->next_stream_id as
+ * stream ID.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * error codes:
+ *
+ * NGHTTP2_ERR_INVALID_ARGUMENT
+ * Stream attempted to depend on itself.
+ */
+static int detect_self_dependency(nghttp2_session *session, int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec) {
+ assert(pri_spec);
+
+ if (stream_id == -1) {
+ if ((int32_t)session->next_stream_id == pri_spec->stream_id) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+ return 0;
+ }
+
+ if (stream_id == pri_spec->stream_id) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ return 0;
+}
+
+/* This function takes ownership of |nva_copy|. Regardless of the
+ return value, the caller must not free |nva_copy| after this
+ function returns. */
+static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec,
+ nghttp2_nv *nva_copy, size_t nvlen,
+ const nghttp2_data_provider *data_prd,
+ void *stream_user_data) {
+ int rv;
+ uint8_t flags_copy;
+ nghttp2_outbound_item *item = NULL;
+ nghttp2_frame *frame = NULL;
+ nghttp2_headers_category hcat;
+ nghttp2_mem *mem;
+
+ mem = &session->mem;
+
+ item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
+ if (item == NULL) {
+ rv = NGHTTP2_ERR_NOMEM;
+ goto fail;
+ }
+
+ nghttp2_outbound_item_init(item);
+
+ if (data_prd != NULL && data_prd->read_callback != NULL) {
+ item->aux_data.headers.data_prd = *data_prd;
+ }
+
+ item->aux_data.headers.stream_user_data = stream_user_data;
+
+ flags_copy =
+ (uint8_t)((flags & (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PRIORITY)) |
+ NGHTTP2_FLAG_END_HEADERS);
+
+ if (stream_id == -1) {
+ if (session->next_stream_id > INT32_MAX) {
+ rv = NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE;
+ goto fail;
+ }
+
+ stream_id = (int32_t)session->next_stream_id;
+ session->next_stream_id += 2;
+
+ hcat = NGHTTP2_HCAT_REQUEST;
+ } else {
+ /* More specific categorization will be done later. */
+ hcat = NGHTTP2_HCAT_HEADERS;
+ }
+
+ frame = &item->frame;
+
+ nghttp2_frame_headers_init(&frame->headers, flags_copy, stream_id, hcat,
+ pri_spec, nva_copy, nvlen);
+
+ rv = nghttp2_session_add_item(session, item);
+
+ if (rv != 0) {
+ nghttp2_frame_headers_free(&frame->headers, mem);
+ goto fail2;
+ }
+
+ if (hcat == NGHTTP2_HCAT_REQUEST) {
+ return stream_id;
+ }
+
+ return 0;
+
+fail:
+ /* nghttp2_frame_headers_init() takes ownership of nva_copy. */
+ nghttp2_nv_array_del(nva_copy, mem);
+fail2:
+ nghttp2_mem_free(mem, item);
+
+ return rv;
+}
+
+static int32_t submit_headers_shared_nva(nghttp2_session *session,
+ uint8_t flags, int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec,
+ const nghttp2_nv *nva, size_t nvlen,
+ const nghttp2_data_provider *data_prd,
+ void *stream_user_data) {
+ int rv;
+ nghttp2_nv *nva_copy;
+ nghttp2_priority_spec copy_pri_spec;
+ nghttp2_mem *mem;
+
+ mem = &session->mem;
+
+ if (pri_spec) {
+ copy_pri_spec = *pri_spec;
+ nghttp2_priority_spec_normalize_weight(©_pri_spec);
+ } else {
+ nghttp2_priority_spec_default_init(©_pri_spec);
+ }
+
+ rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen, mem);
+ if (rv < 0) {
+ return rv;
+ }
+
+ return submit_headers_shared(session, flags, stream_id, ©_pri_spec,
+ nva_copy, nvlen, data_prd, stream_user_data);
+}
+
+int nghttp2_submit_trailer(nghttp2_session *session, int32_t stream_id,
+ const nghttp2_nv *nva, size_t nvlen) {
+ if (stream_id <= 0) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ return (int)submit_headers_shared_nva(session, NGHTTP2_FLAG_END_STREAM,
+ stream_id, NULL, nva, nvlen, NULL,
+ NULL);
+}
+
+int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec,
+ const nghttp2_nv *nva, size_t nvlen,
+ void *stream_user_data) {
+ int rv;
+
+ if (stream_id == -1) {
+ if (session->server) {
+ return NGHTTP2_ERR_PROTO;
+ }
+ } else if (stream_id <= 0) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ flags &= NGHTTP2_FLAG_END_STREAM;
+
+ if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec)) {
+ rv = detect_self_dependency(session, stream_id, pri_spec);
+ if (rv != 0) {
+ return rv;
+ }
+
+ flags |= NGHTTP2_FLAG_PRIORITY;
+ } else {
+ pri_spec = NULL;
+ }
+
+ return submit_headers_shared_nva(session, flags, stream_id, pri_spec, nva,
+ nvlen, NULL, stream_user_data);
+}
+
+int nghttp2_submit_ping(nghttp2_session *session, uint8_t flags,
+ const uint8_t *opaque_data) {
+ flags &= NGHTTP2_FLAG_ACK;
+ return nghttp2_session_add_ping(session, flags, opaque_data);
+}
+
+int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id,
+ const nghttp2_priority_spec *pri_spec) {
+ int rv;
+ nghttp2_outbound_item *item;
+ nghttp2_frame *frame;
+ nghttp2_priority_spec copy_pri_spec;
+ nghttp2_mem *mem;
+ (void)flags;
+
+ mem = &session->mem;
+
+ if (stream_id == 0 || pri_spec == NULL) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ if (stream_id == pri_spec->stream_id) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ copy_pri_spec = *pri_spec;
+
+ nghttp2_priority_spec_normalize_weight(©_pri_spec);
+
+ item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
+
+ if (item == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ nghttp2_outbound_item_init(item);
+
+ frame = &item->frame;
+
+ nghttp2_frame_priority_init(&frame->priority, stream_id, ©_pri_spec);
+
+ rv = nghttp2_session_add_item(session, item);
+
+ if (rv != 0) {
+ nghttp2_frame_priority_free(&frame->priority);
+ nghttp2_mem_free(mem, item);
+
+ return rv;
+ }
+
+ return 0;
+}
+
+int nghttp2_submit_rst_stream(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id, uint32_t error_code) {
+ (void)flags;
+
+ if (stream_id == 0) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ return nghttp2_session_add_rst_stream(session, stream_id, error_code);
+}
+
+int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags,
+ int32_t last_stream_id, uint32_t error_code,
+ const uint8_t *opaque_data, size_t opaque_data_len) {
+ (void)flags;
+
+ if (session->goaway_flags & NGHTTP2_GOAWAY_TERM_ON_SEND) {
+ return 0;
+ }
+ return nghttp2_session_add_goaway(session, last_stream_id, error_code,
+ opaque_data, opaque_data_len,
+ NGHTTP2_GOAWAY_AUX_NONE);
+}
+
+int nghttp2_submit_shutdown_notice(nghttp2_session *session) {
+ if (!session->server) {
+ return NGHTTP2_ERR_INVALID_STATE;
+ }
+ if (session->goaway_flags) {
+ return 0;
+ }
+ return nghttp2_session_add_goaway(session, (1u << 31) - 1, NGHTTP2_NO_ERROR,
+ NULL, 0,
+ NGHTTP2_GOAWAY_AUX_SHUTDOWN_NOTICE);
+}
+
+int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags,
+ const nghttp2_settings_entry *iv, size_t niv) {
+ (void)flags;
+ return nghttp2_session_add_settings(session, NGHTTP2_FLAG_NONE, iv, niv);
+}
+
+int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id, const nghttp2_nv *nva,
+ size_t nvlen,
+ void *promised_stream_user_data) {
+ nghttp2_outbound_item *item;
+ nghttp2_frame *frame;
+ nghttp2_nv *nva_copy;
+ uint8_t flags_copy;
+ int32_t promised_stream_id;
+ int rv;
+ nghttp2_mem *mem;
+ (void)flags;
+
+ mem = &session->mem;
+
+ if (stream_id <= 0 || nghttp2_session_is_my_stream_id(session, stream_id)) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ if (!session->server) {
+ return NGHTTP2_ERR_PROTO;
+ }
+
+ /* All 32bit signed stream IDs are spent. */
+ if (session->next_stream_id > INT32_MAX) {
+ return NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE;
+ }
+
+ item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
+ if (item == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ nghttp2_outbound_item_init(item);
+
+ item->aux_data.headers.stream_user_data = promised_stream_user_data;
+
+ frame = &item->frame;
+
+ rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen, mem);
+ if (rv < 0) {
+ nghttp2_mem_free(mem, item);
+ return rv;
+ }
+
+ flags_copy = NGHTTP2_FLAG_END_HEADERS;
+
+ promised_stream_id = (int32_t)session->next_stream_id;
+ session->next_stream_id += 2;
+
+ nghttp2_frame_push_promise_init(&frame->push_promise, flags_copy, stream_id,
+ promised_stream_id, nva_copy, nvlen);
+
+ rv = nghttp2_session_add_item(session, item);
+
+ if (rv != 0) {
+ nghttp2_frame_push_promise_free(&frame->push_promise, mem);
+ nghttp2_mem_free(mem, item);
+
+ return rv;
+ }
+
+ return promised_stream_id;
+}
+
+int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id,
+ int32_t window_size_increment) {
+ int rv;
+ nghttp2_stream *stream = 0;
+ (void)flags;
+
+ if (window_size_increment == 0) {
+ return 0;
+ }
+ if (stream_id == 0) {
+ rv = nghttp2_adjust_local_window_size(
+ &session->local_window_size, &session->recv_window_size,
+ &session->recv_reduction, &window_size_increment);
+ if (rv != 0) {
+ return rv;
+ }
+ } else {
+ stream = nghttp2_session_get_stream(session, stream_id);
+ if (!stream) {
+ return 0;
+ }
+
+ rv = nghttp2_adjust_local_window_size(
+ &stream->local_window_size, &stream->recv_window_size,
+ &stream->recv_reduction, &window_size_increment);
+ if (rv != 0) {
+ return rv;
+ }
+ }
+
+ if (window_size_increment > 0) {
+ if (stream_id == 0) {
+ session->consumed_size =
+ nghttp2_max(0, session->consumed_size - window_size_increment);
+ } else {
+ stream->consumed_size =
+ nghttp2_max(0, stream->consumed_size - window_size_increment);
+ }
+
+ return nghttp2_session_add_window_update(session, 0, stream_id,
+ window_size_increment);
+ }
+ return 0;
+}
+
+int nghttp2_session_set_local_window_size(nghttp2_session *session,
+ uint8_t flags, int32_t stream_id,
+ int32_t window_size) {
+ int32_t window_size_increment;
+ nghttp2_stream *stream;
+ int rv;
+ (void)flags;
+
+ if (window_size < 0) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ if (stream_id == 0) {
+ window_size_increment = window_size - session->local_window_size;
+
+ if (window_size_increment == 0) {
+ return 0;
+ }
+
+ if (window_size_increment < 0) {
+ return nghttp2_adjust_local_window_size(
+ &session->local_window_size, &session->recv_window_size,
+ &session->recv_reduction, &window_size_increment);
+ }
+
+ rv = nghttp2_increase_local_window_size(
+ &session->local_window_size, &session->recv_window_size,
+ &session->recv_reduction, &window_size_increment);
+
+ if (rv != 0) {
+ return rv;
+ }
+ } else {
+ stream = nghttp2_session_get_stream(session, stream_id);
+
+ if (stream == NULL) {
+ return 0;
+ }
+
+ window_size_increment = window_size - stream->local_window_size;
+
+ if (window_size_increment == 0) {
+ return 0;
+ }
+
+ if (window_size_increment < 0) {
+ return nghttp2_adjust_local_window_size(
+ &stream->local_window_size, &stream->recv_window_size,
+ &stream->recv_reduction, &window_size_increment);
+ }
+
+ rv = nghttp2_increase_local_window_size(
+ &stream->local_window_size, &stream->recv_window_size,
+ &stream->recv_reduction, &window_size_increment);
+
+ if (rv != 0) {
+ return rv;
+ }
+ }
+
+ if (window_size_increment > 0) {
+ return nghttp2_session_add_window_update(session, 0, stream_id,
+ window_size_increment);
+ }
+
+ return 0;
+}
+
+int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id, const uint8_t *origin,
+ size_t origin_len, const uint8_t *field_value,
+ size_t field_value_len) {
+ nghttp2_mem *mem;
+ uint8_t *buf, *p;
+ uint8_t *origin_copy;
+ uint8_t *field_value_copy;
+ nghttp2_outbound_item *item;
+ nghttp2_frame *frame;
+ nghttp2_ext_altsvc *altsvc;
+ int rv;
+ (void)flags;
+
+ mem = &session->mem;
+
+ if (!session->server) {
+ return NGHTTP2_ERR_INVALID_STATE;
+ }
+
+ if (2 + origin_len + field_value_len > NGHTTP2_MAX_PAYLOADLEN) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ if (stream_id == 0) {
+ if (origin_len == 0) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+ } else if (origin_len != 0) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ buf = nghttp2_mem_malloc(mem, origin_len + field_value_len + 2);
+ if (buf == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ p = buf;
+
+ origin_copy = p;
+ if (origin_len) {
+ p = nghttp2_cpymem(p, origin, origin_len);
+ }
+ *p++ = '\0';
+
+ field_value_copy = p;
+ if (field_value_len) {
+ p = nghttp2_cpymem(p, field_value, field_value_len);
+ }
+ *p++ = '\0';
+
+ item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
+ if (item == NULL) {
+ rv = NGHTTP2_ERR_NOMEM;
+ goto fail_item_malloc;
+ }
+
+ nghttp2_outbound_item_init(item);
+
+ item->aux_data.ext.builtin = 1;
+
+ altsvc = &item->ext_frame_payload.altsvc;
+
+ frame = &item->frame;
+ frame->ext.payload = altsvc;
+
+ nghttp2_frame_altsvc_init(&frame->ext, stream_id, origin_copy, origin_len,
+ field_value_copy, field_value_len);
+
+ rv = nghttp2_session_add_item(session, item);
+ if (rv != 0) {
+ nghttp2_frame_altsvc_free(&frame->ext, mem);
+ nghttp2_mem_free(mem, item);
+
+ return rv;
+ }
+
+ return 0;
+
+fail_item_malloc:
+ nghttp2_mem_free(mem, buf);
+
+ return rv;
+}
+
+static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
+ const nghttp2_data_provider *data_prd) {
+ uint8_t flags = NGHTTP2_FLAG_NONE;
+ if (data_prd == NULL || data_prd->read_callback == NULL) {
+ flags |= NGHTTP2_FLAG_END_STREAM;
+ }
+
+ if (pri_spec) {
+ flags |= NGHTTP2_FLAG_PRIORITY;
+ }
+
+ return flags;
+}
+
+int32_t nghttp2_submit_request(nghttp2_session *session,
+ const nghttp2_priority_spec *pri_spec,
+ const nghttp2_nv *nva, size_t nvlen,
+ const nghttp2_data_provider *data_prd,
+ void *stream_user_data) {
+ uint8_t flags;
+ int rv;
+
+ if (session->server) {
+ return NGHTTP2_ERR_PROTO;
+ }
+
+ if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec)) {
+ rv = detect_self_dependency(session, -1, pri_spec);
+ if (rv != 0) {
+ return rv;
+ }
+ } else {
+ pri_spec = NULL;
+ }
+
+ flags = set_request_flags(pri_spec, data_prd);
+
+ return submit_headers_shared_nva(session, flags, -1, pri_spec, nva, nvlen,
+ data_prd, stream_user_data);
+}
+
+static uint8_t set_response_flags(const nghttp2_data_provider *data_prd) {
+ uint8_t flags = NGHTTP2_FLAG_NONE;
+ if (data_prd == NULL || data_prd->read_callback == NULL) {
+ flags |= NGHTTP2_FLAG_END_STREAM;
+ }
+ return flags;
+}
+
+int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id,
+ const nghttp2_nv *nva, size_t nvlen,
+ const nghttp2_data_provider *data_prd) {
+ uint8_t flags;
+
+ if (stream_id <= 0) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ if (!session->server) {
+ return NGHTTP2_ERR_PROTO;
+ }
+
+ flags = set_response_flags(data_prd);
+ return submit_headers_shared_nva(session, flags, stream_id, NULL, nva, nvlen,
+ data_prd, NULL);
+}
+
+int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
+ int32_t stream_id,
+ const nghttp2_data_provider *data_prd) {
+ int rv;
+ nghttp2_outbound_item *item;
+ nghttp2_frame *frame;
+ nghttp2_data_aux_data *aux_data;
+ uint8_t nflags = flags & NGHTTP2_FLAG_END_STREAM;
+ nghttp2_mem *mem;
+
+ mem = &session->mem;
+
+ if (stream_id == 0) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
+ if (item == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ nghttp2_outbound_item_init(item);
+
+ frame = &item->frame;
+ aux_data = &item->aux_data.data;
+ aux_data->data_prd = *data_prd;
+ aux_data->eof = 0;
+ aux_data->flags = nflags;
+
+ /* flags are sent on transmission */
+ nghttp2_frame_data_init(&frame->data, NGHTTP2_FLAG_NONE, stream_id);
+
+ rv = nghttp2_session_add_item(session, item);
+ if (rv != 0) {
+ nghttp2_frame_data_free(&frame->data);
+ nghttp2_mem_free(mem, item);
+ return rv;
+ }
+ return 0;
+}
+
+ssize_t nghttp2_pack_settings_payload(uint8_t *buf, size_t buflen,
+ const nghttp2_settings_entry *iv,
+ size_t niv) {
+ if (!nghttp2_iv_check(iv, niv)) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ if (buflen < (niv * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH)) {
+ return NGHTTP2_ERR_INSUFF_BUFSIZE;
+ }
+
+ return (ssize_t)nghttp2_frame_pack_settings_payload(buf, iv, niv);
+}
+
+int nghttp2_submit_extension(nghttp2_session *session, uint8_t type,
+ uint8_t flags, int32_t stream_id, void *payload) {
+ int rv;
+ nghttp2_outbound_item *item;
+ nghttp2_frame *frame;
+ nghttp2_mem *mem;
+
+ mem = &session->mem;
+
+ if (type <= NGHTTP2_CONTINUATION) {
+ return NGHTTP2_ERR_INVALID_ARGUMENT;
+ }
+
+ if (!session->callbacks.pack_extension_callback) {
+ return NGHTTP2_ERR_INVALID_STATE;
+ }
+
+ item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
+ if (item == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ nghttp2_outbound_item_init(item);
+
+ frame = &item->frame;
+ nghttp2_frame_extension_init(&frame->ext, type, flags, stream_id, payload);
+
+ rv = nghttp2_session_add_item(session, item);
+ if (rv != 0) {
+ nghttp2_frame_extension_free(&frame->ext);
+ nghttp2_mem_free(mem, item);
+ return rv;
+ }
+
+ return 0;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_submit.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_submit.h
new file mode 100644
index 00000000..4d35029a
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_submit.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2_SUBMIT_H
+#define NGHTTP2_SUBMIT_H
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+#endif /* NGHTTP2_SUBMIT_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_version.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_version.c
new file mode 100644
index 00000000..1b21d39c
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2_version.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif /* HAVE_CONFIG_H */
+
+#include "nghttp2.h"
+
+static nghttp2_info version = {NGHTTP2_VERSION_AGE, NGHTTP2_VERSION_NUM,
+ NGHTTP2_VERSION, NGHTTP2_PROTO_VERSION_ID};
+
+nghttp2_info *nghttp2_version(int least_version) {
+ if (least_version > NGHTTP2_VERSION_NUM)
+ return NULL;
+ return &version;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2ver.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2ver.h
new file mode 100644
index 00000000..28ededcd
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/external_libs/nghttp2/nghttp2ver.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#ifndef NGHTTP2VER_H
+#define NGHTTP2VER_H
+
+/**
+ * @macro
+ * Version number of the nghttp2 library release
+ */
+#define NGHTTP2_VERSION "nghttp2"
+
+/**
+ * @macro
+ * Numerical representation of the version number of the nghttp2 library
+ * release. This is a 24 bit number with 8 bits for major number, 8 bits
+ * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
+ */
+#define NGHTTP2_VERSION_NUM 0x013190
+
+#endif /* NGHTTP2VER_H */
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/extract.bat b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/extract.bat
new file mode 100644
index 00000000..61d8cd6e
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/extract.bat
@@ -0,0 +1,11 @@
+@echo off
+
+SET SHELLDIR=tools\prebuilt\windows\shell.w32-ix86
+SET SHELL=%SHELLDIR%/bash.exe
+SET BASH=%SHELL%
+
+SET PATH=%SHELLDIR%;%PATH%
+
+"%SHELL%" extract.sh
+
+pause
\ No newline at end of file
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/extract.sh b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/extract.sh
new file mode 100644
index 00000000..248f8124
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/extract.sh
@@ -0,0 +1,399 @@
+#! /bin/bash
+
+# LOCK_PATTERN=bash_lock
+# LOCK_FILE=${LOCK_PATTERN}.$$
+
+# cleanup ()
+# {
+# rm -f ${LOCK_FILE}
+# }
+
+# trap cleanup EXIT
+
+# if [ "$(ls ${LOCK_PATTERN}.* 2>/dev/null)" = "" ];then
+# echo "LOCK" > ${LOCK_FILE}
+# else
+# echo "Another Extract Script Is Running, Exit..."
+# exit
+# fi
+
+env_check()
+{
+ CHECK_OS=$(uname -r | grep 'ali')
+ if [ "${OS}" = "Linux" ] && [ "${CHECK_OS}" = "" ]; then
+ export PATH=tools/prebuilt/ubuntu/bin:${PATH}
+ fi
+ gawk --help > /dev/null 2>&1
+ if [ "$?" != "0" ];then
+ echo "Please install gawk, using sudo apt-get install gawk for ubuntu 16.04"
+ exit
+ fi
+}
+
+extract_from_cloud()
+{
+ OS=$(uname)
+ EXTRACT_ID=$(curl --connect-timeout 5 -sF "file=@make.settings" --url https://linkkit.aliyuncs.com/upload/config?pk=a1AuWIoEr4Z\&os=${OS})
+ # echo ${EXTRACT_ID}
+ RETRY_COUNT=0
+ if [ "${EXTRACT_ID}" != "" ];then
+ echo ". Download request sent, waiting respond ..."
+ sleep 2
+
+ while :
+ do
+ DOWNLOAD_FILE=$(curl -s --connect-timeout 5 https://linkkit.aliyuncs.com/get/linkkit?extractId=${EXTRACT_ID})
+ # echo ${DOWNLOAD_FILE}
+
+ if [ "${DOWNLOAD_FILE}" = "404" ] || [ "${DOWNLOAD_FILE}" = "" ];then
+ break
+
+ elif [ "${DOWNLOAD_FILE}" = "406" ];then
+ echo ". Respond generating, wait longer"
+
+ if [ "${RETRY_COUNT}" = "20" ];then
+ break
+ fi
+
+ RETRY_COUNT=$[RETRY_COUNT+1]
+
+ echo ". Retried ${RETRY_COUNT}/20"
+ sleep 2
+
+ else
+
+ echo ""
+ curl ${DOWNLOAD_FILE} > output.zip
+ rm -rf output
+ unzip -q output.zip
+ rm -rf output.zip
+ echo ""
+ echo "Please pick up extracted source files in [${PWD}/${OUTPUT_DIR}]"
+ echo ""
+ # rm -rf ${LOCK_FILE}
+ exit
+ fi
+ done
+ fi
+}
+
+OS="$(uname)"
+
+if [ "${OS}" = "Linux" ]; then
+ FIND="find -L"
+else
+ FIND="find"
+fi
+
+OUTPUT_DIR=output
+INFRA_DIR=${OUTPUT_DIR}/eng/infra
+WRAPPERS_DIR=${OUTPUT_DIR}/eng/wrappers
+
+XTRC_FILE_RULS=./tools/misc/xtrc_file_rules
+TEMP_FILE_RULS="${PWD}/.temp_file_rule_filter"
+
+XTRC_WRAPPER_RULS=./tools/misc/xtrc_wrapper_rules
+TEMP_WRAPPER_RULS="${PWD}/.temp_wrapper_rule_filter"
+WRAPPER_DOC=./tools/misc/wrapper
+
+# Try Extract Linkkit From Cloud
+#
+if [ "$1" = "" ] || ( [ "$1" != "test" ] && [ "$1" != "local" ] ) then
+ extract_from_cloud
+fi
+
+# environment check
+env_check
+
+# Prepare Config Macro In make.settings
+MACRO_LIST=$(sed -n '/#/!{/=y/p}' make.settings | sed -n 's/=y//gp' | sed -n 's/FEATURE_//gp')
+
+mkdir -p ${OUTPUT_DIR} ${OUTPUT_DIR}/examples
+rm -rf $(${FIND} ${OUTPUT_DIR} -mindepth 1 -maxdepth 1|grep -v release)
+
+# Generate infra_config.h and extract necessary infra files
+mkdir -p ${INFRA_DIR}
+echo "#ifndef _INFRA_CONFIG_H_" > ${INFRA_DIR}/infra_config.h
+echo -e "#define _INFRA_CONFIG_H_\n" >> ${INFRA_DIR}/infra_config.h
+echo "${MACRO_LIST}" | sed -n 's/^/#define /p' >> ${INFRA_DIR}/infra_config.h
+echo -e "\n#endif" >> ${INFRA_DIR}/infra_config.h
+
+${FIND} ./src -name "infra_types.h" | xargs -i cp -f {} ${INFRA_DIR}
+${FIND} ./src -name "infra_defs.[ch]" | xargs -i cp -f {} ${INFRA_DIR}
+${FIND} ./src -name "infra_list.h" | xargs -i cp -f {} ${INFRA_DIR}
+${FIND} ./src -name "infra_compat.[ch]" | xargs -i cp -f {} ${INFRA_DIR}
+
+# echo -e "${MACRO_LIST}"
+
+cond_and_check()
+{
+ COND_AND_VAR=$(echo $1 | gawk -F '&' '{for(i=1;i<=NF;i++){print $i;}}')
+ # echo "${COND_AND_VAR}"
+ for item in ${COND_AND_VAR}
+ do
+ echo ${MACRO_LIST} | grep -wo ${item} > /dev/null
+ if [ $? -ne 0 ];then
+ return 1
+ fi
+ done
+ return 0
+}
+
+cond_not_check()
+{
+ COND_NOT_VAR=$(echo $1 | gawk -F '&' '{for(i=1;i<=NF;i++){print $i;}}')
+ # echo "${COND_AND_VAR}"
+ for item in ${COND_NOT_VAR}
+ do
+ echo ${MACRO_LIST} | grep -wo ${item} > /dev/null
+ if [ $? -eq 0 ];then
+ return 0
+ fi
+ done
+ return 1
+}
+
+DOTS_LINE=".................................................................."
+
+extract_file_by()
+{
+ local rule="$*"
+
+ COND_AND=$(echo $rule | gawk -F'|' '{print $1}')
+ COND_NOT=$(echo $rule | gawk -F'|' '{print $2}')
+ SRC_DIR=$(echo $rule | gawk -F'|' '{print $3}')
+ DEST_DIR=$(echo $rule | gawk -F'|' '{print $4}')
+
+ # echo "${COND_AND}"
+ cond_and_check "${COND_AND}"
+ if [ $? -ne 0 ]; then
+ return 1
+ fi
+
+ # echo "${COND_NOT}"
+ cond_not_check "${COND_NOT}"
+ if [ $? -eq 0 ]; then
+ return 1
+ fi
+
+ # echo "${SRC_DIR}"
+ # echo "${DEST_DIR}"
+
+ if [ "${DEST_DIR}" != "" ];then
+ mkdir -p ${DEST_DIR} && ${FIND} ${SRC_DIR} -maxdepth 1 -name *.[ch] | xargs -i cp -rf {} ${DEST_DIR}
+ fi
+}
+
+echo ""
+echo "Analysing extract rules for sources and wrappers ..."
+echo ""
+
+SWITCHES=$(cat make.settings | grep -v '^#' | sed '/^$/d;s:FEATURE_::g;s:=.*::g')
+SWCH_PAT="$(echo ${SWITCHES}|sed 's: :\\\|:g')"
+SPEC_PAT="$(echo ${SWITCHES}|sed 's:\([_A-Z]*\) :^\1||\\\|:g')"
+SPEC_PAT="${SPEC_PAT}||"
+
+grep ${SWCH_PAT} ${XTRC_FILE_RULS} > ${TEMP_FILE_RULS}
+grep ${SWCH_PAT} ${XTRC_WRAPPER_RULS} > ${TEMP_WRAPPER_RULS}
+
+FUNC_NAME_LIST=""
+HEADER_FILE_LIST=""
+
+FUNC_NAME_LIST=$(grep "${SPEC_PAT}" ${TEMP_WRAPPER_RULS}|gawk -F '|' '{ print $3 }'|sort -u)
+HEADER_FILE_LIST=$(grep "${SPEC_PAT}" ${TEMP_WRAPPER_RULS}|gawk -F '|' '{ print $4 }'|sort -u)
+
+FUNC_PAT="$(echo ${FUNC_NAME_LIST}|sed 's: :\\\|:g')"
+HDER_PAT="$(echo ${HEADER_FILE_LIST}|sed 's: :\\\|:g')"
+
+# [ "${FUNC_PAT}" != "" ] && sed -i "/${FUNC_PAT}/d" ${TEMP_WRAPPER_RULS}
+# [ "${HDER_PAT}" != "" ] && sed -i "/${HDER_PAT}/d" ${TEMP_WRAPPER_RULS}
+
+#if [ "${FUNC_PAT}" != "" ] && [ "${HDER_PAT}" != "" ]; then
+# sed -i "/${FUNC_PAT}/{/${HDER_PAT}/d}" ${TEMP_WRAPPER_RULS}
+#fi
+
+printf "Interpret [%03d] sources rules" $(cat ${TEMP_FILE_RULS}|wc -l|sed 's/[[:space:]]//g')
+printf " from [%03d] base\n" $(cat ${XTRC_FILE_RULS}|wc -l|sed 's/[[:space:]]//g')
+
+printf "Interpret [%03d] wrapper rules" $(cat ${TEMP_WRAPPER_RULS}|wc -l|sed 's/[[:space:]]//g')
+printf " from [%03d] base" $(cat ${XTRC_WRAPPER_RULS}|wc -l|sed 's/[[:space:]]//g')
+
+echo ""
+
+FUNC_NAME_LIST="$(echo ${FUNC_NAME_LIST}|tr ' ' '\n')\n"
+HEADER_FILE_LIST="$(echo ${HEADER_FILE_LIST}|tr ' ' '\n')\n"
+
+FUNC_NAME_LIST=""
+HEADER_FILE_LIST=""
+
+echo ""
+# Read xtrc_file_rules
+TOTAL_ITERATION=$(wc -l ${TEMP_FILE_RULS}|gawk '{ print $1 }')
+ITER=0
+
+while read rule
+do
+ ITER=$(( ${ITER} + 1 ))
+ printf "\r%.40s %.2f%%" "Extract Files ${DOTS_LINE}" $(echo 100*${ITER}/${TOTAL_ITERATION}|bc -l)
+ TEST=$(echo $rule | gawk -F'|' '{print NF}')
+ if [ ${TEST} -ne 4 ];then
+ continue
+ fi
+
+ if [ "${OS}" = "Linux" ]; then
+ extract_file_by ${rule} &
+ else
+ extract_file_by ${rule}
+ fi
+
+done < ${TEMP_FILE_RULS}
+
+[ "${OS}" = "Linux" ] && wait
+
+rm -f ${TEMP_FILE_RULS}
+echo -e ""
+
+# Generate wrapper.c
+mkdir -p ${WRAPPERS_DIR}
+cp -f wrappers/wrappers_defs.h ${WRAPPERS_DIR}/
+
+# Read xtrc_wrapper_rules
+TOTAL_ITERATION=$(wc -l ${TEMP_WRAPPER_RULS}|gawk '{ print $1 }')
+ITER=0
+
+while read rule
+do
+ ITER=$(( ${ITER} + 1 ))
+ printf "\r%.40s %.2f%%" "Extract HAL/Wrapper Functions ${DOTS_LINE}" $(echo 100*${ITER}/${TOTAL_ITERATION}|bc -l)
+ TEST=$(echo $rule | gawk -F'|' '{print NF}')
+ if [ ${TEST} -ne 4 ];then
+ continue
+ fi
+
+ COND_AND=$(echo $rule | gawk -F'|' '{print $1}')
+ COND_NOT=$(echo $rule | gawk -F'|' '{print $2}')
+ FUNC_NAME=$(echo $rule | gawk -F'|' '{print $3}')
+ HEADER_FILE=$(echo $rule | gawk -F'|' '{print $4}')
+
+ # echo "${COND_AND}"
+ cond_and_check "${COND_AND}"
+ if [ $? -ne 0 ];then
+ continue
+ fi
+
+ # echo "${COND_NOT}"
+ cond_not_check "${COND_NOT}"
+ if [ $? -eq 0 ];then
+ continue
+ fi
+
+ if [ "${FUNC_NAME}" != "" ];then
+ FUNC_NAME_LIST="${FUNC_NAME_LIST}""${FUNC_NAME}\n"
+ fi
+ if [ "${HEADER_FILE}" != "" ];then
+ HEADER_FILE_LIST="${HEADER_FILE_LIST}""${HEADER_FILE}\n"
+ fi
+done < ${TEMP_WRAPPER_RULS}
+rm -f ${TEMP_WRAPPER_RULS}
+
+echo -e ""
+
+FUNC_NAME_LIST=$(echo -e "${FUNC_NAME_LIST}" | sed -n '/^$/!{p}' | sort -u)
+HEADER_FILE_LIST=$(echo -e "${HEADER_FILE_LIST}" | sed -n '/^$/!{p}' | sort -u)
+
+# For Debug
+if [ "${FUNC_NAME_LIST}" != "" ];then
+ echo -e "\nHAL/Wrapper Function List:" && echo -e "${FUNC_NAME_LIST}" |gawk '{ printf("%03d %s\n", NR, $0); }'
+fi
+
+if [ "${HEADER_FILE_LIST}" != "" ];then
+ echo -e "\nHAL/Wrapper Header File List:" && echo -e "${HEADER_FILE_LIST}" |gawk '{ printf("%03d %s\n", NR, $0); }'
+fi
+
+# Annotation For wrapper.c
+sed -n '/WRAPPER_NOTE:/{:a;N;/*\//!ba;p}' ${WRAPPER_DOC} | sed -n '1d;p' >> ${WRAPPERS_DIR}/wrapper.c
+
+# Output Header File Into wrapper.c
+echo -e "#include \"infra_types.h\"" >> ${WRAPPERS_DIR}/wrapper.c
+echo -e "#include \"infra_defs.h\"" >> ${WRAPPERS_DIR}/wrapper.c
+echo -e "#include \"infra_compat.h\"" >> ${WRAPPERS_DIR}/wrapper.c
+echo -e "#include \"wrappers_defs.h\"" >> ${WRAPPERS_DIR}/wrapper.c
+echo -e "${HEADER_FILE_LIST}" | sed -n '/.h/{s/^/#include "/p}' | sed -n 's/$/"/p' >> ${WRAPPERS_DIR}/wrapper.c
+echo -e "" >> ${WRAPPERS_DIR}/wrapper.c
+
+# Generate Default Implenmentation For HAL/Wrapper Function
+echo ""
+TOTAL_ITERATION=$(echo "${FUNC_NAME_LIST}"|wc -w|sed 's/[[:space:]]//g')
+ITER=0
+
+for func in $(echo "${FUNC_NAME_LIST}")
+do
+ ITER=$(( ${ITER} + 1 ))
+ printf "\r%.40s %.2f%%" "Generate wrapper.c ${DOTS_LINE}" $(echo 100*${ITER}/${TOTAL_ITERATION}|bc -l)
+
+ # echo ${func}
+ if [ "${func}" = "" ];then
+ continue
+ fi
+
+ FUNC_DEC=$(${FIND} ./src -name *wrapper.h | xargs -i cat {})
+ FUNC_DEC=$(echo "${FUNC_DEC}" | sed -n '/.*'${func}'(.*/{/.*);/ba;{:c;N;/.*);/!bc};:a;p;q}')
+
+ DATA_TYPE=$(echo "${FUNC_DEC}" | head -1 | gawk -F' ' '{if ($1~/^DLL/ || $1~/extern/) {if ($3~/*/) {print $2"*";} else {print $2;}} else {if ($2~/*/) {print $1"*";} else {print $1;}}}'# | sed s/[[:space:]]//g)
+ # echo -e "\n${DATA_TYPE}"
+ # echo -e "\n${FUNC_DEC}"
+
+ FUNC_FILE=$(grep ${func} ./wrappers/os/ubuntu/* | gawk -F':' '{print $1}' | sed -n 's/.\/wrappers\///g;s/\//\\\//g;p' | sed -n '1,1p')
+ if [ "${FUNC_FILE}" = "" ];then
+ FUNC_FILE=$(grep ${func} ./wrappers/tls/* | gawk -F':' '{print $1}' | sed -n 's/.\/wrappers\///g;s/\//\\\//g;p' | sed -n '1,1p')
+ fi
+ # echo -e "\n${FUNC_FILE}"
+
+ sed -n '/WRAPPER_FUNC_REFERENCE:/{:a;N;/*\//!ba;p}' ${WRAPPER_DOC} | sed -n '1d;s/FUNC_NAME/'${func}'/g;s/FUNC_FILE/'${FUNC_FILE}'/g;p' >> ${WRAPPERS_DIR}/wrapper.c
+ sed -n '/'${func}':/{:a;N;/*\//!ba;p}' ${WRAPPER_DOC} | sed -n '1d;p' >> ${WRAPPERS_DIR}/wrapper.c
+
+ if [ "${DATA_TYPE}" = "void" ];then
+ echo "${FUNC_DEC}" | sed -n 's/^ *//1;/;/{s/;/\n{\n\treturn;\n}\n\n/g};p' >> ${WRAPPERS_DIR}/wrapper.c
+ else
+ echo "${FUNC_DEC}" | sed -n 's/^ *//1;/;/{s/;/\n{\n\treturn ('${DATA_TYPE}')1;\n}\n\n/g};p' >> ${WRAPPERS_DIR}/wrapper.c
+ fi
+done
+
+if [ "${TOTAL_ITERATION}" = "0" ]; then
+ echo "Only [dev_sign] enabled, so NO function requires being implemented in [${WRAPPERS_DIR}/wrapper.c]"
+else
+ echo ""
+fi
+
+echo -e "#ifndef _SDK_INCLUDE_H_" > ${OUTPUT_DIR}/eng/sdk_include.h
+echo -e "#define _SDK_INCLUDE_H_\n" >> ${OUTPUT_DIR}/eng/sdk_include.h
+echo -e "#include \"infra_types.h\"" >> ${OUTPUT_DIR}/eng/sdk_include.h
+echo -e "#include \"infra_defs.h\"" >> ${OUTPUT_DIR}/eng/sdk_include.h
+echo -e "#include \"infra_compat.h\"" >> ${OUTPUT_DIR}/eng/sdk_include.h
+echo -e "#include \"wrappers_defs.h\"" >> ${OUTPUT_DIR}/eng/sdk_include.h
+find ${OUTPUT_DIR}/eng -name "*wrapper.h" | gawk -F'/' '{print $NF}' | sed -n 's/^/#include "/g;s/$/"/gp' >> ${OUTPUT_DIR}/eng/sdk_include.h
+find ${OUTPUT_DIR}/eng -name "*api.h" | gawk -F'/' '{print $NF}' | sed -n 's/^/#include "/g;s/$/"/gp' >> ${OUTPUT_DIR}/eng/sdk_include.h
+echo -e "\n#endif" >> ${OUTPUT_DIR}/eng/sdk_include.h
+
+# if echo "${SWITCHES}"|grep -qw "DEVICE_MODEL_ENABLED"; then
+# echo ""
+# bash tools/misc/compose.sh ${PWD}/output/examples/linkkit_example_auto.c
+# fi
+
+echo ""
+echo "Please pick up extracted source files in [${PWD}/${OUTPUT_DIR}]"
+echo ""
+
+cp tools/misc/makefile.output output/Makefile
+if [ "${1}" = "test" ];then
+ ENV_TEST=$(cat .config 2>/dev/null| sed -n '/VENDOR/{s/[[:space:]]//gp}'| gawk -F ':' '{print $2}')
+ if [ "${ENV_TEST}" = "ubuntu" ];then
+ rm -f ${WRAPPERS_DIR}/wrapper.c
+ cp -rf wrappers/os/ubuntu ${WRAPPERS_DIR}/
+ cp -rf wrappers/tls ${WRAPPERS_DIR}/
+ cp -rfl external_libs ${WRAPPERS_DIR}/
+ rm -f ${WRAPPERS_DIR}/ubuntu/HAL_UART_linux.c
+ fi
+fi
+
+# rm -rf ${LOCK_FILE}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/make.settings b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/make.settings
new file mode 100644
index 00000000..b2fcb7c9
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/make.settings
@@ -0,0 +1,88 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Main Menu
+#
+
+#
+# Configure C-SDK for IoT Embedded Devices
+#
+FEATURE_PLATFORM_HAS_STDINT=y
+FEATURE_PLATFORM_HAS_DYNMEM=y
+# FEATURE_PLATFORM_HAS_OS is not set
+FEATURE_INFRA_STRING=y
+FEATURE_INFRA_NET=y
+FEATURE_INFRA_LIST=y
+FEATURE_INFRA_LOG_NETWORK_PAYLOAD=y
+FEATURE_INFRA_LOG=y
+
+#
+# Log Configurations
+#
+FEATURE_INFRA_LOG_ALL_MUTED=y
+FEATURE_INFRA_LOG_MUTE_FLW=y
+FEATURE_INFRA_LOG_MUTE_DBG=y
+FEATURE_INFRA_LOG_MUTE_INF=y
+FEATURE_INFRA_LOG_MUTE_WRN=y
+FEATURE_INFRA_LOG_MUTE_ERR=y
+FEATURE_INFRA_LOG_MUTE_CRT=y
+# FEATURE_INFRA_MEM_STATS is not set
+FEATURE_INFRA_TIMER=y
+# FEATURE_INFRA_RANDOM is not set
+# FEATURE_INFRA_JSON_PARSER is not set
+FEATURE_INFRA_CJSON=y
+# FEATURE_INFRA_MD5 is not set
+# FEATURE_INFRA_SHA1 is not set
+FEATURE_INFRA_SHA256=y
+FEATURE_INFRA_REPORT=y
+# FEATURE_INFRA_HTTPC is not set
+FEATURE_INFRA_COMPAT=y
+FEATURE_INFRA_CLASSIC=y
+# FEATURE_INFRA_PREAUTH is not set
+# FEATURE_INFRA_AES is not set
+FEATURE_DEV_SIGN=y
+FEATURE_MQTT_COMM_ENABLED=y
+
+#
+# MQTT Configurations
+#
+FEATURE_MQTT_DEFAULT_IMPL=y
+# FEATURE_MQTT_PRE_AUTH is not set
+FEATURE_MQTT_DIRECT=y
+# FEATURE_ASYNC_PROTOCOL_STACK is not set
+# FEATURE_DYNAMIC_REGISTER is not set
+FEATURE_DEVICE_MODEL_CLASSIC=y
+FEATURE_LOG_REPORT_TO_CLOUD=y
+FEATURE_DEVICE_MODEL_ENABLED=y
+
+#
+# Device Model Configurations
+#
+# FEATURE_DEVICE_MODEL_GATEWAY is not set
+# FEATURE_DEPRECATED_LINKKIT is not set
+# FEATURE_DEVICE_MODEL_RAWDATA_SOLO is not set
+# FEATURE_ALCS_ENABLED is not set
+# FEATURE_SUB_PERSISTENCE_ENABLED is not set
+# FEATURE_DEVICE_MODEL_SHADOW is not set
+# FEATURE_HAL_KV is not set
+# FEATURE_SUPPORT_TLS is not set
+# FEATURE_HAL_CRYPTO is not set
+# FEATURE_HAL_UDP is not set
+# FEATURE_COAP_DTLS_SUPPORT is not set
+# FEATURE_ATM_ENABLED is not set
+# FEATURE_OTA_ENABLED is not set
+# FEATURE_COAP_COMM_ENABLED is not set
+# FEATURE_COAP_PACKET is not set
+# FEATURE_COAP_CLIENT is not set
+# FEATURE_COAP_SERVER is not set
+# FEATURE_DEV_RESET is not set
+# FEATURE_HTTP_COMM_ENABLED is not set
+# FEATURE_HTTP2_COMM_ENABLED is not set
+# FEATURE_FS_ENABLED is not set
+# FEATURE_AWSS_SUPPORT_APLIST is not set
+# FEATURE_AWSS_DISABLE_ENROLLEE is not set
+# FEATURE_AWSS_DISABLE_REGISTRAR is not set
+# FEATURE_AWSS_SUPPORT_ADHA is not set
+# FEATURE_AWSS_FRAMEWORKS is not set
+# FEATURE_WIFI_PROVISION_ENABLED is not set
+# FEATURE_AWSS_SUPPORT_SMARTCONFIG_WPS is not set
+# FEATURE_DEV_BIND_ENABLED is not set
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/makefile b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/makefile
new file mode 100644
index 00000000..00c5c086
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/makefile
@@ -0,0 +1,37 @@
+include tools/project.mk
+include make.settings
+include tools/default_settings.mk
+include tools/parse_make_settings.mk
+include $(RULE_DIR)/funcs.mk
+
+# CFLAGS += -DINSPECT_MQTT_FLOW
+
+COMP_LIB := libiot_sdk.a
+COMP_LIB_COMPONENTS := \
+ src/infra \
+ src/dev_sign \
+
+$(call CompLib_Map, FEATURE_MQTT_COMM_ENABLED, src/mqtt)
+$(call CompLib_Map, FEATURE_COAP_CLIENT, src/coap)
+$(call CompLib_Map, FEATURE_COAP_SERVER, src/coap)
+$(call CompLib_Map, FEATURE_SUPPORT_TLS, certs)
+$(call CompLib_Map, FEATURE_COAP_DTLS_SUPPORT, certs)
+$(call CompLib_Map, FEATURE_DYNAMIC_REGISTER, src/dynamic_register)
+$(call CompLib_Map, FEATURE_ATM_ENABLED, src/atm)
+$(call CompLib_Map, FEATURE_DEV_RESET, src/dev_reset)
+$(call CompLib_Map, FEATURE_OTA_ENABLED, src/ota)
+$(call CompLib_Map, FEATURE_DEVICE_MODEL_ENABLED, src/dev_model)
+$(call CompLib_Map, FEATURE_HTTP_COMM_ENABLED, src/http)
+$(call CompLib_Map, FEATURE_DEV_BIND_ENABLED, src/dev_bind)
+$(call CompLib_Map, FEATURE_WIFI_PROVISION_ENABLED, src/wifi_provision)
+$(call CompLib_Map, FEATURE_HTTP2_COMM_ENABLED, src/http2)
+
+SUBDIRS += wrappers
+SUBDIRS += external_libs/mbedtls
+SUBDIRS += tests
+
+$(call Append_Conditional, SUBDIRS, external_libs/nghttp2, HTTP2_COMM_ENABLED)
+
+include $(RULE_DIR)/rules.mk
+include tools/mock_build_options.mk
+
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/model.json b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/model.json
new file mode 100644
index 00000000..9989387b
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/model.json
@@ -0,0 +1,222 @@
+{
+ "schema":"https://iotx-tsl.oss-ap-southeast-1.aliyuncs.com/schema.json",
+ "profile":{
+ "productKey":"a1h88DsZIaY"
+ },
+ "services":[
+ {
+ "outputData":[
+
+ ],
+ "identifier":"set",
+ "inputData":[
+ {
+ "identifier":"LightStatus",
+ "dataType":{
+ "specs":{
+ "0":"å…³é—",
+ "1":"打开"
+ },
+ "type":"bool"
+ },
+ "name":"工作状æ€"
+ },
+ {
+ "identifier":"LightAdjustLevel",
+ "dataType":{
+ "specs":{
+ "unit":"%",
+ "min":"0",
+ "max":"100",
+ "step":"1"
+ },
+ "type":"int"
+ },
+ "name":"调光ç‰çº§"
+ },
+ {
+ "identifier":"LightAlias",
+ "dataType":{
+ "specs":{
+ "length":"32"
+ },
+ "type":"text"
+ },
+ "name":"别å"
+ }
+ ],
+ "method":"thing.service.property.set",
+ "name":"set",
+ "required":true,
+ "callType":"async",
+ "desc":"属性设置"
+ },
+ {
+ "outputData":[
+ {
+ "identifier":"LightStatus",
+ "dataType":{
+ "specs":{
+ "0":"å…³é—",
+ "1":"打开"
+ },
+ "type":"bool"
+ },
+ "name":"工作状æ€"
+ },
+ {
+ "identifier":"LightAdjustLevel",
+ "dataType":{
+ "specs":{
+ "unit":"%",
+ "min":"0",
+ "max":"100",
+ "step":"1"
+ },
+ "type":"int"
+ },
+ "name":"调光ç‰çº§"
+ },
+ {
+ "identifier":"LightAlias",
+ "dataType":{
+ "specs":{
+ "length":"32"
+ },
+ "type":"text"
+ },
+ "name":"别å"
+ }
+ ],
+ "identifier":"get",
+ "inputData":[
+ "LightStatus",
+ "LightAdjustLevel",
+ "LightAlias"
+ ],
+ "method":"thing.service.property.get",
+ "name":"get",
+ "required":true,
+ "callType":"async",
+ "desc":"属性获å–"
+ }
+ ],
+ "properties":[
+ {
+ "identifier":"LightStatus",
+ "dataType":{
+ "specs":{
+ "0":"å…³é—",
+ "1":"打开"
+ },
+ "type":"bool"
+ },
+ "name":"工作状æ€",
+ "accessMode":"rw",
+ "required":false
+ },
+ {
+ "identifier":"LightAdjustLevel",
+ "dataType":{
+ "specs":{
+ "unit":"%",
+ "min":"0",
+ "max":"100",
+ "step":"1"
+ },
+ "type":"int"
+ },
+ "name":"调光ç‰çº§",
+ "accessMode":"rw",
+ "required":false,
+ "desc":"调光ç‰çº§é‡‡ç”¨ç™¾åˆ†æ¯”表示"
+ },
+ {
+ "identifier":"LightAlias",
+ "dataType":{
+ "specs":{
+ "length":"32"
+ },
+ "type":"text"
+ },
+ "name":"别å",
+ "accessMode":"rw",
+ "required":false
+ }
+ ],
+ "events":[
+ {
+ "outputData":[
+ {
+ "identifier":"LightStatus",
+ "dataType":{
+ "specs":{
+ "0":"å…³é—",
+ "1":"打开"
+ },
+ "type":"bool"
+ },
+ "name":"工作状æ€"
+ },
+ {
+ "identifier":"LightAdjustLevel",
+ "dataType":{
+ "specs":{
+ "unit":"%",
+ "min":"0",
+ "max":"100",
+ "step":"1"
+ },
+ "type":"int"
+ },
+ "name":"调光ç‰çº§"
+ },
+ {
+ "identifier":"LightAlias",
+ "dataType":{
+ "specs":{
+ "length":"32"
+ },
+ "type":"text"
+ },
+ "name":"别å"
+ }
+ ],
+ "identifier":"post",
+ "method":"thing.event.property.post",
+ "name":"post",
+ "type":"info",
+ "required":true,
+ "desc":"属性上报"
+ },
+ {
+ "outputData":[
+ {
+ "identifier":"ErrorCode",
+ "dataType":{
+ "specs":{
+ "0":"æ¢å¤æ£å¸¸"
+ },
+ "type":"enum"
+ },
+ "name":"故障代ç "
+ }
+ ],
+ "identifier":"Error",
+ "method":"thing.event.Error.post",
+ "name":"故障上报",
+ "type":"alert",
+ "required":false
+ },
+ {
+ "outputData":[
+
+ ],
+ "identifier":"TamperAlarm",
+ "method":"thing.event.TamperAlarm.post",
+ "name":"防撬报è¦",
+ "type":"alert",
+ "required":false
+ }
+ ]
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_api.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_api.c
new file mode 100644
index 00000000..fd8073d4
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_api.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015-2019 Alibaba Group Holding Limited
+ */
+
+#include "infra_config.h"
+
+int at_conn_init(void);
+int at_parser_init(void);
+
+/* See detail struct definition in at_wrapper.h */
+struct at_conn_input;
+struct at_mqtt_input;
+int at_conn_input(struct at_conn_input *param);
+int at_mqtt_input(struct at_mqtt_input *param);
+
+int IOT_ATM_Init(void)
+{
+#ifdef AT_PARSER_ENABLED
+ if (at_parser_init() < 0) {
+ return -1;
+ }
+#endif
+
+#ifdef AT_TCP_ENABLED
+ if (at_conn_init() < 0) {
+ return -1;
+ }
+#endif
+
+ return 0;
+}
+
+
+int IOT_ATM_Input(void * param)
+{
+ int ret = -1;
+
+#if defined(AT_TCP_ENABLED)
+ ret = at_conn_input((struct at_conn_input *)param);
+#elif defined(AT_MQTT_ENABLED)
+ ret = at_mqtt_input((struct at_mqtt_input *)param);
+#endif
+
+ return ret;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_api.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_api.h
new file mode 100644
index 00000000..e46c57cb
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_api.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2015-2019 Alibaba Group Holding Limited
+ */
+
+#ifndef _AT_API_H_
+#define _AT_API_H_
+
+/**
+ * AT module initialization.
+ * Call this function before example starts.
+ * at_parser or at_tcp will be initialized if enabled.
+ * @param[in] none
+ *
+ * @return 0 - success, -1 - failure
+ */
+int IOT_ATM_Init(void);
+
+
+/**
+ * Hand received data to ATM layer.
+ * Call this function in low-layer HAL.
+ * @param[in] param pointer to input struct.
+ * See struct at_conn_input and struct at_mqtt_input
+ * in at_wrapper.h
+ *
+ * @return 0 - success, -1 - failure
+ */
+int IOT_ATM_Input(void * param);
+
+#endif
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mbox.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mbox.c
new file mode 100644
index 00000000..e43ee54d
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mbox.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2015-2019 Alibaba Group Holding Limited
+ */
+
+#include "infra_types.h"
+#include "at_wrapper.h"
+
+#include "at_conn_mbox.h"
+
+typedef struct
+{
+ void *buffer;
+ uint32_t length;
+ uint32_t head;
+ uint32_t tail;
+ uint8_t full;
+} at_ringbuf_t;
+
+#ifndef PLATFORM_HAS_DYNMEM
+static at_ringbuf_t ringbufs[AT_CONN_NUM] = {{NULL, 0, 0, 0, 0}};
+#endif
+
+static at_ringbuf_t *alloc_ringbuf(void)
+{
+#ifdef PLATFORM_HAS_DYNMEM
+ return HAL_Malloc(sizeof(at_ringbuf_t));
+#else
+ int i;
+
+ for (i = 0; i < AT_CONN_NUM; i++) {
+ if (NULL == ringbufs[i].buffer) {
+ return &ringbufs[i];
+ }
+ }
+
+ return NULL;
+#endif
+}
+
+static void free_ringbuf(at_ringbuf_t *ringbuf)
+{
+ if (ringbuf) {
+#ifdef PLATFORM_HAS_DYNMEM
+ HAL_Free(ringbuf);
+#else
+ memset(ringbuf, 0, sizeof(at_ringbuf_t));
+#endif
+ }
+}
+
+static int at_ringbuf_available_read_space(at_ringbuf_t *ringbuf)
+{
+ if (ringbuf->full)
+ return ringbuf->length;
+
+ if (ringbuf->head == ringbuf->tail) {
+ return 0;
+ } else if (ringbuf->head < ringbuf->tail) {
+ return ringbuf->tail - ringbuf->head;
+ } else {
+ return ringbuf->length - (ringbuf->head - ringbuf->tail);
+ }
+}
+
+static int at_ringbuf_full(at_ringbuf_t *ringbuf)
+{
+ return ringbuf->full;
+}
+
+static int at_ringbuf_empty(at_ringbuf_t *ringbuf)
+{
+ return (at_ringbuf_available_read_space(ringbuf) == 0);
+}
+
+static at_ringbuf_t *at_ringbuf_create(int length, void *buf)
+{
+ at_ringbuf_t *ringbuf = NULL;
+
+ if (length < 2 || NULL == buf) {
+ HAL_Printf("Error: ringbuf len MUST exceed one!");
+ return NULL;
+ }
+
+ ringbuf = alloc_ringbuf();
+ if (ringbuf == NULL) {
+ return NULL;
+ }
+ memset(ringbuf, 0, sizeof(at_ringbuf_t));
+
+ ringbuf->length = length;
+ ringbuf->buffer = buf;
+
+ return ringbuf;
+}
+
+static void at_ringbuf_clear_all(at_ringbuf_t *ringbuf)
+{
+ ringbuf->head = ringbuf->tail = 0;
+}
+
+static void at_ringbuf_destroy(at_ringbuf_t *ringbuf)
+{
+ if (ringbuf) {
+ if (ringbuf->buffer) {
+ at_ringbuf_clear_all(ringbuf);
+
+ ringbuf->buffer = NULL;
+ }
+ free_ringbuf(ringbuf);
+ }
+}
+
+static int at_ringbuf_write(at_ringbuf_t *ringbuf, void *data, int size)
+{
+ uint32_t next;
+
+ if (ringbuf == NULL || data == NULL) {
+ return -1;
+ }
+
+ if (at_ringbuf_full(ringbuf)) {
+ HAL_Printf("ringbuf full!");
+ return -1;
+ }
+
+ memcpy(&(((void **) ringbuf->buffer)[ringbuf->tail]), data, size);
+ next = (ringbuf->tail + 1) % (ringbuf->length);
+ if (next == ringbuf->head) {
+ ringbuf->full = 1;
+ } else {
+ ringbuf->tail = next;
+ }
+
+ return 0;
+}
+
+static int at_ringbuf_read(at_ringbuf_t *ringbuf, void *target,
+ unsigned int ms, unsigned int *size)
+{
+ *size = 0;
+
+ if (ringbuf == NULL || target == NULL) {
+ return -1;
+ }
+
+ /* TODO: timeout handle */
+ if (at_ringbuf_empty(ringbuf)) {
+ return -1;
+ }
+
+ memcpy(((void **)target), &((void **)ringbuf->buffer)[ringbuf->head], sizeof(void *));
+ ((void **)ringbuf->buffer)[ringbuf->head] = NULL;
+ *size = sizeof(void *);
+ ringbuf->head = (ringbuf->head + 1) % (ringbuf->length);
+
+ if (ringbuf->full) {
+ ringbuf->full = 0;
+ ringbuf->tail = (ringbuf->tail + 1) % (ringbuf->length);
+ }
+
+ return 0;
+}
+
+/**********************public interface***********************/
+int at_mbox_new(at_mbox_t *mb, int size, void *buf)
+{
+ void *hdl = NULL;
+
+ if (NULL == mb || NULL == buf) {
+ return -1;
+ }
+
+ hdl = at_ringbuf_create(size, buf);
+ if (hdl == NULL) {
+ return -1;
+ }
+ mb->hdl = hdl;
+
+ return 0;
+}
+
+void at_mbox_free(at_mbox_t *mb)
+{
+ if ((mb != NULL)) {
+ at_ringbuf_destroy((at_ringbuf_t *)mb->hdl);
+ }
+}
+
+void at_mbox_post(at_mbox_t *mb, void *msg)
+{
+ at_ringbuf_write((at_ringbuf_t *)mb->hdl, &msg, sizeof(void *));
+}
+
+int at_mbox_trypost(at_mbox_t *mb, void *msg)
+{
+ if (at_ringbuf_write((at_ringbuf_t *)mb->hdl,
+ &msg, sizeof(void *)) != 0) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+int at_mbox_valid(at_mbox_t *mbox)
+{
+ if (mbox == NULL) {
+ return 0;
+ }
+
+ if (mbox->hdl == NULL) {
+ return 0;
+ }
+
+ return 1;
+}
+
+uint32_t at_mbox_fetch(at_mbox_t *mb, void **msg, uint32_t timeout)
+{
+ uint32_t begin_ms, end_ms, elapsed_ms;
+ uint32_t len;
+ uint32_t ret;
+
+ if (mb == NULL) {
+ return AT_MBOX_TIMEOUT;
+ }
+
+ begin_ms = HAL_UptimeMs();
+
+ if (timeout != 0UL) {
+ if (at_ringbuf_read((at_ringbuf_t *)mb->hdl, msg, timeout, &len) == 0) {
+ end_ms = HAL_UptimeMs();
+ elapsed_ms = end_ms - begin_ms;
+ ret = elapsed_ms;
+ } else {
+ ret = AT_MBOX_TIMEOUT;
+ }
+ } else {
+ while (at_ringbuf_read((at_ringbuf_t *)mb->hdl, msg, AT_MBOX_TIMEOUT, &len) != 0);
+ end_ms = HAL_UptimeMs();
+ elapsed_ms = end_ms - begin_ms;
+
+ if (elapsed_ms == 0UL) {
+ elapsed_ms = 1UL;
+ }
+
+ ret = elapsed_ms;
+ }
+
+ return ret;
+}
+
+uint32_t at_mbox_tryfetch(at_mbox_t *mb, void **msg)
+{
+ uint32_t len;
+
+ if (mb == NULL) {
+ return AT_MBOX_EMPTY;
+ }
+
+ if (at_ringbuf_read((at_ringbuf_t *)mb->hdl, msg, 0u, &len) != 0) {
+ return AT_MBOX_EMPTY;
+ } else {
+ return 0;
+ }
+}
+
+int at_mbox_empty(at_mbox_t *mb)
+{
+ if (mb == NULL) {
+ return -1;
+ }
+
+ return at_ringbuf_empty((at_ringbuf_t *)mb->hdl);
+}
+
+void at_mbox_set_invalid(at_mbox_t *mb)
+{
+ if (mb != NULL) {
+ mb->hdl = NULL;
+ }
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mbox.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mbox.h
new file mode 100644
index 00000000..a3a05c94
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mbox.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015-2019 Alibaba Group Holding Limited
+ */
+
+#ifndef _AT_CONN_MBOX_H_
+#define _AT_CONN_MBOX_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AT_CONN_NUM 3
+#define AT_MBOX_TIMEOUT (~0)
+#define AT_MBOX_EMPTY (~0)
+
+typedef struct
+{
+ void *hdl;
+} at_mbox_t;
+
+/**
+ * @ingroup sys_mbox
+ * Create a new mbox of specified size
+ * @param mbox pointer to the mbox to create
+ * @param size (minimum) number of messages in this mbox
+ * @return 0 if successful, another err_t otherwise
+ */
+int at_mbox_new(at_mbox_t *mbox, int size, void *buf);
+/**
+ * @ingroup sys_mbox
+ * Post a message to an mbox - may not fail
+ * -> blocks if full, only used from tasks not from ISR
+ * @param mbox mbox to posts the message
+ * @param msg message to post (ATTENTION: can be NULL)
+ */
+void at_mbox_post(at_mbox_t *mbox, void *msg);
+/**
+ * @ingroup sys_mbox
+ * Try to post a message to an mbox - may fail if full or ISR
+ * @param mbox mbox to posts the message
+ * @param msg message to post (ATTENTION: can be NULL)
+ */
+int at_mbox_trypost(at_mbox_t *mbox, void *msg);
+/**
+ * @ingroup sys_mbox
+ * Wait for a new message to arrive in the mbox
+ * @param mbox mbox to get a message from
+ * @param msg pointer where the message is stored
+ * @param timeout maximum time (in milliseconds) to wait for a message (0 = wait forever)
+ * @return time (in milliseconds) waited for a message, may be 0 if not waited
+ or SYS_ARCH_TIMEOUT on timeout
+ * The returned time has to be accurate to prevent timer jitter!
+ */
+uint32_t at_mbox_fetch(at_mbox_t *mbox, void **msg, uint32_t timeout);
+/**
+ * @ingroup sys_mbox
+ * Wait for a new message to arrive in the mbox
+ * @param mbox mbox to get a message from
+ * @param msg pointer where the message is stored
+ * @return 0 (milliseconds) if a message has been received
+ * or at_MBOX_EMPTY if the mailbox is empty
+ */
+uint32_t at_mbox_tryfetch(at_mbox_t *mbox, void **msg);
+
+/**
+ * @ingroup sys_mbox
+ * Delete an mbox
+ * @param mbox mbox to delete
+ */
+void at_mbox_free(at_mbox_t *mbox);
+
+/**
+ * @ingroup sys_mbox
+ * Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid
+ */
+int at_mbox_valid(at_mbox_t *mbox);
+
+/**
+ * @ingroup sys_mbox
+ * Set an mbox invalid so that sys_mbox_valid returns 0
+ */
+void at_mbox_set_invalid(at_mbox_t *mbox);
+
+/**
+ * @ingroup sys_mbox
+ * Set an mbox invalid so that sys_mbox_valid returns 0
+ */
+int at_mbox_empty(at_mbox_t *mb);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_at_ARCH_H_*/
+
+
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mgmt.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mgmt.c
new file mode 100644
index 00000000..15113704
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mgmt.c
@@ -0,0 +1,654 @@
+/*
+ * Copyright (C) 2015-2019 Alibaba Group Holding Limited
+ */
+
+#include
+#include
+
+#include "infra_types.h"
+#include "mqtt_api.h"
+#include "at_wrapper.h"
+
+#include "at_conn_mbox.h"
+#include "at_conn_mgmt.h"
+
+#define AT_DEFAULT_INPUTMBOX_SIZE 3
+#define AT_DEFAULT_PAYLOAD_SIZE (CONFIG_MQTT_MESSAGE_MAXLEN + CONFIG_MQTT_TOPIC_MAXLEN + 20)
+
+#define AT_DEFAULT_SEND_TIMEOUT_MS 1000
+#define AT_DEFAULT_RECV_TIMEOUT_MS 1000
+
+#define DNS_MAX_NAME_LENGTH 256
+#define AT_IP4_ANY_ADDR "0.0.0.0"
+#define IPV4_STR_MAX_LEN 16
+
+#define AT_MAX_PAYLOAD_SIZE 1512
+
+#define UNUSED_ATCONN -1
+
+#ifdef AT_DEBUG_MODE
+#define AT_DEBUG(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define AT_ERROR(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#else
+#define AT_DEBUG(...)
+#define AT_ERROR(...)
+#endif
+
+enum netconn_state {
+ NETCONN_NONE = 0,
+ NETCONN_WRITE,
+ NETCONN_LISTEN,
+ NETCONN_CONNECT,
+ NETCONN_CLOSE
+};
+
+/** Contains all internal pointers and states used for a socket */
+struct at_conn {
+ /** connnection ID */
+ int connid;
+ /** type of the netconn (TCP) */
+ enum netconn_type type;
+ /** current state of the netconn */
+ enum netconn_state state;
+ /** remote port number */
+ uint16_t remote_port;
+ /** remote ip address */
+ char remote_ip[IPV4_STR_MAX_LEN];
+ /** data that was left from the previous read */
+ void *lastdata;
+ /** offset in the data that was left from the previous read */
+ uint16_t lastoffset;
+ /** mbox where received packets are stored until they are fetched
+ by the neconn application thread. */
+ at_mbox_t recvmbox;
+ /** pointer buffer for mbox which is used by ringbuf module. */
+ void *recvbuf[AT_DEFAULT_INPUTMBOX_SIZE];
+ /** timeout to wait for sending data (which means enqueueing data for sending
+ in internal buffers) in milliseconds */
+ int send_timeout_ms;
+ /** timeout in milliseconds to wait for new data to be received
+ (or connections to arrive for listening netconns) */
+ int recv_timeout_ms;
+};
+
+typedef struct at_netbuf {
+ void *payload;
+ uint16_t len;
+ uint16_t remote_port;
+ char remote_ip[IPV4_STR_MAX_LEN];
+} at_netbuf_t;
+
+/** The global array of available at */
+static struct at_conn atconnects[AT_CONN_NUM];
+static void *g_atconnmutex = NULL;
+
+#ifndef PLATFORM_HAS_DYNMEM
+static at_netbuf_t atnetbuf[AT_DEFAULT_INPUTMBOX_SIZE] =
+ {{NULL, 0, 0, {'\0'}}};
+
+typedef struct at_payload {
+ uint8_t buf[AT_DEFAULT_PAYLOAD_SIZE];
+ uint8_t used;
+} at_payload_t;
+
+static at_payload_t atpayload[AT_DEFAULT_INPUTMBOX_SIZE] =
+ {{{0}, 0}};
+#endif
+
+static void *alloc_payload(int size)
+{
+#ifdef PLATFORM_HAS_DYNMEM
+ return HAL_Malloc(size);
+#else
+ int i;
+
+ if (size <= 0 || size > AT_DEFAULT_PAYLOAD_SIZE) {
+ return NULL;
+ }
+
+ for (i = 0; i < AT_DEFAULT_INPUTMBOX_SIZE; i++) {
+ if (0 == atpayload[i].used) {
+ atpayload[i].used = 1;
+ return atpayload[i].buf;
+ }
+ }
+
+ return NULL;
+#endif
+}
+
+static void free_payload(void *payload)
+{
+ if (payload) {
+#ifdef PLATFORM_HAS_DYNMEM
+ HAL_Free(payload);
+#else
+ memset(payload, 0, sizeof(at_payload_t));
+#endif
+ }
+}
+
+static at_netbuf_t *alloc_atnetbuf(void)
+{
+#ifdef PLATFORM_HAS_DYNMEM
+ return HAL_Malloc(sizeof(at_netbuf_t));
+#else
+ int i;
+
+ for (i = 0; i < AT_DEFAULT_INPUTMBOX_SIZE; i++) {
+ if (NULL == atnetbuf[i].payload) {
+ return &atnetbuf[i];
+ }
+ }
+
+ return NULL;
+#endif
+}
+
+static void free_atnetbuf(at_netbuf_t *netbuf)
+{
+ if (netbuf) {
+#ifdef PLATFORM_HAS_DYNMEM
+ HAL_Free(netbuf);
+#else
+ memset(netbuf, 0, sizeof(at_netbuf_t));
+#endif
+ }
+}
+
+static struct at_conn *get_conn(int c)
+{
+ struct at_conn *conn = NULL;
+
+ if ((c < 0) || (c >= AT_CONN_NUM)) {
+ AT_DEBUG("get_conn(%d): invalid", c);
+ return NULL;
+ }
+
+ conn = &atconnects[c];
+
+ if (UNUSED_ATCONN == conn->connid) {
+ AT_DEBUG("get_conn(%d): not active", c);
+ return NULL;
+ }
+
+ return conn;
+}
+
+static int at_newconn(void)
+{
+ int i;
+
+ for (i = 0; i < AT_CONN_NUM; i++) {
+ if (atconnects[i].connid == UNUSED_ATCONN) {
+ if (at_mbox_new(&atconnects[i].recvmbox,
+ AT_DEFAULT_INPUTMBOX_SIZE,
+ atconnects[i].recvbuf) != 0) {
+ AT_ERROR("fai to new input mail box size %d \n", AT_DEFAULT_INPUTMBOX_SIZE);
+ return -1;
+ }
+
+ atconnects[i].type = NETCONN_INVALID;
+ atconnects[i].state = NETCONN_NONE;
+ atconnects[i].lastdata = NULL;
+ atconnects[i].lastoffset = 0;
+ atconnects[i].connid = i;
+ atconnects[i].send_timeout_ms = AT_DEFAULT_SEND_TIMEOUT_MS;
+ atconnects[i].recv_timeout_ms = AT_DEFAULT_RECV_TIMEOUT_MS;
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+static void at_drainconn(struct at_conn *conn)
+{
+ at_netbuf_t *mem;
+
+ if (NULL == conn)
+ return;
+
+ if (at_mbox_valid(&conn->recvmbox)) {
+ while (at_mbox_tryfetch(&conn->recvmbox, (void **)(&mem)) != AT_MBOX_EMPTY) {
+ if (mem != NULL) {
+ if (mem->payload) {
+ free_payload(mem->payload);
+ mem->payload = NULL;
+ }
+ free_atnetbuf(mem);
+ }
+ }
+ at_mbox_free(&conn->recvmbox);
+ at_mbox_set_invalid(&conn->recvmbox);
+ }
+
+ return;
+}
+
+static int at_freeconn(struct at_conn *conn)
+{
+ at_netbuf_t *buf = NULL;
+
+ if (NULL == conn)
+ return -1;
+
+ if (NULL != conn->lastdata) {
+ buf = (at_netbuf_t *) conn->lastdata;
+
+ if (buf->payload) {
+ free_payload(buf->payload);
+ buf->payload = NULL;
+ }
+
+ free_atnetbuf(buf);
+ }
+
+ conn->lastdata = NULL;
+ conn->lastoffset = 0;
+
+ at_drainconn(conn);
+
+ conn->type = NETCONN_INVALID;
+ conn->state = NETCONN_NONE;
+ conn->connid = UNUSED_ATCONN;
+
+ return 0;
+}
+
+static int at_conn_fetch(struct at_conn *conn, at_netbuf_t **new_buf)
+{
+ uint32_t ret = 0;
+ void *buf = NULL;
+
+ if (NULL == conn || NULL == new_buf) {
+ return -1;
+ }
+
+ if (!at_mbox_valid(&conn->recvmbox)) {
+ AT_ERROR("conn %d invalid recvmbox\n", conn->connid);
+ return -1;
+ }
+
+ ret = at_mbox_fetch(&conn->recvmbox, &buf, conn->recv_timeout_ms);
+ if (ret == AT_MBOX_TIMEOUT) {
+ AT_ERROR("at conn %d fetch data time out %d\n", conn->connid, conn->recv_timeout_ms);
+ return -1;
+ }
+
+ *new_buf = buf;
+ return 0;
+}
+
+/****************************public interface*********************/
+int at_conn_input(struct at_conn_input *param)
+{
+ int s = -1;
+ void *data = NULL;
+ int len = 0;
+ char *remote_ip = NULL;
+ uint16_t remote_port = 0;
+ struct at_conn *conn = NULL;
+ at_netbuf_t *buf = NULL;
+
+ if (NULL == param) {
+ AT_ERROR("at conn input param NULL\n");
+ return -1;
+ }
+
+ s = param->fd;
+ data = param->data;
+ len = param->datalen;
+ remote_ip = param->remote_ip;
+ remote_port = param->remote_port;
+
+ if (NULL == data || 0 == len) {
+ AT_ERROR("low level invalid input data\n");
+ return -1;
+ }
+
+ if (remote_ip != NULL &&
+ strlen(remote_ip) > IPV4_STR_MAX_LEN) {
+ AT_ERROR("invalid ip string");
+ return -1;
+ }
+
+ conn = get_conn(s);
+ if (NULL == conn) {
+ AT_ERROR("conn %d doesn't exist\n", s);
+ return -1;
+ }
+
+ if (conn->connid < 0) {
+ AT_ERROR("conn %d invalid connid\n", s);
+ return -1;
+ }
+
+ if (!at_mbox_valid(&conn->recvmbox)) {
+ AT_ERROR("invalid conn to input packet\n");
+ return -1;
+ }
+
+ buf = alloc_atnetbuf();
+ if (NULL == buf) {
+ AT_ERROR("alloc at net buf size %d fail\n", sizeof(at_netbuf_t));
+ return -1;
+ }
+ memset(buf, 0, sizeof(*buf));
+
+ buf->payload = alloc_payload(len);
+ if (NULL == buf->payload) {
+ free_atnetbuf(buf);
+ AT_ERROR("alloc payload size %d fail\n", len);
+ return -1;
+ }
+
+ memcpy(buf->payload, data, len);
+ buf->len = len;
+ buf->remote_port = remote_port;
+ if (remote_ip)
+ memcpy(buf->remote_ip, remote_ip, IPV4_STR_MAX_LEN);
+
+ if (at_mbox_trypost(&conn->recvmbox, buf) != 0) {
+ free_payload(buf->payload);
+ buf->payload = NULL;
+ free_atnetbuf(buf);
+ AT_ERROR("try post recv packet fail\n");
+ return -1;
+ }
+
+ return 0;
+ }
+
+int at_conn_init(void)
+{
+ static int at_conn_init_done = 0;
+ int i;
+
+ if (at_conn_init_done) {
+ AT_ERROR("at conn have already init done\n");
+ return 0;
+ }
+
+ for (i = 0; i < AT_CONN_NUM; i++) {
+ atconnects[i].connid = UNUSED_ATCONN;
+ }
+
+ g_atconnmutex = HAL_MutexCreate();
+ if (g_atconnmutex == NULL) {
+ AT_ERROR("failed to creat g_atconnmutex \n");
+ return -1;
+ }
+
+ if (HAL_AT_CONN_Init() != 0) {
+ AT_ERROR("at conn low level init fail\n");
+ HAL_MutexDestroy(g_atconnmutex);
+ return -1;
+ }
+
+ at_conn_init_done = 1;
+
+ return 0 ;
+}
+
+int at_conn_getaddrinfo(const char *nodename, char resultip[16])
+{
+ int namelen;
+
+ if (NULL == nodename || NULL == resultip) {
+ return -1;
+ }
+
+ namelen = strlen(nodename);
+ if (namelen > DNS_MAX_NAME_LENGTH)
+ return -1;
+
+ if (HAL_AT_CONN_DomainToIp((char *)nodename, resultip) != 0) {
+ AT_ERROR("domain to ip failed.");
+ return -1;
+ }
+
+ return 0;
+}
+
+int at_conn_setup(netconn_type_t type)
+{
+ struct at_conn *conn = NULL;
+ int connid = -1;
+
+ if (type >= NETCONN_TYPE_NUM || type <= NETCONN_INVALID) {
+ return -1;
+ }
+
+ HAL_MutexLock(g_atconnmutex);
+ if ((connid = at_newconn()) == -1) {
+ AT_ERROR("fai to new at conn\n");
+ HAL_MutexUnlock(g_atconnmutex);
+ return -1;
+ }
+
+ if ((conn = get_conn(connid)) == NULL) {
+ AT_ERROR("fai to get at conn\n");
+ HAL_MutexUnlock(g_atconnmutex);
+ return -1;
+ }
+
+ conn->type = type;
+ conn->state = NETCONN_NONE;
+ HAL_MutexUnlock(g_atconnmutex);
+
+ return connid;
+}
+
+int at_conn_start(int connid, char* remoteipaddr, uint16_t remoteport)
+{
+ char *ipv4anyadrr = AT_IP4_ANY_ADDR;
+ at_conn_t statconn = {0};
+ struct at_conn *conn = NULL;
+
+ HAL_MutexLock(g_atconnmutex);
+ conn = get_conn(connid);
+ if (NULL == conn) {
+ AT_ERROR("at_startconn: invalid conn\n");
+ HAL_MutexUnlock(g_atconnmutex);
+ return -1;
+ }
+
+ if (conn->state != NETCONN_NONE) {
+ AT_ERROR("at_startconn: conn %d state is %d \n", connid, conn->state);
+ HAL_MutexUnlock(g_atconnmutex);
+ return -1;
+ }
+
+ statconn.fd = connid;
+ statconn.r_port = remoteport;
+ statconn.l_port = -1;
+ statconn.addr = (char *)remoteipaddr;
+ if (NULL == statconn.addr) {
+ statconn.addr = ipv4anyadrr;
+ }
+
+ switch (conn->type) {
+ case NETCONN_TCP:
+ statconn.type = TCP_CLIENT;
+ if (HAL_AT_CONN_Start(&statconn) != 0) {
+ AT_ERROR("fail to setup tcp connect, remote is %s port is %d.\n", statconn.addr, remoteport);
+ HAL_MutexUnlock(g_atconnmutex);
+ return -1;
+ }
+ memcpy(conn->remote_ip, statconn.addr, IPV4_STR_MAX_LEN);
+ conn->remote_port = remoteport;
+ break;
+ default:
+ AT_ERROR("Unsupported at connection type.\n");
+ HAL_MutexUnlock(g_atconnmutex);
+ return -1;
+ }
+
+ /* Update at conn state */
+ conn->state = NETCONN_CONNECT;
+ HAL_MutexUnlock(g_atconnmutex);
+
+ return 0;
+}
+
+int at_conn_close(int c)
+{
+ struct at_conn *conn = NULL;
+ int err;
+
+ AT_DEBUG("at_close(%d)\r\n", c);
+
+ conn = get_conn(c);
+ if (NULL == conn) {
+ return -1;
+ }
+
+ if (conn->state == NETCONN_CONNECT) {
+ if (HAL_AT_CONN_Close(c, -1) != 0) {
+ AT_DEBUG("HAL_AT_close failed.");
+ }
+ }
+
+ HAL_MutexLock(g_atconnmutex);
+ err = at_freeconn(conn);
+ HAL_MutexUnlock(g_atconnmutex);
+ if (err != 0) {
+ AT_ERROR("at_freeconn failed in %s.", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int at_conn_recvbufempty(int c)
+{
+ struct at_conn *conn = NULL;
+
+ conn = get_conn(c);
+ if (NULL == conn) {
+ AT_ERROR("at_recvbufempty cannot get socket %d\n", c);
+ return -1;
+ }
+
+ /* remain data */
+ if (conn->lastdata)
+ return 0;
+
+ if (!at_mbox_valid(&conn->recvmbox)) {
+ AT_ERROR("conn %d invalid recvmbox\n", c);
+ return -1;
+ }
+
+ return at_mbox_empty(&conn->recvmbox);
+}
+
+int at_conn_send(int c, const void *data, uint32_t size)
+{
+ struct at_conn *conn = NULL;
+
+ if (NULL == data || size == 0 || size > AT_MAX_PAYLOAD_SIZE) {
+ AT_ERROR("at_conn_send fail to send, size %d\n", size);
+ return -1;
+ }
+
+ conn = get_conn(c);
+ if (NULL == conn) {
+ AT_ERROR("at_conn_send fail to get conn %d\n", c);
+ return -1;
+ }
+
+ if (conn->type == NETCONN_TCP) {
+ if (conn->state == NETCONN_NONE) {
+ AT_ERROR("at_conn_send connect %d state %d\n", c, conn->state);
+ return -1;
+ }
+ }
+
+ if (HAL_AT_CONN_Send(c, (uint8_t *)data, size, NULL, -1, conn->send_timeout_ms)) {
+ AT_ERROR("c %d fail to send do nothing for now\n", c);
+ return -1;
+ }
+
+ return size;
+}
+
+int at_conn_recv(int c, void *mem, uint32_t len)
+{
+ struct at_conn *conn = NULL;
+ at_netbuf_t *buf = NULL;
+ int off = 0;
+ uint16_t buflen = 0;
+ uint16_t copylen = 0;
+ int err = 0;
+ uint8_t done = 0;
+
+ if (NULL == mem || 0 == len) {
+ return -1;
+ }
+
+ conn = get_conn(c);
+ if (NULL == conn) {
+ AT_ERROR("at_conn_recv fail to get conn %d\n", c);
+ return -1;
+ }
+
+ do {
+ if (conn->lastdata) {
+ buf = conn->lastdata;
+ } else {
+ err = at_conn_fetch(conn, &buf);
+ if (err != 0 || buf == NULL || buf->payload == NULL) {
+ if (off > 0) {
+ return off;
+ } else {
+ return -1;
+ }
+ }
+
+ conn->lastdata = buf;
+ }
+
+ buflen = buf->len;
+ AT_DEBUG("at_conn_recv: buflen=%u, len=%u, off=%d, lastoffset=%u\n",
+ buflen, len, off, conn->lastoffset);
+
+ buflen -= conn->lastoffset;
+ if (len > buflen) {
+ copylen = buflen;
+ } else {
+ copylen = len;
+ }
+
+ memcpy(&((uint8_t *)mem)[off], &((uint8_t *)buf->payload)[conn->lastoffset], copylen);
+ off += copylen;
+
+ if (NETCONN_TCP == conn->type) {
+ if (len < copylen) {
+ AT_ERROR("invalid copylen %d, len = %d\n", copylen, len);
+ return -1;
+ }
+
+ len -= copylen;
+ if (len <= 0) {
+ done = 1;
+ }
+ } else {
+ done = 1;
+ }
+
+ if ((NETCONN_TCP == conn->type) && (buflen > copylen)) {
+ conn->lastdata = buf;
+ conn->lastoffset += copylen;
+ } else {
+ conn->lastdata = NULL;
+ conn->lastoffset = 0;
+ free_payload(buf->payload);
+ buf->payload = NULL;
+ free_atnetbuf(buf);
+ buf = NULL;
+ }
+ } while (!done);
+
+ return off;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mgmt.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mgmt.h
new file mode 100644
index 00000000..7131fefb
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_conn_mgmt.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2015-2019 Alibaba Group Holding Limited
+ */
+
+#ifndef _AT_CONN_MGMT_H_
+#define _AT_CONN_MGMT_H_
+
+typedef enum netconn_type {
+ NETCONN_INVALID = 0,
+ /** TCP IPv4 */
+ NETCONN_TCP,
+ NETCONN_TYPE_NUM
+} netconn_type_t;
+
+/**
+ * at connection module initialization
+ *
+ * @param null
+ *
+ * @return 0 : on success, -1: error
+ */
+int at_conn_init(void);
+
+/**
+ * receive data from an at connection
+ *
+ * @param[in]: connection id;
+ * @param[out]: pointer to output buffer
+ * @param[in]: expect length
+ *
+ * @return 0 : on success, -1: error
+ */
+int at_conn_recv(int connid, void *mem, uint32_t len);
+
+/**
+ * query ip from domain address
+ *
+ * @param[in]: domain address
+ * @param[out]: query result
+ *
+ * @return 0 : on success, -1: error
+ */
+int at_conn_getaddrinfo(const char *nodename, char resultip[16]);
+
+
+/**
+ * setup an new at connection
+ *
+ * @param[in]: connection type only tcp support
+ *
+ * @return 0 : on success, -1: error
+ */
+int at_conn_setup(netconn_type_t type);
+
+/**
+ * start an at connection
+ *
+ * @param[in]: connection id
+ * @param[in]: remote ip address
+ * @param[in]: remote port
+ *
+ * @return 0 : on success, -1: error
+ */
+int at_conn_start(int connid, char* remoteipaddr, uint16_t remoteport);
+
+/**
+ * close an at connection
+ *
+ * @param[in] connection id
+ *
+ * @return 0 : on success, -1: error
+ */
+int at_conn_close(int connid);
+
+/**
+ * check whether recvbuf empty
+ *
+ * @param[in] connection id
+ *
+ * @return 0 : on success, -1: error
+ */
+int at_conn_recvbufempty(int connid);
+
+/**
+ * send data through an at connection
+ *
+ * @param[in] connection id
+ * @param[in] send buf pointer
+ *
+ * @return 0 : on success, -1: error
+ */
+int at_conn_send(int connid, const void *data, uint32_t size);
+
+#endif
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_mqtt.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_mqtt.c
new file mode 100644
index 00000000..9b1c7eed
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_mqtt.c
@@ -0,0 +1,1269 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include
+#include
+#include
+
+#include "mqtt_api.h"
+#include "mqtt_wrapper.h"
+#include "at_mqtt.h"
+#include "at_wrapper.h"
+
+#ifndef PLATFORM_HAS_OS
+ #ifdef AT_PARSER_ENABLED
+ #include "at_parser.h"
+ #endif
+#endif
+
+#define MAL_TIMEOUT_FOREVER -1
+#define MAL_TIMEOUT_DEFAULT 3000
+#define MAL_MC_PACKET_ID_MAX (65535)
+#define MAL_MC_DEFAULT_BUFFER_NUM 1
+#ifdef PLATFORM_HAS_DYNMEM
+ #define MAL_MC_MAX_BUFFER_NUM 14
+#else
+ #define MAL_MC_MAX_BUFFER_NUM 1
+#endif
+#define MAL_MC_MAX_TOPIC_LEN CONFIG_MQTT_TOPIC_MAXLEN
+#define MAL_MC_MAX_MSG_LEN CONFIG_MQTT_MESSAGE_MAXLEN
+
+#define MAL_MC_DEFAULT_TIMEOUT (8000)
+
+#define mal_emerg(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define mal_crit(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define mal_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define mal_warning(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define mal_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define mal_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+
+#ifdef PLATFORM_HAS_DYNMEM
+ #ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+ #define mal_malloc(size) LITE_malloc(size, MEM_MAGIC, "mqtt")
+ #define mal_free(ptr) LITE_free(ptr)
+ #else
+ #define mal_malloc(size) HAL_Malloc(size)
+ #define mal_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+ #endif /* INFRA_MEM_STATS */
+#else
+ #define IOTX_MC_CLIENT_MAX_COUNT 1
+#endif
+
+typedef struct at_mqtt_msg_buff_s {
+ uint8_t write_index;
+ uint8_t read_index;
+ uint8_t last_write_index;
+ uint8_t valid_flag[MAL_MC_MAX_BUFFER_NUM];
+ uint8_t buffer_num;
+ char *topic[MAL_MC_MAX_BUFFER_NUM];
+ char *msg_data[MAL_MC_MAX_BUFFER_NUM];
+ void *buffer_mutex;
+} at_mqtt_msg_buff_t;
+static at_mqtt_msg_buff_t g_at_mqtt_buff_mgr;
+#ifdef PLATFORM_HAS_DYNMEM
+static char g_at_mqtt_topic[MAL_MC_DEFAULT_BUFFER_NUM][MAL_MC_MAX_TOPIC_LEN];
+static char g_at_mqtt_msg_data[MAL_MC_DEFAULT_BUFFER_NUM][MAL_MC_MAX_MSG_LEN];
+#else
+static char g_at_mqtt_topic[MAL_MC_MAX_BUFFER_NUM][MAL_MC_MAX_TOPIC_LEN];
+static char g_at_mqtt_msg_data[MAL_MC_MAX_BUFFER_NUM][MAL_MC_MAX_MSG_LEN];
+iotx_mc_client_t g_iotx_mc_client[IOTX_MC_CLIENT_MAX_COUNT] = {0};
+#endif
+
+static iotx_mc_state_t mal_mc_get_client_state(iotx_mc_client_t *pClient);
+static void mal_mc_set_client_state(iotx_mc_client_t *pClient, iotx_mc_state_t newState);
+
+typedef struct {
+ uint32_t time;
+} mal_time_t;
+
+static uint32_t mal_time_is_expired(mal_time_t *timer)
+{
+ uint32_t cur_time;
+
+ if (!timer) {
+ return 1;
+ }
+
+ cur_time = HAL_UptimeMs();
+ /*
+ * WARNING: Do NOT change the following code until you know exactly what it do!
+ *
+ * check whether it reach destination time or not.
+ */
+ if ((cur_time - timer->time) < (UINT32_MAX / 2)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static uint32_t mal_time_left(mal_time_t *end)
+{
+ uint32_t now, res;
+
+ if (!end) {
+ return 0;
+ }
+
+ if (mal_time_is_expired(end)) {
+ return 0;
+ }
+
+ now = HAL_UptimeMs();
+ res = end->time - now;
+ return res;
+}
+
+static void mal_time_init(mal_time_t *timer)
+{
+ if (!timer) {
+ return;
+ }
+
+ timer->time = 0;
+}
+
+static void mal_time_countdown_ms(mal_time_t *timer, uint32_t millisecond)
+{
+ if (!timer) {
+ return;
+ }
+
+ timer->time = HAL_UptimeMs() + millisecond;
+}
+
+static int mal_mc_check_rule(char *iterm, iotx_mc_topic_type_t type)
+{
+ int i = 0;
+ int len = 0;
+
+ if (NULL == iterm) {
+ mal_err("iterm is NULL");
+ return FAIL_RETURN;
+ }
+
+ len = strlen(iterm);
+
+ for (i = 0; i < len; i++) {
+ if (TOPIC_FILTER_TYPE == type) {
+ if ('+' == iterm[i] || '#' == iterm[i]) {
+ if (1 != len) {
+ mal_err("the character # and + is error");
+ return FAIL_RETURN;
+ }
+ }
+ } else {
+ if ('+' == iterm[i] || '#' == iterm[i]) {
+ mal_err("has character # and + is error");
+ return FAIL_RETURN;
+ }
+ }
+
+ if (iterm[i] < 32 || iterm[i] >= 127) {
+ return FAIL_RETURN;
+ }
+ }
+ return SUCCESS_RETURN;
+}
+
+/* check whether the topic is matched or not */
+static char mal_mc_is_topic_matched(char *topicFilter, const char *topicName)
+{
+ char *curf;
+ const char *curn;
+ const char *curn_end;
+
+ if (!topicFilter || !topicName) {
+ return 0;
+ }
+
+ curf = topicFilter;
+ curn = topicName;
+ curn_end = curn + strlen(topicName);
+
+ while (*curf && curn < curn_end) {
+ if (*curn == '/' && *curf != '/') {
+ break;
+ }
+
+ if (*curf != '+' && *curf != '#' && *curf != *curn) {
+ break;
+ }
+
+ if (*curf == '+') {
+ /* skip until we meet the next separator, or end of string */
+ const char *nextpos = curn + 1;
+ while (nextpos < curn_end && *nextpos != '/') {
+ nextpos = ++curn + 1;
+ }
+ } else if (*curf == '#') {
+ curn = curn_end - 1; /* skip until end of string */
+ }
+ curf++;
+ curn++;
+ }
+
+ return (curn == curn_end) && (*curf == '\0');
+}
+
+/* Check topic name */
+/* 0, topic name is valid; NOT 0, topic name is invalid */
+static int mal_mc_check_topic(const char *topicName, iotx_mc_topic_type_t type)
+{
+ int mask = 0;
+ char *delim = "/";
+ char *iterm = NULL;
+ char topicString[MAL_MC_MAX_TOPIC_LEN];
+ if (NULL == topicName || '/' != topicName[0]) {
+ return FAIL_RETURN;
+ }
+
+ if (strlen(topicName) > MAL_MC_MAX_TOPIC_LEN) {
+ mal_err("len of topicName(%d) exceeds 64", strlen(topicName));
+ return FAIL_RETURN;
+ }
+
+ memset(topicString, 0x0, MAL_MC_MAX_TOPIC_LEN);
+ strncpy(topicString, topicName, MAL_MC_MAX_TOPIC_LEN - 1);
+
+ iterm = strtok(topicString, delim);
+
+ if (SUCCESS_RETURN != mal_mc_check_rule(iterm, type)) {
+ mal_err("run iotx_check_rule error");
+ return FAIL_RETURN;
+ }
+
+ for (;;) {
+ iterm = strtok(NULL, delim);
+
+ if (iterm == NULL) {
+ break;
+ }
+
+ /* The character '#' is not in the last */
+ if (1 == mask) {
+ mal_err("the character # is error");
+ return FAIL_RETURN;
+ }
+
+ if (SUCCESS_RETURN != mal_mc_check_rule(iterm, type)) {
+ mal_err("run iotx_check_rule error");
+ return FAIL_RETURN;
+ }
+
+ if (iterm[0] == '#') {
+ mask = 1;
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+#ifndef PLATFORM_HAS_DYNMEM
+static int mal_mc_check_handle_is_identical_ex(iotx_mc_topic_handle_t *messageHandlers1,
+ iotx_mc_topic_handle_t *messageHandler2)
+{
+ int topicNameLen = 0;
+ if (!messageHandlers1 || !messageHandler2) {
+ return 1;
+ }
+ if (!(messageHandlers1->topic_filter) || !(messageHandler2->topic_filter)) {
+ return 1;
+ }
+ topicNameLen = strlen(messageHandlers1->topic_filter);
+ if (topicNameLen != strlen(messageHandler2->topic_filter)) {
+ return 1;
+ }
+ if (0 != strncmp(messageHandlers1->topic_filter, messageHandler2->topic_filter, topicNameLen)) {
+ return 1;
+ }
+ return 0;
+}
+static int mal_mc_check_handle_is_identical(iotx_mc_topic_handle_t *messageHandlers1,
+ iotx_mc_topic_handle_t *messageHandler2)
+{
+ if (mal_mc_check_handle_is_identical_ex(messageHandlers1, messageHandler2) != 0) {
+ return 1;
+ }
+ if (messageHandlers1->handle.h_fp != messageHandler2->handle.h_fp) {
+ return 1;
+ }
+ if (messageHandlers1->handle.pcontext != messageHandler2->handle.pcontext) {
+ return 1;
+ }
+ return 0;
+}
+#endif /* PLATFORM_HAS_DYNMEM */
+/* MQTT send connect packet */
+static int MALMQTTConnect(iotx_mc_client_t *pClient)
+{
+ char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
+ char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
+ char device_secret[IOTX_DEVICE_SECRET_LEN + 1] = {0};
+
+ HAL_GetProductKey(product_key);
+ HAL_GetDeviceName(device_name);
+ HAL_GetDeviceSecret(device_secret);
+
+ if (0 != HAL_AT_MQTT_Connect(product_key, device_name, device_secret)) {
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+static int MALMQTTPublish(iotx_mc_client_t *c, const char *topicName, iotx_mqtt_topic_info_pt topic_msg)
+
+{
+ if (!c || !topicName || !topic_msg) {
+ mal_err("MALMQTTPublish invalid parms\n");
+ return FAIL_RETURN;
+ }
+
+ if (0 != HAL_AT_MQTT_Publish(topicName, topic_msg->qos, topic_msg->payload,
+ topic_msg->payload_len)) {
+ mal_err("MALMQTTPublish publish failed\n");
+ return FAIL_RETURN;
+ }
+
+ return SUCCESS_RETURN;
+}
+
+#ifdef PLATFORM_HAS_DYNMEM
+static int remove_handle_from_list(iotx_mc_client_t *c, iotx_mc_topic_handle_t *h)
+{
+ iotx_mc_topic_handle_t **hp, *h1;
+ hp = &c->first_sub_handle;
+ while ((*hp) != NULL) {
+ h1 = *hp;
+ if (h1 == h) {
+ *hp = h->next;
+ } else {
+ hp = &h1->next;
+ }
+ }
+
+ return 0;
+}
+#endif
+
+/* MQTT send subscribe packet */
+static int MALMQTTSubscribe(iotx_mc_client_t *c, const char *topicFilter, iotx_mqtt_qos_t qos, unsigned int msgId,
+ iotx_mqtt_event_handle_func_fpt messageHandler, void *pcontext, int timeout_ms)
+{
+ int status;
+ iotx_mc_topic_handle_t *h = NULL;
+#ifndef PLATFORM_HAS_DYNMEM
+ int idx = 0;
+ int dup = 0;
+#endif
+
+ if (!c || !topicFilter || !messageHandler) {
+ return FAIL_RETURN;
+ }
+#ifdef PLATFORM_HAS_DYNMEM
+ h = mal_malloc(sizeof(iotx_mc_topic_handle_t));
+ if (h == NULL) {
+ mal_err("maloc failed!");
+ return FAIL_RETURN;
+ }
+#else
+ for (idx = 0; idx < IOTX_MC_SUBHANDLE_LIST_MAX_LEN; idx++) {
+ if (c->list_sub_handle[idx].used == 0) {
+ h = &c->list_sub_handle[idx];
+ memset(h, 0, sizeof(iotx_mc_topic_handle_t));
+ c->list_sub_handle[idx].used = 1;
+ break;
+ }
+ }
+
+ if (h == NULL) {
+ mal_err("sub handle list is too short!");
+ return FAIL_RETURN;
+ }
+#endif
+#ifdef PLATFORM_HAS_DYNMEM
+ memset(h, 0, sizeof(iotx_mc_topic_handle_t));
+
+ h->topic_filter = mal_malloc(strlen(topicFilter) + 1);
+ if (NULL == h->topic_filter) {
+ mal_free(h);
+ return FAIL_RETURN;
+ }
+#else
+ if (strlen(topicFilter) >= CONFIG_MQTT_TOPIC_MAXLEN) {
+ mal_err("sub topic length is too large!");
+ memset(h, 0, sizeof(iotx_mc_topic_handle_t));
+ return FAIL_RETURN;
+ }
+#endif
+ memcpy((char *)h->topic_filter, topicFilter, strlen(topicFilter) + 1);
+
+ h->handle.h_fp = messageHandler;
+ h->handle.pcontext = pcontext;
+ h->topic_type = TOPIC_NAME_TYPE;
+
+ HAL_MutexLock(c->lock_generic);
+#ifdef PLATFORM_HAS_DYNMEM
+ h->next = c->first_sub_handle;
+ c->first_sub_handle = h;
+#else
+ for (idx = 0; idx < IOTX_MC_SUBHANDLE_LIST_MAX_LEN; idx++) {
+ if (&c->list_sub_handle[idx] != h &&
+ 0 == mal_mc_check_handle_is_identical(&c->list_sub_handle[idx], h)) {
+ mal_warning("dup sub,topic = %s", topicFilter);
+ dup = 1;
+ }
+ }
+ if (dup == 1) {
+ memset(h, 0, sizeof(iotx_mc_topic_handle_t));
+ }
+#endif
+ HAL_MutexUnlock(c->lock_generic);
+ if (HAL_AT_MQTT_Subscribe(topicFilter, qos, &msgId, &status, timeout_ms) != 0) {
+ return FAIL_RETURN;
+ }
+ return SUCCESS_RETURN;
+}
+
+
+/* MQTT send unsubscribe packet */
+static int MALMQTTUnsubscribe(iotx_mc_client_t *c, const char *topicFilter, unsigned int msgId)
+{
+ int status;
+ int ret;
+#ifdef PLATFORM_HAS_DYNMEM
+ iotx_mc_topic_handle_t *h;
+#else
+ int idx;
+#endif
+
+ ret = HAL_AT_MQTT_Unsubscribe(topicFilter, &msgId, &status);
+ if (ret != 0) {
+ return -1;
+ }
+
+#ifdef PLATFORM_HAS_DYNMEM
+ for (h = c->first_sub_handle; h != NULL; h = h->next) {
+ if (((strlen(topicFilter) == strlen(h->topic_filter))
+ && (strcmp(topicFilter, (char *)h->topic_filter) == 0))
+ || (mal_mc_is_topic_matched((char *)h->topic_filter, topicFilter))) {
+ remove_handle_from_list(c, h);
+ }
+ }
+#else
+ for (idx = 0; idx < IOTX_MC_SUBHANDLE_LIST_MAX_LEN; idx++) {
+ if ((c->list_sub_handle[idx].used == 1) &&
+ (((strlen(topicFilter) == strlen(c->list_sub_handle[idx].topic_filter))
+ && (strcmp(topicFilter, (char *)c->list_sub_handle[idx].topic_filter) == 0)) ||
+ mal_mc_is_topic_matched((char *)c->list_sub_handle[idx].topic_filter, topicFilter))) {
+ mal_debug("topic be matched");
+ memset(&c->list_sub_handle[idx], 0, sizeof(iotx_mc_topic_handle_t));
+ }
+ }
+#endif
+
+ return 0;
+}
+
+/* MQTT send disconnect packet */
+static int MALMQTTDisconnect(iotx_mc_client_t *c)
+{
+ return HAL_AT_MQTT_Disconnect();
+}
+
+/* get next packet-id */
+static int mal_mc_get_next_packetid(iotx_mc_client_t *c)
+{
+ unsigned int id = 0;
+
+ if (!c) {
+ return FAIL_RETURN;
+ }
+
+ HAL_MutexLock(c->lock_generic);
+ c->packet_id = (c->packet_id == MAL_MC_PACKET_ID_MAX) ? 1 : c->packet_id + 1;
+ id = c->packet_id;
+ HAL_MutexUnlock(c->lock_generic);
+
+ return id;
+}
+
+/* handle PUBLISH packet received from remote MQTT broker */
+static int iotx_mc_handle_recv_PUBLISH(iotx_mc_client_t *c, char *topic, char *msg)
+{
+ iotx_mqtt_topic_info_t topic_msg = {0};
+ int flag_matched = 0;
+ static uint64_t time_prev = 0;
+ uint64_t time_curr = 0;
+ /* flowControl for specific topic */
+ char *filterStr = "{\"method\":\"thing.service.property.set\"";
+ int filterLen = strlen(filterStr);
+#ifdef PLATFORM_HAS_DYNMEM
+ iotx_mc_topic_handle_t *h, *msg_handle;
+#else
+ iotx_mc_topic_handle_t *msg_handle;
+ int idx;
+#endif
+
+ if (!c || !topic || !msg) {
+ return FAIL_RETURN;
+ }
+ mal_debug("recv pub topic=%s msg=%s", topic, msg);
+
+ if (0 == memcmp(msg, filterStr, filterLen)) {
+ /* mal_debug("iotx_mc_handle_recv_PUBLISH match filterstring"); */
+ time_curr = HAL_UptimeMs();
+ if (time_curr < time_prev) {
+ time_curr = time_prev;
+ }
+ if ((time_curr - time_prev) <= (uint64_t)50) {
+ mal_debug("pub over threshould");
+ return SUCCESS_RETURN;
+ } else {
+ time_prev = time_curr;
+ }
+ }
+
+ /* we have to find the right message handler - indexed by topic */
+ HAL_MutexLock(c->lock_generic);
+#ifdef PLATFORM_HAS_DYNMEM
+ for (h = c->first_sub_handle; h != NULL; h = h->next) {
+ if (((strlen(topic) == strlen(h->topic_filter))
+ && (strcmp(topic, (char *)h->topic_filter) == 0))
+ || (mal_mc_is_topic_matched((char *)h->topic_filter, topic))) {
+ msg_handle = h;
+#else
+ for (idx = 0; idx < IOTX_MC_SUBHANDLE_LIST_MAX_LEN; idx++) {
+ if ((c->list_sub_handle[idx].used == 1) &&
+ (((strlen(topic) == strlen(c->list_sub_handle[idx].topic_filter))
+ && (strcmp(topic, (char *)c->list_sub_handle[idx].topic_filter) == 0))
+ || (mal_mc_is_topic_matched((char *)c->list_sub_handle[idx].topic_filter, topic)))) {
+ msg_handle = &c->list_sub_handle[idx];
+#endif
+ mal_debug("pub topic is matched");
+
+ HAL_MutexUnlock(c->lock_generic);
+
+ if (NULL != msg_handle->handle.h_fp) {
+ iotx_mqtt_event_msg_t event_msg;
+ topic_msg.payload = msg;
+ topic_msg.payload_len = strlen(msg);
+ topic_msg.ptopic = topic;
+ topic_msg.topic_len = strlen(topic);
+ event_msg.event_type = IOTX_MQTT_EVENT_PUBLISH_RECEIVED;
+ event_msg.msg = &topic_msg;
+ msg_handle->handle.h_fp(msg_handle->handle.pcontext, c, &event_msg);
+ flag_matched = 1;
+ }
+
+ HAL_MutexLock(c->lock_generic);
+ }
+ }
+
+ HAL_MutexUnlock(c->lock_generic);
+
+ if (0 == flag_matched) {
+ mal_debug("NO matching any topic, call default handle function");
+
+ if (NULL != c->handle_event.h_fp) {
+ iotx_mqtt_event_msg_t event_msg;
+
+ topic_msg.payload = msg;
+ topic_msg.payload_len = strlen(msg);
+ topic_msg.ptopic = topic;
+ topic_msg.topic_len = strlen(topic);
+ event_msg.event_type = IOTX_MQTT_EVENT_PUBLISH_RECEIVED;
+ event_msg.msg = &topic_msg;
+
+ c->handle_event.h_fp(c->handle_event.pcontext, c, &event_msg);
+ }
+ }
+
+ return SUCCESS_RETURN;
+}
+
+/* MQTT cycle to handle packet from remote broker */
+static int mal_mc_cycle(iotx_mc_client_t *c, mal_time_t *timer)
+{
+ int rc = SUCCESS_RETURN;
+ char *msg = NULL;
+ char *topic = NULL;
+ uint8_t read_index = 0;
+
+ if (!c) {
+ return FAIL_RETURN;
+ }
+
+ if (HAL_AT_MQTT_State() == IOTX_MC_STATE_CONNECTED) {
+ mal_mc_set_client_state(c, IOTX_MC_STATE_CONNECTED);
+ }
+
+ if (mal_mc_get_client_state(c) != IOTX_MC_STATE_CONNECTED) {
+ mal_err("mal state = %d error", mal_mc_get_client_state(c));
+#ifndef PLATFORM_HAS_OS
+#ifdef AT_PARSER_ENABLED
+ at_yield(NULL, 0, NULL, 100);
+#endif
+#endif
+ return MQTT_STATE_ERROR;
+ }
+
+ if (HAL_AT_MQTT_State() != IOTX_MC_STATE_CONNECTED) {
+ mal_err("hal mal state = %d error", HAL_AT_MQTT_State());
+ mal_mc_set_client_state(c, IOTX_MC_STATE_DISCONNECTED);
+#ifndef PLATFORM_HAS_OS
+#ifdef AT_PARSER_ENABLED
+ at_yield(NULL, 0, NULL, 100);
+#endif
+#endif
+ return MQTT_NETWORK_ERROR;
+ }
+
+ /* read the buf, see what work is due */
+ HAL_MutexLock(g_at_mqtt_buff_mgr.buffer_mutex);
+ read_index = g_at_mqtt_buff_mgr.read_index;
+
+ if (g_at_mqtt_buff_mgr.valid_flag[read_index] == 0) {
+ HAL_MutexUnlock(g_at_mqtt_buff_mgr.buffer_mutex);
+ return FAIL_RETURN;
+ }
+
+ topic = g_at_mqtt_buff_mgr.topic[read_index];
+ msg = g_at_mqtt_buff_mgr.msg_data[read_index];
+
+ rc = iotx_mc_handle_recv_PUBLISH(c, topic, msg);
+ if (SUCCESS_RETURN != rc) {
+ mal_err("recvPublishProc error,result = %d", rc);
+ }
+
+ memset(g_at_mqtt_buff_mgr.topic[read_index], 0, MAL_MC_MAX_TOPIC_LEN);
+ memset(g_at_mqtt_buff_mgr.msg_data[read_index], 0, MAL_MC_MAX_MSG_LEN);
+ g_at_mqtt_buff_mgr.valid_flag[read_index] = 0;
+
+ read_index++;
+ if (read_index >= g_at_mqtt_buff_mgr.buffer_num) {
+ read_index = 0;
+ }
+
+ g_at_mqtt_buff_mgr.read_index = read_index;
+ HAL_MutexUnlock(g_at_mqtt_buff_mgr.buffer_mutex);
+
+ return rc;
+}
+
+/* get state of MQTT client */
+static iotx_mc_state_t mal_mc_get_client_state(iotx_mc_client_t *pClient)
+{
+ iotx_mc_state_t state;
+ HAL_MutexLock(pClient->lock_generic);
+ state = pClient->client_state;
+ HAL_MutexUnlock(pClient->lock_generic);
+
+ return state;
+}
+
+/* set state of MQTT client */
+static void mal_mc_set_client_state(iotx_mc_client_t *pClient, iotx_mc_state_t newState)
+{
+
+ HAL_MutexLock(pClient->lock_generic);
+ pClient->client_state = newState;
+ HAL_MutexUnlock(pClient->lock_generic);
+}
+
+static int mal_mc_recv_buf_init()
+{
+ int i;
+ g_at_mqtt_buff_mgr.read_index = 0;
+ g_at_mqtt_buff_mgr.write_index = 0;
+ g_at_mqtt_buff_mgr.last_write_index = 0;
+ g_at_mqtt_buff_mgr.buffer_num = MAL_MC_DEFAULT_BUFFER_NUM;
+
+ for (i = 0; i < MAL_MC_MAX_BUFFER_NUM; i++) {
+ g_at_mqtt_buff_mgr.valid_flag[i] = 0;
+#ifdef PLATFORM_HAS_DYNMEM
+ if (i < MAL_MC_DEFAULT_BUFFER_NUM) {
+ g_at_mqtt_buff_mgr.topic[i] = g_at_mqtt_topic[i];
+ g_at_mqtt_buff_mgr.msg_data[i] = g_at_mqtt_msg_data[i];
+ memset(g_at_mqtt_buff_mgr.topic[i], 0, MAL_MC_MAX_TOPIC_LEN);
+ memset(g_at_mqtt_buff_mgr.msg_data[i], 0, MAL_MC_MAX_MSG_LEN);
+ } else {
+ g_at_mqtt_buff_mgr.topic[i] = NULL;
+ g_at_mqtt_buff_mgr.msg_data[i] = NULL;
+ }
+#else
+ g_at_mqtt_buff_mgr.topic[i] = g_at_mqtt_topic[i];
+ g_at_mqtt_buff_mgr.msg_data[i] = g_at_mqtt_msg_data[i];
+ memset(g_at_mqtt_buff_mgr.topic[i], 0, MAL_MC_MAX_TOPIC_LEN);
+ memset(g_at_mqtt_buff_mgr.msg_data[i], 0, MAL_MC_MAX_MSG_LEN);
+#endif
+ }
+
+ if (NULL == (g_at_mqtt_buff_mgr.buffer_mutex = HAL_MutexCreate())) {
+ mal_err("create buffer mutex error");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void mal_mc_recv_buf_deinit()
+{
+ int i;
+ g_at_mqtt_buff_mgr.read_index = 0;
+ g_at_mqtt_buff_mgr.write_index = 0;
+ g_at_mqtt_buff_mgr.last_write_index = 0;
+
+#ifdef PLATFORM_HAS_DYNMEM
+ for (i = 0; i < MAL_MC_MAX_BUFFER_NUM; i++) {
+ g_at_mqtt_buff_mgr.valid_flag[i] = 0;
+ if (i < MAL_MC_DEFAULT_BUFFER_NUM) {
+ memset(g_at_mqtt_buff_mgr.topic[i], 0, MAL_MC_MAX_TOPIC_LEN);
+ memset(g_at_mqtt_buff_mgr.msg_data[i], 0, MAL_MC_MAX_MSG_LEN);
+ } else {
+ if (i < g_at_mqtt_buff_mgr.buffer_num) {
+ if (g_at_mqtt_buff_mgr.topic[i] != NULL) {
+ mal_free(g_at_mqtt_buff_mgr.topic[i]);
+ }
+ if (g_at_mqtt_buff_mgr.msg_data[i] != NULL) {
+ mal_free(g_at_mqtt_buff_mgr.msg_data[i]);
+ }
+ }
+ }
+ }
+#else
+ for (i = 0; i < g_at_mqtt_buff_mgr.buffer_num; i++) {
+ g_at_mqtt_buff_mgr.valid_flag[i] = 0;
+ memset(g_at_mqtt_buff_mgr.topic[i], 0, MAL_MC_MAX_TOPIC_LEN);
+ memset(g_at_mqtt_buff_mgr.msg_data[i], 0, MAL_MC_MAX_MSG_LEN);
+ }
+#endif
+
+ HAL_MutexDestroy(g_at_mqtt_buff_mgr.buffer_mutex);
+}
+
+static int mal_mc_wait_for_result()
+{
+#ifdef PLATFORM_HAS_OS
+ mal_time_t time;
+ int state = 0;
+ int timeout_ms = MAL_MC_DEFAULT_TIMEOUT;
+ mal_time_init(&time);
+ mal_time_countdown_ms(&time, timeout_ms);
+ do {
+ unsigned int left_t;
+ left_t = mal_time_left(&time);
+ if (left_t < 100) {
+ HAL_SleepMs(left_t);
+ } else {
+ HAL_SleepMs(100);
+ }
+
+ state = HAL_AT_MQTT_State();
+ } while (!mal_time_is_expired(&time) && (state != IOTX_MC_STATE_CONNECTED));
+
+ if (state == IOTX_MC_STATE_CONNECTED) {
+ return SUCCESS_RETURN;
+ } else {
+ return FAIL_RETURN;
+ }
+#else
+ int state = 0;
+#ifdef AT_PARSER_ENABLED
+ int timeout_ms = 1000;
+#endif
+ int count = 10;
+ while ((count > 0) && ((state = HAL_AT_MQTT_State()) != IOTX_MC_STATE_CONNECTED)) {
+#ifdef AT_PARSER_ENABLED
+ at_yield(NULL, 0, NULL, timeout_ms);
+#endif
+ count --;
+ }
+
+ if (state == IOTX_MC_STATE_CONNECTED) {
+ return SUCCESS_RETURN;
+ } else {
+ return FAIL_RETURN;
+ }
+#endif
+}
+
+static int mal_mc_disconnect(iotx_mc_client_t *pClient)
+{
+ int rc = -1;
+
+ if (NULL == pClient) {
+ return NULL_VALUE_ERROR;
+ }
+
+ if (wrapper_mqtt_check_state(pClient)) {
+ rc = MALMQTTDisconnect(pClient);
+ mal_debug("rc = MALMQTTDisconnect() = %d", rc);
+ }
+
+ mal_mc_set_client_state(pClient, IOTX_MC_STATE_INITIALIZED);
+
+ mal_info("mqtt disconnect!");
+ return SUCCESS_RETURN;
+}
+
+int at_mqtt_input(struct at_mqtt_input *param)
+{
+ char *topic;
+ uint32_t topic_len;
+ char *message;
+ uint32_t message_len;
+ uint8_t write_index;
+ char *copy_ptr;
+
+ if (NULL == param) {
+ mal_err("input param null");
+ return -1;
+ }
+
+ topic = param->topic;
+ topic_len = param->topic_len;
+ message = param->message;
+ message_len = param->msg_len;
+
+ if ((topic == NULL) || (topic_len == 0) ||
+ (message == NULL) || (message_len == 0)) {
+ mal_err("input topic or message is NULL");
+ return -1;
+ }
+
+ if ((topic_len >= MAL_MC_MAX_TOPIC_LEN) ||
+ (message_len >= MAL_MC_MAX_MSG_LEN)) {
+ mal_err("topic(%d) or message(%d) too large", topic_len, message_len);
+ return -1;
+ }
+
+ HAL_MutexLock(g_at_mqtt_buff_mgr.buffer_mutex);
+ write_index = g_at_mqtt_buff_mgr.write_index;
+
+ if ((g_at_mqtt_buff_mgr.valid_flag[write_index])
+ && (g_at_mqtt_buff_mgr.buffer_num == MAL_MC_MAX_BUFFER_NUM)) {
+ mal_err("buffer is full");
+
+ HAL_MutexUnlock(g_at_mqtt_buff_mgr.buffer_mutex);
+ return -1;
+ }
+ if (g_at_mqtt_buff_mgr.valid_flag[write_index]) {
+ int last_write_index = write_index;
+ g_at_mqtt_buff_mgr.last_write_index = last_write_index;
+ write_index = g_at_mqtt_buff_mgr.buffer_num;
+ mal_err("increase buffer to %d", g_at_mqtt_buff_mgr.buffer_num);
+#ifdef PLATFORM_HAS_DYNMEM
+ g_at_mqtt_buff_mgr.topic[write_index] = mal_malloc(MAL_MC_MAX_TOPIC_LEN);
+ if (g_at_mqtt_buff_mgr.topic[write_index] == NULL) {
+ mal_err("increase buffer failed, drop it");
+ return -1;
+ }
+ g_at_mqtt_buff_mgr.msg_data[write_index] = mal_malloc(MAL_MC_MAX_MSG_LEN);
+ if (g_at_mqtt_buff_mgr.msg_data[write_index] == NULL) {
+ mal_err("increase buffer failed, drop it");
+ mal_free(g_at_mqtt_buff_mgr.topic[write_index]);
+ return -1;
+ }
+ g_at_mqtt_buff_mgr.buffer_num ++;
+#else
+ g_at_mqtt_buff_mgr.buffer_num ++;
+ g_at_mqtt_buff_mgr.topic[g_at_mqtt_buff_mgr.buffer_num] = g_at_mqtt_topic[g_at_mqtt_buff_mgr.buffer_num];
+ g_at_mqtt_buff_mgr.msg_data[g_at_mqtt_buff_mgr.buffer_num] = g_at_mqtt_msg_data[g_at_mqtt_buff_mgr.buffer_num];
+ memset(g_at_mqtt_buff_mgr.topic[g_at_mqtt_buff_mgr.buffer_num], 0, MAL_MC_MAX_TOPIC_LEN);
+ memset(g_at_mqtt_buff_mgr.msg_data[g_at_mqtt_buff_mgr.buffer_num], 0, MAL_MC_MAX_MSG_LEN);
+#endif
+ } else {
+ g_at_mqtt_buff_mgr.last_write_index = 0;
+ }
+
+ copy_ptr = g_at_mqtt_buff_mgr.topic[write_index];
+ memcpy(copy_ptr, topic, topic_len);
+ copy_ptr = g_at_mqtt_buff_mgr.msg_data[write_index];
+ memcpy(copy_ptr, message, message_len);
+
+ g_at_mqtt_buff_mgr.valid_flag[write_index] = 1;
+ write_index++;
+
+ if (write_index >= g_at_mqtt_buff_mgr.buffer_num) {
+ write_index = 0;
+ }
+
+ if (g_at_mqtt_buff_mgr.last_write_index != 0) {
+ g_at_mqtt_buff_mgr.write_index = g_at_mqtt_buff_mgr.last_write_index;
+ } else {
+ g_at_mqtt_buff_mgr.write_index = write_index;
+ }
+ HAL_MutexUnlock(g_at_mqtt_buff_mgr.buffer_mutex);
+
+ return 0;
+}
+
+/* Initialize MQTT client */
+static int mal_mc_init(iotx_mc_client_t *pClient, iotx_mqtt_param_t *pInitParams)
+{
+ int rc = FAIL_RETURN;
+ iotx_mc_state_t mc_state = IOTX_MC_STATE_INVALID;
+
+ if (pClient == NULL || pInitParams == NULL ||
+ pInitParams->write_buf_size == 0 || pInitParams->read_buf_size == 0) {
+ return NULL_VALUE_ERROR;
+ }
+
+ memset(pClient, 0, sizeof(iotx_mc_client_t));
+
+ if (HAL_AT_MQTT_Init(pInitParams) != 0) {
+ mal_err("low layer init failed");
+ return FAIL_RETURN;
+ }
+
+ pClient->lock_generic = HAL_MutexCreate();
+ if (!pClient->lock_generic) {
+ return FAIL_RETURN;
+ }
+
+ pClient->lock_yield = HAL_MutexCreate();
+ if (!pClient->lock_yield) {
+ goto RETURN;
+ }
+
+ pClient->handle_event.h_fp = pInitParams->handle_event.h_fp;
+ pClient->handle_event.pcontext = pInitParams->handle_event.pcontext;
+
+ mal_mc_recv_buf_init();
+
+ mc_state = IOTX_MC_STATE_INITIALIZED;
+ rc = SUCCESS_RETURN;
+
+RETURN:
+ mal_mc_set_client_state(pClient, mc_state);
+
+ if (rc != SUCCESS_RETURN) {
+ if (pClient->lock_generic) {
+ HAL_MutexDestroy(pClient->lock_generic);
+ pClient->lock_generic = NULL;
+ }
+
+ if (pClient->lock_yield) {
+ HAL_MutexDestroy(pClient->lock_yield);
+ pClient->lock_yield = NULL;
+ }
+ }
+
+ return rc;
+}
+
+/************************ Public Interface ************************/
+void *wrapper_mqtt_init(iotx_mqtt_param_t *mqtt_params)
+{
+ int err;
+ iotx_mc_client_t *pclient;
+#ifndef PLATFORM_HAS_DYNMEM
+ int idx;
+#endif
+
+#ifdef PLATFORM_HAS_DYNMEM
+ pclient = (iotx_mc_client_t *)mal_malloc(sizeof(iotx_mc_client_t));
+ if (NULL == pclient) {
+ mal_err("not enough memory.");
+ if (mqtt_params != NULL) {
+ mal_free(mqtt_params);
+ }
+ return NULL;
+ }
+#else
+ for (idx = 0; idx < IOTX_MC_CLIENT_MAX_COUNT; idx++) {
+ if (g_iotx_mc_client[idx].used == 0) {
+ g_iotx_mc_client[idx].used = 1;
+ pclient = &g_iotx_mc_client[idx];
+ break;
+ }
+ }
+
+ if (NULL == pclient) {
+ mal_err("wrapper_mqtt_init IOTX_MC_CLIENT_MAX_COUNT too short: %d", IOTX_MC_CLIENT_MAX_COUNT);
+ return NULL;
+ }
+#endif
+ err = mal_mc_init(pclient, mqtt_params);
+ if (SUCCESS_RETURN != err) {
+ mal_err("mal_mc_init failed");
+#ifdef PLATFORM_HAS_DYNMEM
+ mal_free(pclient);
+#else
+ memset(pclient, 0, sizeof(iotx_mc_client_t));
+#endif
+ return NULL;
+ }
+
+ return pclient;
+}
+
+int wrapper_mqtt_connect(void *client)
+{
+ int rc = FAIL_RETURN;
+
+ if (NULL == client) {
+ return NULL_VALUE_ERROR;
+ }
+
+ rc = MALMQTTConnect((iotx_mc_client_t *)client);
+ if (rc != SUCCESS_RETURN) {
+ mal_err("send connect packet failed");
+ return rc;
+ }
+ if (SUCCESS_RETURN != mal_mc_wait_for_result()) {
+ mal_err("current state is not connected");
+ return FAIL_RETURN;
+ }
+
+ mal_mc_set_client_state((iotx_mc_client_t *)client, IOTX_MC_STATE_CONNECTED);
+
+ mal_info("mqtt connect success!");
+ return SUCCESS_RETURN;
+}
+
+int wrapper_mqtt_yield(void *client, int timeout_ms)
+{
+ int rc = SUCCESS_RETURN;
+ mal_time_t time;
+ unsigned int left_t;
+
+ iotx_mc_client_t *pClient = (iotx_mc_client_t *)client;
+
+ if (pClient == NULL) {
+ return NULL_VALUE_ERROR;
+ }
+
+ if (timeout_ms < 0) {
+ mal_err("Invalid argument, timeout_ms = %d", timeout_ms);
+ return -1;
+ }
+ if (timeout_ms == 0) {
+ timeout_ms = 10;
+ }
+
+ mal_time_init(&time);
+ mal_time_countdown_ms(&time, timeout_ms);
+
+ do {
+ if (SUCCESS_RETURN != rc) {
+ unsigned int left_t = mal_time_left(&time);
+ /*mal_info("error occur or no data");*/
+ if (left_t < 20) {
+ HAL_SleepMs(left_t);
+ } else {
+ HAL_SleepMs(20);
+ }
+ }
+ HAL_MutexLock(pClient->lock_yield);
+
+ /* acquire package in cycle, such as PUBLISH */
+ rc = mal_mc_cycle(pClient, &time);
+ HAL_MutexUnlock(pClient->lock_yield);
+
+ left_t = mal_time_left(&time);
+ if (left_t < 10) {
+ HAL_SleepMs(left_t);
+ } else {
+ HAL_SleepMs(10);
+ }
+ } while (!mal_time_is_expired(&time));
+
+ return 0;
+}
+
+int wrapper_mqtt_check_state(void *client)
+{
+ if (!client) {
+ return 0;
+ }
+
+ if (mal_mc_get_client_state((iotx_mc_client_t *)client) == IOTX_MC_STATE_CONNECTED) {
+ return 1;
+ }
+
+ return 0;
+}
+
+int wrapper_mqtt_subscribe_sync(void *client,
+ const char *topicFilter,
+ iotx_mqtt_qos_t qos,
+ iotx_mqtt_event_handle_func_fpt topic_handle_func,
+ void *pcontext,
+ int timeout_ms)
+{
+ int rc = FAIL_RETURN;
+ unsigned int msgId;
+ iotx_mc_client_t *c = (iotx_mc_client_t *)client;
+
+ if (NULL == client || NULL == topicFilter || strlen(topicFilter) == 0 || !topic_handle_func) {
+ mal_err(" paras error");
+ return NULL_VALUE_ERROR;
+ }
+
+ c = (iotx_mc_client_t *)client;
+ msgId = mal_mc_get_next_packetid(c);
+
+ if (!wrapper_mqtt_check_state(c)) {
+ mal_err("mqtt client state is error,state = %d", mal_mc_get_client_state(c));
+ return MQTT_STATE_ERROR;
+ }
+
+ if (0 != mal_mc_check_topic(topicFilter, TOPIC_FILTER_TYPE)) {
+ mal_err("topic format is error,topicFilter = %s", topicFilter);
+ return MQTT_TOPIC_FORMAT_ERROR;
+ }
+
+ mal_debug("PERFORM subscribe to '%s' (msgId=%d)", topicFilter, msgId);
+ rc = MALMQTTSubscribe(c, topicFilter, qos, msgId, topic_handle_func, pcontext, timeout_ms);
+ if (rc != SUCCESS_RETURN) {
+ if (rc == MQTT_NETWORK_ERROR) {
+ mal_mc_set_client_state(c, IOTX_MC_STATE_DISCONNECTED);
+ }
+
+ mal_err("run MQTTSubscribe error, rc = %d", rc);
+ return rc;
+ }
+
+ mal_info("mqtt subscribe packet sent,topic = %s!", topicFilter);
+ return msgId;
+}
+
+int wrapper_mqtt_subscribe(void *client,
+ const char *topic_filter,
+ iotx_mqtt_qos_t qos,
+ iotx_mqtt_event_handle_func_fpt topic_handle_func,
+ void *pcontext)
+{
+ return wrapper_mqtt_subscribe_sync(client, topic_filter, qos, topic_handle_func, pcontext, MAL_TIMEOUT_DEFAULT);
+}
+
+int wrapper_mqtt_unsubscribe(void *client, const char *topicFilter)
+{
+ int rc = FAIL_RETURN;
+ unsigned int msgId;
+ iotx_mc_client_t *c;
+
+ if (NULL == client || NULL == topicFilter) {
+ return NULL_VALUE_ERROR;
+ }
+
+ c = (iotx_mc_client_t *)client;
+ msgId = mal_mc_get_next_packetid(c);
+
+ if (0 != mal_mc_check_topic(topicFilter, TOPIC_FILTER_TYPE)) {
+ mal_err("topic format is error,topicFilter = %s", topicFilter);
+ return MQTT_TOPIC_FORMAT_ERROR;
+ }
+
+ if (!wrapper_mqtt_check_state(c)) {
+ mal_err("mqtt client state is error,state = %d", mal_mc_get_client_state(c));
+ return MQTT_STATE_ERROR;
+ }
+
+ rc = MALMQTTUnsubscribe(c, topicFilter, msgId);
+ if (rc != SUCCESS_RETURN) {
+ if (rc == MQTT_NETWORK_ERROR) { /* send the subscribe packet */
+ mal_mc_set_client_state(c, IOTX_MC_STATE_DISCONNECTED);
+ }
+
+ mal_err("run MALMQTTUnsubscribe error!");
+ return rc;
+ }
+
+ mal_info("mqtt unsubscribe packet sent,topic = %s!", topicFilter);
+ return (int)msgId;
+}
+
+int wrapper_mqtt_publish(void *client, const char *topicName, iotx_mqtt_topic_info_pt topic_msg)
+{
+ uint16_t msg_id = 0;
+ int rc = FAIL_RETURN;
+ iotx_mc_client_t *c = (iotx_mc_client_t *)client;
+
+ if (NULL == c || NULL == topicName || NULL == topic_msg || NULL == topic_msg->payload) {
+ return NULL_VALUE_ERROR;
+ }
+
+ if (0 != mal_mc_check_topic(topicName, TOPIC_NAME_TYPE)) {
+ mal_err("topic format is error,topicFilter = %s", topicName);
+ return MQTT_TOPIC_FORMAT_ERROR;
+ }
+
+ if (!wrapper_mqtt_check_state(c)) {
+ mal_err("mqtt client state is error,state = %d", mal_mc_get_client_state(c));
+ return MQTT_STATE_ERROR;
+ }
+
+ if (topic_msg->qos == IOTX_MQTT_QOS1 || topic_msg->qos == IOTX_MQTT_QOS2) {
+ msg_id = mal_mc_get_next_packetid(c);
+ topic_msg->packet_id = msg_id;
+ }
+
+ if (topic_msg->qos == IOTX_MQTT_QOS2) {
+ mal_err("MALMQTTPublish return error,MQTT_QOS2 is now not supported.");
+ return MQTT_PUBLISH_QOS_ERROR;
+ }
+
+ rc = MALMQTTPublish(c, topicName, topic_msg);
+ if (rc != SUCCESS_RETURN) { /* send the subscribe packet */
+ if (rc == MQTT_NETWORK_ERROR) {
+ mal_mc_set_client_state(c, IOTX_MC_STATE_DISCONNECTED);
+ }
+ mal_err("MALMQTTPublish is error, rc = %d", rc);
+ return rc;
+ }
+
+ return (int)msg_id;
+}
+
+int wrapper_mqtt_release(void **client)
+{
+ iotx_mc_client_t *pClient;
+
+ if (NULL == client) {
+ return NULL_VALUE_ERROR;
+ }
+
+ pClient = (iotx_mc_client_t *)*client;
+ if (NULL == pClient) {
+ return NULL_VALUE_ERROR;
+ }
+
+ /* iotx_delete_thread(pClient); */
+ mal_mc_disconnect(pClient);
+ mal_mc_set_client_state(pClient, IOTX_MC_STATE_INVALID);
+#ifdef PLATFORM_HAS_DYNMEM
+ if (pClient->first_sub_handle != NULL) {
+ iotx_mc_topic_handle_t *handler = pClient->first_sub_handle;
+ iotx_mc_topic_handle_t *next_handler = pClient->first_sub_handle;
+ while (handler) {
+ next_handler = handler->next;
+ if (handler->topic_filter != NULL) {
+ mal_free(handler->topic_filter);
+ handler->topic_filter = NULL;
+ }
+ mal_free(handler);
+ handler = next_handler;
+ }
+ }
+#else
+ memset(pClient->list_sub_handle, 0, sizeof(iotx_mc_topic_handle_t) * IOTX_MC_SUBHANDLE_LIST_MAX_LEN);
+#endif
+ HAL_MutexDestroy(pClient->lock_generic);
+ HAL_MutexDestroy(pClient->lock_yield);
+
+ mal_mc_recv_buf_deinit();
+#ifdef PLATFORM_HAS_DYNMEM
+ mal_free(pClient);
+ *client = NULL;
+#else
+ memset(pClient, 0, sizeof(iotx_mc_client_t) * IOTX_MC_CLIENT_MAX_COUNT);
+#endif
+ mal_info("mqtt release!");
+ return SUCCESS_RETURN;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_mqtt.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_mqtt.h
new file mode 100644
index 00000000..4eea8338
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_mqtt.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef _AT_MQTT_H_
+#define _AT_MQTT_H_
+
+#ifndef PLATFORM_HAS_DYNMEM
+ #ifndef IOTX_MC_SUBHANDLE_LIST_MAX_LEN
+ #define IOTX_MC_SUBHANDLE_LIST_MAX_LEN (5)
+ #endif
+
+ #ifndef CONFIG_MQTT_TOPIC_MAXLEN
+ #define CONFIG_MQTT_TOPIC_MAXLEN (128)
+ #endif
+#endif
+
+/* State of MQTT client */
+typedef enum {
+ IOTX_MC_STATE_INVALID = 0, /* MQTT in invalid state */
+ IOTX_MC_STATE_INITIALIZED = 1, /* MQTT in initializing state */
+ IOTX_MC_STATE_CONNECTED = 2, /* MQTT in connected state */
+ IOTX_MC_STATE_DISCONNECTED = 3, /* MQTT in disconnected state */
+ IOTX_MC_STATE_DISCONNECTED_RECONNECTING = 4, /* MQTT in reconnecting state */
+} iotx_mc_state_t;
+
+typedef enum {
+ TOPIC_NAME_TYPE = 0,
+ TOPIC_FILTER_TYPE
+} iotx_mc_topic_type_t;
+
+/* Handle structure of subscribed topic */
+typedef struct iotx_mc_topic_handle_s {
+#ifdef PLATFORM_HAS_DYNMEM
+ const char *topic_filter;
+#else
+ const char topic_filter[CONFIG_MQTT_TOPIC_MAXLEN];
+ int used;
+#endif
+ iotx_mc_topic_type_t topic_type;
+ iotx_mqtt_event_handle_t handle;
+ struct iotx_mc_topic_handle_s *next;
+} iotx_mc_topic_handle_t;
+
+typedef struct Client {
+ uint32_t packet_id; /* packet id */
+ void *lock_generic; /* generic lock */
+ void *lock_yield;
+#ifdef PLATFORM_HAS_DYNMEM
+ iotx_mc_topic_handle_t *first_sub_handle; /* list of subscribe handle */
+#else
+ iotx_mc_topic_handle_t list_sub_handle[IOTX_MC_SUBHANDLE_LIST_MAX_LEN];
+#endif
+ void *lock_list_sub; /* lock for list of sub/unsub */
+ iotx_mc_state_t client_state; /* state of MQTT client */
+ iotx_mqtt_event_handle_t handle_event; /* event handle */
+#ifndef PLATFORM_HAS_DYNMEM
+ int used;
+#endif
+} iotx_mc_client_t, *iotx_mc_client_pt;
+
+#endif
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_parser.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_parser.c
new file mode 100644
index 00000000..ec6e1e2e
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_parser.c
@@ -0,0 +1,948 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#include
+#include
+
+#include "infra_types.h"
+#include "at_wrapper.h"
+#include "at_parser.h"
+
+#define OOB_MAX 5
+
+typedef struct oob_s
+{
+ char * prefix;
+ char * postfix;
+ char * oobinputdata;
+ uint32_t reallen;
+ uint32_t maxlen;
+ at_recv_cb cb;
+ void * arg;
+} oob_t;
+
+/*
+ * --> | slist | --> | slist | --> NULL
+ * --------- ---------
+ * | smhr | | smpr |
+ * --------- ---------
+ * | rsp | | rsp |
+ * --------- ---------
+ */
+#if !AT_SINGLE_TASK
+#include "infra_list.h"
+typedef struct at_task_s
+{
+ slist_t next;
+ void * smpr;
+ char * command;
+ char * rsp;
+ char * rsp_prefix;
+ char * rsp_success_postfix;
+ char * rsp_fail_postfix;
+ uint32_t rsp_prefix_len;
+ uint32_t rsp_success_postfix_len;
+ uint32_t rsp_fail_postfix_len;
+ uint32_t rsp_offset;
+ uint32_t rsp_len;
+} at_task_t;
+#endif
+
+/**
+ * Parser structure for parsing AT commands
+ */
+typedef struct
+{
+ uart_dev_t *_pstuart;
+ int _timeout;
+ char * _default_recv_prefix;
+ char * _default_recv_success_postfix;
+ char * _default_recv_fail_postfix;
+ char * _send_delimiter;
+ int _recv_prefix_len;
+ int _recv_success_postfix_len;
+ int _recv_fail_postfix_len;
+ int _send_delim_size;
+ oob_t _oobs[OOB_MAX];
+ int _oobs_num;
+ void * at_uart_recv_mutex;
+ void * at_uart_send_mutex;
+ void * task_mutex;
+#if !AT_SINGLE_TASK
+ slist_t task_l;
+#endif
+} at_parser_t;
+
+#define TASK_DEFAULT_WAIT_TIME 5000
+
+#ifndef AT_WORKER_STACK_SIZE
+#define AT_WORKER_STACK_SIZE 1024
+#endif
+
+#ifndef AT_UART_TIMEOUT_MS
+#define AT_UART_TIMEOUT_MS 1000
+#endif
+
+#ifndef AT_CMD_DATA_INTERVAL_MS
+#define AT_CMD_DATA_INTERVAL_MS 0
+#endif
+
+#ifdef AT_DEBUG_MODE
+#define atpsr_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define atpsr_warning(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define atpsr_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#define atpsr_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
+#else
+#define atpsr_err(...)
+#define atpsr_warning(...)
+#define atpsr_info(...)
+#define atpsr_debug(...)
+#endif
+
+static uint8_t inited = 0;
+static uart_dev_t at_uart;
+
+static at_parser_t at;
+
+#if !AT_SINGLE_TASK
+static void* at_worker(void *arg);
+#endif
+
+#ifndef PLATFORM_HAS_DYNMEM
+#if !AT_SINGLE_TASK
+static at_task_t g_at_task;
+#endif
+#endif
+
+static void at_uart_configure(uart_dev_t *u)
+{
+ u->port = AT_UART_PORT;
+ u->config.baud_rate = AT_UART_BAUDRATE;
+ u->config.data_width = AT_UART_DATA_WIDTH;
+ u->config.parity = AT_UART_PARITY;
+ u->config.stop_bits = AT_UART_STOP_BITS;
+ u->config.flow_control = AT_UART_FLOW_CONTROL;
+ u->config.mode = AT_UART_MODE;
+}
+
+static int at_init_uart()
+{
+ at_uart_configure(&at_uart);
+
+ if (HAL_AT_Uart_Init(&at_uart) != 0) {
+ return -1;
+ }
+
+ at._pstuart = &at_uart;
+
+ return 0;
+}
+
+static void at_set_timeout(int timeout)
+{
+ at._timeout = timeout;
+}
+
+static void at_set_recv_delimiter(const char *recv_prefix,
+ const char *recv_success_postfix,
+ const char *recv_fail_postfix)
+{
+ at._default_recv_prefix = (char *)recv_prefix;
+ at._default_recv_success_postfix = (char *)recv_success_postfix;
+ at._default_recv_fail_postfix = (char *)recv_fail_postfix;
+ at._recv_prefix_len = strlen(recv_prefix);
+ at._recv_success_postfix_len = strlen(recv_success_postfix);
+ at._recv_fail_postfix_len = strlen(recv_fail_postfix);
+}
+
+static void at_set_send_delimiter(const char *delimiter)
+{
+ at._send_delimiter = (char *)delimiter;
+ at._send_delim_size = strlen(delimiter);
+}
+
+static int at_init_task_mutex()
+{
+ at.task_mutex = HAL_MutexCreate();
+ if (NULL == at.task_mutex) {
+ atpsr_err("Creating task mutex failed\r\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void at_deinit_task_mutex()
+{
+ if (at.task_mutex) {
+ HAL_MutexDestroy(at.task_mutex);
+ }
+ return;
+}
+
+static int at_init_uart_recv_mutex()
+{
+ at.at_uart_recv_mutex = HAL_MutexCreate();
+ if (NULL == at.at_uart_recv_mutex) {
+ atpsr_err("Creating at_uart_recv_mutex failed\r\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void at_deinit_uart_recv_mutex()
+{
+ if (at.at_uart_recv_mutex) {
+ HAL_MutexDestroy(at.at_uart_recv_mutex);
+ }
+ return;
+}
+
+static int at_worker_uart_send_mutex_init()
+{
+ at.at_uart_send_mutex = HAL_MutexCreate();
+ if (NULL == at.at_uart_send_mutex) {
+ atpsr_err("Creating at worker sem failed\r\n");
+ return -1;
+ }
+ return 0;
+}
+
+#if !AT_SINGLE_TASK
+static void at_worker_uart_send_mutex_deinit()
+{
+ if (at.at_uart_send_mutex) {
+ HAL_MutexDestroy(at.at_uart_send_mutex);
+ }
+}
+#endif
+
+int at_parser_init(void)
+{
+ char *recv_prefix = AT_RECV_PREFIX;
+ char *recv_success_postfix = AT_RECV_SUCCESS_POSTFIX;
+ char *recv_fail_postfix = AT_RECV_FAIL_POSTFIX;
+ char *send_delimiter = AT_SEND_DELIMITER;
+ int timeout = AT_UART_TIMEOUT_MS;
+#if !AT_SINGLE_TASK
+ void *task;
+ int stack_used;
+ hal_os_thread_param_t task_parms = {0};
+#endif
+
+ if (inited == 1) {
+ atpsr_info("have already inited ,it will init again\r\n");
+ return -1;
+ }
+
+ memset(&at, 0, sizeof(at_parser_t));
+
+ if (at_init_uart() != 0) {
+ atpsr_err("at uart init fail \r\n");
+ return -1;
+ }
+
+ memset(at._oobs, 0, sizeof(oob_t) * OOB_MAX);
+
+ at_set_timeout(timeout);
+ at_set_recv_delimiter(recv_prefix, recv_success_postfix, recv_fail_postfix);
+ at_set_send_delimiter(send_delimiter);
+
+ if (at_init_uart_recv_mutex() != 0) {
+ atpsr_err("at_uart_recv_mutex init fail \r\n");
+ return -1;
+ }
+
+ if (at_init_task_mutex() != 0) {
+ at_deinit_uart_recv_mutex();
+ atpsr_err("at mutex init fail \r\n");
+ return -1;
+ }
+
+ if (at_worker_uart_send_mutex_init() != 0) {
+ at_deinit_uart_recv_mutex();
+ at_deinit_task_mutex();
+ atpsr_err("fail to creat at worker sem\r\n");
+ }
+
+#if AT_SINGLE_TASK
+ inited = true;
+#else
+ slist_init(&at.task_l);
+
+ task_parms.priority = os_thread_priority_normal;
+ task_parms.stack_size = AT_WORKER_STACK_SIZE;
+ task_parms.name = "at_worker";
+ if (HAL_ThreadCreate(&task, at_worker, NULL, &task_parms, &stack_used) != 0) {
+ at_deinit_uart_recv_mutex();
+ at_deinit_task_mutex();
+ at_worker_uart_send_mutex_deinit();
+ atpsr_err("fail to creat at task\r\n");
+ return -1;
+ }
+#endif
+
+ return 0;
+}
+
+static int at_sendto_lower(uart_dev_t *uart, void *data, uint32_t size,
+ uint32_t timeout, bool ackreq)
+{
+ int ret = -1;
+
+ (void) ackreq;
+ ret = HAL_AT_Uart_Send(uart, data, size, timeout);
+
+ return ret;
+}
+
+static int at_recvfrom_lower(uart_dev_t *uart, void *data, uint32_t expect_size,
+ uint32_t *recv_size, uint32_t timeout)
+{
+ int ret = -1;
+
+ ret = HAL_AT_Uart_Recv(uart, data, expect_size, recv_size, timeout);
+
+ return ret;
+}
+
+#if AT_SINGLE_TASK
+int at_send_wait_reply(const char *cmd, int cmdlen, bool delimiter,
+ const char *data, int datalen,
+ char *replybuf, int bufsize,
+ const atcmd_config_t *atcmdconfig)
+{
+ int intval_ms = AT_CMD_DATA_INTERVAL_MS;
+
+ if (at_send_no_reply(cmd, cmdlen, delimiter) < 0) {
+ return -1;
+ }
+
+ if (data && datalen) {
+ if (intval_ms > 0)
+ HAL_SleepMs(intval_ms);
+
+ if (at_send_no_reply(data, datalen, false) < 0) {
+ return -1;
+ }
+ }
+
+ if (at_yield(replybuf, bufsize, atcmdconfig, at._timeout) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+#else
+static int at_worker_task_add(at_task_t *tsk)
+{
+ if (NULL == tsk) {
+ atpsr_err("invalid input %s \r\n", __func__);
+ return -1;
+ }
+
+ HAL_MutexLock(at.task_mutex);
+ slist_add_tail(&tsk->next, &at.task_l);
+ HAL_MutexUnlock(at.task_mutex);
+
+ return 0;
+}
+
+static int at_worker_task_del(at_task_t *tsk)
+{
+ if (NULL == tsk) {
+ atpsr_err("invalid input %s \r\n", __func__);
+ return -1;
+ }
+
+ HAL_MutexLock(at.task_mutex);
+ slist_del(&tsk->next, &at.task_l);
+ HAL_MutexUnlock(at.task_mutex);
+ if (tsk->smpr) {
+ HAL_SemaphoreDestroy(tsk->smpr);
+ }
+ if (tsk) {
+#ifdef PLATFORM_HAS_DYNMEM
+ HAL_Free(tsk);
+#endif
+ }
+
+ return 0;
+}
+
+int at_send_wait_reply(const char *cmd, int cmdlen, bool delimiter,
+ const char *data, int datalen,
+ char *replybuf, int bufsize,
+ const atcmd_config_t *atcmdconfig)
+{
+ int ret = 0;
+ int intval_ms = AT_CMD_DATA_INTERVAL_MS;
+ at_task_t *tsk;
+
+ if (inited == 0) {
+ atpsr_err("at have not init yet\r\n");
+ return -1;
+ }
+
+ if (NULL == cmd || cmdlen <= 0) {
+ atpsr_err("%s invalid input \r\n", __FUNCTION__);
+ return -1;
+ }
+
+ if (NULL == replybuf || 0 == bufsize) {
+ atpsr_err("%s invalid input \r\n", __FUNCTION__);
+ return -1;
+ }
+
+ HAL_MutexLock(at.at_uart_send_mutex);
+#ifdef PLATFORM_HAS_DYNMEM
+ tsk = (at_task_t *)HAL_Malloc(sizeof(at_task_t));
+#else
+ tsk = &g_at_task;
+#endif
+ if (NULL == tsk) {
+ atpsr_err("tsk buffer allocating failed");
+ HAL_MutexUnlock(at.at_uart_send_mutex);
+ return -1;
+ }
+ memset(tsk, 0, sizeof(at_task_t));
+
+ tsk->smpr = HAL_SemaphoreCreate();
+ if (NULL == tsk->smpr) {
+ atpsr_err("failed to allocate semaphore");
+ goto end;
+ }
+
+ if (atcmdconfig) {
+ if (NULL != atcmdconfig->reply_prefix) {
+ tsk->rsp_prefix = atcmdconfig->reply_prefix;
+ tsk->rsp_prefix_len = strlen(atcmdconfig->reply_prefix);
+ }
+
+ if (NULL != atcmdconfig->reply_success_postfix) {
+ tsk->rsp_success_postfix = atcmdconfig->reply_success_postfix;
+ tsk->rsp_success_postfix_len = strlen(atcmdconfig->reply_success_postfix);
+ }
+
+ if (NULL != atcmdconfig->reply_fail_postfix) {
+ tsk->rsp_fail_postfix = atcmdconfig->reply_fail_postfix;
+ tsk->rsp_fail_postfix_len = strlen(atcmdconfig->reply_fail_postfix);
+ }
+ }
+
+ tsk->command = (char *)cmd;
+ tsk->rsp = replybuf;
+ tsk->rsp_len = bufsize;
+
+ at_worker_task_add(tsk);
+
+ if ((ret = at_sendto_lower(at._pstuart, (void *)cmd, cmdlen,
+ at._timeout, true)) != 0) {
+ atpsr_err("uart send command failed");
+ goto end;
+ }
+
+ if (delimiter) {
+ if ((ret = at_sendto_lower(at._pstuart, (void *)at._send_delimiter,
+ strlen(at._send_delimiter), at._timeout, false)) != 0) {
+ atpsr_err("uart send delimiter failed");
+ goto end;
+ }
+ }
+
+ if (data && datalen > 0) {
+ if (intval_ms > 0)
+ HAL_SleepMs(intval_ms);
+
+ if ((ret = at_sendto_lower(at._pstuart, (void *)data, datalen, at._timeout, true)) != 0) {
+ atpsr_err("uart send delimiter failed");
+ goto end;
+ }
+ }
+
+ if ((ret = HAL_SemaphoreWait(tsk->smpr, TASK_DEFAULT_WAIT_TIME)) != 0) {
+ atpsr_err("sem_wait failed");
+ goto end;
+ }
+
+end:
+ at_worker_task_del(tsk);
+ HAL_MutexUnlock(at.at_uart_send_mutex);
+ return ret;
+}
+#endif
+
+int at_send_no_reply(const char *data, int datalen, bool delimiter)
+{
+ int ret = 0;
+
+ if (inited == 0) {
+ atpsr_err("at have not init yet\r\n");
+ return -1;
+ }
+
+ if (NULL == data || datalen <= 0) {
+ atpsr_err("invalid input \r\n");
+ return -1;
+ }
+
+ HAL_MutexLock(at.at_uart_send_mutex);
+ if ((ret = at_sendto_lower(at._pstuart, (void *)data,
+ datalen, at._timeout, true)) != 0) {
+ atpsr_err("uart send raw content (%s) failed", data);
+ HAL_MutexUnlock(at.at_uart_send_mutex);
+ return -1;
+ }
+
+ if (delimiter) {
+ if ((ret = at_sendto_lower(at._pstuart, (void *)at._send_delimiter,
+ strlen(at._send_delimiter), at._timeout, false)) != 0) {
+ atpsr_err("uart send delimiter failed");
+ HAL_MutexUnlock(at.at_uart_send_mutex);
+ return -1;
+ }
+ }
+ HAL_MutexUnlock(at.at_uart_send_mutex);
+
+ return ret;
+}
+
+static int at_getc(char *c, int timeout_ms)
+{
+ int ret = 0;
+ char data;
+ uint32_t recv_size = 0;
+
+ if (NULL == c) {
+ return -1;
+ }
+
+ if (inited == 0) {
+ atpsr_err("at have not init yet\r\n");
+ return -1;
+ }
+
+ HAL_MutexLock(at.at_uart_recv_mutex);
+ ret = at_recvfrom_lower(at._pstuart, (void *)&data, 1, &recv_size, timeout_ms);
+ HAL_MutexUnlock(at.at_uart_recv_mutex);
+
+ if (ret != 0) {
+#ifdef WORKAROUND_DEVELOPERBOARD_DMA_UART
+ if (ret == 1) {
+ HAL_UART_Deinit(at._pstuart);
+ at_init_uart();
+ }
+#endif
+ return -1;
+ }
+
+ if (recv_size == 1) {
+ *c = data;
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+int at_read(char *outbuf, int readsize)
+{
+ int ret = 0;
+ uint32_t recv_size, total_read = 0;
+
+ if (inited == 0) {
+ atpsr_err("at have not init yet\r\n");
+ return -1;
+ }
+
+ HAL_MutexLock(at.at_uart_recv_mutex);
+ while (total_read < readsize) {
+ ret = at_recvfrom_lower(at._pstuart, (void *)(outbuf + total_read),
+ readsize - total_read, &recv_size, at._timeout);
+ if (ret != 0) {
+ atpsr_err("at_read failed on uart_recv.");
+ break;
+ }
+
+ if (recv_size <= 0) {
+ continue;
+ }
+ total_read += recv_size;
+ if (total_read >= readsize) {
+ break;
+ }
+ }
+ HAL_MutexUnlock(at.at_uart_recv_mutex);
+
+ if (ret != 0) {
+ return -1;
+ }
+
+ return total_read;
+}
+
+#define RECV_BUFFER_SIZE 512
+static char at_rx_buf[RECV_BUFFER_SIZE];
+int at_register_callback(const char *prefix, const char *postfix, char *recvbuf,
+ int bufsize, at_recv_cb cb, void *arg)
+{
+ oob_t *oob = NULL;
+ int i = 0;
+
+ if (bufsize < 0 || bufsize >= RECV_BUFFER_SIZE || NULL == prefix) {
+ atpsr_err("%s invalid input \r\n", __func__);
+ return -1;
+ }
+
+ if (NULL != postfix && (NULL == recvbuf || 0 == bufsize)) {
+ atpsr_err("%s invalid postfix input \r\n", __func__);
+ return -1;
+ }
+
+ if (at._oobs_num >= OOB_MAX) {
+ atpsr_err("No place left in OOB.\r\n");
+ return -1;
+ }
+
+ /*check oob exist*/
+ for (i = 0; i < at._oobs_num; i++) {
+ if (NULL != at._oobs[i].prefix &&
+ strcmp(prefix, at._oobs[i].prefix) == 0) {
+ atpsr_warning("oob prefix %s is already exist.\r\n", prefix);
+ return -1;
+ }
+ }
+
+ oob = &(at._oobs[at._oobs_num++]);
+
+ oob->oobinputdata = recvbuf;
+ if (oob->oobinputdata != NULL) {
+ memset(oob->oobinputdata, 0, bufsize);
+ }
+ oob->maxlen = bufsize;
+ oob->prefix = (char *)prefix;
+ oob->postfix = (char *)postfix;
+ oob->cb = cb;
+ oob->arg = arg;
+ oob->reallen = 0;
+
+ atpsr_debug("New oob registered (%s)", oob->prefix);
+
+ return 0;
+}
+
+static void at_scan_for_callback(char c, char *buf, int *index)
+{
+ int k;
+ oob_t *oob = NULL;
+ int offset = *index;
+
+ if (!buf || offset < 0) {
+ return;
+ }
+
+ for (k = 0; k < at._oobs_num; k++) {
+ oob = &(at._oobs[k]);
+ if (oob->reallen > 0 ||
+ (offset >= strlen(oob->prefix) &&
+ memcmp(oob->prefix, buf + offset - strlen(oob->prefix),
+ strlen(oob->prefix)) == 0)) {
+ atpsr_debug("AT! %s\r\n", oob->prefix);
+ if (oob->postfix == NULL) {
+ oob->cb(oob->arg, NULL, 0);
+ memset(buf, 0, offset);
+ offset = 0;
+ } else {
+ if (oob->reallen == 0) {
+ int len = strlen(oob->prefix) - 1;
+ len = len > 0 ? len : 0;
+ memset(oob->oobinputdata, 0, oob->maxlen);
+ memcpy(oob->oobinputdata, oob->prefix, len);
+ oob->reallen += len;
+ }
+
+ if (oob->reallen < oob->maxlen) {
+ oob->oobinputdata[oob->reallen] = c;
+ oob->reallen++;
+ if ((oob->reallen >=
+ strlen(oob->prefix) + strlen(oob->postfix)) &&
+ (strncmp(oob->oobinputdata + oob->reallen -
+ strlen(oob->postfix),
+ oob->postfix,
+ strlen(oob->postfix)) == 0)) {
+ /*recv postfix*/
+ oob->cb(oob->arg, oob->oobinputdata, oob->reallen);
+ memset(oob->oobinputdata, 0, oob->reallen);
+ oob->reallen = 0;
+ memset(buf, 0, offset);
+ offset = 0;
+ }
+ } else {
+ atpsr_err("invalid oob %s input , for oversize %s \r\n",
+ oob->prefix, oob->oobinputdata);
+ memset(oob->oobinputdata, 0, oob->reallen);
+ oob->reallen = 0;
+ memset(buf, 0, offset);
+ offset = 0;
+ }
+
+ /*oob data maybe more than buf size */
+ if (offset > (RECV_BUFFER_SIZE - 2)) {
+ memset(buf, 0, offset);
+ offset = 0;
+ }
+ }
+ continue;
+ }
+ }
+
+ *index = offset;
+ return;
+}
+
+#if AT_SINGLE_TASK
+int at_yield(char *replybuf, int bufsize, const atcmd_config_t *atcmdconfig,
+ int timeout_ms)
+{
+ int offset = 0;
+ int ret = 0;
+ int rsp_prefix_len = 0;
+ int rsp_success_postfix_len = 0;
+ int rsp_fail_postfix_len = 0;
+ int at_reply_begin = 0;
+ int at_reply_offset = 0;
+ char c = 0;
+ char *buf = NULL;
+ char *rsp_prefix = NULL;
+ char *rsp_success_postfix = NULL;
+ char *rsp_fail_postfix = NULL;
+
+ if (!inited) {
+ atpsr_err("AT parser has not inited!\r\n");
+ return -1;
+ }
+
+ if (replybuf != NULL && bufsize <= 0) {
+ atpsr_err("buffer size %d unmatched!\r\n", bufsize);
+ return -1;
+ }
+
+ buf = at_rx_buf;
+ if (NULL == buf) {
+ atpsr_err("AT worker fail to malloc ,task exist \r\n");
+ return -1;
+ }
+
+ memset(buf, 0, RECV_BUFFER_SIZE);
+
+ while (true) {
+ /* read from uart and store buf */
+ ret = at_getc(&c, timeout_ms);
+ if (ret != 0) {
+ atpsr_err("at yield timeout break loop");
+ break;
+ }
+
+ if (offset + 1 >= RECV_BUFFER_SIZE) {
+ atpsr_err("buffer full");
+ break;
+ }
+ buf[offset++] = c;
+ buf[offset] = 0;
+
+ at_scan_for_callback(c, buf, &offset);
+
+ if (replybuf == NULL || bufsize <= 0) {
+ /* if no task, continue recv */
+ continue;
+ }
+
+ if (NULL != atcmdconfig && NULL != atcmdconfig->reply_prefix) {
+ rsp_prefix = atcmdconfig->reply_prefix;
+ rsp_prefix_len = strlen(rsp_prefix);
+ } else {
+ rsp_prefix = at._default_recv_prefix;
+ rsp_prefix_len = at._recv_prefix_len;
+ }
+
+ if (NULL != atcmdconfig && NULL != atcmdconfig->reply_success_postfix) {
+ rsp_success_postfix = atcmdconfig->reply_success_postfix;
+ rsp_success_postfix_len = strlen(rsp_success_postfix);
+ } else {
+ rsp_success_postfix = at._default_recv_success_postfix;
+ rsp_success_postfix_len = at._recv_success_postfix_len;
+ }
+
+ if (NULL != atcmdconfig && NULL != atcmdconfig->reply_fail_postfix) {
+ rsp_fail_postfix = atcmdconfig->reply_fail_postfix;
+ rsp_fail_postfix_len = strlen(rsp_fail_postfix);
+ } else {
+ rsp_fail_postfix = at._default_recv_fail_postfix;
+ rsp_fail_postfix_len = at._recv_fail_postfix_len;
+ }
+
+ if (offset >= rsp_prefix_len && at_reply_begin == 0 &&
+ (strncmp(buf + offset - rsp_prefix_len, rsp_prefix,
+ rsp_prefix_len) == 0)) {
+ at_reply_begin = 1;
+ }
+
+ if (at_reply_begin == 1) {
+ if (at_reply_offset < bufsize) {
+ replybuf[at_reply_offset] = c;
+ at_reply_offset++;
+
+ if ((at_reply_offset >= rsp_success_postfix_len &&
+ strncmp(
+ replybuf + at_reply_offset - rsp_success_postfix_len,
+ rsp_success_postfix, rsp_success_postfix_len) == 0) ||
+ (at_reply_offset >= rsp_fail_postfix_len &&
+ strncmp(replybuf + at_reply_offset - rsp_fail_postfix_len,
+ rsp_fail_postfix, rsp_fail_postfix_len) == 0)) {
+ return 0;
+ }
+ } else {
+ memset(replybuf, 0, bufsize);
+ strcpy(replybuf, rsp_fail_postfix);
+ break;
+ }
+ }
+
+ }
+
+ return -1;
+}
+#else
+static void* at_worker(void *arg)
+{
+ int offset = 0;
+ int ret = 0;
+ int at_task_empty = 0;
+ int at_task_reponse_begin = 0;
+ int memcpy_size = 0;
+ int rsp_prefix_len = 0;
+ int rsp_success_postfix_len = 0;
+ int rsp_fail_postfix_len = 0;
+ char c = 0;
+ at_task_t *tsk;
+ char *buf = NULL;
+ char *rsp_prefix = NULL;
+ char *rsp_success_postfix = NULL;
+ char *rsp_fail_postfix = NULL;
+
+ atpsr_debug("at_work started.");
+
+ buf = at_rx_buf;
+ if (NULL == buf) {
+ atpsr_err("AT worker fail to malloc ,task exist \r\n");
+ return NULL;
+ }
+
+ memset(buf, 0, RECV_BUFFER_SIZE);
+ inited = 1;
+
+ while (true) {
+ ret = at_getc(&c, at._timeout);
+ if (ret != 0) {
+ continue;
+ }
+
+ if (offset + 1 >= RECV_BUFFER_SIZE) {
+ atpsr_err("Fatal error, no one is handling AT uart");
+ goto check_buffer;
+ }
+ buf[offset++] = c;
+ buf[offset] = 0;
+
+ at_scan_for_callback(c, buf, &offset);
+
+ HAL_MutexLock(at.task_mutex);
+ at_task_empty = slist_empty(&at.task_l);
+
+ if (!at_task_empty) {
+ tsk = slist_first_entry(&at.task_l, at_task_t, next);
+ }
+ HAL_MutexUnlock(at.task_mutex);
+
+ /* if no task, continue recv */
+ if (at_task_empty) {
+ atpsr_debug("No task in queue");
+ goto check_buffer;
+ }
+
+ if (NULL != tsk->rsp_prefix && 0 != tsk->rsp_prefix_len) {
+ rsp_prefix = tsk->rsp_prefix;
+ rsp_prefix_len = tsk->rsp_prefix_len;
+ } else {
+ rsp_prefix = at._default_recv_prefix;
+ rsp_prefix_len = at._recv_prefix_len;
+ }
+
+ if (NULL != tsk->rsp_success_postfix &&
+ 0 != tsk->rsp_success_postfix_len) {
+ rsp_success_postfix = tsk->rsp_success_postfix;
+ rsp_success_postfix_len = tsk->rsp_success_postfix_len;
+ } else {
+ rsp_success_postfix = at._default_recv_success_postfix;
+ rsp_success_postfix_len = at._recv_success_postfix_len;
+ }
+
+ if (NULL != tsk->rsp_fail_postfix && 0 != tsk->rsp_fail_postfix_len) {
+ rsp_fail_postfix = tsk->rsp_fail_postfix;
+ rsp_fail_postfix_len = tsk->rsp_fail_postfix_len;
+ } else {
+ rsp_fail_postfix = at._default_recv_fail_postfix;
+ rsp_fail_postfix_len = at._recv_fail_postfix_len;
+ }
+
+ if (offset >= rsp_prefix_len && at_task_reponse_begin == 0 &&
+ (strncmp(buf + offset - rsp_prefix_len, rsp_prefix,
+ rsp_prefix_len) == 0)) {
+ at_task_reponse_begin = 1;
+ }
+
+ if (at_task_reponse_begin == 1) {
+ if (tsk->rsp_offset < tsk->rsp_len) {
+ tsk->rsp[tsk->rsp_offset] = c;
+ tsk->rsp_offset++;
+
+ if ((tsk->rsp_offset >= rsp_success_postfix_len &&
+ strncmp(
+ tsk->rsp + tsk->rsp_offset - rsp_success_postfix_len,
+ rsp_success_postfix, rsp_success_postfix_len) == 0) ||
+ (tsk->rsp_offset >= rsp_fail_postfix_len &&
+ strncmp(tsk->rsp + tsk->rsp_offset - rsp_fail_postfix_len,
+ rsp_fail_postfix, rsp_fail_postfix_len) == 0)) {
+ HAL_SemaphorePost(tsk->smpr);
+ at_task_reponse_begin = 0;
+ memset(buf, 0, offset);
+ offset = 0;
+ }
+ } else {
+ memset(tsk->rsp, 0, tsk->rsp_len);
+ strcpy(tsk->rsp, rsp_fail_postfix);
+ HAL_SemaphorePost(tsk->smpr);
+ at_task_reponse_begin = 0;
+ memset(buf, 0, offset);
+ offset = 0;
+ }
+ }
+ check_buffer:
+ /* in case buffer is full */
+ if (offset > (RECV_BUFFER_SIZE - 2)) {
+ memcpy_size = rsp_prefix_len > rsp_success_postfix_len
+ ? rsp_prefix_len
+ : rsp_success_postfix_len;
+ memcpy_size = memcpy_size > rsp_fail_postfix_len
+ ? memcpy_size
+ : rsp_fail_postfix_len;
+ memcpy(buf, buf + offset - memcpy_size, memcpy_size);
+ memset(buf + memcpy_size, 0, offset - memcpy_size);
+ offset = memcpy_size;
+ }
+ }
+
+ return NULL;
+}
+#endif
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_parser.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_parser.h
new file mode 100644
index 00000000..1d2eb168
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_parser.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef _AT_PARSER_H_
+#define _AT_PARSER_H_
+
+#include "infra_config.h"
+
+/* uart config */
+#define AT_UART_PORT 1
+#define AT_UART_LINUX_DEV "/dev/ttyUSB0"
+#define AT_UART_BAUDRATE 115200
+#define AT_UART_DATA_WIDTH DATA_WIDTH_8BIT
+#define AT_UART_PARITY NO_PARITY
+#define AT_UART_STOP_BITS STOP_BITS_1
+#define AT_UART_FLOW_CONTROL FLOW_CONTROL_DISABLED
+#define AT_UART_MODE MODE_TX_RX
+#define AT_UART_TIMEOUT_MS 1000
+
+/* Delimiter */
+#define AT_RECV_PREFIX "\r\n"
+#define AT_RECV_SUCCESS_POSTFIX "OK\r\n"
+#define AT_RECV_FAIL_POSTFIX "ERROR\r\n"
+#define AT_SEND_DELIMITER "\r"
+
+#if defined(AT_TCP_HAL_SIM800)
+#define AT_CMD_DATA_INTERVAL_MS 50
+#endif
+
+#ifdef PLATFORM_HAS_OS
+#define AT_SINGLE_TASK 0
+#else
+#define AT_SINGLE_TASK 1
+#endif
+
+#ifndef bool
+#define bool unsigned char
+#endif
+
+#ifndef true
+#define true 1
+#endif
+#ifndef false
+#define false 0
+#endif
+
+typedef struct {
+ char *reply_prefix;
+ char *reply_success_postfix;
+ char *reply_fail_postfix;
+} atcmd_config_t;
+
+typedef void (*at_recv_cb)(void *arg, char *buf, int buflen);
+
+/**
+ * initialization
+ * Configuration (e.g. AT_UART_PORT, UART_BAUDRATE) can be found
+ * in above macro
+ */
+int at_parser_init(void);
+
+/**
+ * at send (format: command + delimiter + data) and wait reply
+ *
+ * @param cmd at command sending buf. MUST not be NULL.
+ * @param cmdlen at command length.
+ * @param delimiter whether sending delimiter, usually value is true
+ * @param data data sending buf. NULL if no data.
+ * @param datalen data length. Zero if no data.
+ * @param replybuf reply buffer. MUST not be NULL.
+ * @param bufsize reply buffer size
+ * @param atcmdconfig AT cmd reply format config. Use default if NULL
+ */
+int at_send_wait_reply(const char *cmd, int cmdlen, bool delimiter,
+ const char *data, int datalen,
+ char *replybuf, int bufsize,
+ const atcmd_config_t *atcmdconfig);
+
+/**
+ * at send (format: data + delimiter) and does not wait reply
+ *
+ * @param data sending buffer.
+ * @param datalen sending length.
+ * @param delimiter whether sending delimiter, usually value is false
+ */
+int at_send_no_reply(const char *data, int datalen, bool delimiter);
+
+
+/**
+ * at read for certain bytes of data
+ *
+ * @param outbuf output buffer.
+ * @param readsize read size.
+ */
+int at_read(char *outbuf, int readsize);
+
+
+/**
+ * at register callback for recv
+ *
+ * @param prefix interested string. Must not be NULL.
+ * @param postfix intersted postfix. NULL if postfix not provided.
+ * @param recvbuf recv data buffer provided by caller, NULL if postfix not provided
+ * @param bufsize buffer size for recv data, zero if postfix not provided
+ * @param cb callback handle function. Must not be NULL.
+ * @param arg callback handle function args. NULL if not used.
+ */
+int at_register_callback(const char *prefix, const char *postfix, char *recvbuf,
+ int bufsize, at_recv_cb cb, void *arg);
+
+
+/**
+ * at yield receive function. Only used in single task scenario
+ *
+ * @param replybuf reply buffer.
+ * @param bufsize reply buffer size.
+ * @param atcmdconfig AT cmd reply format config. Use default if NULL
+ * @param timeout_ms receive timeout in millisecond
+ */
+int at_yield(char *replybuf, int bufsize, const atcmd_config_t *atcmdconfig,
+ int timeout_ms);
+#endif
+
+
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_tcp.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_tcp.c
new file mode 100644
index 00000000..fbece6e1
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_tcp.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include
+#include
+
+#include "infra_types.h"
+#include "infra_config.h"
+
+#include "at_conn_mgmt.h"
+
+#include "at_wrapper.h"
+
+#ifdef AT_PARSER_ENABLED
+#include "at_parser.h"
+#endif
+
+static uint64_t _get_time_ms(void)
+{
+ return HAL_UptimeMs();
+}
+
+static uint64_t _time_left(uint64_t t_end, uint64_t t_now)
+{
+ uint64_t t_left;
+
+ if (t_end > t_now) {
+ t_left = t_end - t_now;
+ } else {
+ t_left = 0;
+ }
+
+ return t_left;
+}
+
+uintptr_t AT_TCP_Establish(const char *host, uint16_t port)
+{
+ int fd = 0;
+ int rc = 0;
+ char resultip[16];
+
+ HAL_Printf("establish tcp connection with server(host='%s', port=[%u])\n", host, port);
+
+ if ((rc = at_conn_getaddrinfo(host, resultip)) != 0) {
+ HAL_Printf("getaddrinfo error(%d), host = '%s', port = [%d]\n", rc, host, port);
+ return (uintptr_t)(-1);
+ }
+
+ fd = at_conn_setup(NETCONN_TCP);
+ if (fd < 0) {
+ HAL_Printf("create at conn error\n");
+ return (uintptr_t)(-1);
+ }
+
+ if (at_conn_start(fd, resultip, port) == 0) {
+ rc = fd;
+ } else {
+ at_conn_close(fd);
+ HAL_Printf("connect error\n");
+ rc = -1;
+ }
+
+ if (-1 == rc) {
+ HAL_Printf("fail to establish tcp\n");
+ } else {
+ HAL_Printf("success to establish tcp, fd=%d\n", rc);
+ }
+
+ return (uintptr_t)rc;
+}
+
+int AT_TCP_Destroy(uintptr_t fd)
+{
+ int rc;
+
+ rc = at_conn_close((int) fd);
+ if (0 != rc) {
+ HAL_Printf("closesocket error\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int32_t AT_TCP_Write(uintptr_t fd, const char *buf, uint32_t len, uint32_t timeout_ms)
+{
+ int ret;
+ uint32_t len_sent;
+ uint64_t t_end;
+ int net_err = 0;
+
+ t_end = _get_time_ms() + timeout_ms;
+ len_sent = 0;
+ ret = 1; /* send one time if timeout_ms is value 0 */
+
+ do {
+ ret = at_conn_send(fd, buf + len_sent, len - len_sent);
+ if (ret > 0) {
+ len_sent += ret;
+ } else if (0 == ret) {
+ HAL_Printf("No data be sent\n");
+ } else {
+ HAL_Printf("send fail, ret = send() = %d\n", ret);
+ net_err = 1;
+ break;
+ }
+ } while (!net_err && (len_sent < len) && (_time_left(t_end, _get_time_ms()) > 0));
+
+ if (net_err) {
+ return -1;
+ } else {
+ return len_sent;
+ }
+}
+
+int32_t AT_TCP_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms)
+{
+ int ret, err_code;
+ uint32_t len_recv;
+ uint64_t t_end, t_left;
+ int empty;
+
+ t_end = _get_time_ms() + timeout_ms;
+ len_recv = 0;
+ err_code = 0;
+
+ do {
+ t_left = _time_left(t_end, _get_time_ms());
+ if (0 == t_left) {
+ break;
+ }
+
+ while(1) {
+#ifdef AT_PARSER_ENABLED
+#if AT_SINGLE_TASK
+ at_yield(NULL, 0, NULL, 100);
+#endif
+#endif
+ empty = at_conn_recvbufempty(fd);
+ if (0 == empty) {
+ ret = 1;
+ break;
+ } else if (empty < 0) {
+ ret = -1;
+ }
+
+ t_left = _time_left(t_end, _get_time_ms());
+ if (0 == t_left) {
+ ret = 0;
+ break;
+ }
+
+ HAL_SleepMs(10);
+ }
+
+ if (ret > 0) {
+ ret = at_conn_recv(fd, buf + len_recv, len - len_recv);
+ if (ret > 0) {
+ len_recv += ret;
+ } else if (0 == ret) {
+ HAL_Printf("connection is closed\n");
+ err_code = -1;
+ break;
+ } else {
+ HAL_Printf("recv fail\n");
+ err_code = -2;
+ break;
+ }
+ } else if (0 == ret) {
+ break;
+ } else {
+ HAL_Printf("select-recv fail\n");
+ err_code = -2;
+ break;
+ }
+ } while ((len_recv < len));
+
+ /* priority to return data bytes if any data be received from TCP connection. */
+ /* It will get error code on next calling */
+ return (0 != len_recv) ? len_recv : err_code;
+}
+
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_wrapper.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_wrapper.h
new file mode 100644
index 00000000..9a350294
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/at_wrapper.h
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2015-2017 Alibaba Group Holding Limited
+ */
+
+#ifndef _AT_WRAPPER_H_
+#define _AT_WRAPPER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "infra_config.h"
+#include "wrappers_defs.h"
+
+#ifndef NULL
+#define NULL (void *)0
+#endif
+
+void *HAL_Malloc(uint32_t size);
+void HAL_Free(void *ptr);
+void HAL_Printf(const char *fmt, ...);
+int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
+uint64_t HAL_UptimeMs(void);
+void *HAL_MutexCreate(void);
+void HAL_MutexDestroy(void *mutex);
+void HAL_MutexLock(void *mutex);
+void HAL_MutexUnlock(void *mutex);
+void HAL_SleepMs(uint32_t ms);
+
+#ifdef PLATFORM_HAS_OS
+void *HAL_SemaphoreCreate(void);
+void HAL_SemaphoreDestroy(void *sem);
+void HAL_SemaphorePost(void *sem);
+int HAL_SemaphoreWait(void *sem, uint32_t timeout_ms);
+
+int HAL_ThreadCreate(
+ void **thread_handle,
+ void *(*work_routine)(void *),
+ void *arg,
+ hal_os_thread_param_t *hal_os_thread_param,
+ int *stack_used);
+#endif
+
+#define HAL_WAIT_FOREVER 0xFFFFFFFFU
+
+
+#if defined(AT_PARSER_ENABLED)
+/*
+ * UART data width
+ */
+typedef enum {
+ DATA_WIDTH_5BIT,
+ DATA_WIDTH_6BIT,
+ DATA_WIDTH_7BIT,
+ DATA_WIDTH_8BIT,
+ DATA_WIDTH_9BIT
+} hal_uart_data_width_t;
+
+/*
+ * UART stop bits
+ */
+typedef enum {
+ STOP_BITS_1,
+ STOP_BITS_2
+} hal_uart_stop_bits_t;
+
+/*
+ * UART flow control
+ */
+typedef enum {
+ FLOW_CONTROL_DISABLED,
+ FLOW_CONTROL_CTS,
+ FLOW_CONTROL_RTS,
+ FLOW_CONTROL_CTS_RTS
+} hal_uart_flow_control_t;
+
+/*
+ * UART parity
+ */
+typedef enum {
+ NO_PARITY,
+ ODD_PARITY,
+ EVEN_PARITY
+} hal_uart_parity_t;
+
+/*
+ * UART mode
+ */
+typedef enum {
+ MODE_TX,
+ MODE_RX,
+ MODE_TX_RX
+} hal_uart_mode_t;
+
+/*
+ * UART configuration
+ */
+typedef struct {
+ uint32_t baud_rate;
+ hal_uart_data_width_t data_width;
+ hal_uart_parity_t parity;
+ hal_uart_stop_bits_t stop_bits;
+ hal_uart_flow_control_t flow_control;
+ hal_uart_mode_t mode;
+} uart_config_t;
+
+typedef struct {
+ uint8_t port; /* uart port */
+ uart_config_t config; /* uart config */
+ void *priv; /* priv data */
+} uart_dev_t;
+
+/**
+ * Initialises a UART interface
+ *
+ *
+ * @param[in] uart the interface which should be initialised
+ *
+ * @return 0 : on success, EIO : if an error occurred with any step
+ */
+int32_t HAL_AT_Uart_Init(uart_dev_t *uart);
+
+/**
+ * Deinitialises a UART interface
+ *
+ * @param[in] uart the interface which should be deinitialised
+ *
+ * @return 0 : on success, EIO : if an error occurred with any step
+ */
+int32_t HAL_AT_Uart_Deinit(uart_dev_t *uart);
+
+/**
+ * Transmit data on a UART interface
+ *
+ * @param[in] uart the UART interface
+ * @param[in] data pointer to the start of data
+ * @param[in] size number of bytes to transmit
+ * @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ * if you want to wait forever
+ *
+ * @return 0 : on success, EIO : if an error occurred with any step
+ */
+int32_t HAL_AT_Uart_Send(uart_dev_t *uart, const void *data, uint32_t size, uint32_t timeout);
+
+/**
+ * Receive data on a UART interface
+ *
+ * @param[in] uart the UART interface
+ * @param[out] data pointer to the buffer which will store incoming data
+ * @param[in] expect_size number of bytes to receive
+ * @param[out] recv_size number of bytes received
+ * @param[in] timeout timeout in milisecond, set this value to HAL_WAIT_FOREVER
+ * if you want to wait forever
+ *
+ * @return 0 : on success, EIO : if an error occurred with any step
+ */
+int32_t HAL_AT_Uart_Recv(uart_dev_t *uart, void *data, uint32_t expect_size,
+ uint32_t *recv_size, uint32_t timeout);
+#endif
+
+#if defined(AT_TCP_ENABLED)
+typedef enum {
+ /* WiFi */
+ TCP_SERVER,
+ TCP_CLIENT,
+ SSL_CLIENT,
+ UDP_BROADCAST,
+ UDP_UNICAST,
+ /*WiFi end */
+ /* Add others hereafter */
+} CONN_TYPE;
+
+/* Fill necessary fileds according to the socket type. */
+typedef struct {
+ int fd; /* fd that are used in socket level */
+ CONN_TYPE type;
+ char *addr; /* remote ip or domain */
+ int32_t r_port; /* remote port (set to -1 if not used) */
+ int32_t l_port; /* local port (set to -1 if not used) */
+ uint32_t tcp_keep_alive; /* tcp keep alive value (set to 0 if not used) */
+} at_conn_t;
+
+struct at_conn_input {
+ int fd;
+ void *data;
+ uint32_t datalen;
+ char *remote_ip;
+ uint16_t remote_port;
+};
+
+/**
+ * Module low level init so that it's ready to setup socket connection.
+ *
+ * @return 0 - success, -1 - failure
+ */
+int HAL_AT_CONN_Init(void);
+
+
+/**
+ * Start a socket connection via module.
+ *
+ * @param[in] conn - connect parameters which are used to setup
+ * the socket connection.
+ *
+ * @return 0 - success, -1 - failure
+ */
+int HAL_AT_CONN_Start(at_conn_t *conn);
+
+
+/**
+ * Send data via module.
+ * This function does not return until all data sent.
+ *
+ * @param[in] fd - the file descripter to operate on.
+ * @param[in] data - pointer to data to send.
+ * @param[in] len - length of the data.
+ * @param[in] remote_ip - remote port number (optional).
+ * @param[in] remote_port - remote port number (optional).
+ *
+ * @return 0 - success, -1 - failure
+ */
+int HAL_AT_CONN_Send(int fd, uint8_t *data, uint32_t len, char remote_ip[16],
+ int32_t remote_port, int32_t timeout);
+
+
+/**
+ * Get IP information of the corresponding domain.
+ * Currently only one IP string is returned (even when the domain
+ * coresponses to mutliple IPs). Note: only IPv4 is supported.
+ *
+ * @param[in] domain - the domain string.
+ * @param[out] ip - the place to hold the dot-formatted ip string.
+ *
+ * @return 0 - success, -1 - failure
+ */
+int HAL_AT_CONN_DomainToIp(char *domain, char ip[16]);
+
+
+/**
+ * Close the socket connection.
+ *
+ * @param[in] fd - the file descripter to operate on.
+ * @param[in] remote_port - remote port number (optional).
+ *
+ * @return 0 - success, -1 - failure
+ */
+int HAL_AT_CONN_Close(int fd, int32_t remote_port);
+
+
+/**
+ * Destroy SAL or exit low level state if necessary.
+ *
+ * @return 0 - success, -1 - failure
+ */
+int HAL_AT_CONN_Deinit(void);
+
+#elif defined(AT_MQTT_ENABLED)
+#include "mqtt_api.h"
+
+struct at_mqtt_input {
+ char *topic;
+ uint32_t topic_len;
+ char *message;
+ uint32_t msg_len;
+};
+
+int HAL_AT_MQTT_Init(iotx_mqtt_param_t *pInitParams);
+int HAL_AT_MQTT_Deinit(void);
+int HAL_AT_MQTT_Connect(char *proKey, char *devName, char *devSecret);
+int HAL_AT_MQTT_Disconnect(void);
+int HAL_AT_MQTT_Subscribe(const char *topic, int qos, unsigned int *mqtt_packet_id, int *mqtt_status, int timeout_ms);
+int HAL_AT_MQTT_Unsubscribe(const char *topic, unsigned int *mqtt_packet_id, int *mqtt_status);
+int HAL_AT_MQTT_Publish(const char *topic, int qos, const char *message, unsigned int msg_len);
+int HAL_AT_MQTT_State(void);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/iot.mk b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/iot.mk
new file mode 100644
index 00000000..0e3647ec
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/atm/iot.mk
@@ -0,0 +1,19 @@
+LIBA_TARGET := libiot_at.a
+
+HDR_REFS := src/infra
+
+ifneq (,$(filter -DATM_ENABLED, $(CFLAGS)))
+LIB_SRCS_PATTERN += at_api.c
+
+ifneq (,$(filter -DAT_TCP_ENABLED, $(CFLAGS)))
+LIB_SRCS_PATTERN += at_conn_mbox.c at_conn_mgmt.c at_tcp.c
+endif
+
+ifneq (,$(filter -DAT_MQTT_ENABLED, $(CFLAGS)))
+LIB_SRCS_PATTERN += at_mqtt.c
+endif
+
+ifneq (,$(filter -DAT_PARSER_ENABLED, $(CFLAGS)))
+LIB_SRCS_PATTERN += at_parser.c
+endif
+endif
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPDeserialize.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPDeserialize.h
new file mode 100644
index 00000000..8d0cef68
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPDeserialize.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef __COAP_DESERIALIZE_H__
+#define __COAP_DESERIALIZE_H__
+#include
+#include "iotx_coap_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+int CoAPDeserialize_Message(CoAPMessage *msg, unsigned char *buf, int buflen);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPDeserialize_common.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPDeserialize_common.c
new file mode 100644
index 00000000..c034a795
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPDeserialize_common.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#include
+#include
+#include "iotx_coap_internal.h"
+
+int CoAPDeserialize_Header(CoAPMessage *msg, unsigned char *buf)
+{
+ msg->header.version = ((buf[0] >> 6) & 0x03);
+ msg->header.type = ((buf[0] >> 4) & 0x03);
+ msg->header.tokenlen = (buf[0] & 0x0F);
+ msg->header.code = buf[1];
+ msg->header.msgid = buf[2] << 8;
+ msg->header.msgid += buf[3];
+
+ return 4;
+}
+
+int CoAPDeserialize_Token(CoAPMessage *msg, unsigned char *buf)
+{
+ memcpy(msg->token, buf, msg->header.tokenlen);
+ return msg->header.tokenlen;
+}
+
+static int CoAPDeserialize_Option(CoAPMsgOption *option, unsigned char *buf, unsigned short *predeltas)
+{
+ unsigned char *ptr = buf;
+ unsigned short optdelta = 0;
+ unsigned short optlen = 0;
+ unsigned short predelta = 0;
+
+ optdelta = (*ptr & 0xF0) >> 4;
+ optlen = (*ptr & 0x0F);
+ ptr++;
+
+ predelta = *predeltas;
+ if (13 == optdelta) {
+ predelta += 13 + *ptr;
+ ptr ++;
+
+ } else if (14 == optdelta) {
+ predelta += 269;
+ predelta += (*ptr << 8);
+ predelta += *(ptr + 1);
+ ptr += 2;
+ } else {
+ predelta += optdelta;
+ }
+ option->num = predelta;
+
+ if (13 == optlen) {
+ optlen = 13 + *ptr;
+ ptr ++;
+ } else if (14 == optlen) {
+ optlen = 269;
+ optlen += (*ptr << 8);
+ optlen += *(ptr + 1);
+ ptr += 2;
+ }
+ option->len = optlen;
+
+ option->val = ptr;
+ *predeltas = option->num;
+
+ return (ptr - buf + option->len);
+}
+
+int CoAPDeserialize_Options(CoAPMessage *msg, unsigned char *buf, int buflen)
+{
+ int index = 0;
+ int count = 0;
+ unsigned char *ptr = buf;
+ unsigned short len = 0;
+ unsigned short optdeltas = 0;
+
+ msg->optcount = 0;
+ while ((count < buflen) && (0xFF != *ptr)) {
+ len = CoAPDeserialize_Option(&msg->options[index], ptr, &optdeltas);
+ msg->optcount += 1;
+ ptr += len;
+ index ++;
+ count += len;
+ }
+
+ return (int)(ptr - buf);
+}
+
+int CoAPDeserialize_Payload(CoAPMessage *msg, unsigned char *buf, int buflen)
+{
+ unsigned char *ptr = buf;
+
+ if (0xFF == *ptr) {
+ ptr ++;
+ } else {
+ return 0;
+ }
+ msg->payloadlen = buflen - 1;
+ msg->payload = (unsigned char *)ptr;
+
+ return buflen;
+}
+
+int CoAPDeserialize_Message(CoAPMessage *msg, unsigned char *buf, int buflen)
+{
+ int count = 0;
+ int remlen = buflen;
+ unsigned char *ptr = buf;
+
+ if (NULL == buf || NULL == msg) {
+ return COAP_ERROR_INVALID_PARAM;
+ }
+
+ if (buflen < 4) {
+ return COAP_ERROR_INVALID_LENGTH;
+ }
+
+ /* Deserialize CoAP header. */
+ count = CoAPDeserialize_Header(msg, ptr);
+ ptr += count;
+ remlen -= count;
+
+ /* Deserialize the token, if any. */
+ count = CoAPDeserialize_Token(msg, ptr);
+ ptr += count;
+ remlen -= count;
+
+ count = CoAPDeserialize_Options(msg, ptr, remlen);
+ ptr += count;
+ remlen -= count;
+
+ CoAPDeserialize_Payload(msg, ptr, remlen);
+
+ return COAP_SUCCESS;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPMessage_common.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPMessage_common.c
new file mode 100644
index 00000000..47e6104f
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPMessage_common.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+
+#include
+#include "iotx_coap_internal.h"
+#include "CoAPSerialize.h"
+#include "CoAPDeserialize.h"
+#if 0
+#include "CoAPResource.h"
+#include "CoAPObserve.h"
+#include "CoAPInternal.h"
+#endif
+#include "CoAPPlatform.h"
+
+#define COAPAckMsg(header) \
+ ((header.code == COAP_MSG_CODE_EMPTY_MESSAGE) \
+ &&(header.type == COAP_MESSAGE_TYPE_ACK))
+
+#define CoAPRespMsg(header)\
+ ((header.code >= 0x40) && (header.code < 0xc0))
+
+#define CoAPPingMsg(header)\
+ ((header.code == COAP_MSG_CODE_EMPTY_MESSAGE)\
+ && (header.type == COAP_MESSAGE_TYPE_CON))
+
+#define CoAPResetMsg(header)\
+ (header.type == COAP_MESSAGE_TYPE_RST)
+
+#define CoAPCONRespMsg(header)\
+ ((header.code == COAP_MSG_CODE_205_CONTENT) \
+ && (header.type == COAP_MESSAGE_TYPE_CON))
+
+#define CoAPReqMsg(header)\
+ ((1 <= header.code) && (32 > header.code))
+
+
+#define COAP_CUR_VERSION 1
+#define COAP_WAIT_TIME_MS 2000
+#define COAP_MAX_MESSAGE_ID 65535
+#define COAP_MAX_RETRY_COUNT 4
+#define COAP_ACK_TIMEOUT 2
+#define COAP_ACK_RANDOM_FACTOR 1
+#define COAP_MAX_TRANSMISSION_SPAN 10
+
+int CoAPStrOption_add(CoAPMessage *message, unsigned short optnum, unsigned char *data, unsigned short datalen)
+{
+ unsigned char *ptr = NULL;
+ if (COAP_MSG_MAX_OPTION_NUM <= message->optcount) {
+ return COAP_ERROR_INVALID_PARAM;
+ }
+
+ message->options[message->optcount].num = optnum - message->optdelta;
+ message->options[message->optcount].len = datalen;
+ ptr = (unsigned char *)coap_malloc(datalen);
+ if (NULL == ptr) {
+ return COAP_ERROR_MALLOC;
+ }
+ memset(ptr, 0x00, datalen);
+ memcpy(ptr, data, datalen);
+ message->options[message->optcount].val = ptr;
+ message->optdelta = optnum;
+ message->optcount ++;
+
+ return COAP_SUCCESS;
+
+}
+
+int CoAPStrOption_get(CoAPMessage *message, unsigned short optnum, unsigned char *data, unsigned short *datalen)
+{
+ unsigned char index = 0;
+
+ for (index = 0; index < message->optcount; index++) {
+ if (message->options[index].num == optnum) {
+ if (*datalen >= message->options[index].len) {
+ memcpy(data, message->options[index].val, message->options[index].len);
+ *datalen = message->options[index].len;
+ return COAP_SUCCESS;
+ } else {
+ return COAP_ERROR_INVALID_LENGTH;
+ }
+ }
+ }
+
+ return COAP_ERROR_NOT_FOUND;
+
+}
+
+
+int CoAPUintOption_add(CoAPMessage *message, unsigned short optnum, unsigned int data)
+{
+ unsigned char *ptr = NULL;
+ if (COAP_MSG_MAX_OPTION_NUM <= message->optcount) {
+ return COAP_ERROR_INVALID_PARAM;
+ }
+ message->options[message->optcount].num = optnum - message->optdelta;
+
+ if (0 == data) {
+ message->options[message->optcount].len = 0;
+ } else if (255 >= data) {
+ message->options[message->optcount].len = 1;
+ ptr = (unsigned char *)coap_malloc(1);
+ if (NULL != ptr) {
+ *ptr = (unsigned char)data;
+ }
+ } else if (65535 >= data) {
+ message->options[message->optcount].len = 2;
+ ptr = (unsigned char *)coap_malloc(2);
+ if (NULL != ptr) {
+ *ptr = (unsigned char)((data & 0xFF00) >> 8);
+ *(ptr + 1) = (unsigned char)(data & 0x00FF);
+ }
+ } else {
+ message->options[message->optcount].len = 4;
+ ptr = (unsigned char *)coap_malloc(4);
+ if (NULL != ptr) {
+ *ptr = (unsigned char)((data & 0xFF000000) >> 24);
+ *(ptr + 1) = (unsigned char)((data & 0x00FF0000) >> 16);
+ *(ptr + 2) = (unsigned char)((data & 0x0000FF00) >> 8);
+ *(ptr + 3) = (unsigned char)(data & 0x000000FF);
+ }
+ }
+ message->options[message->optcount].val = ptr;
+ message->optdelta = optnum;
+ message->optcount += 1;
+
+ return COAP_SUCCESS;
+}
+
+int CoAPUintOption_get(CoAPMessage *message,
+ unsigned short optnum,
+ unsigned int *data)
+{
+
+ unsigned char index = 0;
+
+ for (index = 0; index < message->optcount; index++) {
+ if (message->options[index].num == optnum) {
+ int byte = 0;
+ switch (message->options[index].len) {
+ case 1:
+ *data |= message->options[index].val[byte++];
+ break;
+ case 2:
+ *data |= (message->options[index].val[byte++] << 8);
+ *data |= message->options[index].val[byte++];
+ break;
+ case 3:
+ *data |= (message->options[index].val[byte++] << 16);
+ *data |= (message->options[index].val[byte++] << 8);
+ *data |= message->options[index].val[byte++];
+ break;
+ case 4:
+ *data |= (message->options[index].val[byte++] << 24);
+ *data |= (message->options[index].val[byte++] << 16);
+ *data |= (message->options[index].val[byte++] << 8);
+ *data |= message->options[index].val[byte++];
+ break;
+ default:
+ *data = 0;
+ break;
+ }
+ return COAP_SUCCESS;
+ }
+ }
+
+ return COAP_ERROR_NOT_FOUND;
+}
+
+
+int CoAPOption_present(CoAPMessage *message, unsigned short option)
+{
+ unsigned char index = 0;
+
+
+ for (index = 0; index < message->optcount; index++) {
+ if (message->options[index].num == option) {
+ return COAP_SUCCESS;
+ }
+ }
+ return COAP_ERROR_NOT_FOUND;
+}
+
+int CoAPMessageId_set(CoAPMessage *message, unsigned short msgid)
+{
+ if (NULL == message) {
+ return COAP_ERROR_NULL;
+ }
+ message->header.msgid = msgid;
+ return COAP_SUCCESS;
+}
+
+int CoAPMessageType_set(CoAPMessage *message, unsigned char type)
+{
+ if (NULL == message) {
+ return COAP_ERROR_NULL;
+ }
+ if (COAP_MESSAGE_TYPE_CON != type && COAP_MESSAGE_TYPE_NON != type
+ && COAP_MESSAGE_TYPE_ACK != type && COAP_MESSAGE_TYPE_RST != type) {
+ return COAP_ERROR_INVALID_PARAM;
+ }
+
+ message->header.type = type;
+ return COAP_SUCCESS;
+}
+
+int CoAPMessageCode_set(CoAPMessage *message, CoAPMessageCode code)
+{
+ if (NULL == message) {
+ return COAP_ERROR_NULL;
+ }
+ message->header.code = code;
+ return COAP_SUCCESS;
+}
+
+int CoAPMessageCode_get(CoAPMessage *message, CoAPMessageCode *code)
+{
+ if (NULL == message || NULL == code) {
+ return COAP_ERROR_NULL;
+ }
+ *code = message->header.code;
+ return COAP_SUCCESS;
+}
+
+int CoAPMessageToken_set(CoAPMessage *message, unsigned char *token,
+ unsigned char tokenlen)
+{
+ if (NULL == message || NULL == token) {
+ return COAP_ERROR_NULL;
+ }
+ if (COAP_MSG_MAX_TOKEN_LEN < tokenlen) {
+ return COAP_ERROR_INVALID_LENGTH;
+ }
+ memcpy(message->token, token, tokenlen);
+ message->header.tokenlen = tokenlen;
+
+ return COAP_SUCCESS;
+}
+
+int CoAPMessageUserData_set(CoAPMessage *message, void *userdata)
+{
+ if (NULL == message || NULL == userdata) {
+ return COAP_ERROR_NULL;
+ }
+ message->user = userdata;
+ return COAP_SUCCESS;
+}
+
+int CoAPMessageKeep_Set(CoAPMessage *message, int keep)
+{
+ if (NULL == message || keep < 0) {
+ return COAP_ERROR_NULL;
+ }
+ message->keep = keep;
+ return COAP_SUCCESS;
+}
+
+int CoAPMessagePayload_set(CoAPMessage *message, unsigned char *payload,
+ unsigned short payloadlen)
+{
+ if (NULL == message || (0 < payloadlen && NULL == payload)) {
+ return COAP_ERROR_NULL;
+ }
+ message->payload = payload;
+ message->payloadlen = payloadlen;
+
+ return COAP_SUCCESS;
+}
+
+int CoAPMessage_init(CoAPMessage *message)
+{
+ int count = 0;
+
+ if (NULL == message) {
+ return COAP_ERROR_NULL;
+ }
+ memset(message, 0x00, sizeof(CoAPMessage));
+ message->header.version = COAP_CUR_VERSION;
+ message->header.type = COAP_MESSAGE_TYPE_ACK;
+ message->header.tokenlen = 0;
+ message->header.code = COAP_MSG_CODE_EMPTY_MESSAGE;
+ message->header.msgid = 0;
+ message->payload = NULL;
+ message->payloadlen = 0;
+ message->optcount = 0;
+ message->optdelta = 0;
+ message->handler = NULL;
+ message->keep = 0;
+ for (count = 0; count < COAP_MSG_MAX_OPTION_NUM; count++) {
+ message->options[count].len = 0;
+ message->options[count].num = 0;
+ message->options[count].val = NULL;
+ }
+
+ return COAP_SUCCESS;
+}
+
+int CoAPMessage_destory(CoAPMessage *message)
+{
+ int count = 0;
+ if (NULL == message) {
+ return COAP_ERROR_NULL;
+ }
+
+ for (count = 0; count < COAP_MSG_MAX_OPTION_NUM; count++) {
+ if (NULL != message->options[count].val) {
+ coap_free(message->options[count].val);
+ message->options[count].val = NULL;
+ }
+ }
+
+ return COAP_SUCCESS;
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPPlatform.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPPlatform.h
new file mode 100644
index 00000000..02f6eca0
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPPlatform.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __COAP_PLATFORM_OS_H__
+#define __COAP_PLATFORM_OS_H__
+
+#include
+#include "iotx_coap_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+ #define coap_malloc(size) LITE_malloc(size, MEM_MAGIC, "coap.local")
+ #define coap_free(ptr) LITE_free(ptr)
+#else
+ #define coap_malloc(size) HAL_Malloc(size)
+ #define coap_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+#ifdef INFRA_LOG
+ #include "infra_log.h"
+ #define COAP_ERR(...) log_err("coap_local", __VA_ARGS__)
+ #define COAP_WRN(...) log_warning("coap_local", __VA_ARGS__)
+ #define COAP_INFO(...) log_info("coap_local", __VA_ARGS__)
+ #define COAP_TRC(...) log_debug("coap_local", __VA_ARGS__)
+ #define COAP_DUMP(...) log_debug("coap_local", __VA_ARGS__)
+ #define COAP_DEBUG(...) log_debug("coap_local", __VA_ARGS__)
+ #define COAP_FLOW(...) log_flow("coap_local", __VA_ARGS__)
+#else
+ #define COAP_ERR(...)
+ #define COAP_WRN(...)
+ #define COAP_INFO(...)
+ #define COAP_TRC(...)
+ #define COAP_DUMP(...)
+ #define COAP_DEBUG(...)
+ #define COAP_FLOW(...)
+#endif
+
+int platform_is_multicast(const char *ip_str);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPSerialize.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPSerialize.h
new file mode 100644
index 00000000..4a8177d1
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPSerialize.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+#ifndef __COAP_SERIALIZE_H__
+#define __COAP_SERIALIZE_H__
+#include "iotx_coap_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+unsigned short CoAPSerialize_MessageLength(CoAPMessage *msg);
+
+int CoAPSerialize_Message(CoAPMessage *msg, unsigned char *buf, unsigned short buflen);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
+
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPSerialize_common.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPSerialize_common.c
new file mode 100644
index 00000000..ae2f0d89
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/CoAPPacket/CoAPSerialize_common.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#include
+#include
+#include "CoAPSerialize.h"
+#include "iotx_coap_internal.h"
+
+int CoAPSerialize_Header(CoAPMessage *msg, unsigned char *buf, unsigned short buflen)
+{
+ if(4 > buflen){
+ return 0;
+ }
+ buf[0] = (((msg->header.version & 0x3) << 6) | ((msg->header.type & 0x3) << 4))
+ | (msg->header.tokenlen & 0x0F);
+
+ buf[1] = msg->header.code;
+ buf[2] = (msg->header.msgid & 0xFF00) >> 8;
+ buf[3] = (msg->header.msgid & 0x00FF);
+
+ return 4;
+}
+
+int CoAPSerialize_Token(CoAPMessage *msg, unsigned char * buf, unsigned short buflen)
+{
+ int i = 0;
+
+ if(buflen < msg->header.tokenlen){
+ return 0;
+ }
+ for (i = 0; i < msg->header.tokenlen; i++){
+ buf[i] = msg->token[i];
+ }
+ return msg->header.tokenlen;
+}
+
+static unsigned short CoAPSerialize_Option(CoAPMsgOption *option, unsigned char *buf)
+{
+ unsigned char *ptr = buf;
+
+ if(269 <= option->num){
+ *ptr = ((14 & 0x0F) << 4);
+ }
+ else if(13 <= option->num){
+ *ptr = ((13 & 0x0F) << 4);
+ }
+ else{
+ *ptr = option->num << 4;
+ }
+
+ if (269 <= option->len){
+ *ptr |= (14 & 0x0F);
+ }
+ else if(13 <= option->len){
+ *ptr |= (13 & 0x0F);
+ }
+ else{
+ *ptr |= (option->len & 0x0F);
+ }
+ ptr ++;
+
+ if (269 <= option->num){
+ *ptr = (unsigned char)(((option->num - 269) & 0xFF00) >> 8);
+ *(ptr+1) = (unsigned char)(((option->num - 269) & 0x00FF));
+ ptr += 2;
+ }
+ else if(13 <= option->num){
+ *ptr = (unsigned char)(option->num - 13);
+ ptr ++;
+ }
+
+
+ if (269 <= option->len){
+ *ptr = (unsigned char)(((option->len - 269) & 0xFF00) >> 8);
+ *(ptr+1) = (unsigned char)(((option->len - 269) & 0x00FF));
+ ptr += 2;
+ }
+ else if(13 <= option->len){
+ *ptr = (unsigned char)(option->len - 13);
+ ptr ++;
+ }
+
+
+ memcpy(ptr, option->val, option->len);
+ ptr += option->len;
+
+ return (int)(ptr - buf);
+}
+
+unsigned short CoAPSerialize_Options(CoAPMessage *msg, unsigned char * buf, unsigned short buflen)
+{
+ int i = 0;
+ unsigned short count = 0;
+
+ for (i = 0; i < msg->optcount; i++)
+ {
+ unsigned short len = 0;
+ len = CoAPSerialize_Option(&msg->options[i], &buf[count]);
+ if (0 < len){
+ count += len;
+ }
+ else{
+ return 0;
+ }
+ }
+
+ return count;
+}
+
+static unsigned short CoAPSerialize_OptionLen(CoAPMsgOption *option)
+{
+ unsigned short len = 1;
+
+ if(269 <= option->num){
+ len += 2;
+ }
+ else if(13 <= option->num){
+ len += 1;
+ }
+ else{
+ }
+
+ if (269 <= option->len){
+ len += 2;
+ }
+ else if(13 <= option->len){
+ len += 1;
+ }
+ else{
+ }
+
+ len += option->len;
+ return len;
+}
+
+
+unsigned short CoAPSerialize_OptionsLen(CoAPMessage *msg)
+{
+ int i = 0;
+ unsigned short count = 0;
+
+ for (i = 0; i < msg->optcount; i++)
+ {
+ unsigned short len = 0;
+ len = CoAPSerialize_OptionLen(&msg->options[i]);
+ if (0 < len){
+ count += len;
+ }
+ else{
+ return 0;
+ }
+ }
+
+ return count;
+}
+
+
+int CoAPSerialize_Payload(CoAPMessage *msg, unsigned char *buf, int buflen)
+{
+ if(msg->payloadlen + 1 > buflen){
+ return 0;
+ }
+ if(msg->payloadlen > 0 && NULL != msg->payload)
+ {
+ *buf = 0xFF;
+ buf ++;
+ memcpy(buf, msg->payload, msg->payloadlen);
+ return msg->payloadlen + 1;
+ }
+ else{
+ return 0;
+ }
+}
+
+
+unsigned short CoAPSerialize_MessageLength(CoAPMessage *msg)
+{
+ unsigned short msglen = 4;
+
+ msglen += msg->header.tokenlen;
+ msglen += CoAPSerialize_OptionsLen(msg);
+
+ if(0 < msg->payloadlen){
+ msglen += msg->payloadlen;
+ msglen += 1; /*CoAP payload marker*/
+ }
+
+ return msglen;
+}
+
+int CoAPSerialize_Message(CoAPMessage *msg, unsigned char *buf, unsigned short buflen)
+{
+ unsigned char *ptr = buf;
+ unsigned short count = 0;
+ unsigned short remlen = buflen;
+
+ if(NULL == buf || NULL == msg){
+ return COAP_ERROR_INVALID_PARAM;
+ }
+
+ count = CoAPSerialize_Header(msg, ptr, remlen);
+ ptr += count;
+ remlen -= count;
+
+ count = CoAPSerialize_Token(msg, ptr, remlen);
+ ptr += count;
+ remlen -= count;
+
+ count = CoAPSerialize_Options(msg, ptr, remlen);
+ ptr += count;
+ remlen -= count;
+
+ count = CoAPSerialize_Payload(msg, ptr, remlen);
+ ptr += count;
+ remlen -= count;
+
+ return (buflen-remlen);
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPExport.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPExport.h
new file mode 100644
index 00000000..5e0016cd
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPExport.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "Cloud_CoAPNetwork.h"
+#include "iotx_coap_internal.h"
+
+#ifndef CLOUD__COAP_EXPORT_H__
+#define CLOUD__COAP_EXPORT_H__
+
+/* #define COAP_DTLS_SUPPORT */
+typedef CoAPMsgOption Cloud_CoAPMsgOption;
+typedef CoAPMessageCode Cloud_CoAPMessageCode;
+typedef CoAPMessage Cloud_CoAPMessage ;
+#define COAP_OPTION_SEQ 2089
+
+typedef void (*Cloud_CoAPRespMsgHandler)(void *data, void *message);
+
+typedef struct {
+ void *user;
+ unsigned short msgid;
+ char acked;
+ unsigned char tokenlen;
+ unsigned char token[8];
+ unsigned char retrans_count;
+ unsigned short timeout;
+ unsigned short timeout_val;
+ unsigned char *message;
+ unsigned int msglen;
+ Cloud_CoAPRespMsgHandler resp;
+ struct list_head sendlist;
+} Cloud_CoAPSendNode;
+
+
+typedef struct {
+ unsigned char count;
+ unsigned char maxcount;
+ struct list_head sendlist;
+} Cloud_CoAPSendList;
+
+
+typedef void (*Cloud_CoAPEventNotifier)(unsigned int event, void *p_message);
+typedef struct {
+ char *url;
+ unsigned char maxcount; /*list maximal count*/
+ unsigned int waittime;
+ Cloud_CoAPEventNotifier notifier;
+} Cloud_CoAPInitParam;
+
+typedef struct {
+ unsigned short message_id;
+ coap_network_t network;
+ Cloud_CoAPEventNotifier notifier;
+ unsigned char *sendbuf;
+ unsigned char *recvbuf;
+ Cloud_CoAPSendList list;
+ unsigned int waittime;
+} Cloud_CoAPContext;
+
+#define COAP_TRC(...) log_debug("coap_cloud", __VA_ARGS__)
+#define COAP_DUMP(...) log_debug("coap_cloud", __VA_ARGS__)
+#define COAP_DEBUG(...) log_debug("coap_cloud", __VA_ARGS__)
+#define COAP_INFO(...) log_info("coap_cloud", __VA_ARGS__)
+#define COAP_WRN(...) log_warning("coap_cloud", __VA_ARGS__)
+#define COAP_ERR(...) log_err("coap_cloud", __VA_ARGS__)
+
+Cloud_CoAPContext *Cloud_CoAPContext_create(Cloud_CoAPInitParam *param);
+void Cloud_CoAPContext_free(Cloud_CoAPContext *p_ctx);
+
+
+#endif
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPMessage.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPMessage.h
new file mode 100644
index 00000000..5899698b
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPMessage.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#include "Cloud_CoAPExport.h"
+
+#ifndef __COAP_HANDLE_MSG_H__
+#define __COAP_HANDLE_MSG_H__
+
+int Cloud_CoAPStrOption_add(Cloud_CoAPMessage *message, unsigned short optnum,
+ unsigned char *data, unsigned short datalen);
+
+
+int Cloud_CoAPUintOption_add(Cloud_CoAPMessage *message, unsigned short optnum,
+ unsigned int data);
+
+unsigned short Cloud_CoAPMessageId_gen(Cloud_CoAPContext *context);
+
+int Cloud_CoAPMessageId_set(Cloud_CoAPMessage *message, unsigned short msgid);
+
+int Cloud_CoAPMessageType_set(Cloud_CoAPMessage *message, unsigned char type);
+
+int Cloud_CoAPMessageCode_set(Cloud_CoAPMessage *message, Cloud_CoAPMessageCode code);
+
+int Cloud_CoAPMessageToken_set(Cloud_CoAPMessage *message, unsigned char *token,
+ unsigned char tokenlen);
+
+int Cloud_CoAPMessageUserData_set(Cloud_CoAPMessage *message, void *userdata);
+
+int Cloud_CoAPMessagePayload_set(Cloud_CoAPMessage *message, unsigned char *payload,
+ unsigned short payloadlen);
+
+int Cloud_CoAPMessageHandler_set(Cloud_CoAPMessage *message, Cloud_CoAPRespMsgHandler handler);
+
+int Cloud_CoAPMessage_init(Cloud_CoAPMessage *message);
+
+int Cloud_CoAPMessage_destory(Cloud_CoAPMessage *message);
+
+int Cloud_CoAPMessage_send(Cloud_CoAPContext *context, Cloud_CoAPMessage *message);
+
+int Cloud_CoAPMessage_recv(Cloud_CoAPContext *context, unsigned int timeout, int readcount);
+
+int Cloud_CoAPMessage_cycle(Cloud_CoAPContext *context);
+
+
+
+#endif
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPNetwork.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPNetwork.h
new file mode 100644
index 00000000..43ec5b1e
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPNetwork.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include
+
+#ifndef COAP_TRANSPORT_H__
+#define COAP_TRANSPORT_H__
+
+typedef enum {
+ COAP_ENDPOINT_NOSEC = 0,
+ COAP_ENDPOINT_DTLS,
+ COAP_ENDPOINT_PSK,
+} coap_endpoint_type;
+
+
+typedef struct {
+ DTLSContext *context;
+} coap_remote_session_t;
+
+
+typedef struct {
+ int socket_id;
+ coap_endpoint_type ep_type;
+ void *context;
+} coap_network_t;
+
+
+typedef struct {
+ coap_endpoint_type ep_type;
+ unsigned char *p_ca_cert_pem;
+ char *p_host;
+ unsigned short port;
+} coap_network_init_t;
+
+
+unsigned int Cloud_CoAPNetwork_init(const coap_network_init_t *p_param, coap_network_t *p_network);
+
+
+unsigned int Cloud_CoAPNetwork_write(coap_network_t *p_network,
+ const unsigned char *p_data,
+ unsigned int datalen);
+
+int Cloud_CoAPNetwork_read(coap_network_t *network, unsigned char *data,
+ unsigned int datalen, unsigned int timeout);
+
+unsigned int Cloud_CoAPNetwork_deinit(coap_network_t *p_network);
+
+
+#endif
+
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPPlatform.h b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPPlatform.h
new file mode 100644
index 00000000..8e8da178
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/Cloud_CoAPPlatform.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#ifndef __COAP_PLATFORM_OS_H__
+#define __COAP_PLATFORM_OS_H__
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifdef INFRA_MEM_STATS
+ #include "infra_mem_stats.h"
+ #define coap_malloc(size) LITE_malloc(size, MEM_MAGIC, "coap.cloud")
+ #define coap_free(ptr) LITE_free(ptr)
+#else
+ #define coap_malloc(size) HAL_Malloc(size)
+ #define coap_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/CoAPExport.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/CoAPExport.c
new file mode 100644
index 00000000..5c9a6dea
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/CoAPExport.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+#include
+#include
+#include
+#include "iotx_coap_internal.h"
+#include "ctype.h"
+#include "Cloud_CoAPPlatform.h"
+#include "Cloud_CoAPNetwork.h"
+#include "Cloud_CoAPExport.h"
+
+#define COAP_DEFAULT_PORT 5683 /* CoAP default UDP port */
+#define COAPS_DEFAULT_PORT 5684 /* CoAP default UDP port for secure transmission */
+
+#define COAP_DEFAULT_SCHEME "coap" /* the default scheme for CoAP URIs */
+#define COAP_DEFAULT_HOST_LEN 128
+#define COAP_DEFAULT_WAIT_TIME_MS 2000
+
+unsigned int Cloud_CoAPUri_parse(char *p_uri, coap_endpoint_type *p_endpoint_type,
+ char host[COAP_DEFAULT_HOST_LEN], unsigned short *port)
+{
+ int len = 0;
+ char *p = NULL, *q = NULL;
+ if (NULL == p_uri || NULL == p_endpoint_type) {
+ return COAP_ERROR_INVALID_PARAM;
+ }
+
+ COAP_DEBUG("The uri is %s", p_uri);
+ len = strlen(p_uri);
+ p = p_uri;
+ q = (char *)COAP_DEFAULT_SCHEME;
+ while (len && *q && tolower(*p) == *q) {
+ ++p;
+ ++q;
+ --len;
+ }
+
+ if (*q) {
+ return COAP_ERROR_INVALID_URI;
+ }
+ if (tolower(*p) == 's') {
+ ++p;
+ --len;
+ *p_endpoint_type = COAP_ENDPOINT_DTLS;
+ *port = COAPS_DEFAULT_PORT;
+ } else if (*p == '-') {
+ ++p;
+ --len;
+ q = (char *)"psk";
+ while (len && *q && tolower(*p) == *q) {
+ ++p;
+ ++q;
+ --len;
+ }
+ if (*q) {
+ return COAP_ERROR_INVALID_URI;
+ }
+ *p_endpoint_type = COAP_ENDPOINT_PSK;
+ *port = COAP_DEFAULT_PORT;
+ } else {
+ *p_endpoint_type = COAP_ENDPOINT_NOSEC;
+ *port = COAP_DEFAULT_PORT;
+ }
+ COAP_DEBUG("The endpoint type is: %d", *p_endpoint_type);
+
+ q = (char *)"://";
+ while (len && *q && tolower(*p) == *q) {
+ ++p;
+ ++q;
+ --len;
+ }
+
+ if (*q) {
+ return COAP_ERROR_INVALID_URI;
+ }
+
+ q = p;
+ while (len && *q != ':') {
+ ++q;
+ --len;
+ }
+ if (p == q) {
+ return COAP_ERROR_INVALID_URI;
+ }
+
+ if (COAP_DEFAULT_HOST_LEN - 1 < (q - p)) {
+ return COAP_ERROR_INVALID_URI;
+ } else {
+ memset(host, 0x00, COAP_DEFAULT_HOST_LEN);
+ strncpy(host, p, q - p);
+ }
+ COAP_DEBUG("The host name is: %s", host);
+ if (len && *q == ':') {
+ p = ++q;
+ --len;
+
+ while (len && isdigit(*q)) {
+ ++q;
+ --len;
+ }
+
+ if (p < q) {
+ int uri_port = 0;
+
+ while (p < q) {
+ uri_port = uri_port * 10 + (*p++ - '0');
+ }
+
+ if (uri_port > 65535) {
+ return COAP_ERROR_INVALID_URI;
+ }
+ *port = uri_port;
+ }
+ }
+ COAP_DEBUG("The port is: %d", *port);
+
+ return COAP_SUCCESS;
+}
+
+
+Cloud_CoAPContext *Cloud_CoAPContext_create(Cloud_CoAPInitParam *param)
+{
+ unsigned int ret = COAP_SUCCESS;
+ Cloud_CoAPContext *p_ctx = NULL;
+ coap_network_init_t network_param;
+ char host[COAP_DEFAULT_HOST_LEN] = {0};
+
+ memset(&network_param, 0x00, sizeof(coap_network_init_t));
+ p_ctx = coap_malloc(sizeof(Cloud_CoAPContext));
+ if (NULL == p_ctx) {
+ COAP_ERR("malloc for coap context failed");
+ goto err;
+ }
+
+ memset(p_ctx, 0, sizeof(Cloud_CoAPContext));
+ p_ctx->message_id = 1;
+ p_ctx->notifier = param->notifier;
+ p_ctx->sendbuf = coap_malloc(COAP_MSG_MAX_PDU_LEN);
+ if (NULL == p_ctx->sendbuf) {
+ COAP_ERR("not enough memory");
+ goto err;
+ }
+
+ p_ctx->recvbuf = coap_malloc(COAP_MSG_MAX_PDU_LEN);
+ if (NULL == p_ctx->recvbuf) {
+ COAP_ERR("not enough memory");
+ goto err;
+ }
+
+ if (0 == param->waittime) {
+ p_ctx->waittime = COAP_DEFAULT_WAIT_TIME_MS;
+ } else {
+ p_ctx->waittime = param->waittime;
+ }
+
+ /*CoAP message send list*/
+ INIT_LIST_HEAD(&p_ctx->list.sendlist);
+ p_ctx->list.count = 0;
+ p_ctx->list.maxcount = param->maxcount;
+
+ /*set the endpoint type by uri schema*/
+ if (NULL != param->url) {
+ ret = Cloud_CoAPUri_parse(param->url, &network_param.ep_type, host, &network_param.port);
+ }
+
+ if (COAP_SUCCESS != ret) {
+ goto err;
+ }
+
+#ifdef COAP_DTLS_SUPPORT
+ if (COAP_ENDPOINT_DTLS == network_param.ep_type) {
+ extern const char *iotx_ca_crt;
+ network_param.p_ca_cert_pem = (unsigned char *)iotx_ca_crt;
+ }
+#endif
+ if (COAP_ENDPOINT_NOSEC == network_param.ep_type
+ || COAP_ENDPOINT_PSK == network_param.ep_type) {
+ network_param.p_ca_cert_pem = NULL;
+ }
+ network_param.p_host = host;
+
+ /*CoAP network init*/
+ ret = Cloud_CoAPNetwork_init(&network_param, &p_ctx->network);
+
+ if (COAP_SUCCESS != ret) {
+ goto err;
+ }
+
+ return p_ctx;
+err:
+ if (NULL == p_ctx) {
+ return p_ctx;
+ }
+
+ if (NULL != p_ctx->recvbuf) {
+ coap_free(p_ctx->recvbuf);
+ p_ctx->recvbuf = NULL;
+ }
+
+ if (NULL != p_ctx->sendbuf) {
+ coap_free(p_ctx->sendbuf);
+ p_ctx->sendbuf = NULL;
+ }
+
+ coap_free(p_ctx);
+ p_ctx = NULL;
+
+ return p_ctx;
+}
+
+void Cloud_CoAPContext_free(Cloud_CoAPContext *p_ctx)
+{
+ Cloud_CoAPSendNode *cur, *next;
+
+ if (NULL == p_ctx) {
+ return;
+ }
+
+ Cloud_CoAPNetwork_deinit(&p_ctx->network);
+
+ list_for_each_entry_safe(cur, next, &p_ctx->list.sendlist, sendlist, Cloud_CoAPSendNode) {
+ if (NULL != cur) {
+ if (NULL != cur->message) {
+ coap_free(cur->message);
+ cur->message = NULL;
+ }
+ coap_free(cur);
+ cur = NULL;
+ }
+ }
+
+ if (NULL != p_ctx->recvbuf) {
+ coap_free(p_ctx->recvbuf);
+ p_ctx->recvbuf = NULL;
+ }
+
+ if (NULL != p_ctx->sendbuf) {
+ coap_free(p_ctx->sendbuf);
+ p_ctx->sendbuf = NULL;
+ }
+
+
+ if (NULL != p_ctx) {
+ coap_free(p_ctx);
+ p_ctx = NULL;
+ }
+}
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/CoAPMessage.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/CoAPMessage.c
new file mode 100644
index 00000000..4214d880
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/CoAPMessage.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+#include "iotx_coap_internal.h"
+#include "Cloud_CoAPExport.h"
+#include "CoAPSerialize.h"
+#include "CoAPDeserialize.h"
+#include "Cloud_CoAPPlatform.h"
+
+
+#define COAPAckMsg(header) \
+ ((header.code == COAP_MSG_CODE_EMPTY_MESSAGE) \
+ &&(header.type == COAP_MESSAGE_TYPE_ACK))
+
+#define Cloud_CoAPRespMsg(header)\
+ ((header.code >= 0x40) && (header.code < 0xc0))
+
+#define Cloud_CoAPPingMsg(header)\
+ ((header.code == COAP_MSG_CODE_EMPTY_MESSAGE)\
+ && (header.type == COAP_MESSAGE_TYPE_CON))
+
+#define Cloud_CoAPRstMsg(header)\
+ (header.type == COAP_MESSAGE_TYPE_RST)
+
+#define Cloud_CoAPCONRespMsg(header)\
+ ((header.code == COAP_MSG_CODE_205_CONTENT) \
+ && (header.type == COAP_MESSAGE_TYPE_CON))
+
+#define Cloud_CoAPReqMsg(header)\
+ ((1 <= header.code) && (32 > header.code))
+
+
+#define COAP_CUR_VERSION 1
+#define COAP_WAIT_TIME_MS 2000
+#define COAP_MAX_MESSAGE_ID 65535
+#define COAP_MAX_RETRY_COUNT 4
+#define COAP_ACK_TIMEOUT 2
+#define COAP_ACK_RANDOM_FACTOR 1
+#define COAP_MAX_TRANSMISSION_SPAN 10
+
+unsigned short Cloud_CoAPMessageId_gen(Cloud_CoAPContext *context)
+{
+ unsigned short msg_id = 0;
+ msg_id = ((COAP_MAX_MESSAGE_ID == context->message_id) ? 1 : context->message_id++);
+ return msg_id;
+}
+
+int Cloud_CoAPMessageHandler_set(Cloud_CoAPMessage *message, Cloud_CoAPRespMsgHandler resp)
+{
+ if (NULL == message) {
+ return COAP_ERROR_NULL;
+ }
+ message->resp = resp;
+ return COAP_SUCCESS;
+}
+
+static int Cloud_CoAPMessageList_add(Cloud_CoAPContext *context, Cloud_CoAPMessage *message, int len)
+{
+ Cloud_CoAPSendNode *node = NULL;
+ node = coap_malloc(sizeof(Cloud_CoAPSendNode));
+
+ if (NULL != node) {
+ node->acked = 0;
+ node->user = message->user;
+ node->msgid = message->header.msgid;
+ node->resp = message->resp;
+ node->msglen = len;
+ node->timeout_val = COAP_ACK_TIMEOUT * COAP_ACK_RANDOM_FACTOR;
+
+ if (COAP_MESSAGE_TYPE_CON == message->header.type) {
+ node->timeout = node->timeout_val;
+ node->retrans_count = 0;
+ } else {
+ node->timeout = COAP_MAX_TRANSMISSION_SPAN;
+ node->retrans_count = COAP_MAX_RETRY_COUNT;
+ }
+ node->tokenlen = message->header.tokenlen;
+ memcpy(node->token, message->token, message->header.tokenlen);
+ node->message = (unsigned char *)coap_malloc(len);
+ if (NULL != node->message) {
+ memcpy(node->message, context->sendbuf, len);
+ }
+
+ if (&context->list.count >= &context->list.maxcount) {
+ coap_free(node);
+ return -1;
+ } else {
+ list_add_tail(&node->sendlist, &context->list.sendlist);
+ context->list.count ++;
+ return 0;
+ }
+ } else {
+ return -1;
+ }
+}
+
+int Cloud_CoAPMessage_send(Cloud_CoAPContext *context, Cloud_CoAPMessage *message)
+{
+ unsigned int ret = COAP_SUCCESS;
+ unsigned short msglen = 0;
+
+ if (NULL == message || NULL == context) {
+ return (COAP_ERROR_INVALID_PARAM);
+ }
+
+ /* TODO: get the message length */
+ /* msglen = CoAPSerialize_MessageLength(message); */
+ msglen = CoAPSerialize_MessageLength(message);
+ if (COAP_MSG_MAX_PDU_LEN < msglen) {
+ COAP_INFO("The message length %d is too loog", msglen);
+ return COAP_ERROR_DATA_SIZE;
+ }
+
+ memset(context->sendbuf, 0x00, COAP_MSG_MAX_PDU_LEN);
+ msglen = CoAPSerialize_Message(message, context->sendbuf, COAP_MSG_MAX_PDU_LEN);
+ COAP_DEBUG("----The message length %d-----", msglen);
+
+
+ ret = Cloud_CoAPNetwork_write(&context->network, context->sendbuf, (unsigned int)msglen);
+ if (COAP_SUCCESS == ret) {
+ if (Cloud_CoAPReqMsg(message->header) || Cloud_CoAPCONRespMsg(message->header)) {
+ COAP_DEBUG("Add message id %d len %d to the list",
+ message->header.msgid, msglen);
+ Cloud_CoAPMessageList_add(context, message, msglen);
+ } else {
+ COAP_DEBUG("The message doesn't need to be retransmitted");
+ }
+ } else {
+ COAP_ERR("CoAP transport write failed, return %d", ret);
+ }
+
+ return ret;
+}
+
+
+static int Cloud_CoAPAckMessage_handle(Cloud_CoAPContext *context, Cloud_CoAPMessage *message)
+{
+ Cloud_CoAPSendNode *node = NULL;
+
+ list_for_each_entry(node, &context->list.sendlist, sendlist, Cloud_CoAPSendNode) {
+ if (node->msgid == message->header.msgid) {
+ node->acked = 1;
+ return COAP_SUCCESS;
+ }
+ }
+
+ return COAP_SUCCESS;
+}
+
+static int Cloud_CoAPAckMessage_send(Cloud_CoAPContext *context, unsigned short msgid)
+{
+ Cloud_CoAPMessage message;
+ CoAPMessage_init(&message);
+ CoAPMessageId_set(&message, msgid);
+ return Cloud_CoAPMessage_send(context, &message);
+}
+
+static int Cloud_CoAPRespMessage_handle(Cloud_CoAPContext *context, Cloud_CoAPMessage *message)
+{
+ Cloud_CoAPSendNode *node = NULL;
+
+ if (COAP_MESSAGE_TYPE_CON == message->header.type) {
+ Cloud_CoAPAckMessage_send(context, message->header.msgid);
+ }
+
+
+ list_for_each_entry(node, &context->list.sendlist, sendlist, Cloud_CoAPSendNode) {
+ if (0 != node->tokenlen && node->tokenlen == message->header.tokenlen
+ && 0 == memcmp(node->token, message->token, message->header.tokenlen)) {
+
+#ifdef INFRA_LOG_NETWORK_PAYLOAD
+ COAP_DEBUG("Find the node by token");
+ COAP_INFO("Downstream Payload:");
+ iotx_facility_json_print((const char *)message->payload, LOG_INFO_LEVEL, '<');
+#endif
+ message->user = node->user;
+ if (COAP_MSG_CODE_400_BAD_REQUEST <= message->header.code) {
+ /* TODO:i */
+ if (NULL != context->notifier) {
+ /* context->notifier(message->header.code, message); */
+ }
+ }
+
+ if (NULL != node->resp) {
+ node->resp(node->user, message);
+ }
+ COAP_DEBUG("Remove the message id %d from list", node->msgid);
+ list_del_init(&node->sendlist);
+ context->list.count--;
+ if (NULL != node->message) {
+ coap_free(node->message);
+ }
+ coap_free(node);
+ node = NULL;
+ return COAP_SUCCESS;
+ }
+ }
+ return COAP_ERROR_NOT_FOUND;
+}
+
+static void Cloud_CoAPMessage_handle(Cloud_CoAPContext *context,
+ unsigned char *buf,
+ unsigned short datalen)
+{
+ int ret = COAP_SUCCESS;
+ Cloud_CoAPMessage message;
+ unsigned char code, msgclass, detail;
+ memset(&message, 0x00, sizeof(Cloud_CoAPMessage));
+
+ ret = CoAPDeserialize_Message(&message, buf, datalen);
+ code = (unsigned char)message.header.code;
+ msgclass = code >> 5;
+ detail = code & 0x1F;
+
+ COAP_DEBUG("Version : %d", message.header.version);
+ COAP_DEBUG("Code : %d.%02d(0x%x)", msgclass, detail, code);
+ COAP_DEBUG("Type : 0x%x", message.header.type);
+ COAP_DEBUG("Msgid : %d", message.header.msgid);
+ COAP_DEBUG("Option : %d", message.optcount);
+ COAP_DEBUG("Payload Len : %d", message.payloadlen);
+
+ msgclass = msgclass;
+ detail = detail;
+
+ if (COAP_SUCCESS != ret) {
+ if (NULL != context->notifier) {
+ /* TODO: */
+ /* context->notifier(context, event); */
+ }
+ }
+
+ if (COAPAckMsg(message.header)) {
+ COAP_DEBUG("Receive CoAP ACK Message,ID %d", message.header.msgid);
+ Cloud_CoAPAckMessage_handle(context, &message);
+
+ } else if (Cloud_CoAPRespMsg(message.header)) {
+ COAP_DEBUG("Receive CoAP Response Message,ID %d", message.header.msgid);
+ Cloud_CoAPRespMessage_handle(context, &message);
+ }
+}
+
+int Cloud_CoAPMessage_recv(Cloud_CoAPContext *context, unsigned int timeout, int readcount)
+{
+ int len = 0;
+ int count = readcount;
+
+ while (1) {
+ len = Cloud_CoAPNetwork_read(&context->network, context->recvbuf,
+ COAP_MSG_MAX_PDU_LEN, timeout);
+ if (len > 0) {
+ if (0 == readcount) {
+ Cloud_CoAPMessage_handle(context, context->recvbuf, len);
+ } else {
+ count--;
+ Cloud_CoAPMessage_handle(context, context->recvbuf, len);
+ if (0 == count) {
+ return len;
+ }
+ }
+ } else {
+ return 0;
+ }
+ }
+}
+
+int Cloud_CoAPMessage_cycle(Cloud_CoAPContext *context)
+{
+ unsigned int ret = 0;
+ Cloud_CoAPSendNode *node = NULL, *next = NULL;
+ Cloud_CoAPMessage_recv(context, context->waittime, 0);
+
+ list_for_each_entry_safe(node, next, &context->list.sendlist, sendlist, Cloud_CoAPSendNode) {
+ if (NULL != node) {
+ if (node->timeout == 0) {
+ if (node->retrans_count < COAP_MAX_RETRY_COUNT && (0 == node->acked)) {
+ node->timeout = node->timeout_val * 2;
+ node->timeout_val = node->timeout;
+ node->retrans_count++;
+ COAP_DEBUG("Retansmit the message id %d len %d", node->msgid, node->msglen);
+ ret = Cloud_CoAPNetwork_write(&context->network, node->message, node->msglen);
+ if (ret != COAP_SUCCESS) {
+ if (NULL != context->notifier) {
+ /* TODO: */
+ /* context->notifier(context, event); */
+ }
+ }
+ }
+
+ if ((node->timeout > COAP_MAX_TRANSMISSION_SPAN) ||
+ (node->retrans_count >= COAP_MAX_RETRY_COUNT)) {
+ if (NULL != context->notifier) {
+ /* TODO: */
+ /* context->notifier(context, event); */
+ }
+
+ /*Remove the node from the list*/
+ list_del_init(&node->sendlist);
+ context->list.count--;
+ COAP_INFO("Retransmit timeout,remove the message id %d count %d",
+ node->msgid, context->list.count);
+ coap_free(node->message);
+ coap_free(node);
+ }
+ } else {
+ node->timeout--;
+ }
+ }
+ }
+ return COAP_SUCCESS;
+}
+
diff --git a/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/CoAPNetwork.c b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/CoAPNetwork.c
new file mode 100644
index 00000000..68847070
--- /dev/null
+++ b/components/connectivity/iotkit-embedded-3.0.1/3rdparty/src/coap/client/CoAPNetwork.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2015-2018 Alibaba Group Holding Limited
+ */
+
+
+
+
+#include
+#include
+#include
+#include